clinkx 0.2.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (574) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +10 -0
  3. package/README.md +113 -18
  4. package/clinkx-workflows/dist/allowed-roots.d.ts +1 -0
  5. package/clinkx-workflows/dist/allowed-roots.js +5 -0
  6. package/clinkx-workflows/dist/allowed-roots.js.map +1 -0
  7. package/clinkx-workflows/dist/artifacts.d.ts +20 -1
  8. package/clinkx-workflows/dist/artifacts.js +38 -9
  9. package/clinkx-workflows/dist/artifacts.js.map +1 -1
  10. package/clinkx-workflows/dist/backend.d.ts +4 -0
  11. package/clinkx-workflows/dist/citation-check.d.ts +40 -0
  12. package/clinkx-workflows/dist/citation-check.js +348 -0
  13. package/clinkx-workflows/dist/citation-check.js.map +1 -0
  14. package/clinkx-workflows/dist/clink-client.d.ts +2 -1
  15. package/clinkx-workflows/dist/clink-client.js +17 -4
  16. package/clinkx-workflows/dist/clink-client.js.map +1 -1
  17. package/clinkx-workflows/dist/config.d.ts +145 -16
  18. package/clinkx-workflows/dist/config.js +384 -26
  19. package/clinkx-workflows/dist/config.js.map +1 -1
  20. package/clinkx-workflows/dist/contained-file.d.ts +172 -0
  21. package/clinkx-workflows/dist/contained-file.js +483 -0
  22. package/clinkx-workflows/dist/contained-file.js.map +1 -0
  23. package/clinkx-workflows/dist/context-builder-lifecycle-contract.d.ts +416 -0
  24. package/clinkx-workflows/dist/context-builder-lifecycle-contract.js +328 -0
  25. package/clinkx-workflows/dist/context-builder-lifecycle-contract.js.map +1 -0
  26. package/clinkx-workflows/dist/context-builder-lifecycle-router.d.ts +24 -0
  27. package/clinkx-workflows/dist/context-builder-lifecycle-router.js +39 -0
  28. package/clinkx-workflows/dist/context-builder-lifecycle-router.js.map +1 -0
  29. package/clinkx-workflows/dist/context-cache-key.d.ts +53 -0
  30. package/clinkx-workflows/dist/context-cache-key.js +91 -0
  31. package/clinkx-workflows/dist/context-cache-key.js.map +1 -0
  32. package/clinkx-workflows/dist/context-mode-resolver.d.ts +27 -0
  33. package/clinkx-workflows/dist/context-mode-resolver.js +126 -0
  34. package/clinkx-workflows/dist/context-mode-resolver.js.map +1 -0
  35. package/clinkx-workflows/dist/context-preflight.d.ts +184 -0
  36. package/clinkx-workflows/dist/context-preflight.js +91 -0
  37. package/clinkx-workflows/dist/context-preflight.js.map +1 -0
  38. package/clinkx-workflows/dist/council-expander.d.ts +1 -1
  39. package/clinkx-workflows/dist/council-expander.js +2 -1
  40. package/clinkx-workflows/dist/council-expander.js.map +1 -1
  41. package/clinkx-workflows/dist/dashboard/activity-contract.d.ts +165 -0
  42. package/clinkx-workflows/dist/dashboard/activity-contract.js +105 -0
  43. package/clinkx-workflows/dist/dashboard/activity-contract.js.map +1 -0
  44. package/clinkx-workflows/dist/dashboard/activity-lease.d.ts +25 -0
  45. package/clinkx-workflows/dist/dashboard/activity-lease.js +34 -0
  46. package/clinkx-workflows/dist/dashboard/activity-lease.js.map +1 -0
  47. package/clinkx-workflows/dist/dashboard/activity-reader.d.ts +86 -0
  48. package/clinkx-workflows/dist/dashboard/activity-reader.js +480 -0
  49. package/clinkx-workflows/dist/dashboard/activity-reader.js.map +1 -0
  50. package/clinkx-workflows/dist/dashboard/api-routes.d.ts +36 -0
  51. package/clinkx-workflows/dist/dashboard/api-routes.js +1047 -0
  52. package/clinkx-workflows/dist/dashboard/api-routes.js.map +1 -0
  53. package/clinkx-workflows/dist/dashboard/artifact-index.d.ts +37 -0
  54. package/clinkx-workflows/dist/dashboard/artifact-index.js +145 -0
  55. package/clinkx-workflows/dist/dashboard/artifact-index.js.map +1 -0
  56. package/clinkx-workflows/dist/dashboard/auth/challenge-store.d.ts +31 -0
  57. package/clinkx-workflows/dist/dashboard/auth/challenge-store.js +65 -0
  58. package/clinkx-workflows/dist/dashboard/auth/challenge-store.js.map +1 -0
  59. package/clinkx-workflows/dist/dashboard/auth/controller.d.ts +26 -0
  60. package/clinkx-workflows/dist/dashboard/auth/controller.js +596 -0
  61. package/clinkx-workflows/dist/dashboard/auth/controller.js.map +1 -0
  62. package/clinkx-workflows/dist/dashboard/auth/credential-store.d.ts +60 -0
  63. package/clinkx-workflows/dist/dashboard/auth/credential-store.js +776 -0
  64. package/clinkx-workflows/dist/dashboard/auth/credential-store.js.map +1 -0
  65. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.d.ts +9 -0
  66. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js +44 -0
  67. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js.map +1 -0
  68. package/clinkx-workflows/dist/dashboard/auth/session-store.d.ts +17 -0
  69. package/clinkx-workflows/dist/dashboard/auth/session-store.js +77 -0
  70. package/clinkx-workflows/dist/dashboard/auth/session-store.js.map +1 -0
  71. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.d.ts +25 -0
  72. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js +71 -0
  73. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js.map +1 -0
  74. package/clinkx-workflows/dist/dashboard/context-run-liveness.d.ts +37 -0
  75. package/clinkx-workflows/dist/dashboard/context-run-liveness.js +49 -0
  76. package/clinkx-workflows/dist/dashboard/context-run-liveness.js.map +1 -0
  77. package/clinkx-workflows/dist/dashboard/context-run-reader.d.ts +222 -0
  78. package/clinkx-workflows/dist/dashboard/context-run-reader.js +1178 -0
  79. package/clinkx-workflows/dist/dashboard/context-run-reader.js.map +1 -0
  80. package/clinkx-workflows/dist/dashboard/contracts.d.ts +8936 -0
  81. package/clinkx-workflows/dist/dashboard/contracts.js +1157 -0
  82. package/clinkx-workflows/dist/dashboard/contracts.js.map +1 -0
  83. package/clinkx-workflows/dist/dashboard/generation.d.ts +14 -0
  84. package/clinkx-workflows/dist/dashboard/generation.js +41 -0
  85. package/clinkx-workflows/dist/dashboard/generation.js.map +1 -0
  86. package/clinkx-workflows/dist/dashboard/index.d.ts +28 -0
  87. package/clinkx-workflows/dist/dashboard/index.js +16 -0
  88. package/clinkx-workflows/dist/dashboard/index.js.map +1 -0
  89. package/clinkx-workflows/dist/dashboard/lazy-content.d.ts +101 -0
  90. package/clinkx-workflows/dist/dashboard/lazy-content.js +748 -0
  91. package/clinkx-workflows/dist/dashboard/lazy-content.js.map +1 -0
  92. package/clinkx-workflows/dist/dashboard/progress-report-contract.d.ts +303 -0
  93. package/clinkx-workflows/dist/dashboard/progress-report-contract.js +221 -0
  94. package/clinkx-workflows/dist/dashboard/progress-report-contract.js.map +1 -0
  95. package/clinkx-workflows/dist/dashboard/progress-report-reader.d.ts +50 -0
  96. package/clinkx-workflows/dist/dashboard/progress-report-reader.js +581 -0
  97. package/clinkx-workflows/dist/dashboard/progress-report-reader.js.map +1 -0
  98. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.d.ts +89 -0
  99. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js +71 -0
  100. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js.map +1 -0
  101. package/clinkx-workflows/dist/dashboard/progress-report-status-store.d.ts +28 -0
  102. package/clinkx-workflows/dist/dashboard/progress-report-status-store.js +110 -0
  103. package/clinkx-workflows/dist/dashboard/progress-report-status-store.js.map +1 -0
  104. package/clinkx-workflows/dist/dashboard/read-model.d.ts +86 -0
  105. package/clinkx-workflows/dist/dashboard/read-model.js +440 -0
  106. package/clinkx-workflows/dist/dashboard/read-model.js.map +1 -0
  107. package/clinkx-workflows/dist/dashboard/request-admission.d.ts +31 -0
  108. package/clinkx-workflows/dist/dashboard/request-admission.js +126 -0
  109. package/clinkx-workflows/dist/dashboard/request-admission.js.map +1 -0
  110. package/clinkx-workflows/dist/dashboard/scanner.d.ts +75 -0
  111. package/clinkx-workflows/dist/dashboard/scanner.js +1110 -0
  112. package/clinkx-workflows/dist/dashboard/scanner.js.map +1 -0
  113. package/clinkx-workflows/dist/dashboard/server-factory.d.ts +50 -0
  114. package/clinkx-workflows/dist/dashboard/server-factory.js +431 -0
  115. package/clinkx-workflows/dist/dashboard/server-factory.js.map +1 -0
  116. package/clinkx-workflows/dist/dashboard/session-log-contract.d.ts +2611 -0
  117. package/clinkx-workflows/dist/dashboard/session-log-contract.js +480 -0
  118. package/clinkx-workflows/dist/dashboard/session-log-contract.js.map +1 -0
  119. package/clinkx-workflows/dist/dashboard/session-log-identity.d.ts +21 -0
  120. package/clinkx-workflows/dist/dashboard/session-log-identity.js +101 -0
  121. package/clinkx-workflows/dist/dashboard/session-log-identity.js.map +1 -0
  122. package/clinkx-workflows/dist/dashboard/session-log-journal.d.ts +43 -0
  123. package/clinkx-workflows/dist/dashboard/session-log-journal.js +522 -0
  124. package/clinkx-workflows/dist/dashboard/session-log-journal.js.map +1 -0
  125. package/clinkx-workflows/dist/dashboard/session-log-reader.d.ts +61 -0
  126. package/clinkx-workflows/dist/dashboard/session-log-reader.js +378 -0
  127. package/clinkx-workflows/dist/dashboard/session-log-reader.js.map +1 -0
  128. package/clinkx-workflows/dist/dashboard/session-log-redaction.d.ts +6 -0
  129. package/clinkx-workflows/dist/dashboard/session-log-redaction.js +367 -0
  130. package/clinkx-workflows/dist/dashboard/session-log-redaction.js.map +1 -0
  131. package/clinkx-workflows/dist/dashboard/session-log-retention.d.ts +23 -0
  132. package/clinkx-workflows/dist/dashboard/session-log-retention.js +212 -0
  133. package/clinkx-workflows/dist/dashboard/session-log-retention.js.map +1 -0
  134. package/clinkx-workflows/dist/dashboard/static-responses.d.ts +10 -0
  135. package/clinkx-workflows/dist/dashboard/static-responses.js +94 -0
  136. package/clinkx-workflows/dist/dashboard/static-responses.js.map +1 -0
  137. package/clinkx-workflows/dist/dashboard/worker-lock-observer.d.ts +28 -0
  138. package/clinkx-workflows/dist/dashboard/worker-lock-observer.js +241 -0
  139. package/clinkx-workflows/dist/dashboard/worker-lock-observer.js.map +1 -0
  140. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  141. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  142. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  143. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  144. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  145. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  146. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  147. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  148. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  149. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  150. package/clinkx-workflows/dist/dashboard-ui/assets/index-DOkMXTfB.js +25 -0
  151. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  152. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  153. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  154. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  155. package/clinkx-workflows/dist/dashboard-ui/assets/style-ChJsn0KD.css +1 -0
  156. package/clinkx-workflows/dist/dashboard-ui/contracts/council-plan-review-input-v1.json +158 -0
  157. package/clinkx-workflows/dist/dashboard-ui/index.html +15 -0
  158. package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Mono-OFL.txt +93 -0
  159. package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Sans-OFL.txt +93 -0
  160. package/clinkx-workflows/dist/dashboard-ui/licenses/JetBrains-Mono-OFL.txt +93 -0
  161. package/clinkx-workflows/dist/dashboard-ui/licenses/NOTICE.md +32 -0
  162. package/clinkx-workflows/dist/dashboard-ui/theme-init.js +8 -0
  163. package/clinkx-workflows/dist/definition-normalizer.d.ts +19 -0
  164. package/clinkx-workflows/dist/definition-normalizer.js.map +1 -1
  165. package/clinkx-workflows/dist/delegate-validate.d.ts +78 -0
  166. package/clinkx-workflows/dist/delegate-validate.js +97 -0
  167. package/clinkx-workflows/dist/delegate-validate.js.map +1 -0
  168. package/clinkx-workflows/dist/engine.d.ts +141 -0
  169. package/clinkx-workflows/dist/engine.js +882 -28
  170. package/clinkx-workflows/dist/engine.js.map +1 -1
  171. package/clinkx-workflows/dist/errors.d.ts +2 -0
  172. package/clinkx-workflows/dist/errors.js.map +1 -1
  173. package/clinkx-workflows/dist/fingerprint.d.ts +1 -1
  174. package/clinkx-workflows/dist/fingerprint.js +1 -1
  175. package/clinkx-workflows/dist/index.d.ts +19 -0
  176. package/clinkx-workflows/dist/index.js +15 -0
  177. package/clinkx-workflows/dist/index.js.map +1 -1
  178. package/clinkx-workflows/dist/loader.d.ts +9 -3
  179. package/clinkx-workflows/dist/loader.js +92 -21
  180. package/clinkx-workflows/dist/loader.js.map +1 -1
  181. package/clinkx-workflows/dist/plan-review/admission.d.ts +160 -0
  182. package/clinkx-workflows/dist/plan-review/admission.js +290 -0
  183. package/clinkx-workflows/dist/plan-review/admission.js.map +1 -0
  184. package/clinkx-workflows/dist/plan-review/context-policy.d.ts +55 -0
  185. package/clinkx-workflows/dist/plan-review/context-policy.js +146 -0
  186. package/clinkx-workflows/dist/plan-review/context-policy.js.map +1 -0
  187. package/clinkx-workflows/dist/plan-review/contract.d.ts +763 -0
  188. package/clinkx-workflows/dist/plan-review/contract.js +289 -0
  189. package/clinkx-workflows/dist/plan-review/contract.js.map +1 -0
  190. package/clinkx-workflows/dist/plan-review/digest.d.ts +68 -0
  191. package/clinkx-workflows/dist/plan-review/digest.js +241 -0
  192. package/clinkx-workflows/dist/plan-review/digest.js.map +1 -0
  193. package/clinkx-workflows/dist/plan-review/discovery.d.ts +45 -0
  194. package/clinkx-workflows/dist/plan-review/discovery.js +36 -0
  195. package/clinkx-workflows/dist/plan-review/discovery.js.map +1 -0
  196. package/clinkx-workflows/dist/plan-review/execution-contract.d.ts +298 -0
  197. package/clinkx-workflows/dist/plan-review/execution-contract.js +194 -0
  198. package/clinkx-workflows/dist/plan-review/execution-contract.js.map +1 -0
  199. package/clinkx-workflows/dist/plan-review/expander.d.ts +48 -0
  200. package/clinkx-workflows/dist/plan-review/expander.js +243 -0
  201. package/clinkx-workflows/dist/plan-review/expander.js.map +1 -0
  202. package/clinkx-workflows/dist/plan-review/projector.d.ts +126 -0
  203. package/clinkx-workflows/dist/plan-review/projector.js +437 -0
  204. package/clinkx-workflows/dist/plan-review/projector.js.map +1 -0
  205. package/clinkx-workflows/dist/plan-review/publication.d.ts +95 -0
  206. package/clinkx-workflows/dist/plan-review/publication.js +182 -0
  207. package/clinkx-workflows/dist/plan-review/publication.js.map +1 -0
  208. package/clinkx-workflows/dist/plan-review/ranking-reducer.d.ts +34 -0
  209. package/clinkx-workflows/dist/plan-review/ranking-reducer.js +139 -0
  210. package/clinkx-workflows/dist/plan-review/ranking-reducer.js.map +1 -0
  211. package/clinkx-workflows/dist/plan-review/resume.d.ts +38 -0
  212. package/clinkx-workflows/dist/plan-review/resume.js +122 -0
  213. package/clinkx-workflows/dist/plan-review/resume.js.map +1 -0
  214. package/clinkx-workflows/dist/plan-review/rubric.d.ts +7 -0
  215. package/clinkx-workflows/dist/plan-review/rubric.js +24 -0
  216. package/clinkx-workflows/dist/plan-review/rubric.js.map +1 -0
  217. package/clinkx-workflows/dist/plan-review/run-state.d.ts +398 -0
  218. package/clinkx-workflows/dist/plan-review/run-state.js +183 -0
  219. package/clinkx-workflows/dist/plan-review/run-state.js.map +1 -0
  220. package/clinkx-workflows/dist/plan-review/runtime-policy.d.ts +74 -0
  221. package/clinkx-workflows/dist/plan-review/runtime-policy.js +186 -0
  222. package/clinkx-workflows/dist/plan-review/runtime-policy.js.map +1 -0
  223. package/clinkx-workflows/dist/plan-review/snapshot.d.ts +81 -0
  224. package/clinkx-workflows/dist/plan-review/snapshot.js +170 -0
  225. package/clinkx-workflows/dist/plan-review/snapshot.js.map +1 -0
  226. package/clinkx-workflows/dist/plan-review/stage-error.d.ts +19 -0
  227. package/clinkx-workflows/dist/plan-review/stage-error.js +20 -0
  228. package/clinkx-workflows/dist/plan-review/stage-error.js.map +1 -0
  229. package/clinkx-workflows/dist/post-processors/index.d.ts +20 -0
  230. package/clinkx-workflows/dist/post-processors/index.js +21 -0
  231. package/clinkx-workflows/dist/post-processors/index.js.map +1 -0
  232. package/clinkx-workflows/dist/prompt-budget.d.ts +7 -0
  233. package/clinkx-workflows/dist/prompt-budget.js +7 -1
  234. package/clinkx-workflows/dist/prompt-budget.js.map +1 -1
  235. package/clinkx-workflows/dist/reducers/index.js +2 -0
  236. package/clinkx-workflows/dist/reducers/index.js.map +1 -1
  237. package/clinkx-workflows/dist/run-lock-heartbeat.d.ts +2 -0
  238. package/clinkx-workflows/dist/run-lock-heartbeat.js +3 -0
  239. package/clinkx-workflows/dist/run-lock-heartbeat.js.map +1 -0
  240. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.d.ts +34 -0
  241. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js +74 -0
  242. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js.map +1 -0
  243. package/clinkx-workflows/dist/run-summary/cards/index.js +5 -0
  244. package/clinkx-workflows/dist/run-summary/cards/index.js.map +1 -1
  245. package/clinkx-workflows/dist/run-summary.d.ts +13 -0
  246. package/clinkx-workflows/dist/run-summary.js +29 -1
  247. package/clinkx-workflows/dist/run-summary.js.map +1 -1
  248. package/clinkx-workflows/dist/schema.d.ts +76 -21
  249. package/clinkx-workflows/dist/schema.js +10 -1
  250. package/clinkx-workflows/dist/schema.js.map +1 -1
  251. package/clinkx-workflows/dist/seed-terms.d.ts +30 -0
  252. package/clinkx-workflows/dist/seed-terms.js +176 -0
  253. package/clinkx-workflows/dist/seed-terms.js.map +1 -0
  254. package/clinkx-workflows/dist/server.d.ts +5 -2
  255. package/clinkx-workflows/dist/server.js +82 -52
  256. package/clinkx-workflows/dist/server.js.map +1 -1
  257. package/clinkx-workflows/dist/shutdown.d.ts +18 -20
  258. package/clinkx-workflows/dist/shutdown.js +43 -61
  259. package/clinkx-workflows/dist/shutdown.js.map +1 -1
  260. package/clinkx-workflows/dist/state-schema.d.ts +38 -0
  261. package/clinkx-workflows/dist/state.d.ts +170 -3
  262. package/clinkx-workflows/dist/state.js +1275 -28
  263. package/clinkx-workflows/dist/state.js.map +1 -1
  264. package/clinkx-workflows/dist/transport.d.ts +15 -0
  265. package/clinkx-workflows/dist/transport.js +19 -10
  266. package/clinkx-workflows/dist/transport.js.map +1 -1
  267. package/clinkx-workflows/dist/types.d.ts +14 -2
  268. package/clinkx-workflows/dist/validators/council.d.ts +318 -85
  269. package/clinkx-workflows/dist/validators/council.js +52 -13
  270. package/clinkx-workflows/dist/validators/council.js.map +1 -1
  271. package/clinkx-workflows/dist/validators/index.d.ts +1 -0
  272. package/clinkx-workflows/dist/validators/index.js +3 -0
  273. package/clinkx-workflows/dist/validators/index.js.map +1 -1
  274. package/clinkx-workflows/dist/validators/plan-review.d.ts +398 -0
  275. package/clinkx-workflows/dist/validators/plan-review.js +316 -0
  276. package/clinkx-workflows/dist/validators/plan-review.js.map +1 -0
  277. package/clinkx-workflows/dist/workflow-receipt.js +188 -4
  278. package/clinkx-workflows/dist/workflow-receipt.js.map +1 -1
  279. package/clinkx-workflows/dist/workflow-tools.d.ts +48 -3
  280. package/clinkx-workflows/dist/workflow-tools.js +1402 -59
  281. package/clinkx-workflows/dist/workflow-tools.js.map +1 -1
  282. package/clinkx-workflows/dist/workspace-signature.d.ts +16 -0
  283. package/clinkx-workflows/dist/workspace-signature.js +388 -0
  284. package/clinkx-workflows/dist/workspace-signature.js.map +1 -0
  285. package/clinkx-workflows/templates/council/answer-specialist.txt +2 -1
  286. package/clinkx-workflows/templates/council/code-review-chairman.txt +13 -0
  287. package/clinkx-workflows/templates/council/code-review-cross-reviewer.txt +4 -1
  288. package/clinkx-workflows/templates/council/code-review-reviewer.txt +19 -3
  289. package/clinkx-workflows/templates/council/debug-debugger.txt +2 -1
  290. package/clinkx-workflows/templates/council/discover-analyst.txt +2 -1
  291. package/clinkx-workflows/templates/council/member.txt +2 -1
  292. package/clinkx-workflows/templates/council/plan-review-chairman.txt +68 -0
  293. package/clinkx-workflows/templates/council/plan-review-cross-reviewer.txt +51 -0
  294. package/clinkx-workflows/templates/council/plan-review-reviewer.txt +60 -0
  295. package/clinkx-workflows/templates/plan-review/chairman.txt +48 -0
  296. package/clinkx-workflows/templates/plan-review/cross-review.txt +52 -0
  297. package/clinkx-workflows/templates/plan-review/ranking.txt +16 -0
  298. package/clinkx-workflows/templates/plan-review/reviewer.txt +57 -0
  299. package/clinkx-workflows/workflows/council-answer.yaml +97 -8
  300. package/clinkx-workflows/workflows/council-code-review.yaml +103 -8
  301. package/clinkx-workflows/workflows/council-debug.yaml +97 -8
  302. package/clinkx-workflows/workflows/council-default.yaml +97 -8
  303. package/clinkx-workflows/workflows/council-discover.yaml +97 -8
  304. package/clinkx-workflows/workflows/council-plan-review.yaml +250 -0
  305. package/clinkx-workflows/workflows/plan-review-receipts.yaml +230 -0
  306. package/conf/adapters/agy.json +49 -0
  307. package/conf/adapters/claude.json +5 -0
  308. package/conf/adapters/codex-app-server.json +44 -0
  309. package/conf/adapters/codex.json +7 -2
  310. package/conf/adapters/glm.json +5 -0
  311. package/conf/adapters/grok.json +60 -0
  312. package/conf/adapters/hapi/agy.json +52 -0
  313. package/conf/adapters/hapi/claude.json +5 -0
  314. package/conf/adapters/hapi/codex.json +7 -2
  315. package/conf/adapters/hapi/glm.json +5 -0
  316. package/conf/prompts/json-codereviewer.txt +1 -0
  317. package/conf/prompts/json.txt +1 -0
  318. package/dist/activity-journal.d.ts +42 -0
  319. package/dist/activity-journal.js +381 -0
  320. package/dist/activity-journal.js.map +1 -0
  321. package/dist/allowed-roots.d.ts +53 -0
  322. package/dist/allowed-roots.js +216 -0
  323. package/dist/allowed-roots.js.map +1 -0
  324. package/dist/codex/activity-session-log.d.ts +14 -0
  325. package/dist/codex/activity-session-log.js +206 -0
  326. package/dist/codex/activity-session-log.js.map +1 -0
  327. package/dist/codex/agent-tools.d.ts +23 -0
  328. package/dist/codex/agent-tools.js +1270 -0
  329. package/dist/codex/agent-tools.js.map +1 -0
  330. package/dist/codex/app-server-client.d.ts +76 -0
  331. package/dist/codex/app-server-client.js +582 -0
  332. package/dist/codex/app-server-client.js.map +1 -0
  333. package/dist/codex/app-server-registry.d.ts +389 -0
  334. package/dist/codex/app-server-registry.js +1407 -0
  335. package/dist/codex/app-server-registry.js.map +1 -0
  336. package/dist/codex/client-types.d.ts +109 -0
  337. package/dist/codex/client-types.js +2 -0
  338. package/dist/codex/client-types.js.map +1 -0
  339. package/dist/codex/protocol.d.ts +5375 -0
  340. package/dist/codex/protocol.js +614 -0
  341. package/dist/codex/protocol.js.map +1 -0
  342. package/dist/codex/session.d.ts +263 -0
  343. package/dist/codex/session.js +466 -0
  344. package/dist/codex/session.js.map +1 -0
  345. package/dist/config.d.ts +185 -19
  346. package/dist/config.js +82 -16
  347. package/dist/config.js.map +1 -1
  348. package/dist/context-builder/anchors.d.ts +12 -0
  349. package/dist/context-builder/anchors.js +22 -0
  350. package/dist/context-builder/anchors.js.map +1 -0
  351. package/dist/context-builder/bundle.d.ts +109 -0
  352. package/dist/context-builder/bundle.js +1498 -0
  353. package/dist/context-builder/bundle.js.map +1 -0
  354. package/dist/context-builder/codemap.d.ts +22 -0
  355. package/dist/context-builder/codemap.js +675 -0
  356. package/dist/context-builder/codemap.js.map +1 -0
  357. package/dist/context-builder/config.d.ts +61 -0
  358. package/dist/context-builder/config.js +216 -0
  359. package/dist/context-builder/config.js.map +1 -0
  360. package/dist/context-builder/context-run-catalog.d.ts +17 -0
  361. package/dist/context-builder/context-run-catalog.js +99 -0
  362. package/dist/context-builder/context-run-catalog.js.map +1 -0
  363. package/dist/context-builder/delegate-packet.d.ts +219 -0
  364. package/dist/context-builder/delegate-packet.js +1190 -0
  365. package/dist/context-builder/delegate-packet.js.map +1 -0
  366. package/dist/context-builder/delegate-reconstruction.d.ts +13 -0
  367. package/dist/context-builder/delegate-reconstruction.js +220 -0
  368. package/dist/context-builder/delegate-reconstruction.js.map +1 -0
  369. package/dist/context-builder/delegate-validation.d.ts +27 -0
  370. package/dist/context-builder/delegate-validation.js +479 -0
  371. package/dist/context-builder/delegate-validation.js.map +1 -0
  372. package/dist/context-builder/delegate.d.ts +26 -0
  373. package/dist/context-builder/delegate.js +134 -0
  374. package/dist/context-builder/delegate.js.map +1 -0
  375. package/dist/context-builder/diagnostics.d.ts +36 -0
  376. package/dist/context-builder/diagnostics.js +107 -0
  377. package/dist/context-builder/diagnostics.js.map +1 -0
  378. package/dist/context-builder/discovery.d.ts +146 -0
  379. package/dist/context-builder/discovery.js +2129 -0
  380. package/dist/context-builder/discovery.js.map +1 -0
  381. package/dist/context-builder/globs.d.ts +14 -0
  382. package/dist/context-builder/globs.js +175 -0
  383. package/dist/context-builder/globs.js.map +1 -0
  384. package/dist/context-builder/handler.d.ts +41 -0
  385. package/dist/context-builder/handler.js +2590 -0
  386. package/dist/context-builder/handler.js.map +1 -0
  387. package/dist/context-builder/lifecycle-contract.d.ts +424 -0
  388. package/dist/context-builder/lifecycle-contract.js +523 -0
  389. package/dist/context-builder/lifecycle-contract.js.map +1 -0
  390. package/dist/context-builder/lifecycle-journal.d.ts +62 -0
  391. package/dist/context-builder/lifecycle-journal.js +88 -0
  392. package/dist/context-builder/lifecycle-journal.js.map +1 -0
  393. package/dist/context-builder/lifecycle-observer.d.ts +102 -0
  394. package/dist/context-builder/lifecycle-observer.js +258 -0
  395. package/dist/context-builder/lifecycle-observer.js.map +1 -0
  396. package/dist/context-builder/lifecycle-reconcile.d.ts +32 -0
  397. package/dist/context-builder/lifecycle-reconcile.js +191 -0
  398. package/dist/context-builder/lifecycle-reconcile.js.map +1 -0
  399. package/dist/context-builder/lifecycle-recovery.d.ts +2 -0
  400. package/dist/context-builder/lifecycle-recovery.js +14 -0
  401. package/dist/context-builder/lifecycle-recovery.js.map +1 -0
  402. package/dist/context-builder/path-signals.d.ts +7 -0
  403. package/dist/context-builder/path-signals.js +70 -0
  404. package/dist/context-builder/path-signals.js.map +1 -0
  405. package/dist/context-builder/paths.d.ts +30 -0
  406. package/dist/context-builder/paths.js +153 -0
  407. package/dist/context-builder/paths.js.map +1 -0
  408. package/dist/context-builder/progress.d.ts +17 -0
  409. package/dist/context-builder/progress.js +93 -0
  410. package/dist/context-builder/progress.js.map +1 -0
  411. package/dist/context-builder/receipt.d.ts +91 -0
  412. package/dist/context-builder/receipt.js +180 -0
  413. package/dist/context-builder/receipt.js.map +1 -0
  414. package/dist/context-builder/refine-handler.d.ts +14 -0
  415. package/dist/context-builder/refine-handler.js +790 -0
  416. package/dist/context-builder/refine-handler.js.map +1 -0
  417. package/dist/context-builder/review-coverage.d.ts +84 -0
  418. package/dist/context-builder/review-coverage.js +437 -0
  419. package/dist/context-builder/review-coverage.js.map +1 -0
  420. package/dist/context-builder/run-id.d.ts +7 -0
  421. package/dist/context-builder/run-id.js +31 -0
  422. package/dist/context-builder/run-id.js.map +1 -0
  423. package/dist/context-builder/schema.d.ts +669 -0
  424. package/dist/context-builder/schema.js +399 -0
  425. package/dist/context-builder/schema.js.map +1 -0
  426. package/dist/context-builder/secrets.d.ts +41 -0
  427. package/dist/context-builder/secrets.js +1651 -0
  428. package/dist/context-builder/secrets.js.map +1 -0
  429. package/dist/context-builder/selection.d.ts +56 -0
  430. package/dist/context-builder/selection.js +1111 -0
  431. package/dist/context-builder/selection.js.map +1 -0
  432. package/dist/context-builder/session-log-identity.d.ts +1 -0
  433. package/dist/context-builder/session-log-identity.js +66 -0
  434. package/dist/context-builder/session-log-identity.js.map +1 -0
  435. package/dist/context-builder/slice-range-math.d.ts +16 -0
  436. package/dist/context-builder/slice-range-math.js +137 -0
  437. package/dist/context-builder/slice-range-math.js.map +1 -0
  438. package/dist/context-builder/status.d.ts +66 -0
  439. package/dist/context-builder/status.js +160 -0
  440. package/dist/context-builder/status.js.map +1 -0
  441. package/dist/context-builder/storage.d.ts +118 -0
  442. package/dist/context-builder/storage.js +1003 -0
  443. package/dist/context-builder/storage.js.map +1 -0
  444. package/dist/context-builder/token-estimate.d.ts +19 -0
  445. package/dist/context-builder/token-estimate.js +90 -0
  446. package/dist/context-builder/token-estimate.js.map +1 -0
  447. package/dist/context-builder/versions.d.ts +29 -0
  448. package/dist/context-builder/versions.js +30 -0
  449. package/dist/context-builder/versions.js.map +1 -0
  450. package/dist/context-builder/workflow-runner.d.ts +69 -0
  451. package/dist/context-builder/workflow-runner.js +1051 -0
  452. package/dist/context-builder/workflow-runner.js.map +1 -0
  453. package/dist/context-builder/write-watchdog.d.ts +14 -0
  454. package/dist/context-builder/write-watchdog.js +38 -0
  455. package/dist/context-builder/write-watchdog.js.map +1 -0
  456. package/dist/dashboard-adapter-catalog.d.ts +9 -0
  457. package/dist/dashboard-adapter-catalog.js +46 -0
  458. package/dist/dashboard-adapter-catalog.js.map +1 -0
  459. package/dist/dashboard-cli.d.ts +79 -0
  460. package/dist/dashboard-cli.js +585 -0
  461. package/dist/dashboard-cli.js.map +1 -0
  462. package/dist/dashboard-companion/client.d.ts +36 -0
  463. package/dist/dashboard-companion/client.js +210 -0
  464. package/dist/dashboard-companion/client.js.map +1 -0
  465. package/dist/dashboard-companion/config.d.ts +8 -0
  466. package/dist/dashboard-companion/config.js +52 -0
  467. package/dist/dashboard-companion/config.js.map +1 -0
  468. package/dist/dashboard-companion/http-proxy.d.ts +10 -0
  469. package/dist/dashboard-companion/http-proxy.js +234 -0
  470. package/dist/dashboard-companion/http-proxy.js.map +1 -0
  471. package/dist/dashboard-companion/protocol.d.ts +80 -0
  472. package/dist/dashboard-companion/protocol.js +455 -0
  473. package/dist/dashboard-companion/protocol.js.map +1 -0
  474. package/dist/dashboard-companion/standalone-assets.d.ts +12 -0
  475. package/dist/dashboard-companion/standalone-assets.js +72 -0
  476. package/dist/dashboard-companion/standalone-assets.js.map +1 -0
  477. package/dist/dashboard-companion/standalone-entry.d.ts +1 -0
  478. package/dist/dashboard-companion/standalone-entry.js +17 -0
  479. package/dist/dashboard-companion/standalone-entry.js.map +1 -0
  480. package/dist/dashboard-gateway/config.d.ts +9 -0
  481. package/dist/dashboard-gateway/config.js +44 -0
  482. package/dist/dashboard-gateway/config.js.map +1 -0
  483. package/dist/dashboard-gateway/index.d.ts +11 -0
  484. package/dist/dashboard-gateway/index.js +755 -0
  485. package/dist/dashboard-gateway/index.js.map +1 -0
  486. package/dist/dashboard-gateway/main.d.ts +1 -0
  487. package/dist/dashboard-gateway/main.js +25 -0
  488. package/dist/dashboard-gateway/main.js.map +1 -0
  489. package/dist/dashboard-pairing-token.d.ts +1 -0
  490. package/dist/dashboard-pairing-token.js +5 -0
  491. package/dist/dashboard-pairing-token.js.map +1 -0
  492. package/dist/elaris/client.d.ts +73 -0
  493. package/dist/elaris/client.js +825 -0
  494. package/dist/elaris/client.js.map +1 -0
  495. package/dist/elaris/config.d.ts +18 -0
  496. package/dist/elaris/config.js +75 -0
  497. package/dist/elaris/config.js.map +1 -0
  498. package/dist/elaris/errors.d.ts +41 -0
  499. package/dist/elaris/errors.js +205 -0
  500. package/dist/elaris/errors.js.map +1 -0
  501. package/dist/elaris/github-repo.d.ts +18 -0
  502. package/dist/elaris/github-repo.js +89 -0
  503. package/dist/elaris/github-repo.js.map +1 -0
  504. package/dist/elaris/index.d.ts +10 -0
  505. package/dist/elaris/index.js +11 -0
  506. package/dist/elaris/index.js.map +1 -0
  507. package/dist/elaris/redact.d.ts +89 -0
  508. package/dist/elaris/redact.js +423 -0
  509. package/dist/elaris/redact.js.map +1 -0
  510. package/dist/elaris/run-id.d.ts +5 -0
  511. package/dist/elaris/run-id.js +20 -0
  512. package/dist/elaris/run-id.js.map +1 -0
  513. package/dist/elaris/status.d.ts +45 -0
  514. package/dist/elaris/status.js +122 -0
  515. package/dist/elaris/status.js.map +1 -0
  516. package/dist/elaris/tool-schemas.d.ts +314 -0
  517. package/dist/elaris/tool-schemas.js +208 -0
  518. package/dist/elaris/tool-schemas.js.map +1 -0
  519. package/dist/elaris/tools.d.ts +73 -0
  520. package/dist/elaris/tools.js +1065 -0
  521. package/dist/elaris/tools.js.map +1 -0
  522. package/dist/elaris/types.d.ts +1541 -0
  523. package/dist/elaris/types.js +252 -0
  524. package/dist/elaris/types.js.map +1 -0
  525. package/dist/errors.d.ts +16 -0
  526. package/dist/errors.js +19 -0
  527. package/dist/errors.js.map +1 -1
  528. package/dist/handler.d.ts +4 -0
  529. package/dist/handler.js +10 -1
  530. package/dist/handler.js.map +1 -1
  531. package/dist/index.d.ts +2 -1
  532. package/dist/index.js +13 -3
  533. package/dist/index.js.map +1 -1
  534. package/dist/local-clink-backend.d.ts +3 -0
  535. package/dist/local-clink-backend.js +4 -0
  536. package/dist/local-clink-backend.js.map +1 -1
  537. package/dist/package-info.d.ts +2 -0
  538. package/dist/package-info.js +18 -0
  539. package/dist/package-info.js.map +1 -0
  540. package/dist/parsers/codex-jsonl.js +48 -3
  541. package/dist/parsers/codex-jsonl.js.map +1 -1
  542. package/dist/parsers/extract.d.ts +10 -1
  543. package/dist/parsers/extract.js +11 -3
  544. package/dist/parsers/extract.js.map +1 -1
  545. package/dist/paths.d.ts +8 -0
  546. package/dist/paths.js +31 -43
  547. package/dist/paths.js.map +1 -1
  548. package/dist/pipeline.d.ts +51 -3
  549. package/dist/pipeline.js +264 -47
  550. package/dist/pipeline.js.map +1 -1
  551. package/dist/run-dir.d.ts +24 -0
  552. package/dist/run-dir.js +201 -2
  553. package/dist/run-dir.js.map +1 -1
  554. package/dist/runner.d.ts +13 -0
  555. package/dist/runner.js +184 -15
  556. package/dist/runner.js.map +1 -1
  557. package/dist/safety.d.ts +4 -4
  558. package/dist/safety.js +4 -4
  559. package/dist/schema.d.ts +7 -7
  560. package/dist/server.d.ts +2 -0
  561. package/dist/server.js +396 -24
  562. package/dist/server.js.map +1 -1
  563. package/dist/session-log-stream.d.ts +18 -0
  564. package/dist/session-log-stream.js +319 -0
  565. package/dist/session-log-stream.js.map +1 -0
  566. package/package.json +47 -5
  567. package/conf/adapters/gemini.json +0 -44
  568. package/conf/adapters/hapi/gemini.json +0 -47
  569. package/dist/artifacts.d.ts +0 -9
  570. package/dist/artifacts.js +0 -24
  571. package/dist/artifacts.js.map +0 -1
  572. package/dist/parsers/gemini-json.d.ts +0 -2
  573. package/dist/parsers/gemini-json.js +0 -72
  574. package/dist/parsers/gemini-json.js.map +0 -1
