@kaelio/ktx 0.5.0 → 0.6.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 (872) hide show
  1. package/assets/python/{kaelio_ktx-0.5.0-py3-none-any.whl → kaelio_ktx-0.6.0-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/clack.d.ts +8 -0
  5. package/dist/clack.js +14 -0
  6. package/dist/connection.js +2 -9
  7. package/dist/connectors/bigquery/connector.d.ts +6 -1
  8. package/dist/connectors/bigquery/connector.js +38 -9
  9. package/dist/connectors/bigquery/dialect.d.ts +11 -9
  10. package/dist/connectors/bigquery/dialect.js +25 -45
  11. package/dist/connectors/clickhouse/connector.d.ts +5 -0
  12. package/dist/connectors/clickhouse/connector.js +36 -3
  13. package/dist/connectors/clickhouse/dialect.d.ts +11 -12
  14. package/dist/connectors/clickhouse/dialect.js +25 -100
  15. package/dist/connectors/mysql/connector.d.ts +7 -1
  16. package/dist/connectors/mysql/connector.js +67 -9
  17. package/dist/connectors/mysql/dialect.d.ts +11 -9
  18. package/dist/connectors/mysql/dialect.js +25 -43
  19. package/dist/connectors/postgres/connector.d.ts +6 -0
  20. package/dist/connectors/postgres/connector.js +67 -12
  21. package/dist/connectors/postgres/dialect.d.ts +11 -9
  22. package/dist/connectors/postgres/dialect.js +26 -35
  23. package/dist/connectors/snowflake/connector.d.ts +8 -3
  24. package/dist/connectors/snowflake/connector.js +39 -20
  25. package/dist/connectors/snowflake/dialect.d.ts +11 -9
  26. package/dist/connectors/snowflake/dialect.js +25 -24
  27. package/dist/connectors/sqlite/connector.d.ts +3 -1
  28. package/dist/connectors/sqlite/connector.js +23 -3
  29. package/dist/connectors/sqlite/dialect.d.ts +11 -9
  30. package/dist/connectors/sqlite/dialect.js +25 -29
  31. package/dist/connectors/sqlserver/connector.d.ts +6 -0
  32. package/dist/connectors/sqlserver/connector.js +56 -9
  33. package/dist/connectors/sqlserver/dialect.d.ts +11 -10
  34. package/dist/connectors/sqlserver/dialect.js +24 -40
  35. package/dist/context/connections/connection-type.d.ts +1 -1
  36. package/dist/context/connections/dialect-helpers.d.ts +9 -0
  37. package/dist/context/connections/dialect-helpers.js +67 -0
  38. package/dist/context/connections/dialects.d.ts +23 -5
  39. package/dist/context/connections/dialects.js +18 -56
  40. package/dist/context/connections/drivers.d.ts +23 -0
  41. package/dist/context/connections/drivers.js +171 -0
  42. package/dist/context/connections/local-query-executor.js +25 -7
  43. package/dist/context/connections/local-warehouse-descriptor.js +0 -2
  44. package/dist/context/connections/postgres-query-executor.js +1 -1
  45. package/dist/context/connections/sqlite-query-executor.js +1 -1
  46. package/dist/context/ingest/adapters/historic-sql/chunk-unified.js +1 -1
  47. package/dist/context/ingest/adapters/historic-sql/connection-dialect.js +11 -7
  48. package/dist/context/ingest/adapters/historic-sql/evidence-tool.d.ts +1 -1
  49. package/dist/context/ingest/adapters/historic-sql/evidence-tool.js +8 -5
  50. package/dist/context/ingest/adapters/historic-sql/evidence.d.ts +4 -4
  51. package/dist/context/ingest/adapters/historic-sql/evidence.js +2 -2
  52. package/dist/context/ingest/adapters/historic-sql/projection.js +5 -2
  53. package/dist/context/ingest/adapters/live-database/daemon-introspection.js +1 -1
  54. package/dist/context/ingest/adapters/live-database/stage.d.ts +2 -0
  55. package/dist/context/ingest/adapters/live-database/stage.js +9 -0
  56. package/dist/context/ingest/adapters/looker/mapping.d.ts +0 -3
  57. package/dist/context/ingest/adapters/looker/mapping.js +0 -3
  58. package/dist/context/ingest/adapters/looker/types.d.ts +1 -1
  59. package/dist/context/ingest/historic-sql-probes/bigquery-runner.d.ts +34 -0
  60. package/dist/context/ingest/historic-sql-probes/bigquery-runner.js +99 -0
  61. package/dist/context/ingest/historic-sql-probes/postgres-runner.d.ts +26 -0
  62. package/dist/context/ingest/historic-sql-probes/postgres-runner.js +76 -0
  63. package/dist/context/ingest/historic-sql-probes/snowflake-runner.d.ts +29 -0
  64. package/dist/context/ingest/historic-sql-probes/snowflake-runner.js +62 -0
  65. package/dist/context/ingest/historic-sql-probes.d.ts +46 -0
  66. package/dist/context/ingest/historic-sql-probes.js +62 -0
  67. package/dist/context/ingest/local-adapters.js +0 -1
  68. package/dist/context/ingest/local-ingest.js +1 -1
  69. package/dist/context/mcp/context-tools.js +11 -48
  70. package/dist/context/mcp/local-project-ports.js +0 -3
  71. package/dist/context/project/config.d.ts +0 -8
  72. package/dist/context/project/driver-schemas.d.ts +0 -4
  73. package/dist/context/project/driver-schemas.js +0 -2
  74. package/dist/context/scan/constraint-discovery.d.ts +19 -0
  75. package/dist/context/scan/constraint-discovery.js +23 -0
  76. package/dist/context/scan/enabled-tables.d.ts +4 -5
  77. package/dist/context/scan/enabled-tables.js +4 -18
  78. package/dist/context/scan/entity-details.js +14 -44
  79. package/dist/context/scan/local-enrichment.js +13 -1
  80. package/dist/context/scan/local-scan.js +5 -4
  81. package/dist/context/scan/local-structural-artifacts.js +51 -0
  82. package/dist/context/scan/relationship-benchmarks.js +9 -6
  83. package/dist/context/scan/relationship-composite-candidates.d.ts +3 -2
  84. package/dist/context/scan/relationship-composite-candidates.js +21 -33
  85. package/dist/context/scan/relationship-discovery.d.ts +3 -2
  86. package/dist/context/scan/relationship-discovery.js +4 -4
  87. package/dist/context/scan/relationship-profiling.d.ts +2 -3
  88. package/dist/context/scan/relationship-profiling.js +25 -94
  89. package/dist/context/scan/relationship-validation.d.ts +3 -2
  90. package/dist/context/scan/relationship-validation.js +12 -22
  91. package/dist/context/scan/table-ref.d.ts +1 -2
  92. package/dist/context/scan/table-ref.js +3 -4
  93. package/dist/context/scan/types.d.ts +6 -2
  94. package/dist/context/scan/warehouse-catalog.js +31 -48
  95. package/dist/context/sl/local-query.js +0 -3
  96. package/dist/context/sl/local-sl.js +0 -13
  97. package/dist/context/sl/semantic-layer.service.js +1 -4
  98. package/dist/context/tools/context-candidate-write.tool.d.ts +2 -2
  99. package/dist/context-build-view.js +1 -1
  100. package/dist/database-tree-picker.js +14 -7
  101. package/dist/error-message.d.ts +1 -0
  102. package/dist/error-message.js +29 -0
  103. package/dist/ingest-depth.js +0 -1
  104. package/dist/ingest.js +2 -2
  105. package/dist/llm/embedding-health.js +2 -2
  106. package/dist/local-scan-connectors.js +13 -56
  107. package/dist/managed-local-embeddings.js +2 -1
  108. package/dist/managed-python-daemon.d.ts +5 -0
  109. package/dist/managed-python-daemon.js +29 -9
  110. package/dist/managed-python-http.js +2 -1
  111. package/dist/public-ingest.js +1 -6
  112. package/dist/runtime-requirements.js +2 -2
  113. package/dist/setup-agents.d.ts +1 -1
  114. package/dist/setup-agents.js +16 -74
  115. package/dist/setup-context.js +2 -1
  116. package/dist/setup-databases.d.ts +3 -13
  117. package/dist/setup-databases.js +141 -313
  118. package/dist/setup-embeddings.js +10 -2
  119. package/dist/setup-runtime.js +2 -1
  120. package/dist/setup-sources.js +2 -1
  121. package/dist/setup.js +10 -4
  122. package/dist/skills/historic_sql_patterns/SKILL.md +1 -3
  123. package/dist/skills/historic_sql_table_digest/SKILL.md +0 -1
  124. package/dist/skills/sl/SKILL.md +2 -2
  125. package/dist/sql.js +0 -4
  126. package/dist/status-project.d.ts +3 -18
  127. package/dist/status-project.js +42 -216
  128. package/dist/telemetry/events.d.ts +1 -1
  129. package/dist/telemetry/index.js +8 -3
  130. package/dist/tree-picker-state.d.ts +2 -2
  131. package/dist/tree-picker-state.js +29 -13
  132. package/dist/tree-picker-tui.d.ts +3 -1
  133. package/dist/tree-picker-tui.js +20 -32
  134. package/package.json +6 -6
  135. package/dist/admin-reindex.test.d.ts +0 -1
  136. package/dist/admin-reindex.test.js +0 -119
  137. package/dist/admin.test.d.ts +0 -1
  138. package/dist/admin.test.js +0 -201
  139. package/dist/cli-program-telemetry.test.d.ts +0 -1
  140. package/dist/cli-program-telemetry.test.js +0 -89
  141. package/dist/cli-program.test.d.ts +0 -1
  142. package/dist/cli-program.test.js +0 -71
  143. package/dist/command-tree.test.d.ts +0 -1
  144. package/dist/command-tree.test.js +0 -126
  145. package/dist/commands/mcp-commands.test.d.ts +0 -1
  146. package/dist/commands/mcp-commands.test.js +0 -111
  147. package/dist/commands/sql-commands.test.d.ts +0 -1
  148. package/dist/commands/sql-commands.test.js +0 -68
  149. package/dist/connection.test.d.ts +0 -1
  150. package/dist/connection.test.js +0 -426
  151. package/dist/connectors/bigquery/connector.test.d.ts +0 -1
  152. package/dist/connectors/bigquery/connector.test.js +0 -363
  153. package/dist/connectors/bigquery/dialect.test.d.ts +0 -1
  154. package/dist/connectors/bigquery/dialect.test.js +0 -36
  155. package/dist/connectors/clickhouse/connector.test.d.ts +0 -1
  156. package/dist/connectors/clickhouse/connector.test.js +0 -342
  157. package/dist/connectors/clickhouse/dialect.test.d.ts +0 -1
  158. package/dist/connectors/clickhouse/dialect.test.js +0 -36
  159. package/dist/connectors/mysql/connector.test.d.ts +0 -1
  160. package/dist/connectors/mysql/connector.test.js +0 -365
  161. package/dist/connectors/mysql/dialect.test.d.ts +0 -1
  162. package/dist/connectors/mysql/dialect.test.js +0 -36
  163. package/dist/connectors/postgres/connector.test.d.ts +0 -1
  164. package/dist/connectors/postgres/connector.test.js +0 -391
  165. package/dist/connectors/postgres/dialect.test.d.ts +0 -1
  166. package/dist/connectors/postgres/dialect.test.js +0 -37
  167. package/dist/connectors/postgres/historic-sql-query-client.test.d.ts +0 -1
  168. package/dist/connectors/postgres/historic-sql-query-client.test.js +0 -45
  169. package/dist/connectors/snowflake/connector.test.d.ts +0 -1
  170. package/dist/connectors/snowflake/connector.test.js +0 -462
  171. package/dist/connectors/snowflake/dialect.test.d.ts +0 -1
  172. package/dist/connectors/snowflake/dialect.test.js +0 -34
  173. package/dist/connectors/snowflake/identifiers.test.d.ts +0 -1
  174. package/dist/connectors/snowflake/identifiers.test.js +0 -12
  175. package/dist/connectors/snowflake/sdk-logger.test.d.ts +0 -1
  176. package/dist/connectors/snowflake/sdk-logger.test.js +0 -47
  177. package/dist/connectors/sqlite/connector.test.d.ts +0 -1
  178. package/dist/connectors/sqlite/connector.test.js +0 -207
  179. package/dist/connectors/sqlite/dialect.test.d.ts +0 -1
  180. package/dist/connectors/sqlite/dialect.test.js +0 -23
  181. package/dist/connectors/sqlserver/connector.test.d.ts +0 -1
  182. package/dist/connectors/sqlserver/connector.test.js +0 -313
  183. package/dist/connectors/sqlserver/dialect.test.d.ts +0 -1
  184. package/dist/connectors/sqlserver/dialect.test.js +0 -36
  185. package/dist/context/connections/bigquery-identifiers.test.d.ts +0 -1
  186. package/dist/context/connections/bigquery-identifiers.test.js +0 -13
  187. package/dist/context/connections/dialects.test.d.ts +0 -1
  188. package/dist/context/connections/dialects.test.js +0 -24
  189. package/dist/context/connections/local-query-executor.test.d.ts +0 -1
  190. package/dist/context/connections/local-query-executor.test.js +0 -48
  191. package/dist/context/connections/local-warehouse-descriptor.test.d.ts +0 -1
  192. package/dist/context/connections/local-warehouse-descriptor.test.js +0 -53
  193. package/dist/context/connections/notion-config.test.d.ts +0 -1
  194. package/dist/context/connections/notion-config.test.js +0 -121
  195. package/dist/context/connections/postgres-query-executor.test.d.ts +0 -1
  196. package/dist/context/connections/postgres-query-executor.test.js +0 -91
  197. package/dist/context/connections/read-only-sql.test.d.ts +0 -1
  198. package/dist/context/connections/read-only-sql.test.js +0 -20
  199. package/dist/context/connections/sqlite-query-executor.test.d.ts +0 -1
  200. package/dist/context/connections/sqlite-query-executor.test.js +0 -113
  201. package/dist/context/core/config-reference.test.d.ts +0 -1
  202. package/dist/context/core/config-reference.test.js +0 -27
  203. package/dist/context/core/git.service.assert-worktree-clean.test.d.ts +0 -1
  204. package/dist/context/core/git.service.assert-worktree-clean.test.js +0 -62
  205. package/dist/context/core/git.service.delete-directories.test.d.ts +0 -1
  206. package/dist/context/core/git.service.delete-directories.test.js +0 -61
  207. package/dist/context/core/git.service.patch.test.d.ts +0 -1
  208. package/dist/context/core/git.service.patch.test.js +0 -40
  209. package/dist/context/core/git.service.reset-hard.test.d.ts +0 -1
  210. package/dist/context/core/git.service.reset-hard.test.js +0 -47
  211. package/dist/context/core/git.service.test.d.ts +0 -1
  212. package/dist/context/core/git.service.test.js +0 -357
  213. package/dist/context/core/session-worktree.service.test.d.ts +0 -1
  214. package/dist/context/core/session-worktree.service.test.js +0 -97
  215. package/dist/context/daemon/semantic-layer-compute.test.d.ts +0 -1
  216. package/dist/context/daemon/semantic-layer-compute.test.js +0 -305
  217. package/dist/context/index-sync/reindex.test.d.ts +0 -1
  218. package/dist/context/index-sync/reindex.test.js +0 -139
  219. package/dist/context/ingest/action-identity.test.d.ts +0 -1
  220. package/dist/context/ingest/action-identity.test.js +0 -19
  221. package/dist/context/ingest/adapters/dbt/chunk.test.d.ts +0 -1
  222. package/dist/context/ingest/adapters/dbt/chunk.test.js +0 -30
  223. package/dist/context/ingest/adapters/dbt/dbt.adapter.test.d.ts +0 -1
  224. package/dist/context/ingest/adapters/dbt/dbt.adapter.test.js +0 -43
  225. package/dist/context/ingest/adapters/dbt/fetch.test.d.ts +0 -1
  226. package/dist/context/ingest/adapters/dbt/fetch.test.js +0 -30
  227. package/dist/context/ingest/adapters/dbt/parse.test.d.ts +0 -1
  228. package/dist/context/ingest/adapters/dbt/parse.test.js +0 -7
  229. package/dist/context/ingest/adapters/dbt-descriptions/parse-schema.test.d.ts +0 -1
  230. package/dist/context/ingest/adapters/dbt-descriptions/parse-schema.test.js +0 -195
  231. package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.test.d.ts +0 -1
  232. package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.test.js +0 -121
  233. package/dist/context/ingest/adapters/historic-sql/buckets.test.d.ts +0 -1
  234. package/dist/context/ingest/adapters/historic-sql/buckets.test.js +0 -49
  235. package/dist/context/ingest/adapters/historic-sql/chunk-unified.test.d.ts +0 -1
  236. package/dist/context/ingest/adapters/historic-sql/chunk-unified.test.js +0 -160
  237. package/dist/context/ingest/adapters/historic-sql/detect.test.d.ts +0 -1
  238. package/dist/context/ingest/adapters/historic-sql/detect.test.js +0 -48
  239. package/dist/context/ingest/adapters/historic-sql/evidence-tool.test.d.ts +0 -1
  240. package/dist/context/ingest/adapters/historic-sql/evidence-tool.test.js +0 -67
  241. package/dist/context/ingest/adapters/historic-sql/evidence.test.d.ts +0 -1
  242. package/dist/context/ingest/adapters/historic-sql/evidence.test.js +0 -43
  243. package/dist/context/ingest/adapters/historic-sql/historic-sql.adapter.test.d.ts +0 -1
  244. package/dist/context/ingest/adapters/historic-sql/historic-sql.adapter.test.js +0 -98
  245. package/dist/context/ingest/adapters/historic-sql/local-ingest-acceptance.test.d.ts +0 -1
  246. package/dist/context/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +0 -235
  247. package/dist/context/ingest/adapters/historic-sql/pattern-inputs.test.d.ts +0 -1
  248. package/dist/context/ingest/adapters/historic-sql/pattern-inputs.test.js +0 -68
  249. package/dist/context/ingest/adapters/historic-sql/postgres-pgss-reader.test.d.ts +0 -1
  250. package/dist/context/ingest/adapters/historic-sql/postgres-pgss-reader.test.js +0 -205
  251. package/dist/context/ingest/adapters/historic-sql/projection.test.d.ts +0 -1
  252. package/dist/context/ingest/adapters/historic-sql/projection.test.js +0 -392
  253. package/dist/context/ingest/adapters/historic-sql/redaction.test.d.ts +0 -1
  254. package/dist/context/ingest/adapters/historic-sql/redaction.test.js +0 -22
  255. package/dist/context/ingest/adapters/historic-sql/skill-schemas.test.d.ts +0 -1
  256. package/dist/context/ingest/adapters/historic-sql/skill-schemas.test.js +0 -62
  257. package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.test.d.ts +0 -1
  258. package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.test.js +0 -117
  259. package/dist/context/ingest/adapters/historic-sql/stage-unified.test.d.ts +0 -1
  260. package/dist/context/ingest/adapters/historic-sql/stage-unified.test.js +0 -405
  261. package/dist/context/ingest/adapters/historic-sql/types.test.d.ts +0 -1
  262. package/dist/context/ingest/adapters/historic-sql/types.test.js +0 -87
  263. package/dist/context/ingest/adapters/live-database/chunk.test.d.ts +0 -1
  264. package/dist/context/ingest/adapters/live-database/chunk.test.js +0 -95
  265. package/dist/context/ingest/adapters/live-database/daemon-introspection.test.d.ts +0 -1
  266. package/dist/context/ingest/adapters/live-database/daemon-introspection.test.js +0 -241
  267. package/dist/context/ingest/adapters/live-database/live-database.adapter.test.d.ts +0 -1
  268. package/dist/context/ingest/adapters/live-database/live-database.adapter.test.js +0 -105
  269. package/dist/context/ingest/adapters/live-database/manifest.test.d.ts +0 -1
  270. package/dist/context/ingest/adapters/live-database/manifest.test.js +0 -291
  271. package/dist/context/ingest/adapters/live-database/stage.test.d.ts +0 -1
  272. package/dist/context/ingest/adapters/live-database/stage.test.js +0 -133
  273. package/dist/context/ingest/adapters/looker/chunk.test.d.ts +0 -1
  274. package/dist/context/ingest/adapters/looker/chunk.test.js +0 -142
  275. package/dist/context/ingest/adapters/looker/client-boundary.test.d.ts +0 -1
  276. package/dist/context/ingest/adapters/looker/client-boundary.test.js +0 -12
  277. package/dist/context/ingest/adapters/looker/client.test.d.ts +0 -1
  278. package/dist/context/ingest/adapters/looker/client.test.js +0 -407
  279. package/dist/context/ingest/adapters/looker/daemon-table-identifier-parser.test.d.ts +0 -1
  280. package/dist/context/ingest/adapters/looker/daemon-table-identifier-parser.test.js +0 -40
  281. package/dist/context/ingest/adapters/looker/detect.test.d.ts +0 -1
  282. package/dist/context/ingest/adapters/looker/detect.test.js +0 -39
  283. package/dist/context/ingest/adapters/looker/evidence-documents.test.d.ts +0 -1
  284. package/dist/context/ingest/adapters/looker/evidence-documents.test.js +0 -178
  285. package/dist/context/ingest/adapters/looker/factory.test.d.ts +0 -1
  286. package/dist/context/ingest/adapters/looker/factory.test.js +0 -55
  287. package/dist/context/ingest/adapters/looker/fetch-report.test.d.ts +0 -1
  288. package/dist/context/ingest/adapters/looker/fetch-report.test.js +0 -71
  289. package/dist/context/ingest/adapters/looker/fetch.test.d.ts +0 -1
  290. package/dist/context/ingest/adapters/looker/fetch.test.js +0 -592
  291. package/dist/context/ingest/adapters/looker/local-runtime-store.test.d.ts +0 -1
  292. package/dist/context/ingest/adapters/looker/local-runtime-store.test.js +0 -106
  293. package/dist/context/ingest/adapters/looker/looker.adapter.test.d.ts +0 -1
  294. package/dist/context/ingest/adapters/looker/looker.adapter.test.js +0 -99
  295. package/dist/context/ingest/adapters/looker/mapping.test.d.ts +0 -1
  296. package/dist/context/ingest/adapters/looker/mapping.test.js +0 -334
  297. package/dist/context/ingest/adapters/looker/reconcile.test.d.ts +0 -1
  298. package/dist/context/ingest/adapters/looker/reconcile.test.js +0 -12
  299. package/dist/context/ingest/adapters/looker/scope.test.d.ts +0 -1
  300. package/dist/context/ingest/adapters/looker/scope.test.js +0 -84
  301. package/dist/context/ingest/adapters/looker/target-connections.test.d.ts +0 -1
  302. package/dist/context/ingest/adapters/looker/target-connections.test.js +0 -71
  303. package/dist/context/ingest/adapters/looker/tools/looker-query-to-sl.tool.test.d.ts +0 -1
  304. package/dist/context/ingest/adapters/looker/tools/looker-query-to-sl.tool.test.js +0 -211
  305. package/dist/context/ingest/adapters/looker/types.test.d.ts +0 -1
  306. package/dist/context/ingest/adapters/looker/types.test.js +0 -261
  307. package/dist/context/ingest/adapters/lookml/chunk.test.d.ts +0 -1
  308. package/dist/context/ingest/adapters/lookml/chunk.test.js +0 -213
  309. package/dist/context/ingest/adapters/lookml/detect.test.d.ts +0 -1
  310. package/dist/context/ingest/adapters/lookml/detect.test.js +0 -37
  311. package/dist/context/ingest/adapters/lookml/fetch-report.test.d.ts +0 -1
  312. package/dist/context/ingest/adapters/lookml/fetch-report.test.js +0 -82
  313. package/dist/context/ingest/adapters/lookml/fetch.test.d.ts +0 -1
  314. package/dist/context/ingest/adapters/lookml/fetch.test.js +0 -121
  315. package/dist/context/ingest/adapters/lookml/graph.test.d.ts +0 -1
  316. package/dist/context/ingest/adapters/lookml/graph.test.js +0 -105
  317. package/dist/context/ingest/adapters/lookml/lookml.adapter.test.d.ts +0 -1
  318. package/dist/context/ingest/adapters/lookml/lookml.adapter.test.js +0 -49
  319. package/dist/context/ingest/adapters/lookml/parse.test.d.ts +0 -1
  320. package/dist/context/ingest/adapters/lookml/parse.test.js +0 -118
  321. package/dist/context/ingest/adapters/lookml/pull-config.test.d.ts +0 -1
  322. package/dist/context/ingest/adapters/lookml/pull-config.test.js +0 -128
  323. package/dist/context/ingest/adapters/metabase/card-references.test.d.ts +0 -1
  324. package/dist/context/ingest/adapters/metabase/card-references.test.js +0 -36
  325. package/dist/context/ingest/adapters/metabase/chunk.test.d.ts +0 -1
  326. package/dist/context/ingest/adapters/metabase/chunk.test.js +0 -299
  327. package/dist/context/ingest/adapters/metabase/client-boundary.test.d.ts +0 -1
  328. package/dist/context/ingest/adapters/metabase/client-boundary.test.js +0 -38
  329. package/dist/context/ingest/adapters/metabase/client-port.test.d.ts +0 -1
  330. package/dist/context/ingest/adapters/metabase/client-port.test.js +0 -86
  331. package/dist/context/ingest/adapters/metabase/client.test.d.ts +0 -1
  332. package/dist/context/ingest/adapters/metabase/client.test.js +0 -377
  333. package/dist/context/ingest/adapters/metabase/detect.test.d.ts +0 -1
  334. package/dist/context/ingest/adapters/metabase/detect.test.js +0 -42
  335. package/dist/context/ingest/adapters/metabase/fanout-planner.test.d.ts +0 -1
  336. package/dist/context/ingest/adapters/metabase/fanout-planner.test.js +0 -44
  337. package/dist/context/ingest/adapters/metabase/fetch-scope.test.d.ts +0 -1
  338. package/dist/context/ingest/adapters/metabase/fetch-scope.test.js +0 -124
  339. package/dist/context/ingest/adapters/metabase/fetch.test.d.ts +0 -1
  340. package/dist/context/ingest/adapters/metabase/fetch.test.js +0 -557
  341. package/dist/context/ingest/adapters/metabase/local-metabase.adapter.test.d.ts +0 -1
  342. package/dist/context/ingest/adapters/metabase/local-metabase.adapter.test.js +0 -56
  343. package/dist/context/ingest/adapters/metabase/local-source-state-store.test.d.ts +0 -1
  344. package/dist/context/ingest/adapters/metabase/local-source-state-store.test.js +0 -99
  345. package/dist/context/ingest/adapters/metabase/mapping.test.d.ts +0 -1
  346. package/dist/context/ingest/adapters/metabase/mapping.test.js +0 -215
  347. package/dist/context/ingest/adapters/metabase/metabase.adapter.test.d.ts +0 -1
  348. package/dist/context/ingest/adapters/metabase/metabase.adapter.test.js +0 -129
  349. package/dist/context/ingest/adapters/metabase/serialize-card.test.d.ts +0 -1
  350. package/dist/context/ingest/adapters/metabase/serialize-card.test.js +0 -205
  351. package/dist/context/ingest/adapters/metabase/types.test.d.ts +0 -1
  352. package/dist/context/ingest/adapters/metabase/types.test.js +0 -75
  353. package/dist/context/ingest/adapters/metricflow/chunk.test.d.ts +0 -1
  354. package/dist/context/ingest/adapters/metricflow/chunk.test.js +0 -114
  355. package/dist/context/ingest/adapters/metricflow/deep-parse.test.d.ts +0 -1
  356. package/dist/context/ingest/adapters/metricflow/deep-parse.test.js +0 -1139
  357. package/dist/context/ingest/adapters/metricflow/detect.test.d.ts +0 -1
  358. package/dist/context/ingest/adapters/metricflow/detect.test.js +0 -43
  359. package/dist/context/ingest/adapters/metricflow/fetch.test.d.ts +0 -1
  360. package/dist/context/ingest/adapters/metricflow/fetch.test.js +0 -97
  361. package/dist/context/ingest/adapters/metricflow/graph.test.d.ts +0 -1
  362. package/dist/context/ingest/adapters/metricflow/graph.test.js +0 -245
  363. package/dist/context/ingest/adapters/metricflow/import-semantic-models.test.d.ts +0 -1
  364. package/dist/context/ingest/adapters/metricflow/import-semantic-models.test.js +0 -318
  365. package/dist/context/ingest/adapters/metricflow/metricflow.adapter.test.d.ts +0 -1
  366. package/dist/context/ingest/adapters/metricflow/metricflow.adapter.test.js +0 -212
  367. package/dist/context/ingest/adapters/metricflow/parse.test.d.ts +0 -1
  368. package/dist/context/ingest/adapters/metricflow/parse.test.js +0 -171
  369. package/dist/context/ingest/adapters/metricflow/pull-config.test.d.ts +0 -1
  370. package/dist/context/ingest/adapters/metricflow/pull-config.test.js +0 -57
  371. package/dist/context/ingest/adapters/metricflow/semantic-models.test.d.ts +0 -1
  372. package/dist/context/ingest/adapters/metricflow/semantic-models.test.js +0 -204
  373. package/dist/context/ingest/adapters/notion/cluster.test.d.ts +0 -1
  374. package/dist/context/ingest/adapters/notion/cluster.test.js +0 -123
  375. package/dist/context/ingest/adapters/notion/fetch.test.d.ts +0 -1
  376. package/dist/context/ingest/adapters/notion/fetch.test.js +0 -358
  377. package/dist/context/ingest/adapters/notion/local-state-store.test.d.ts +0 -1
  378. package/dist/context/ingest/adapters/notion/local-state-store.test.js +0 -29
  379. package/dist/context/ingest/adapters/notion/normalize.test.d.ts +0 -1
  380. package/dist/context/ingest/adapters/notion/normalize.test.js +0 -64
  381. package/dist/context/ingest/adapters/notion/notion-client.test.d.ts +0 -1
  382. package/dist/context/ingest/adapters/notion/notion-client.test.js +0 -49
  383. package/dist/context/ingest/adapters/notion/notion.adapter.test.d.ts +0 -1
  384. package/dist/context/ingest/adapters/notion/notion.adapter.test.js +0 -315
  385. package/dist/context/ingest/artifact-gates.test.d.ts +0 -1
  386. package/dist/context/ingest/artifact-gates.test.js +0 -167
  387. package/dist/context/ingest/canonical-pins.test.d.ts +0 -1
  388. package/dist/context/ingest/canonical-pins.test.js +0 -66
  389. package/dist/context/ingest/clustering/kmeans.test.d.ts +0 -1
  390. package/dist/context/ingest/clustering/kmeans.test.js +0 -61
  391. package/dist/context/ingest/context-candidates/candidate-dedup.service.test.d.ts +0 -1
  392. package/dist/context/ingest/context-candidates/candidate-dedup.service.test.js +0 -216
  393. package/dist/context/ingest/context-candidates/context-candidate-carryforward.service.test.d.ts +0 -1
  394. package/dist/context/ingest/context-candidates/context-candidate-carryforward.service.test.js +0 -161
  395. package/dist/context/ingest/context-candidates/curator-pagination.service.test.d.ts +0 -1
  396. package/dist/context/ingest/context-candidates/curator-pagination.service.test.js +0 -168
  397. package/dist/context/ingest/context-candidates/embedding-text.test.d.ts +0 -1
  398. package/dist/context/ingest/context-candidates/embedding-text.test.js +0 -10
  399. package/dist/context/ingest/context-candidates/store.test.d.ts +0 -1
  400. package/dist/context/ingest/context-candidates/store.test.js +0 -67
  401. package/dist/context/ingest/context-evidence/context-evidence-index.service.test.d.ts +0 -1
  402. package/dist/context/ingest/context-evidence/context-evidence-index.service.test.js +0 -374
  403. package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.test.d.ts +0 -1
  404. package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.test.js +0 -416
  405. package/dist/context/ingest/context-evidence/store.test.d.ts +0 -1
  406. package/dist/context/ingest/context-evidence/store.test.js +0 -55
  407. package/dist/context/ingest/dbt-shared/project-vars.test.d.ts +0 -1
  408. package/dist/context/ingest/dbt-shared/project-vars.test.js +0 -90
  409. package/dist/context/ingest/dbt-shared/schema-files.test.d.ts +0 -1
  410. package/dist/context/ingest/dbt-shared/schema-files.test.js +0 -35
  411. package/dist/context/ingest/diff-set.service.test.d.ts +0 -1
  412. package/dist/context/ingest/diff-set.service.test.js +0 -132
  413. package/dist/context/ingest/final-gate-repair.test.d.ts +0 -1
  414. package/dist/context/ingest/final-gate-repair.test.js +0 -109
  415. package/dist/context/ingest/finalization-scope.test.d.ts +0 -1
  416. package/dist/context/ingest/finalization-scope.test.js +0 -114
  417. package/dist/context/ingest/ingest-bundle.runner.isolated-diff.test.d.ts +0 -1
  418. package/dist/context/ingest/ingest-bundle.runner.isolated-diff.test.js +0 -1928
  419. package/dist/context/ingest/ingest-bundle.runner.test.d.ts +0 -1
  420. package/dist/context/ingest/ingest-bundle.runner.test.js +0 -1899
  421. package/dist/context/ingest/ingest-prompts.test.d.ts +0 -1
  422. package/dist/context/ingest/ingest-prompts.test.js +0 -32
  423. package/dist/context/ingest/ingest-runtime-assets.test.d.ts +0 -1
  424. package/dist/context/ingest/ingest-runtime-assets.test.js +0 -89
  425. package/dist/context/ingest/ingest-trace.test.d.ts +0 -1
  426. package/dist/context/ingest/ingest-trace.test.js +0 -76
  427. package/dist/context/ingest/isolated-diff/git-patch.test.d.ts +0 -1
  428. package/dist/context/ingest/isolated-diff/git-patch.test.js +0 -76
  429. package/dist/context/ingest/isolated-diff/patch-integrator.test.d.ts +0 -1
  430. package/dist/context/ingest/isolated-diff/patch-integrator.test.js +0 -369
  431. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.test.d.ts +0 -1
  432. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.test.js +0 -101
  433. package/dist/context/ingest/isolated-diff/work-unit-executor.test.d.ts +0 -1
  434. package/dist/context/ingest/isolated-diff/work-unit-executor.test.js +0 -137
  435. package/dist/context/ingest/local-adapters.test.d.ts +0 -1
  436. package/dist/context/ingest/local-adapters.test.js +0 -612
  437. package/dist/context/ingest/local-bundle-ingest.test.d.ts +0 -1
  438. package/dist/context/ingest/local-bundle-ingest.test.js +0 -794
  439. package/dist/context/ingest/local-bundle-runtime.test.d.ts +0 -1
  440. package/dist/context/ingest/local-bundle-runtime.test.js +0 -240
  441. package/dist/context/ingest/local-embedding-provider.integration.test.d.ts +0 -1
  442. package/dist/context/ingest/local-embedding-provider.integration.test.js +0 -139
  443. package/dist/context/ingest/local-mapping-reconcile.test.d.ts +0 -1
  444. package/dist/context/ingest/local-mapping-reconcile.test.js +0 -61
  445. package/dist/context/ingest/local-metabase-ingest.test.d.ts +0 -1
  446. package/dist/context/ingest/local-metabase-ingest.test.js +0 -227
  447. package/dist/context/ingest/local-stage-ingest.test.d.ts +0 -1
  448. package/dist/context/ingest/local-stage-ingest.test.js +0 -581
  449. package/dist/context/ingest/memory-flow/acceptance-fixtures.d.ts +0 -6
  450. package/dist/context/ingest/memory-flow/acceptance-fixtures.js +0 -155
  451. package/dist/context/ingest/memory-flow/acceptance.test.d.ts +0 -1
  452. package/dist/context/ingest/memory-flow/acceptance.test.js +0 -43
  453. package/dist/context/ingest/memory-flow/events.test.d.ts +0 -1
  454. package/dist/context/ingest/memory-flow/events.test.js +0 -319
  455. package/dist/context/ingest/memory-flow/interaction.test.d.ts +0 -1
  456. package/dist/context/ingest/memory-flow/interaction.test.js +0 -264
  457. package/dist/context/ingest/memory-flow/interactive-render.test.d.ts +0 -1
  458. package/dist/context/ingest/memory-flow/interactive-render.test.js +0 -160
  459. package/dist/context/ingest/memory-flow/live-buffer.test.d.ts +0 -1
  460. package/dist/context/ingest/memory-flow/live-buffer.test.js +0 -77
  461. package/dist/context/ingest/memory-flow/render.test.d.ts +0 -1
  462. package/dist/context/ingest/memory-flow/render.test.js +0 -105
  463. package/dist/context/ingest/memory-flow/schema.test.d.ts +0 -1
  464. package/dist/context/ingest/memory-flow/schema.test.js +0 -147
  465. package/dist/context/ingest/memory-flow/summary.test.d.ts +0 -1
  466. package/dist/context/ingest/memory-flow/summary.test.js +0 -130
  467. package/dist/context/ingest/memory-flow/view-model.test.d.ts +0 -1
  468. package/dist/context/ingest/memory-flow/view-model.test.js +0 -397
  469. package/dist/context/ingest/memory-flow/visuals.test.d.ts +0 -1
  470. package/dist/context/ingest/memory-flow/visuals.test.js +0 -49
  471. package/dist/context/ingest/page-triage/page-triage.service.test.d.ts +0 -1
  472. package/dist/context/ingest/page-triage/page-triage.service.test.js +0 -311
  473. package/dist/context/ingest/raw-sources-paths.test.d.ts +0 -1
  474. package/dist/context/ingest/raw-sources-paths.test.js +0 -18
  475. package/dist/context/ingest/repo-fetch.test.d.ts +0 -1
  476. package/dist/context/ingest/repo-fetch.test.js +0 -168
  477. package/dist/context/ingest/report-snapshot.test.d.ts +0 -1
  478. package/dist/context/ingest/report-snapshot.test.js +0 -329
  479. package/dist/context/ingest/semantic-layer-target-policy.test.d.ts +0 -1
  480. package/dist/context/ingest/semantic-layer-target-policy.test.js +0 -25
  481. package/dist/context/ingest/source-adapter-registry.test.d.ts +0 -1
  482. package/dist/context/ingest/source-adapter-registry.test.js +0 -35
  483. package/dist/context/ingest/sqlite-bundle-ingest-store.test.d.ts +0 -1
  484. package/dist/context/ingest/sqlite-bundle-ingest-store.test.js +0 -517
  485. package/dist/context/ingest/sqlite-local-ingest-store.test.d.ts +0 -1
  486. package/dist/context/ingest/sqlite-local-ingest-store.test.js +0 -143
  487. package/dist/context/ingest/stages/build-reconcile-context.context-candidates.test.d.ts +0 -1
  488. package/dist/context/ingest/stages/build-reconcile-context.context-candidates.test.js +0 -102
  489. package/dist/context/ingest/stages/build-reconcile-context.test.d.ts +0 -1
  490. package/dist/context/ingest/stages/build-reconcile-context.test.js +0 -141
  491. package/dist/context/ingest/stages/build-wu-context.test.d.ts +0 -1
  492. package/dist/context/ingest/stages/build-wu-context.test.js +0 -196
  493. package/dist/context/ingest/stages/stage-1-stage-raw-files.test.d.ts +0 -1
  494. package/dist/context/ingest/stages/stage-1-stage-raw-files.test.js +0 -54
  495. package/dist/context/ingest/stages/stage-3-work-units.test.d.ts +0 -1
  496. package/dist/context/ingest/stages/stage-3-work-units.test.js +0 -175
  497. package/dist/context/ingest/stages/stage-4-reconciliation.test.d.ts +0 -1
  498. package/dist/context/ingest/stages/stage-4-reconciliation.test.js +0 -144
  499. package/dist/context/ingest/stages/validate-wu-sources.test.d.ts +0 -1
  500. package/dist/context/ingest/stages/validate-wu-sources.test.js +0 -27
  501. package/dist/context/ingest/tools/emit-reconciliation-records.tool.test.d.ts +0 -1
  502. package/dist/context/ingest/tools/emit-reconciliation-records.tool.test.js +0 -237
  503. package/dist/context/ingest/tools/eviction-list.tool.test.d.ts +0 -1
  504. package/dist/context/ingest/tools/eviction-list.tool.test.js +0 -44
  505. package/dist/context/ingest/tools/read-raw-file.tool.test.d.ts +0 -1
  506. package/dist/context/ingest/tools/read-raw-file.tool.test.js +0 -45
  507. package/dist/context/ingest/tools/read-raw-span.tool.test.d.ts +0 -1
  508. package/dist/context/ingest/tools/read-raw-span.tool.test.js +0 -34
  509. package/dist/context/ingest/tools/stage-diff.tool.test.d.ts +0 -1
  510. package/dist/context/ingest/tools/stage-diff.tool.test.js +0 -112
  511. package/dist/context/ingest/tools/stage-list.tool.test.d.ts +0 -1
  512. package/dist/context/ingest/tools/stage-list.tool.test.js +0 -58
  513. package/dist/context/ingest/tools/tool-transcript-summary.test.d.ts +0 -1
  514. package/dist/context/ingest/tools/tool-transcript-summary.test.js +0 -141
  515. package/dist/context/ingest/tools/warehouse-verification/discover-data.tool.test.d.ts +0 -1
  516. package/dist/context/ingest/tools/warehouse-verification/discover-data.tool.test.js +0 -107
  517. package/dist/context/ingest/tools/warehouse-verification/entity-details.tool.test.d.ts +0 -1
  518. package/dist/context/ingest/tools/warehouse-verification/entity-details.tool.test.js +0 -146
  519. package/dist/context/ingest/tools/warehouse-verification/sql-execution.tool.test.d.ts +0 -1
  520. package/dist/context/ingest/tools/warehouse-verification/sql-execution.tool.test.js +0 -50
  521. package/dist/context/ingest/wiki-body-refs.test.d.ts +0 -1
  522. package/dist/context/ingest/wiki-body-refs.test.js +0 -138
  523. package/dist/context/ingest/wiki-sl-ref-repair.test.d.ts +0 -1
  524. package/dist/context/ingest/wiki-sl-ref-repair.test.js +0 -81
  525. package/dist/context/llm/ai-sdk-runtime.test.d.ts +0 -1
  526. package/dist/context/llm/ai-sdk-runtime.test.js +0 -308
  527. package/dist/context/llm/claude-code-env.test.d.ts +0 -1
  528. package/dist/context/llm/claude-code-env.test.js +0 -17
  529. package/dist/context/llm/claude-code-models.test.d.ts +0 -1
  530. package/dist/context/llm/claude-code-models.test.js +0 -15
  531. package/dist/context/llm/claude-code-runtime.test.d.ts +0 -1
  532. package/dist/context/llm/claude-code-runtime.test.js +0 -434
  533. package/dist/context/llm/debug-request-recorder.test.d.ts +0 -1
  534. package/dist/context/llm/debug-request-recorder.test.js +0 -112
  535. package/dist/context/llm/embedding-port.test.d.ts +0 -1
  536. package/dist/context/llm/embedding-port.test.js +0 -34
  537. package/dist/context/llm/local-config.test.d.ts +0 -1
  538. package/dist/context/llm/local-config.test.js +0 -164
  539. package/dist/context/llm/runtime-local-config.test.d.ts +0 -1
  540. package/dist/context/llm/runtime-local-config.test.js +0 -17
  541. package/dist/context/llm/runtime-tools.test.d.ts +0 -1
  542. package/dist/context/llm/runtime-tools.test.js +0 -36
  543. package/dist/context/mcp/local-project-ports.test.d.ts +0 -1
  544. package/dist/context/mcp/local-project-ports.test.js +0 -689
  545. package/dist/context/mcp/server.test.d.ts +0 -1
  546. package/dist/context/mcp/server.test.js +0 -902
  547. package/dist/context/memory/local-memory.test.d.ts +0 -1
  548. package/dist/context/memory/local-memory.test.js +0 -173
  549. package/dist/context/memory/memory-agent.service.ingest.test.d.ts +0 -1
  550. package/dist/context/memory/memory-agent.service.ingest.test.js +0 -355
  551. package/dist/context/memory/memory-agent.service.test.d.ts +0 -1
  552. package/dist/context/memory/memory-agent.service.test.js +0 -413
  553. package/dist/context/memory/memory-runs.test.d.ts +0 -1
  554. package/dist/context/memory/memory-runs.test.js +0 -158
  555. package/dist/context/memory/memory-runtime-assets.test.d.ts +0 -1
  556. package/dist/context/memory/memory-runtime-assets.test.js +0 -162
  557. package/dist/context/project/config.test.d.ts +0 -1
  558. package/dist/context/project/config.test.js +0 -467
  559. package/dist/context/project/driver-schemas.test.d.ts +0 -1
  560. package/dist/context/project/driver-schemas.test.js +0 -125
  561. package/dist/context/project/local-git-file-store.test.d.ts +0 -1
  562. package/dist/context/project/local-git-file-store.test.js +0 -71
  563. package/dist/context/project/mappings-yaml-schema.test.d.ts +0 -1
  564. package/dist/context/project/mappings-yaml-schema.test.js +0 -79
  565. package/dist/context/project/project.test.d.ts +0 -1
  566. package/dist/context/project/project.test.js +0 -55
  567. package/dist/context/project/setup-config.test.d.ts +0 -1
  568. package/dist/context/project/setup-config.test.js +0 -38
  569. package/dist/context/prompts/prompt.service.test.d.ts +0 -1
  570. package/dist/context/prompts/prompt.service.test.js +0 -43
  571. package/dist/context/scan/credentials.test.d.ts +0 -1
  572. package/dist/context/scan/credentials.test.js +0 -162
  573. package/dist/context/scan/data-dictionary.test.d.ts +0 -1
  574. package/dist/context/scan/data-dictionary.test.js +0 -92
  575. package/dist/context/scan/description-generation.test.d.ts +0 -1
  576. package/dist/context/scan/description-generation.test.js +0 -693
  577. package/dist/context/scan/embedding-text.test.d.ts +0 -1
  578. package/dist/context/scan/embedding-text.test.js +0 -36
  579. package/dist/context/scan/enrichment-state.test.d.ts +0 -1
  580. package/dist/context/scan/enrichment-state.test.js +0 -147
  581. package/dist/context/scan/enrichment-summary.test.d.ts +0 -1
  582. package/dist/context/scan/enrichment-summary.test.js +0 -34
  583. package/dist/context/scan/enrichment-types.test.d.ts +0 -1
  584. package/dist/context/scan/enrichment-types.test.js +0 -141
  585. package/dist/context/scan/entity-details.test.d.ts +0 -1
  586. package/dist/context/scan/entity-details.test.js +0 -234
  587. package/dist/context/scan/local-enrichment-artifacts.test.d.ts +0 -1
  588. package/dist/context/scan/local-enrichment-artifacts.test.js +0 -771
  589. package/dist/context/scan/local-enrichment.test.d.ts +0 -1
  590. package/dist/context/scan/local-enrichment.test.js +0 -765
  591. package/dist/context/scan/local-scan.test.d.ts +0 -1
  592. package/dist/context/scan/local-scan.test.js +0 -1663
  593. package/dist/context/scan/local-structural-artifacts.test.d.ts +0 -1
  594. package/dist/context/scan/local-structural-artifacts.test.js +0 -144
  595. package/dist/context/scan/relationship-benchmark-report.test.d.ts +0 -1
  596. package/dist/context/scan/relationship-benchmark-report.test.js +0 -389
  597. package/dist/context/scan/relationship-benchmarks.test.d.ts +0 -1
  598. package/dist/context/scan/relationship-benchmarks.test.js +0 -1072
  599. package/dist/context/scan/relationship-budget.test.d.ts +0 -1
  600. package/dist/context/scan/relationship-budget.test.js +0 -71
  601. package/dist/context/scan/relationship-candidates.test.d.ts +0 -1
  602. package/dist/context/scan/relationship-candidates.test.js +0 -747
  603. package/dist/context/scan/relationship-composite-candidates.test.d.ts +0 -1
  604. package/dist/context/scan/relationship-composite-candidates.test.js +0 -69
  605. package/dist/context/scan/relationship-diagnostics.test.d.ts +0 -1
  606. package/dist/context/scan/relationship-diagnostics.test.js +0 -333
  607. package/dist/context/scan/relationship-discovery.test.d.ts +0 -1
  608. package/dist/context/scan/relationship-discovery.test.js +0 -618
  609. package/dist/context/scan/relationship-formal-metadata.test.d.ts +0 -1
  610. package/dist/context/scan/relationship-formal-metadata.test.js +0 -125
  611. package/dist/context/scan/relationship-graph-resolver.test.d.ts +0 -1
  612. package/dist/context/scan/relationship-graph-resolver.test.js +0 -604
  613. package/dist/context/scan/relationship-llm-proposal.test.d.ts +0 -1
  614. package/dist/context/scan/relationship-llm-proposal.test.js +0 -197
  615. package/dist/context/scan/relationship-locality.test.d.ts +0 -1
  616. package/dist/context/scan/relationship-locality.test.js +0 -128
  617. package/dist/context/scan/relationship-name-similarity.test.d.ts +0 -1
  618. package/dist/context/scan/relationship-name-similarity.test.js +0 -68
  619. package/dist/context/scan/relationship-profiling.test.d.ts +0 -1
  620. package/dist/context/scan/relationship-profiling.test.js +0 -392
  621. package/dist/context/scan/relationship-scoring.test.d.ts +0 -1
  622. package/dist/context/scan/relationship-scoring.test.js +0 -86
  623. package/dist/context/scan/relationship-validation.test.d.ts +0 -1
  624. package/dist/context/scan/relationship-validation.test.js +0 -455
  625. package/dist/context/scan/table-ref.test.d.ts +0 -1
  626. package/dist/context/scan/table-ref.test.js +0 -53
  627. package/dist/context/scan/type-normalization.test.d.ts +0 -1
  628. package/dist/context/scan/type-normalization.test.js +0 -21
  629. package/dist/context/scan/types.test.d.ts +0 -1
  630. package/dist/context/scan/types.test.js +0 -206
  631. package/dist/context/scan/warehouse-catalog.test.d.ts +0 -1
  632. package/dist/context/scan/warehouse-catalog.test.js +0 -158
  633. package/dist/context/search/backend-conformance.test-utils.d.ts +0 -39
  634. package/dist/context/search/backend-conformance.test-utils.js +0 -88
  635. package/dist/context/search/backend-conformance.test-utils.test.d.ts +0 -1
  636. package/dist/context/search/backend-conformance.test-utils.test.js +0 -408
  637. package/dist/context/search/discover.test.d.ts +0 -1
  638. package/dist/context/search/discover.test.js +0 -197
  639. package/dist/context/search/hybrid-search-core.test.d.ts +0 -1
  640. package/dist/context/search/hybrid-search-core.test.js +0 -113
  641. package/dist/context/search/pglite-owner-process.test.d.ts +0 -1
  642. package/dist/context/search/pglite-owner-process.test.js +0 -273
  643. package/dist/context/search/pglite-runtime-boundary.test.d.ts +0 -1
  644. package/dist/context/search/pglite-runtime-boundary.test.js +0 -40
  645. package/dist/context/search/pglite-spike.test.d.ts +0 -1
  646. package/dist/context/search/pglite-spike.test.js +0 -249
  647. package/dist/context/search/query.test.d.ts +0 -1
  648. package/dist/context/search/query.test.js +0 -23
  649. package/dist/context/search/rrf.test.d.ts +0 -1
  650. package/dist/context/search/rrf.test.js +0 -47
  651. package/dist/context/skills/skills-registry.service.test.d.ts +0 -1
  652. package/dist/context/skills/skills-registry.service.test.js +0 -161
  653. package/dist/context/sl/dictionary-search.test.d.ts +0 -1
  654. package/dist/context/sl/dictionary-search.test.js +0 -204
  655. package/dist/context/sl/local-query.test.d.ts +0 -1
  656. package/dist/context/sl/local-query.test.js +0 -283
  657. package/dist/context/sl/local-sl.test.d.ts +0 -1
  658. package/dist/context/sl/local-sl.test.js +0 -334
  659. package/dist/context/sl/pglite-sl-search-prototype.test.d.ts +0 -1
  660. package/dist/context/sl/pglite-sl-search-prototype.test.js +0 -240
  661. package/dist/context/sl/schemas.contract.test.d.ts +0 -1
  662. package/dist/context/sl/schemas.contract.test.js +0 -62
  663. package/dist/context/sl/semantic-layer.service.test.d.ts +0 -1
  664. package/dist/context/sl/semantic-layer.service.test.js +0 -1107
  665. package/dist/context/sl/sl-dictionary-profile.test.d.ts +0 -1
  666. package/dist/context/sl/sl-dictionary-profile.test.js +0 -88
  667. package/dist/context/sl/sl-search.service.test.d.ts +0 -1
  668. package/dist/context/sl/sl-search.service.test.js +0 -256
  669. package/dist/context/sl/sqlite-sl-sources-index.test.d.ts +0 -1
  670. package/dist/context/sl/sqlite-sl-sources-index.test.js +0 -175
  671. package/dist/context/sl/tools/connection-id-schema.test.d.ts +0 -1
  672. package/dist/context/sl/tools/connection-id-schema.test.js +0 -14
  673. package/dist/context/sl/tools/sl-discover.tool.test.d.ts +0 -1
  674. package/dist/context/sl/tools/sl-discover.tool.test.js +0 -72
  675. package/dist/context/sl/tools/sl-edit-source.tool.test.d.ts +0 -1
  676. package/dist/context/sl/tools/sl-edit-source.tool.test.js +0 -184
  677. package/dist/context/sl/tools/sl-read-source.tool.session.test.d.ts +0 -1
  678. package/dist/context/sl/tools/sl-read-source.tool.session.test.js +0 -55
  679. package/dist/context/sl/tools/sl-rollback.tool.test.d.ts +0 -1
  680. package/dist/context/sl/tools/sl-rollback.tool.test.js +0 -57
  681. package/dist/context/sl/tools/sl-validate.tool.test.d.ts +0 -1
  682. package/dist/context/sl/tools/sl-validate.tool.test.js +0 -54
  683. package/dist/context/sl/tools/sl-warehouse-validation.test.d.ts +0 -1
  684. package/dist/context/sl/tools/sl-warehouse-validation.test.js +0 -136
  685. package/dist/context/sl/tools/sl-write-source.tool.test.d.ts +0 -1
  686. package/dist/context/sl/tools/sl-write-source.tool.test.js +0 -307
  687. package/dist/context/sql-analysis/http-sql-analysis-port.test.d.ts +0 -1
  688. package/dist/context/sql-analysis/http-sql-analysis-port.test.js +0 -147
  689. package/dist/context/test/make-local-git-repo.d.ts +0 -10
  690. package/dist/context/test/make-local-git-repo.js +0 -34
  691. package/dist/context/tools/context-evidence-tools.test.d.ts +0 -1
  692. package/dist/context/tools/context-evidence-tools.test.js +0 -486
  693. package/dist/context/tools/touched-sl-sources.test.d.ts +0 -1
  694. package/dist/context/tools/touched-sl-sources.test.js +0 -31
  695. package/dist/context/wiki/knowledge-wiki.service.test.d.ts +0 -1
  696. package/dist/context/wiki/knowledge-wiki.service.test.js +0 -205
  697. package/dist/context/wiki/local-knowledge.test.d.ts +0 -1
  698. package/dist/context/wiki/local-knowledge.test.js +0 -270
  699. package/dist/context/wiki/sqlite-knowledge-index.test.d.ts +0 -1
  700. package/dist/context/wiki/sqlite-knowledge-index.test.js +0 -129
  701. package/dist/context/wiki/tools/wiki-list-tags.tool.test.d.ts +0 -1
  702. package/dist/context/wiki/tools/wiki-list-tags.tool.test.js +0 -35
  703. package/dist/context/wiki/tools/wiki-read.tool.test.d.ts +0 -1
  704. package/dist/context/wiki/tools/wiki-read.tool.test.js +0 -66
  705. package/dist/context/wiki/tools/wiki-remove.tool.test.d.ts +0 -1
  706. package/dist/context/wiki/tools/wiki-remove.tool.test.js +0 -95
  707. package/dist/context/wiki/tools/wiki-search.tool.test.d.ts +0 -1
  708. package/dist/context/wiki/tools/wiki-search.tool.test.js +0 -35
  709. package/dist/context/wiki/tools/wiki-write.tool.test.d.ts +0 -1
  710. package/dist/context/wiki/tools/wiki-write.tool.test.js +0 -264
  711. package/dist/context/wiki/wiki-ref-validation.test.d.ts +0 -1
  712. package/dist/context/wiki/wiki-ref-validation.test.js +0 -64
  713. package/dist/context-build-view.test.d.ts +0 -1
  714. package/dist/context-build-view.test.js +0 -942
  715. package/dist/database-tree-picker.test.d.ts +0 -1
  716. package/dist/database-tree-picker.test.js +0 -188
  717. package/dist/demo-assets.test.d.ts +0 -1
  718. package/dist/demo-assets.test.js +0 -121
  719. package/dist/demo-metrics.test.d.ts +0 -1
  720. package/dist/demo-metrics.test.js +0 -108
  721. package/dist/doctor.test.d.ts +0 -1
  722. package/dist/doctor.test.js +0 -596
  723. package/dist/embedding-resolution.test.d.ts +0 -1
  724. package/dist/embedding-resolution.test.js +0 -132
  725. package/dist/example-smoke.test.d.ts +0 -1
  726. package/dist/example-smoke.test.js +0 -83
  727. package/dist/index.test.d.ts +0 -1
  728. package/dist/index.test.js +0 -1300
  729. package/dist/ingest-query-executor.test.d.ts +0 -1
  730. package/dist/ingest-query-executor.test.js +0 -71
  731. package/dist/ingest-report-file.test.d.ts +0 -1
  732. package/dist/ingest-report-file.test.js +0 -63
  733. package/dist/ingest-viz.test.d.ts +0 -1
  734. package/dist/ingest-viz.test.js +0 -691
  735. package/dist/ingest.test-utils.d.ts +0 -126
  736. package/dist/ingest.test-utils.js +0 -629
  737. package/dist/ingest.test.d.ts +0 -1
  738. package/dist/ingest.test.js +0 -1568
  739. package/dist/io/logger.test.d.ts +0 -1
  740. package/dist/io/logger.test.js +0 -55
  741. package/dist/io/mode.test.d.ts +0 -1
  742. package/dist/io/mode.test.js +0 -48
  743. package/dist/io/print-list.test.d.ts +0 -1
  744. package/dist/io/print-list.test.js +0 -277
  745. package/dist/knowledge.test.d.ts +0 -1
  746. package/dist/knowledge.test.js +0 -198
  747. package/dist/llm/embedding-health.test.d.ts +0 -1
  748. package/dist/llm/embedding-health.test.js +0 -72
  749. package/dist/llm/embedding-provider.test.d.ts +0 -1
  750. package/dist/llm/embedding-provider.test.js +0 -84
  751. package/dist/llm/message-builder.test.d.ts +0 -1
  752. package/dist/llm/message-builder.test.js +0 -127
  753. package/dist/llm/model-health.test.d.ts +0 -1
  754. package/dist/llm/model-health.test.js +0 -55
  755. package/dist/llm/model-provider.test.d.ts +0 -1
  756. package/dist/llm/model-provider.test.js +0 -246
  757. package/dist/llm/repair.test.d.ts +0 -1
  758. package/dist/llm/repair.test.js +0 -78
  759. package/dist/local-adapters.test.d.ts +0 -1
  760. package/dist/local-adapters.test.js +0 -166
  761. package/dist/local-scan-connectors.test.d.ts +0 -1
  762. package/dist/local-scan-connectors.test.js +0 -92
  763. package/dist/managed-local-embeddings.test.d.ts +0 -1
  764. package/dist/managed-local-embeddings.test.js +0 -229
  765. package/dist/managed-mcp-daemon.test.d.ts +0 -1
  766. package/dist/managed-mcp-daemon.test.js +0 -187
  767. package/dist/managed-python-command.test.d.ts +0 -1
  768. package/dist/managed-python-command.test.js +0 -262
  769. package/dist/managed-python-daemon.test.d.ts +0 -1
  770. package/dist/managed-python-daemon.test.js +0 -360
  771. package/dist/managed-python-http.test.d.ts +0 -1
  772. package/dist/managed-python-http.test.js +0 -177
  773. package/dist/managed-python-runtime.test.d.ts +0 -1
  774. package/dist/managed-python-runtime.test.js +0 -426
  775. package/dist/mcp-http-server.test.d.ts +0 -1
  776. package/dist/mcp-http-server.test.js +0 -209
  777. package/dist/mcp-server-factory.test.d.ts +0 -1
  778. package/dist/mcp-server-factory.test.js +0 -142
  779. package/dist/memory-flow-interactive.test.d.ts +0 -1
  780. package/dist/memory-flow-interactive.test.js +0 -109
  781. package/dist/memory-flow-tui.test.d.ts +0 -1
  782. package/dist/memory-flow-tui.test.js +0 -247
  783. package/dist/next-steps.test.d.ts +0 -1
  784. package/dist/next-steps.test.js +0 -77
  785. package/dist/notion-page-picker.test.d.ts +0 -1
  786. package/dist/notion-page-picker.test.js +0 -244
  787. package/dist/print-command-tree.test.d.ts +0 -1
  788. package/dist/print-command-tree.test.js +0 -37
  789. package/dist/project-dir.test.d.ts +0 -1
  790. package/dist/project-dir.test.js +0 -124
  791. package/dist/project-resolver.test.d.ts +0 -1
  792. package/dist/project-resolver.test.js +0 -49
  793. package/dist/prompt-navigation.test.d.ts +0 -1
  794. package/dist/prompt-navigation.test.js +0 -33
  795. package/dist/proxy-env.test.d.ts +0 -1
  796. package/dist/proxy-env.test.js +0 -17
  797. package/dist/public-ingest-copy.test.d.ts +0 -1
  798. package/dist/public-ingest-copy.test.js +0 -24
  799. package/dist/public-ingest.test.d.ts +0 -1
  800. package/dist/public-ingest.test.js +0 -891
  801. package/dist/runtime-requirements.test.d.ts +0 -1
  802. package/dist/runtime-requirements.test.js +0 -73
  803. package/dist/runtime.test.d.ts +0 -1
  804. package/dist/runtime.test.js +0 -381
  805. package/dist/scan.test.d.ts +0 -1
  806. package/dist/scan.test.js +0 -1123
  807. package/dist/setup-agents.test.d.ts +0 -1
  808. package/dist/setup-agents.test.js +0 -1028
  809. package/dist/setup-context.test.d.ts +0 -1
  810. package/dist/setup-context.test.js +0 -491
  811. package/dist/setup-databases.test.d.ts +0 -1
  812. package/dist/setup-databases.test.js +0 -2101
  813. package/dist/setup-demo-tour.test.d.ts +0 -1
  814. package/dist/setup-demo-tour.test.js +0 -221
  815. package/dist/setup-embeddings.test.d.ts +0 -1
  816. package/dist/setup-embeddings.test.js +0 -436
  817. package/dist/setup-interrupt.test.d.ts +0 -1
  818. package/dist/setup-interrupt.test.js +0 -77
  819. package/dist/setup-models.test.d.ts +0 -1
  820. package/dist/setup-models.test.js +0 -885
  821. package/dist/setup-project.test.d.ts +0 -1
  822. package/dist/setup-project.test.js +0 -209
  823. package/dist/setup-prompts.test.d.ts +0 -1
  824. package/dist/setup-prompts.test.js +0 -208
  825. package/dist/setup-ready-menu.test.d.ts +0 -1
  826. package/dist/setup-ready-menu.test.js +0 -44
  827. package/dist/setup-runtime.test.d.ts +0 -1
  828. package/dist/setup-runtime.test.js +0 -111
  829. package/dist/setup-secrets.test.d.ts +0 -1
  830. package/dist/setup-secrets.test.js +0 -30
  831. package/dist/setup-sources-notion.test.d.ts +0 -1
  832. package/dist/setup-sources-notion.test.js +0 -109
  833. package/dist/setup-sources.test.d.ts +0 -1
  834. package/dist/setup-sources.test.js +0 -1303
  835. package/dist/setup.test.d.ts +0 -1
  836. package/dist/setup.test.js +0 -1825
  837. package/dist/sl.test.d.ts +0 -1
  838. package/dist/sl.test.js +0 -567
  839. package/dist/source-mapping.test.d.ts +0 -1
  840. package/dist/source-mapping.test.js +0 -65
  841. package/dist/sql.test.d.ts +0 -1
  842. package/dist/sql.test.js +0 -253
  843. package/dist/standalone-smoke.test.d.ts +0 -1
  844. package/dist/standalone-smoke.test.js +0 -250
  845. package/dist/status-project.test.d.ts +0 -1
  846. package/dist/status-project.test.js +0 -502
  847. package/dist/telemetry/command-hook.test.d.ts +0 -1
  848. package/dist/telemetry/command-hook.test.js +0 -31
  849. package/dist/telemetry/demo-detect.test.d.ts +0 -1
  850. package/dist/telemetry/demo-detect.test.js +0 -22
  851. package/dist/telemetry/emitter.test.d.ts +0 -1
  852. package/dist/telemetry/emitter.test.js +0 -103
  853. package/dist/telemetry/events.snapshot.test.d.ts +0 -1
  854. package/dist/telemetry/events.snapshot.test.js +0 -135
  855. package/dist/telemetry/events.test.d.ts +0 -1
  856. package/dist/telemetry/events.test.js +0 -136
  857. package/dist/telemetry/identity.test.d.ts +0 -1
  858. package/dist/telemetry/identity.test.js +0 -148
  859. package/dist/telemetry/project-snapshot.test.d.ts +0 -1
  860. package/dist/telemetry/project-snapshot.test.js +0 -71
  861. package/dist/telemetry/schema-writer.test.d.ts +0 -1
  862. package/dist/telemetry/schema-writer.test.js +0 -23
  863. package/dist/telemetry/scrubber.test.d.ts +0 -1
  864. package/dist/telemetry/scrubber.test.js +0 -21
  865. package/dist/text-ingest.test.d.ts +0 -1
  866. package/dist/text-ingest.test.js +0 -247
  867. package/dist/tree-picker-state.test.d.ts +0 -1
  868. package/dist/tree-picker-state.test.js +0 -303
  869. package/dist/tree-picker-tui.test.d.ts +0 -1
  870. package/dist/tree-picker-tui.test.js +0 -248
  871. package/dist/viz-fallback.test.d.ts +0 -1
  872. package/dist/viz-fallback.test.js +0 -77
@@ -1,1899 +0,0 @@
1
- import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { beforeEach, describe, expect, it, vi } from 'vitest';
5
- import { addTouchedSlSource } from '../../context/tools/touched-sl-sources.js';
6
- import { IngestBundleRunner } from './ingest-bundle.runner.js';
7
- import { createMemoryFlowLiveBuffer } from './memory-flow/live-buffer.js';
8
- class TestJobContext {
9
- jobId;
10
- userId;
11
- checkCancellation;
12
- updateProgressFn;
13
- parent;
14
- start;
15
- span;
16
- currentProgress = 0;
17
- constructor(jobId, userId, checkCancellation, updateProgressFn, parent, start = 0, span = 1) {
18
- this.jobId = jobId;
19
- this.userId = userId;
20
- this.checkCancellation = checkCancellation;
21
- this.updateProgressFn = updateProgressFn;
22
- this.parent = parent;
23
- this.start = start;
24
- this.span = span;
25
- }
26
- async updateProgress(progress, message) {
27
- const local = Math.max(0, Math.min(1, progress));
28
- this.currentProgress = local;
29
- if (this.parent) {
30
- await this.parent.updateProgress(Math.max(0, Math.min(1, this.start + this.span * local)), message);
31
- return;
32
- }
33
- await this.updateProgressFn(local, message);
34
- }
35
- startPhase(fraction) {
36
- return new TestJobContext(this.jobId, this.userId, this.checkCancellation, this.updateProgressFn, this, this.currentProgress, Math.max(0, Math.min(1, fraction)));
37
- }
38
- }
39
- const deferred = () => {
40
- let resolve;
41
- const promise = new Promise((r) => {
42
- resolve = r;
43
- });
44
- return { promise, resolve };
45
- };
46
- function bundleReplayInput() {
47
- return {
48
- runId: 'pending',
49
- connectionId: 'c1',
50
- adapter: 'fake',
51
- status: 'running',
52
- sourceDir: '/tmp/stage/upload-x',
53
- syncId: 'pending',
54
- errors: [],
55
- events: [],
56
- plannedWorkUnits: [],
57
- details: { actions: [], provenance: [], transcripts: [] },
58
- };
59
- }
60
- const makeDeps = () => {
61
- const runsRepo = {
62
- create: vi.fn().mockResolvedValue({ id: 'run-1' }),
63
- findMostRecentCompleted: vi.fn().mockResolvedValue(null),
64
- markFailed: vi.fn(),
65
- markCompleted: vi.fn(),
66
- };
67
- const provenanceRepo = {
68
- insertMany: vi.fn(),
69
- findHashesBySync: vi.fn().mockResolvedValue(new Map()),
70
- findLatestArtifactsForRawPaths: vi.fn().mockResolvedValue(new Map()),
71
- };
72
- const reportsRepo = {
73
- create: vi.fn().mockResolvedValue({ id: 'report-1' }),
74
- findByJobId: vi.fn().mockResolvedValue(null),
75
- markSuperseded: vi.fn().mockResolvedValue(undefined),
76
- };
77
- const canonicalPins = {
78
- listPins: vi.fn().mockResolvedValue([]),
79
- };
80
- const adapter = {
81
- source: 'fake',
82
- skillNames: [],
83
- reconcileSkillNames: undefined,
84
- evidenceIndexing: undefined,
85
- triageSupported: undefined,
86
- detect: vi.fn().mockResolvedValue(true),
87
- listTargetConnectionIds: undefined,
88
- finalize: undefined,
89
- chunk: vi.fn().mockResolvedValue({
90
- workUnits: [{ unitKey: 'u1', rawFiles: ['a.yml'], peerFileIndex: [], dependencyPaths: [] }],
91
- }),
92
- };
93
- const registry = { get: vi.fn().mockReturnValue(adapter) };
94
- const diffSetService = {
95
- compute: vi.fn().mockResolvedValue({ added: ['a.yml'], modified: [], deleted: [], unchanged: [] }),
96
- };
97
- const contextEvidenceIndex = {
98
- indexStagedDir: vi.fn().mockResolvedValue({
99
- documentsIndexed: 1,
100
- chunksIndexed: 1,
101
- documentsDeleted: 0,
102
- embeddingFailures: 0,
103
- warnings: [],
104
- }),
105
- publishSync: vi.fn().mockResolvedValue(undefined),
106
- };
107
- const pageTriage = {
108
- triageRun: vi.fn().mockResolvedValue({
109
- enabled: true,
110
- fullRawPaths: new Set(['a.yml']),
111
- warnings: [],
112
- }),
113
- };
114
- const scopedGit = {
115
- revParseHead: vi.fn().mockResolvedValue('h'),
116
- commitFiles: vi.fn().mockResolvedValue({ created: true, commitHash: 'h' }),
117
- commitStaged: vi.fn().mockResolvedValue({ created: false, commitHash: 'h' }),
118
- resetHardTo: vi.fn(),
119
- assertWorktreeClean: vi.fn().mockResolvedValue(undefined),
120
- writeBinaryNoRenamePatch: vi.fn(async (_base, _head, patchPath) => {
121
- await writeFile(patchPath, '', 'utf-8');
122
- }),
123
- applyPatchFile3WayIndex: vi.fn(),
124
- diffNameStatus: vi.fn().mockResolvedValue([]),
125
- changedPaths: vi.fn().mockResolvedValue([]),
126
- };
127
- const sessionWorktreeService = {
128
- create: vi.fn().mockResolvedValue({
129
- chatId: 'j1',
130
- workdir: '/tmp/wt',
131
- branch: 'session/j1',
132
- baseSha: 'b',
133
- createdAt: new Date(),
134
- git: scopedGit,
135
- config: {},
136
- }),
137
- cleanup: vi.fn(),
138
- };
139
- const agentRunner = { runLoop: vi.fn().mockResolvedValue({ stopReason: 'natural' }) };
140
- const gitService = {
141
- revParseHead: vi.fn().mockResolvedValue('base'),
142
- listFilesAtHead: vi.fn().mockResolvedValue([]),
143
- getFileAtCommit: vi.fn(),
144
- squashMergeIntoMain: vi
145
- .fn()
146
- .mockResolvedValue({ ok: true, squashSha: 'sq', touchedPaths: ['raw-sources/c1/fake/s/a.yml'] }),
147
- };
148
- const lockingService = {
149
- withLock: vi.fn().mockImplementation(async (_k, fn) => fn()),
150
- };
151
- const appSettingsService = {
152
- settings: {
153
- ai: { slValidation: { probeRowCount: 1 } },
154
- llm: { memoryIngestionModel: 'test-model' },
155
- },
156
- };
157
- const skillsRegistry = {
158
- listSkills: vi.fn().mockResolvedValue([]),
159
- getSkill: vi.fn().mockResolvedValue(null),
160
- buildSkillsPrompt: vi.fn().mockReturnValue(''),
161
- stripFrontmatter: vi.fn().mockImplementation((s) => s),
162
- };
163
- const promptService = {
164
- loadPrompt: vi.fn().mockResolvedValue('base-framing'),
165
- };
166
- const wikiService = {
167
- forWorktree: vi.fn(),
168
- listPageKeys: vi.fn().mockResolvedValue([]),
169
- readPage: vi.fn().mockResolvedValue(null),
170
- syncFromCommit: vi.fn().mockResolvedValue(undefined),
171
- };
172
- wikiService.forWorktree.mockReturnValue(wikiService);
173
- const knowledgeSlRefs = {
174
- syncFromWiki: vi.fn().mockResolvedValue({ inserted: 1, deleted: 0 }),
175
- };
176
- const knowledgeIndex = {
177
- listPagesForUser: vi.fn().mockResolvedValue([]),
178
- };
179
- const semanticLayerService = {
180
- forWorktree: vi.fn(),
181
- listFilesForConnection: vi
182
- .fn()
183
- .mockImplementation((connectionId) => Promise.resolve(connectionId === 'warehouse-2' ? ['looker__orders.yaml'] : [])),
184
- loadAllSources: vi
185
- .fn()
186
- .mockImplementation((connectionId) => Promise.resolve({
187
- sources: connectionId === 'warehouse-2' ? [{ name: 'looker__orders' }] : [],
188
- loadErrors: [],
189
- })),
190
- };
191
- semanticLayerService.forWorktree.mockReturnValue(semanticLayerService);
192
- const slSearchService = {
193
- indexSources: vi.fn().mockResolvedValue(undefined),
194
- };
195
- const slSourcesRepository = {};
196
- const slValidator = { validateSingleSource: vi.fn().mockResolvedValue({ errors: [], warnings: [] }) };
197
- const toolsetFactory = {
198
- createIngestWuToolset: vi.fn().mockReturnValue({
199
- toRuntimeTools: vi.fn().mockReturnValue({}),
200
- getAllTools: vi.fn().mockReturnValue([]),
201
- getToolNames: vi.fn().mockReturnValue([]),
202
- }),
203
- };
204
- const configService = {
205
- enqueueCommitMessageJobForExternalCommit: vi.fn().mockResolvedValue(undefined),
206
- };
207
- return {
208
- runsRepo,
209
- provenanceRepo,
210
- reportsRepo,
211
- canonicalPins,
212
- adapter,
213
- registry,
214
- diffSetService,
215
- contextEvidenceIndex,
216
- pageTriage,
217
- sessionWorktreeService,
218
- agentRunner,
219
- gitService,
220
- lockingService,
221
- slValidator,
222
- appSettingsService,
223
- skillsRegistry,
224
- promptService,
225
- wikiService,
226
- knowledgeSlRefs,
227
- knowledgeIndex,
228
- semanticLayerService,
229
- slSearchService,
230
- slSourcesRepository,
231
- toolsetFactory,
232
- configService,
233
- };
234
- };
235
- const buildRunner = (deps = makeDeps(), overrides = {}) => new IngestBundleRunner({
236
- runs: deps.runsRepo,
237
- provenance: deps.provenanceRepo,
238
- registry: deps.registry,
239
- diffSetService: deps.diffSetService,
240
- contextEvidenceIndex: deps.contextEvidenceIndex,
241
- pageTriage: deps.pageTriage,
242
- sessionWorktreeService: deps.sessionWorktreeService,
243
- agentRunner: deps.agentRunner,
244
- gitService: deps.gitService,
245
- lockingService: deps.lockingService,
246
- storage: {
247
- homeDir: '/tmp/ktx-test',
248
- systemGitAuthor: { name: 'KTX Test', email: 'system@ktx.local' },
249
- resolveUploadDir: (uploadId) => `/tmp/ktx-test/ingest-uploads/${uploadId}`,
250
- resolvePullDir: (jobId) => `/tmp/ktx-test/ingest-pulls/${jobId}`,
251
- resolveTranscriptDir: (jobId) => `/tmp/ktx-test/run/wu-transcripts/${jobId}`,
252
- resolveTracePath: (jobId) => `/tmp/ktx-test/ingest-traces/${jobId}/trace.jsonl`,
253
- },
254
- settings: {
255
- probeRowCount: 1,
256
- memoryIngestionModel: 'test-model',
257
- },
258
- skillsRegistry: deps.skillsRegistry,
259
- promptService: deps.promptService,
260
- wikiService: deps.wikiService,
261
- knowledgeSlRefs: deps.knowledgeSlRefs,
262
- knowledgeIndex: deps.knowledgeIndex,
263
- semanticLayerService: deps.semanticLayerService,
264
- slSearchService: deps.slSearchService,
265
- slSourcesRepository: deps.slSourcesRepository,
266
- connections: {
267
- listEnabledConnections: vi.fn().mockResolvedValue([]),
268
- getConnectionById: vi.fn().mockResolvedValue({ id: 'c1', name: 'warehouse', connectionType: 'POSTGRES' }),
269
- executeQuery: vi.fn().mockResolvedValue({ headers: [], rows: [] }),
270
- },
271
- reports: deps.reportsRepo,
272
- canonicalPins: deps.canonicalPins,
273
- slValidator: deps.slValidator,
274
- toolsetFactory: deps.toolsetFactory,
275
- commitMessages: {
276
- enqueueForExternalCommit: deps.configService.enqueueCommitMessageJobForExternalCommit,
277
- },
278
- embedding: {
279
- maxBatchSize: 10,
280
- computeEmbedding: async () => [0],
281
- computeEmbeddingsBulk: async (texts) => texts.map(() => [0]),
282
- },
283
- ...overrides,
284
- });
285
- describe('IngestBundleRunner — FIFO-per-connection', () => {
286
- let spy;
287
- beforeEach(() => {
288
- spy = vi.fn();
289
- });
290
- it('serializes two jobs on the same connectionId', async () => {
291
- const runner = buildRunner();
292
- runner.runInner = async (job) => {
293
- spy(job.jobId);
294
- await new Promise((r) => setTimeout(r, 5));
295
- spy(`done-${job.jobId}`);
296
- return {
297
- runId: 'r',
298
- syncId: 's',
299
- diffSummary: { added: 0, modified: 0, deleted: 0, unchanged: 0 },
300
- workUnitCount: 0,
301
- failedWorkUnits: [],
302
- artifactsWritten: 0,
303
- commitSha: null,
304
- };
305
- };
306
- const p1 = runner.run({
307
- jobId: 'j1',
308
- connectionId: 'c1',
309
- sourceKey: 'fake',
310
- trigger: 'upload',
311
- bundleRef: { kind: 'upload', uploadId: 'u1' },
312
- });
313
- const p2 = runner.run({
314
- jobId: 'j2',
315
- connectionId: 'c1',
316
- sourceKey: 'fake',
317
- trigger: 'upload',
318
- bundleRef: { kind: 'upload', uploadId: 'u2' },
319
- });
320
- await Promise.all([p1, p2]);
321
- expect(spy.mock.calls.map((c) => c[0])).toEqual(['j1', 'done-j1', 'j2', 'done-j2']);
322
- });
323
- it('runs jobs on different connections in parallel', async () => {
324
- const runner = buildRunner();
325
- const d1 = deferred();
326
- const d2 = deferred();
327
- runner.runInner = async (job) => {
328
- spy(`start-${job.jobId}`);
329
- if (job.jobId === 'j1') {
330
- await d1.promise;
331
- }
332
- if (job.jobId === 'j2') {
333
- await d2.promise;
334
- }
335
- return {
336
- runId: 'r',
337
- syncId: 's',
338
- diffSummary: { added: 0, modified: 0, deleted: 0, unchanged: 0 },
339
- workUnitCount: 0,
340
- failedWorkUnits: [],
341
- artifactsWritten: 0,
342
- commitSha: null,
343
- };
344
- };
345
- const p1 = runner.run({
346
- jobId: 'j1',
347
- connectionId: 'c1',
348
- sourceKey: 'fake',
349
- trigger: 'upload',
350
- bundleRef: { kind: 'upload', uploadId: 'u1' },
351
- });
352
- const p2 = runner.run({
353
- jobId: 'j2',
354
- connectionId: 'c2',
355
- sourceKey: 'fake',
356
- trigger: 'upload',
357
- bundleRef: { kind: 'upload', uploadId: 'u2' },
358
- });
359
- await new Promise((r) => setTimeout(r, 10));
360
- expect(spy.mock.calls.map((c) => c[0]).sort()).toEqual(['start-j1', 'start-j2']);
361
- d1.resolve();
362
- d2.resolve();
363
- await Promise.all([p1, p2]);
364
- });
365
- });
366
- describe('IngestBundleRunner — Stages 1 → 7', () => {
367
- it('runs the full pipeline, creates a run row, stages files, chunks, squashes, writes provenance', async () => {
368
- const deps = makeDeps();
369
- const runner = buildRunner(deps);
370
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
371
- currentHashes: new Map([['a.yml', 'h1']]),
372
- rawDirInWorktree: 'raw-sources/c1/fake/s',
373
- });
374
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
375
- const result = await runner.run({
376
- jobId: 'j1',
377
- connectionId: 'c1',
378
- sourceKey: 'fake',
379
- trigger: 'upload',
380
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
381
- });
382
- expect(deps.runsRepo.create).toHaveBeenCalledWith(expect.objectContaining({ jobId: 'j1', connectionId: 'c1', sourceKey: 'fake', trigger: 'upload' }));
383
- expect(deps.adapter.detect).toHaveBeenCalled();
384
- expect(deps.adapter.chunk).toHaveBeenCalled();
385
- expect(result.workUnitCount).toBe(1);
386
- expect(deps.diffSetService.compute).toHaveBeenCalled();
387
- expect(deps.gitService.squashMergeIntoMain).toHaveBeenCalledWith('session/j1', expect.any(String), expect.any(String), expect.stringContaining('ingest(fake): j1'));
388
- expect(deps.provenanceRepo.insertMany).toHaveBeenCalled();
389
- expect(result.commitSha).toBe('sq');
390
- expect(deps.runsRepo.markCompleted).toHaveBeenCalledWith('run-1', expect.any(Object), 'completed');
391
- // Single touched path → path-scoped diff for the LLM commit-message note.
392
- expect(deps.configService.enqueueCommitMessageJobForExternalCommit).toHaveBeenCalledWith({ commitHash: 'sq' }, expect.stringContaining('ingest(fake): j1'), 'raw-sources/c1/fake/s/a.yml');
393
- });
394
- it('fails before squash when reconciliation leaves a touched wiki page with dangling refs', async () => {
395
- const deps = makeDeps();
396
- let currentToolSession = null;
397
- const scopedWiki = {
398
- listPageKeys: vi.fn().mockResolvedValue(['page-a']),
399
- readPage: vi.fn().mockImplementation((_scope, _scopeId, key) => {
400
- if (key === 'page-a') {
401
- return Promise.resolve({
402
- pageKey: 'page-a',
403
- frontmatter: { summary: 'Page A', usage_mode: 'auto', refs: ['missing-page'] },
404
- content: 'See [[missing-page]].',
405
- });
406
- }
407
- return Promise.resolve(null);
408
- }),
409
- };
410
- deps.wikiService.forWorktree.mockReturnValue(scopedWiki);
411
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
412
- currentToolSession = toolSession;
413
- return {
414
- toRuntimeTools: vi.fn().mockReturnValue({}),
415
- getAllTools: vi.fn().mockReturnValue([]),
416
- getToolNames: vi.fn().mockReturnValue([]),
417
- };
418
- });
419
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
420
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
421
- currentToolSession.actions.push({ target: 'sl', type: 'updated', key: 'orders', detail: 'Orders source' });
422
- }
423
- if (params.telemetryTags.operationName === 'ingest-bundle-reconcile') {
424
- currentToolSession.actions.push({ target: 'wiki', type: 'created', key: 'page-a', detail: 'Page A' });
425
- }
426
- return { stopReason: 'natural' };
427
- });
428
- const runner = buildRunner(deps);
429
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
430
- currentHashes: new Map([['a.yml', 'h1']]),
431
- rawDirInWorktree: 'raw-sources/c1/fake/s',
432
- });
433
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
434
- await expect(runner.run({
435
- jobId: 'j1',
436
- connectionId: 'c1',
437
- sourceKey: 'fake',
438
- trigger: 'upload',
439
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
440
- })).rejects.toThrow(/wiki references target missing page\(s\): page-a -> missing-page/);
441
- expect(deps.runsRepo.markFailed).toHaveBeenCalledWith('run-1');
442
- expect(deps.gitService.squashMergeIntoMain).not.toHaveBeenCalled();
443
- });
444
- it('allows reconciliation to save circular wiki refs once both pages exist', async () => {
445
- const deps = makeDeps();
446
- let currentToolSession = null;
447
- const scopedWiki = {
448
- listPageKeys: vi.fn().mockResolvedValue(['page-a', 'page-b']),
449
- readPage: vi.fn().mockImplementation((_scope, _scopeId, key) => {
450
- if (key === 'page-a') {
451
- return Promise.resolve({
452
- pageKey: 'page-a',
453
- frontmatter: { summary: 'Page A', usage_mode: 'auto', refs: ['page-b'] },
454
- content: 'See [[page-b]].',
455
- });
456
- }
457
- if (key === 'page-b') {
458
- return Promise.resolve({
459
- pageKey: 'page-b',
460
- frontmatter: { summary: 'Page B', usage_mode: 'auto', refs: ['page-a'] },
461
- content: 'See [[page-a]].',
462
- });
463
- }
464
- return Promise.resolve(null);
465
- }),
466
- };
467
- deps.wikiService.forWorktree.mockReturnValue(scopedWiki);
468
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
469
- currentToolSession = toolSession;
470
- return {
471
- toRuntimeTools: vi.fn().mockReturnValue({}),
472
- getAllTools: vi.fn().mockReturnValue([]),
473
- getToolNames: vi.fn().mockReturnValue([]),
474
- };
475
- });
476
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
477
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
478
- currentToolSession.actions.push({ target: 'sl', type: 'updated', key: 'orders', detail: 'Orders source' });
479
- }
480
- if (params.telemetryTags.operationName === 'ingest-bundle-reconcile') {
481
- currentToolSession.actions.push({ target: 'wiki', type: 'created', key: 'page-a', detail: 'Page A' }, { target: 'wiki', type: 'created', key: 'page-b', detail: 'Page B' });
482
- }
483
- return { stopReason: 'natural' };
484
- });
485
- const runner = buildRunner(deps);
486
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
487
- currentHashes: new Map([['a.yml', 'h1']]),
488
- rawDirInWorktree: 'raw-sources/c1/fake/s',
489
- });
490
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
491
- const result = await runner.run({
492
- jobId: 'j1',
493
- connectionId: 'c1',
494
- sourceKey: 'fake',
495
- trigger: 'upload',
496
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
497
- });
498
- expect(result.failedWorkUnits).toEqual([]);
499
- expect(deps.gitService.squashMergeIntoMain).toHaveBeenCalled();
500
- expect(deps.runsRepo.markFailed).not.toHaveBeenCalled();
501
- });
502
- it('threads target warehouse connection names into WorkUnit and reconcile tool sessions', async () => {
503
- const deps = makeDeps();
504
- const sessions = [];
505
- deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['warehouse']);
506
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
507
- sessions.push(toolSession);
508
- return {
509
- toRuntimeTools: vi.fn().mockReturnValue({}),
510
- getAllTools: vi.fn().mockReturnValue([]),
511
- getToolNames: vi.fn().mockReturnValue([]),
512
- };
513
- });
514
- deps.agentRunner.runLoop.mockResolvedValue({ stopReason: 'natural' });
515
- const runner = buildRunner(deps);
516
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
517
- currentHashes: new Map([['a.yml', 'h1']]),
518
- rawDirInWorktree: 'raw-sources/notion/fake/s',
519
- });
520
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
521
- await runner.run({
522
- jobId: 'j1',
523
- connectionId: 'notion',
524
- sourceKey: 'fake',
525
- trigger: 'upload',
526
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
527
- });
528
- expect([...sessions[0].allowedConnectionNames].sort()).toEqual(['notion', 'warehouse']);
529
- });
530
- it('reuses document evidence indexing and page triage for document WorkUnits', async () => {
531
- const deps = makeDeps();
532
- deps.adapter.source = 'notion';
533
- deps.adapter.skillNames = ['notion_synthesize'];
534
- deps.adapter.reconcileSkillNames = [];
535
- deps.adapter.evidenceIndexing = 'documents';
536
- deps.adapter.triageSupported = true;
537
- deps.adapter.chunk.mockResolvedValue({
538
- workUnits: [
539
- { unitKey: 'full', rawFiles: ['pages/full/metadata.json'], dependencyPaths: [], peerFileIndex: [] },
540
- { unitKey: 'skip', rawFiles: ['pages/skip/metadata.json'], dependencyPaths: [], peerFileIndex: [] },
541
- ],
542
- });
543
- deps.diffSetService.compute.mockResolvedValue({
544
- added: ['pages/full/metadata.json', 'pages/skip/metadata.json'],
545
- modified: [],
546
- deleted: [],
547
- unchanged: [],
548
- });
549
- deps.pageTriage.triageRun.mockResolvedValue({
550
- enabled: true,
551
- fullRawPaths: new Set(['pages/full/metadata.json']),
552
- warnings: [],
553
- });
554
- const runner = buildRunner(deps);
555
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
556
- currentHashes: new Map([
557
- ['pages/full/metadata.json', 'h-full'],
558
- ['pages/skip/metadata.json', 'h-skip'],
559
- ]),
560
- rawDirInWorktree: 'raw-sources/c1/notion/s',
561
- });
562
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
563
- const result = await runner.run({
564
- jobId: 'j1',
565
- connectionId: 'c1',
566
- sourceKey: 'notion',
567
- trigger: 'upload',
568
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
569
- });
570
- const workUnitCalls = deps.agentRunner.runLoop.mock.calls.filter(([params]) => params.telemetryTags?.operationName === 'ingest-bundle-wu');
571
- expect(deps.contextEvidenceIndex.indexStagedDir).toHaveBeenCalled();
572
- expect(deps.pageTriage.triageRun).toHaveBeenCalled();
573
- expect(workUnitCalls).toHaveLength(1);
574
- expect(workUnitCalls[0][0].telemetryTags.unitKey).toBe('full');
575
- expect(result.workUnitCount).toBe(1);
576
- });
577
- it('emits memory-flow source and planning events for bundle ingest', async () => {
578
- const deps = makeDeps();
579
- deps.adapter.chunk.mockResolvedValue({
580
- workUnits: [
581
- {
582
- unitKey: 'u1',
583
- rawFiles: ['a.yml'],
584
- peerFileIndex: ['peer.yml'],
585
- dependencyPaths: ['manifest.yml'],
586
- },
587
- ],
588
- eviction: { deletedRawPaths: ['old.yml'] },
589
- });
590
- const runner = buildRunner(deps);
591
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
592
- currentHashes: new Map([['a.yml', 'h1']]),
593
- rawDirInWorktree: 'raw-sources/c1/fake/s',
594
- });
595
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
596
- const snapshots = [];
597
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput(), {
598
- onChange: (snapshot) => snapshots.push(snapshot),
599
- });
600
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve());
601
- ctx.memoryFlow = memoryFlow;
602
- await runner.run({
603
- jobId: 'j1',
604
- connectionId: 'c1',
605
- sourceKey: 'fake',
606
- trigger: 'upload',
607
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
608
- }, ctx);
609
- expect(memoryFlow.snapshot()).toMatchObject({
610
- runId: 'run-1',
611
- connectionId: 'c1',
612
- adapter: 'fake',
613
- sourceDir: '/tmp/stage/upload-x',
614
- });
615
- expect(memoryFlow.snapshot().plannedWorkUnits).toEqual([
616
- {
617
- unitKey: 'u1',
618
- rawFiles: ['a.yml'],
619
- peerFileCount: 1,
620
- dependencyCount: 1,
621
- },
622
- ]);
623
- expect(memoryFlow.snapshot().events).toEqual(expect.arrayContaining([
624
- expect.objectContaining({ type: 'source_acquired', adapter: 'fake', trigger: 'upload', fileCount: 1 }),
625
- expect.objectContaining({ type: 'scope_detected', fingerprint: null }),
626
- expect.objectContaining({ type: 'raw_snapshot_written', rawFileCount: 1 }),
627
- expect.objectContaining({ type: 'diff_computed', added: 1, modified: 0, deleted: 0, unchanged: 0 }),
628
- expect.objectContaining({ type: 'chunks_planned', chunkCount: 1, workUnitCount: 1, evictionCount: 1 }),
629
- ]));
630
- expect(snapshots.length).toBeGreaterThan(4);
631
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
632
- body: expect.objectContaining({
633
- memoryFlow: expect.objectContaining({
634
- metadata: expect.objectContaining({
635
- schemaVersion: 1,
636
- mode: 'full',
637
- origin: 'captured',
638
- timing: 'captured',
639
- }),
640
- events: expect.arrayContaining([
641
- expect.objectContaining({
642
- type: 'source_acquired',
643
- emittedAt: expect.stringMatching(/^\d{4}-\d{2}-\d{2}T/),
644
- }),
645
- ]),
646
- }),
647
- }),
648
- }));
649
- });
650
- it('emits memory-flow WorkUnit step, candidate action, and finish events', async () => {
651
- const deps = makeDeps();
652
- let currentToolSession = null;
653
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
654
- currentToolSession = toolSession;
655
- return {
656
- toRuntimeTools: vi.fn().mockReturnValue({}),
657
- getAllTools: vi.fn().mockReturnValue([]),
658
- getToolNames: vi.fn().mockReturnValue([]),
659
- };
660
- });
661
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
662
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
663
- await params.onStepFinish?.({ stepIndex: 1, stepBudget: params.stepBudget });
664
- currentToolSession.actions.push({
665
- target: 'wiki',
666
- type: 'created',
667
- key: 'wiki/orders.md',
668
- detail: 'captured order context',
669
- });
670
- }
671
- return { stopReason: 'natural' };
672
- });
673
- const runner = buildRunner(deps);
674
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
675
- currentHashes: new Map([['a.yml', 'h1']]),
676
- rawDirInWorktree: 'raw-sources/c1/fake/s',
677
- });
678
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
679
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput());
680
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve());
681
- ctx.memoryFlow = memoryFlow;
682
- await runner.run({
683
- jobId: 'j1',
684
- connectionId: 'c1',
685
- sourceKey: 'fake',
686
- trigger: 'upload',
687
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
688
- }, ctx);
689
- expect(memoryFlow.snapshot().events).toEqual(expect.arrayContaining([
690
- expect.objectContaining({
691
- type: 'work_unit_started',
692
- unitKey: 'u1',
693
- skills: ['ingest_triage', 'sl_capture', 'wiki_capture'],
694
- stepBudget: 40,
695
- }),
696
- expect.objectContaining({ type: 'work_unit_step', unitKey: 'u1', stepIndex: 1, stepBudget: 40 }),
697
- expect.objectContaining({
698
- type: 'candidate_action',
699
- unitKey: 'u1',
700
- target: 'wiki',
701
- action: 'created',
702
- key: 'wiki/orders.md',
703
- }),
704
- expect.objectContaining({ type: 'work_unit_finished', unitKey: 'u1', status: 'success' }),
705
- ]));
706
- });
707
- it('emits memory-flow gate, saved, provenance, and report events', async () => {
708
- const deps = makeDeps();
709
- let currentToolSession = null;
710
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
711
- currentToolSession = toolSession;
712
- return {
713
- toRuntimeTools: vi.fn().mockReturnValue({}),
714
- getAllTools: vi.fn().mockReturnValue([]),
715
- getToolNames: vi.fn().mockReturnValue([]),
716
- };
717
- });
718
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
719
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
720
- currentToolSession.actions.push({
721
- target: 'sl',
722
- type: 'updated',
723
- key: 'orders',
724
- detail: 'captured gross revenue',
725
- });
726
- }
727
- if (params.telemetryTags.operationName === 'ingest-bundle-reconcile') {
728
- await params.toolSet.record_verification_ledger.execute({
729
- summary: 'Reconciliation emits no warehouse identifiers before fallback recording.',
730
- verifiedIdentifiers: [],
731
- unverifiedIdentifiers: [],
732
- }, { toolCallId: 'ledger-1', messages: [] });
733
- await params.toolSet.emit_conflict_resolution.execute({
734
- kind: 'near_duplicate',
735
- artifactKey: 'sl:orders',
736
- detail: 'orders retained as canonical',
737
- flaggedForHuman: false,
738
- }, { toolCallId: 'conflict-1', messages: [] });
739
- await params.toolSet.emit_unmapped_fallback.execute({
740
- rawPath: 'a.yml',
741
- reason: 'parse_error',
742
- clarification: 'semantic_not_representable',
743
- fallback: 'flagged',
744
- }, { toolCallId: 'fallback-1', messages: [] });
745
- }
746
- return { stopReason: 'natural' };
747
- });
748
- const runner = buildRunner(deps);
749
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
750
- currentHashes: new Map([['a.yml', 'h1']]),
751
- rawDirInWorktree: 'raw-sources/c1/fake/s',
752
- });
753
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
754
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput());
755
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve());
756
- ctx.memoryFlow = memoryFlow;
757
- await runner.run({
758
- jobId: 'j1',
759
- connectionId: 'c1',
760
- sourceKey: 'fake',
761
- trigger: 'upload',
762
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
763
- }, ctx);
764
- expect(memoryFlow.snapshot()).toMatchObject({
765
- reportId: 'report-1',
766
- reportPath: 'report-1',
767
- });
768
- expect(memoryFlow.snapshot().events).toEqual(expect.arrayContaining([
769
- expect.objectContaining({ type: 'reconciliation_finished', conflictCount: 1, fallbackCount: 1 }),
770
- expect.objectContaining({ type: 'saved', commitSha: 'sq', wikiCount: 0, slCount: 1 }),
771
- expect.objectContaining({ type: 'provenance_recorded', rowCount: 1 }),
772
- expect.objectContaining({ type: 'report_created', runId: 'run-1', reportPath: 'report-1' }),
773
- ]));
774
- });
775
- it('finishes successful bundle memory-flow runs as done', async () => {
776
- const deps = makeDeps();
777
- const runner = buildRunner(deps);
778
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
779
- currentHashes: new Map([['a.yml', 'h1']]),
780
- rawDirInWorktree: 'raw-sources/c1/fake/s',
781
- });
782
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
783
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput());
784
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve());
785
- ctx.memoryFlow = memoryFlow;
786
- await runner.run({
787
- jobId: 'j1',
788
- connectionId: 'c1',
789
- sourceKey: 'fake',
790
- trigger: 'upload',
791
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
792
- }, ctx);
793
- expect(memoryFlow.snapshot().status).toBe('done');
794
- });
795
- it('finishes bundle memory-flow runs with sanitized errors when the runner fails', async () => {
796
- const deps = makeDeps();
797
- const sensitiveMessage = [
798
- 'failed to read postgres://user',
799
- ':password',
800
- '@localhost:5432/db?api_key=abc',
801
- ' token=',
802
- 'secret',
803
- ].join('');
804
- deps.adapter.detect.mockRejectedValue(new Error(sensitiveMessage));
805
- const runner = buildRunner(deps);
806
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
807
- currentHashes: new Map([['a.yml', 'h1']]),
808
- rawDirInWorktree: 'raw-sources/c1/fake/s',
809
- });
810
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
811
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput());
812
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve());
813
- ctx.memoryFlow = memoryFlow;
814
- await expect(runner.run({
815
- jobId: 'j1',
816
- connectionId: 'c1',
817
- sourceKey: 'fake',
818
- trigger: 'upload',
819
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
820
- }, ctx)).rejects.toThrow(/failed to read/);
821
- expect(memoryFlow.snapshot()).toMatchObject({
822
- status: 'error',
823
- errors: ['failed to read postgres://[redacted] token=[redacted]'],
824
- });
825
- expect(memoryFlow.snapshot().events).toEqual(expect.arrayContaining([
826
- expect.objectContaining({ type: 'source_acquired', adapter: 'fake', trigger: 'upload', fileCount: 1 }),
827
- ]));
828
- });
829
- it('stores memory-flow provenance and transcript summaries in the ingest report body', async () => {
830
- const deps = makeDeps();
831
- deps.toolsetFactory.createIngestWuToolset.mockReturnValue({
832
- toRuntimeTools: vi.fn().mockReturnValue({
833
- read_raw_span: {
834
- description: 'read a raw span',
835
- inputSchema: {},
836
- execute: vi.fn().mockResolvedValue('safe excerpt'),
837
- },
838
- wiki_write: {
839
- description: 'write wiki',
840
- inputSchema: {},
841
- execute: vi.fn().mockResolvedValue('written'),
842
- },
843
- }),
844
- getAllTools: vi.fn().mockReturnValue([]),
845
- getToolNames: vi.fn().mockReturnValue([]),
846
- });
847
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
848
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
849
- await params.toolSet.read_raw_span.execute({ path: 'a.yml', startLine: 1, endLine: 2 }, { toolCallId: 'read-1', messages: [] });
850
- await params.toolSet.record_verification_ledger.execute({
851
- summary: 'Wiki write contains no warehouse identifiers.',
852
- verifiedIdentifiers: [],
853
- unverifiedIdentifiers: [],
854
- }, { toolCallId: 'ledger-1', messages: [] });
855
- await params.toolSet.wiki_write.execute({ key: 'wiki/a.md', content: 'safe summary' }, { toolCallId: 'wiki-1', messages: [] });
856
- }
857
- return { stopReason: 'natural' };
858
- });
859
- const runner = buildRunner(deps);
860
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
861
- currentHashes: new Map([['a.yml', 'h1']]),
862
- rawDirInWorktree: 'raw-sources/c1/fake/s',
863
- });
864
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
865
- await runner.run({
866
- jobId: 'j1',
867
- connectionId: 'c1',
868
- sourceKey: 'fake',
869
- trigger: 'upload',
870
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
871
- });
872
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
873
- body: expect.objectContaining({
874
- provenanceRows: [
875
- expect.objectContaining({
876
- rawPath: 'a.yml',
877
- artifactKind: null,
878
- artifactKey: null,
879
- actionType: 'skipped',
880
- targetConnectionId: null,
881
- }),
882
- ],
883
- toolTranscripts: [
884
- {
885
- unitKey: 'u1',
886
- path: '/tmp/ktx-test/run/wu-transcripts/j1/u1.jsonl',
887
- toolCallCount: 3,
888
- errorCount: 0,
889
- toolNames: ['read_raw_span', 'record_verification_ledger', 'wiki_write'],
890
- },
891
- ],
892
- }),
893
- }));
894
- });
895
- it('persists WorkUnit unmapped fallback records in the report body', async () => {
896
- const deps = makeDeps();
897
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
898
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
899
- await params.toolSet.record_verification_ledger.execute({
900
- summary: 'Unmapped fallback records an unsupported conversion metric without verified warehouse identifiers.',
901
- verifiedIdentifiers: [],
902
- unverifiedIdentifiers: [],
903
- }, { toolCallId: 'ledger-1', messages: [] });
904
- await params.toolSet.emit_unmapped_fallback.execute({
905
- rawPath: 'a.yml',
906
- reason: 'conversion_metric_unsupported',
907
- fallback: 'flagged',
908
- }, { toolCallId: 'fallback-1', messages: [] });
909
- }
910
- return { stopReason: 'natural' };
911
- });
912
- const runner = buildRunner(deps);
913
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
914
- currentHashes: new Map([['a.yml', 'h1']]),
915
- rawDirInWorktree: 'raw-sources/c1/fake/s',
916
- });
917
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
918
- await runner.run({
919
- jobId: 'j1',
920
- connectionId: 'c1',
921
- sourceKey: 'fake',
922
- trigger: 'upload',
923
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
924
- });
925
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
926
- body: expect.objectContaining({
927
- unmappedFallbacks: [
928
- {
929
- rawPath: 'a.yml',
930
- reason: 'conversion_metric_unsupported',
931
- detail: expect.stringContaining('conversion metric'),
932
- fallback: 'flagged',
933
- },
934
- ],
935
- }),
936
- }));
937
- });
938
- it('persists reconciliation conflict and eviction records in the report body', async () => {
939
- const deps = makeDeps();
940
- deps.diffSetService.compute.mockResolvedValue({
941
- added: [],
942
- modified: [],
943
- deleted: ['views/old_orders.view.lkml'],
944
- unchanged: [],
945
- });
946
- deps.adapter.chunk.mockResolvedValue({
947
- workUnits: [],
948
- eviction: { deletedRawPaths: ['views/old_orders.view.lkml'] },
949
- });
950
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
951
- if (params.telemetryTags.operationName === 'ingest-bundle-reconcile') {
952
- await params.toolSet.record_verification_ledger.execute({
953
- summary: 'Reconciliation records conflict, eviction, and fallback decisions without warehouse identifiers.',
954
- verifiedIdentifiers: [],
955
- unverifiedIdentifiers: [],
956
- }, { toolCallId: 'ledger-1', messages: [] });
957
- await params.toolSet.emit_conflict_resolution.execute({
958
- kind: 'near_duplicate',
959
- artifactKey: 'sl:orders',
960
- detail: 'orders and old_orders overlapped; orders is retained as canonical',
961
- flaggedForHuman: false,
962
- }, { toolCallId: 'conflict-1', messages: [] });
963
- await params.toolSet.emit_eviction_decision.execute({
964
- rawPath: 'views/old_orders.view.lkml',
965
- artifactKind: 'sl',
966
- artifactKey: 'old_orders',
967
- action: 'removed',
968
- reason: 'raw source disappeared in this sync',
969
- }, { toolCallId: 'eviction-1', messages: [] });
970
- await params.toolSet.emit_unmapped_fallback.execute({
971
- rawPath: 'cards/untranslated.json',
972
- reason: 'parse_error',
973
- clarification: 'metabase_sql_untranslated',
974
- fallback: 'flagged',
975
- }, { toolCallId: 'fallback-1', messages: [] });
976
- }
977
- return { stopReason: 'natural' };
978
- });
979
- const runner = buildRunner(deps);
980
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
981
- currentHashes: new Map([['cards/untranslated.json', 'h-card']]),
982
- rawDirInWorktree: 'raw-sources/c1/fake/s',
983
- });
984
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
985
- await runner.run({
986
- jobId: 'j1',
987
- connectionId: 'c1',
988
- sourceKey: 'fake',
989
- trigger: 'upload',
990
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
991
- });
992
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
993
- body: expect.objectContaining({
994
- conflictsResolved: [
995
- {
996
- kind: 'near_duplicate',
997
- artifactKey: 'sl:orders',
998
- detail: 'orders and old_orders overlapped; orders is retained as canonical',
999
- flaggedForHuman: false,
1000
- },
1001
- ],
1002
- evictionsApplied: [
1003
- {
1004
- rawPath: 'views/old_orders.view.lkml',
1005
- artifactKind: 'sl',
1006
- artifactKey: 'old_orders',
1007
- action: 'removed',
1008
- reason: 'raw source disappeared in this sync',
1009
- },
1010
- ],
1011
- unmappedFallbacks: [
1012
- {
1013
- rawPath: 'cards/untranslated.json',
1014
- reason: 'parse_error',
1015
- detail: expect.stringContaining('metabase_sql_untranslated'),
1016
- fallback: 'flagged',
1017
- },
1018
- ],
1019
- }),
1020
- }));
1021
- });
1022
- it('persists reconciliation artifact resolutions as provenance rows', async () => {
1023
- const deps = makeDeps();
1024
- deps.diffSetService.compute.mockResolvedValue({
1025
- added: [],
1026
- modified: [],
1027
- deleted: ['looks/20.json'],
1028
- unchanged: ['explores/b2b/sales_pipeline.json'],
1029
- });
1030
- deps.adapter.chunk.mockResolvedValue({
1031
- workUnits: [],
1032
- eviction: { deletedRawPaths: ['looks/20.json'] },
1033
- });
1034
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
1035
- if (params.telemetryTags.operationName === 'ingest-bundle-reconcile') {
1036
- await params.toolSet.emit_artifact_resolution.execute({
1037
- rawPath: 'explores/b2b/sales_pipeline.json',
1038
- artifactKind: 'sl',
1039
- artifactKey: 'looker__b2b__sales_pipeline',
1040
- actionType: 'subsumed',
1041
- reason: 'File adapter source b2b__sales_pipeline is canonical.',
1042
- }, { toolCallId: 'resolution-1', messages: [] });
1043
- }
1044
- return { stopReason: 'natural' };
1045
- });
1046
- const runner = buildRunner(deps);
1047
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1048
- currentHashes: new Map([['explores/b2b/sales_pipeline.json', 'h-explore']]),
1049
- rawDirInWorktree: 'raw-sources/c1/looker/s',
1050
- });
1051
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1052
- await runner.run({
1053
- jobId: 'j1',
1054
- connectionId: 'c1',
1055
- sourceKey: 'looker',
1056
- trigger: 'upload',
1057
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1058
- });
1059
- expect(deps.provenanceRepo.insertMany).toHaveBeenCalledWith(expect.arrayContaining([
1060
- expect.objectContaining({
1061
- rawPath: 'explores/b2b/sales_pipeline.json',
1062
- artifactKind: 'sl',
1063
- artifactKey: 'looker__b2b__sales_pipeline',
1064
- actionType: 'subsumed',
1065
- }),
1066
- ]));
1067
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
1068
- body: expect.objectContaining({
1069
- artifactResolutions: [
1070
- {
1071
- rawPath: 'explores/b2b/sales_pipeline.json',
1072
- artifactKind: 'sl',
1073
- artifactKey: 'looker__b2b__sales_pipeline',
1074
- actionType: 'subsumed',
1075
- reason: 'File adapter source b2b__sales_pipeline is canonical.',
1076
- },
1077
- ],
1078
- }),
1079
- }));
1080
- });
1081
- it('runs manual override reconciliation from the prior report snapshot and marks the prior report superseded', async () => {
1082
- const tempRoot = await mkdtemp(join(tmpdir(), 'ktx-override-'));
1083
- const deps = makeDeps();
1084
- deps.reportsRepo.findByJobId.mockResolvedValue({
1085
- id: 'report-old',
1086
- runId: 'run-old',
1087
- jobId: 'job-old',
1088
- connectionId: 'c1',
1089
- sourceKey: 'fake',
1090
- createdAt: '2026-04-27T10:00:00.000Z',
1091
- body: {
1092
- syncId: '2026-04-27-100000-job-old',
1093
- diffSummary: { added: 1, modified: 0, deleted: 0, unchanged: 0 },
1094
- commitSha: 'old-sha',
1095
- workUnits: [
1096
- {
1097
- unitKey: 'wu-orders',
1098
- rawFiles: ['a.yml'],
1099
- status: 'success',
1100
- actions: [
1101
- {
1102
- target: 'sl',
1103
- type: 'updated',
1104
- key: 'orders',
1105
- detail: 'captured gross_revenue as orders.gross_revenue',
1106
- },
1107
- ],
1108
- touchedSlSources: ['orders'],
1109
- },
1110
- ],
1111
- failedWorkUnits: [],
1112
- reconciliationSkipped: false,
1113
- conflictsResolved: [
1114
- {
1115
- kind: 'definitional_contradiction',
1116
- contestedKey: 'gross_revenue',
1117
- artifactKey: 'orders.gross_revenue',
1118
- detail: 'billing and orders disagree',
1119
- flaggedForHuman: true,
1120
- },
1121
- ],
1122
- evictionsApplied: [],
1123
- unmappedFallbacks: [],
1124
- evictionInputs: [],
1125
- unresolvedCards: [],
1126
- supersededBy: null,
1127
- overrideOf: null,
1128
- },
1129
- });
1130
- deps.gitService.listFilesAtHead.mockResolvedValue(['raw-sources/c1/fake/2026-04-27-100000-job-old/a.yml']);
1131
- deps.gitService.getFileAtCommit.mockResolvedValue('name: orders\n');
1132
- deps.diffSetService.compute.mockResolvedValue({ added: [], modified: [], deleted: [], unchanged: ['a.yml'] });
1133
- deps.agentRunner.runLoop.mockImplementation(async (args) => {
1134
- await args.toolSet.emit_conflict_resolution.execute({
1135
- kind: 'definitional_contradiction',
1136
- contestedKey: 'gross_revenue',
1137
- artifactKey: 'orders.gross_revenue',
1138
- detail: 'canonical pin applied',
1139
- flaggedForHuman: false,
1140
- }, { toolCallId: 'tc-1', messages: [] });
1141
- return { stopReason: 'natural' };
1142
- });
1143
- const runner = new IngestBundleRunner({
1144
- ...buildRunner(deps).deps,
1145
- storage: {
1146
- homeDir: tempRoot,
1147
- systemGitAuthor: { name: 'KTX Test', email: 'system@ktx.local' },
1148
- resolveUploadDir: (uploadId) => join(tempRoot, 'ingest-uploads', uploadId),
1149
- resolvePullDir: (jobId) => join(tempRoot, 'ingest-pulls', jobId),
1150
- resolveTranscriptDir: (jobId) => join(tempRoot, 'run', 'wu-transcripts', jobId),
1151
- },
1152
- });
1153
- await runner.run({
1154
- jobId: 'job-new',
1155
- connectionId: 'c1',
1156
- sourceKey: 'fake',
1157
- trigger: 'manual_override',
1158
- bundleRef: { kind: 'override', priorJobId: 'job-old' },
1159
- });
1160
- await expect(readFile(join(tempRoot, 'ingest-pulls/job-new/a.yml'), 'utf-8')).resolves.toBe('name: orders\n');
1161
- expect(deps.adapter.chunk).not.toHaveBeenCalled();
1162
- expect(deps.agentRunner.runLoop).toHaveBeenCalled();
1163
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
1164
- jobId: 'job-new',
1165
- body: expect.objectContaining({
1166
- overrideOf: 'job-old',
1167
- supersededBy: null,
1168
- conflictsResolved: [
1169
- expect.objectContaining({
1170
- contestedKey: 'gross_revenue',
1171
- flaggedForHuman: false,
1172
- }),
1173
- ],
1174
- }),
1175
- }));
1176
- expect(deps.reportsRepo.markSuperseded).toHaveBeenCalledWith('job-old', 'job-new');
1177
- await rm(tempRoot, { recursive: true, force: true });
1178
- });
1179
- it('passes connection canonical pins into each WorkUnit system prompt', async () => {
1180
- const deps = makeDeps();
1181
- deps.adapter.chunk.mockResolvedValue({
1182
- workUnits: [
1183
- {
1184
- unitKey: 'wu-orders',
1185
- rawFiles: ['cards/orders.yml'],
1186
- peerFileIndex: [],
1187
- dependencyPaths: [],
1188
- },
1189
- ],
1190
- });
1191
- deps.canonicalPins.listPins.mockResolvedValue([
1192
- {
1193
- contestedKey: 'gross_revenue',
1194
- canonicalArtifactKey: 'finance.gross_revenue',
1195
- pinnedAt: '2026-04-27T12:00:00.000Z',
1196
- pinnedBy: 'user-1',
1197
- reason: 'finance owns revenue definitions',
1198
- },
1199
- ]);
1200
- deps.agentRunner.runLoop.mockResolvedValue({ stopReason: 'natural' });
1201
- const runner = buildRunner(deps);
1202
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1203
- currentHashes: new Map([['cards/orders.yml', 'h1']]),
1204
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1205
- });
1206
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1207
- await runner.run({
1208
- jobId: 'j1',
1209
- connectionId: 'c1',
1210
- sourceKey: 'fake',
1211
- trigger: 'upload',
1212
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1213
- });
1214
- const workUnitCall = deps.agentRunner.runLoop.mock.calls.find(([params]) => params.telemetryTags.operationName === 'ingest-bundle-wu');
1215
- expect(workUnitCall?.[0].systemPrompt).toContain('<canonical_pins>');
1216
- expect(workUnitCall?.[0].systemPrompt).toContain('contestedKey: gross_revenue');
1217
- expect(workUnitCall?.[0].systemPrompt).toContain('canonicalArtifactKey: finance.gross_revenue');
1218
- expect(deps.canonicalPins.listPins).toHaveBeenCalledTimes(1);
1219
- expect(deps.canonicalPins.listPins).toHaveBeenCalledWith(['c1']);
1220
- });
1221
- it('builds WorkUnit SL index and canonical pins across adapter target connections', async () => {
1222
- const deps = makeDeps();
1223
- deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['warehouse-2']);
1224
- deps.adapter.chunk.mockResolvedValue({
1225
- workUnits: [
1226
- {
1227
- unitKey: 'looker-explore-b2b-orders',
1228
- rawFiles: ['explores/b2b/orders.json'],
1229
- peerFileIndex: [],
1230
- dependencyPaths: [],
1231
- },
1232
- ],
1233
- });
1234
- deps.canonicalPins.listPins.mockResolvedValue([
1235
- {
1236
- contestedKey: 'gross_revenue',
1237
- canonicalArtifactKey: 'finance.gross_revenue',
1238
- pinnedAt: '2026-05-01T12:00:00.000Z',
1239
- pinnedBy: 'user-1',
1240
- reason: 'finance owns revenue definitions',
1241
- },
1242
- ]);
1243
- const runner = buildRunner(deps);
1244
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1245
- currentHashes: new Map([['explores/b2b/orders.json', 'h1']]),
1246
- rawDirInWorktree: 'raw-sources/looker-run/fake/s',
1247
- });
1248
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1249
- await runner.run({
1250
- jobId: 'j1',
1251
- connectionId: 'looker-run',
1252
- sourceKey: 'fake',
1253
- trigger: 'upload',
1254
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1255
- });
1256
- const workUnitCall = deps.agentRunner.runLoop.mock.calls.find(([params]) => params.telemetryTags.operationName === 'ingest-bundle-wu');
1257
- expect(deps.adapter.listTargetConnectionIds).toHaveBeenCalledWith('/tmp/stage/upload-x');
1258
- expect(deps.semanticLayerService.loadAllSources).toHaveBeenCalledWith('looker-run');
1259
- expect(deps.semanticLayerService.loadAllSources).toHaveBeenCalledWith('warehouse-2');
1260
- expect(workUnitCall?.[0].userPrompt).toContain('looker__orders');
1261
- expect(deps.canonicalPins.listPins).toHaveBeenCalledWith(['looker-run', 'warehouse-2']);
1262
- });
1263
- it('syncs wiki refs, reindexes, and records provenance on SL target connections', async () => {
1264
- const deps = makeDeps();
1265
- let currentToolSession = null;
1266
- deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['warehouse-2']);
1267
- deps.wikiService.readPage = vi.fn().mockResolvedValue({
1268
- frontmatter: { sl_refs: ['looker__b2b__sales_pipeline.arr'] },
1269
- });
1270
- deps.semanticLayerService.loadAllSources.mockImplementation((connectionId) => Promise.resolve({ sources: [{ name: `${connectionId}_source` }], loadErrors: [] }));
1271
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
1272
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
1273
- currentToolSession.actions.push({
1274
- target: 'wiki',
1275
- type: 'created',
1276
- key: 'wiki/global/pipeline.md',
1277
- detail: 'Pipeline article',
1278
- }, {
1279
- target: 'sl',
1280
- type: 'created',
1281
- key: 'looker__b2b__sales_pipeline',
1282
- detail: 'Created warehouse source',
1283
- targetConnectionId: 'warehouse-2',
1284
- });
1285
- addTouchedSlSource(currentToolSession.touchedSlSources, 'warehouse-2', 'looker__b2b__sales_pipeline');
1286
- }
1287
- return { stopReason: 'natural' };
1288
- });
1289
- deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession) => {
1290
- currentToolSession = toolSession;
1291
- return {
1292
- toRuntimeTools: vi.fn().mockReturnValue({}),
1293
- getAllTools: vi.fn().mockReturnValue([]),
1294
- getToolNames: vi.fn().mockReturnValue([]),
1295
- };
1296
- });
1297
- const runner = buildRunner(deps);
1298
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1299
- currentHashes: new Map([['a.yml', 'h1']]),
1300
- rawDirInWorktree: 'raw-sources/looker-run/fake/s',
1301
- });
1302
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1303
- await runner.run({
1304
- jobId: 'j1',
1305
- connectionId: 'looker-run',
1306
- sourceKey: 'fake',
1307
- trigger: 'upload',
1308
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1309
- });
1310
- expect(deps.knowledgeSlRefs.syncFromWiki).toHaveBeenCalledWith({
1311
- wikiPageKey: 'wiki/global/pipeline.md',
1312
- wikiScope: 'GLOBAL',
1313
- wikiScopeId: null,
1314
- refs: [{ connectionId: 'warehouse-2', sourceName: 'looker__b2b__sales_pipeline' }],
1315
- });
1316
- expect(deps.semanticLayerService.loadAllSources).toHaveBeenCalledWith('warehouse-2');
1317
- expect(deps.slSearchService.indexSources).toHaveBeenCalledWith('warehouse-2', [{ name: 'warehouse-2_source' }]);
1318
- expect(deps.provenanceRepo.insertMany).toHaveBeenCalledWith(expect.arrayContaining([
1319
- expect.objectContaining({
1320
- connectionId: 'looker-run',
1321
- targetConnectionId: 'warehouse-2',
1322
- artifactKind: 'sl',
1323
- artifactKey: 'looker__b2b__sales_pipeline',
1324
- }),
1325
- expect.objectContaining({
1326
- connectionId: 'looker-run',
1327
- targetConnectionId: null,
1328
- artifactKind: 'wiki',
1329
- artifactKey: 'wiki/global/pipeline.md',
1330
- }),
1331
- ]));
1332
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
1333
- body: expect.objectContaining({
1334
- workUnits: [
1335
- expect.objectContaining({
1336
- touchedSlSources: [{ connectionId: 'warehouse-2', sourceName: 'looker__b2b__sales_pipeline' }],
1337
- }),
1338
- ],
1339
- provenanceRows: expect.arrayContaining([
1340
- expect.objectContaining({
1341
- artifactKind: 'sl',
1342
- artifactKey: 'looker__b2b__sales_pipeline',
1343
- targetConnectionId: 'warehouse-2',
1344
- }),
1345
- ]),
1346
- }),
1347
- }));
1348
- });
1349
- it('runs adapter finalization before squash, records the outcome, and reindexes touched sources', async () => {
1350
- const deps = makeDeps();
1351
- deps.adapter.source = 'metricflow';
1352
- deps.registry.get.mockReturnValue(deps.adapter);
1353
- deps.adapter.chunk.mockResolvedValue({
1354
- workUnits: [],
1355
- parseArtifacts: { semanticModels: [{ name: 'orders' }] },
1356
- });
1357
- deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['warehouse-2']);
1358
- deps.adapter.finalize = vi.fn().mockResolvedValue({
1359
- result: { sourcesTouched: 1 },
1360
- warnings: ['kept going'],
1361
- errors: [],
1362
- touchedSources: [{ connectionId: 'warehouse-2', sourceName: 'orders' }],
1363
- changedWikiPageKeys: [],
1364
- actions: [
1365
- {
1366
- target: 'sl',
1367
- type: 'updated',
1368
- key: 'orders',
1369
- targetConnectionId: 'warehouse-2',
1370
- detail: 'Finalized orders usage',
1371
- rawPaths: ['semantic_models.yml'],
1372
- },
1373
- ],
1374
- });
1375
- deps.semanticLayerService.loadAllSources.mockImplementation((connectionId) => Promise.resolve({ sources: [{ name: `${connectionId}_source` }], loadErrors: [] }));
1376
- let head = 'pre-finalization';
1377
- const git = {
1378
- revParseHead: vi.fn(async () => head),
1379
- commitFiles: vi.fn().mockImplementation(async (paths) => {
1380
- if (paths.includes('semantic-layer/warehouse-2/orders.yaml')) {
1381
- head = 'post-finalization';
1382
- return { created: true, commitHash: 'finalization-sha' };
1383
- }
1384
- return { created: true, commitHash: head };
1385
- }),
1386
- commitStaged: vi.fn().mockResolvedValue({ created: false, commitHash: 'post-finalization' }),
1387
- resetHardTo: vi.fn(),
1388
- assertWorktreeClean: vi.fn().mockResolvedValue(undefined),
1389
- writeBinaryNoRenamePatch: vi.fn(async (_base, _head, patchPath) => {
1390
- await writeFile(patchPath, '', 'utf-8');
1391
- }),
1392
- applyPatchFile3WayIndex: vi.fn(),
1393
- diffNameStatus: vi.fn().mockImplementation(async (from, to) => from === 'pre-finalization' && to === 'post-finalization'
1394
- ? [{ status: 'M', path: 'semantic-layer/warehouse-2/orders.yaml' }]
1395
- : []),
1396
- changedPaths: vi.fn().mockResolvedValue(['semantic-layer/warehouse-2/orders.yaml']),
1397
- };
1398
- deps.sessionWorktreeService.create.mockResolvedValue({
1399
- chatId: 'j1',
1400
- workdir: '/tmp/wt',
1401
- branch: 'session/j1',
1402
- baseSha: 'b',
1403
- createdAt: new Date(),
1404
- git,
1405
- config: {},
1406
- });
1407
- const runner = buildRunner(deps);
1408
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1409
- currentHashes: new Map([['semantic_models.yml', 'h1']]),
1410
- rawDirInWorktree: 'raw-sources/c1/metricflow/s',
1411
- });
1412
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1413
- await runner.run({
1414
- jobId: 'j1',
1415
- connectionId: 'c1',
1416
- sourceKey: 'metricflow',
1417
- trigger: 'upload',
1418
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1419
- });
1420
- expect(deps.adapter.finalize).toHaveBeenCalledWith(expect.objectContaining({
1421
- connectionId: 'c1',
1422
- sourceKey: 'metricflow',
1423
- syncId: expect.any(String),
1424
- jobId: 'j1',
1425
- runId: 'run-1',
1426
- workdir: '/tmp/wt',
1427
- parseArtifacts: { semanticModels: [{ name: 'orders' }] },
1428
- }));
1429
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
1430
- body: expect.objectContaining({
1431
- finalization: expect.objectContaining({
1432
- sourceKey: 'metricflow',
1433
- status: 'success',
1434
- commitSha: 'finalization-sha',
1435
- touchedPaths: ['semantic-layer/warehouse-2/orders.yaml'],
1436
- derivedTouchedSources: [{ connectionId: 'warehouse-2', sourceName: 'orders' }],
1437
- declaredTouchedSources: [{ connectionId: 'warehouse-2', sourceName: 'orders' }],
1438
- actions: [expect.objectContaining({ key: 'orders' })],
1439
- }),
1440
- }),
1441
- }));
1442
- expect(deps.semanticLayerService.loadAllSources).toHaveBeenCalledWith('warehouse-2');
1443
- expect(deps.slSearchService.indexSources).toHaveBeenCalledWith('warehouse-2', [{ name: 'warehouse-2_source' }]);
1444
- expect(deps.sessionWorktreeService.cleanup).toHaveBeenCalledWith(expect.any(Object), 'success');
1445
- });
1446
- it('includes finalization actions in memory-flow saved counts', async () => {
1447
- const deps = makeDeps();
1448
- deps.adapter.source = 'historic-sql';
1449
- deps.registry.get.mockReturnValue(deps.adapter);
1450
- deps.adapter.chunk.mockResolvedValue({
1451
- workUnits: [
1452
- {
1453
- unitKey: 'historic-sql-table-public-orders',
1454
- rawFiles: ['tables/public/orders.json'],
1455
- peerFileIndex: [],
1456
- dependencyPaths: [],
1457
- },
1458
- ],
1459
- });
1460
- deps.adapter.finalize = vi.fn().mockResolvedValue({
1461
- warnings: [],
1462
- errors: [],
1463
- touchedSources: [],
1464
- changedWikiPageKeys: [],
1465
- actions: [
1466
- { target: 'sl', type: 'updated', key: 'orders', detail: 'Merged usage' },
1467
- { target: 'sl', type: 'updated', key: 'customers', detail: 'Merged usage' },
1468
- { target: 'wiki', type: 'created', key: 'historic-sql-orders', detail: 'Projected pattern' },
1469
- { target: 'wiki', type: 'updated', key: 'historic-sql-customers', detail: 'Projected pattern' },
1470
- ],
1471
- });
1472
- const runner = buildRunner(deps);
1473
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1474
- currentHashes: new Map([['tables/public/orders.json', 'h1']]),
1475
- rawDirInWorktree: 'raw-sources/c1/historic-sql/s',
1476
- });
1477
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1478
- const memoryFlow = createMemoryFlowLiveBuffer(bundleReplayInput());
1479
- await runner.run({
1480
- jobId: 'j1',
1481
- connectionId: 'c1',
1482
- sourceKey: 'historic-sql',
1483
- trigger: 'upload',
1484
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1485
- }, {
1486
- jobId: 'j1',
1487
- memoryFlow,
1488
- startPhase: () => new TestJobContext('j1', null, () => Promise.resolve(), () => Promise.resolve()),
1489
- });
1490
- expect(memoryFlow.snapshot().events).toContainEqual(expect.objectContaining({
1491
- type: 'saved',
1492
- wikiCount: 2,
1493
- slCount: 2,
1494
- }));
1495
- });
1496
- it('marks finalization infrastructure failure as failed and preserves worktree cleanup state', async () => {
1497
- const deps = makeDeps();
1498
- deps.adapter.source = 'metricflow';
1499
- deps.registry.get.mockReturnValue(deps.adapter);
1500
- deps.adapter.chunk.mockResolvedValue({
1501
- workUnits: [{ unitKey: 'u1', rawFiles: ['semantic_models.yml'], peerFileIndex: [], dependencyPaths: [] }],
1502
- parseArtifacts: { semanticModels: [{ name: 'orders' }] },
1503
- });
1504
- deps.adapter.finalize = vi.fn().mockRejectedValue(new Error('worktree write failed'));
1505
- const runner = buildRunner(deps);
1506
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1507
- currentHashes: new Map([['semantic_models.yml', 'h1']]),
1508
- rawDirInWorktree: 'raw-sources/c1/metricflow/s',
1509
- });
1510
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1511
- await expect(runner.run({
1512
- jobId: 'j1',
1513
- connectionId: 'c1',
1514
- sourceKey: 'metricflow',
1515
- trigger: 'upload',
1516
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1517
- })).rejects.toThrow('worktree write failed');
1518
- expect(deps.runsRepo.markFailed).toHaveBeenCalledWith('run-1');
1519
- expect(deps.gitService.squashMergeIntoMain).not.toHaveBeenCalled();
1520
- expect(deps.sessionWorktreeService.cleanup).toHaveBeenCalledWith(expect.any(Object), 'crash');
1521
- });
1522
- it('reports finalization actions excluded from provenance when raw paths are not defensible', async () => {
1523
- const deps = makeDeps();
1524
- deps.adapter.finalize = vi.fn().mockResolvedValue({
1525
- warnings: [],
1526
- errors: [],
1527
- touchedSources: [],
1528
- changedWikiPageKeys: [],
1529
- actions: [
1530
- { target: 'wiki', type: 'updated', key: 'historic-sql-pattern', detail: 'No raw path' },
1531
- { target: 'sl', type: 'updated', key: 'orders', detail: 'Invalid raw path', rawPaths: ['missing.json'] },
1532
- ],
1533
- });
1534
- const runner = buildRunner(deps);
1535
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1536
- currentHashes: new Map([['current.json', 'h1']]),
1537
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1538
- });
1539
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1540
- await runner.run({
1541
- jobId: 'j1',
1542
- connectionId: 'c1',
1543
- sourceKey: 'fake',
1544
- trigger: 'upload',
1545
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1546
- });
1547
- expect(deps.reportsRepo.create).toHaveBeenCalledWith(expect.objectContaining({
1548
- body: expect.objectContaining({
1549
- finalization: expect.objectContaining({
1550
- provenanceExclusions: [
1551
- expect.objectContaining({ reason: 'missing_raw_paths' }),
1552
- expect.objectContaining({ reason: 'raw_path_not_defensible', invalidRawPaths: ['missing.json'] }),
1553
- ],
1554
- }),
1555
- }),
1556
- }));
1557
- expect(deps.provenanceRepo.insertMany).not.toHaveBeenCalledWith(expect.arrayContaining([expect.objectContaining({ rawPath: 'missing.json' })]));
1558
- });
1559
- it('passes explicit override replay metadata and no current work unit outcomes', async () => {
1560
- const deps = makeDeps();
1561
- deps.reportsRepo.findByJobId.mockResolvedValue({
1562
- id: 'prior-report',
1563
- runId: 'prior-run',
1564
- jobId: 'prior-job',
1565
- connectionId: 'c1',
1566
- sourceKey: 'fake',
1567
- createdAt: '2026-05-18T00:00:00.000Z',
1568
- body: {
1569
- status: 'completed',
1570
- syncId: 'prior-sync',
1571
- diffSummary: { added: 0, modified: 0, deleted: 0, unchanged: 0 },
1572
- commitSha: 'prior-sha',
1573
- workUnits: [
1574
- {
1575
- unitKey: 'prior-unit',
1576
- rawFiles: ['prior.json'],
1577
- status: 'success',
1578
- actions: [{ target: 'wiki', type: 'created', key: 'prior', detail: 'prior' }],
1579
- touchedSlSources: [],
1580
- },
1581
- ],
1582
- failedWorkUnits: [],
1583
- reconciliationSkipped: false,
1584
- conflictsResolved: [],
1585
- evictionsApplied: [
1586
- {
1587
- rawPath: 'do-not-replay.json',
1588
- artifactKind: 'wiki',
1589
- artifactKey: 'old',
1590
- action: 'removed',
1591
- reason: 'prior',
1592
- },
1593
- ],
1594
- unmappedFallbacks: [],
1595
- artifactResolutions: [],
1596
- evictionInputs: ['evicted-from-prior-report.json'],
1597
- unresolvedCards: [],
1598
- supersededBy: null,
1599
- overrideOf: null,
1600
- provenanceRows: [],
1601
- toolTranscripts: [],
1602
- },
1603
- });
1604
- deps.adapter.finalize = vi.fn().mockResolvedValue({
1605
- warnings: [],
1606
- errors: [],
1607
- touchedSources: [],
1608
- changedWikiPageKeys: [],
1609
- actions: [],
1610
- });
1611
- deps.gitService.listFilesAtHead.mockResolvedValue(['raw-sources/c1/fake/prior-sync/prior.json']);
1612
- deps.gitService.getFileAtCommit.mockResolvedValue('{"id":1}\n');
1613
- const runner = buildRunner(deps);
1614
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1615
- currentHashes: new Map([['prior.json', 'h1']]),
1616
- rawDirInWorktree: 'raw-sources/c1/fake/prior-sync',
1617
- });
1618
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/prior');
1619
- await runner.run({
1620
- jobId: 'override-job',
1621
- connectionId: 'c1',
1622
- sourceKey: 'fake',
1623
- trigger: 'manual_override',
1624
- bundleRef: { kind: 'override', priorJobId: 'prior-job' },
1625
- });
1626
- expect(deps.adapter.finalize).toHaveBeenCalledWith(expect.objectContaining({
1627
- workUnitOutcomes: [],
1628
- overrideReplay: {
1629
- priorJobId: 'prior-job',
1630
- priorRunId: 'prior-run',
1631
- priorSyncId: 'prior-sync',
1632
- evictionRawPaths: ['evicted-from-prior-report.json'],
1633
- },
1634
- }));
1635
- });
1636
- it('includes existing global wiki pages in WorkUnit prompts', async () => {
1637
- const deps = makeDeps();
1638
- deps.knowledgeIndex.listPagesForUser.mockResolvedValue([
1639
- {
1640
- page_key: 'revenue-recognition',
1641
- summary: 'Recognize revenue net of refunds after fulfillment.',
1642
- scope: 'GLOBAL',
1643
- scope_id: null,
1644
- },
1645
- ]);
1646
- const runner = buildRunner(deps);
1647
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1648
- currentHashes: new Map([['cards/orders.yml', 'h1']]),
1649
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1650
- });
1651
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1652
- await runner.run({
1653
- jobId: 'j1',
1654
- connectionId: 'c1',
1655
- sourceKey: 'fake',
1656
- trigger: 'upload',
1657
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1658
- });
1659
- const workUnitCall = deps.agentRunner.runLoop.mock.calls.find(([params]) => params.telemetryTags.operationName === 'ingest-bundle-wu');
1660
- expect(workUnitCall?.[0].userPrompt).toContain('## Wiki Pages');
1661
- expect(workUnitCall?.[0].userPrompt).toContain('- revenue-recognition: Recognize revenue net of refunds after fulfillment.');
1662
- expect(deps.knowledgeIndex.listPagesForUser).toHaveBeenCalledWith('system');
1663
- });
1664
- it('includes manifest-backed target sources in WorkUnit prompts', async () => {
1665
- const deps = makeDeps();
1666
- deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['postgres-warehouse']);
1667
- deps.semanticLayerService.loadAllSources.mockImplementation((connectionId) => Promise.resolve({
1668
- sources: connectionId === 'postgres-warehouse' ? [{ name: 'stg_accounts' }] : [],
1669
- loadErrors: [],
1670
- }));
1671
- const runner = buildRunner(deps);
1672
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1673
- currentHashes: new Map([['models/schema.yml', 'h1']]),
1674
- rawDirInWorktree: 'raw-sources/dbt-main/dbt/s',
1675
- });
1676
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1677
- await runner.run({
1678
- jobId: 'j1',
1679
- connectionId: 'dbt-main',
1680
- sourceKey: 'fake',
1681
- trigger: 'upload',
1682
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1683
- });
1684
- const workUnitCall = deps.agentRunner.runLoop.mock.calls.find(([params]) => params.telemetryTags.operationName === 'ingest-bundle-wu');
1685
- expect(workUnitCall?.[0].userPrompt).toContain('## postgres-warehouse');
1686
- expect(workUnitCall?.[0].userPrompt).toContain('stg_accounts');
1687
- expect(deps.canonicalPins.listPins).toHaveBeenCalledWith(['dbt-main', 'postgres-warehouse']);
1688
- });
1689
- it('does not resolve qualified fallback table refs by source name alone', async () => {
1690
- const deps = makeDeps();
1691
- deps.semanticLayerService.loadAllSources.mockResolvedValue({
1692
- sources: [{ name: 'orders', table: 'sales.orders' }],
1693
- loadErrors: [],
1694
- });
1695
- const runner = buildRunner(deps);
1696
- await expect(runner.tableRefExistsInSemanticLayer(deps.semanticLayerService, ['warehouse'], 'finance.orders')).resolves.toBe(false);
1697
- await expect(runner.tableRefExistsInSemanticLayer(deps.semanticLayerService, ['warehouse'], 'sales.orders')).resolves.toBe(true);
1698
- });
1699
- it('passes relevant canonical pins into the reconciliation system prompt', async () => {
1700
- const deps = makeDeps();
1701
- deps.diffSetService.compute.mockResolvedValue({
1702
- added: [],
1703
- modified: [],
1704
- deleted: ['metrics/old.yml'],
1705
- unchanged: [],
1706
- });
1707
- deps.adapter.chunk.mockResolvedValue({
1708
- workUnits: [
1709
- {
1710
- unitKey: 'wu-billing',
1711
- rawFiles: ['metrics/churn_risk_score.yml'],
1712
- peerFileIndex: [],
1713
- dependencyPaths: [],
1714
- },
1715
- ],
1716
- eviction: { deletedRawPaths: ['metrics/old.yml'] },
1717
- });
1718
- deps.canonicalPins.listPins.mockResolvedValue([
1719
- {
1720
- contestedKey: 'churn_risk_score',
1721
- canonicalArtifactKey: 'billing.churn_risk_score',
1722
- pinnedAt: '2026-04-27T12:00:00.000Z',
1723
- pinnedBy: 'user-1',
1724
- reason: 'billing owns the contractual definition',
1725
- },
1726
- {
1727
- contestedKey: 'gross_margin',
1728
- canonicalArtifactKey: 'finance.gross_margin',
1729
- pinnedAt: '2026-04-27T12:01:00.000Z',
1730
- pinnedBy: 'user-2',
1731
- reason: null,
1732
- },
1733
- ]);
1734
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
1735
- if (params.telemetryTags.operationName === 'ingest-bundle-wu') {
1736
- return { stopReason: 'natural' };
1737
- }
1738
- return { stopReason: 'natural' };
1739
- });
1740
- const runner = buildRunner(deps);
1741
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1742
- currentHashes: new Map([
1743
- ['metrics/churn_risk_score.yml', 'h1'],
1744
- ['metrics/old.yml', 'h2'],
1745
- ]),
1746
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1747
- });
1748
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1749
- await runner.run({
1750
- jobId: 'j1',
1751
- connectionId: 'c1',
1752
- sourceKey: 'fake',
1753
- trigger: 'upload',
1754
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1755
- });
1756
- const reconcileCall = deps.agentRunner.runLoop.mock.calls.find(([params]) => params.telemetryTags.operationName === 'ingest-bundle-reconcile');
1757
- expect(reconcileCall?.[0].systemPrompt).toContain('<canonical_pins>');
1758
- expect(reconcileCall?.[0].systemPrompt).toContain('contestedKey: churn_risk_score');
1759
- expect(reconcileCall?.[0].systemPrompt).not.toContain('gross_margin');
1760
- expect(deps.canonicalPins.listPins).toHaveBeenCalledWith(['c1']);
1761
- });
1762
- it('emits a monotonically non-decreasing progress sequence reaching 1.0, covering all 7 stages', async () => {
1763
- const deps = makeDeps();
1764
- // Simulate an agent that calls onStepFinish a few times so stage 3 and 4 emit per-step progress.
1765
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
1766
- if (params.onStepFinish) {
1767
- for (let i = 1; i <= 3; i++) {
1768
- await params.onStepFinish({ stepIndex: i, stepBudget: params.stepBudget });
1769
- }
1770
- }
1771
- return { stopReason: 'natural' };
1772
- });
1773
- // Trigger Stage 4 reconciliation by having at least one action.
1774
- deps.agentRunner.runLoop.mockImplementation(async (params) => {
1775
- if (params.onStepFinish) {
1776
- await params.onStepFinish({ stepIndex: 1, stepBudget: params.stepBudget });
1777
- }
1778
- return { stopReason: 'natural' };
1779
- });
1780
- const runner = buildRunner(deps);
1781
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1782
- currentHashes: new Map([['a.yml', 'h1']]),
1783
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1784
- });
1785
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1786
- const observed = [];
1787
- const ctx = new TestJobContext('j1', null, () => Promise.resolve(), (p, m) => {
1788
- observed.push({ p, m });
1789
- return Promise.resolve();
1790
- });
1791
- await runner.run({
1792
- jobId: 'j1',
1793
- connectionId: 'c1',
1794
- sourceKey: 'fake',
1795
- trigger: 'upload',
1796
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1797
- }, ctx);
1798
- // Monotonic.
1799
- for (let i = 1; i < observed.length; i++) {
1800
- expect(observed[i].p).toBeGreaterThanOrEqual(observed[i - 1].p);
1801
- }
1802
- // Reaches completion.
1803
- expect(observed.at(-1)?.p).toBeCloseTo(1.0, 3);
1804
- // Every stage surfaces a user-facing message.
1805
- const phaseLabels = [
1806
- 'Fetching source files',
1807
- 'Planning updates',
1808
- 'Processing',
1809
- /Reconcil|reconcil/,
1810
- 'Saving changes',
1811
- 'Recording history',
1812
- 'Wrapping up',
1813
- ];
1814
- for (const label of phaseLabels) {
1815
- expect(observed.some((o) => (typeof label === 'string' ? o.m?.includes(label) : label.test(o.m ?? '')))).toBe(true);
1816
- }
1817
- });
1818
- it('a Stage 3 failure leaves the shared knowledge table untouched', async () => {
1819
- const deps = makeDeps();
1820
- // Agent runner returns a successful result but the adapter emits a WU whose
1821
- // outcome still produces no actions — the point is that the scoped wiki service
1822
- // must not touch indexRepository during Stage 3, and syncFromCommit is what
1823
- // drives the shared table. If we cancel the run before squash, syncFromCommit
1824
- // must not be called.
1825
- deps.gitService.squashMergeIntoMain.mockRejectedValue(new Error('simulated squash failure'));
1826
- const runner = buildRunner(deps);
1827
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1828
- currentHashes: new Map([['a.yml', 'h1']]),
1829
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1830
- });
1831
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1832
- await expect(runner.run({
1833
- jobId: 'j1',
1834
- connectionId: 'c1',
1835
- sourceKey: 'fake',
1836
- trigger: 'upload',
1837
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1838
- })).rejects.toThrow(/simulated squash failure/);
1839
- expect(deps.wikiService.syncFromCommit).not.toHaveBeenCalled();
1840
- });
1841
- it('refuses to squash-merge when the session worktree has an in-progress sequencer op', async () => {
1842
- const deps = makeDeps();
1843
- const assertError = new Error('Worktree has in-progress git operation (sequencer ...); refusing to proceed');
1844
- const sessionGit = {
1845
- revParseHead: vi.fn().mockResolvedValue('h'),
1846
- commitFiles: vi.fn().mockResolvedValue({ created: true, commitHash: 'h' }),
1847
- commitStaged: vi.fn().mockResolvedValue({ created: false, commitHash: 'h' }),
1848
- resetHardTo: vi.fn(),
1849
- assertWorktreeClean: vi.fn().mockRejectedValue(assertError),
1850
- writeBinaryNoRenamePatch: vi.fn(async (_base, _head, patchPath) => {
1851
- await writeFile(patchPath, '', 'utf-8');
1852
- }),
1853
- applyPatchFile3WayIndex: vi.fn(),
1854
- diffNameStatus: vi.fn().mockResolvedValue([]),
1855
- };
1856
- deps.sessionWorktreeService.create.mockResolvedValue({
1857
- chatId: 'j1',
1858
- workdir: '/tmp/wt',
1859
- branch: 'session/j1',
1860
- baseSha: 'b',
1861
- createdAt: new Date(),
1862
- git: sessionGit,
1863
- config: {},
1864
- });
1865
- const runner = buildRunner(deps);
1866
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1867
- currentHashes: new Map([['a.yml', 'h1']]),
1868
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1869
- });
1870
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1871
- await expect(runner.run({
1872
- jobId: 'j1',
1873
- connectionId: 'c1',
1874
- sourceKey: 'fake',
1875
- trigger: 'upload',
1876
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1877
- })).rejects.toThrow(/in-progress git operation/);
1878
- expect(deps.runsRepo.markFailed).toHaveBeenCalledWith('run-1');
1879
- expect(deps.gitService.squashMergeIntoMain).not.toHaveBeenCalled();
1880
- });
1881
- it('fails the run and rethrows when the adapter cannot detect the bundle', async () => {
1882
- const deps = makeDeps();
1883
- deps.adapter.detect.mockResolvedValue(false);
1884
- const runner = buildRunner(deps);
1885
- runner.stageRawFilesStage1 = vi.fn().mockResolvedValue({
1886
- currentHashes: new Map([['a.yml', 'h1']]),
1887
- rawDirInWorktree: 'raw-sources/c1/fake/s',
1888
- });
1889
- runner.resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x');
1890
- await expect(runner.run({
1891
- jobId: 'j1',
1892
- connectionId: 'c1',
1893
- sourceKey: 'fake',
1894
- trigger: 'upload',
1895
- bundleRef: { kind: 'upload', uploadId: 'upload-x' },
1896
- })).rejects.toThrow(/did not recognize/);
1897
- expect(deps.runsRepo.markFailed).toHaveBeenCalledWith('run-1');
1898
- });
1899
- });