@zxyycom/vibe-check 0.0.2 → 0.0.3

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 (670) hide show
  1. package/README.md +36 -5
  2. package/dist/esm/check/check.mjs +4 -0
  3. package/dist/esm/check/check.mjs.map +1 -1
  4. package/dist/esm/check/flag-enablement.mjs +32 -0
  5. package/dist/esm/check/flag-enablement.mjs.map +1 -0
  6. package/dist/esm/check/handoff-provider-identity.mjs +18 -0
  7. package/dist/esm/check/handoff-provider-identity.mjs.map +1 -0
  8. package/dist/esm/check/inherited-collection.mjs +1 -1
  9. package/dist/esm/check/inherited-collection.mjs.map +1 -1
  10. package/dist/esm/check/project-changes.mjs +2 -0
  11. package/dist/esm/check/project-changes.mjs.map +1 -0
  12. package/dist/esm/check/project-context.mjs +2 -0
  13. package/dist/esm/check/project-context.mjs.map +1 -0
  14. package/dist/esm/check-settlement/facts.mjs.map +1 -1
  15. package/dist/esm/check-settlement/record-store.mjs +1 -1
  16. package/dist/esm/check-settlement/record-store.mjs.map +1 -1
  17. package/dist/esm/data-boundary/canonical-data.mjs +36 -7
  18. package/dist/esm/data-boundary/canonical-data.mjs.map +1 -1
  19. package/dist/esm/data-boundary/canonical-json.mjs.map +1 -1
  20. package/dist/esm/data-boundary/closed-values.mjs +28 -4
  21. package/dist/esm/data-boundary/closed-values.mjs.map +1 -1
  22. package/dist/esm/{package-checks/project-files → data-boundary}/config-glob.mjs +3 -3
  23. package/dist/esm/data-boundary/config-glob.mjs.map +1 -0
  24. package/dist/esm/data-boundary/project-path.mjs +19 -0
  25. package/dist/esm/data-boundary/project-path.mjs.map +1 -0
  26. package/dist/esm/index.mjs +12 -5
  27. package/dist/esm/index.mjs.map +1 -1
  28. package/dist/esm/machine-output/v4/atomic-publication.mjs +4 -1
  29. package/dist/esm/machine-output/v4/atomic-publication.mjs.map +1 -1
  30. package/dist/esm/package-checks/check-authoring.mjs +69 -0
  31. package/dist/esm/package-checks/check-authoring.mjs.map +1 -0
  32. package/dist/esm/package-checks/code-quality-findings/finding-waiver-authoring.mjs.map +1 -1
  33. package/dist/esm/package-checks/code-quality-findings/finding-waiver-evidence.mjs.map +1 -1
  34. package/dist/esm/package-checks/command-check/command-check.mjs +55 -0
  35. package/dist/esm/package-checks/command-check/command-check.mjs.map +1 -0
  36. package/dist/esm/package-checks/command-check/contract.mjs +2 -0
  37. package/dist/esm/package-checks/command-check/contract.mjs.map +1 -0
  38. package/dist/esm/package-checks/command-check/execution.mjs +134 -0
  39. package/dist/esm/package-checks/command-check/execution.mjs.map +1 -0
  40. package/dist/esm/package-checks/command-check/options.mjs +284 -0
  41. package/dist/esm/package-checks/command-check/options.mjs.map +1 -0
  42. package/dist/esm/package-checks/command-check/transcript.mjs +26 -0
  43. package/dist/esm/package-checks/command-check/transcript.mjs.map +1 -0
  44. package/dist/esm/package-checks/duplicate-detection/default-check.mjs +9 -11
  45. package/dist/esm/package-checks/duplicate-detection/default-check.mjs.map +1 -1
  46. package/dist/esm/package-checks/duplicate-detection/execution.mjs +2 -4
  47. package/dist/esm/package-checks/duplicate-detection/execution.mjs.map +1 -1
  48. package/dist/esm/package-checks/duplicate-detection/finding-messages.mjs +1 -1
  49. package/dist/esm/package-checks/duplicate-detection/finding-messages.mjs.map +1 -1
  50. package/dist/esm/package-checks/duplicate-detection/jscpd/availability.mjs +1 -1
  51. package/dist/esm/package-checks/duplicate-detection/jscpd/availability.mjs.map +1 -1
  52. package/dist/esm/package-checks/duplicate-detection/options.mjs.map +1 -1
  53. package/dist/esm/package-checks/duplicate-detection/records.mjs.map +1 -1
  54. package/dist/esm/package-checks/file-metrics/constructor.mjs +9 -11
  55. package/dist/esm/package-checks/file-metrics/constructor.mjs.map +1 -1
  56. package/dist/esm/package-checks/file-metrics/execution.mjs +2 -4
  57. package/dist/esm/package-checks/file-metrics/execution.mjs.map +1 -1
  58. package/dist/esm/package-checks/file-metrics/finding-messages.mjs +1 -1
  59. package/dist/esm/package-checks/file-metrics/finding-messages.mjs.map +1 -1
  60. package/dist/esm/package-checks/file-metrics/options.mjs.map +1 -1
  61. package/dist/esm/package-checks/file-metrics/records.mjs.map +1 -1
  62. package/dist/esm/package-checks/file-metrics/scc/availability.mjs +1 -1
  63. package/dist/esm/package-checks/file-metrics/scc/availability.mjs.map +1 -1
  64. package/dist/esm/package-checks/file-metrics/scc/batch-planner.mjs +38 -0
  65. package/dist/esm/package-checks/file-metrics/scc/batch-planner.mjs.map +1 -0
  66. package/dist/esm/package-checks/file-metrics/scc/logical-scan-resources.mjs +35 -0
  67. package/dist/esm/package-checks/file-metrics/scc/logical-scan-resources.mjs.map +1 -0
  68. package/dist/esm/package-checks/file-metrics/scc/scanner.mjs +102 -29
  69. package/dist/esm/package-checks/file-metrics/scc/scanner.mjs.map +1 -1
  70. package/dist/esm/package-checks/function-metrics/analysis.mjs +7 -2
  71. package/dist/esm/package-checks/function-metrics/analysis.mjs.map +1 -1
  72. package/dist/esm/package-checks/function-metrics/analyzer/analysis-model.mjs +1 -1
  73. package/dist/esm/package-checks/function-metrics/analyzer/analysis-model.mjs.map +1 -1
  74. package/dist/esm/package-checks/function-metrics/analyzer/extensions/lizardcomplextags.mjs +1 -3
  75. package/dist/esm/package-checks/function-metrics/analyzer/extensions/lizardcomplextags.mjs.map +1 -1
  76. package/dist/esm/package-checks/function-metrics/analyzer/extensions/protocol.mjs.map +1 -1
  77. package/dist/esm/package-checks/function-metrics/analyzer/pipeline.mjs +3 -2
  78. package/dist/esm/package-checks/function-metrics/analyzer/pipeline.mjs.map +1 -1
  79. package/dist/esm/package-checks/function-metrics/analyzer/readers/erlang.mjs +6 -6
  80. package/dist/esm/package-checks/function-metrics/analyzer/readers/erlang.mjs.map +1 -1
  81. package/dist/esm/package-checks/function-metrics/analyzer/readers/fortran.mjs +1 -1
  82. package/dist/esm/package-checks/function-metrics/analyzer/readers/fortran.mjs.map +1 -1
  83. package/dist/esm/package-checks/function-metrics/analyzer/readers/objc.mjs +9 -3
  84. package/dist/esm/package-checks/function-metrics/analyzer/readers/objc.mjs.map +1 -1
  85. package/dist/esm/package-checks/function-metrics/analyzer/readers/php-states.mjs +12 -7
  86. package/dist/esm/package-checks/function-metrics/analyzer/readers/php-states.mjs.map +1 -1
  87. package/dist/esm/package-checks/function-metrics/analyzer/readers/plsql.mjs +6 -6
  88. package/dist/esm/package-checks/function-metrics/analyzer/readers/plsql.mjs.map +1 -1
  89. package/dist/esm/package-checks/function-metrics/analyzer/readers/python.mjs +5 -3
  90. package/dist/esm/package-checks/function-metrics/analyzer/readers/python.mjs.map +1 -1
  91. package/dist/esm/package-checks/function-metrics/analyzer/readers/r.mjs +2 -0
  92. package/dist/esm/package-checks/function-metrics/analyzer/readers/r.mjs.map +1 -1
  93. package/dist/esm/package-checks/function-metrics/analyzer/readers/ttcn.mjs +9 -3
  94. package/dist/esm/package-checks/function-metrics/analyzer/readers/ttcn.mjs.map +1 -1
  95. package/dist/esm/package-checks/function-metrics/analyzer/readers/typescript.mjs +9 -3
  96. package/dist/esm/package-checks/function-metrics/analyzer/readers/typescript.mjs.map +1 -1
  97. package/dist/esm/package-checks/function-metrics/analyzer/readers/zig.mjs +3 -1
  98. package/dist/esm/package-checks/function-metrics/analyzer/readers/zig.mjs.map +1 -1
  99. package/dist/esm/package-checks/function-metrics/analyzer/shared/code-reader.mjs +3 -1
  100. package/dist/esm/package-checks/function-metrics/analyzer/shared/code-reader.mjs.map +1 -1
  101. package/dist/esm/package-checks/function-metrics/analyzer/shared/js-style-regex.mjs +12 -5
  102. package/dist/esm/package-checks/function-metrics/analyzer/shared/js-style-regex.mjs.map +1 -1
  103. package/dist/esm/package-checks/function-metrics/analyzer-worker-port.mjs +20 -8
  104. package/dist/esm/package-checks/function-metrics/analyzer-worker-port.mjs.map +1 -1
  105. package/dist/esm/package-checks/function-metrics/constructor.mjs +9 -11
  106. package/dist/esm/package-checks/function-metrics/constructor.mjs.map +1 -1
  107. package/dist/esm/package-checks/function-metrics/execution.mjs +2 -4
  108. package/dist/esm/package-checks/function-metrics/execution.mjs.map +1 -1
  109. package/dist/esm/package-checks/function-metrics/finding-messages.mjs +1 -1
  110. package/dist/esm/package-checks/function-metrics/finding-messages.mjs.map +1 -1
  111. package/dist/esm/package-checks/function-metrics/measurement.mjs +3 -1
  112. package/dist/esm/package-checks/function-metrics/measurement.mjs.map +1 -1
  113. package/dist/esm/package-checks/function-metrics/options.mjs.map +1 -1
  114. package/dist/esm/package-checks/function-metrics/records.mjs.map +1 -1
  115. package/dist/esm/package-checks/host-environment/git.mjs +11 -0
  116. package/dist/esm/package-checks/host-environment/git.mjs.map +1 -1
  117. package/dist/esm/package-checks/host-environment/path.mjs +1 -17
  118. package/dist/esm/package-checks/host-environment/path.mjs.map +1 -1
  119. package/dist/esm/package-checks/host-environment/process/contract.mjs.map +1 -1
  120. package/dist/esm/package-checks/host-environment/process/result.mjs +43 -17
  121. package/dist/esm/package-checks/host-environment/process/result.mjs.map +1 -1
  122. package/dist/esm/package-checks/host-environment/process/runner.mjs +7 -5
  123. package/dist/esm/package-checks/host-environment/process/runner.mjs.map +1 -1
  124. package/dist/esm/package-checks/json-schema-validation/default-check.mjs +9 -11
  125. package/dist/esm/package-checks/json-schema-validation/default-check.mjs.map +1 -1
  126. package/dist/esm/package-checks/json-schema-validation/options.mjs.map +1 -1
  127. package/dist/esm/package-checks/json-schema-validation/reference-resolver.mjs +6 -2
  128. package/dist/esm/package-checks/json-schema-validation/reference-resolver.mjs.map +1 -1
  129. package/dist/esm/package-checks/json-schema-validation/schema-policy.mjs +11 -3
  130. package/dist/esm/package-checks/json-schema-validation/schema-policy.mjs.map +1 -1
  131. package/dist/esm/package-checks/json-validation/default-check.mjs +9 -11
  132. package/dist/esm/package-checks/json-validation/default-check.mjs.map +1 -1
  133. package/dist/esm/package-checks/json-validation/options.mjs.map +1 -1
  134. package/dist/esm/package-checks/local-cache-options.mjs +28 -0
  135. package/dist/esm/package-checks/local-cache-options.mjs.map +1 -0
  136. package/dist/esm/package-checks/maintenance-reminders/maintenance-reminders.mjs +37 -45
  137. package/dist/esm/package-checks/maintenance-reminders/maintenance-reminders.mjs.map +1 -1
  138. package/dist/esm/package-checks/maintenance-reminders/maintenance-support.mjs +3 -1
  139. package/dist/esm/package-checks/maintenance-reminders/maintenance-support.mjs.map +1 -1
  140. package/dist/esm/package-checks/markdown-link-validation/default-check.mjs +19 -33
  141. package/dist/esm/package-checks/markdown-link-validation/default-check.mjs.map +1 -1
  142. package/dist/esm/package-checks/markdown-link-validation/execution.mjs +1 -1
  143. package/dist/esm/package-checks/markdown-link-validation/execution.mjs.map +1 -1
  144. package/dist/esm/package-checks/markdown-link-validation/finding-messages.mjs +1 -1
  145. package/dist/esm/package-checks/markdown-link-validation/finding-messages.mjs.map +1 -1
  146. package/dist/esm/package-checks/markdown-link-validation/markdown-parser.mjs +1 -3
  147. package/dist/esm/package-checks/markdown-link-validation/markdown-parser.mjs.map +1 -1
  148. package/dist/esm/package-checks/markdown-link-validation/options-resolution.mjs +3 -18
  149. package/dist/esm/package-checks/markdown-link-validation/options-resolution.mjs.map +1 -1
  150. package/dist/esm/package-checks/markdown-link-validation/options-validation.mjs +2 -14
  151. package/dist/esm/package-checks/markdown-link-validation/options-validation.mjs.map +1 -1
  152. package/dist/esm/package-checks/markdown-link-validation/options.mjs.map +1 -1
  153. package/dist/esm/package-checks/markdown-link-validation/parse-facts-cache-payload.mjs +4 -5
  154. package/dist/esm/package-checks/markdown-link-validation/parse-facts-cache-payload.mjs.map +1 -1
  155. package/dist/esm/package-checks/markdown-lint/adapter.mjs +125 -0
  156. package/dist/esm/package-checks/markdown-lint/adapter.mjs.map +1 -0
  157. package/dist/esm/package-checks/markdown-lint/default-check.mjs +37 -0
  158. package/dist/esm/package-checks/markdown-lint/default-check.mjs.map +1 -0
  159. package/dist/esm/package-checks/markdown-lint/execution.mjs +202 -0
  160. package/dist/esm/package-checks/markdown-lint/execution.mjs.map +1 -0
  161. package/dist/esm/package-checks/markdown-lint/final-data.mjs +16 -0
  162. package/dist/esm/package-checks/markdown-lint/final-data.mjs.map +1 -0
  163. package/dist/esm/package-checks/markdown-lint/finding-messages.mjs +72 -0
  164. package/dist/esm/package-checks/markdown-lint/finding-messages.mjs.map +1 -0
  165. package/dist/esm/package-checks/markdown-lint/finding-waiver-identity.mjs +41 -0
  166. package/dist/esm/package-checks/markdown-lint/finding-waiver-identity.mjs.map +1 -0
  167. package/dist/esm/package-checks/markdown-lint/findings-cache.mjs +110 -0
  168. package/dist/esm/package-checks/markdown-lint/findings-cache.mjs.map +1 -0
  169. package/dist/esm/package-checks/markdown-lint/options-resolution.mjs +74 -0
  170. package/dist/esm/package-checks/markdown-lint/options-resolution.mjs.map +1 -0
  171. package/dist/esm/package-checks/markdown-lint/options-validation.mjs +41 -0
  172. package/dist/esm/package-checks/markdown-lint/options-validation.mjs.map +1 -0
  173. package/dist/esm/package-checks/markdown-lint/options.mjs +13 -0
  174. package/dist/esm/package-checks/markdown-lint/options.mjs.map +1 -0
  175. package/dist/esm/package-checks/markdown-lint/records.mjs +65 -0
  176. package/dist/esm/package-checks/markdown-lint/records.mjs.map +1 -0
  177. package/dist/esm/package-checks/markdown-lint/unavailable-reasons.mjs +14 -0
  178. package/dist/esm/package-checks/markdown-lint/unavailable-reasons.mjs.map +1 -0
  179. package/dist/esm/package-checks/project-files/collection.mjs +23 -19
  180. package/dist/esm/package-checks/project-files/collection.mjs.map +1 -1
  181. package/dist/esm/package-checks/project-files/configuration.mjs +1 -1
  182. package/dist/esm/package-checks/project-files/configuration.mjs.map +1 -1
  183. package/dist/esm/package-checks/project-files/gitlink-revision.mjs +2 -5
  184. package/dist/esm/package-checks/project-files/gitlink-revision.mjs.map +1 -1
  185. package/dist/esm/package-checks/project-files/gitlink-worktree.mjs +22 -6
  186. package/dist/esm/package-checks/project-files/gitlink-worktree.mjs.map +1 -1
  187. package/dist/esm/package-checks/project-files/public-collection.mjs +1 -1
  188. package/dist/esm/package-checks/project-files/public-collection.mjs.map +1 -1
  189. package/dist/esm/package-checks/project-files/revision-paths.mjs +3 -3
  190. package/dist/esm/package-checks/project-files/revision-paths.mjs.map +1 -1
  191. package/dist/esm/package-checks/project-files/revision-worktree-files.mjs +11 -15
  192. package/dist/esm/package-checks/project-files/revision-worktree-files.mjs.map +1 -1
  193. package/dist/esm/package-checks/secret-detection/default-check.mjs +9 -11
  194. package/dist/esm/package-checks/secret-detection/default-check.mjs.map +1 -1
  195. package/dist/esm/package-checks/secret-detection/execution.mjs +2 -2
  196. package/dist/esm/package-checks/secret-detection/execution.mjs.map +1 -1
  197. package/dist/esm/package-checks/secret-detection/input-preparation.mjs +46 -7
  198. package/dist/esm/package-checks/secret-detection/input-preparation.mjs.map +1 -1
  199. package/dist/esm/package-checks/secret-detection/options.mjs.map +1 -1
  200. package/dist/esm/package-checks/secret-detection/records.mjs.map +1 -1
  201. package/dist/esm/package-checks/secret-detection/secretlint/adapter.mjs +3 -4
  202. package/dist/esm/package-checks/secret-detection/secretlint/adapter.mjs.map +1 -1
  203. package/dist/esm/package-tools/admission-policy/define-admission-policy.mjs +10 -0
  204. package/dist/esm/package-tools/admission-policy/define-admission-policy.mjs.map +1 -0
  205. package/dist/esm/{cache → package-tools/cache}/cache-json-by-key.mjs +13 -14
  206. package/dist/esm/package-tools/cache/cache-json-by-key.mjs.map +1 -0
  207. package/dist/esm/package-tools/finding-presentation/finding-presentation.mjs.map +1 -0
  208. package/dist/esm/{finding-waivers → package-tools/finding-waivers}/reconciliation.mjs +14 -5
  209. package/dist/esm/package-tools/finding-waivers/reconciliation.mjs.map +1 -0
  210. package/dist/esm/package-tools/learned-critical-path/critical-path-ranking.mjs.map +1 -0
  211. package/dist/esm/package-tools/learned-critical-path/duration-model/bounded-history.mjs.map +1 -0
  212. package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/duration-model/prediction.mjs +2 -2
  213. package/dist/esm/package-tools/learned-critical-path/duration-model/prediction.mjs.map +1 -0
  214. package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/duration-model/preparation.mjs +4 -2
  215. package/dist/esm/package-tools/learned-critical-path/duration-model/preparation.mjs.map +1 -0
  216. package/dist/esm/package-tools/learned-critical-path/duration-model/recording.mjs.map +1 -0
  217. package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/duration-model/storage.mjs +8 -8
  218. package/dist/esm/package-tools/learned-critical-path/duration-model/storage.mjs.map +1 -0
  219. package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/selection-layers.mjs +1 -2
  220. package/dist/esm/package-tools/learned-critical-path/selection-layers.mjs.map +1 -0
  221. package/dist/esm/package-tools/learned-critical-path/static-decision.mjs.map +1 -0
  222. package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/strategy.mjs +3 -3
  223. package/dist/esm/package-tools/learned-critical-path/strategy.mjs.map +1 -0
  224. package/dist/esm/project-definition/check-tree/authoring.mjs +8 -5
  225. package/dist/esm/project-definition/check-tree/authoring.mjs.map +1 -1
  226. package/dist/esm/project-definition/check-tree/check-fields-authoring.mjs +79 -66
  227. package/dist/esm/project-definition/check-tree/check-fields-authoring.mjs.map +1 -1
  228. package/dist/esm/project-definition/check-tree/flag-conditions.mjs +71 -0
  229. package/dist/esm/project-definition/check-tree/flag-conditions.mjs.map +1 -0
  230. package/dist/esm/project-definition/check-tree/materialization.mjs +13 -8
  231. package/dist/esm/project-definition/check-tree/materialization.mjs.map +1 -1
  232. package/dist/esm/project-definition/check-tree/resolution.mjs +7 -6
  233. package/dist/esm/project-definition/check-tree/resolution.mjs.map +1 -1
  234. package/dist/esm/project-definition/declarative-snapshot.mjs +2 -1
  235. package/dist/esm/project-definition/declarative-snapshot.mjs.map +1 -1
  236. package/dist/esm/project-definition/project-changes.mjs +70 -0
  237. package/dist/esm/project-definition/project-changes.mjs.map +1 -0
  238. package/dist/esm/project-definition/project-definition-validation.mjs +40 -8
  239. package/dist/esm/project-definition/project-definition-validation.mjs.map +1 -1
  240. package/dist/esm/project-definition/project-definition.mjs +22 -15
  241. package/dist/esm/project-definition/project-definition.mjs.map +1 -1
  242. package/dist/esm/project-definition/scheduler-policy.mjs.map +1 -1
  243. package/dist/esm/project-run/admission-strategy-provider/custom-strategy-preparation.mjs +9 -6
  244. package/dist/esm/project-run/admission-strategy-provider/custom-strategy-preparation.mjs.map +1 -1
  245. package/dist/esm/project-run/admission-strategy-provider/prepared-admission-strategy.mjs.map +1 -1
  246. package/dist/esm/project-run/aggregation.mjs +42 -59
  247. package/dist/esm/project-run/aggregation.mjs.map +1 -1
  248. package/dist/esm/project-run/changes/git.mjs +161 -0
  249. package/dist/esm/project-run/changes/git.mjs.map +1 -0
  250. package/dist/esm/project-run/check-execution/admitted-check-execution.mjs +41 -0
  251. package/dist/esm/project-run/check-execution/admitted-check-execution.mjs.map +1 -0
  252. package/dist/esm/project-run/check-execution/callback.mjs +3 -2
  253. package/dist/esm/project-run/check-execution/callback.mjs.map +1 -1
  254. package/dist/esm/project-run/check-execution/dependencies.mjs +80 -5
  255. package/dist/esm/project-run/check-execution/dependencies.mjs.map +1 -1
  256. package/dist/esm/project-run/check-execution/execution-finalization.mjs +5 -3
  257. package/dist/esm/project-run/check-execution/execution-finalization.mjs.map +1 -1
  258. package/dist/esm/project-run/check-execution/execution-settlement.mjs +37 -16
  259. package/dist/esm/project-run/check-execution/execution-settlement.mjs.map +1 -1
  260. package/dist/esm/project-run/check-execution/flag-controls.mjs +15 -7
  261. package/dist/esm/project-run/check-execution/flag-controls.mjs.map +1 -1
  262. package/dist/esm/project-run/check-execution/lifecycle.mjs.map +1 -1
  263. package/dist/esm/project-run/check-execution/{preflight-result.mjs → preparation-result.mjs} +24 -24
  264. package/dist/esm/project-run/check-execution/preparation-result.mjs.map +1 -0
  265. package/dist/esm/project-run/check-execution/{preflight.mjs → preparation.mjs} +52 -52
  266. package/dist/esm/project-run/check-execution/preparation.mjs.map +1 -0
  267. package/dist/esm/project-run/check-execution/ready-check-execution.mjs +71 -0
  268. package/dist/esm/project-run/check-execution/ready-check-execution.mjs.map +1 -0
  269. package/dist/esm/project-run/check-execution/resolved-checks.mjs +27 -164
  270. package/dist/esm/project-run/check-execution/resolved-checks.mjs.map +1 -1
  271. package/dist/esm/project-run/check-execution/scheduled-check-run.mjs +79 -0
  272. package/dist/esm/project-run/check-execution/scheduled-check-run.mjs.map +1 -0
  273. package/dist/esm/project-run/check-execution/terminal-result.mjs +70 -25
  274. package/dist/esm/project-run/check-execution/terminal-result.mjs.map +1 -1
  275. package/dist/esm/project-run/completion/completion.mjs +18 -1
  276. package/dist/esm/project-run/completion/completion.mjs.map +1 -1
  277. package/dist/esm/project-run/controls/contract.mjs.map +1 -1
  278. package/dist/esm/project-run/controls/validation.mjs +7 -54
  279. package/dist/esm/project-run/controls/validation.mjs.map +1 -1
  280. package/dist/esm/project-run/diagnostic-logging/diagnostic-detail-rendering.mjs +3 -3
  281. package/dist/esm/project-run/diagnostic-logging/diagnostic-detail-rendering.mjs.map +1 -1
  282. package/dist/esm/project-run/diagnostic-logging/observation-rendering.mjs +1 -1
  283. package/dist/esm/project-run/diagnostic-logging/observation-rendering.mjs.map +1 -1
  284. package/dist/esm/project-run/invocation/candidate.mjs +17 -13
  285. package/dist/esm/project-run/invocation/candidate.mjs.map +1 -1
  286. package/dist/esm/project-run/invocation/candidates.mjs +26 -0
  287. package/dist/esm/project-run/invocation/candidates.mjs.map +1 -0
  288. package/dist/esm/project-run/invocation/creation.mjs +7 -3
  289. package/dist/esm/project-run/invocation/creation.mjs.map +1 -1
  290. package/dist/esm/project-run/invocation/execution.mjs +98 -0
  291. package/dist/esm/project-run/invocation/execution.mjs.map +1 -0
  292. package/dist/esm/project-run/invocation/run.mjs +13 -112
  293. package/dist/esm/project-run/invocation/run.mjs.map +1 -1
  294. package/dist/esm/project-run/invocation/scheduler.mjs +13 -6
  295. package/dist/esm/project-run/invocation/scheduler.mjs.map +1 -1
  296. package/dist/esm/project-run/outputs/status.mjs +12 -12
  297. package/dist/esm/project-run/outputs/status.mjs.map +1 -1
  298. package/dist/esm/project-run/progress-rendering/presentation.mjs +31 -11
  299. package/dist/esm/project-run/progress-rendering/presentation.mjs.map +1 -1
  300. package/dist/esm/project-run/progress-rendering/renderer-formatting.mjs +11 -4
  301. package/dist/esm/project-run/progress-rendering/renderer-formatting.mjs.map +1 -1
  302. package/dist/esm/project-run/progress-rendering/renderer-lifecycle.mjs +20 -6
  303. package/dist/esm/project-run/progress-rendering/renderer-lifecycle.mjs.map +1 -1
  304. package/dist/esm/project-run/progress-rendering/renderer.mjs +6 -2
  305. package/dist/esm/project-run/progress-rendering/renderer.mjs.map +1 -1
  306. package/dist/esm/project-run/project-context.mjs +2 -1
  307. package/dist/esm/project-run/project-context.mjs.map +1 -1
  308. package/dist/esm/project-run/result.mjs +2 -2
  309. package/dist/esm/project-run/result.mjs.map +1 -1
  310. package/dist/esm/project-run/run.mjs.map +1 -1
  311. package/dist/esm/project-run/task-scheduler/admission-core/compiled-graph-lookup.mjs +45 -0
  312. package/dist/esm/project-run/task-scheduler/admission-core/compiled-graph-lookup.mjs.map +1 -0
  313. package/dist/esm/project-run/task-scheduler/admission-core/compiled-graph.mjs +9 -4
  314. package/dist/esm/project-run/task-scheduler/admission-core/compiled-graph.mjs.map +1 -1
  315. package/dist/esm/project-run/task-scheduler/admission-core/selection-query.mjs +3 -5
  316. package/dist/esm/project-run/task-scheduler/admission-core/selection-query.mjs.map +1 -1
  317. package/dist/esm/project-run/task-scheduler/admission-core/selection-seed.mjs +25 -8
  318. package/dist/esm/project-run/task-scheduler/admission-core/selection-seed.mjs.map +1 -1
  319. package/dist/esm/project-run/task-scheduler/admission-core/selection-transition.mjs +8 -8
  320. package/dist/esm/project-run/task-scheduler/admission-core/selection-transition.mjs.map +1 -1
  321. package/dist/esm/project-run/task-scheduler/execution-state.mjs.map +1 -1
  322. package/dist/esm/project-run/task-scheduler/measurement/diagnostics.mjs +8 -4
  323. package/dist/esm/project-run/task-scheduler/measurement/diagnostics.mjs.map +1 -1
  324. package/dist/esm/project-run/task-scheduler/measurement/timing.mjs +12 -6
  325. package/dist/esm/project-run/task-scheduler/measurement/timing.mjs.map +1 -1
  326. package/dist/esm/project-run/task-scheduler/scheduler-observation.mjs +3 -1
  327. package/dist/esm/project-run/task-scheduler/scheduler-observation.mjs.map +1 -1
  328. package/dist/esm/project-run/task-scheduler/scheduler-terminal-measurement.mjs +17 -17
  329. package/dist/esm/project-run/task-scheduler/scheduler-terminal-measurement.mjs.map +1 -1
  330. package/dist/esm/project-run/task-scheduler/scheduler.mjs +18 -6
  331. package/dist/esm/project-run/task-scheduler/scheduler.mjs.map +1 -1
  332. package/docs/api-mechanics.md +147 -28
  333. package/docs/changelog.md +145 -2
  334. package/docs/checks/duplicate-detection.md +22 -3
  335. package/docs/checks/file-metrics.md +25 -6
  336. package/docs/checks/function-metrics.md +21 -2
  337. package/docs/checks/json-schema-validation.md +25 -4
  338. package/docs/checks/json-validation.md +24 -5
  339. package/docs/checks/maintenance-reminders.md +30 -6
  340. package/docs/checks/markdown-link-validation.md +24 -4
  341. package/docs/checks/markdown-lint.md +167 -0
  342. package/docs/checks/secret-detection.md +31 -7
  343. package/docs/examples/artifacts/mixed-outcomes/definition.ts +10 -10
  344. package/docs/guides/building-project-gate.md +706 -0
  345. package/docs/guides/callbacks.md +81 -22
  346. package/docs/guides/check-dependencies.md +41 -10
  347. package/docs/guides/collecting-project-files.md +7 -7
  348. package/docs/guides/command-check.md +155 -0
  349. package/docs/guides/data-boundaries.md +140 -0
  350. package/docs/guides/extending-check-lifecycle.md +77 -25
  351. package/docs/guides/finding-waivers.md +43 -1
  352. package/docs/guides/learned-scheduling.md +1 -1
  353. package/docs/guides/run-outputs.md +35 -9
  354. package/docs/guides/scheduling.md +15 -15
  355. package/docs/output.md +6 -5
  356. package/package.json +2 -1
  357. package/src/check/check.ts +332 -92
  358. package/src/check/flag-enablement.ts +76 -0
  359. package/src/check/handoff-provider-identity.ts +34 -0
  360. package/src/check/inherited-collection.ts +1 -1
  361. package/src/check/project-changes.ts +14 -0
  362. package/src/check/project-context.ts +11 -0
  363. package/src/check-settlement/facts.ts +1 -1
  364. package/src/check-settlement/record-store.ts +1 -1
  365. package/src/data-boundary/canonical-data.ts +36 -9
  366. package/src/data-boundary/canonical-json.ts +18 -1
  367. package/src/data-boundary/closed-values.ts +26 -6
  368. package/src/data-boundary/config-glob.ts +17 -0
  369. package/src/data-boundary/project-path.ts +21 -0
  370. package/src/index.ts +72 -11
  371. package/src/machine-output/v4/atomic-publication.ts +3 -1
  372. package/src/package-checks/check-authoring.ts +136 -0
  373. package/src/package-checks/code-quality-findings/finding-waiver-authoring.ts +1 -1
  374. package/src/package-checks/code-quality-findings/finding-waiver-evidence.ts +1 -1
  375. package/src/package-checks/command-check/command-check.ts +152 -0
  376. package/src/package-checks/command-check/contract.ts +168 -0
  377. package/src/package-checks/command-check/execution.ts +211 -0
  378. package/src/package-checks/command-check/options.ts +331 -0
  379. package/src/package-checks/command-check/transcript.ts +35 -0
  380. package/src/package-checks/duplicate-detection/default-check.ts +37 -6
  381. package/src/package-checks/duplicate-detection/execution.ts +2 -4
  382. package/src/package-checks/duplicate-detection/finding-messages.ts +2 -2
  383. package/src/package-checks/duplicate-detection/jscpd/availability.ts +1 -1
  384. package/src/package-checks/duplicate-detection/options.ts +6 -3
  385. package/src/package-checks/duplicate-detection/records.ts +1 -1
  386. package/src/package-checks/file-metrics/constructor.ts +29 -6
  387. package/src/package-checks/file-metrics/execution.ts +2 -4
  388. package/src/package-checks/file-metrics/finding-messages.ts +1 -1
  389. package/src/package-checks/file-metrics/options.ts +6 -3
  390. package/src/package-checks/file-metrics/records.ts +1 -1
  391. package/src/package-checks/file-metrics/scc/availability.ts +1 -1
  392. package/src/package-checks/file-metrics/scc/batch-planner.ts +56 -0
  393. package/src/package-checks/file-metrics/scc/logical-scan-resources.ts +59 -0
  394. package/src/package-checks/file-metrics/scc/scanner.ts +134 -32
  395. package/src/package-checks/function-metrics/analysis.ts +7 -2
  396. package/src/package-checks/function-metrics/analyzer/analysis-model.ts +1 -1
  397. package/src/package-checks/function-metrics/analyzer/extension-output.ts +14 -6
  398. package/src/package-checks/function-metrics/analyzer/extensions/lizardcomplextags.ts +1 -3
  399. package/src/package-checks/function-metrics/analyzer/extensions/protocol.ts +3 -3
  400. package/src/package-checks/function-metrics/analyzer/pipeline.ts +4 -2
  401. package/src/package-checks/function-metrics/analyzer/readers/erlang.ts +6 -6
  402. package/src/package-checks/function-metrics/analyzer/readers/fortran.ts +1 -1
  403. package/src/package-checks/function-metrics/analyzer/readers/objc.ts +9 -3
  404. package/src/package-checks/function-metrics/analyzer/readers/php-states.ts +14 -7
  405. package/src/package-checks/function-metrics/analyzer/readers/plsql.ts +8 -4
  406. package/src/package-checks/function-metrics/analyzer/readers/python.ts +4 -3
  407. package/src/package-checks/function-metrics/analyzer/readers/r.ts +2 -1
  408. package/src/package-checks/function-metrics/analyzer/readers/ttcn.ts +9 -3
  409. package/src/package-checks/function-metrics/analyzer/readers/typescript.ts +9 -3
  410. package/src/package-checks/function-metrics/analyzer/readers/zig.ts +2 -1
  411. package/src/package-checks/function-metrics/analyzer/shared/code-reader.ts +3 -1
  412. package/src/package-checks/function-metrics/analyzer/shared/js-style-regex.ts +10 -5
  413. package/src/package-checks/function-metrics/analyzer-worker-port.ts +20 -6
  414. package/src/package-checks/function-metrics/constructor.ts +30 -7
  415. package/src/package-checks/function-metrics/execution.ts +2 -4
  416. package/src/package-checks/function-metrics/finding-messages.ts +2 -2
  417. package/src/package-checks/function-metrics/measurement.ts +3 -1
  418. package/src/package-checks/function-metrics/options.ts +6 -3
  419. package/src/package-checks/function-metrics/records.ts +1 -1
  420. package/src/package-checks/host-environment/git.ts +11 -0
  421. package/src/package-checks/host-environment/path.ts +1 -20
  422. package/src/package-checks/host-environment/process/contract.ts +17 -9
  423. package/src/package-checks/host-environment/process/result.ts +48 -20
  424. package/src/package-checks/host-environment/process/runner.ts +8 -4
  425. package/src/package-checks/json-schema-validation/default-check.ts +38 -5
  426. package/src/package-checks/json-schema-validation/options.ts +4 -1
  427. package/src/package-checks/json-schema-validation/reference-resolver.ts +6 -2
  428. package/src/package-checks/json-schema-validation/schema-policy.ts +10 -5
  429. package/src/package-checks/json-validation/default-check.ts +27 -6
  430. package/src/package-checks/json-validation/options.ts +4 -1
  431. package/src/package-checks/local-cache-options.ts +40 -0
  432. package/src/package-checks/maintenance-reminders/maintenance-reminders.ts +89 -9
  433. package/src/package-checks/maintenance-reminders/maintenance-support.ts +3 -3
  434. package/src/package-checks/markdown-link-validation/default-check.ts +48 -5
  435. package/src/package-checks/markdown-link-validation/execution.ts +1 -1
  436. package/src/package-checks/markdown-link-validation/finding-messages.ts +1 -1
  437. package/src/package-checks/markdown-link-validation/markdown-parser.ts +1 -5
  438. package/src/package-checks/markdown-link-validation/options-resolution.ts +2 -19
  439. package/src/package-checks/markdown-link-validation/options-validation.ts +2 -17
  440. package/src/package-checks/markdown-link-validation/options.ts +6 -7
  441. package/src/package-checks/markdown-link-validation/parse-facts-cache-payload.ts +4 -5
  442. package/src/package-checks/markdown-lint/adapter.ts +167 -0
  443. package/src/package-checks/markdown-lint/default-check.ts +92 -0
  444. package/src/package-checks/markdown-lint/execution.ts +266 -0
  445. package/src/package-checks/markdown-lint/final-data.ts +33 -0
  446. package/src/package-checks/markdown-lint/finding-messages.ts +87 -0
  447. package/src/package-checks/markdown-lint/finding-waiver-identity.ts +54 -0
  448. package/src/package-checks/markdown-lint/findings-cache.ts +141 -0
  449. package/src/package-checks/markdown-lint/options-resolution.ts +102 -0
  450. package/src/package-checks/markdown-lint/options-validation.ts +50 -0
  451. package/src/package-checks/markdown-lint/options.ts +82 -0
  452. package/src/package-checks/markdown-lint/records.ts +132 -0
  453. package/src/package-checks/markdown-lint/unavailable-reasons.ts +33 -0
  454. package/src/package-checks/project-files/collection.ts +38 -22
  455. package/src/package-checks/project-files/config-glob.ts +1 -17
  456. package/src/package-checks/project-files/configuration.ts +1 -1
  457. package/src/package-checks/project-files/gitlink-revision.ts +4 -6
  458. package/src/package-checks/project-files/gitlink-worktree.ts +35 -7
  459. package/src/package-checks/project-files/public-collection.ts +1 -1
  460. package/src/package-checks/project-files/revision-paths.ts +3 -3
  461. package/src/package-checks/project-files/revision-worktree-files.ts +16 -16
  462. package/src/package-checks/secret-detection/default-check.ts +29 -6
  463. package/src/package-checks/secret-detection/execution.ts +2 -2
  464. package/src/package-checks/secret-detection/input-preparation.ts +64 -7
  465. package/src/package-checks/secret-detection/options.ts +5 -2
  466. package/src/package-checks/secret-detection/records.ts +1 -1
  467. package/src/package-checks/secret-detection/secretlint/adapter.ts +3 -4
  468. package/src/package-tools/admission-policy/define-admission-policy.ts +54 -0
  469. package/src/{cache → package-tools/cache}/cache-json-by-key.ts +13 -17
  470. package/src/{check → package-tools/finding-presentation}/finding-presentation.ts +3 -1
  471. package/src/{finding-waivers → package-tools/finding-waivers}/reconciliation.ts +16 -8
  472. package/src/{learned-critical-path → package-tools/learned-critical-path}/duration-model/prediction.ts +5 -2
  473. package/src/{learned-critical-path → package-tools/learned-critical-path}/duration-model/preparation.ts +5 -3
  474. package/src/{learned-critical-path → package-tools/learned-critical-path}/duration-model/recording.ts +5 -4
  475. package/src/{learned-critical-path → package-tools/learned-critical-path}/duration-model/storage.ts +9 -10
  476. package/src/{learned-critical-path → package-tools/learned-critical-path}/selection-layers.ts +2 -3
  477. package/src/{learned-critical-path → package-tools/learned-critical-path}/static-decision.ts +1 -1
  478. package/src/{learned-critical-path → package-tools/learned-critical-path}/strategy.ts +7 -4
  479. package/src/project-definition/check-tree/authoring.ts +15 -8
  480. package/src/project-definition/check-tree/check-fields-authoring.ts +106 -91
  481. package/src/project-definition/check-tree/flag-conditions.ts +99 -0
  482. package/src/project-definition/check-tree/materialization.ts +12 -8
  483. package/src/project-definition/check-tree/resolution.ts +13 -15
  484. package/src/project-definition/declarative-snapshot.ts +9 -2
  485. package/src/project-definition/project-changes.ts +112 -0
  486. package/src/project-definition/project-definition-validation.ts +58 -10
  487. package/src/project-definition/project-definition.ts +41 -68
  488. package/src/project-definition/scheduler-policy.ts +6 -3
  489. package/src/project-run/admission-strategy-provider/custom-strategy-preparation.ts +11 -8
  490. package/src/project-run/admission-strategy-provider/prepared-admission-strategy.ts +2 -2
  491. package/src/project-run/aggregation.ts +51 -74
  492. package/src/project-run/changes/git.ts +206 -0
  493. package/src/project-run/check-execution/admitted-check-execution.ts +62 -0
  494. package/src/project-run/check-execution/callback.ts +3 -2
  495. package/src/project-run/check-execution/dependencies.ts +120 -6
  496. package/src/project-run/check-execution/execution-finalization.ts +6 -4
  497. package/src/project-run/check-execution/execution-settlement.ts +88 -29
  498. package/src/project-run/check-execution/flag-controls.ts +22 -8
  499. package/src/project-run/check-execution/lifecycle.ts +14 -6
  500. package/src/project-run/check-execution/{preflight-result.ts → preparation-result.ts} +34 -32
  501. package/src/project-run/check-execution/{preflight.ts → preparation.ts} +92 -84
  502. package/src/project-run/check-execution/ready-check-execution.ts +97 -0
  503. package/src/project-run/check-execution/resolved-checks.ts +40 -219
  504. package/src/project-run/check-execution/scheduled-check-run.ts +119 -0
  505. package/src/project-run/check-execution/terminal-result.ts +108 -29
  506. package/src/project-run/completion/completion.ts +17 -3
  507. package/src/project-run/controls/contract.ts +6 -16
  508. package/src/project-run/controls/validation.ts +7 -60
  509. package/src/project-run/diagnostic-logging/diagnostic-detail-rendering.ts +1 -2
  510. package/src/project-run/diagnostic-logging/observation-rendering.ts +1 -1
  511. package/src/project-run/invocation/candidate.ts +28 -15
  512. package/src/project-run/invocation/candidates.ts +56 -0
  513. package/src/project-run/invocation/creation.ts +7 -3
  514. package/src/project-run/invocation/execution.ts +136 -0
  515. package/src/project-run/invocation/run.ts +15 -179
  516. package/src/project-run/invocation/scheduler.ts +13 -6
  517. package/src/project-run/outputs/status.ts +15 -15
  518. package/src/project-run/progress-rendering/presentation.ts +35 -13
  519. package/src/project-run/progress-rendering/renderer-formatting.ts +20 -7
  520. package/src/project-run/progress-rendering/renderer-lifecycle.ts +23 -6
  521. package/src/project-run/progress-rendering/renderer.ts +10 -4
  522. package/src/project-run/project-context.ts +8 -4
  523. package/src/project-run/result.ts +5 -5
  524. package/src/project-run/run.ts +1 -1
  525. package/src/project-run/task-scheduler/admission-core/compiled-graph-lookup.ts +71 -0
  526. package/src/project-run/task-scheduler/admission-core/compiled-graph.ts +9 -4
  527. package/src/project-run/task-scheduler/admission-core/selection-query.ts +6 -4
  528. package/src/project-run/task-scheduler/admission-core/selection-seed.ts +36 -6
  529. package/src/project-run/task-scheduler/admission-core/selection-transition.ts +17 -8
  530. package/src/project-run/task-scheduler/execution-state.ts +4 -4
  531. package/src/project-run/task-scheduler/measurement/diagnostics.ts +10 -4
  532. package/src/project-run/task-scheduler/measurement/timing.ts +13 -5
  533. package/src/project-run/task-scheduler/scheduler-observation.ts +3 -1
  534. package/src/project-run/task-scheduler/scheduler-terminal-measurement.ts +24 -22
  535. package/src/project-run/task-scheduler/scheduler.ts +23 -6
  536. package/types/check/check.d.ts +178 -67
  537. package/types/check/flag-enablement.d.ts +42 -0
  538. package/types/check/handoff-provider-identity.d.ts +12 -0
  539. package/types/check/project-changes.d.ts +13 -0
  540. package/types/check/project-context.d.ts +10 -0
  541. package/types/check-settlement/facts.d.ts +1 -1
  542. package/types/data-boundary/canonical-data.d.ts +28 -5
  543. package/types/data-boundary/canonical-json.d.ts +18 -1
  544. package/types/data-boundary/closed-values.d.ts +17 -1
  545. package/types/data-boundary/config-glob.d.ts +5 -0
  546. package/types/data-boundary/project-path.d.ts +4 -0
  547. package/types/index.d.ts +27 -11
  548. package/types/package-checks/check-authoring.d.ts +45 -0
  549. package/types/package-checks/code-quality-findings/finding-waiver-authoring.d.ts +1 -1
  550. package/types/package-checks/code-quality-findings/finding-waiver-evidence.d.ts +1 -1
  551. package/types/package-checks/command-check/command-check.d.ts +48 -0
  552. package/types/package-checks/command-check/contract.d.ts +108 -0
  553. package/types/package-checks/command-check/execution.d.ts +7 -0
  554. package/types/package-checks/command-check/options.d.ts +11 -0
  555. package/types/package-checks/command-check/transcript.d.ts +8 -0
  556. package/types/package-checks/duplicate-detection/default-check.d.ts +5 -2
  557. package/types/package-checks/duplicate-detection/finding-messages.d.ts +1 -1
  558. package/types/package-checks/duplicate-detection/options.d.ts +4 -3
  559. package/types/package-checks/duplicate-detection/records.d.ts +1 -1
  560. package/types/package-checks/file-metrics/constructor.d.ts +5 -2
  561. package/types/package-checks/file-metrics/options.d.ts +4 -3
  562. package/types/package-checks/file-metrics/records.d.ts +1 -1
  563. package/types/package-checks/file-metrics/scc/batch-planner.d.ts +18 -0
  564. package/types/package-checks/file-metrics/scc/logical-scan-resources.d.ts +14 -0
  565. package/types/package-checks/function-metrics/analyzer/extensions/protocol.d.ts +3 -3
  566. package/types/package-checks/function-metrics/constructor.d.ts +5 -2
  567. package/types/package-checks/function-metrics/finding-messages.d.ts +1 -1
  568. package/types/package-checks/function-metrics/options.d.ts +4 -3
  569. package/types/package-checks/function-metrics/records.d.ts +1 -1
  570. package/types/package-checks/host-environment/git.d.ts +2 -0
  571. package/types/package-checks/host-environment/path.d.ts +1 -3
  572. package/types/package-checks/host-environment/process/contract.d.ts +17 -9
  573. package/types/package-checks/json-schema-validation/default-check.d.ts +4 -1
  574. package/types/package-checks/json-schema-validation/options.d.ts +2 -1
  575. package/types/package-checks/json-validation/default-check.d.ts +4 -1
  576. package/types/package-checks/json-validation/options.d.ts +2 -1
  577. package/types/package-checks/local-cache-options.d.ts +9 -0
  578. package/types/package-checks/maintenance-reminders/maintenance-reminders.d.ts +11 -2
  579. package/types/package-checks/markdown-link-validation/default-check.d.ts +4 -1
  580. package/types/package-checks/markdown-link-validation/options.d.ts +4 -7
  581. package/types/package-checks/markdown-lint/adapter.d.ts +10 -0
  582. package/types/package-checks/markdown-lint/default-check.d.ts +37 -0
  583. package/types/package-checks/markdown-lint/execution.d.ts +24 -0
  584. package/types/package-checks/markdown-lint/final-data.d.ts +8 -0
  585. package/types/package-checks/markdown-lint/finding-messages.d.ts +6 -0
  586. package/types/package-checks/markdown-lint/finding-waiver-identity.d.ts +3 -0
  587. package/types/package-checks/markdown-lint/findings-cache.d.ts +17 -0
  588. package/types/package-checks/markdown-lint/options-resolution.d.ts +3 -0
  589. package/types/package-checks/markdown-lint/options-validation.d.ts +2 -0
  590. package/types/package-checks/markdown-lint/options.d.ts +65 -0
  591. package/types/package-checks/markdown-lint/records.d.ts +39 -0
  592. package/types/package-checks/markdown-lint/unavailable-reasons.d.ts +3 -0
  593. package/types/package-checks/secret-detection/default-check.d.ts +4 -1
  594. package/types/package-checks/secret-detection/options.d.ts +3 -2
  595. package/types/package-tools/admission-policy/define-admission-policy.d.ts +26 -0
  596. package/types/{check → package-tools/finding-presentation}/finding-presentation.d.ts +3 -1
  597. package/types/{finding-waivers → package-tools/finding-waivers}/reconciliation.d.ts +3 -3
  598. package/types/{learned-critical-path → package-tools/learned-critical-path}/duration-model/prediction.d.ts +2 -2
  599. package/types/{learned-critical-path → package-tools/learned-critical-path}/duration-model/preparation.d.ts +1 -1
  600. package/types/{learned-critical-path → package-tools/learned-critical-path}/duration-model/recording.d.ts +1 -1
  601. package/types/{learned-critical-path → package-tools/learned-critical-path}/selection-layers.d.ts +1 -1
  602. package/types/{learned-critical-path → package-tools/learned-critical-path}/static-decision.d.ts +1 -1
  603. package/types/{learned-critical-path → package-tools/learned-critical-path}/strategy.d.ts +1 -1
  604. package/types/project-definition/check-tree/authoring.d.ts +5 -3
  605. package/types/project-definition/check-tree/check-fields-authoring.d.ts +12 -7
  606. package/types/project-definition/check-tree/flag-conditions.d.ts +5 -0
  607. package/types/project-definition/check-tree/resolution.d.ts +6 -4
  608. package/types/project-definition/declarative-snapshot.d.ts +4 -1
  609. package/types/project-definition/project-changes.d.ts +30 -0
  610. package/types/project-definition/project-definition.d.ts +15 -30
  611. package/types/project-definition/scheduler-policy.d.ts +3 -3
  612. package/types/project-run/admission-strategy-provider/prepared-admission-strategy.d.ts +2 -2
  613. package/types/project-run/aggregation.d.ts +8 -6
  614. package/types/project-run/changes/git.d.ts +14 -0
  615. package/types/project-run/check-execution/admitted-check-execution.d.ts +18 -0
  616. package/types/project-run/check-execution/dependencies.d.ts +3 -0
  617. package/types/project-run/check-execution/execution-finalization.d.ts +1 -1
  618. package/types/project-run/check-execution/execution-settlement.d.ts +15 -7
  619. package/types/project-run/check-execution/flag-controls.d.ts +1 -1
  620. package/types/project-run/check-execution/lifecycle.d.ts +9 -5
  621. package/types/project-run/check-execution/{preflight-result.d.ts → preparation-result.d.ts} +3 -3
  622. package/types/project-run/check-execution/{preflight.d.ts → preparation.d.ts} +10 -9
  623. package/types/project-run/check-execution/ready-check-execution.d.ts +18 -0
  624. package/types/project-run/check-execution/resolved-checks.d.ts +12 -13
  625. package/types/project-run/check-execution/scheduled-check-run.d.ts +10 -0
  626. package/types/project-run/check-execution/terminal-result.d.ts +13 -1
  627. package/types/project-run/completion/completion.d.ts +3 -1
  628. package/types/project-run/controls/contract.d.ts +6 -16
  629. package/types/project-run/invocation/candidates.d.ts +8 -0
  630. package/types/project-run/invocation/execution.d.ts +5 -0
  631. package/types/project-run/invocation/run.d.ts +2 -2
  632. package/types/project-run/outputs/status.d.ts +4 -4
  633. package/types/project-run/progress-rendering/presentation.d.ts +4 -3
  634. package/types/project-run/progress-rendering/renderer-formatting.d.ts +5 -2
  635. package/types/project-run/progress-rendering/renderer-lifecycle.d.ts +2 -0
  636. package/types/project-run/progress-rendering/renderer.d.ts +4 -2
  637. package/types/project-run/project-context.d.ts +3 -3
  638. package/types/project-run/result.d.ts +3 -3
  639. package/types/project-run/run.d.ts +1 -1
  640. package/types/project-run/task-scheduler/admission-core/compiled-graph-lookup.d.ts +10 -0
  641. package/types/project-run/task-scheduler/execution-state.d.ts +4 -4
  642. package/types/project-run/task-scheduler/measurement/diagnostics.d.ts +2 -2
  643. package/types/project-run/task-scheduler/scheduler-terminal-measurement.d.ts +1 -1
  644. package/dist/esm/cache/cache-json-by-key.mjs.map +0 -1
  645. package/dist/esm/check/finding-presentation.mjs.map +0 -1
  646. package/dist/esm/finding-waivers/reconciliation.mjs.map +0 -1
  647. package/dist/esm/learned-critical-path/duration-model/bounded-history.mjs.map +0 -1
  648. package/dist/esm/learned-critical-path/duration-model/prediction.mjs.map +0 -1
  649. package/dist/esm/learned-critical-path/duration-model/preparation.mjs.map +0 -1
  650. package/dist/esm/learned-critical-path/duration-model/recording.mjs.map +0 -1
  651. package/dist/esm/learned-critical-path/duration-model/storage.mjs.map +0 -1
  652. package/dist/esm/learned-critical-path/selection-layers.mjs.map +0 -1
  653. package/dist/esm/learned-critical-path/static-decision.mjs.map +0 -1
  654. package/dist/esm/learned-critical-path/strategy.mjs.map +0 -1
  655. package/dist/esm/package-checks/project-files/config-glob.mjs.map +0 -1
  656. package/dist/esm/project-run/check-execution/preflight-result.mjs.map +0 -1
  657. package/dist/esm/project-run/check-execution/preflight.mjs.map +0 -1
  658. package/dist/esm/project-run/task-scheduler/critical-path-ranking.mjs.map +0 -1
  659. package/types/package-checks/project-files/config-glob.d.ts +0 -5
  660. /package/dist/esm/{check → package-tools/finding-presentation}/finding-presentation.mjs +0 -0
  661. /package/dist/esm/{project-run/task-scheduler → package-tools/learned-critical-path}/critical-path-ranking.mjs +0 -0
  662. /package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/duration-model/bounded-history.mjs +0 -0
  663. /package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/duration-model/recording.mjs +0 -0
  664. /package/dist/esm/{learned-critical-path → package-tools/learned-critical-path}/static-decision.mjs +0 -0
  665. /package/src/{project-run/task-scheduler → package-tools/learned-critical-path}/critical-path-ranking.ts +0 -0
  666. /package/src/{learned-critical-path → package-tools/learned-critical-path}/duration-model/bounded-history.ts +0 -0
  667. /package/types/{cache → package-tools/cache}/cache-json-by-key.d.ts +0 -0
  668. /package/types/{project-run/task-scheduler → package-tools/learned-critical-path}/critical-path-ranking.d.ts +0 -0
  669. /package/types/{learned-critical-path → package-tools/learned-critical-path}/duration-model/bounded-history.d.ts +0 -0
  670. /package/types/{learned-critical-path → package-tools/learned-critical-path}/duration-model/storage.d.ts +0 -0
