@n-dx/web 0.1.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 (671) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +5 -0
  3. package/build.js +243 -0
  4. package/dist/cli/index.d.ts +8 -0
  5. package/dist/cli/index.js +50 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/landing/index.html +325 -0
  8. package/dist/landing/landing.d.ts +38 -0
  9. package/dist/landing/landing.js +299 -0
  10. package/dist/landing/landing.js.map +1 -0
  11. package/dist/public.d.ts +55 -0
  12. package/dist/public.js +51 -0
  13. package/dist/public.js.map +1 -0
  14. package/dist/schema/features.d.ts +28 -0
  15. package/dist/schema/features.js +9 -0
  16. package/dist/schema/features.js.map +1 -0
  17. package/dist/schema/v1.d.ts +317 -0
  18. package/dist/schema/v1.js +3 -0
  19. package/dist/schema/v1.js.map +1 -0
  20. package/dist/server/aggregation-cache.d.ts +105 -0
  21. package/dist/server/aggregation-cache.js +163 -0
  22. package/dist/server/aggregation-cache.js.map +1 -0
  23. package/dist/server/concurrent-execution-metrics.d.ts +103 -0
  24. package/dist/server/concurrent-execution-metrics.js +253 -0
  25. package/dist/server/concurrent-execution-metrics.js.map +1 -0
  26. package/dist/server/domain-gateway.d.ts +18 -0
  27. package/dist/server/domain-gateway.js +19 -0
  28. package/dist/server/domain-gateway.js.map +1 -0
  29. package/dist/server/incremental-task-usage.d.ts +92 -0
  30. package/dist/server/incremental-task-usage.js +251 -0
  31. package/dist/server/incremental-task-usage.js.map +1 -0
  32. package/dist/server/index.d.ts +39 -0
  33. package/dist/server/index.js +36 -0
  34. package/dist/server/index.js.map +1 -0
  35. package/dist/server/port.d.ts +96 -0
  36. package/dist/server/port.js +134 -0
  37. package/dist/server/port.js.map +1 -0
  38. package/dist/server/pr-markdown-refresh-diagnostics.d.ts +59 -0
  39. package/dist/server/pr-markdown-refresh-diagnostics.js +429 -0
  40. package/dist/server/pr-markdown-refresh-diagnostics.js.map +1 -0
  41. package/dist/server/prd-io.d.ts +40 -0
  42. package/dist/server/prd-io.js +66 -0
  43. package/dist/server/prd-io.js.map +1 -0
  44. package/dist/server/process-memory-tracker.d.ts +79 -0
  45. package/dist/server/process-memory-tracker.js +194 -0
  46. package/dist/server/process-memory-tracker.js.map +1 -0
  47. package/dist/server/register-scheduler.d.ts +53 -0
  48. package/dist/server/register-scheduler.js +36 -0
  49. package/dist/server/register-scheduler.js.map +1 -0
  50. package/dist/server/rex-gateway.d.ts +39 -0
  51. package/dist/server/rex-gateway.js +47 -0
  52. package/dist/server/rex-gateway.js.map +1 -0
  53. package/dist/server/routes-adaptive.d.ts +21 -0
  54. package/dist/server/routes-adaptive.js +659 -0
  55. package/dist/server/routes-adaptive.js.map +1 -0
  56. package/dist/server/routes-config.d.ts +47 -0
  57. package/dist/server/routes-config.js +222 -0
  58. package/dist/server/routes-config.js.map +1 -0
  59. package/dist/server/routes-data.d.ts +14 -0
  60. package/dist/server/routes-data.js +129 -0
  61. package/dist/server/routes-data.js.map +1 -0
  62. package/dist/server/routes-features.d.ts +14 -0
  63. package/dist/server/routes-features.js +245 -0
  64. package/dist/server/routes-features.js.map +1 -0
  65. package/dist/server/routes-hench.d.ts +116 -0
  66. package/dist/server/routes-hench.js +2016 -0
  67. package/dist/server/routes-hench.js.map +1 -0
  68. package/dist/server/routes-integrations.d.ts +23 -0
  69. package/dist/server/routes-integrations.js +277 -0
  70. package/dist/server/routes-integrations.js.map +1 -0
  71. package/dist/server/routes-mcp.d.ts +31 -0
  72. package/dist/server/routes-mcp.js +175 -0
  73. package/dist/server/routes-mcp.js.map +1 -0
  74. package/dist/server/routes-notion.d.ts +23 -0
  75. package/dist/server/routes-notion.js +723 -0
  76. package/dist/server/routes-notion.js.map +1 -0
  77. package/dist/server/routes-project.d.ts +47 -0
  78. package/dist/server/routes-project.js +128 -0
  79. package/dist/server/routes-project.js.map +1 -0
  80. package/dist/server/routes-rex/analysis.d.ts +11 -0
  81. package/dist/server/routes-rex/analysis.js +583 -0
  82. package/dist/server/routes-rex/analysis.js.map +1 -0
  83. package/dist/server/routes-rex/execution.d.ts +37 -0
  84. package/dist/server/routes-rex/execution.js +355 -0
  85. package/dist/server/routes-rex/execution.js.map +1 -0
  86. package/dist/server/routes-rex/health.d.ts +8 -0
  87. package/dist/server/routes-rex/health.js +136 -0
  88. package/dist/server/routes-rex/health.js.map +1 -0
  89. package/dist/server/routes-rex/index.d.ts +35 -0
  90. package/dist/server/routes-rex/index.js +72 -0
  91. package/dist/server/routes-rex/index.js.map +1 -0
  92. package/dist/server/routes-rex/items.d.ts +8 -0
  93. package/dist/server/routes-rex/items.js +359 -0
  94. package/dist/server/routes-rex/items.js.map +1 -0
  95. package/dist/server/routes-rex/prune.d.ts +11 -0
  96. package/dist/server/routes-rex/prune.js +379 -0
  97. package/dist/server/routes-rex/prune.js.map +1 -0
  98. package/dist/server/routes-rex/reads.d.ts +9 -0
  99. package/dist/server/routes-rex/reads.js +119 -0
  100. package/dist/server/routes-rex/reads.js.map +1 -0
  101. package/dist/server/routes-rex/requirements.d.ts +10 -0
  102. package/dist/server/routes-rex/requirements.js +408 -0
  103. package/dist/server/routes-rex/requirements.js.map +1 -0
  104. package/dist/server/routes-rex/shared.d.ts +37 -0
  105. package/dist/server/routes-rex/shared.js +73 -0
  106. package/dist/server/routes-rex/shared.js.map +1 -0
  107. package/dist/server/routes-search.d.ts +26 -0
  108. package/dist/server/routes-search.js +82 -0
  109. package/dist/server/routes-search.js.map +1 -0
  110. package/dist/server/routes-sourcevision.d.ts +18 -0
  111. package/dist/server/routes-sourcevision.js +444 -0
  112. package/dist/server/routes-sourcevision.js.map +1 -0
  113. package/dist/server/routes-static.d.ts +20 -0
  114. package/dist/server/routes-static.js +168 -0
  115. package/dist/server/routes-static.js.map +1 -0
  116. package/dist/server/routes-status.d.ts +58 -0
  117. package/dist/server/routes-status.js +191 -0
  118. package/dist/server/routes-status.js.map +1 -0
  119. package/dist/server/routes-token-usage.d.ts +63 -0
  120. package/dist/server/routes-token-usage.js +720 -0
  121. package/dist/server/routes-token-usage.js.map +1 -0
  122. package/dist/server/routes-validation.d.ts +10 -0
  123. package/dist/server/routes-validation.js +365 -0
  124. package/dist/server/routes-validation.js.map +1 -0
  125. package/dist/server/routes-workflow.d.ts +15 -0
  126. package/dist/server/routes-workflow.js +498 -0
  127. package/dist/server/routes-workflow.js.map +1 -0
  128. package/dist/server/search-index.d.ts +111 -0
  129. package/dist/server/search-index.js +348 -0
  130. package/dist/server/search-index.js.map +1 -0
  131. package/dist/server/shared-types.d.ts +65 -0
  132. package/dist/server/shared-types.js +31 -0
  133. package/dist/server/shared-types.js.map +1 -0
  134. package/dist/server/start.d.ts +68 -0
  135. package/dist/server/start.js +568 -0
  136. package/dist/server/start.js.map +1 -0
  137. package/dist/server/task-usage.d.ts +17 -0
  138. package/dist/server/task-usage.js +20 -0
  139. package/dist/server/task-usage.js.map +1 -0
  140. package/dist/server/types.d.ts +27 -0
  141. package/dist/server/types.js +26 -0
  142. package/dist/server/types.js.map +1 -0
  143. package/dist/server/usage-cleanup-scheduler.d.ts +107 -0
  144. package/dist/server/usage-cleanup-scheduler.js +232 -0
  145. package/dist/server/usage-cleanup-scheduler.js.map +1 -0
  146. package/dist/server/websocket.d.ts +131 -0
  147. package/dist/server/websocket.js +512 -0
  148. package/dist/server/websocket.js.map +1 -0
  149. package/dist/shared/data-files.d.ts +17 -0
  150. package/dist/shared/data-files.js +18 -0
  151. package/dist/shared/data-files.js.map +1 -0
  152. package/dist/shared/index.d.ts +9 -0
  153. package/dist/shared/index.js +9 -0
  154. package/dist/shared/index.js.map +1 -0
  155. package/dist/shared/view-id.d.ts +8 -0
  156. package/dist/shared/view-id.js +9 -0
  157. package/dist/shared/view-id.js.map +1 -0
  158. package/dist/viewer/Hench-F.png +0 -0
  159. package/dist/viewer/Rex-F.png +0 -0
  160. package/dist/viewer/SourceVision-F.png +0 -0
  161. package/dist/viewer/SourceVision.png +0 -0
  162. package/dist/viewer/api.d.ts +19 -0
  163. package/dist/viewer/api.js +17 -0
  164. package/dist/viewer/api.js.map +1 -0
  165. package/dist/viewer/bootstrap.d.ts +13 -0
  166. package/dist/viewer/bootstrap.js +40 -0
  167. package/dist/viewer/bootstrap.js.map +1 -0
  168. package/dist/viewer/components/active-tasks-panel.d.ts +36 -0
  169. package/dist/viewer/components/active-tasks-panel.js +183 -0
  170. package/dist/viewer/components/active-tasks-panel.js.map +1 -0
  171. package/dist/viewer/components/breadcrumb.d.ts +21 -0
  172. package/dist/viewer/components/breadcrumb.js +117 -0
  173. package/dist/viewer/components/breadcrumb.js.map +1 -0
  174. package/dist/viewer/components/concurrency-panel.d.ts +18 -0
  175. package/dist/viewer/components/concurrency-panel.js +175 -0
  176. package/dist/viewer/components/concurrency-panel.js.map +1 -0
  177. package/dist/viewer/components/config-footer.d.ts +11 -0
  178. package/dist/viewer/components/config-footer.js +132 -0
  179. package/dist/viewer/components/config-footer.js.map +1 -0
  180. package/dist/viewer/components/constants.d.ts +10 -0
  181. package/dist/viewer/components/constants.js +11 -0
  182. package/dist/viewer/components/constants.js.map +1 -0
  183. package/dist/viewer/components/copy-link-button.d.ts +30 -0
  184. package/dist/viewer/components/copy-link-button.js +74 -0
  185. package/dist/viewer/components/copy-link-button.js.map +1 -0
  186. package/dist/viewer/components/crash-recovery-banner.d.ts +28 -0
  187. package/dist/viewer/components/crash-recovery-banner.js +47 -0
  188. package/dist/viewer/components/crash-recovery-banner.js.map +1 -0
  189. package/dist/viewer/components/data-display/collapsible-section.d.ts +14 -0
  190. package/dist/viewer/components/data-display/collapsible-section.js +66 -0
  191. package/dist/viewer/components/data-display/collapsible-section.js.map +1 -0
  192. package/dist/viewer/components/data-display/findings-list.d.ts +13 -0
  193. package/dist/viewer/components/data-display/findings-list.js +136 -0
  194. package/dist/viewer/components/data-display/findings-list.js.map +1 -0
  195. package/dist/viewer/components/data-display/health-gauge.d.ts +37 -0
  196. package/dist/viewer/components/data-display/health-gauge.js +62 -0
  197. package/dist/viewer/components/data-display/health-gauge.js.map +1 -0
  198. package/dist/viewer/components/data-display/mini-charts.d.ts +36 -0
  199. package/dist/viewer/components/data-display/mini-charts.js +124 -0
  200. package/dist/viewer/components/data-display/mini-charts.js.map +1 -0
  201. package/dist/viewer/components/data-display/tree-view.d.ts +18 -0
  202. package/dist/viewer/components/data-display/tree-view.js +107 -0
  203. package/dist/viewer/components/data-display/tree-view.js.map +1 -0
  204. package/dist/viewer/components/data-display/zone-map.d.ts +28 -0
  205. package/dist/viewer/components/data-display/zone-map.js +197 -0
  206. package/dist/viewer/components/data-display/zone-map.js.map +1 -0
  207. package/dist/viewer/components/degradation-banner.d.ts +28 -0
  208. package/dist/viewer/components/degradation-banner.js +47 -0
  209. package/dist/viewer/components/degradation-banner.js.map +1 -0
  210. package/dist/viewer/components/detail-panel.d.ts +12 -0
  211. package/dist/viewer/components/detail-panel.js +166 -0
  212. package/dist/viewer/components/detail-panel.js.map +1 -0
  213. package/dist/viewer/components/elapsed-time.d.ts +38 -0
  214. package/dist/viewer/components/elapsed-time.js +35 -0
  215. package/dist/viewer/components/elapsed-time.js.map +1 -0
  216. package/dist/viewer/components/faq.d.ts +12 -0
  217. package/dist/viewer/components/faq.js +237 -0
  218. package/dist/viewer/components/faq.js.map +1 -0
  219. package/dist/viewer/components/favicon.d.ts +30 -0
  220. package/dist/viewer/components/favicon.js +90 -0
  221. package/dist/viewer/components/favicon.js.map +1 -0
  222. package/dist/viewer/components/guide.d.ts +5 -0
  223. package/dist/viewer/components/guide.js +116 -0
  224. package/dist/viewer/components/guide.js.map +1 -0
  225. package/dist/viewer/components/index.d.ts +37 -0
  226. package/dist/viewer/components/index.js +46 -0
  227. package/dist/viewer/components/index.js.map +1 -0
  228. package/dist/viewer/components/logos.d.ts +42 -0
  229. package/dist/viewer/components/logos.js +46 -0
  230. package/dist/viewer/components/logos.js.map +1 -0
  231. package/dist/viewer/components/memory-panel.d.ts +19 -0
  232. package/dist/viewer/components/memory-panel.js +181 -0
  233. package/dist/viewer/components/memory-panel.js.map +1 -0
  234. package/dist/viewer/components/memory-warning.d.ts +23 -0
  235. package/dist/viewer/components/memory-warning.js +42 -0
  236. package/dist/viewer/components/memory-warning.js.map +1 -0
  237. package/dist/viewer/components/notion-schema-wizard.d.ts +16 -0
  238. package/dist/viewer/components/notion-schema-wizard.js +263 -0
  239. package/dist/viewer/components/notion-schema-wizard.js.map +1 -0
  240. package/dist/viewer/components/polling-suspension-indicator.d.ts +24 -0
  241. package/dist/viewer/components/polling-suspension-indicator.js +31 -0
  242. package/dist/viewer/components/polling-suspension-indicator.js.map +1 -0
  243. package/dist/viewer/components/prd-tree/add-item-form.d.ts +31 -0
  244. package/dist/viewer/components/prd-tree/add-item-form.js +231 -0
  245. package/dist/viewer/components/prd-tree/add-item-form.js.map +1 -0
  246. package/dist/viewer/components/prd-tree/analyze-panel.d.ts +13 -0
  247. package/dist/viewer/components/prd-tree/analyze-panel.js +245 -0
  248. package/dist/viewer/components/prd-tree/analyze-panel.js.map +1 -0
  249. package/dist/viewer/components/prd-tree/batch-import-panel.d.ts +34 -0
  250. package/dist/viewer/components/prd-tree/batch-import-panel.js +415 -0
  251. package/dist/viewer/components/prd-tree/batch-import-panel.js.map +1 -0
  252. package/dist/viewer/components/prd-tree/bulk-actions.d.ts +19 -0
  253. package/dist/viewer/components/prd-tree/bulk-actions.js +90 -0
  254. package/dist/viewer/components/prd-tree/bulk-actions.js.map +1 -0
  255. package/dist/viewer/components/prd-tree/compute.d.ts +32 -0
  256. package/dist/viewer/components/prd-tree/compute.js +129 -0
  257. package/dist/viewer/components/prd-tree/compute.js.map +1 -0
  258. package/dist/viewer/components/prd-tree/delete-confirmation.d.ts +23 -0
  259. package/dist/viewer/components/prd-tree/delete-confirmation.js +83 -0
  260. package/dist/viewer/components/prd-tree/delete-confirmation.js.map +1 -0
  261. package/dist/viewer/components/prd-tree/execution-panel.d.ts +14 -0
  262. package/dist/viewer/components/prd-tree/execution-panel.js +291 -0
  263. package/dist/viewer/components/prd-tree/execution-panel.js.map +1 -0
  264. package/dist/viewer/components/prd-tree/facet-filter.d.ts +40 -0
  265. package/dist/viewer/components/prd-tree/facet-filter.js +188 -0
  266. package/dist/viewer/components/prd-tree/facet-filter.js.map +1 -0
  267. package/dist/viewer/components/prd-tree/index.d.ts +24 -0
  268. package/dist/viewer/components/prd-tree/index.js +16 -0
  269. package/dist/viewer/components/prd-tree/index.js.map +1 -0
  270. package/dist/viewer/components/prd-tree/inline-add-form.d.ts +32 -0
  271. package/dist/viewer/components/prd-tree/inline-add-form.js +175 -0
  272. package/dist/viewer/components/prd-tree/inline-add-form.js.map +1 -0
  273. package/dist/viewer/components/prd-tree/inline-status-picker.d.ts +31 -0
  274. package/dist/viewer/components/prd-tree/inline-status-picker.js +110 -0
  275. package/dist/viewer/components/prd-tree/inline-status-picker.js.map +1 -0
  276. package/dist/viewer/components/prd-tree/lazy-children.d.ts +40 -0
  277. package/dist/viewer/components/prd-tree/lazy-children.js +73 -0
  278. package/dist/viewer/components/prd-tree/lazy-children.js.map +1 -0
  279. package/dist/viewer/components/prd-tree/levels.d.ts +31 -0
  280. package/dist/viewer/components/prd-tree/levels.js +72 -0
  281. package/dist/viewer/components/prd-tree/levels.js.map +1 -0
  282. package/dist/viewer/components/prd-tree/listener-lifecycle.d.ts +105 -0
  283. package/dist/viewer/components/prd-tree/listener-lifecycle.js +173 -0
  284. package/dist/viewer/components/prd-tree/listener-lifecycle.js.map +1 -0
  285. package/dist/viewer/components/prd-tree/merge-preview.d.ts +25 -0
  286. package/dist/viewer/components/prd-tree/merge-preview.js +181 -0
  287. package/dist/viewer/components/prd-tree/merge-preview.js.map +1 -0
  288. package/dist/viewer/components/prd-tree/prd-tree.d.ts +91 -0
  289. package/dist/viewer/components/prd-tree/prd-tree.js +565 -0
  290. package/dist/viewer/components/prd-tree/prd-tree.js.map +1 -0
  291. package/dist/viewer/components/prd-tree/proposal-editor.d.ts +44 -0
  292. package/dist/viewer/components/prd-tree/proposal-editor.js +438 -0
  293. package/dist/viewer/components/prd-tree/proposal-editor.js.map +1 -0
  294. package/dist/viewer/components/prd-tree/prune-confirmation.d.ts +25 -0
  295. package/dist/viewer/components/prd-tree/prune-confirmation.js +336 -0
  296. package/dist/viewer/components/prd-tree/prune-confirmation.js.map +1 -0
  297. package/dist/viewer/components/prd-tree/prune-diff-tree.d.ts +39 -0
  298. package/dist/viewer/components/prd-tree/prune-diff-tree.js +319 -0
  299. package/dist/viewer/components/prd-tree/prune-diff-tree.js.map +1 -0
  300. package/dist/viewer/components/prd-tree/reorganize-panel.d.ts +16 -0
  301. package/dist/viewer/components/prd-tree/reorganize-panel.js +213 -0
  302. package/dist/viewer/components/prd-tree/reorganize-panel.js.map +1 -0
  303. package/dist/viewer/components/prd-tree/smart-add-input.d.ts +19 -0
  304. package/dist/viewer/components/prd-tree/smart-add-input.js +383 -0
  305. package/dist/viewer/components/prd-tree/smart-add-input.js.map +1 -0
  306. package/dist/viewer/components/prd-tree/status-filter.d.ts +40 -0
  307. package/dist/viewer/components/prd-tree/status-filter.js +131 -0
  308. package/dist/viewer/components/prd-tree/status-filter.js.map +1 -0
  309. package/dist/viewer/components/prd-tree/task-detail.d.ts +41 -0
  310. package/dist/viewer/components/prd-tree/task-detail.js +1205 -0
  311. package/dist/viewer/components/prd-tree/task-detail.js.map +1 -0
  312. package/dist/viewer/components/prd-tree/task-utilization.d.ts +7 -0
  313. package/dist/viewer/components/prd-tree/task-utilization.js +25 -0
  314. package/dist/viewer/components/prd-tree/task-utilization.js.map +1 -0
  315. package/dist/viewer/components/prd-tree/tree-differ.d.ts +59 -0
  316. package/dist/viewer/components/prd-tree/tree-differ.js +200 -0
  317. package/dist/viewer/components/prd-tree/tree-differ.js.map +1 -0
  318. package/dist/viewer/components/prd-tree/tree-event-delegate.d.ts +70 -0
  319. package/dist/viewer/components/prd-tree/tree-event-delegate.js +176 -0
  320. package/dist/viewer/components/prd-tree/tree-event-delegate.js.map +1 -0
  321. package/dist/viewer/components/prd-tree/tree-search.d.ts +65 -0
  322. package/dist/viewer/components/prd-tree/tree-search.js +178 -0
  323. package/dist/viewer/components/prd-tree/tree-search.js.map +1 -0
  324. package/dist/viewer/components/prd-tree/tree-utils.d.ts +38 -0
  325. package/dist/viewer/components/prd-tree/tree-utils.js +107 -0
  326. package/dist/viewer/components/prd-tree/tree-utils.js.map +1 -0
  327. package/dist/viewer/components/prd-tree/types.d.ts +93 -0
  328. package/dist/viewer/components/prd-tree/types.js +16 -0
  329. package/dist/viewer/components/prd-tree/types.js.map +1 -0
  330. package/dist/viewer/components/prd-tree/virtual-scroll.d.ts +119 -0
  331. package/dist/viewer/components/prd-tree/virtual-scroll.js +169 -0
  332. package/dist/viewer/components/prd-tree/virtual-scroll.js.map +1 -0
  333. package/dist/viewer/components/progressive-loader.d.ts +114 -0
  334. package/dist/viewer/components/progressive-loader.js +225 -0
  335. package/dist/viewer/components/progressive-loader.js.map +1 -0
  336. package/dist/viewer/components/refresh-queue-status.d.ts +20 -0
  337. package/dist/viewer/components/refresh-queue-status.js +65 -0
  338. package/dist/viewer/components/refresh-queue-status.js.map +1 -0
  339. package/dist/viewer/components/rex-task-link.d.ts +50 -0
  340. package/dist/viewer/components/rex-task-link.js +218 -0
  341. package/dist/viewer/components/rex-task-link.js.map +1 -0
  342. package/dist/viewer/components/search-filter.d.ts +20 -0
  343. package/dist/viewer/components/search-filter.js +28 -0
  344. package/dist/viewer/components/search-filter.js.map +1 -0
  345. package/dist/viewer/components/search-overlay.d.ts +31 -0
  346. package/dist/viewer/components/search-overlay.js +472 -0
  347. package/dist/viewer/components/search-overlay.js.map +1 -0
  348. package/dist/viewer/components/sidebar.d.ts +18 -0
  349. package/dist/viewer/components/sidebar.js +357 -0
  350. package/dist/viewer/components/sidebar.js.map +1 -0
  351. package/dist/viewer/components/status-indicators.d.ts +63 -0
  352. package/dist/viewer/components/status-indicators.js +136 -0
  353. package/dist/viewer/components/status-indicators.js.map +1 -0
  354. package/dist/viewer/components/theme-toggle.d.ts +8 -0
  355. package/dist/viewer/components/theme-toggle.js +28 -0
  356. package/dist/viewer/components/theme-toggle.js.map +1 -0
  357. package/dist/viewer/components/throttle-controls.d.ts +18 -0
  358. package/dist/viewer/components/throttle-controls.js +304 -0
  359. package/dist/viewer/components/throttle-controls.js.map +1 -0
  360. package/dist/viewer/components/ws-health-panel.d.ts +18 -0
  361. package/dist/viewer/components/ws-health-panel.js +250 -0
  362. package/dist/viewer/components/ws-health-panel.js.map +1 -0
  363. package/dist/viewer/components/zone-slideout.d.ts +17 -0
  364. package/dist/viewer/components/zone-slideout.js +162 -0
  365. package/dist/viewer/components/zone-slideout.js.map +1 -0
  366. package/dist/viewer/crash/crash-detector.d.ts +69 -0
  367. package/dist/viewer/crash/crash-detector.js +239 -0
  368. package/dist/viewer/crash/crash-detector.js.map +1 -0
  369. package/dist/viewer/crash/index.d.ts +7 -0
  370. package/dist/viewer/crash/index.js +8 -0
  371. package/dist/viewer/crash/index.js.map +1 -0
  372. package/dist/viewer/deployed-mode.d.ts +37 -0
  373. package/dist/viewer/deployed-mode.js +94 -0
  374. package/dist/viewer/deployed-mode.js.map +1 -0
  375. package/dist/viewer/external.d.ts +17 -0
  376. package/dist/viewer/external.js +17 -0
  377. package/dist/viewer/external.js.map +1 -0
  378. package/dist/viewer/graph/index.d.ts +9 -0
  379. package/dist/viewer/graph/index.js +12 -0
  380. package/dist/viewer/graph/index.js.map +1 -0
  381. package/dist/viewer/graph/physics.d.ts +96 -0
  382. package/dist/viewer/graph/physics.js +366 -0
  383. package/dist/viewer/graph/physics.js.map +1 -0
  384. package/dist/viewer/graph/renderer.d.ts +184 -0
  385. package/dist/viewer/graph/renderer.js +1438 -0
  386. package/dist/viewer/graph/renderer.js.map +1 -0
  387. package/dist/viewer/hooks/index.d.ts +27 -0
  388. package/dist/viewer/hooks/index.js +28 -0
  389. package/dist/viewer/hooks/index.js.map +1 -0
  390. package/dist/viewer/hooks/use-app-data.d.ts +31 -0
  391. package/dist/viewer/hooks/use-app-data.js +152 -0
  392. package/dist/viewer/hooks/use-app-data.js.map +1 -0
  393. package/dist/viewer/hooks/use-crash-recovery.d.ts +50 -0
  394. package/dist/viewer/hooks/use-crash-recovery.js +76 -0
  395. package/dist/viewer/hooks/use-crash-recovery.js.map +1 -0
  396. package/dist/viewer/hooks/use-delete-actions.d.ts +48 -0
  397. package/dist/viewer/hooks/use-delete-actions.js +103 -0
  398. package/dist/viewer/hooks/use-delete-actions.js.map +1 -0
  399. package/dist/viewer/hooks/use-dom-performance-monitor.d.ts +68 -0
  400. package/dist/viewer/hooks/use-dom-performance-monitor.js +71 -0
  401. package/dist/viewer/hooks/use-dom-performance-monitor.js.map +1 -0
  402. package/dist/viewer/hooks/use-facet-state.d.ts +32 -0
  403. package/dist/viewer/hooks/use-facet-state.js +119 -0
  404. package/dist/viewer/hooks/use-facet-state.js.map +1 -0
  405. package/dist/viewer/hooks/use-feature-toggle.d.ts +18 -0
  406. package/dist/viewer/hooks/use-feature-toggle.js +57 -0
  407. package/dist/viewer/hooks/use-feature-toggle.js.map +1 -0
  408. package/dist/viewer/hooks/use-file-edges.d.ts +23 -0
  409. package/dist/viewer/hooks/use-file-edges.js +221 -0
  410. package/dist/viewer/hooks/use-file-edges.js.map +1 -0
  411. package/dist/viewer/hooks/use-graceful-degradation.d.ts +30 -0
  412. package/dist/viewer/hooks/use-graceful-degradation.js +45 -0
  413. package/dist/viewer/hooks/use-graceful-degradation.js.map +1 -0
  414. package/dist/viewer/hooks/use-item-selection.d.ts +49 -0
  415. package/dist/viewer/hooks/use-item-selection.js +117 -0
  416. package/dist/viewer/hooks/use-item-selection.js.map +1 -0
  417. package/dist/viewer/hooks/use-memory-monitor.d.ts +39 -0
  418. package/dist/viewer/hooks/use-memory-monitor.js +73 -0
  419. package/dist/viewer/hooks/use-memory-monitor.js.map +1 -0
  420. package/dist/viewer/hooks/use-pan-zoom.d.ts +33 -0
  421. package/dist/viewer/hooks/use-pan-zoom.js +110 -0
  422. package/dist/viewer/hooks/use-pan-zoom.js.map +1 -0
  423. package/dist/viewer/hooks/use-persistent-filter.d.ts +24 -0
  424. package/dist/viewer/hooks/use-persistent-filter.js +37 -0
  425. package/dist/viewer/hooks/use-persistent-filter.js.map +1 -0
  426. package/dist/viewer/hooks/use-polling-suspension.d.ts +32 -0
  427. package/dist/viewer/hooks/use-polling-suspension.js +41 -0
  428. package/dist/viewer/hooks/use-polling-suspension.js.map +1 -0
  429. package/dist/viewer/hooks/use-polling.d.ts +39 -0
  430. package/dist/viewer/hooks/use-polling.js +55 -0
  431. package/dist/viewer/hooks/use-polling.js.map +1 -0
  432. package/dist/viewer/hooks/use-prd-actions.d.ts +126 -0
  433. package/dist/viewer/hooks/use-prd-actions.js +250 -0
  434. package/dist/viewer/hooks/use-prd-actions.js.map +1 -0
  435. package/dist/viewer/hooks/use-prd-data.d.ts +45 -0
  436. package/dist/viewer/hooks/use-prd-data.js +159 -0
  437. package/dist/viewer/hooks/use-prd-data.js.map +1 -0
  438. package/dist/viewer/hooks/use-prd-deep-link.d.ts +45 -0
  439. package/dist/viewer/hooks/use-prd-deep-link.js +60 -0
  440. package/dist/viewer/hooks/use-prd-deep-link.js.map +1 -0
  441. package/dist/viewer/hooks/use-prd-websocket.d.ts +47 -0
  442. package/dist/viewer/hooks/use-prd-websocket.js +139 -0
  443. package/dist/viewer/hooks/use-prd-websocket.js.map +1 -0
  444. package/dist/viewer/hooks/use-project-metadata.d.ts +25 -0
  445. package/dist/viewer/hooks/use-project-metadata.js +55 -0
  446. package/dist/viewer/hooks/use-project-metadata.js.map +1 -0
  447. package/dist/viewer/hooks/use-project-status.d.ts +60 -0
  448. package/dist/viewer/hooks/use-project-status.js +133 -0
  449. package/dist/viewer/hooks/use-project-status.js.map +1 -0
  450. package/dist/viewer/hooks/use-refresh-throttle.d.ts +45 -0
  451. package/dist/viewer/hooks/use-refresh-throttle.js +52 -0
  452. package/dist/viewer/hooks/use-refresh-throttle.js.map +1 -0
  453. package/dist/viewer/hooks/use-route-state.d.ts +18 -0
  454. package/dist/viewer/hooks/use-route-state.js +115 -0
  455. package/dist/viewer/hooks/use-route-state.js.map +1 -0
  456. package/dist/viewer/hooks/use-subzone-edges.d.ts +21 -0
  457. package/dist/viewer/hooks/use-subzone-edges.js +147 -0
  458. package/dist/viewer/hooks/use-subzone-edges.js.map +1 -0
  459. package/dist/viewer/hooks/use-tab-visibility.d.ts +31 -0
  460. package/dist/viewer/hooks/use-tab-visibility.js +43 -0
  461. package/dist/viewer/hooks/use-tab-visibility.js.map +1 -0
  462. package/dist/viewer/hooks/use-tick.d.ts +43 -0
  463. package/dist/viewer/hooks/use-tick.js +76 -0
  464. package/dist/viewer/hooks/use-tick.js.map +1 -0
  465. package/dist/viewer/hooks/use-toast.d.ts +24 -0
  466. package/dist/viewer/hooks/use-toast.js +26 -0
  467. package/dist/viewer/hooks/use-toast.js.map +1 -0
  468. package/dist/viewer/hooks/use-zone-drag.d.ts +30 -0
  469. package/dist/viewer/hooks/use-zone-drag.js +60 -0
  470. package/dist/viewer/hooks/use-zone-drag.js.map +1 -0
  471. package/dist/viewer/index.html +36 -0
  472. package/dist/viewer/loader.d.ts +33 -0
  473. package/dist/viewer/loader.js +195 -0
  474. package/dist/viewer/loader.js.map +1 -0
  475. package/dist/viewer/main.d.ts +1 -0
  476. package/dist/viewer/main.js +121 -0
  477. package/dist/viewer/main.js.map +1 -0
  478. package/dist/viewer/messaging/call-rate-limiter.d.ts +50 -0
  479. package/dist/viewer/messaging/call-rate-limiter.js +103 -0
  480. package/dist/viewer/messaging/call-rate-limiter.js.map +1 -0
  481. package/dist/viewer/messaging/fetch-pipeline.d.ts +58 -0
  482. package/dist/viewer/messaging/fetch-pipeline.js +58 -0
  483. package/dist/viewer/messaging/fetch-pipeline.js.map +1 -0
  484. package/dist/viewer/messaging/index.d.ts +43 -0
  485. package/dist/viewer/messaging/index.js +46 -0
  486. package/dist/viewer/messaging/index.js.map +1 -0
  487. package/dist/viewer/messaging/message-coalescer.d.ts +96 -0
  488. package/dist/viewer/messaging/message-coalescer.js +121 -0
  489. package/dist/viewer/messaging/message-coalescer.js.map +1 -0
  490. package/dist/viewer/messaging/message-throttle.d.ts +95 -0
  491. package/dist/viewer/messaging/message-throttle.js +147 -0
  492. package/dist/viewer/messaging/message-throttle.js.map +1 -0
  493. package/dist/viewer/messaging/request-dedup.d.ts +43 -0
  494. package/dist/viewer/messaging/request-dedup.js +55 -0
  495. package/dist/viewer/messaging/request-dedup.js.map +1 -0
  496. package/dist/viewer/messaging/ws-pipeline.d.ts +85 -0
  497. package/dist/viewer/messaging/ws-pipeline.js +68 -0
  498. package/dist/viewer/messaging/ws-pipeline.js.map +1 -0
  499. package/dist/viewer/n-dx.png +0 -0
  500. package/dist/viewer/performance/dom-performance-monitor.d.ts +157 -0
  501. package/dist/viewer/performance/dom-performance-monitor.js +341 -0
  502. package/dist/viewer/performance/dom-performance-monitor.js.map +1 -0
  503. package/dist/viewer/performance/dom-update-gate.d.ts +122 -0
  504. package/dist/viewer/performance/dom-update-gate.js +229 -0
  505. package/dist/viewer/performance/dom-update-gate.js.map +1 -0
  506. package/dist/viewer/performance/graceful-degradation.d.ts +73 -0
  507. package/dist/viewer/performance/graceful-degradation.js +152 -0
  508. package/dist/viewer/performance/graceful-degradation.js.map +1 -0
  509. package/dist/viewer/performance/index.d.ts +14 -0
  510. package/dist/viewer/performance/index.js +20 -0
  511. package/dist/viewer/performance/index.js.map +1 -0
  512. package/dist/viewer/performance/memory-monitor.d.ts +78 -0
  513. package/dist/viewer/performance/memory-monitor.js +218 -0
  514. package/dist/viewer/performance/memory-monitor.js.map +1 -0
  515. package/dist/viewer/performance/refresh-throttle.d.ts +90 -0
  516. package/dist/viewer/performance/refresh-throttle.js +266 -0
  517. package/dist/viewer/performance/refresh-throttle.js.map +1 -0
  518. package/dist/viewer/performance/response-buffer-gate.d.ts +108 -0
  519. package/dist/viewer/performance/response-buffer-gate.js +170 -0
  520. package/dist/viewer/performance/response-buffer-gate.js.map +1 -0
  521. package/dist/viewer/performance/update-batcher.d.ts +79 -0
  522. package/dist/viewer/performance/update-batcher.js +119 -0
  523. package/dist/viewer/performance/update-batcher.js.map +1 -0
  524. package/dist/viewer/polling/batched-tick-dispatcher.d.ts +83 -0
  525. package/dist/viewer/polling/batched-tick-dispatcher.js +183 -0
  526. package/dist/viewer/polling/batched-tick-dispatcher.js.map +1 -0
  527. package/dist/viewer/polling/index.d.ts +13 -0
  528. package/dist/viewer/polling/index.js +16 -0
  529. package/dist/viewer/polling/index.js.map +1 -0
  530. package/dist/viewer/polling/polling-manager.d.ts +82 -0
  531. package/dist/viewer/polling/polling-manager.js +254 -0
  532. package/dist/viewer/polling/polling-manager.js.map +1 -0
  533. package/dist/viewer/polling/polling-restart.d.ts +45 -0
  534. package/dist/viewer/polling/polling-restart.js +98 -0
  535. package/dist/viewer/polling/polling-restart.js.map +1 -0
  536. package/dist/viewer/polling/polling-state.d.ts +182 -0
  537. package/dist/viewer/polling/polling-state.js +306 -0
  538. package/dist/viewer/polling/polling-state.js.map +1 -0
  539. package/dist/viewer/polling/tab-visibility.d.ts +112 -0
  540. package/dist/viewer/polling/tab-visibility.js +276 -0
  541. package/dist/viewer/polling/tab-visibility.js.map +1 -0
  542. package/dist/viewer/polling/tick-timer.d.ts +70 -0
  543. package/dist/viewer/polling/tick-timer.js +168 -0
  544. package/dist/viewer/polling/tick-timer.js.map +1 -0
  545. package/dist/viewer/polling/tick-visibility-gate.d.ts +92 -0
  546. package/dist/viewer/polling/tick-visibility-gate.js +146 -0
  547. package/dist/viewer/polling/tick-visibility-gate.js.map +1 -0
  548. package/dist/viewer/route-state.d.ts +8 -0
  549. package/dist/viewer/route-state.js +77 -0
  550. package/dist/viewer/route-state.js.map +1 -0
  551. package/dist/viewer/schema-compat.d.ts +17 -0
  552. package/dist/viewer/schema-compat.js +49 -0
  553. package/dist/viewer/schema-compat.js.map +1 -0
  554. package/dist/viewer/types.d.ts +66 -0
  555. package/dist/viewer/types.js +2 -0
  556. package/dist/viewer/types.js.map +1 -0
  557. package/dist/viewer/usage/constants.d.ts +14 -0
  558. package/dist/viewer/usage/constants.js +14 -0
  559. package/dist/viewer/usage/constants.js.map +1 -0
  560. package/dist/viewer/usage/index.d.ts +7 -0
  561. package/dist/viewer/usage/index.js +8 -0
  562. package/dist/viewer/usage/index.js.map +1 -0
  563. package/dist/viewer/utils.d.ts +25 -0
  564. package/dist/viewer/utils.js +48 -0
  565. package/dist/viewer/utils.js.map +1 -0
  566. package/dist/viewer/validate.d.ts +23 -0
  567. package/dist/viewer/validate.js +275 -0
  568. package/dist/viewer/validate.js.map +1 -0
  569. package/dist/viewer/views/analysis.d.ts +10 -0
  570. package/dist/viewer/views/analysis.js +109 -0
  571. package/dist/viewer/views/analysis.js.map +1 -0
  572. package/dist/viewer/views/architecture.d.ts +10 -0
  573. package/dist/viewer/views/architecture.js +44 -0
  574. package/dist/viewer/views/architecture.js.map +1 -0
  575. package/dist/viewer/views/domain-hench.d.ts +13 -0
  576. package/dist/viewer/views/domain-hench.js +14 -0
  577. package/dist/viewer/views/domain-hench.js.map +1 -0
  578. package/dist/viewer/views/domain-rex.d.ts +17 -0
  579. package/dist/viewer/views/domain-rex.js +18 -0
  580. package/dist/viewer/views/domain-rex.js.map +1 -0
  581. package/dist/viewer/views/domain-settings.d.ts +12 -0
  582. package/dist/viewer/views/domain-settings.js +13 -0
  583. package/dist/viewer/views/domain-settings.js.map +1 -0
  584. package/dist/viewer/views/domain-sourcevision.d.ts +20 -0
  585. package/dist/viewer/views/domain-sourcevision.js +21 -0
  586. package/dist/viewer/views/domain-sourcevision.js.map +1 -0
  587. package/dist/viewer/views/enrichment-thresholds.d.ts +11 -0
  588. package/dist/viewer/views/enrichment-thresholds.js +12 -0
  589. package/dist/viewer/views/enrichment-thresholds.js.map +1 -0
  590. package/dist/viewer/views/feature-toggles.d.ts +13 -0
  591. package/dist/viewer/views/feature-toggles.js +185 -0
  592. package/dist/viewer/views/feature-toggles.js.map +1 -0
  593. package/dist/viewer/views/files.d.ts +13 -0
  594. package/dist/viewer/views/files.js +174 -0
  595. package/dist/viewer/views/files.js.map +1 -0
  596. package/dist/viewer/views/graph.d.ts +12 -0
  597. package/dist/viewer/views/graph.js +316 -0
  598. package/dist/viewer/views/graph.js.map +1 -0
  599. package/dist/viewer/views/hench-config.d.ts +39 -0
  600. package/dist/viewer/views/hench-config.js +473 -0
  601. package/dist/viewer/views/hench-config.js.map +1 -0
  602. package/dist/viewer/views/hench-runs.d.ts +19 -0
  603. package/dist/viewer/views/hench-runs.js +460 -0
  604. package/dist/viewer/views/hench-runs.js.map +1 -0
  605. package/dist/viewer/views/hench-templates.d.ts +17 -0
  606. package/dist/viewer/views/hench-templates.js +262 -0
  607. package/dist/viewer/views/hench-templates.js.map +1 -0
  608. package/dist/viewer/views/integration-config.d.ts +73 -0
  609. package/dist/viewer/views/integration-config.js +524 -0
  610. package/dist/viewer/views/integration-config.js.map +1 -0
  611. package/dist/viewer/views/notion-config.d.ts +16 -0
  612. package/dist/viewer/views/notion-config.js +357 -0
  613. package/dist/viewer/views/notion-config.js.map +1 -0
  614. package/dist/viewer/views/overview.d.ts +10 -0
  615. package/dist/viewer/views/overview.js +187 -0
  616. package/dist/viewer/views/overview.js.map +1 -0
  617. package/dist/viewer/views/pr-markdown.d.ts +3 -0
  618. package/dist/viewer/views/pr-markdown.js +350 -0
  619. package/dist/viewer/views/pr-markdown.js.map +1 -0
  620. package/dist/viewer/views/prd.d.ts +34 -0
  621. package/dist/viewer/views/prd.js +257 -0
  622. package/dist/viewer/views/prd.js.map +1 -0
  623. package/dist/viewer/views/problems.d.ts +8 -0
  624. package/dist/viewer/views/problems.js +50 -0
  625. package/dist/viewer/views/problems.js.map +1 -0
  626. package/dist/viewer/views/rex-dashboard.d.ts +14 -0
  627. package/dist/viewer/views/rex-dashboard.js +334 -0
  628. package/dist/viewer/views/rex-dashboard.js.map +1 -0
  629. package/dist/viewer/views/routes.d.ts +8 -0
  630. package/dist/viewer/views/routes.js +216 -0
  631. package/dist/viewer/views/routes.js.map +1 -0
  632. package/dist/viewer/views/sourcevision-tabs.d.ts +18 -0
  633. package/dist/viewer/views/sourcevision-tabs.js +14 -0
  634. package/dist/viewer/views/sourcevision-tabs.js.map +1 -0
  635. package/dist/viewer/views/suggestions.d.ts +8 -0
  636. package/dist/viewer/views/suggestions.js +36 -0
  637. package/dist/viewer/views/suggestions.js.map +1 -0
  638. package/dist/viewer/views/task-audit.d.ts +18 -0
  639. package/dist/viewer/views/task-audit.js +413 -0
  640. package/dist/viewer/views/task-audit.js.map +1 -0
  641. package/dist/viewer/views/token-usage.d.ts +10 -0
  642. package/dist/viewer/views/token-usage.js +410 -0
  643. package/dist/viewer/views/token-usage.js.map +1 -0
  644. package/dist/viewer/views/validation.d.ts +11 -0
  645. package/dist/viewer/views/validation.js +475 -0
  646. package/dist/viewer/views/validation.js.map +1 -0
  647. package/dist/viewer/views/view-registry.d.ts +27 -0
  648. package/dist/viewer/views/view-registry.js +70 -0
  649. package/dist/viewer/views/view-registry.js.map +1 -0
  650. package/dist/viewer/views/workflow-optimization.d.ts +12 -0
  651. package/dist/viewer/views/workflow-optimization.js +311 -0
  652. package/dist/viewer/views/workflow-optimization.js.map +1 -0
  653. package/dist/viewer/views/zone-types.d.ts +69 -0
  654. package/dist/viewer/views/zone-types.js +5 -0
  655. package/dist/viewer/views/zone-types.js.map +1 -0
  656. package/dist/viewer/views/zones.d.ts +50 -0
  657. package/dist/viewer/views/zones.js +1438 -0
  658. package/dist/viewer/views/zones.js.map +1 -0
  659. package/dist/viewer/visualization/colors.d.ts +16 -0
  660. package/dist/viewer/visualization/colors.js +31 -0
  661. package/dist/viewer/visualization/colors.js.map +1 -0
  662. package/dist/viewer/visualization/flow.d.ts +54 -0
  663. package/dist/viewer/visualization/flow.js +123 -0
  664. package/dist/viewer/visualization/flow.js.map +1 -0
  665. package/dist/viewer/visualization/index.d.ts +34 -0
  666. package/dist/viewer/visualization/index.js +40 -0
  667. package/dist/viewer/visualization/index.js.map +1 -0
  668. package/dist/viewer/visualization/metrics.d.ts +8 -0
  669. package/dist/viewer/visualization/metrics.js +16 -0
  670. package/dist/viewer/visualization/metrics.js.map +1 -0
  671. package/package.json +54 -0