@@ -0,0 +1,1498 @@
1
+ import { boundContextBuilderOmissions, boundContextBuilderPathList, boundContextBuilderWarnings, sanitizeDiagnosticText, } from "./diagnostics.js";
2
+ import { createContextBuilderReceipt, cloneContextBuilderDelegateReceiptMetadata, } from "./receipt.js";
3
+ import { assertTaskSecretsGated, hasConservativeResidualSecret, } from "./secrets.js";
4
+ import { capEventsFromContextBuilderMetrics, reduceContextBuilderStatus, } from "./status.js";
5
+ import { writeContextBuilderArtifactsAndCommit, } from "./storage.js";
6
+ import { contextBuilderTokenCountingMethod, estimateContextBuilderTokens, } from "./token-estimate.js";
7
+ import { contextBuilderInternalCapsForManifest, } from "./config.js";
8
+ import { buildFileCodemap, remapCodemapToSourceCoordinates, renderCodemapJsonl, } from "./codemap.js";
9
+ // Folded into the cache key so bundle markdown format changes invalidate stale cache entries.
10
+ export const CONTEXT_BUILDER_RENDERER_VERSION = 2;
11
+ export function renderContextBuilderBundle(input) {
12
+ const allowSecrets = input.allowSecrets ?? true;
13
+ assertTaskSecretsGated(input.task, allowSecrets);
14
+ const selected = input.selected_context.map((file) => sanitizeSelectedFile(file, allowSecrets));
15
+ const tree = input.tree.map((file) => sanitizeTreeFile(file, allowSecrets));
16
+ const search = input.search.map((record) => sanitizeSearchRecord(record, allowSecrets));
17
+ const slices = input.slices.map((record) => sanitizeSliceRecord(record, allowSecrets));
18
+ const presentationSelected = promoteTaskPresentationEvidence(filterTaskPresentationSelected(selected, input.task), input.task, slices);
19
+ const omissions = boundContextBuilderOmissions([...(input.omissions ?? [])], contextBuilderInternalCapsForManifest(input.internal_caps));
20
+ const warnings = boundContextBuilderWarnings([...(input.warnings ?? [])], contextBuilderInternalCapsForManifest(input.internal_caps));
21
+ const presentationOmissions = reconcileSelectedOmissions(filterTaskPresentationOmissions(omissions, input.task), presentationSelected);
22
+ const openQuestions = buildPresentationOpenQuestions(boundOpenQuestions(input.open_questions ?? []), presentationSelected, presentationOmissions);
23
+ const showRootLabels = input.roots.length > 1;
24
+ return [
25
+ "# Context Bundle",
26
+ "",
27
+ "## Original Task",
28
+ "",
29
+ input.task,
30
+ "",
31
+ "## How To Use This Bundle",
32
+ "",
33
+ "- Start with top must-read ranges and verify the cited evidence directly.",
34
+ "- Inspect selected files, repository shape, and search evidence before editing.",
35
+ "- Treat omissions and open questions as follow-up checks, not as resolved facts.",
36
+ "",
37
+ "## Top Must-Read Ranges",
38
+ "",
39
+ renderTopMustReadRanges({
40
+ task: input.task,
41
+ selected: presentationSelected,
42
+ search,
43
+ showRootLabels,
44
+ }),
45
+ "",
46
+ "## Selected Files",
47
+ "",
48
+ renderSelectedFilesList({
49
+ task: input.task,
50
+ selected: presentationSelected,
51
+ search,
52
+ showRootLabels,
53
+ }),
54
+ "",
55
+ "## Repository Shape",
56
+ "",
57
+ renderRepositoryShape({
58
+ tree,
59
+ selected: presentationSelected,
60
+ showRootLabels,
61
+ }),
62
+ "",
63
+ "## Search Evidence",
64
+ "",
65
+ renderSearchEvidence({
66
+ search,
67
+ selected: presentationSelected,
68
+ showRootLabels,
69
+ }),
70
+ "",
71
+ "## File Context",
72
+ "",
73
+ renderFileContext(presentationSelected, search, showRootLabels),
74
+ "",
75
+ "## Open Questions",
76
+ "",
77
+ renderOpenQuestions(openQuestions),
78
+ "",
79
+ "## Omissions And Budget Notes",
80
+ "",
81
+ renderOmissionsAndBudgetNotes({
82
+ omissions: presentationOmissions,
83
+ warnings,
84
+ metrics: input.metrics,
85
+ }),
86
+ "",
87
+ ].join("\n");
88
+ }
89
+ export function buildContextBuilderStatus(input) {
90
+ return reduceContextBuilderStatus(buildContextBuilderStatusEvidence(input));
91
+ }
92
+ export function buildContextBuilderStatusEvidence(input, boundedDiagnostics = {}) {
93
+ const omissions = boundedDiagnostics.omissions ?? input.omissions ?? [];
94
+ const warnings = boundedDiagnostics.warnings ?? input.warnings ?? [];
95
+ return {
96
+ ...(input.status_evidence ?? {}),
97
+ omissions: [
98
+ ...omissions.map(omissionEventFromDiagnostic),
99
+ ...(input.status_evidence?.omissions ?? []),
100
+ ],
101
+ warnings: [
102
+ ...warnings.map(warningEventFromDiagnostic),
103
+ ...(input.status_evidence?.warnings ?? []),
104
+ ],
105
+ caps: [
106
+ ...capEventsFromContextBuilderMetrics(input.metrics, input.search_coverage == null
107
+ ? {}
108
+ : { search_coverage: input.search_coverage }),
109
+ ...(input.status_evidence?.caps ?? []),
110
+ ],
111
+ storage: [
112
+ ...(input.metrics.truncated
113
+ ? [{ reason: "artifact_truncated" }]
114
+ : []),
115
+ ...(input.status_evidence?.storage ?? []),
116
+ ],
117
+ delegate: [
118
+ ...(input.delegate?.fallback_used === true
119
+ ? [{ reason: "delegate_fallback", fallback: true }]
120
+ : []),
121
+ ...(input.status_evidence?.delegate ?? []),
122
+ ],
123
+ };
124
+ }
125
+ export function renderContextBuilderArtifactContents(input) {
126
+ const allowSecrets = input.allowSecrets ?? true;
127
+ assertTaskSecretsGated(input.task, allowSecrets);
128
+ const tree = input.tree.map((file) => sanitizeTreeFile(file, allowSecrets));
129
+ const search = input.search.map((record) => sanitizeSearchRecord(record, allowSecrets));
130
+ const slices = input.slices.map((record) => sanitizeSliceRecord(record, allowSecrets));
131
+ const selectedContext = input.selected_context.map((file) => sanitizeSelectedFile(file, allowSecrets));
132
+ const summary = buildContextBuilderSummary(input);
133
+ return {
134
+ bundle_md: renderContextBuilderBundle(input),
135
+ selected_context_jsonl: renderSelectedContextJsonl(selectedContext),
136
+ tree_json: `${JSON.stringify({
137
+ schema_version: 1,
138
+ roots: input.roots.map((root) => sanitizeRoot(root, allowSecrets)),
139
+ files: tree,
140
+ })}\n`,
141
+ search_jsonl: renderJsonl(search),
142
+ slices_jsonl: renderJsonl(slices),
143
+ codemap_jsonl: renderCodemapJsonl(selectedContext.map((file) => remapCodemapToSourceCoordinates(buildFileCodemap(file.path, file.content), file.ranges))),
144
+ summary_json: `${JSON.stringify({
145
+ ...summary,
146
+ selected_context: selectedContext.map(stripSelectedContent),
147
+ })}\n`,
148
+ };
149
+ }
150
+ export function buildContextBuilderManifestDraft(input) {
151
+ const allowSecrets = input.allowSecrets ?? true;
152
+ const internalCaps = contextBuilderInternalCapsForManifest(input.internal_caps);
153
+ const omissions = boundContextBuilderOmissions([...(input.omissions ?? [])], internalCaps);
154
+ const warnings = boundContextBuilderWarnings([...(input.warnings ?? [])], internalCaps);
155
+ const status = reduceContextBuilderStatus(buildContextBuilderStatusEvidence(input));
156
+ return {
157
+ status,
158
+ created_at: input.created_at,
159
+ task: validateTaskForRendering(input.task, allowSecrets),
160
+ // Echo the RESOLVED secret profile (per-call > workflow > env > true) so
161
+ // artifact-only readers do not have to infer it from omission behavior.
162
+ // Additive: manifest validation is required-key based and every known
163
+ // reader picks named keys.
164
+ allow_secrets_resolved: allowSecrets,
165
+ roots: input.roots.map((root) => sanitizeRoot(root, allowSecrets)),
166
+ inputs: sanitizeJsonValue(input.inputs, allowSecrets),
167
+ budget: { ...input.budget },
168
+ internal_caps: internalCaps,
169
+ token_counting: contextBuilderTokenCountingMethod(),
170
+ selected_context: input.selected_context
171
+ .map((file) => sanitizeSelectedFile(file, allowSecrets))
172
+ .map(stripSelectedContent),
173
+ omissions,
174
+ warnings,
175
+ metrics: { ...input.metrics },
176
+ ...(input.search_coverage == null
177
+ ? {}
178
+ : {
179
+ search_coverage: sanitizeSearchCoverage(input.search_coverage, allowSecrets),
180
+ }),
181
+ ...(input.coverage == null ? {} : { coverage: input.coverage }),
182
+ ...(input.parent_run_id == null
183
+ ? {}
184
+ : { parent_run_id: input.parent_run_id }),
185
+ ...(input.refine_ops == null
186
+ ? {}
187
+ : { refine_ops: input.refine_ops.map((op) => ({ ...op })) }),
188
+ ...(input.file_fingerprints == null
189
+ ? {}
190
+ : {
191
+ file_fingerprints: input.file_fingerprints.map((fingerprint) => ({
192
+ ...fingerprint,
193
+ })),
194
+ }),
195
+ ...(input.delegate == null
196
+ ? {}
197
+ : { delegate: cloneContextBuilderDelegateReceiptMetadata(input.delegate) }),
198
+ ...(input.observability == null
199
+ ? {}
200
+ : { observability: { ...input.observability } }),
201
+ ...(input.debug === true
202
+ ? {
203
+ debug_diagnostics: boundDebugDiagnostics(input.debug_diagnostics, internalCaps),
204
+ }
205
+ : {}),
206
+ };
207
+ }
208
+ export async function writeContextBuilderFinalArtifacts(storage, input, options = {}) {
209
+ const { contents, metrics } = renderContentsWithStableByteMetric(input);
210
+ const writeInput = { ...input, metrics };
211
+ await writeContextBuilderArtifactsAndCommit(storage, contents, buildContextBuilderManifestDraft(writeInput), {
212
+ ...(options.signal == null ? {} : { signal: options.signal }),
213
+ ...(options.ownerNonce == null ? {} : { ownerNonce: options.ownerNonce }),
214
+ ...(options.ops == null ? {} : { ops: options.ops }),
215
+ ...(options.beforeManifestCommit == null
216
+ ? {}
217
+ : { beforeManifestCommit: options.beforeManifestCommit }),
218
+ });
219
+ const internalCaps = contextBuilderInternalCapsForManifest(input.internal_caps);
220
+ const warnings = boundContextBuilderWarnings(input.warnings == null ? [] : [...input.warnings], internalCaps);
221
+ const omissions = boundContextBuilderOmissions(input.omissions == null ? [] : [...input.omissions], internalCaps);
222
+ return createContextBuilderReceipt({
223
+ run_id: storage.runId,
224
+ status: reduceContextBuilderStatus(buildContextBuilderStatusEvidence({ ...input, metrics })),
225
+ artifact_dir: storage.artifactDir,
226
+ artifacts: storage.artifacts,
227
+ metrics,
228
+ warnings,
229
+ omissions,
230
+ ...(input.delegate == null
231
+ ? {}
232
+ : { delegate: cloneContextBuilderDelegateReceiptMetadata(input.delegate) }),
233
+ });
234
+ }
235
+ function renderContentsWithStableByteMetric(input) {
236
+ let metrics = { ...input.metrics, bytes_written: 0 };
237
+ let contents = renderContextBuilderArtifactContents({ ...input, metrics });
238
+ for (let attempt = 0; attempt < 4; attempt += 1) {
239
+ const bytesWritten = Object.values(contents).reduce((total, content) => total + Buffer.byteLength(content, "utf8"), 0);
240
+ const nextMetrics = { ...metrics, bytes_written: bytesWritten };
241
+ const nextContents = renderContextBuilderArtifactContents({
242
+ ...input,
243
+ metrics: nextMetrics,
244
+ });
245
+ if (bytesWritten === metrics.bytes_written &&
246
+ JSON.stringify(nextContents) === JSON.stringify(contents)) {
247
+ return { contents, metrics };
248
+ }
249
+ metrics = nextMetrics;
250
+ contents = nextContents;
251
+ }
252
+ return { contents, metrics };
253
+ }
254
+ function buildContextBuilderSummary(input) {
255
+ const allowSecrets = input.allowSecrets ?? true;
256
+ const selected = input.selected_context.map((file) => sanitizeSelectedFile(file, allowSecrets));
257
+ const omissions = reconcileSelectedOmissions(filterTaskPresentationOmissions(boundContextBuilderOmissions([...(input.omissions ?? [])], contextBuilderInternalCapsForManifest(input.internal_caps)), input.task), selected);
258
+ const openQuestions = buildPresentationOpenQuestions(boundOpenQuestions(input.open_questions ?? []), selected, omissions);
259
+ return {
260
+ schema_version: 1,
261
+ run_id: input.run_id,
262
+ created_at: input.created_at,
263
+ status: reduceContextBuilderStatus(buildContextBuilderStatusEvidence(input)),
264
+ // Mirror of the manifest's resolved secret-profile echo, so summary-only
265
+ // readers get the same explicit benchmark/run profile.
266
+ allow_secrets_resolved: allowSecrets,
267
+ token_counting: contextBuilderTokenCountingMethod(),
268
+ metrics: { ...input.metrics },
269
+ selected_file_count: input.selected_context.length,
270
+ warning_count: input.warnings?.length ?? 0,
271
+ omission_count: omissions.length,
272
+ open_questions: openQuestions,
273
+ ...(input.search_coverage == null
274
+ ? {}
275
+ : {
276
+ search_coverage: sanitizeSearchCoverage(input.search_coverage, allowSecrets),
277
+ }),
278
+ ...(input.delegate == null
279
+ ? {}
280
+ : { delegate: cloneContextBuilderDelegateReceiptMetadata(input.delegate) }),
281
+ };
282
+ }
283
+ function sanitizeRoot(root, allowSecrets) {
284
+ return {
285
+ root_index: root.root_index,
286
+ ...(root.input_path == null
287
+ ? {}
288
+ : { input_path: safePath(root.input_path, allowSecrets) }),
289
+ path: safePath(root.path, allowSecrets),
290
+ };
291
+ }
292
+ function sanitizeTreeFile(file, allowSecrets) {
293
+ return {
294
+ root_index: file.root_index,
295
+ path: safePath(file.path, allowSecrets),
296
+ size_bytes: file.size_bytes,
297
+ eligible: file.eligible,
298
+ content_eligible: file.content_eligible,
299
+ ...(file.omission_reason == null
300
+ ? {}
301
+ : { omission_reason: sanitizeDiagnosticText(file.omission_reason) }),
302
+ };
303
+ }
304
+ function sanitizeSearchRecord(record, allowSecrets) {
305
+ return {
306
+ root_index: record.root_index,
307
+ path: safePath(record.path, allowSecrets),
308
+ line: record.line,
309
+ column: record.column,
310
+ search_term: sanitizeDiagnosticText(record.search_term, allowSecrets),
311
+ search_term_index: record.search_term_index,
312
+ preview: safeContent(record.preview, allowSecrets),
313
+ };
314
+ }
315
+ // Defensive bound matching the public caller search-term cap; T1's coverage
316
+ // rows are already bounded by it, so this only guards a malformed producer.
317
+ const MAX_SEARCH_COVERAGE_CALLER_TERM_ROWS = 20;
318
+ function sanitizeSearchCoverage(coverage, allowSecrets) {
319
+ return {
320
+ eligible_candidate_count: coverage.eligible_candidate_count,
321
+ searched_candidate_count: coverage.searched_candidate_count,
322
+ unsearched_candidate_count: coverage.unsearched_candidate_count,
323
+ caller_term_count: coverage.caller_term_count,
324
+ derived_term_count: coverage.derived_term_count,
325
+ caller_record_count: coverage.caller_record_count,
326
+ derived_record_count: coverage.derived_record_count,
327
+ caller_coverage_complete: coverage.caller_coverage_complete,
328
+ caller_terms: coverage.caller_terms
329
+ .slice(0, MAX_SEARCH_COVERAGE_CALLER_TERM_ROWS)
330
+ .map((term) => ({
331
+ term: sanitizeDiagnosticText(term.term, allowSecrets),
332
+ search_term_index: term.search_term_index,
333
+ hit_count: term.hit_count,
334
+ scan_complete: term.scan_complete,
335
+ })),
336
+ };
337
+ }
338
+ function sanitizeSliceRecord(record, allowSecrets) {
339
+ return {
340
+ root_index: record.root_index,
341
+ path: safePath(record.path, allowSecrets),
342
+ start_line: record.start_line,
343
+ end_line: record.end_line,
344
+ source: record.source,
345
+ content: safeContent(record.content, allowSecrets),
346
+ ...(record.search_term_index == null
347
+ ? {}
348
+ : { search_term_index: record.search_term_index }),
349
+ };
350
+ }
351
+ function sanitizeSelectedFile(file, allowSecrets) {
352
+ return {
353
+ root_index: file.root_index,
354
+ path: safePath(file.path, allowSecrets),
355
+ ranges: file.ranges.map(sanitizeRange),
356
+ content: safeContent(file.content, allowSecrets),
357
+ bytes: file.bytes,
358
+ estimated_tokens: file.estimated_tokens > 0
359
+ ? file.estimated_tokens
360
+ : estimateContextBuilderTokens(file.content),
361
+ source: file.source,
362
+ ...(file.disposition == null ? {} : { disposition: file.disposition }),
363
+ };
364
+ }
365
+ function sanitizeRange(range) {
366
+ return {
367
+ start_line: range.start_line,
368
+ end_line: range.end_line,
369
+ };
370
+ }
371
+ function stripSelectedContent(file) {
372
+ return {
373
+ root_index: file.root_index,
374
+ path: file.path,
375
+ ranges: file.ranges.map(sanitizeRange),
376
+ bytes: file.bytes,
377
+ estimated_tokens: file.estimated_tokens,
378
+ source: file.source,
379
+ ...(file.disposition == null ? {} : { disposition: file.disposition }),
380
+ };
381
+ }
382
+ function renderSelectedFilesList(input) {
383
+ const { task, selected, search, showRootLabels } = input;
384
+ if (selected.length === 0) {
385
+ return "- None selected.";
386
+ }
387
+ const visible = selected.slice(0, 18);
388
+ const hiddenCount = selected.length - visible.length;
389
+ const rendered = visible
390
+ .map((file) => {
391
+ return [
392
+ `- ${renderRootPrefix(file.root_index, showRootLabels)}${file.path} (${file.source})`,
393
+ ` purpose: ${selectedFilePurpose(task, file, search)}`,
394
+ ].join("\n");
395
+ })
396
+ .join("\n");
397
+ return hiddenCount > 0
398
+ ? `${rendered}\n- ${hiddenCount} more selected files are listed in manifest.json and selected-context.jsonl.`
399
+ : rendered;
400
+ }
401
+ function selectedFilePurpose(_task, file, search) {
402
+ const source = file.source === "focus" ? "requested focus evidence" : "matched task anchors";
403
+ const clauses = [
404
+ source,
405
+ pathPurpose(file.path),
406
+ rangePurpose(file.ranges),
407
+ ];
408
+ const symbols = selectedFileSymbols(file);
409
+ if (symbols.length > 0) {
410
+ clauses.push(`symbols: ${symbols.join(", ")}`);
411
+ }
412
+ else {
413
+ const terms = selectedFileSearchTerms(file, search);
414
+ if (terms.length > 0) {
415
+ clauses.push(`search-backed slice`);
416
+ }
417
+ }
418
+ return `${clauses.join("; ")}.`;
419
+ }
420
+ function selectedFileRangeNotes(task, file, search) {
421
+ const sourceLines = splitSelectedFileContentByRange(file);
422
+ const searchTerms = selectedFileSearchTerms(file, search);
423
+ return file.ranges.slice(0, 4).map((range, index) => {
424
+ const symbols = symbolsFromLines(sourceLines[index] ?? []);
425
+ const rangeHits = search.filter((record) => record.root_index === file.root_index &&
426
+ record.path === file.path &&
427
+ record.line >= range.start_line &&
428
+ record.line <= range.end_line);
429
+ const label = range.start_line === range.end_line
430
+ ? `${range.start_line}`
431
+ : `${range.start_line}-${range.end_line}`;
432
+ return `${label}: ${rangeEvidenceSummary({
433
+ task,
434
+ path: file.path,
435
+ source: file.source,
436
+ symbols,
437
+ searchTerms,
438
+ rangeHits,
439
+ })}`;
440
+ });
441
+ }
442
+ function rangeEvidenceSummary(input) {
443
+ const hitSummary = rangeHitSummary(input.rangeHits ?? []);
444
+ if (hitSummary != null) {
445
+ return hitSummary;
446
+ }
447
+ if (input.searchTerms.length > 0) {
448
+ return `${pathPurpose(input.path)} selected by matching task evidence`;
449
+ }
450
+ if (input.symbols.length > 0) {
451
+ return `${input.source} evidence around ${input.symbols.slice(0, 4).join(", ")}`;
452
+ }
453
+ return "bounded supporting evidence for the task";
454
+ }
455
+ function rangeHitSummary(hits) {
456
+ if (hits.length === 0) {
457
+ return undefined;
458
+ }
459
+ const byTerm = new Map();
460
+ for (const hit of hits) {
461
+ const term = hit.search_term.trim();
462
+ if (term.length === 0) {
463
+ continue;
464
+ }
465
+ const lines = byTerm.get(term) ?? [];
466
+ if (!lines.includes(hit.line)) {
467
+ lines.push(hit.line);
468
+ }
469
+ byTerm.set(term, lines);
470
+ if (byTerm.size >= 3) {
471
+ break;
472
+ }
473
+ }
474
+ const rendered = [...byTerm.entries()]
475
+ .slice(0, 3)
476
+ .map(([term, lines]) => `"${term}" at ${lines.slice(0, 3).join(",")}`);
477
+ return rendered.length === 0 ? undefined : `matches ${rendered.join("; ")}`;
478
+ }
479
+ function selectedFileSymbols(file) {
480
+ return symbolsFromLines(splitTextLinesForBundle(file.content)).slice(0, 6);
481
+ }
482
+ function splitSelectedFileContentByRange(file) {
483
+ const lines = splitTextLinesForBundle(file.content);
484
+ if (file.ranges.length <= 1) {
485
+ return [lines];
486
+ }
487
+ const totalRangeLines = file.ranges.reduce((total, range) => total + Math.max(0, range.end_line - range.start_line + 1), 0);
488
+ if (totalRangeLines !== lines.length) {
489
+ return file.ranges.map(() => []);
490
+ }
491
+ const output = [];
492
+ let offset = 0;
493
+ for (const range of file.ranges) {
494
+ const count = Math.max(0, range.end_line - range.start_line + 1);
495
+ output.push(lines.slice(offset, offset + count));
496
+ offset += count;
497
+ }
498
+ return output;
499
+ }
500
+ function renderSelectedContextJsonl(selected) {
501
+ return renderJsonl(selected.flatMap((file) => {
502
+ const rangeBodies = splitSelectedFileContentByRange(file);
503
+ return file.ranges.map((range, index) => ({
504
+ root_index: file.root_index,
505
+ path: file.path,
506
+ start_line: range.start_line,
507
+ end_line: range.end_line,
508
+ source: file.source,
509
+ ...(file.disposition == null ? {} : { disposition: file.disposition }),
510
+ content: isCodemapOnlyDisposition(file.disposition)
511
+ ? ""
512
+ : (rangeBodies[index] ?? []).join("\n"),
513
+ }));
514
+ }));
515
+ }
516
+ function splitTextLinesForBundle(text) {
517
+ if (text.length === 0) {
518
+ return [];
519
+ }
520
+ const withoutFinalNewline = text.endsWith("\n")
521
+ ? text.slice(0, text.endsWith("\r\n") ? -2 : -1)
522
+ : text;
523
+ return withoutFinalNewline.length === 0
524
+ ? [""]
525
+ : withoutFinalNewline.split(/\r\n|\n/);
526
+ }
527
+ function symbolsFromLines(lines) {
528
+ const symbols = [];
529
+ const seen = new Set();
530
+ for (const line of lines) {
531
+ for (const symbol of symbolsFromLine(line)) {
532
+ if (seen.has(symbol)) {
533
+ continue;
534
+ }
535
+ seen.add(symbol);
536
+ symbols.push(symbol);
537
+ if (symbols.length >= 8) {
538
+ return symbols;
539
+ }
540
+ }
541
+ }
542
+ return symbols;
543
+ }
544
+ function symbolsFromLine(line) {
545
+ const patterns = [
546
+ /\b(?:async\s+)?(?:def|function|class)\s+([A-Za-z_][A-Za-z0-9_]*)/g,
547
+ /\b(?:const|let|var)\s+([A-Za-z_][A-Za-z0-9_]*)\s*=/g,
548
+ /\bexport\s+(?:async\s+)?(?:function|class|const)\s+([A-Za-z_][A-Za-z0-9_]*)/g,
549
+ /\bit\(\s*['"]([^'"]{8,90})['"]/g,
550
+ /\bdescribe\(\s*['"]([^'"]{8,90})['"]/g,
551
+ ];
552
+ const symbols = [];
553
+ for (const pattern of patterns) {
554
+ for (const match of line.matchAll(pattern)) {
555
+ const value = match[1]?.trim();
556
+ if (value != null && value.length > 0) {
557
+ symbols.push(value);
558
+ }
559
+ }
560
+ }
561
+ return symbols;
562
+ }
563
+ function selectedFileSearchTerms(file, search) {
564
+ const terms = [];
565
+ const seen = new Set();
566
+ for (const record of search) {
567
+ if (record.root_index !== file.root_index || record.path !== file.path) {
568
+ continue;
569
+ }
570
+ const term = record.search_term.trim();
571
+ if (term.length === 0 || seen.has(term)) {
572
+ continue;
573
+ }
574
+ seen.add(term);
575
+ terms.push(term);
576
+ if (terms.length >= 4) {
577
+ break;
578
+ }
579
+ }
580
+ return terms;
581
+ }
582
+ function pathPurpose(path) {
583
+ const normalized = path.toLowerCase();
584
+ const basename = normalized.split("/").at(-1) ?? normalized;
585
+ const language = languagePurpose(basename);
586
+ if (isTestPath(normalized, basename)) {
587
+ return `${language} test coverage`;
588
+ }
589
+ if (normalized.startsWith("docs/") || normalized.includes("/docs/")) {
590
+ return `${language} documentation`;
591
+ }
592
+ if (isClosurePath(normalized)) {
593
+ return `${language} contract or configuration`;
594
+ }
595
+ if (normalized.startsWith("frontend/") || normalized.includes("/frontend/")) {
596
+ return `${language} frontend implementation`;
597
+ }
598
+ if (normalized.startsWith("backend/") || normalized.includes("/backend/")) {
599
+ return `${language} backend implementation`;
600
+ }
601
+ if (normalized.startsWith("src/") || normalized.includes("/src/")) {
602
+ return `${language} source implementation`;
603
+ }
604
+ return `${language} selected context`;
605
+ }
606
+ function languagePurpose(basename) {
607
+ if (basename.endsWith(".tsx")) {
608
+ return "TSX";
609
+ }
610
+ if (basename.endsWith(".ts")) {
611
+ return "TypeScript";
612
+ }
613
+ if (basename.endsWith(".jsx")) {
614
+ return "JSX";
615
+ }
616
+ if (basename.endsWith(".js")) {
617
+ return "JavaScript";
618
+ }
619
+ if (basename.endsWith(".py")) {
620
+ return "Python";
621
+ }
622
+ if (basename.endsWith(".rs")) {
623
+ return "Rust";
624
+ }
625
+ if (basename.endsWith(".md") || basename.endsWith(".mdx")) {
626
+ return "Markdown";
627
+ }
628
+ if (basename.endsWith(".json")) {
629
+ return "JSON";
630
+ }
631
+ if (basename.endsWith(".yml") || basename.endsWith(".yaml")) {
632
+ return "YAML";
633
+ }
634
+ return "file";
635
+ }
636
+ function isTestPath(path, basename) {
637
+ return (path.startsWith("test/") ||
638
+ path.startsWith("tests/") ||
639
+ path.includes("/test/") ||
640
+ path.includes("/tests/") ||
641
+ path.includes("/__tests__/") ||
642
+ basename.includes(".test.") ||
643
+ basename.includes(".spec.") ||
644
+ basename.startsWith("test_"));
645
+ }
646
+ function rangePurpose(ranges) {
647
+ if (ranges.length === 0) {
648
+ return "full-file context";
649
+ }
650
+ const rendered = ranges
651
+ .slice(0, 3)
652
+ .map((range) => range.start_line === range.end_line
653
+ ? `${range.start_line}`
654
+ : `${range.start_line}-${range.end_line}`);
655
+ const suffix = ranges.length > rendered.length ? ` +${ranges.length - rendered.length}` : "";
656
+ return `ranges ${rendered.join(", ")}${suffix}`;
657
+ }
658
+ function renderTopMustReadRanges(input) {
659
+ if (input.selected.length === 0) {
660
+ return "- No selected ranges available.";
661
+ }
662
+ const candidates = topMustReadRangeCandidates(input)
663
+ .sort((left, right) => right.score - left.score || left.order - right.order)
664
+ .slice(0, 8);
665
+ return candidates
666
+ .map((candidate, index) => {
667
+ const header = `${index + 1}. ${renderRootPrefix(candidate.file.root_index, input.showRootLabels)}${candidate.file.path}:${singleRangeLabel(candidate.range)} - ${candidate.reason}`;
668
+ const snippet = renderTopMustReadSnippet(candidate, index, input.task);
669
+ return snippet.length === 0 ? header : `${header}\n\n${snippet}`;
670
+ })
671
+ .join("\n");
672
+ }
673
+ function topMustReadRangeCandidates(input) {
674
+ const candidates = [];
675
+ let order = 0;
676
+ for (const file of input.selected) {
677
+ const searchTerms = selectedFileSearchTerms(file, input.search);
678
+ const searchHitCount = input.search.filter((record) => record.root_index === file.root_index && record.path === file.path).length;
679
+ const sourceLines = splitSelectedFileContentByRange(file);
680
+ for (const [rangeIndex, range] of file.ranges.entries()) {
681
+ const symbols = symbolsFromLines(sourceLines[rangeIndex] ?? []);
682
+ const summary = rangeEvidenceSummary({
683
+ task: input.task,
684
+ path: file.path,
685
+ source: file.source,
686
+ symbols,
687
+ searchTerms,
688
+ });
689
+ const score = (file.source === "focus" ? 40 : 20)
690
+ + Math.min(searchHitCount, 6) * 3
691
+ + (pathLooksLikeTest(file.path) ? 8 : 0)
692
+ - rangeIndex;
693
+ const hitText = searchHitCount === 0
694
+ ? ""
695
+ : `; ${searchHitCount} selected-file search hit${searchHitCount === 1 ? "" : "s"}`;
696
+ candidates.push({
697
+ file,
698
+ range,
699
+ score,
700
+ order,
701
+ reason: `${summary}${hitText}`,
702
+ });
703
+ order += 1;
704
+ }
705
+ }
706
+ return candidates;
707
+ }
708
+ function singleRangeLabel(range) {
709
+ return range.start_line === range.end_line
710
+ ? `${range.start_line}`
711
+ : `${range.start_line}-${range.end_line}`;
712
+ }
713
+ function renderTopMustReadSnippet(candidate, index, task) {
714
+ if (isCodemapOnlyDisposition(candidate.file.disposition)) {
715
+ return "";
716
+ }
717
+ if (index >= 3) {
718
+ return "";
719
+ }
720
+ const rangeIndex = candidate.file.ranges.findIndex((range) => range.start_line === candidate.range.start_line &&
721
+ range.end_line === candidate.range.end_line);
722
+ const rangeLines = splitSelectedFileContentByRange(candidate.file)[rangeIndex] ?? [];
723
+ const numbered = topMustReadSnippetLines(candidate.range, rangeLines, evidenceTermsForTask(task), candidate.file.path);
724
+ if (numbered.length === 0) {
725
+ return "";
726
+ }
727
+ return ["```text", ...numbered, "```"].join("\n");
728
+ }
729
+ function topMustReadSnippetLines(range, rangeLines, terms, path) {
730
+ const evidenceLines = rangeLines
731
+ .map((line, lineIndex) => ({
732
+ lineNumber: range.start_line + lineIndex,
733
+ rangeIndex: 0,
734
+ text: line.trimEnd(),
735
+ }))
736
+ .filter((line) => line.text.trim().length > 0);
737
+ const scored = evidenceLines
738
+ .map((line, index) => ({
739
+ index,
740
+ score: evidenceLineScore(line.text, terms, path),
741
+ }))
742
+ .filter((candidate) => candidate.score > 0)
743
+ .sort((left, right) => right.score - left.score ||
744
+ evidenceLines[left.index].lineNumber -
745
+ evidenceLines[right.index].lineNumber);
746
+ if (scored.length > 0) {
747
+ const rendered = renderEvidenceLineWindows(mergedEvidenceWindows(evidenceLines, scored.slice(0, 2).map((candidate) => candidate.index)), evidenceLines)
748
+ .split("\n")
749
+ .filter((line) => line.length > 0)
750
+ .slice(0, 8);
751
+ if (rendered.length > 0) {
752
+ return rendered;
753
+ }
754
+ }
755
+ return evidenceLines
756
+ .slice(0, 8)
757
+ .map((line) => `${line.lineNumber}: ${trimEvidenceLine(line.text)}`);
758
+ }
759
+ function pathLooksLikeTest(path) {
760
+ return /(?:^|\/)(?:tests?|__tests__)\//.test(path) || /\.test\.[^.]+$/.test(path);
761
+ }
762
+ const SOURCE_EVIDENCE_WINDOW_RADIUS = 4;
763
+ function mergedEvidenceWindows(lines, anchors) {
764
+ const windows = anchors
765
+ .map((anchor) => evidenceWindowAroundAnchor(lines, anchor))
766
+ .sort((left, right) => left.startIndex - right.startIndex);
767
+ const merged = [];
768
+ for (const window of windows) {
769
+ const previous = merged.at(-1);
770
+ if (previous != null &&
771
+ lines[previous.endIndex]?.rangeIndex === lines[window.startIndex]?.rangeIndex &&
772
+ window.startIndex <= previous.endIndex + 1) {
773
+ previous.endIndex = Math.max(previous.endIndex, window.endIndex);
774
+ continue;
775
+ }
776
+ merged.push({ ...window });
777
+ }
778
+ return merged;
779
+ }
780
+ function evidenceWindowAroundAnchor(lines, anchor) {
781
+ const anchorLine = lines[anchor];
782
+ if (anchorLine == null) {
783
+ return { startIndex: anchor, endIndex: anchor };
784
+ }
785
+ let startIndex = anchor;
786
+ let before = SOURCE_EVIDENCE_WINDOW_RADIUS;
787
+ while (before > 0 &&
788
+ startIndex > 0 &&
789
+ lines[startIndex - 1]?.rangeIndex === anchorLine.rangeIndex) {
790
+ startIndex -= 1;
791
+ before -= 1;
792
+ }
793
+ let endIndex = anchor;
794
+ let after = SOURCE_EVIDENCE_WINDOW_RADIUS;
795
+ while (after > 0 &&
796
+ endIndex + 1 < lines.length &&
797
+ lines[endIndex + 1]?.rangeIndex === anchorLine.rangeIndex) {
798
+ endIndex += 1;
799
+ after -= 1;
800
+ }
801
+ return { startIndex, endIndex };
802
+ }
803
+ function renderEvidenceLineWindows(windows, lines) {
804
+ const rendered = [];
805
+ let previousRenderedLine;
806
+ for (const window of windows) {
807
+ for (let index = window.startIndex; index <= window.endIndex; index += 1) {
808
+ const line = lines[index];
809
+ if (line == null || line.text.trim().length === 0) {
810
+ continue;
811
+ }
812
+ if (previousRenderedLine != null &&
813
+ (previousRenderedLine.rangeIndex !== line.rangeIndex ||
814
+ previousRenderedLine.lineNumber !== line.lineNumber - 1) &&
815
+ rendered.at(-1) !== "...") {
816
+ rendered.push("...");
817
+ }
818
+ rendered.push(`${line.lineNumber}: ${trimEvidenceLine(line.text)}`);
819
+ previousRenderedLine = line;
820
+ }
821
+ }
822
+ return rendered.join("\n");
823
+ }
824
+ function evidenceTermsForTask(task) {
825
+ return task
826
+ .toLowerCase()
827
+ .split(/[^a-z0-9_]+/)
828
+ .filter((term) => term.length >= 4)
829
+ .slice(0, 8);
830
+ }
831
+ function evidenceLineScore(line, terms, _path) {
832
+ const normalized = line.toLowerCase();
833
+ let score = 0;
834
+ for (const term of terms) {
835
+ if (normalized.includes(term.toLowerCase())) {
836
+ score += 10;
837
+ }
838
+ }
839
+ if (score === 0) {
840
+ return 0;
841
+ }
842
+ if (/^\s*import\b/.test(line)) {
843
+ score -= 20;
844
+ }
845
+ if (/^\s*(const|let|return|if|await|async|def|function|type|interface)\b/.test(line)) {
846
+ score += 4;
847
+ }
848
+ if (/[.=:(]\s*[^=]|=>|append|values|request|response|onChange|value=/.test(line)) {
849
+ score += 3;
850
+ }
851
+ return score;
852
+ }
853
+ function trimEvidenceLine(line) {
854
+ const maxLength = 180;
855
+ if (line.length <= maxLength) {
856
+ return line;
857
+ }
858
+ return `${line.slice(0, maxLength - 3)}...`;
859
+ }
860
+ function isClosurePath(path) {
861
+ const normalized = path.toLowerCase();
862
+ const basename = normalized.split("/").at(-1) ?? normalized;
863
+ return (normalized.includes("/types/") ||
864
+ normalized.includes("/schemas/") ||
865
+ normalized.includes("/constants.") ||
866
+ normalized.includes("/config.") ||
867
+ normalized.includes("/querykeys.") ||
868
+ basename.endsWith(".types.ts") ||
869
+ basename === "types.ts" ||
870
+ basename === "schema.ts" ||
871
+ basename === "schemas.ts" ||
872
+ basename === "constants.ts" ||
873
+ basename === "constants.py" ||
874
+ basename === "config.ts" ||
875
+ basename === "config.py" ||
876
+ basename === "querykeys.ts");
877
+ }
878
+ function renderRepositoryShape(input) {
879
+ const { tree, selected, showRootLabels } = input;
880
+ if (tree.length === 0) {
881
+ return "- No files discovered.";
882
+ }
883
+ const selectedKeys = selectedFileKeys(selected);
884
+ const selectedTree = tree.filter((file) => selectedKeys.has(fileKey(file)));
885
+ if (selectedTree.length === 0) {
886
+ return "- Full repository shape is available in tree.json; no selected files were present in the discovered tree.";
887
+ }
888
+ return [
889
+ "- Full repository shape is available in tree.json; inline shape is limited to selected files.",
890
+ ...selectedTree
891
+ .map((file) => {
892
+ const flags = [
893
+ file.eligible ? "eligible" : "omitted",
894
+ file.content_eligible ? "content" : "metadata-only",
895
+ ].join(", ");
896
+ return `- ${renderRootPrefix(file.root_index, showRootLabels)}${file.path} (${file.size_bytes} bytes; ${flags})`;
897
+ }),
898
+ ].join("\n");
899
+ }
900
+ function renderSearchEvidence(input) {
901
+ const { search, selected, showRootLabels } = input;
902
+ if (search.length === 0) {
903
+ return "- No search hits recorded.";
904
+ }
905
+ const selectedPathKeys = selectedFileKeys(selected);
906
+ const selectedHits = search.filter((record) => selectedPathKeys.has(fileKey(record)));
907
+ const repoWideHits = search.filter((record) => !selectedPathKeys.has(fileKey(record)));
908
+ const lines = [];
909
+ lines.push(renderSelectedSearchSummary(selectedHits, showRootLabels));
910
+ if (repoWideHits.length > 0) {
911
+ lines.push(`- Repo-wide hits suppressed from inline bundle: ${repoWideHits.length} hits across ${countSearchPaths(repoWideHits)} unselected files; see search.jsonl.`);
912
+ }
913
+ return lines.join("\n");
914
+ }
915
+ function renderSelectedSearchSummary(selectedHits, showRootLabels) {
916
+ if (selectedHits.length === 0) {
917
+ return "- Selected-file hits: none.";
918
+ }
919
+ const countByPath = new Map();
920
+ for (const record of selectedHits) {
921
+ const path = `${renderRootPrefix(record.root_index, showRootLabels)}${record.path}`;
922
+ countByPath.set(path, (countByPath.get(path) ?? 0) + 1);
923
+ }
924
+ const topPaths = [...countByPath.entries()]
925
+ .sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]))
926
+ .slice(0, 12)
927
+ .map(([path, count]) => `${path}=${count}`)
928
+ .join(", ");
929
+ const suppressed = countByPath.size > 12 ? `; ${countByPath.size - 12} more selected files in search.jsonl` : "";
930
+ return `- Selected-file hits: ${selectedHits.length} hits across ${countByPath.size} selected files (${topPaths}${suppressed}).`;
931
+ }
932
+ function countSearchPaths(search) {
933
+ return new Set(search.map(fileKey)).size;
934
+ }
935
+ function renderFileContext(selected, search, showRootLabels) {
936
+ if (selected.length === 0) {
937
+ return "No file context selected.";
938
+ }
939
+ const totalRanges = selected.reduce((total, file) => total + file.ranges.length, 0);
940
+ const totalBytes = selected.reduce((total, file) => total + file.bytes, 0);
941
+ const previewFiles = selected.slice(0, 12).map((file) => {
942
+ const ranges = file.ranges
943
+ .slice(0, 4)
944
+ .map((range) => `${range.start_line}-${range.end_line}`)
945
+ .join(", ");
946
+ const suffix = file.ranges.length > 4 ? ` +${file.ranges.length - 4}` : "";
947
+ return `- ${renderRootPrefix(file.root_index, showRootLabels)}${file.path}: ${ranges}${suffix}`;
948
+ });
949
+ const hidden = selected.length > previewFiles.length
950
+ ? [`- ${selected.length - previewFiles.length} more selected files are listed in manifest.json and selected-context.jsonl.`]
951
+ : [];
952
+ const selectedHitPreviews = renderSelectedHitPreviews({
953
+ selected,
954
+ search,
955
+ showRootLabels,
956
+ });
957
+ const selectedRangeLandmarks = selected.length > 12
958
+ ? []
959
+ : renderSelectedRangeLandmarks({
960
+ selected,
961
+ showRootLabels,
962
+ });
963
+ const selectedCodemapOutlines = selected.length > 12
964
+ ? []
965
+ : renderSelectedCodemapOutlines({
966
+ selected,
967
+ showRootLabels,
968
+ });
969
+ return [
970
+ "- Full selected source is stored in `selected-context.jsonl`; `slices.jsonl` is the bounded candidate/debug universe and may include unselected files or ranges.",
971
+ `- Selected source payload: ${selected.length} files, ${totalRanges} ranges, ${totalBytes} bytes before artifact serialization.`,
972
+ "- Range index:",
973
+ ...previewFiles,
974
+ ...hidden,
975
+ ...(selectedRangeLandmarks.length === 0
976
+ ? []
977
+ : ["", "- Range landmarks:", ...selectedRangeLandmarks]),
978
+ ...(selectedCodemapOutlines.length === 0
979
+ ? []
980
+ : ["", "- Codemap outlines:", ...selectedCodemapOutlines]),
981
+ ...(selected.length > 12 || selectedHitPreviews.length === 0
982
+ ? []
983
+ : ["", "- Selected hit previews:", ...selectedHitPreviews]),
984
+ ].join("\n");
985
+ }
986
+ function renderSelectedRangeLandmarks(input) {
987
+ const rendered = [];
988
+ const seen = new Set();
989
+ for (const file of input.selected) {
990
+ if (isCodemapOnlyDisposition(file.disposition)) {
991
+ continue;
992
+ }
993
+ let fileCount = 0;
994
+ const rangeLines = splitSelectedFileContentByRange(file);
995
+ file.ranges.forEach((range, rangeIndex) => {
996
+ const lines = rangeLines[rangeIndex] ?? [];
997
+ let rangeCount = 0;
998
+ lines.forEach((line, offset) => {
999
+ const preview = line.trim();
1000
+ if (preview.length === 0 || !isRangeLandmarkLine(preview)) {
1001
+ return;
1002
+ }
1003
+ const lineNumber = range.start_line + offset;
1004
+ const key = `${file.root_index}\u0000${file.path}\u0000${lineNumber}\u0000${preview}`;
1005
+ if (seen.has(key)) {
1006
+ return;
1007
+ }
1008
+ seen.add(key);
1009
+ rendered.push(` - ${renderRootPrefix(file.root_index, input.showRootLabels)}${file.path}:${lineNumber} ${preview}`);
1010
+ fileCount += 1;
1011
+ rangeCount += 1;
1012
+ });
1013
+ });
1014
+ if (fileCount >= 16 || rendered.length >= 48) {
1015
+ break;
1016
+ }
1017
+ }
1018
+ return rendered.slice(0, 48);
1019
+ }
1020
+ function isRangeLandmarkLine(line) {
1021
+ return symbolsFromLine(line).length > 0;
1022
+ }
1023
+ function renderSelectedCodemapOutlines(input) {
1024
+ const rendered = [];
1025
+ for (const file of input.selected) {
1026
+ if (!isCodemapOnlyDisposition(file.disposition)) {
1027
+ continue;
1028
+ }
1029
+ const map = selectedFileCodemap(file);
1030
+ const prefix = renderRootPrefix(file.root_index, input.showRootLabels);
1031
+ if (map.symbols.length === 0) {
1032
+ rendered.push(` - ${prefix}${file.path}: no symbols detected`);
1033
+ continue;
1034
+ }
1035
+ rendered.push(` - ${prefix}${file.path}:`);
1036
+ rendered.push(...map.symbols
1037
+ .slice(0, 24)
1038
+ .map((symbol) => ` - ${renderCodemapSymbolLine(symbol)}`));
1039
+ if (map.symbols.length > 24) {
1040
+ rendered.push(` - +${map.symbols.length - 24} more symbols`);
1041
+ }
1042
+ }
1043
+ return rendered;
1044
+ }
1045
+ function selectedFileCodemap(file) {
1046
+ return remapCodemapToSourceCoordinates(buildFileCodemap(file.path, file.content), file.ranges);
1047
+ }
1048
+ function renderCodemapSymbolLine(symbol) {
1049
+ return `${symbol.kind} ${symbol.name} ${singleRangeLabel({
1050
+ start_line: symbol.start_line,
1051
+ end_line: symbol.end_line,
1052
+ })}`;
1053
+ }
1054
+ function isCodemapOnlyDisposition(disposition) {
1055
+ return disposition === "codemap_only";
1056
+ }
1057
+ function renderSelectedHitPreviews(input) {
1058
+ const selectedPaths = new Set(input.selected
1059
+ .filter((file) => !isCodemapOnlyDisposition(file.disposition))
1060
+ .map((file) => `${file.root_index}\u0000${file.path}`));
1061
+ const rendered = [];
1062
+ const seen = new Set();
1063
+ const perFileCount = new Map();
1064
+ for (const record of input.search) {
1065
+ const fileKey = `${record.root_index}\u0000${record.path}`;
1066
+ if (!selectedPaths.has(fileKey)) {
1067
+ continue;
1068
+ }
1069
+ if ((perFileCount.get(fileKey) ?? 0) >= 4) {
1070
+ continue;
1071
+ }
1072
+ const preview = record.preview.trim();
1073
+ if (preview.length === 0) {
1074
+ continue;
1075
+ }
1076
+ const hitKey = `${fileKey}\u0000${record.line}\u0000${preview}`;
1077
+ if (seen.has(hitKey)) {
1078
+ continue;
1079
+ }
1080
+ seen.add(hitKey);
1081
+ perFileCount.set(fileKey, (perFileCount.get(fileKey) ?? 0) + 1);
1082
+ rendered.push(` - ${renderRootPrefix(record.root_index, input.showRootLabels)}${record.path}:${record.line}:${record.column} matches "${record.search_term}": ${preview}`);
1083
+ if (rendered.length >= 24) {
1084
+ break;
1085
+ }
1086
+ }
1087
+ return rendered;
1088
+ }
1089
+ function renderRootPrefix(rootIndex, showRootLabels) {
1090
+ return showRootLabels ? `root ${rootIndex}: ` : "";
1091
+ }
1092
+ function renderOpenQuestions(questions) {
1093
+ if (questions.length === 0) {
1094
+ return "- None.";
1095
+ }
1096
+ return questions.map((question) => `- ${question}`).join("\n");
1097
+ }
1098
+ function renderOmissionsAndBudgetNotes(input) {
1099
+ const maxMaterialOmissions = 12;
1100
+ const maxPathsPerMaterialOmission = 5;
1101
+ const notes = [];
1102
+ notes.push(`- Metrics: selected ${input.metrics.files_selected} files, recorded ${input.omissions.length} omissions, estimated ${input.metrics.estimated_tokens} tokens.`);
1103
+ if (input.metrics.truncated) {
1104
+ notes.push("- Output was truncated or budget-limited.");
1105
+ }
1106
+ for (const warning of input.warnings.filter(isHumanUsefulWarning)) {
1107
+ notes.push(`- Warning ${warning.code}: ${warning.message}`);
1108
+ }
1109
+ const materialOmissions = input.omissions.filter(isMaterialOmission);
1110
+ const incidentalOmissions = input.omissions.filter((omission) => !isMaterialOmission(omission));
1111
+ if (materialOmissions.length > 0) {
1112
+ notes.push("- Material omissions:");
1113
+ }
1114
+ for (const omission of materialOmissions.slice(0, maxMaterialOmissions)) {
1115
+ notes.push(` - ${humanOmissionReason(omission.reason)}: ${omission.message}${renderOmissionPathSuffix(omission.paths, maxPathsPerMaterialOmission)}`);
1116
+ }
1117
+ if (materialOmissions.length > maxMaterialOmissions) {
1118
+ const hidden = materialOmissions.length - maxMaterialOmissions;
1119
+ const countByReason = summarizeOmissionReasons(materialOmissions.slice(maxMaterialOmissions));
1120
+ notes.push(` - ${hidden} additional material omissions summarized: ${countByReason}. Full details are in manifest.json and summary.json.`);
1121
+ }
1122
+ if (incidentalOmissions.length > 0) {
1123
+ notes.push(`- Incidental omissions summarized: ${summarizeOmissionReasons(incidentalOmissions)}.`);
1124
+ }
1125
+ return notes.join("\n");
1126
+ }
1127
+ function isHumanUsefulWarning(warning) {
1128
+ if (warning.code === "delegate_curator_warning" ||
1129
+ warning.code === "delegate_finalizer_warning") {
1130
+ const normalized = warning.message.toLowerCase();
1131
+ return !(normalized.includes("no filesystem inspection") ||
1132
+ normalized.includes("no filesystem discovery") ||
1133
+ normalized.includes("budget-pruned") ||
1134
+ normalized.includes("packet-provided") ||
1135
+ normalized.includes("packet candidates") ||
1136
+ normalized.includes("packet.candidates") ||
1137
+ normalized.includes("candidate ids and ranges") ||
1138
+ normalized.includes("packet budget") ||
1139
+ normalized.includes("packet ranges") ||
1140
+ normalized.includes("packet did not provide complete source") ||
1141
+ normalized.includes("partial because the packet") ||
1142
+ normalized.includes("empty excerpts") ||
1143
+ normalized.includes("large files were kept") ||
1144
+ normalized.includes("excerpt-only for many slices") ||
1145
+ normalized.includes("packet authority was enforced") ||
1146
+ normalized.includes("curator selected fewer local candidates") ||
1147
+ normalized.includes("server-expanded") ||
1148
+ normalized.includes("server-retained") ||
1149
+ normalized.includes("server-evicted") ||
1150
+ normalized.includes("full ranges were selected") ||
1151
+ normalized.includes("selection intentionally keeps deterministic candidates") ||
1152
+ normalized.includes("full source") ||
1153
+ normalized.includes("full excerpts") ||
1154
+ normalized.includes("expected anchor") ||
1155
+ normalized.includes("intentionally excluded") ||
1156
+ normalized.includes("intentionally excludes") ||
1157
+ normalized.includes("broad search") ||
1158
+ normalized.includes("search spillover") ||
1159
+ normalized.includes("packet slices") ||
1160
+ normalized.includes("short packet ranges") ||
1161
+ normalized.includes("narrow ranges") ||
1162
+ normalized.includes("search-discovered candidates") ||
1163
+ normalized.includes("partial deterministic ranges") ||
1164
+ normalized.includes("sparse for many deterministic ranges") ||
1165
+ normalized.includes("narrow eligible ranges") ||
1166
+ normalized.includes("targeted slices"));
1167
+ }
1168
+ return true;
1169
+ }
1170
+ function renderOmissionPathSuffix(paths, limit) {
1171
+ if (paths == null || paths.length === 0) {
1172
+ return "";
1173
+ }
1174
+ const uniquePaths = [...new Set(paths)];
1175
+ const rendered = uniquePaths.slice(0, limit);
1176
+ const omitted = uniquePaths.length - rendered.length;
1177
+ return ` (${rendered.join(", ")}${omitted > 0 ? ` +${omitted} more` : ""})`;
1178
+ }
1179
+ function humanOmissionReason(reason) {
1180
+ if (reason === "target_estimated_tokens") {
1181
+ return "budget-limited";
1182
+ }
1183
+ if (reason === "max_files") {
1184
+ return "file-count-limited";
1185
+ }
1186
+ if (reason === "max_total_bytes" || reason === "max_bytes_per_file") {
1187
+ return "byte-budget-limited";
1188
+ }
1189
+ return reason;
1190
+ }
1191
+ function summarizeOmissionReasons(omissions) {
1192
+ const countByReason = new Map();
1193
+ for (const omission of omissions) {
1194
+ const reason = humanOmissionReason(omission.reason);
1195
+ countByReason.set(reason, (countByReason.get(reason) ?? 0) + 1);
1196
+ }
1197
+ return [...countByReason.entries()]
1198
+ .sort(([left], [right]) => left.localeCompare(right))
1199
+ .map(([reason, count]) => `${reason}=${count}`)
1200
+ .join(", ");
1201
+ }
1202
+ function isMaterialOmission(omission) {
1203
+ if (new Set([
1204
+ "binary_file",
1205
+ "content_secret",
1206
+ "exclude_glob",
1207
+ "secret_path",
1208
+ "symlink",
1209
+ ]).has(omission.reason)) {
1210
+ return false;
1211
+ }
1212
+ return omissionEventBaseFromReason(omission.reason).material === true;
1213
+ }
1214
+ function reconcileSelectedOmissions(omissions, selected) {
1215
+ if (omissions.length === 0 || selected.length === 0) {
1216
+ return [...omissions];
1217
+ }
1218
+ const selectedKeys = selectedFileKeys(selected);
1219
+ const selectedPaths = new Set(selected.map((file) => file.path));
1220
+ const reconciled = [];
1221
+ for (const omission of omissions) {
1222
+ if (omission.paths == null || omission.paths.length === 0) {
1223
+ reconciled.push(omission);
1224
+ continue;
1225
+ }
1226
+ const paths = omission.paths.filter((path) => {
1227
+ if (omission.root_index == null) {
1228
+ return !selectedPaths.has(path);
1229
+ }
1230
+ return !selectedKeys.has(fileKey({ root_index: omission.root_index, path }));
1231
+ });
1232
+ if (paths.length > 0) {
1233
+ reconciled.push({ ...omission, paths });
1234
+ }
1235
+ }
1236
+ return reconciled;
1237
+ }
1238
+ function filterTaskPresentationOmissions(omissions, _task) {
1239
+ return [...omissions];
1240
+ }
1241
+ function filterTaskPresentationSelected(selected, _task) {
1242
+ return [...selected];
1243
+ }
1244
+ function promoteTaskPresentationEvidence(selected, _task, _slices) {
1245
+ return [...selected];
1246
+ }
1247
+ function reconcileSelectedOpenQuestions(questions, selected) {
1248
+ if (questions.length === 0 || selected.length === 0) {
1249
+ return [...questions];
1250
+ }
1251
+ const refs = selectedQuestionReferences(selected);
1252
+ return questions.filter((question) => {
1253
+ if (isConceptualQuestionAnsweredBySelectedContext(question, selected)) {
1254
+ return false;
1255
+ }
1256
+ if (!isSelectedEvidenceQuestion(question)) {
1257
+ return true;
1258
+ }
1259
+ return !questionReferencesSelectedContext(question, refs);
1260
+ });
1261
+ }
1262
+ function buildPresentationOpenQuestions(questions, selected, omissions) {
1263
+ const reconciled = reconcileSelectedOpenQuestions(questions, selected);
1264
+ const seen = new Set(reconciled);
1265
+ const output = [...reconciled];
1266
+ for (const question of omissionFollowUpQuestions(omissions)) {
1267
+ if (seen.has(question)) {
1268
+ continue;
1269
+ }
1270
+ seen.add(question);
1271
+ output.push(question);
1272
+ if (output.length >= 20) {
1273
+ break;
1274
+ }
1275
+ }
1276
+ return output;
1277
+ }
1278
+ function omissionFollowUpQuestions(omissions) {
1279
+ return omissions
1280
+ .filter(isMaterialOmission)
1281
+ .slice(0, 3)
1282
+ .map((omission) => {
1283
+ const reason = humanOmissionReason(omission.reason);
1284
+ const paths = renderOmissionQuestionPaths(omission.paths);
1285
+ if (paths.length === 0) {
1286
+ return `What task-relevant evidence is missing from the ${reason} omission: ${omission.message}?`;
1287
+ }
1288
+ return `Can the omitted ${reason} paths (${paths}) change the answer, risk assessment, or required tests for this task?`;
1289
+ });
1290
+ }
1291
+ function renderOmissionQuestionPaths(paths) {
1292
+ if (paths == null || paths.length === 0) {
1293
+ return "";
1294
+ }
1295
+ const uniquePaths = [...new Set(paths)];
1296
+ const rendered = uniquePaths.slice(0, 3);
1297
+ const omitted = uniquePaths.length - rendered.length;
1298
+ return `${rendered.join(", ")}${omitted > 0 ? ` +${omitted} more` : ""}`;
1299
+ }
1300
+ function isConceptualQuestionAnsweredBySelectedContext(_question, _selected) {
1301
+ return false;
1302
+ }
1303
+ function isSelectedEvidenceQuestion(question) {
1304
+ return /\b(?:missing|missed|omitted|not selected|not present|unavailable|outside packet|need|needs|verify|confirm|include|includes|contain|contains|selected|available|additional|represented|constraints?|excerpt)\b/i.test(question);
1305
+ }
1306
+ function selectedQuestionReferences(selected) {
1307
+ const refs = new Set();
1308
+ for (const file of selected) {
1309
+ for (const value of selectedQuestionReferenceValues(file.path)) {
1310
+ const normalized = normalizeQuestionReference(value);
1311
+ if (isConcreteQuestionReference(normalized)) {
1312
+ refs.add(normalized);
1313
+ }
1314
+ }
1315
+ }
1316
+ return refs;
1317
+ }
1318
+ function selectedQuestionReferenceValues(path) {
1319
+ const parts = path.split("/");
1320
+ const basename = parts.at(-1) ?? path;
1321
+ const stem = basename.split(".")[0] ?? basename;
1322
+ return [path, basename, stem];
1323
+ }
1324
+ function questionReferencesSelectedContext(question, refs) {
1325
+ const normalized = normalizeQuestionReference(question);
1326
+ for (const ref of refs) {
1327
+ if (normalized.includes(ref)) {
1328
+ return true;
1329
+ }
1330
+ }
1331
+ return false;
1332
+ }
1333
+ function normalizeQuestionReference(value) {
1334
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "");
1335
+ }
1336
+ function isConcreteQuestionReference(value) {
1337
+ if (value.length < 4) {
1338
+ return false;
1339
+ }
1340
+ return !new Set([
1341
+ "backend",
1342
+ "frontend",
1343
+ "schema",
1344
+ "schemas",
1345
+ "service",
1346
+ "services",
1347
+ "source",
1348
+ "test",
1349
+ "tests",
1350
+ "types",
1351
+ ]).has(value);
1352
+ }
1353
+ function selectedFileKeys(selected) {
1354
+ return new Set(selected.map(fileKey));
1355
+ }
1356
+ function fileKey(file) {
1357
+ return `${file.root_index}\u0000${file.path}`;
1358
+ }
1359
+ function boundOpenQuestions(questions) {
1360
+ return questions.slice(0, 20).map((question) => sanitizeDiagnosticText(typeof question === "string" ? question : question.question));
1361
+ }
1362
+ function omissionEventFromDiagnostic(omission) {
1363
+ const base = omissionEventBaseFromReason(omission.reason);
1364
+ const rootIndex = omission.root_index;
1365
+ return {
1366
+ ...base,
1367
+ ...(rootIndex !== undefined && Number.isInteger(rootIndex) && rootIndex >= 0
1368
+ ? { root_index: rootIndex }
1369
+ : {}),
1370
+ ...(omission.paths == null || omission.paths.length === 0
1371
+ ? {}
1372
+ : { paths: [...omission.paths] }),
1373
+ };
1374
+ }
1375
+ function warningEventFromDiagnostic(warning) {
1376
+ return {
1377
+ reason: "non_material_notice",
1378
+ material: false,
1379
+ code: warning.code,
1380
+ message: warning.message,
1381
+ };
1382
+ }
1383
+ function omissionEventBaseFromReason(reason) {
1384
+ if (reason === "excluded" ||
1385
+ reason === "exclude_glob" ||
1386
+ reason === "caller_include_glob" ||
1387
+ reason === "symlink_omitted" ||
1388
+ reason === "symlink_file" ||
1389
+ reason === "binary_file" ||
1390
+ reason === "duplicate_root") {
1391
+ return { reason: "incidental_skip", material: false };
1392
+ }
1393
+ if (reason === "noisy_file" ||
1394
+ reason === "default_exclude" ||
1395
+ reason === "default_noisy_exclude") {
1396
+ return { reason: "default_noisy_exclude", material: false };
1397
+ }
1398
+ if (reason === "focus_sliced" || reason === "focus_over_cap") {
1399
+ return { reason: "budget_omission", material: true };
1400
+ }
1401
+ if (reason.includes("secret")) {
1402
+ return { reason: "secret_skip", material: true };
1403
+ }
1404
+ if (reason.includes("unreadable")) {
1405
+ return { reason: "unreadable_file", material: true };
1406
+ }
1407
+ if (reason.includes("max_scan_files") ||
1408
+ reason.includes("max_discovery_bytes") ||
1409
+ reason.includes("max_candidate") ||
1410
+ reason.includes("discovery_byte_cap") ||
1411
+ reason.includes("candidate_cap") ||
1412
+ reason.includes("search_cap") ||
1413
+ reason.includes("scan_cap")) {
1414
+ return { reason: "cap_omission", material: true };
1415
+ }
1416
+ if (reason.startsWith("max_") ||
1417
+ reason.includes("budget") ||
1418
+ reason === "target_estimated_tokens" ||
1419
+ reason === "file_too_large") {
1420
+ return { reason: "budget_omission", material: true };
1421
+ }
1422
+ return { reason: "requested_evidence_omission", material: true };
1423
+ }
1424
+ function boundDebugDiagnostics(diagnostics, caps) {
1425
+ if (diagnostics == null) {
1426
+ return {};
1427
+ }
1428
+ return {
1429
+ ...(diagnostics.notes == null
1430
+ ? {}
1431
+ : {
1432
+ notes: diagnostics.notes
1433
+ .slice(0, caps.max_warnings)
1434
+ .map((note) => sanitizeDiagnosticText(note)),
1435
+ }),
1436
+ ...(diagnostics.counters == null
1437
+ ? {}
1438
+ : { counters: sanitizeCounters(diagnostics.counters) }),
1439
+ };
1440
+ }
1441
+ function sanitizeCounters(counters) {
1442
+ return Object.fromEntries(Object.entries(counters)
1443
+ .slice(0, 50)
1444
+ .map(([key, value]) => [
1445
+ sanitizeDiagnosticText(key),
1446
+ typeof value === "string" ? sanitizeDiagnosticText(value) : value,
1447
+ ]));
1448
+ }
1449
+ function renderJsonl(records) {
1450
+ return records.map((record) => JSON.stringify(record)).join("\n")
1451
+ + (records.length === 0 ? "" : "\n");
1452
+ }
1453
+ function validateTaskForRendering(task, allowSecrets) {
1454
+ assertTaskSecretsGated(task, allowSecrets);
1455
+ return task;
1456
+ }
1457
+ function safePath(path, allowSecrets) {
1458
+ if (allowSecrets) {
1459
+ return path;
1460
+ }
1461
+ return boundContextBuilderPathList([path], 1)[0] ?? "[redacted-sensitive-path]";
1462
+ }
1463
+ function safeContent(content, allowSecrets) {
1464
+ if (allowSecrets) {
1465
+ return content;
1466
+ }
1467
+ return hasConservativeResidualSecret(content)
1468
+ ? "[redacted-sensitive-content]"
1469
+ : content;
1470
+ }
1471
+ function sanitizeJsonValue(value, allowSecrets) {
1472
+ if (typeof value === "string") {
1473
+ const pathSafe = safePath(value, allowSecrets);
1474
+ return pathSafe === "[redacted-sensitive-path]"
1475
+ ? pathSafe
1476
+ : sanitizeDiagnosticText(value, allowSecrets);
1477
+ }
1478
+ if (typeof value === "number" || typeof value === "boolean" || value == null) {
1479
+ return value;
1480
+ }
1481
+ if (Array.isArray(value)) {
1482
+ return value.slice(0, 200).map((item) => sanitizeJsonValue(item, allowSecrets));
1483
+ }
1484
+ if (typeof value === "object") {
1485
+ return Object.fromEntries(Object.entries(value)
1486
+ .slice(0, 200)
1487
+ .map(([key, entryValue]) => [
1488
+ sanitizeDiagnosticText(key, allowSecrets),
1489
+ sanitizeJsonValue(entryValue, allowSecrets),
1490
+ ]));
1491
+ }
1492
+ return String(value);
1493
+ }
1494
+ function markdownFenceFor(content) {
1495
+ const longest = Math.max(3, ...Array.from(content.matchAll(/`+/g), (match) => match[0].length + 1));
1496
+ return "`".repeat(longest);
1497
+ }
1498
+ //# sourceMappingURL=bundle.js.map