@@ -1,8 +1,9 @@
1
1
  import type { ProjectOutputs } from "../../project-definition/project-definition.ts";
2
+ import type { CoreCheck } from "../../check-settlement/facts.ts";
2
3
  /**
3
4
  * `run(definition, controls?)` 的第二个参数,只指定这一次怎么运行。
4
5
  *
5
- * root、flags、signal、Check 产物与日志目标以及显式 aggregation 属于本次调用;`outputs` 只逐字段
6
+ * root、flags、signal、Check 产物与日志目标以及 aggregation 属于本次调用;`outputs` 只逐字段
6
7
  * 覆盖 Definition 的输出默认值,不修改原 Definition。Checks、Check options 与 scheduler 仍在
7
8
  * `defineConfig(...)` 中声明,不能从这里替换;这些 Controls 不进入 Definition fingerprint。
8
9
  */
@@ -13,7 +14,7 @@ export interface RunControls {
13
14
  readonly progressLogFile?: string;
14
15
  /** caller 选择的 Check-owned invocation artifact base;省略时不授予 artifact capability。 */
15
16
  readonly checkArtifactBaseDirectory?: string;
16
- /** 为本次 Run 选择并折叠 Check statuses;省略时结果的 `aggregate` 为 `null`。 */
17
+ /** 为本次 Run 解释有效 Check facts;省略时使用严格的 all-passed 默认折叠。 */
17
18
  readonly checkAggregation?: CheckAggregation;
18
19
  /** 仅为本次调用覆盖 Run-owned outputs。 */
19
20
  readonly outputs?: Partial<{
@@ -25,23 +26,12 @@ export interface RunControls {
25
26
  readonly flags?: readonly string[];
26
27
  /** 项目相对输入与 output target 的解析根;省略时使用调用进程的当前工作目录。 */
27
28
  readonly projectRoot?: string;
28
- /** 供 planning、preflight 与 execution 协作响应的 caller cancellation signal。 */
29
+ /** 供 planning、preparation 与 execution 协作响应的 caller cancellation signal。 */
29
30
  readonly signal?: AbortSignal;
30
31
  }
31
32
  /** Diagnostic 文件名选择;不改变目录、日志内容或 invocation identity。 */
32
33
  export type DiagnosticLogFileNaming = "unique" | "channel";
33
- /** 将选定 Check statuses 折叠为 invocation aggregate 的规则。 */
34
- export interface CheckAggregation {
35
- /** `all` 选择全部 Check,ID 数组选择明确集合,`effective` 复用本 invocation 的 flag-and-dependency selection。 */
36
- readonly checks: "all" | "effective" | readonly string[];
37
- /** `all` 要求所有纳入状态通过;`any` 只要求至少一个纳入状态通过。 */
38
- readonly mode: "all" | "any";
39
- /** 将 `unavailable` 原样传播、按失败纳入,或从 `all`/`any` 计算中排除。 */
40
- readonly unavailable: "propagate" | "fail" | "exclude";
41
- /** 将 `not-applicable` 从计算中排除,或按通过/失败纳入。 */
42
- readonly notApplicable: "exclude" | "pass" | "fail";
43
- /** 选择为空或所有状态都被排除时返回的明确 aggregate。 */
44
- readonly empty: "passed" | "failed" | "not-applicable";
45
- }
46
34
  /** `CheckAggregation` 计算出的 invocation 级结果。 */
47
35
  export type CheckAggregate = "passed" | "failed" | "not-applicable" | "unavailable";
36
+ /** 同步解释本次有效 Check facts 的 caller-local aggregation。 */
37
+ export type CheckAggregation = (checks: readonly CoreCheck[]) => CheckAggregate;
@@ -0,0 +1,8 @@
1
+ import { type NonConfigurationRunResult, type RunDiagnostic } from "../result.ts";
2
+ import type { Invocation } from "./run.ts";
3
+ /** Records a pre-execution cancellation as the Run-owned candidate result. */
4
+ export declare function cancelledBeforeExecution(invocation: Invocation, phase: "pre-work" | "planning"): NonConfigurationRunResult;
5
+ /** Constructs the planning failure candidate after the static graph has been rejected. */
6
+ export declare function planningResult(invocation: Invocation, code: Extract<RunDiagnostic["code"], "task-graph-invalid">): NonConfigurationRunResult;
7
+ /** Constructs a pre-settlement execution failure without revising existing output facts. */
8
+ export declare function executionResult(invocation: Invocation, code: Extract<RunDiagnostic["code"], "admission-strategy-preparation-failed" | "task-engine-failed">): NonConfigurationRunResult;
@@ -0,0 +1,5 @@
1
+ import type { CheckAggregation } from "../controls/contract.ts";
2
+ import { type NonConfigurationRunResult } from "../result.ts";
3
+ import type { Invocation } from "./run.ts";
4
+ /** Executes the post-validation invocation phases, from change preparation through Scheduler completion. */
5
+ export declare function executePlannedInvocation(invocation: Invocation, aggregation: CheckAggregation | undefined): Promise<NonConfigurationRunResult>;
@@ -1,12 +1,12 @@
1
1
  import { type DefinitionWarning, type NormalizedProjectDefinition, type ProjectDefinition, type ResolvedProjectOutputs } from "../../project-definition/project-definition.ts";
2
2
  import type { RunControls } from "../controls/contract.ts";
3
- import { type AdmissionStrategyProviderFactory } from "../admission-strategy-provider/provider.ts";
3
+ import type { AdmissionStrategyProviderFactory } from "../admission-strategy-provider/provider.ts";
4
4
  import { type CheckExecutionClock } from "../check-execution/resolved-checks.ts";
5
5
  import { type ProgressRefreshScheduler, type ProgressRendering, type ProgressWriterFactory } from "../progress-rendering/presentation.ts";
6
6
  import type { ResolvedInvocationPaths } from "./paths.ts";
7
+ import type { OutputStatuses } from "../outputs/status.ts";
7
8
  import { type RunResult } from "../result.ts";
8
9
  import { type DiagnosticLoggerFactory, type DiagnosticLoggingRouter } from "../diagnostic-logging/logger.ts";
9
- import type { OutputStatuses } from "../outputs/status.ts";
10
10
  export type Invocation = Readonly<{
11
11
  /** Product-private test seam; package `run` never accepts a provider factory. */
12
12
  readonly admissionStrategyProviderFactory: AdmissionStrategyProviderFactory | undefined;
@@ -29,14 +29,14 @@ export interface RunOutputStatuses {
29
29
  /** core 与 scheduler diagnostic channels 的 aggregate 状态。 */
30
30
  readonly diagnosticLogging: RunDiagnosticLoggingOutputStatus;
31
31
  /**
32
- * Definition generic Hooks 与 prepared custom strategy 的 optional `complete` 所形成的 terminal participant
32
+ * Definition generic effects 与 prepared custom strategy 的 optional `terminalEffect` 所形成的 terminal participant
33
33
  * 状态;它不能由 RunControls 注入或覆盖。
34
34
  */
35
- readonly measurementHooks: RunOutputStatus;
35
+ readonly terminalEffects: RunOutputStatus;
36
36
  }
37
37
  export interface OutputStatuses {
38
38
  /** Enables a runtime-only terminal participant after successful preparation. */
39
- readonly enableMeasurementHooks: () => void;
39
+ readonly enableTerminalEffects: () => void;
40
40
  /** A diagnostic channel failure is isolated but updates the aggregate diagnostic output. */
41
41
  readonly failedDiagnosticChannel: (channel: DiagnosticChannel) => void;
42
42
  readonly failed: (output: keyof RunOutputStatuses) => void;
@@ -44,5 +44,5 @@ export interface OutputStatuses {
44
44
  readonly succeeded: (output: keyof RunOutputStatuses) => void;
45
45
  readonly value: () => RunOutputStatuses;
46
46
  }
47
- export declare function createOutputStatuses(configuration: ProjectOutputs, diagnosticLoggingFiles: Readonly<Record<DiagnosticChannel, string | null>>, initialMeasurementHooksEnabled: boolean): OutputStatuses;
47
+ export declare function createOutputStatuses(configuration: ProjectOutputs, diagnosticLoggingFiles: Readonly<Record<DiagnosticChannel, string | null>>, initialTerminalEffectsEnabled: boolean): OutputStatuses;
48
48
  export declare function failedOutput(statuses: RunOutputStatuses): keyof RunOutputStatuses | undefined;
@@ -1,4 +1,4 @@
1
- import type { CheckExecutionLifecycle } from "../check-execution/lifecycle.ts";
1
+ import type { CheckExecutionLifecycle, InvocationLifecycle } from "../check-execution/lifecycle.ts";
2
2
  import { type ProgressClock, type ProgressOutcomeCounts, type ProgressWriter } from "./renderer.ts";
3
3
  import type { ResolvedProgressRenderingOutput } from "../../project-definition/project-definition.ts";
4
4
  import type { OutputStatuses } from "../outputs/status.ts";
@@ -6,8 +6,9 @@ export interface ProgressRendering {
6
6
  /** Closes only an already-created file tee; it never creates a writer after pre-work termination. */
7
7
  readonly close: () => void;
8
8
  readonly final: (input: ProgressFinalFeedback) => void;
9
- readonly lifecycle: CheckExecutionLifecycle;
10
- readonly prepared: (totalChecks: number) => void;
9
+ readonly checkLifecycle: CheckExecutionLifecycle;
10
+ readonly invocationLifecycle: InvocationLifecycle;
11
+ readonly prepared: (totalChecks: number, quietPassOmissionConfiguredCount: number) => void;
11
12
  }
12
13
  export interface ProgressFinalFeedback {
13
14
  readonly counts: ProgressOutcomeCounts;
@@ -3,7 +3,7 @@ import type { CoreRecord } from "../../check-settlement/facts.ts";
3
3
  import type { ResolvedProgressRenderingOutput } from "../../project-definition/project-definition.ts";
4
4
  import type { ProgressFeedback } from "./renderer.ts";
5
5
  export declare function formatRunningRow(input: Readonly<{
6
- readonly displayIndex: number;
6
+ readonly displayIndex: number | undefined;
7
7
  readonly displayName: string;
8
8
  readonly elapsedMs: number | null;
9
9
  readonly totalChecks: number;
@@ -16,7 +16,7 @@ export declare function isFlagConditionNotMatchedFeedback(feedback: Extract<Prog
16
16
  }>): boolean;
17
17
  export declare function formatFlagConditionNotMatchedBlock(displayNames: readonly [string, ...string[]]): string;
18
18
  export declare function formatSettledBlock(input: Readonly<{
19
- readonly completionOrdinal: number;
19
+ readonly completionOrdinal: number | undefined;
20
20
  readonly displayName: string;
21
21
  readonly durationMs: number | null;
22
22
  readonly messages: readonly CheckMessage[];
@@ -28,4 +28,7 @@ export declare function formatSettledBlock(input: Readonly<{
28
28
  }>): string;
29
29
  export declare function formatFinalSummary(input: Extract<ProgressFeedback, {
30
30
  readonly kind: "final";
31
+ }> & Readonly<{
32
+ readonly quietPassOmissionConfiguredCount: number;
33
+ readonly quietPassOmittedCount: number;
31
34
  }>): string;
@@ -7,6 +7,8 @@ export declare class ProgressRendererController implements ProgressRenderer {
7
7
  private readonly writer;
8
8
  private completedCount;
9
9
  private readonly flagConditionNotMatchedDisplayNames;
10
+ private quietPassOmissionConfiguredCount;
11
+ private quietPassOmittedCount;
10
12
  private preparedTotal;
11
13
  private renderedRunningRows;
12
14
  private readonly running;
@@ -1,4 +1,4 @@
1
- import type { CheckMessage, CheckOutcome, CheckVisibility } from "../../check/check.ts";
1
+ import type { CheckMessage, CheckOutcome } from "../../check/check.ts";
2
2
  import type { CoreRecord } from "../../check-settlement/facts.ts";
3
3
  import type { ResolvedProgressRenderingOutput } from "../../project-definition/project-definition.ts";
4
4
  export interface ProgressWriter {
@@ -10,6 +10,7 @@ export interface ProgressWriter {
10
10
  }
11
11
  export type ProgressFeedback = Readonly<{
12
12
  readonly kind: "prepared";
13
+ readonly quietPassOmissionConfiguredCount: number;
13
14
  readonly totalChecks: number;
14
15
  } | {
15
16
  readonly kind: "flag-control-completed";
@@ -17,13 +18,14 @@ export type ProgressFeedback = Readonly<{
17
18
  readonly kind: "started";
18
19
  readonly checkId: string;
19
20
  readonly displayName: string;
21
+ readonly omitQuietPassedRow: boolean;
20
22
  } | {
21
23
  readonly kind: "settled";
22
24
  readonly checkId: string;
23
25
  readonly displayName: string;
24
26
  readonly outcome: CheckOutcome;
25
27
  readonly durationMs: number | null;
26
- readonly visibility: CheckVisibility;
28
+ readonly omitQuietPassedRow: boolean;
27
29
  readonly messages: readonly CheckMessage[];
28
30
  readonly records: readonly CoreRecord[];
29
31
  } | {
@@ -1,8 +1,8 @@
1
- import type { CheckProjectContext } from "../check/check.ts";
2
- import type { RunControls } from "./controls/contract.ts";
1
+ import type { CheckProjectContext, ProjectChanges } from "../check/check.ts";
3
2
  import type { ResolvedInvocationPaths } from "./invocation/paths.ts";
4
3
  /** Materializes only invocation-wide callback input; Check-local options own domain configuration. */
5
4
  export declare function createProjectContext(input: Readonly<{
6
- readonly controls: RunControls;
5
+ readonly changes?: ProjectChanges;
6
+ readonly flags: readonly string[];
7
7
  readonly paths: ResolvedInvocationPaths;
8
8
  }>): CheckProjectContext;
@@ -29,8 +29,8 @@ export interface CheckRunMessage {
29
29
  }
30
30
  /** 只有已形成 terminal Check facts 的 Run branch 才具备的完整结果 readback。 */
31
31
  export interface RunResultFacts {
32
- /** 调用方未配置 aggregation 时为 `null`;否则是选中 Check statuses 的 invocation-level conclusion。 */
33
- readonly aggregate: CheckAggregate | null;
32
+ /** 有完整 terminal Check facts 时,由有效 Check 列表形成的 invocation-level conclusion。 */
33
+ readonly aggregate: CheckAggregate;
34
34
  /** 按 canonical Check order 的 duration facts;未执行 Check 仍以 `null` 保留。 */
35
35
  readonly checkDurations: readonly CheckDuration[];
36
36
  /** 已接受的 author 与 console-capture messages,不决定 Check outcome。 */
@@ -99,7 +99,7 @@ export type RunResult = Readonly<{
99
99
  readonly definitionWarnings: readonly DefinitionWarning[];
100
100
  /** 失败的 machine、progress、diagnostic 或 scheduler-measurement output 类别。 */
101
101
  readonly diagnostic: Readonly<{
102
- readonly code: "machine-publication-failed" | "progress-rendering-failed" | "diagnostic-logging-failed" | "scheduler-measurement-hooks-failed";
102
+ readonly code: "machine-publication-failed" | "progress-rendering-failed" | "diagnostic-logging-failed" | "scheduler-terminal-effects-failed";
103
103
  }>;
104
104
  readonly outputs: RunOutputStatuses;
105
105
  } & RunResultFacts)>;
@@ -10,7 +10,7 @@ export type { RunDiagnostic, RunResult } from "./result.ts";
10
10
  * @param controls - 本次 invocation context 与 outputs 使用的闭合控制值。
11
11
  * @returns ordinary configuration、planning、execution、cancellation 与 output failures 通过 `RunResult`
12
12
  * 返回;调用方先按 `kind` narrow。
13
- * @remarks Definition validation 关闭 authoring grammar;可选 Check preflight 在其 Task 通过直接 relation
13
+ * @remarks Definition validation 关闭 authoring grammar;可选 Check preparation 在其 Task 通过直接 relation
14
14
  * readiness 后被 Scheduler admission 时运行,并先于该 Check 自己的 execution callback。它受该 Task 的
15
15
  * mutex、capacity、priority 与 cancellation 约束,而不是 invocation-wide barrier。`output` branch 同时提供
16
16
  * 完整 final snapshot 与 output failure diagnostic。
@@ -0,0 +1,10 @@
1
+ /** Required accessors for compiler-owned dense slot indexes. */
2
+ import type { PlannedTask } from "../graph.ts";
3
+ import type { CompiledAdmissionGraph } from "./compiled-graph.ts";
4
+ export declare function requiredTaskForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): PlannedTask;
5
+ export declare function requiredTaskMutexSlotsForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): CompiledAdmissionGraph["taskMutexSlots"][number];
6
+ export declare function requiredTaskResourceClaimsForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): CompiledAdmissionGraph["taskResourceClaims"][number];
7
+ export declare function requiredReverseDependenciesForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): CompiledAdmissionGraph["relationIndexes"]["reverseDependencies"][number];
8
+ export declare function requiredReverseObservationsForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): CompiledAdmissionGraph["relationIndexes"]["reverseObservations"][number];
9
+ export declare function requiredReverseMutexOccurrencesForCompiled(compiled: CompiledAdmissionGraph, mutexSlot: number): CompiledAdmissionGraph["relationIndexes"]["reverseMutexOccurrences"][number];
10
+ export declare function requiredScopeTerminalSlotsForCompiled(compiled: CompiledAdmissionGraph, taskSlot: number): CompiledAdmissionGraph["scopeSlotsByTerminalTaskSlot"][number];
@@ -1,4 +1,4 @@
1
- import type { SchedulerMeasurementContext, SchedulerMeasurementHook } from "../../project-definition/project-definition.ts";
1
+ import type { SchedulerMeasurementContext, SchedulerTerminalEffect } from "../../project-definition/project-definition.ts";
2
2
  import type { PlannedTask, PlannedTaskGraph, PlannedTaskScope, TaskGraph } from "./graph.ts";
3
3
  import { type AdmissionSelectionPolicy } from "./admission-selection-policy.ts";
4
4
  import type { DiagnosticLogger } from "../diagnostic-logging/logger.ts";
@@ -52,9 +52,9 @@ export interface RunTaskGraphOptions<TResult> {
52
52
  /** Explicit enabled-only handoff; no Scheduler behavior is inferred from a logger shape. */
53
53
  readonly performanceDiagnostics?: SchedulerPerformanceDiagnosticsInput;
54
54
  /** Runtime-only terminal consumers; their context is formed after Scheduler drain. */
55
- readonly measurementHooks?: readonly SchedulerMeasurementHook[];
56
- readonly onMeasurementHookFailure?: () => void;
57
- readonly onMeasurementHooksSettled?: () => void;
55
+ readonly terminalEffects?: readonly SchedulerTerminalEffect[];
56
+ readonly onTerminalEffectFailure?: () => void;
57
+ readonly onTerminalEffectsSettled?: () => void;
58
58
  /** Product-private test observer; no package consumer can supply this through `run`. */
59
59
  readonly onAdmissionCoreEffect?: (effect: SchedulerAdmissionCoreEffect) => void;
60
60
  readonly graph: TaskGraph;
@@ -1,4 +1,4 @@
1
- import type { AdmissionPolicyMeasurement, SchedulerMeasurementEffect, SchedulerMeasurementHook, SchedulerRawMeasurement } from "../../../project-definition/project-definition.ts";
1
+ import type { AdmissionPolicyMeasurement, SchedulerMeasurementEffect, SchedulerTerminalEffect, SchedulerRawMeasurement } from "../../../project-definition/project-definition.ts";
2
2
  import { type DiagnosticLogger } from "../../diagnostic-logging/logger.ts";
3
3
  /** Explicit, enabled-only private handoff; the Scheduler never infers this from logger behavior. */
4
4
  export type SchedulerPerformanceDiagnosticsInput = Readonly<{
@@ -43,5 +43,5 @@ export declare class SchedulerPerformanceDiagnostics {
43
43
  completePendingActionObservation(): void;
44
44
  admittedTaskIds(): readonly string[];
45
45
  /** Internal default terminal hook; it contains writer failure without runner special-casing. */
46
- defaultSummaryHook(): SchedulerMeasurementHook | undefined;
46
+ defaultSummaryHook(): SchedulerTerminalEffect | undefined;
47
47
  }
@@ -1,7 +1,7 @@
1
1
  import type { SchedulerMeasurementContext } from "../../project-definition/project-definition.ts";
2
2
  import type { RunTaskGraphOptions, SchedulerState } from "./execution-state.ts";
3
3
  import type { SchedulerPerformanceDiagnostics } from "./measurement/diagnostics.ts";
4
- /** Delivers the terminal measurement to the internal summary and caller hooks exactly once. */
4
+ /** Delivers the terminal measurement to the internal summary and caller effects exactly once. */
5
5
  export declare function observeTerminalMeasurement<TResult>(input: Readonly<{
6
6
  readonly diagnostics: SchedulerPerformanceDiagnostics;
7
7
  readonly options: RunTaskGraphOptions<TResult>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-json-by-key.mjs","sourceRoot":"","sources":["../../../src/cache/cache-json-by-key.ts"],"names":[],"mappings":"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","sourcesContent":["/** caller-keyed canonical JSON cache 的公开存储边界。 */\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { isAbsolute, join } from \"node:path\";\n\nimport {\n canonicalizeJsonObject,\n canonicalJsonBytes,\n type CanonicalJsonObject\n} from \"../data-boundary/canonical-data.ts\";\nimport { hasExactPlainRecordKeys, snapshotClosedRecord } from \"../data-boundary/closed-values.ts\";\n\nconst CACHE_API_VERSION = \"caller-keyed-json-v1\";\nconst CACHE_ENVELOPE_KEYS = [\"cacheFormatVersion\", \"identityDigest\", \"payload\"] as const;\n\n/**\n * `cacheJsonByKey` 的 caller-owned identity、payload parser 与 computation。\n *\n * `key` 必须覆盖所有会改变 computation 结果的输入、实现、options、toolchain 与声明的外部状态;\n * 不能放入 secret 或低熵敏感值。`directory` 是调用方信任、可自行删除的本地状态空间。\n */\ntype NonThenable<T extends object> = T & Readonly<{ readonly then?: undefined }>;\n\n/** Caller-keyed JSON cache 的 options。 */\nexport interface CacheJsonByKeyOptions<T extends object> {\n /** cache miss、读取失败或 payload 无效时执行的 sync/async computation。 */\n readonly compute: () => unknown;\n /** 调用方信任、可自行清理的 absolute local directory。 */\n readonly directory: string;\n /** 覆盖所有影响 computation 结果的完整 semantic key;不得包含 secret 或低熵敏感值。 */\n readonly key: string;\n /** 调用方为这一类缓存选择的非空 identity namespace。 */\n readonly namespace: string;\n /** 同步验证 cached/computed canonical JSON object,并返回调用方的 typed value。 */\n readonly parse: (value: unknown) => NonThenable<T>;\n /** 调用方控制、在 payload 或 computation contract 改变时更新的非空版本。 */\n readonly version: string;\n}\n\n/** `cacheJsonByKey` 返回的闭合 cache observation 与本次 parser value。 */\nexport type CacheJsonByKeyResult<T extends object> =\n | Readonly<{\n /** 已读取并通过 parser 验证现有 payload。 */\n readonly read: \"hit\";\n /** 本次 value 来自 cache,不调用 `compute`。 */\n readonly source: \"cache\";\n /** `parse` 返回的调用方 typed value。 */\n readonly value: T;\n /** cache hit 不尝试重新写入。 */\n readonly write: \"not-attempted\";\n }>\n | Readonly<{\n /** 没有 entry、读取失败,或已有 payload 未通过 identity/parser 验证。 */\n readonly read: \"failed\" | \"invalid\" | \"miss\";\n /** 本次 value 来自成功的 `compute` 与 `parse`。 */\n readonly source: \"computed\";\n /** `parse` 返回的调用方 typed value。 */\n readonly value: T;\n /** 新 payload 已存储,或存储失败但 typed value 仍可使用。 */\n readonly write: \"failed\" | \"stored\";\n }>;\n\n/**\n * 按 caller 提供的完整 semantic key 复用本地 canonical JSON object。\n *\n * cache hit 不会跳过或重放 Check settlement、Records、messages、duration 或 side effects。读取或写入失败\n * 只通过返回的 observation 可见;只要 `compute` 与 `parse` 成功,就仍返回本次 computation 的 value。\n * 不提供依赖发现、默认目录、lock/single-flight、TTL/LRU、cleanup、remote cache 或 tamper protection。\n */\nexport async function cacheJsonByKey<T extends object>(\n authoredOptions: CacheJsonByKeyOptions<T>\n): Promise<CacheJsonByKeyResult<T>> {\n const options = parseOptions(authoredOptions);\n const identityDigest = cacheIdentityDigest(options);\n const targetPath = join(options.directory, `${identityDigest}.json`);\n const cached = await readCacheEntry({ identityDigest, parse: options.parse, targetPath });\n if (cached.hit) {\n return Object.freeze({\n read: \"hit\",\n source: \"cache\",\n value: cached.value,\n write: \"not-attempted\"\n });\n }\n\n const payload = canonicalizeJsonObject(await options.compute());\n if (payload === undefined) {\n throw new TypeError(\"cacheJsonByKey compute must return a canonical JSON object\");\n }\n const value = parseSynchronously(options.parse, payload, \"computed value\");\n const stored = await publishCacheEntry({\n directory: options.directory,\n identityDigest,\n parse: options.parse,\n payload,\n targetPath\n });\n return Object.freeze({\n read: cached.read,\n source: \"computed\",\n value,\n write: stored ? \"stored\" : \"failed\"\n });\n}\n\ntype ParsedOptions<T extends object> = Readonly<{\n readonly compute: () => unknown;\n readonly directory: string;\n readonly key: string;\n readonly namespace: string;\n readonly parse: (value: unknown) => T;\n readonly version: string;\n}>;\n\nfunction parseOptions<T extends object>(value: CacheJsonByKeyOptions<T>): ParsedOptions<T> {\n const record = snapshotClosedRecord(value);\n if (\n record === undefined ||\n !hasExactPlainRecordKeys(record, [\n \"compute\",\n \"directory\",\n \"key\",\n \"namespace\",\n \"parse\",\n \"version\"\n ])\n ) {\n throw new TypeError(\"cacheJsonByKey options must be a closed object\");\n }\n const { compute, directory, key, namespace, parse, version } = record;\n if (typeof compute !== \"function\" || typeof parse !== \"function\") {\n throw new TypeError(\"cacheJsonByKey compute and parse must be functions\");\n }\n if (\n typeof directory !== \"string\" ||\n directory.length === 0 ||\n directory.includes(\"\\0\") ||\n !isAbsolute(directory)\n ) {\n throw new TypeError(\n \"cacheJsonByKey directory must be a non-empty absolute path without U+0000\"\n );\n }\n if (typeof namespace !== \"string\" || namespace.length === 0) {\n throw new TypeError(\"cacheJsonByKey namespace must be a non-empty string\");\n }\n if (typeof version !== \"string\" || version.length === 0) {\n throw new TypeError(\"cacheJsonByKey version must be a non-empty string\");\n }\n if (typeof key !== \"string\" || key.length === 0) {\n throw new TypeError(\"cacheJsonByKey key must be a non-empty string\");\n }\n const typedOptions: ParsedOptions<T> = {\n compute: value.compute,\n directory: value.directory,\n key: value.key,\n namespace: value.namespace,\n parse: value.parse,\n version: value.version\n };\n if (\n typedOptions.compute !== compute ||\n typedOptions.directory !== directory ||\n typedOptions.key !== key ||\n typedOptions.namespace !== namespace ||\n typedOptions.parse !== parse ||\n typedOptions.version !== version\n ) {\n throw new TypeError(\"cacheJsonByKey options changed during validation\");\n }\n return Object.freeze(typedOptions);\n}\n\nfunction cacheIdentityDigest(options: ParsedOptions<object>): string {\n return createHash(\"sha256\")\n .update(\n canonicalJsonBytes({\n cacheApiVersion: CACHE_API_VERSION,\n key: options.key,\n namespace: options.namespace,\n payloadVersion: options.version\n })\n )\n .digest(\"hex\");\n}\n\ntype CacheRead<T extends object> =\n | Readonly<{ readonly hit: true; readonly value: T }>\n | Readonly<{ readonly hit: false; readonly read: \"failed\" | \"invalid\" | \"miss\" }>;\n\nasync function readCacheEntry<T extends object>(\n input: Readonly<{\n readonly identityDigest: string;\n readonly parse: (value: unknown) => T;\n readonly targetPath: string;\n }>\n): Promise<CacheRead<T>> {\n let source: string;\n try {\n source = await fs.readFile(input.targetPath, \"utf8\");\n } catch (error: unknown) {\n return isMissingPath(error)\n ? Object.freeze({ hit: false, read: \"miss\" })\n : Object.freeze({ hit: false, read: \"failed\" });\n }\n try {\n const envelope = parseEnvelope(JSON.parse(source), input.identityDigest);\n if (envelope === undefined) return Object.freeze({ hit: false, read: \"invalid\" });\n return Object.freeze({\n hit: true,\n value: parseSynchronously(input.parse, envelope.payload, \"cached payload\")\n });\n } catch {\n return Object.freeze({ hit: false, read: \"invalid\" });\n }\n}\n\nfunction parseEnvelope(\n value: unknown,\n identityDigest: string\n): Readonly<{ readonly payload: CanonicalJsonObject }> | undefined {\n const record = snapshotClosedRecord(value);\n if (record === undefined || !hasExactPlainRecordKeys(record, CACHE_ENVELOPE_KEYS))\n return undefined;\n if (record.cacheFormatVersion !== CACHE_API_VERSION || record.identityDigest !== identityDigest) {\n return undefined;\n }\n const payload = canonicalizeJsonObject(record.payload);\n return payload === undefined ? undefined : Object.freeze({ payload });\n}\n\nfunction parseSynchronously<T extends object>(\n parse: (value: unknown) => T,\n payload: CanonicalJsonObject,\n subject: string\n): T {\n const value = parse(payload);\n if (isThenable(value))\n throw new TypeError(`cacheJsonByKey parse must synchronously return ${subject}`);\n return value;\n}\n\nfunction isThenable(value: unknown): boolean {\n return (\n ((typeof value === \"object\" && value !== null) || typeof value === \"function\") &&\n typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\nasync function publishCacheEntry<T extends object>(\n input: Readonly<{\n readonly directory: string;\n readonly identityDigest: string;\n readonly parse: (value: unknown) => T;\n readonly payload: CanonicalJsonObject;\n readonly targetPath: string;\n }>\n): Promise<boolean> {\n const temporaryPath = join(input.directory, `.vibe-check-cache-${randomUUID()}.tmp`);\n try {\n await fs.mkdir(input.directory, { recursive: true });\n await fs.writeFile(\n temporaryPath,\n JSON.stringify({\n cacheFormatVersion: CACHE_API_VERSION,\n identityDigest: input.identityDigest,\n payload: input.payload\n }),\n { encoding: \"utf8\", flag: \"wx\" }\n );\n } catch {\n await fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n return false;\n }\n\n try {\n await fs.rename(temporaryPath, input.targetPath);\n return true;\n } catch (error: unknown) {\n if (isConcurrentTargetConflict(error)) {\n const concurrent = await readCacheEntry({\n identityDigest: input.identityDigest,\n parse: input.parse,\n targetPath: input.targetPath\n });\n await fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n return concurrent.hit;\n }\n await fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n return false;\n }\n}\n\nfunction isConcurrentTargetConflict(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === \"EEXIST\"\n );\n}\n\nfunction isMissingPath(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && (error as { code?: unknown }).code === \"ENOENT\"\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"finding-presentation.mjs","sourceRoot":"","sources":["../../../src/check/finding-presentation.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAU,KAK7C;IACC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAE1D,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CACxD,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CACpD,CAAC;IACF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACzE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CACX,MAAM,CAAC,MAAM,CAAC;YACZ,GAAG,KAAK,CAAC,cAAc,CACrB,MAAM,CAAC,MAAM,CAAC;gBACZ,eAAe;gBACf,YAAY,EAAE,eAAe,CAAC,MAAM;gBACpC,cAAc,EAAE,iBAAiB,CAAC,MAAM;gBACxC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;aAClC,CAAC,CACH;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,mBAAmB,CACjC,MAAyB,EACzB,QAAiC;IAEjC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACzC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,MAAM;QACT,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC;KACnE,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,SAAS,CAAC,gEAAgE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC","sourcesContent":["import type { CheckMessage, CheckResult } from \"./check.ts\";\n\n/**\n * 将 Check-owned Finding 投影为有界 terminal messages 所需的超限上下文。\n * 完整 Finding facts 与深入查看位置继续由调用方拥有。\n */\nexport interface FindingOverflowContext<Finding> {\n readonly omittedFindings: readonly Finding[];\n readonly omittedCount: number;\n readonly presentedCount: number;\n readonly totalCount: number;\n}\n\n/**\n * 将调用方已经稳定排序的 Finding 投影为有界 Check messages。\n *\n * `limit`、安全字段和超限后的深入查看说明都由 producing Check 决定。Product 不读取 Finding\n * shape,也不猜测完整明细位于 Records、artifact、transcript 或其它位置。\n */\nexport function presentCheckFindings<Finding>(input: {\n readonly findings: readonly Finding[];\n readonly limit: number;\n readonly message: (finding: Finding, index: number) => CheckMessage;\n readonly omittedMessage: (context: FindingOverflowContext<Finding>) => CheckMessage;\n}): readonly CheckMessage[] {\n assertFindingLimit(input.limit);\n if (input.findings.length === 0) return Object.freeze([]);\n\n const presentedFindings = input.findings.slice(0, input.limit);\n const messages = presentedFindings.map((finding, index) =>\n Object.freeze({ ...input.message(finding, index) })\n );\n const omittedFindings = Object.freeze(input.findings.slice(input.limit));\n if (omittedFindings.length > 0) {\n messages.push(\n Object.freeze({\n ...input.omittedMessage(\n Object.freeze({\n omittedFindings,\n omittedCount: omittedFindings.length,\n presentedCount: presentedFindings.length,\n totalCount: input.findings.length\n })\n )\n })\n );\n }\n return Object.freeze(messages);\n}\n\n/** Appends presentation-only messages without changing the owning terminal result. */\nexport function appendCheckMessages<Data extends object>(\n result: CheckResult<Data>,\n messages: readonly CheckMessage[]\n): CheckResult<Data> {\n if (messages.length === 0) return result;\n return Object.freeze({\n ...result,\n messages: Object.freeze([...(result.messages ?? []), ...messages])\n });\n}\n\nfunction assertFindingLimit(limit: number): void {\n if (!Number.isSafeInteger(limit) || limit < 0) {\n throw new TypeError(\"Finding presentation limit must be a non-negative safe integer\");\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconciliation.mjs","sourceRoot":"","sources":["../../../src/finding-waivers/reconciliation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n canonicalizeJsonValue,\n canonicalJsonText,\n type CanonicalJsonObject,\n type CanonicalJsonValue\n} from \"../data-boundary/canonical-data.ts\";\n\n/** 由采用方声明、用于匹配一个 finding 的语义身份与豁免理由。 */\nexport interface FindingWaiver<Identity> {\n /** 调用方定义的稳定 finding 身份;匹配时按 canonical JSON 结构比较。 */\n readonly identity: Identity;\n /** 解释该 finding 在当前范围内可被豁免的非空理由。 */\n readonly reason: string;\n}\n\n/** helper 安全 materialize 后保留的 waiver evidence;identity 是 detached canonical JSON。 */\nexport interface MaterializedFindingWaiver {\n /** 从 authored identity materialize 的 detached、deep-frozen canonical JSON。 */\n readonly identity: CanonicalJsonValue;\n /** 从 authored reason materialize 的非空理由。 */\n readonly reason: string;\n}\n\n/** 一项 finding waiver 的配置与匹配次数审计。 */\nexport interface FindingWaiverAudit {\n /** 被审计的 materialized authored waiver evidence,而非调用方可变输入引用。 */\n readonly waiver: MaterializedFindingWaiver;\n /** 该 waiver identity 在完整 finding 集合中匹配到的数量。 */\n readonly matchCount: number;\n /** 未使用、正常应用,或因过宽而没有应用。 */\n readonly status: \"unused\" | \"applied\" | \"overmatched\";\n}\n\n/** reconciliation 后单个 finding 的可执行处置;只有 `waived` branch 携带 matched waiver。 */\nexport type ReconciledFinding<Finding> = Readonly<\n | {\n /** 原始 finding;helper 不解释或改写它的领域字段。 */\n readonly finding: Finding;\n /** 没有匹配 waiver 的正常待处理 finding。 */\n readonly disposition: \"actionable\";\n }\n | {\n /** 原始 finding;helper 不解释或改写它的领域字段。 */\n readonly finding: Finding;\n /** 恰好匹配一项 waiver 的 finding。 */\n readonly disposition: \"waived\";\n /** applied waiver 的身份和理由。 */\n readonly waiver: MaterializedFindingWaiver;\n }\n | {\n /** 原始 finding;helper 不解释或改写它的领域字段。 */\n readonly finding: Finding;\n /** `overmatched` 保持为待处理,避免宽泛 waiver 静默覆盖多个 finding。 */\n readonly disposition: \"overmatched\";\n }\n>;\n\n/** 调用方提供完整候选集、身份识别器和 waiver 配置的输入。 */\nexport interface ReconcileFindingWaiversOptions<Finding, Identity> {\n /** 必须是完整 finding 候选集合,helper 才能审计每项 waiver 的匹配次数。 */\n readonly findings: readonly Finding[];\n /** 从完整 finding 提取调用方选择的稳定语义身份。 */\n readonly identify: (finding: Finding) => Identity;\n /** 要与识别器输出进行 canonical structural matching 的 waiver。 */\n readonly waivers: readonly FindingWaiver<Identity>[];\n}\n\n/** 独立 waiver reconciliation 的完整输出,保留 finding 处置和每项配置审计。 */\nexport interface FindingWaiverReconciliation<Finding> {\n /** 与 input finding 顺序相同的 reconciliation 结果。 */\n readonly findings: readonly ReconciledFinding<Finding>[];\n /** 与 input waiver 顺序相同的完整配置审计。 */\n readonly waiverAudits: readonly FindingWaiverAudit[];\n}\n\n/**\n * 按调用方定义的语义身份对完整 finding 集合和 waiver 配置做 canonical structural reconciliation。\n *\n * 每项 waiver 必须有唯一、可 canonicalize 的 identity 和非空 reason。匹配零项时产生 `unused` 审计;\n * 匹配一项时该 finding 为 `waived`;匹配多项时产生 `overmatched` 审计,相关 finding 保持待处理。\n */\nexport function reconcileFindingWaivers<Finding, Identity>(\n options: ReconcileFindingWaiversOptions<Finding, Identity>\n): FindingWaiverReconciliation<Finding> {\n const waivers = materializeWaivers(options.waivers);\n const matchCounts = new Array<number>(waivers.length).fill(0);\n const waiverIndexesByIdentity = new Map<string, number>();\n for (const [index, waiver] of waivers.entries()) {\n const identity = canonicalIdentity(waiver.identity, \"waiver identity\");\n if (waiverIndexesByIdentity.has(identity)) {\n throw new TypeError(\"Finding waivers must not declare duplicate canonical identities\");\n }\n waiverIndexesByIdentity.set(identity, index);\n }\n\n const matchedWaiverIndexes = options.findings.map((finding) => {\n const identity = canonicalIdentity(options.identify(finding), \"finding identity\");\n const waiverIndex = waiverIndexesByIdentity.get(identity);\n if (waiverIndex !== undefined) matchCounts[waiverIndex] += 1;\n return waiverIndex;\n });\n const waiverAudits = Object.freeze(\n waivers.map((waiver, index) =>\n Object.freeze({\n matchCount: matchCounts[index] ?? 0,\n status: waiverAuditStatus(matchCounts[index] ?? 0),\n waiver\n })\n )\n );\n const findings = Object.freeze(\n options.findings.map((finding, index) => {\n const waiverIndex = matchedWaiverIndexes[index];\n const audit = waiverIndex === undefined ? undefined : waiverAudits[waiverIndex];\n return reconciledFinding(finding, audit);\n })\n );\n return Object.freeze({ findings, waiverAudits });\n}\n\nfunction materializeWaivers<Identity>(\n waivers: readonly FindingWaiver<Identity>[]\n): readonly MaterializedFindingWaiver[] {\n const canonicalWaivers = canonicalizeJsonValue(waivers);\n if (canonicalWaivers === undefined || !isCanonicalArray(canonicalWaivers)) {\n throw new TypeError(\"Finding waivers must be canonical JSON arrays\");\n }\n return Object.freeze(canonicalWaivers.map(materializeWaiver));\n}\n\nfunction materializeWaiver(value: CanonicalJsonValue): MaterializedFindingWaiver {\n if (\n !isCanonicalObject(value) ||\n !Object.hasOwn(value, \"identity\") ||\n !Object.hasOwn(value, \"reason\")\n ) {\n throw new TypeError(\"Finding waivers must declare canonical identity and reason fields\");\n }\n const reason = value.reason;\n if (typeof reason !== \"string\" || reason.length === 0) {\n throw new TypeError(\"Finding waiver reasons must be non-empty strings\");\n }\n return Object.freeze({ identity: value.identity, reason });\n}\n\nfunction isCanonicalObject(value: CanonicalJsonValue): value is CanonicalJsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isCanonicalArray(value: CanonicalJsonValue): value is readonly CanonicalJsonValue[] {\n return Array.isArray(value);\n}\n\nfunction canonicalIdentity(identity: unknown, kind: string): string {\n try {\n return canonicalJsonText(identity);\n } catch {\n throw new TypeError(`Finding ${kind} must be canonical JSON`);\n }\n}\n\nfunction waiverAuditStatus(matchCount: number): FindingWaiverAudit[\"status\"] {\n if (matchCount === 0) return \"unused\";\n return matchCount === 1 ? \"applied\" : \"overmatched\";\n}\n\nfunction reconciledFinding<Finding>(\n finding: Finding,\n audit: FindingWaiverAudit | undefined\n): ReconciledFinding<Finding> {\n if (audit === undefined) return Object.freeze({ disposition: \"actionable\", finding });\n if (audit.status === \"applied\") {\n return Object.freeze({ disposition: \"waived\", finding, waiver: audit.waiver });\n }\n return Object.freeze({ disposition: \"overmatched\", finding });\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bounded-history.mjs","sourceRoot":"","sources":["../../../../src/learned-critical-path/duration-model/bounded-history.ts"],"names":[],"mappings":"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","sourcesContent":["export const SCHEDULER_HISTORY_ENVELOPE_VERSION = \"scheduler-history-envelope-v1\";\nexport const SCHEDULER_HISTORY_FILE_NAME = \"scheduler-history.json\";\nexport const SCHEDULER_HISTORY_MODEL_VERSION = \"scheduler-duration-model-v1\";\nexport const MAX_SCHEDULER_HISTORY_SAMPLES_PER_SERIES = 32;\nexport const MAX_SCHEDULER_HISTORY_SERIES = 4_096;\n\n/** Bound persisted task-active durations so aggregates remain exact safe integers. */\nexport const MAX_SCHEDULER_HISTORY_DURATION_MS = 2_147_483_647;\n\n/** Persisted terminal kind vocabulary; duration storage does not depend on Scheduler ownership. */\nexport type SchedulerDurationSettlementKind =\n | \"completed\"\n | \"prerequisite-unsatisfied\"\n | \"failed\"\n | \"blocked\"\n | \"cancelled-before-start\";\n\nexport interface SchedulerHistorySample {\n readonly durationMs: number;\n readonly observationSequence: number;\n readonly settlementKind: SchedulerDurationSettlementKind;\n}\n\nexport interface SchedulerHistorySeries {\n readonly identityDigest: string;\n readonly latestObservationSequence: number;\n readonly samples: readonly SchedulerHistorySample[];\n}\n\n/** Immutable, Product-private local model; the only persisted state is its closed envelope. */\nexport interface SchedulerHistoryModel {\n readonly latestObservationSequence: number;\n readonly series: readonly SchedulerHistorySeries[];\n}\n\nexport function emptySchedulerHistory(): SchedulerHistoryModel {\n return Object.freeze({ latestObservationSequence: 0, series: Object.freeze([]) });\n}\n\nexport function schedulerHistorySeries(\n history: SchedulerHistoryModel,\n identityDigest: string\n): SchedulerHistorySeries | undefined {\n return history.series.find((series) => series.identityDigest === identityDigest);\n}\n\nexport function freezeSchedulerHistoryModel(input: {\n readonly latestObservationSequence: number;\n readonly series: readonly SchedulerHistorySeries[];\n}): SchedulerHistoryModel {\n return Object.freeze({\n latestObservationSequence: input.latestObservationSequence,\n series: Object.freeze(\n [...input.series]\n .sort((left, right) => compareText(left.identityDigest, right.identityDigest))\n .map((series) =>\n Object.freeze({\n identityDigest: series.identityDigest,\n latestObservationSequence: series.latestObservationSequence,\n samples: Object.freeze(\n series.samples.map((sample) =>\n Object.freeze({\n durationMs: sample.durationMs,\n observationSequence: sample.observationSequence,\n settlementKind: sample.settlementKind\n })\n )\n )\n })\n )\n )\n });\n}\n\nexport function isSchedulerHistoryIdentityDigest(value: unknown): value is string {\n return typeof value === \"string\" && /^sha256:[0-9a-f]{64}$/.test(value);\n}\n\nexport function isSchedulerSettlementKind(\n value: unknown\n): value is SchedulerDurationSettlementKind {\n return (\n value === \"completed\" ||\n value === \"prerequisite-unsatisfied\" ||\n value === \"failed\" ||\n value === \"blocked\" ||\n value === \"cancelled-before-start\"\n );\n}\n\nexport function isBoundedDurationMs(value: unknown): value is number {\n return (\n typeof value === \"number\" &&\n Number.isFinite(value) &&\n value >= 0 &&\n value <= MAX_SCHEDULER_HISTORY_DURATION_MS\n );\n}\n\nexport function isObservationSequence(value: unknown): value is number {\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prediction.mjs","sourceRoot":"","sources":["../../../../src/learned-critical-path/duration-model/prediction.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport { canonicalJsonBytes, type CanonicalJsonValue } from \"../../data-boundary/canonical-data.ts\";\nimport {\n SCHEDULER_HISTORY_MODEL_VERSION,\n schedulerHistorySeries,\n type SchedulerHistoryModel\n} from \"./bounded-history.ts\";\n\nexport type SchedulerPredictionSource = \"learned\" | \"project-prior\" | \"cold-start\";\n\nexport interface SchedulerPredictionInput {\n readonly authoredOptions: CanonicalJsonValue;\n readonly checkId: string;\n readonly flags: CanonicalJsonValue;\n readonly taskId: string;\n}\n\nexport interface SchedulerTaskPrediction {\n readonly estimatedDurationMs: number;\n readonly identityDigest: string;\n readonly meanDurationMs: number | null;\n readonly p90DurationMs: number | null;\n readonly sampleCount: number;\n readonly source: SchedulerPredictionSource;\n readonly taskId: string;\n}\n\n/** Frozen before Scheduler admission; it does not retain authored options or flag values. */\nexport interface SchedulerPredictionSnapshot {\n readonly digest: string;\n readonly modelVersion: string;\n readonly predictions: readonly SchedulerTaskPrediction[];\n}\n\nexport function createSchedulerHistoryIdentity(input: {\n readonly authoredOptions: CanonicalJsonValue;\n readonly checkId: string;\n readonly flags: CanonicalJsonValue;\n}): string {\n const authoredOptionsDigest = digestCanonicalValue(input.authoredOptions);\n const flagsDigest = digestCanonicalValue(input.flags);\n return digestCanonicalValue({\n authoredOptionsDigest,\n checkId: input.checkId,\n flagsDigest,\n modelVersion: SCHEDULER_HISTORY_MODEL_VERSION\n });\n}\n\n/** Forms learned means first, then one project median prior, without invoking preflight. */\nexport function createSchedulerPredictionSnapshot(\n history: SchedulerHistoryModel,\n inputs: readonly SchedulerPredictionInput[],\n coldStartDurationMs = 1\n): SchedulerPredictionSnapshot {\n const learned = inputs.map((input) => learnedPrediction(history, input));\n const projectPrior = median(\n learned.flatMap((prediction) =>\n prediction.source === \"learned\" ? [prediction.estimatedDurationMs] : []\n )\n );\n const predictions = learned.map((prediction) => {\n if (prediction.source === \"learned\") return prediction;\n if (projectPrior === undefined) return coldStartPrediction(prediction, coldStartDurationMs);\n return projectPriorPrediction(prediction, projectPrior);\n });\n const digest = digestCanonicalValue({\n modelVersion: SCHEDULER_HISTORY_MODEL_VERSION,\n predictions: [...predictions]\n .sort((left, right) => compareText(left.taskId, right.taskId))\n .map((prediction) => ({\n estimatedDurationMs: prediction.estimatedDurationMs,\n identityDigest: prediction.identityDigest,\n meanDurationMs: prediction.meanDurationMs,\n p90DurationMs: prediction.p90DurationMs,\n sampleCount: prediction.sampleCount,\n source: prediction.source,\n taskId: prediction.taskId\n }))\n });\n return Object.freeze({\n digest,\n modelVersion: SCHEDULER_HISTORY_MODEL_VERSION,\n predictions: Object.freeze(predictions.map(freezePrediction))\n });\n}\n\nexport function predictionForTask(\n snapshot: SchedulerPredictionSnapshot,\n taskId: string\n): SchedulerTaskPrediction | undefined {\n return snapshot.predictions.find((prediction) => prediction.taskId === taskId);\n}\n\nfunction learnedPrediction(\n history: SchedulerHistoryModel,\n input: SchedulerPredictionInput\n): SchedulerTaskPrediction {\n const identityDigest = createSchedulerHistoryIdentity(input);\n const samples = schedulerHistorySeries(history, identityDigest)?.samples ?? [];\n if (samples.length === 0) {\n return Object.freeze({\n estimatedDurationMs: 0,\n identityDigest,\n meanDurationMs: null,\n p90DurationMs: null,\n sampleCount: 0,\n source: \"cold-start\",\n taskId: input.taskId\n });\n }\n const meanDurationMs = arithmeticMean(samples.map((sample) => sample.durationMs));\n return Object.freeze({\n estimatedDurationMs: meanDurationMs,\n identityDigest,\n meanDurationMs,\n p90DurationMs: p90(samples.map((sample) => sample.durationMs)),\n sampleCount: samples.length,\n source: \"learned\",\n taskId: input.taskId\n });\n}\n\nfunction projectPriorPrediction(\n prediction: SchedulerTaskPrediction,\n projectPrior: number\n): SchedulerTaskPrediction {\n return Object.freeze({\n ...prediction,\n estimatedDurationMs: projectPrior,\n source: \"project-prior\"\n });\n}\n\nfunction coldStartPrediction(\n prediction: SchedulerTaskPrediction,\n coldStartDurationMs: number\n): SchedulerTaskPrediction {\n return Object.freeze({\n ...prediction,\n estimatedDurationMs: coldStartDurationMs,\n source: \"cold-start\"\n });\n}\n\nfunction freezePrediction(prediction: SchedulerTaskPrediction): SchedulerTaskPrediction {\n return Object.freeze({ ...prediction });\n}\n\nfunction digestCanonicalValue(value: CanonicalJsonValue): string {\n return `sha256:${createHash(\"sha256\").update(canonicalJsonBytes(value)).digest(\"hex\")}`;\n}\n\nfunction arithmeticMean(values: readonly number[]): number {\n return values.reduce((total, value) => total + value, 0) / values.length;\n}\n\n/** The p90 is the nearest-rank element from an ascending finite duration window. */\nfunction p90(values: readonly number[]): number {\n const ordered = [...values].sort((left, right) => left - right);\n const index = Math.ceil(ordered.length * 0.9) - 1;\n return ordered[index] ?? 0;\n}\n\nfunction median(values: readonly number[]): number | undefined {\n if (values.length === 0) return undefined;\n const ordered = [...values].sort((left, right) => left - right);\n const middle = Math.floor(ordered.length / 2);\n const upper = ordered[middle];\n if (upper === undefined) return undefined;\n if (ordered.length % 2 === 1) return upper;\n const lower = ordered[middle - 1];\n return lower === undefined ? undefined : (lower + upper) / 2;\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"preparation.mjs","sourceRoot":"","sources":["../../../../src/learned-critical-path/duration-model/preparation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAA6C,MAAM,gBAAgB,CAAC;AACnG,OAAO,EACL,iCAAiC,EAGlC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAsB3E,uGAAuG;AACvG,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,KAMnD;IACC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChE,MAAM,UAAU,GAAG,iCAAiC,CAClD,MAAM,CAAC,OAAO,EACd,KAAK,CAAC,gBAAgB,EACtB,KAAK,CAAC,mBAAmB,CAC1B,CAAC;QACF,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,OAAO;YACb,UAAU;YACV,eAAe,EAAE,MAAM,CAAC,WAAW;YACnC,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM;YACjD,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE;gBACpC,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,sBAAsB,CAAC;wBACtC,OAAO,EAAE,MAAM,CAAC,OAAO;wBACvB,UAAU;wBACV,cAAc,EAAE,mBAAmB,CAAC,cAAc;wBAClD,YAAY,EAAE,mBAAmB,CAAC,SAAS,CAAC,YAAY;wBACxD,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;wBAC9C,SAAS,EAAE,KAAK,CAAC,SAAS;qBAC3B,CAAC,CAAC;oBACH,MAAM,gBAAgB,GAAG,MAAM,qBAAqB,CAClD,KAAK,CAAC,cAAc,EACpB,QAAQ,CAAC,OAAO,CACjB,CAAC;oBACF,OAAO,MAAM,CAAC,MAAM,CAAC;wBACnB,IAAI,EAAE,UAAU;wBAChB,SAAS,EAAE,QAAQ,CAAC,WAAW;wBAC/B,gBAAgB;qBACjB,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC","sourcesContent":["import type { SchedulerMeasurementContext } from \"../../project-definition/project-definition.ts\";\nimport { recordSchedulerHistory, type SchedulerHistoryRecordingObservation } from \"./recording.ts\";\nimport {\n createSchedulerPredictionSnapshot,\n type SchedulerPredictionInput,\n type SchedulerPredictionSnapshot\n} from \"./prediction.ts\";\nimport { loadSchedulerHistory, writeSchedulerHistory } from \"./storage.ts\";\n\nexport type SchedulerDurationModelPreparation =\n | Readonly<{\n readonly kind: \"ready\";\n readonly prediction: SchedulerPredictionSnapshot;\n readonly readObservation: Awaited<ReturnType<typeof loadSchedulerHistory>>[\"observation\"];\n readonly retainedSeriesCount: number;\n readonly record: (\n terminalMeasurement: SchedulerMeasurementContext\n ) => Promise<SchedulerDurationModelRecordObservation>;\n }>\n | Readonly<{ readonly kind: \"static-fallback\" }>;\n\nexport type SchedulerDurationModelRecordObservation =\n | Readonly<{\n readonly kind: \"recorded\";\n readonly recording: SchedulerHistoryRecordingObservation;\n readonly writeObservation: Awaited<ReturnType<typeof writeSchedulerHistory>>;\n }>\n | Readonly<{ readonly kind: \"failed\" }>;\n\n/** Prepares one immutable duration prediction and its terminal record capability outside Scheduler. */\nexport async function prepareSchedulerDurationModel(input: {\n readonly predictionInputs: readonly SchedulerPredictionInput[];\n readonly stateDirectory: string;\n readonly coldStartDurationMs?: number;\n readonly maxSamplesPerSeries?: number;\n readonly maxSeries?: number;\n}): Promise<SchedulerDurationModelPreparation> {\n try {\n const loaded = await loadSchedulerHistory(input.stateDirectory);\n const prediction = createSchedulerPredictionSnapshot(\n loaded.history,\n input.predictionInputs,\n input.coldStartDurationMs\n );\n return Object.freeze({\n kind: \"ready\",\n prediction,\n readObservation: loaded.observation,\n retainedSeriesCount: loaded.history.series.length,\n record: async (terminalMeasurement) => {\n try {\n const recorded = recordSchedulerHistory({\n history: loaded.history,\n prediction,\n rawMeasurement: terminalMeasurement.rawMeasurement,\n settledTasks: terminalMeasurement.execution.settledTasks,\n maxSamplesPerSeries: input.maxSamplesPerSeries,\n maxSeries: input.maxSeries\n });\n const writeObservation = await writeSchedulerHistory(\n input.stateDirectory,\n recorded.history\n );\n return Object.freeze({\n kind: \"recorded\",\n recording: recorded.observation,\n writeObservation\n });\n } catch {\n return Object.freeze({ kind: \"failed\" });\n }\n }\n });\n } catch {\n return Object.freeze({ kind: \"static-fallback\" });\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"recording.mjs","sourceRoot":"","sources":["../../../../src/learned-critical-path/duration-model/recording.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SchedulerMeasurementAdmission,\n SchedulerRawMeasurement\n} from \"../../project-definition/project-definition.ts\";\nimport {\n freezeSchedulerHistoryModel,\n isBoundedDurationMs,\n MAX_SCHEDULER_HISTORY_SAMPLES_PER_SERIES,\n MAX_SCHEDULER_HISTORY_SERIES,\n type SchedulerDurationSettlementKind,\n type SchedulerHistoryModel,\n type SchedulerHistorySeries\n} from \"./bounded-history.ts\";\nimport { predictionForTask, type SchedulerPredictionSnapshot } from \"./prediction.ts\";\n\nexport type SchedulerHistoryRecordingObservation =\n | Readonly<{\n readonly acceptedSampleCount: number;\n readonly retainedSeriesCount: number;\n readonly status: \"recorded\";\n }>\n | Readonly<{\n readonly acceptedSampleCount: 0;\n readonly retainedSeriesCount: number;\n readonly status: \"timing-unavailable\";\n }>;\n\nexport interface SchedulerHistoryRecording {\n readonly history: SchedulerHistoryModel;\n readonly observation: SchedulerHistoryRecordingObservation;\n}\n\n/** Merges only trusted terminal Scheduler occupancy intervals; unavailable timing creates no samples. */\nexport function recordSchedulerHistory(input: {\n readonly history: SchedulerHistoryModel;\n readonly prediction: SchedulerPredictionSnapshot;\n readonly rawMeasurement: SchedulerRawMeasurement;\n readonly settledTasks: readonly Readonly<{\n readonly kind: SchedulerDurationSettlementKind;\n readonly taskId: string;\n }>[];\n readonly maxSamplesPerSeries?: number;\n readonly maxSeries?: number;\n}): SchedulerHistoryRecording {\n const rawMeasurement = input.rawMeasurement;\n const timingFacts = rawMeasurement.timingFacts;\n if (rawMeasurement.timing.availability !== \"available\" || timingFacts === undefined) {\n return Object.freeze({\n history: input.history,\n observation: Object.freeze({\n acceptedSampleCount: 0,\n retainedSeriesCount: input.history.series.length,\n status: \"timing-unavailable\"\n })\n });\n }\n\n return recordedHistory(input, timingFacts.admissions);\n}\n\nfunction recordedHistory(\n input: Parameters<typeof recordSchedulerHistory>[0],\n admissions: readonly SchedulerMeasurementAdmission[]\n): SchedulerHistoryRecording {\n const merged = mergeVerifiedAdmissionSamples({\n admissions,\n history: input.history,\n prediction: input.prediction,\n settledByTaskId: new Map(input.settledTasks.map((settled) => [settled.taskId, settled.kind])),\n maxSamplesPerSeries: input.maxSamplesPerSeries ?? MAX_SCHEDULER_HISTORY_SAMPLES_PER_SERIES\n });\n const retained = retainRecentSeries(\n merged.seriesByIdentity.values(),\n input.maxSeries ?? MAX_SCHEDULER_HISTORY_SERIES\n );\n const history = freezeSchedulerHistoryModel({\n latestObservationSequence: merged.latestObservationSequence,\n series: retained\n });\n return Object.freeze({\n history,\n observation: Object.freeze({\n acceptedSampleCount: merged.acceptedSampleCount,\n retainedSeriesCount: history.series.length,\n status: \"recorded\"\n })\n });\n}\n\ntype VerifiedAdmissionMerge = Readonly<{\n readonly acceptedSampleCount: number;\n readonly latestObservationSequence: number;\n readonly seriesByIdentity: ReadonlyMap<string, SchedulerHistorySeries>;\n}>;\n\n/** Applies valid admissions in Scheduler order and returns the updated identity histories. */\nfunction mergeVerifiedAdmissionSamples(input: {\n readonly admissions: readonly SchedulerMeasurementAdmission[];\n readonly history: SchedulerHistoryModel;\n readonly prediction: SchedulerPredictionSnapshot;\n readonly settledByTaskId: ReadonlyMap<string, SchedulerDurationSettlementKind>;\n readonly maxSamplesPerSeries: number;\n}): VerifiedAdmissionMerge {\n const seriesByIdentity = new Map(\n input.history.series.map((series) => [series.identityDigest, series] as const)\n );\n let latestObservationSequence = input.history.latestObservationSequence;\n let acceptedSampleCount = 0;\n for (const admission of input.admissions) {\n const sample = sampleForAdmission(admission, input.prediction, input.settledByTaskId);\n if (sample === undefined || latestObservationSequence === Number.MAX_SAFE_INTEGER) continue;\n latestObservationSequence += 1;\n appendSampleToIdentityHistory(\n seriesByIdentity,\n sample,\n latestObservationSequence,\n input.maxSamplesPerSeries\n );\n acceptedSampleCount += 1;\n }\n return Object.freeze({ acceptedSampleCount, latestObservationSequence, seriesByIdentity });\n}\n\nfunction appendSampleToIdentityHistory(\n seriesByIdentity: Map<string, SchedulerHistorySeries>,\n sample: AdmissionSample,\n observationSequence: number,\n maxSamplesPerSeries: number\n): void {\n const existing = seriesByIdentity.get(sample.identityDigest);\n const samples = [\n ...(existing?.samples ?? []),\n {\n durationMs: sample.durationMs,\n observationSequence,\n settlementKind: sample.settlementKind\n }\n ].slice(-maxSamplesPerSeries);\n seriesByIdentity.set(\n sample.identityDigest,\n Object.freeze({\n identityDigest: sample.identityDigest,\n latestObservationSequence: observationSequence,\n samples: Object.freeze(samples)\n })\n );\n}\n\ntype AdmissionSample = Readonly<{\n readonly durationMs: number;\n readonly identityDigest: string;\n readonly settlementKind: SchedulerDurationSettlementKind;\n}>;\n\nfunction sampleForAdmission(\n admission: Readonly<{\n readonly admittedAtMonotonicMs: number | null;\n readonly settledAtMonotonicMs: number | null;\n readonly taskId: string;\n }>,\n prediction: SchedulerPredictionSnapshot,\n settledByTaskId: ReadonlyMap<string, SchedulerDurationSettlementKind>\n): AdmissionSample | undefined {\n if (\n admission.admittedAtMonotonicMs === null ||\n admission.settledAtMonotonicMs === null ||\n !isFiniteMonotonicTimestamp(admission.admittedAtMonotonicMs) ||\n !isFiniteMonotonicTimestamp(admission.settledAtMonotonicMs) ||\n admission.settledAtMonotonicMs < admission.admittedAtMonotonicMs\n ) {\n return undefined;\n }\n const durationMs = admission.settledAtMonotonicMs - admission.admittedAtMonotonicMs;\n if (!isBoundedDurationMs(durationMs)) return undefined;\n const taskPrediction = predictionForTask(prediction, admission.taskId);\n const settlementKind = settledByTaskId.get(admission.taskId);\n if (taskPrediction === undefined || settlementKind === undefined) return undefined;\n return Object.freeze({\n durationMs,\n identityDigest: taskPrediction.identityDigest,\n settlementKind\n });\n}\n\nfunction retainRecentSeries(\n series: Iterable<SchedulerHistorySeries>,\n maxSeries: number\n): readonly SchedulerHistorySeries[] {\n return Object.freeze(\n [...series]\n .sort(\n (left, right) =>\n right.latestObservationSequence - left.latestObservationSequence ||\n compareText(left.identityDigest, right.identityDigest)\n )\n .slice(0, maxSeries)\n );\n}\n\nfunction isFiniteMonotonicTimestamp(value: number): boolean {\n return Number.isFinite(value) && value >= 0 && value <= Number.MAX_SAFE_INTEGER;\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.mjs","sourceRoot":"","sources":["../../../../src/learned-critical-path/duration-model/storage.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { randomUUID } from \"node:crypto\";\n\nimport { canonicalJsonText } from \"../../data-boundary/canonical-data.ts\";\nimport {\n hasExactPlainRecordKeys,\n snapshotClosedArray,\n snapshotClosedRecord\n} from \"../../data-boundary/closed-values.ts\";\nimport {\n emptySchedulerHistory,\n freezeSchedulerHistoryModel,\n isBoundedDurationMs,\n isObservationSequence,\n isSchedulerHistoryIdentityDigest,\n isSchedulerSettlementKind,\n MAX_SCHEDULER_HISTORY_SAMPLES_PER_SERIES,\n MAX_SCHEDULER_HISTORY_SERIES,\n SCHEDULER_HISTORY_ENVELOPE_VERSION,\n SCHEDULER_HISTORY_FILE_NAME,\n SCHEDULER_HISTORY_MODEL_VERSION,\n type SchedulerHistoryModel,\n type SchedulerHistorySample,\n type SchedulerHistorySeries\n} from \"./bounded-history.ts\";\n\nconst ENVELOPE_KEYS = [\n \"envelopeVersion\",\n \"latestObservationSequence\",\n \"modelVersion\",\n \"series\"\n] as const;\nconst SERIES_KEYS = [\"identityDigest\", \"latestObservationSequence\", \"samples\"] as const;\nconst SAMPLE_KEYS = [\"durationMs\", \"observationSequence\", \"settlementKind\"] as const;\n\nexport type SchedulerHistoryReadObservation =\n | \"loaded\"\n | \"missing\"\n | \"invalid\"\n | \"incompatible\"\n | \"failed\";\n\nexport type SchedulerHistoryWriteObservation = \"stored\" | \"failed\";\n\nexport interface SchedulerHistoryLoad {\n readonly history: SchedulerHistoryModel;\n readonly observation: SchedulerHistoryReadObservation;\n}\n\n/** Reads untrusted local state and always degrades to an empty model on an I/O or format fault. */\nexport async function loadSchedulerHistory(stateDirectory: string): Promise<SchedulerHistoryLoad> {\n let source: string;\n try {\n source = await fs.readFile(schedulerHistoryPath(stateDirectory), \"utf8\");\n } catch (error: unknown) {\n return Object.freeze({\n history: emptySchedulerHistory(),\n observation: isMissingPath(error) ? \"missing\" : \"failed\"\n });\n }\n\n try {\n const parsed = parseSchedulerHistoryEnvelope(JSON.parse(source));\n if (parsed.kind === \"incompatible\") {\n return Object.freeze({ history: emptySchedulerHistory(), observation: \"incompatible\" });\n }\n if (parsed.kind === \"invalid\") {\n return Object.freeze({ history: emptySchedulerHistory(), observation: \"invalid\" });\n }\n return Object.freeze({ history: parsed.history, observation: \"loaded\" });\n } catch {\n return Object.freeze({ history: emptySchedulerHistory(), observation: \"invalid\" });\n }\n}\n\n/** Publishes a full closed model through a same-directory temporary file and atomic replacement. */\nexport async function writeSchedulerHistory(\n stateDirectory: string,\n history: SchedulerHistoryModel\n): Promise<SchedulerHistoryWriteObservation> {\n let temporaryPath: string | undefined;\n try {\n const targetPath = schedulerHistoryPath(stateDirectory);\n temporaryPath = join(stateDirectory, `.vibe-check-scheduler-history-${randomUUID()}.tmp`);\n await fs.mkdir(stateDirectory, { recursive: true });\n await fs.writeFile(temporaryPath, schedulerHistoryText(history), {\n encoding: \"utf8\",\n flag: \"wx\"\n });\n await fs.rename(temporaryPath, targetPath);\n return \"stored\";\n } catch {\n return \"failed\";\n } finally {\n if (temporaryPath !== undefined) {\n await fs.rm(temporaryPath, { force: true }).catch(() => undefined);\n }\n }\n}\n\nexport function schedulerHistoryPath(stateDirectory: string): string {\n return join(stateDirectory, SCHEDULER_HISTORY_FILE_NAME);\n}\n\nfunction schedulerHistoryText(history: SchedulerHistoryModel): string {\n return canonicalJsonText({\n envelopeVersion: SCHEDULER_HISTORY_ENVELOPE_VERSION,\n latestObservationSequence: history.latestObservationSequence,\n modelVersion: SCHEDULER_HISTORY_MODEL_VERSION,\n series: history.series.map((series) => ({\n identityDigest: series.identityDigest,\n latestObservationSequence: series.latestObservationSequence,\n samples: series.samples.map((sample) => ({\n durationMs: sample.durationMs,\n observationSequence: sample.observationSequence,\n settlementKind: sample.settlementKind\n }))\n }))\n });\n}\n\ntype ParsedEnvelope =\n | Readonly<{ readonly kind: \"loaded\"; readonly history: SchedulerHistoryModel }>\n | Readonly<{ readonly kind: \"invalid\" }>\n | Readonly<{ readonly kind: \"incompatible\" }>;\n\nfunction parseSchedulerHistoryEnvelope(value: unknown): ParsedEnvelope {\n const envelope = snapshotClosedRecord(value);\n if (envelope === undefined || !hasExactPlainRecordKeys(envelope, ENVELOPE_KEYS)) {\n return Object.freeze({ kind: \"invalid\" });\n }\n if (\n typeof envelope.envelopeVersion !== \"string\" ||\n typeof envelope.modelVersion !== \"string\" ||\n !isObservationSequence(envelope.latestObservationSequence)\n ) {\n return Object.freeze({ kind: \"invalid\" });\n }\n if (\n envelope.envelopeVersion !== SCHEDULER_HISTORY_ENVELOPE_VERSION ||\n envelope.modelVersion !== SCHEDULER_HISTORY_MODEL_VERSION\n ) {\n return Object.freeze({ kind: \"incompatible\" });\n }\n\n const series = parseSeries(envelope.series);\n if (series === undefined) return Object.freeze({ kind: \"invalid\" });\n const greatestSequence = series.reduce(\n (greatest, entry) => Math.max(greatest, entry.latestObservationSequence),\n 0\n );\n if (envelope.latestObservationSequence !== greatestSequence) {\n return Object.freeze({ kind: \"invalid\" });\n }\n\n return Object.freeze({\n kind: \"loaded\",\n history: freezeSchedulerHistoryModel({\n latestObservationSequence: envelope.latestObservationSequence,\n series\n })\n });\n}\n\nfunction parseSeries(value: unknown): readonly SchedulerHistorySeries[] | undefined {\n const entries = snapshotClosedArray(value);\n if (entries === undefined || entries.length > MAX_SCHEDULER_HISTORY_SERIES) return undefined;\n\n const identities = new Set<string>();\n const parsed: SchedulerHistorySeries[] = [];\n for (const entry of entries) {\n const series = parseSeriesEntry(entry);\n if (series === undefined || identities.has(series.identityDigest)) return undefined;\n identities.add(series.identityDigest);\n parsed.push(series);\n }\n return Object.freeze(parsed);\n}\n\nfunction parseSeriesEntry(value: unknown): SchedulerHistorySeries | undefined {\n const record = snapshotClosedRecord(value);\n if (record === undefined || !hasExactPlainRecordKeys(record, SERIES_KEYS)) return undefined;\n if (\n !isSchedulerHistoryIdentityDigest(record.identityDigest) ||\n !isObservationSequence(record.latestObservationSequence)\n ) {\n return undefined;\n }\n const samples = parseSamples(record.samples);\n if (\n samples === undefined ||\n samples.at(-1)?.observationSequence !== record.latestObservationSequence\n ) {\n return undefined;\n }\n return Object.freeze({\n identityDigest: record.identityDigest,\n latestObservationSequence: record.latestObservationSequence,\n samples\n });\n}\n\nfunction parseSamples(value: unknown): readonly SchedulerHistorySample[] | undefined {\n const entries = snapshotClosedArray(value);\n if (\n entries === undefined ||\n entries.length === 0 ||\n entries.length > MAX_SCHEDULER_HISTORY_SAMPLES_PER_SERIES\n ) {\n return undefined;\n }\n\n const samples: SchedulerHistorySample[] = [];\n let priorSequence = -1;\n for (const entry of entries) {\n const sample = parseSample(entry);\n if (sample === undefined || sample.observationSequence <= priorSequence) return undefined;\n priorSequence = sample.observationSequence;\n samples.push(sample);\n }\n return Object.freeze(samples);\n}\n\nfunction parseSample(value: unknown): SchedulerHistorySample | undefined {\n const record = snapshotClosedRecord(value);\n if (record === undefined || !hasExactPlainRecordKeys(record, SAMPLE_KEYS)) return undefined;\n if (\n !isBoundedDurationMs(record.durationMs) ||\n !isPositiveObservationSequence(record.observationSequence) ||\n !isSchedulerSettlementKind(record.settlementKind)\n ) {\n return undefined;\n }\n return Object.freeze({\n durationMs: record.durationMs,\n observationSequence: record.observationSequence,\n settlementKind: record.settlementKind\n });\n}\n\nfunction isMissingPath(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as { readonly code?: unknown }).code === \"ENOENT\"\n );\n}\n\nfunction isPositiveObservationSequence(value: unknown): value is number {\n return isObservationSequence(value) && value > 0;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"selection-layers.mjs","sourceRoot":"","sources":["../../../src/learned-critical-path/selection-layers.ts"],"names":[],"mappings":"AAgBA,0GAA0G;AAC1G,MAAM,UAAU,sBAAsB,CAAC,OAA+B;IACpE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAU,CAAC,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IAC3F,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC,MAAM,CACzB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CACtC,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC7F,CACF;QACD,SAAS;QACT,QAAQ;QACR,UAAU,EAAE,MAAM,CAAC,MAAM,CACvB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CACtC,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC3F,CACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CACnB,SAAoB,EACpB,QAAmC,EACnC,SAAqC,EACrC,cAAmC,EACnC,WAAmB;IAEnB,MAAM,KAAK,GAAG,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChE,OAAO,CACL,KAAK,KAAK,SAAS;QACnB,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;QAClD,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,WAAW,GAAG,WAAW,CAChC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,SAAoB,EACpB,QAAmC,EACnC,SAAqC,EACrC,cAAmC,EACnC,WAAmB;IAEnB,MAAM,KAAK,GAAG,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChE,OAAO,KAAK,KAAK,SAAS,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,SAAoB,EACpB,QAAmC,EACnC,SAAqC;IAErC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAChG,CAAC","sourcesContent":["import type {\n AdmissionPolicyContext,\n SchedulerGraphSnapshot\n} from \"../project-definition/project-definition.ts\";\n\ntype Candidate = AdmissionPolicyContext[\"candidates\"][number];\ntype Task = SchedulerGraphSnapshot[\"tasks\"][number];\ntype Scope = SchedulerGraphSnapshot[\"scopes\"][number];\n\nexport interface LearnedSelectionLayers {\n readonly continuation: readonly Candidate[];\n readonly scopeById: ReadonlyMap<string, Scope>;\n readonly taskById: ReadonlyMap<string, Task>;\n readonly tightening: readonly Candidate[];\n}\n\n/** Projects the public graph and boundary facts into the Scheduler's two constrained selection layers. */\nexport function learnedSelectionLayers(context: AdmissionPolicyContext): LearnedSelectionLayers {\n const taskById = new Map(context.graph.tasks.map((task) => [task.taskId, task] as const));\n const scopeById = new Map(context.graph.scopes.map((scope) => [scope.id, scope] as const));\n const activeScopeIds = new Set(context.activeScopeIds);\n return Object.freeze({\n continuation: Object.freeze(\n context.candidates.filter((candidate) =>\n isContinuation(candidate, taskById, scopeById, activeScopeIds, context.capacity.maxParallel)\n )\n ),\n scopeById,\n taskById,\n tightening: Object.freeze(\n context.candidates.filter((candidate) =>\n isTightening(candidate, taskById, scopeById, activeScopeIds, context.capacity.maxParallel)\n )\n )\n });\n}\n\nfunction isTightening(\n candidate: Candidate,\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>,\n activeScopeIds: ReadonlySet<string>,\n maxParallel: number\n): boolean {\n const scope = scopeForCandidate(candidate, taskById, scopeById);\n return (\n scope !== undefined &&\n scope.activationTaskIds.includes(candidate.taskId) &&\n !activeScopeIds.has(scope.id) &&\n scope.maxParallel < maxParallel\n );\n}\n\nfunction isContinuation(\n candidate: Candidate,\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>,\n activeScopeIds: ReadonlySet<string>,\n maxParallel: number\n): boolean {\n const scope = scopeForCandidate(candidate, taskById, scopeById);\n return scope !== undefined && activeScopeIds.has(scope.id) && scope.maxParallel < maxParallel;\n}\n\nexport function scopeForCandidate(\n candidate: Candidate,\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>\n): Scope | undefined {\n const task = taskById.get(candidate.taskId);\n return task?.scopeId === null || task === undefined ? undefined : scopeById.get(task.scopeId);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"static-decision.mjs","sourceRoot":"","sources":["../../../src/learned-critical-path/static-decision.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AdmissionPolicyContext,\n AdmissionProposal,\n SchedulerGraphSnapshot\n} from \"../project-definition/project-definition.ts\";\nimport { learnedSelectionLayers, scopeForCandidate } from \"./selection-layers.ts\";\n\ntype Candidate = AdmissionPolicyContext[\"candidates\"][number];\ntype Task = SchedulerGraphSnapshot[\"tasks\"][number];\ntype Scope = SchedulerGraphSnapshot[\"scopes\"][number];\n\n/** Preserves ordinary static selection when learned preparation cannot form a ranking. */\nexport function staticDecision(context: AdmissionPolicyContext): AdmissionProposal {\n const layers = learnedSelectionLayers(context);\n const selected = selectStaticCandidate(\n context.candidates,\n layers.continuation,\n layers.scopeById,\n layers.taskById,\n layers.tightening\n );\n return selected === undefined || !selected.canAdmit\n ? Object.freeze({ kind: \"wait\" })\n : Object.freeze({ kind: \"select\", taskId: selected.taskId });\n}\n\nfunction selectStaticCandidate(\n candidates: readonly Candidate[],\n continuation: readonly Candidate[],\n scopeById: ReadonlyMap<string, Scope>,\n taskById: ReadonlyMap<string, Task>,\n tightening: readonly Candidate[]\n): Candidate | undefined {\n if (tightening.length > 0) return first(sortConstrained(tightening, taskById, scopeById));\n if (continuation.length > 0) return first(sortConstrained(continuation, taskById, scopeById));\n return selectOrdinary(candidates, taskById);\n}\n\nfunction selectOrdinary(\n candidates: readonly Candidate[],\n taskById: ReadonlyMap<string, Task>\n): Candidate | undefined {\n const admissible = candidates.filter((candidate) => candidate.canAdmit);\n return [...(admissible.length === 0 ? candidates : admissible)].sort(\n (left, right) =>\n priorityDifference(left, right, taskById) || compareText(left.taskId, right.taskId)\n )[0];\n}\n\nfunction sortConstrained(\n candidates: readonly Candidate[],\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>\n): Candidate[] {\n return [...candidates].sort((left, right) =>\n constrainedComparison(left, right, taskById, scopeById)\n );\n}\n\nfunction constrainedComparison(\n left: Candidate,\n right: Candidate,\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>\n): number {\n const leftScope = requiredScope(left, taskById, scopeById);\n const rightScope = requiredScope(right, taskById, scopeById);\n return (\n leftScope.maxParallel - rightScope.maxParallel ||\n priorityDifference(left, right, taskById) ||\n compareText(leftScope.id, rightScope.id) ||\n compareText(left.taskId, right.taskId)\n );\n}\n\nfunction requiredScope(\n candidate: Candidate,\n taskById: ReadonlyMap<string, Task>,\n scopeById: ReadonlyMap<string, Scope>\n): Scope {\n const scope = scopeForCandidate(candidate, taskById, scopeById);\n if (scope === undefined) throw new Error(\"constrained task is missing a scope\");\n return scope;\n}\n\nfunction priorityDifference(\n left: Candidate,\n right: Candidate,\n taskById: ReadonlyMap<string, Task>\n): number {\n return (\n (taskById.get(right.taskId)?.admissionPriority ?? 0) -\n (taskById.get(left.taskId)?.admissionPriority ?? 0)\n );\n}\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\nfunction first<T>(values: readonly T[]): T {\n const value = values[0];\n if (value === undefined) throw new Error(\"static strategy requires a candidate\");\n return value;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"strategy.mjs","sourceRoot":"","sources":["../../../src/learned-critical-path/strategy.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from \"node:path\";\n\nimport { canonicalizeJsonValue, type CanonicalJsonValue } from \"../data-boundary/canonical-data.ts\";\nimport type {\n AdmissionPolicyContext,\n AdmissionProposal,\n CustomAdmissionStrategy,\n SchedulerGraphSnapshot,\n SchedulerMeasurementContext\n} from \"../project-definition/project-definition.ts\";\nimport { prepareSchedulerDurationModel } from \"./duration-model/preparation.ts\";\nimport { learnedSelectionLayers } from \"./selection-layers.ts\";\nimport { staticDecision } from \"./static-decision.ts\";\nimport {\n predictionForTask,\n type SchedulerPredictionInput,\n type SchedulerPredictionSnapshot\n} from \"./duration-model/prediction.ts\";\nimport {\n createSchedulerCriticalPathSnapshot,\n criticalPathScoreForTask,\n type SchedulerCriticalPathSnapshot\n} from \"../project-run/task-scheduler/critical-path-ranking.ts\";\n\n/** 公开 learned critical-path prepared strategy 的调用方配置。 */\nexport interface LearnedCriticalPathStrategyOptions {\n /** 调用方拥有的可丢弃 learned duration history 本地目录;必须是绝对路径。 */\n readonly stateDirectory: string;\n /** 为每个公开 Task 提供 canonical-JSON-compatible 的调用方 identity projection。 */\n readonly identityForTask: (task: SchedulerGraphSnapshot[\"tasks\"][number]) => unknown;\n /** 单个 identity 最多保留的样本数;默认 32。 */\n readonly sampleWindow?: number;\n /** 最多保留的 identity 数;默认 4096。 */\n readonly maxHistorySeries?: number;\n /** 正的 cold-start duration 权重(毫秒);默认 1。 */\n readonly coldStartDurationMs?: number;\n /** 可选调用方 observation sink;observer fault 不改变 scheduling 或 Run facts。 */\n readonly observe?: (event: LearnedCriticalPathObservation) => void | Promise<void>;\n}\n\n/** 调用方可选 observer 收到的有界 learned strategy 事件;selection-proposed 不表示 Scheduler 已接受 admission。 */\nexport type LearnedCriticalPathObservation =\n | Readonly<{\n readonly kind: \"history-unavailable\";\n readonly reason: \"identity-invalid\" | \"setup-failed\";\n }>\n | Readonly<{\n readonly kind: \"selection-proposed\";\n readonly taskId: string;\n readonly estimatedDurationMs: number;\n readonly criticalPathScore: number;\n readonly sampleCount: number;\n readonly source: \"learned\" | \"project-prior\" | \"cold-start\";\n }>\n | Readonly<{ readonly kind: \"recording-unavailable\" }>;\n\n/**\n * 构造普通公开 prepared strategy。调用方拥有 history location 与 identity projection;\n * Product 只按同一 custom strategy lifecycle 调用它,不为该 helper 增加特权。\n */\nexport function createLearnedCriticalPathStrategy(\n options: LearnedCriticalPathStrategyOptions\n): CustomAdmissionStrategy {\n if (typeof options.stateDirectory !== \"string\" || !isAbsolute(options.stateDirectory)) {\n throw new TypeError(\"learned critical-path stateDirectory must be an absolute path\");\n }\n const model = modelOptions(options);\n return Object.freeze({\n kind: \"prepared\" as const,\n prepare: async ({ graph }) => {\n const predictionInputs = predictionInputsFor(graph, options.identityForTask, model);\n if (predictionInputs === undefined) {\n observe(options, { kind: \"history-unavailable\", reason: \"identity-invalid\" });\n return Object.freeze({ decide: staticDecision });\n }\n const durationModel = await prepareSchedulerDurationModel({\n predictionInputs,\n stateDirectory: options.stateDirectory,\n coldStartDurationMs: model.coldStartDurationMs,\n maxSamplesPerSeries: model.sampleWindow,\n maxSeries: model.maxHistorySeries\n });\n if (durationModel.kind === \"static-fallback\") {\n observe(options, { kind: \"history-unavailable\", reason: \"setup-failed\" });\n return Object.freeze({ decide: staticDecision });\n }\n let criticalPath: SchedulerCriticalPathSnapshot;\n try {\n criticalPath = createSchedulerCriticalPathSnapshot(graph, durationModel.prediction);\n } catch {\n observe(options, { kind: \"history-unavailable\", reason: \"setup-failed\" });\n return Object.freeze({ decide: staticDecision });\n }\n return Object.freeze({\n decide: (context: AdmissionPolicyContext) =>\n learnedDecision(context, durationModel.prediction, criticalPath, options),\n complete: async (context: SchedulerMeasurementContext) => {\n const recorded = await durationModel.record(context);\n if (recorded.kind === \"failed\" || recorded.writeObservation === \"failed\") {\n observe(options, { kind: \"recording-unavailable\" });\n }\n }\n });\n }\n });\n}\n\nfunction modelOptions(options: LearnedCriticalPathStrategyOptions): Readonly<{\n readonly coldStartDurationMs: number;\n readonly maxHistorySeries: number;\n readonly sampleWindow: number;\n}> {\n const coldStartDurationMs = options.coldStartDurationMs ?? 1;\n const maxHistorySeries = options.maxHistorySeries ?? 4_096;\n const sampleWindow = options.sampleWindow ?? 32;\n validatePositiveFinite(coldStartDurationMs, \"coldStartDurationMs\");\n validateBoundedInteger(maxHistorySeries, \"maxHistorySeries\", 4_096);\n validateBoundedInteger(sampleWindow, \"sampleWindow\", 32);\n return Object.freeze({ coldStartDurationMs, maxHistorySeries, sampleWindow });\n}\n\nfunction validatePositiveFinite(value: number, name: string): void {\n if (!Number.isFinite(value) || value <= 0)\n throw new TypeError(`learned critical-path ${name} must be positive and finite`);\n}\n\nfunction validateBoundedInteger(value: number, name: string, maximum: number): void {\n if (!Number.isSafeInteger(value) || value <= 0 || value > maximum)\n throw new TypeError(`learned critical-path ${name} must be a positive safe integer`);\n}\n\nfunction predictionInputsFor(\n graph: SchedulerGraphSnapshot,\n identityForTask: LearnedCriticalPathStrategyOptions[\"identityForTask\"],\n model: Readonly<{\n readonly coldStartDurationMs: number;\n readonly maxHistorySeries: number;\n readonly sampleWindow: number;\n }>\n): readonly SchedulerPredictionInput[] | undefined {\n const inputs: SchedulerPredictionInput[] = [];\n for (const task of graph.tasks) {\n let identity: CanonicalJsonValue | undefined;\n try {\n identity = canonicalizeJsonValue({ historyKey: identityForTask(task), model });\n } catch {\n return undefined;\n }\n if (identity === undefined) return undefined;\n inputs.push(\n Object.freeze({\n authoredOptions: identity,\n checkId: task.taskId,\n flags: null,\n taskId: task.taskId\n })\n );\n }\n return Object.freeze(inputs);\n}\n\nfunction learnedDecision(\n context: AdmissionPolicyContext,\n prediction: SchedulerPredictionSnapshot,\n criticalPath: SchedulerCriticalPathSnapshot,\n options: LearnedCriticalPathStrategyOptions\n): AdmissionProposal {\n const selected = selectLearnedCandidate(context, criticalPath);\n if (!selected.canAdmit) return Object.freeze({ kind: \"wait\" });\n const taskPrediction = predictionForTask(prediction, selected.taskId);\n const score = criticalPathScoreForTask(criticalPath, selected.taskId);\n if (taskPrediction !== undefined && score !== undefined) {\n observe(\n options,\n Object.freeze({\n kind: \"selection-proposed\",\n taskId: selected.taskId,\n criticalPathScore: score,\n estimatedDurationMs: taskPrediction.estimatedDurationMs,\n sampleCount: taskPrediction.sampleCount,\n source: taskPrediction.source\n })\n );\n }\n return Object.freeze({ kind: \"select\", taskId: selected.taskId });\n}\n\nfunction selectLearnedCandidate(\n context: AdmissionPolicyContext,\n criticalPath: SchedulerCriticalPathSnapshot\n): AdmissionPolicyContext[\"candidates\"][number] {\n const layers = learnedSelectionLayers(context);\n if (layers.tightening.length > 0)\n return requiredFirst(\n sortConstrained(layers.tightening, layers.taskById, layers.scopeById, criticalPath)\n );\n if (layers.continuation.length > 0)\n return requiredFirst(\n sortConstrained(layers.continuation, layers.taskById, layers.scopeById, criticalPath)\n );\n return requiredFirst(\n [...context.candidates].sort(learnedCandidateComparator(layers.taskById, criticalPath))\n );\n}\n\nfunction learnedCandidateComparator(\n taskById: ReadonlyMap<string, SchedulerGraphSnapshot[\"tasks\"][number]>,\n criticalPath: SchedulerCriticalPathSnapshot\n): (\n left: AdmissionPolicyContext[\"candidates\"][number],\n right: AdmissionPolicyContext[\"candidates\"][number]\n) => number {\n return (left, right) => compareLearnedTasks(taskById, criticalPath, left.taskId, right.taskId);\n}\n\nfunction sortConstrained(\n candidates: readonly AdmissionPolicyContext[\"candidates\"][number][],\n taskById: ReadonlyMap<string, SchedulerGraphSnapshot[\"tasks\"][number]>,\n scopeById: ReadonlyMap<string, SchedulerGraphSnapshot[\"scopes\"][number]>,\n criticalPath: SchedulerCriticalPathSnapshot\n): AdmissionPolicyContext[\"candidates\"][number][] {\n return [...candidates].sort(learnedConstrainedComparator(taskById, scopeById, criticalPath));\n}\n\nfunction learnedConstrainedComparator(\n taskById: ReadonlyMap<string, SchedulerGraphSnapshot[\"tasks\"][number]>,\n scopeById: ReadonlyMap<string, SchedulerGraphSnapshot[\"scopes\"][number]>,\n criticalPath: SchedulerCriticalPathSnapshot\n): (\n left: AdmissionPolicyContext[\"candidates\"][number],\n right: AdmissionPolicyContext[\"candidates\"][number]\n) => number {\n return (left, right) => {\n const leftScope = requiredLearnedScope(left, taskById, scopeById);\n const rightScope = requiredLearnedScope(right, taskById, scopeById);\n return (\n leftScope.maxParallel - rightScope.maxParallel ||\n compareLearnedTasks(taskById, criticalPath, left.taskId, right.taskId) ||\n compareText(leftScope.id, rightScope.id) ||\n compareText(left.taskId, right.taskId)\n );\n };\n}\n\nfunction requiredLearnedScope(\n candidate: AdmissionPolicyContext[\"candidates\"][number],\n taskById: ReadonlyMap<string, SchedulerGraphSnapshot[\"tasks\"][number]>,\n scopeById: ReadonlyMap<string, SchedulerGraphSnapshot[\"scopes\"][number]>\n): SchedulerGraphSnapshot[\"scopes\"][number] {\n const task = taskById.get(candidate.taskId);\n const scope =\n task?.scopeId === null || task === undefined ? undefined : scopeById.get(task.scopeId);\n if (scope === undefined) throw new Error(\"constrained task is missing a scope\");\n return scope;\n}\nfunction compareLearnedTasks(\n taskById: ReadonlyMap<string, SchedulerGraphSnapshot[\"tasks\"][number]>,\n criticalPath: SchedulerCriticalPathSnapshot,\n leftId: string,\n rightId: string\n): number {\n const left = taskById.get(leftId);\n const right = taskById.get(rightId);\n if (left === undefined || right === undefined)\n throw new Error(\"learned candidate is missing from graph\");\n const leftScore = criticalPathScoreForTask(criticalPath, leftId);\n const rightScore = criticalPathScoreForTask(criticalPath, rightId);\n if (leftScore === undefined || rightScore === undefined)\n throw new Error(\"learned scheduler score is missing\");\n return (\n rightScore - leftScore ||\n right.admissionPriority - left.admissionPriority ||\n compareText(leftId, rightId)\n );\n}\n\nfunction observe(\n options: LearnedCriticalPathStrategyOptions,\n event: LearnedCriticalPathObservation\n): void {\n try {\n const observed = options.observe?.(event);\n if (observed !== undefined) void Promise.resolve(observed).catch(() => undefined);\n } catch {\n // Caller observation is contained.\n }\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\nfunction requiredFirst<T>(values: readonly T[]): T {\n const first = values[0];\n if (first === undefined) throw new Error(\"learned strategy requires a candidate\");\n return first;\n}\n"]}