@@ -0,0 +1,659 @@
1
+ /**
2
+ * Adaptive workflow adjustment API routes — monitor project evolution
3
+ * and automatically adjust workflow parameters.
4
+ *
5
+ * All endpoints are under /api/hench/adaptive/.
6
+ *
7
+ * GET /api/hench/adaptive/analysis — full adaptive analysis with metrics and adjustments
8
+ * GET /api/hench/adaptive/settings — current adaptive settings
9
+ * POST /api/hench/adaptive/settings — update adaptive settings (enable/disable, window, locks)
10
+ * POST /api/hench/adaptive/apply — apply an adjustment (auto or manual)
11
+ * POST /api/hench/adaptive/dismiss/:id — dismiss a recommended adjustment
12
+ * POST /api/hench/adaptive/lock/:key — lock a config key from auto-adjustment
13
+ * POST /api/hench/adaptive/unlock/:key — unlock a config key for auto-adjustment
14
+ * POST /api/hench/adaptive/override — set a manual override for a config key
15
+ * DELETE /api/hench/adaptive/override/:key — remove a manual override
16
+ * GET /api/hench/adaptive/history — adjustment history + stats
17
+ */
18
+ import { readFileSync, readdirSync, writeFileSync, existsSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { jsonResponse, errorResponse, readBody } from "./types.js";
21
+ const ADAPTIVE_PREFIX = "/api/hench/adaptive/";
22
+ // ── Data loading helpers ─────────────────────────────────────────────
23
+ function loadRuns(projectDir) {
24
+ const runsDir = join(projectDir, ".hench", "runs");
25
+ let files;
26
+ try {
27
+ files = readdirSync(runsDir);
28
+ }
29
+ catch {
30
+ return [];
31
+ }
32
+ const runs = [];
33
+ for (const file of files.filter((f) => f.endsWith(".json"))) {
34
+ try {
35
+ const raw = readFileSync(join(runsDir, file), "utf-8");
36
+ const data = JSON.parse(raw);
37
+ if (data.id && data.startedAt) {
38
+ runs.push(data);
39
+ }
40
+ }
41
+ catch {
42
+ // skip invalid files
43
+ }
44
+ }
45
+ return runs.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
46
+ }
47
+ function loadConfig(projectDir) {
48
+ try {
49
+ const raw = readFileSync(join(projectDir, ".hench", "config.json"), "utf-8");
50
+ return JSON.parse(raw);
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ function defaultSettings() {
57
+ return {
58
+ enabled: true,
59
+ windowSize: 20,
60
+ minRunsRequired: 5,
61
+ lockedKeys: [],
62
+ };
63
+ }
64
+ function loadAdaptiveState(projectDir) {
65
+ const path = join(projectDir, ".hench", "adaptive.json");
66
+ try {
67
+ if (!existsSync(path))
68
+ return { settings: defaultSettings(), history: [], overrides: {} };
69
+ const raw = readFileSync(path, "utf-8");
70
+ const parsed = JSON.parse(raw);
71
+ if (parsed && typeof parsed === "object") {
72
+ return {
73
+ settings: { ...defaultSettings(), ...(parsed.settings ?? {}) },
74
+ history: Array.isArray(parsed.history) ? parsed.history : [],
75
+ overrides: (parsed.overrides && typeof parsed.overrides === "object") ? parsed.overrides : {},
76
+ };
77
+ }
78
+ return { settings: defaultSettings(), history: [], overrides: {} };
79
+ }
80
+ catch {
81
+ return { settings: defaultSettings(), history: [], overrides: {} };
82
+ }
83
+ }
84
+ function saveAdaptiveState(projectDir, state) {
85
+ writeFileSync(join(projectDir, ".hench", "adaptive.json"), JSON.stringify(state, null, 2) + "\n", "utf-8");
86
+ }
87
+ // ── Analysis engine (self-contained) ─────────────────────────────────
88
+ const FAILURE_STATUSES = new Set(["failed", "timeout", "budget_exceeded"]);
89
+ function totalTokens(run) {
90
+ return (run.tokenUsage.input ?? 0) + (run.tokenUsage.output ?? 0);
91
+ }
92
+ function runDurationMs(run) {
93
+ if (!run.finishedAt)
94
+ return 0;
95
+ return new Date(run.finishedAt).getTime() - new Date(run.startedAt).getTime();
96
+ }
97
+ function collectMetrics(runs, windowSize = 20) {
98
+ const now = new Date().toISOString();
99
+ if (runs.length === 0) {
100
+ return {
101
+ timestamp: now, totalRuns: 0, recentSuccessRate: 0, recentAvgTurns: 0,
102
+ recentAvgTokens: 0, recentAvgDurationMs: 0, recentTaskCount: 0,
103
+ runsPerDay: 0, successRateTrend: 0, tokenUsageTrend: 0,
104
+ };
105
+ }
106
+ const sorted = [...runs].sort((a, b) => b.startedAt.localeCompare(a.startedAt));
107
+ const recent = sorted.slice(0, windowSize);
108
+ const finished = recent.filter((r) => r.status !== "running");
109
+ const completed = finished.filter((r) => r.status === "completed");
110
+ const recentSuccessRate = finished.length > 0 ? completed.length / finished.length : 0;
111
+ const recentAvgTurns = recent.length > 0 ? recent.reduce((s, r) => s + r.turns, 0) / recent.length : 0;
112
+ const recentAvgTokens = recent.length > 0 ? recent.map(totalTokens).reduce((a, b) => a + b, 0) / recent.length : 0;
113
+ const durations = recent.map(runDurationMs).filter((d) => d > 0);
114
+ const recentAvgDurationMs = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0;
115
+ const recentTaskCount = new Set(recent.map((r) => r.taskId)).size;
116
+ let runsPerDay = 0;
117
+ if (recent.length >= 2) {
118
+ const oldest = new Date(recent[recent.length - 1].startedAt).getTime();
119
+ const newest = new Date(recent[0].startedAt).getTime();
120
+ const daySpan = (newest - oldest) / (1000 * 60 * 60 * 24);
121
+ runsPerDay = daySpan > 0 ? recent.length / daySpan : 0;
122
+ }
123
+ const halfSize = Math.floor(recent.length / 2);
124
+ let successRateTrend = 0;
125
+ let tokenUsageTrend = 0;
126
+ if (halfSize >= 2) {
127
+ const newerHalf = recent.slice(0, halfSize);
128
+ const olderHalf = recent.slice(halfSize);
129
+ const newerFinished = newerHalf.filter((r) => r.status !== "running");
130
+ const olderFinished = olderHalf.filter((r) => r.status !== "running");
131
+ const newerRate = newerFinished.length > 0
132
+ ? newerFinished.filter((r) => r.status === "completed").length / newerFinished.length : 0;
133
+ const olderRate = olderFinished.length > 0
134
+ ? olderFinished.filter((r) => r.status === "completed").length / olderFinished.length : 0;
135
+ successRateTrend = newerRate - olderRate;
136
+ const newerTokens = newerHalf.length > 0
137
+ ? newerHalf.map(totalTokens).reduce((a, b) => a + b, 0) / newerHalf.length : 0;
138
+ const olderTokens = olderHalf.length > 0
139
+ ? olderHalf.map(totalTokens).reduce((a, b) => a + b, 0) / olderHalf.length : 0;
140
+ tokenUsageTrend = olderTokens > 0 ? (newerTokens - olderTokens) / olderTokens : 0;
141
+ }
142
+ return {
143
+ timestamp: now, totalRuns: runs.length, recentSuccessRate, recentAvgTurns,
144
+ recentAvgTokens, recentAvgDurationMs, recentTaskCount, runsPerDay,
145
+ successRateTrend, tokenUsageTrend,
146
+ };
147
+ }
148
+ let idCounter = 0;
149
+ function nextId(category) {
150
+ return `adj-${category}-${++idCounter}`;
151
+ }
152
+ function generateAdjustments(metrics, config, settings) {
153
+ idCounter = 0;
154
+ const adjustments = [];
155
+ const maxTurns = config.maxTurns ?? 50;
156
+ const tokenBudget = config.tokenBudget ?? 0;
157
+ const loopPauseMs = config.loopPauseMs ?? 2000;
158
+ const maxFailedAttempts = config.maxFailedAttempts ?? 3;
159
+ const maxRetries = config.retry?.maxRetries ?? 3;
160
+ const commandTimeout = config.guard?.commandTimeout ?? 30000;
161
+ // ── Complexity scaling ──
162
+ if (metrics.recentAvgTurns > maxTurns * 0.7 &&
163
+ metrics.recentSuccessRate < 0.7 &&
164
+ !settings.lockedKeys.includes("maxTurns")) {
165
+ const proposed = Math.min(Math.round(metrics.recentAvgTurns * 1.5), 100);
166
+ if (proposed > maxTurns) {
167
+ adjustments.push({
168
+ id: nextId("complexity-scaling"),
169
+ category: "complexity-scaling",
170
+ priority: "high",
171
+ title: "Scale up turn limit for increasing task complexity",
172
+ description: `Recent tasks average ${Math.round(metrics.recentAvgTurns)} turns (${Math.round((metrics.recentAvgTurns / maxTurns) * 100)}% of limit). Scaling up to accommodate growing complexity.`,
173
+ rationale: `Average turn usage at ${Math.round((metrics.recentAvgTurns / maxTurns) * 100)}% of limit with ${Math.round(metrics.recentSuccessRate * 100)}% success rate.`,
174
+ configChanges: { maxTurns: proposed },
175
+ autoApplicable: true,
176
+ currentValue: maxTurns,
177
+ proposedValue: proposed,
178
+ configKey: "maxTurns",
179
+ });
180
+ }
181
+ }
182
+ if (metrics.tokenUsageTrend > 0.2 &&
183
+ metrics.successRateTrend < -0.1 &&
184
+ tokenBudget > 0 &&
185
+ !settings.lockedKeys.includes("tokenBudget")) {
186
+ const proposed = Math.round(tokenBudget * 1.3);
187
+ adjustments.push({
188
+ id: nextId("complexity-scaling"),
189
+ category: "complexity-scaling",
190
+ priority: "medium",
191
+ title: "Increase token budget for growing task complexity",
192
+ description: `Token usage trending up ${Math.round(metrics.tokenUsageTrend * 100)}% while success rate is declining.`,
193
+ rationale: `Token consumption increasing ${Math.round(metrics.tokenUsageTrend * 100)}% with success rate dropping.`,
194
+ configChanges: { tokenBudget: proposed },
195
+ autoApplicable: true,
196
+ currentValue: tokenBudget,
197
+ proposedValue: proposed,
198
+ configKey: "tokenBudget",
199
+ });
200
+ }
201
+ // ── Velocity tracking ──
202
+ if (metrics.runsPerDay > 5 &&
203
+ metrics.recentSuccessRate > 0.85 &&
204
+ metrics.recentAvgTurns < maxTurns * 0.4 &&
205
+ maxTurns > 20 &&
206
+ !settings.lockedKeys.includes("maxTurns")) {
207
+ const proposed = Math.max(Math.round(metrics.recentAvgTurns * 2), 20);
208
+ if (proposed < maxTurns) {
209
+ adjustments.push({
210
+ id: nextId("velocity-tracking"),
211
+ category: "velocity-tracking",
212
+ priority: "low",
213
+ title: "Optimize turn limit for high-velocity workflow",
214
+ description: `Running ${metrics.runsPerDay.toFixed(1)} tasks/day with ${Math.round(metrics.recentSuccessRate * 100)}% success. Lowering the limit saves tokens on outliers.`,
215
+ rationale: `High velocity with strong success allows tighter limits.`,
216
+ configChanges: { maxTurns: proposed },
217
+ autoApplicable: true,
218
+ currentValue: maxTurns,
219
+ proposedValue: proposed,
220
+ configKey: "maxTurns",
221
+ });
222
+ }
223
+ }
224
+ if (metrics.runsPerDay < 1 &&
225
+ metrics.recentSuccessRate < 0.5 &&
226
+ metrics.totalRuns >= 5 &&
227
+ maxFailedAttempts <= 3 &&
228
+ !settings.lockedKeys.includes("maxFailedAttempts")) {
229
+ adjustments.push({
230
+ id: nextId("velocity-tracking"),
231
+ category: "velocity-tracking",
232
+ priority: "medium",
233
+ title: "Increase failure tolerance for low-velocity projects",
234
+ description: `With only ${metrics.runsPerDay.toFixed(1)} runs/day, increasing the failure threshold gives tasks more chances.`,
235
+ rationale: `Low velocity means each run is valuable. Current ${maxFailedAttempts} attempt limit may be too aggressive.`,
236
+ configChanges: { maxFailedAttempts: 5 },
237
+ autoApplicable: true,
238
+ currentValue: maxFailedAttempts,
239
+ proposedValue: 5,
240
+ configKey: "maxFailedAttempts",
241
+ });
242
+ }
243
+ // ── Efficiency tuning ──
244
+ if (metrics.successRateTrend < -0.15 &&
245
+ loopPauseMs > 1000 &&
246
+ !settings.lockedKeys.includes("loopPauseMs")) {
247
+ const proposed = Math.max(Math.round(loopPauseMs * 0.5), 500);
248
+ adjustments.push({
249
+ id: nextId("efficiency-tuning"),
250
+ category: "efficiency-tuning",
251
+ priority: "low",
252
+ title: "Reduce loop pause for faster iteration",
253
+ description: `Success rate declining — faster iteration helps the agent recover more quickly.`,
254
+ rationale: `Declining success trend (${Math.round(metrics.successRateTrend * 100)}%).`,
255
+ configChanges: { loopPauseMs: proposed },
256
+ autoApplicable: true,
257
+ currentValue: loopPauseMs,
258
+ proposedValue: proposed,
259
+ configKey: "loopPauseMs",
260
+ });
261
+ }
262
+ if (tokenBudget > 0 &&
263
+ metrics.recentAvgTokens > 0 &&
264
+ metrics.recentAvgTokens < tokenBudget * 0.3 &&
265
+ metrics.recentSuccessRate > 0.7 &&
266
+ !settings.lockedKeys.includes("tokenBudget")) {
267
+ const proposed = Math.round(metrics.recentAvgTokens * 2.5);
268
+ if (proposed < tokenBudget) {
269
+ adjustments.push({
270
+ id: nextId("efficiency-tuning"),
271
+ category: "efficiency-tuning",
272
+ priority: "low",
273
+ title: "Tighten token budget based on actual usage",
274
+ description: `Runs average ${Math.round(metrics.recentAvgTokens).toLocaleString()} tokens, well below the ${tokenBudget.toLocaleString()} budget.`,
275
+ rationale: `Average usage is ${Math.round((metrics.recentAvgTokens / tokenBudget) * 100)}% of budget with ${Math.round(metrics.recentSuccessRate * 100)}% success.`,
276
+ configChanges: { tokenBudget: proposed },
277
+ autoApplicable: true,
278
+ currentValue: tokenBudget,
279
+ proposedValue: proposed,
280
+ configKey: "tokenBudget",
281
+ });
282
+ }
283
+ }
284
+ // ── Resource scaling ──
285
+ if (metrics.runsPerDay > 10 &&
286
+ maxRetries < 5 &&
287
+ !settings.lockedKeys.includes("retry.maxRetries")) {
288
+ adjustments.push({
289
+ id: nextId("resource-scaling"),
290
+ category: "resource-scaling",
291
+ priority: "medium",
292
+ title: "Increase retries for high-volume workflow",
293
+ description: `Running ${metrics.runsPerDay.toFixed(1)} tasks/day — more retries improves resilience.`,
294
+ rationale: `High volume means transient errors are more likely.`,
295
+ configChanges: { "retry.maxRetries": 5 },
296
+ autoApplicable: true,
297
+ currentValue: maxRetries,
298
+ proposedValue: 5,
299
+ configKey: "retry.maxRetries",
300
+ });
301
+ }
302
+ if (metrics.recentAvgDurationMs > 5 * 60 * 1000 &&
303
+ commandTimeout < 60000 &&
304
+ !settings.lockedKeys.includes("guard.commandTimeout")) {
305
+ adjustments.push({
306
+ id: nextId("resource-scaling"),
307
+ category: "resource-scaling",
308
+ priority: "medium",
309
+ title: "Increase command timeout for long-running tasks",
310
+ description: `Average task duration is ${Math.round(metrics.recentAvgDurationMs / 60000)} minutes — commands may need more time.`,
311
+ rationale: `Tasks averaging ${Math.round(metrics.recentAvgDurationMs / 60000)}min may exceed the ${commandTimeout / 1000}s command timeout.`,
312
+ configChanges: { "guard.commandTimeout": 60000 },
313
+ autoApplicable: true,
314
+ currentValue: commandTimeout,
315
+ proposedValue: 60000,
316
+ configKey: "guard.commandTimeout",
317
+ });
318
+ }
319
+ // Sort by priority
320
+ const priorityOrder = { high: 0, medium: 1, low: 2 };
321
+ adjustments.sort((a, b) => (priorityOrder[a.priority] ?? 2) - (priorityOrder[b.priority] ?? 2));
322
+ return adjustments;
323
+ }
324
+ // ── Config mutation helpers ──────────────────────────────────────────
325
+ function setNestedValue(obj, path, value) {
326
+ const parts = path.split(".");
327
+ let current = obj;
328
+ for (let i = 0; i < parts.length - 1; i++) {
329
+ if (!(parts[i] in current) || typeof current[parts[i]] !== "object" || current[parts[i]] === null) {
330
+ current[parts[i]] = {};
331
+ }
332
+ current = current[parts[i]];
333
+ }
334
+ current[parts[parts.length - 1]] = value;
335
+ }
336
+ function getNestedValue(obj, path) {
337
+ const parts = path.split(".");
338
+ let current = obj;
339
+ for (const part of parts) {
340
+ if (current === null || current === undefined || typeof current !== "object")
341
+ return undefined;
342
+ current = current[part];
343
+ }
344
+ return current;
345
+ }
346
+ // ── Route handler ────────────────────────────────────────────────────
347
+ /** Handle adaptive workflow adjustment API requests. Returns true if handled. */
348
+ export function handleAdaptiveRoute(req, res, ctx) {
349
+ const url = req.url || "/";
350
+ const method = req.method || "GET";
351
+ if (!url.startsWith(ADAPTIVE_PREFIX))
352
+ return false;
353
+ const fullPath = url.slice(ADAPTIVE_PREFIX.length);
354
+ const qIdx = fullPath.indexOf("?");
355
+ const path = qIdx === -1 ? fullPath : fullPath.slice(0, qIdx);
356
+ // GET /api/hench/adaptive/analysis — full adaptive analysis
357
+ if (path === "analysis" && method === "GET") {
358
+ const runs = loadRuns(ctx.projectDir);
359
+ const config = loadConfig(ctx.projectDir);
360
+ const state = loadAdaptiveState(ctx.projectDir);
361
+ if (!config) {
362
+ jsonResponse(res, 200, {
363
+ metrics: collectMetrics([]),
364
+ adjustments: [],
365
+ notifications: [],
366
+ settings: state.settings,
367
+ });
368
+ return true;
369
+ }
370
+ const metrics = collectMetrics(runs, state.settings.windowSize);
371
+ let adjustments = [];
372
+ if (runs.length >= state.settings.minRunsRequired) {
373
+ adjustments = generateAdjustments(metrics, config, state.settings);
374
+ }
375
+ const now = new Date().toISOString();
376
+ const notifications = adjustments.map((adj) => ({
377
+ id: `notif-${adj.id}`,
378
+ timestamp: now,
379
+ type: state.settings.enabled && adj.autoApplicable ? "auto-applied" : "recommended",
380
+ adjustment: adj,
381
+ reason: adj.rationale,
382
+ }));
383
+ jsonResponse(res, 200, {
384
+ metrics,
385
+ adjustments,
386
+ notifications,
387
+ settings: state.settings,
388
+ });
389
+ return true;
390
+ }
391
+ // GET /api/hench/adaptive/settings — current settings
392
+ if (path === "settings" && method === "GET") {
393
+ const state = loadAdaptiveState(ctx.projectDir);
394
+ jsonResponse(res, 200, {
395
+ settings: state.settings,
396
+ overrides: state.overrides,
397
+ });
398
+ return true;
399
+ }
400
+ // POST /api/hench/adaptive/settings — update settings
401
+ if (path === "settings" && method === "POST") {
402
+ return handleUpdateSettings(req, res, ctx);
403
+ }
404
+ // POST /api/hench/adaptive/apply — apply an adjustment
405
+ if (path === "apply" && method === "POST") {
406
+ return handleApplyAdjustment(req, res, ctx);
407
+ }
408
+ // POST /api/hench/adaptive/dismiss/:id — dismiss a recommended adjustment
409
+ const dismissMatch = path.match(/^dismiss\/([a-z0-9-]+)$/);
410
+ if (dismissMatch && method === "POST") {
411
+ return handleDismissAdjustment(req, res, ctx, dismissMatch[1]);
412
+ }
413
+ // POST /api/hench/adaptive/lock/:key — lock a config key
414
+ const lockMatch = path.match(/^lock\/(.+)$/);
415
+ if (lockMatch && method === "POST") {
416
+ const key = decodeURIComponent(lockMatch[1]);
417
+ const state = loadAdaptiveState(ctx.projectDir);
418
+ if (!state.settings.lockedKeys.includes(key)) {
419
+ state.settings.lockedKeys.push(key);
420
+ }
421
+ saveAdaptiveState(ctx.projectDir, state);
422
+ jsonResponse(res, 200, { ok: true, lockedKeys: state.settings.lockedKeys });
423
+ return true;
424
+ }
425
+ // POST /api/hench/adaptive/unlock/:key — unlock a config key
426
+ const unlockMatch = path.match(/^unlock\/(.+)$/);
427
+ if (unlockMatch && method === "POST") {
428
+ const key = decodeURIComponent(unlockMatch[1]);
429
+ const state = loadAdaptiveState(ctx.projectDir);
430
+ state.settings.lockedKeys = state.settings.lockedKeys.filter((k) => k !== key);
431
+ saveAdaptiveState(ctx.projectDir, state);
432
+ jsonResponse(res, 200, { ok: true, lockedKeys: state.settings.lockedKeys });
433
+ return true;
434
+ }
435
+ // POST /api/hench/adaptive/override — set a manual override
436
+ if (path === "override" && method === "POST") {
437
+ return handleSetOverride(req, res, ctx);
438
+ }
439
+ // DELETE /api/hench/adaptive/override/:key — remove a manual override
440
+ const overrideMatch = path.match(/^override\/(.+)$/);
441
+ if (overrideMatch && method === "DELETE") {
442
+ const key = decodeURIComponent(overrideMatch[1]);
443
+ const state = loadAdaptiveState(ctx.projectDir);
444
+ delete state.overrides[key];
445
+ state.settings.lockedKeys = state.settings.lockedKeys.filter((k) => k !== key);
446
+ saveAdaptiveState(ctx.projectDir, state);
447
+ jsonResponse(res, 200, { ok: true, overrides: state.overrides });
448
+ return true;
449
+ }
450
+ // GET /api/hench/adaptive/history — adjustment history and stats
451
+ if (path === "history" && method === "GET") {
452
+ const state = loadAdaptiveState(ctx.projectDir);
453
+ const { history } = state;
454
+ const total = history.length;
455
+ const applied = history.filter((r) => r.decision === "applied").length;
456
+ const dismissed = history.filter((r) => r.decision === "dismissed").length;
457
+ const overridden = history.filter((r) => r.decision === "overridden").length;
458
+ const automatic = history.filter((r) => r.automatic).length;
459
+ const byCategory = {};
460
+ for (const record of history) {
461
+ const cat = byCategory[record.category] ?? { applied: 0, dismissed: 0, overridden: 0 };
462
+ cat[record.decision] = (cat[record.decision] ?? 0) + 1;
463
+ byCategory[record.category] = cat;
464
+ }
465
+ jsonResponse(res, 200, {
466
+ records: history,
467
+ stats: { total, applied, dismissed, overridden, automatic, manual: total - automatic, byCategory },
468
+ });
469
+ return true;
470
+ }
471
+ return false;
472
+ }
473
+ // ── Subroute handlers ────────────────────────────────────────────────
474
+ async function handleUpdateSettings(req, res, ctx) {
475
+ let body;
476
+ try {
477
+ const raw = await readBody(req);
478
+ body = JSON.parse(raw);
479
+ }
480
+ catch {
481
+ errorResponse(res, 400, "Invalid JSON in request body");
482
+ return true;
483
+ }
484
+ const state = loadAdaptiveState(ctx.projectDir);
485
+ if (typeof body.enabled === "boolean") {
486
+ state.settings.enabled = body.enabled;
487
+ }
488
+ if (typeof body.windowSize === "number" && body.windowSize >= 5 && body.windowSize <= 100) {
489
+ state.settings.windowSize = body.windowSize;
490
+ }
491
+ if (typeof body.minRunsRequired === "number" && body.minRunsRequired >= 1 && body.minRunsRequired <= 50) {
492
+ state.settings.minRunsRequired = body.minRunsRequired;
493
+ }
494
+ if (Array.isArray(body.lockedKeys)) {
495
+ state.settings.lockedKeys = body.lockedKeys.filter((k) => typeof k === "string");
496
+ }
497
+ try {
498
+ saveAdaptiveState(ctx.projectDir, state);
499
+ }
500
+ catch (err) {
501
+ errorResponse(res, 500, `Failed to save settings: ${err instanceof Error ? err.message : String(err)}`);
502
+ return true;
503
+ }
504
+ jsonResponse(res, 200, { ok: true, settings: state.settings });
505
+ return true;
506
+ }
507
+ async function handleApplyAdjustment(req, res, ctx) {
508
+ let body;
509
+ try {
510
+ const raw = await readBody(req);
511
+ body = JSON.parse(raw);
512
+ }
513
+ catch {
514
+ errorResponse(res, 400, "Invalid JSON in request body");
515
+ return true;
516
+ }
517
+ const adjustmentId = body.adjustmentId;
518
+ const configKey = body.configKey;
519
+ const newValue = body.newValue;
520
+ const title = body.title || "Manual adjustment";
521
+ const category = body.category || "unknown";
522
+ const automatic = body.automatic === true;
523
+ if (!configKey || newValue === undefined) {
524
+ errorResponse(res, 400, "Request must include 'configKey' and 'newValue'");
525
+ return true;
526
+ }
527
+ // Read and modify config
528
+ const configPath = join(ctx.projectDir, ".hench", "config.json");
529
+ let config;
530
+ try {
531
+ config = JSON.parse(readFileSync(configPath, "utf-8"));
532
+ }
533
+ catch {
534
+ errorResponse(res, 404, "Hench configuration not found. Run 'hench init' first.");
535
+ return true;
536
+ }
537
+ const previousValue = getNestedValue(config, configKey);
538
+ setNestedValue(config, configKey, newValue);
539
+ try {
540
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
541
+ }
542
+ catch (err) {
543
+ errorResponse(res, 500, `Failed to write config: ${err instanceof Error ? err.message : String(err)}`);
544
+ return true;
545
+ }
546
+ // Record the adjustment
547
+ const state = loadAdaptiveState(ctx.projectDir);
548
+ state.history.push({
549
+ adjustmentId: adjustmentId || `manual-${Date.now()}`,
550
+ title,
551
+ category,
552
+ configKey,
553
+ decision: "applied",
554
+ previousValue,
555
+ newValue,
556
+ automatic,
557
+ timestamp: new Date().toISOString(),
558
+ });
559
+ try {
560
+ saveAdaptiveState(ctx.projectDir, state);
561
+ }
562
+ catch {
563
+ // Non-fatal — config was already written
564
+ }
565
+ jsonResponse(res, 200, {
566
+ ok: true,
567
+ configKey,
568
+ previousValue,
569
+ newValue,
570
+ });
571
+ return true;
572
+ }
573
+ async function handleDismissAdjustment(req, res, ctx, adjustmentId) {
574
+ let body;
575
+ try {
576
+ const raw = await readBody(req);
577
+ body = JSON.parse(raw);
578
+ }
579
+ catch {
580
+ errorResponse(res, 400, "Invalid JSON in request body");
581
+ return true;
582
+ }
583
+ const title = body.title || adjustmentId;
584
+ const category = body.category || "unknown";
585
+ const configKey = body.configKey || "unknown";
586
+ const state = loadAdaptiveState(ctx.projectDir);
587
+ state.history.push({
588
+ adjustmentId,
589
+ title,
590
+ category,
591
+ configKey,
592
+ decision: "dismissed",
593
+ automatic: false,
594
+ timestamp: new Date().toISOString(),
595
+ });
596
+ try {
597
+ saveAdaptiveState(ctx.projectDir, state);
598
+ }
599
+ catch (err) {
600
+ errorResponse(res, 500, `Failed to save: ${err instanceof Error ? err.message : String(err)}`);
601
+ return true;
602
+ }
603
+ jsonResponse(res, 200, { ok: true, adjustmentId });
604
+ return true;
605
+ }
606
+ async function handleSetOverride(req, res, ctx) {
607
+ let body;
608
+ try {
609
+ const raw = await readBody(req);
610
+ body = JSON.parse(raw);
611
+ }
612
+ catch {
613
+ errorResponse(res, 400, "Invalid JSON in request body");
614
+ return true;
615
+ }
616
+ const key = body.key;
617
+ const value = body.value;
618
+ if (!key || value === undefined) {
619
+ errorResponse(res, 400, "Request must include 'key' and 'value'");
620
+ return true;
621
+ }
622
+ const state = loadAdaptiveState(ctx.projectDir);
623
+ state.overrides[key] = value;
624
+ if (!state.settings.lockedKeys.includes(key)) {
625
+ state.settings.lockedKeys.push(key);
626
+ }
627
+ // Also apply the override to the actual config
628
+ const configPath = join(ctx.projectDir, ".hench", "config.json");
629
+ try {
630
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
631
+ const previousValue = getNestedValue(config, key);
632
+ setNestedValue(config, key, value);
633
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
634
+ state.history.push({
635
+ adjustmentId: `override-${Date.now()}`,
636
+ title: `Manual override: ${key}`,
637
+ category: "manual",
638
+ configKey: key,
639
+ decision: "overridden",
640
+ previousValue,
641
+ newValue: value,
642
+ automatic: false,
643
+ timestamp: new Date().toISOString(),
644
+ });
645
+ }
646
+ catch {
647
+ // Config write failed — still save override state
648
+ }
649
+ try {
650
+ saveAdaptiveState(ctx.projectDir, state);
651
+ }
652
+ catch (err) {
653
+ errorResponse(res, 500, `Failed to save: ${err instanceof Error ? err.message : String(err)}`);
654
+ return true;
655
+ }
656
+ jsonResponse(res, 200, { ok: true, overrides: state.overrides, lockedKeys: state.settings.lockedKeys });
657
+ return true;
658
+ }
659
+ //# sourceMappingURL=routes-adaptive.js.map