@codeyam/codeyam-cli 0.1.0-staging.2a88920 → 0.1.0-staging.4684848

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 (364) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +4 -4
  4. package/analyzer-template/packages/ai/index.ts +1 -0
  5. package/analyzer-template/packages/ai/package.json +2 -2
  6. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +23 -1
  7. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
  8. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +101 -0
  9. package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
  10. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +6 -0
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +330 -9
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +5 -1
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +11 -2
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +2 -2
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +140 -14
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +20 -1
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +84 -19
  19. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +33 -15
  20. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +58 -3
  21. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +299 -5
  22. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +38 -2
  23. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +359 -142
  24. package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +51 -3
  25. package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
  26. package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
  27. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
  28. package/analyzer-template/packages/analyze/index.ts +2 -0
  29. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +69 -3
  30. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -0
  31. package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1315 -0
  32. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +4 -0
  33. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +59 -26
  34. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +194 -15
  35. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +372 -57
  36. package/analyzer-template/packages/analyze/src/lib/index.ts +1 -0
  37. package/analyzer-template/packages/database/package.json +1 -1
  38. package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
  39. package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
  40. package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
  41. package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
  42. package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
  43. package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
  44. package/analyzer-template/packages/database/src/lib/kysely/db.ts +6 -0
  45. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  46. package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
  47. package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
  48. package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
  49. package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
  50. package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
  51. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
  52. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
  53. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
  54. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
  55. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
  56. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
  57. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
  58. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
  59. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
  60. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
  61. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
  62. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
  63. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -0
  64. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  65. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +3 -0
  66. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  67. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  68. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
  69. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
  70. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  71. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  72. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
  73. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
  74. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
  75. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
  76. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
  77. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
  78. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  79. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  80. package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
  81. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  82. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  83. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  84. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +93 -2
  85. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  86. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +108 -2
  87. package/analyzer-template/project/constructMockCode.ts +36 -1
  88. package/analyzer-template/project/writeMockDataTsx.ts +174 -12
  89. package/analyzer-template/project/writeScenarioComponents.ts +60 -12
  90. package/analyzer-template/project/writeSimpleRoot.ts +21 -11
  91. package/background/src/lib/local/createLocalAnalyzer.js +1 -1
  92. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  93. package/background/src/lib/virtualized/project/constructMockCode.js +30 -1
  94. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  95. package/background/src/lib/virtualized/project/writeMockDataTsx.js +156 -8
  96. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  97. package/background/src/lib/virtualized/project/writeScenarioComponents.js +60 -15
  98. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  99. package/background/src/lib/virtualized/project/writeSimpleRoot.js +21 -11
  100. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  101. package/codeyam-cli/scripts/apply-setup.js +180 -0
  102. package/codeyam-cli/scripts/apply-setup.js.map +1 -1
  103. package/codeyam-cli/src/cli.js +2 -0
  104. package/codeyam-cli/src/cli.js.map +1 -1
  105. package/codeyam-cli/src/codeyam-cli.js +18 -2
  106. package/codeyam-cli/src/codeyam-cli.js.map +1 -1
  107. package/codeyam-cli/src/commands/analyze.js +4 -2
  108. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  109. package/codeyam-cli/src/commands/baseline.js +2 -0
  110. package/codeyam-cli/src/commands/baseline.js.map +1 -1
  111. package/codeyam-cli/src/commands/debug.js +2 -0
  112. package/codeyam-cli/src/commands/debug.js.map +1 -1
  113. package/codeyam-cli/src/commands/default.js +31 -20
  114. package/codeyam-cli/src/commands/default.js.map +1 -1
  115. package/codeyam-cli/src/commands/detect-universal-mocks.js +2 -0
  116. package/codeyam-cli/src/commands/detect-universal-mocks.js.map +1 -1
  117. package/codeyam-cli/src/commands/init.js +49 -257
  118. package/codeyam-cli/src/commands/init.js.map +1 -1
  119. package/codeyam-cli/src/commands/memory.js +17 -26
  120. package/codeyam-cli/src/commands/memory.js.map +1 -1
  121. package/codeyam-cli/src/commands/recapture.js +2 -0
  122. package/codeyam-cli/src/commands/recapture.js.map +1 -1
  123. package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
  124. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  125. package/codeyam-cli/src/commands/setup-simulations.js +284 -0
  126. package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
  127. package/codeyam-cli/src/commands/test-startup.js +2 -0
  128. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  129. package/codeyam-cli/src/commands/verify.js +14 -2
  130. package/codeyam-cli/src/commands/verify.js.map +1 -1
  131. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -86
  132. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  133. package/codeyam-cli/src/utils/analyzer.js +7 -0
  134. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  135. package/codeyam-cli/src/utils/backgroundServer.js +9 -0
  136. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  137. package/codeyam-cli/src/utils/generateReport.js +2 -2
  138. package/codeyam-cli/src/utils/install-skills.js +57 -54
  139. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  140. package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
  141. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
  142. package/codeyam-cli/src/utils/progress.js +7 -0
  143. package/codeyam-cli/src/utils/progress.js.map +1 -1
  144. package/codeyam-cli/src/utils/queue/job.js +4 -0
  145. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  146. package/codeyam-cli/src/utils/requireSimulations.js +10 -0
  147. package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
  148. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
  149. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
  150. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +230 -0
  151. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
  152. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
  153. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
  154. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
  155. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
  156. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
  157. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
  158. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
  159. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
  160. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +75 -0
  161. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
  162. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +378 -0
  163. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
  164. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +115 -0
  165. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
  166. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
  167. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
  168. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
  169. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
  170. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
  171. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
  172. package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
  173. package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
  174. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
  175. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
  176. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
  177. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
  178. package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
  179. package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
  180. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
  181. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
  182. package/codeyam-cli/src/utils/rules/index.js +1 -0
  183. package/codeyam-cli/src/utils/rules/index.js.map +1 -1
  184. package/codeyam-cli/src/utils/rules/parser.js +2 -25
  185. package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
  186. package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
  187. package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
  188. package/codeyam-cli/src/utils/rules/staleness.js +16 -11
  189. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
  190. package/codeyam-cli/src/utils/serverState.js +37 -10
  191. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  192. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -44
  193. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  194. package/codeyam-cli/src/webserver/app/lib/database.js +15 -3
  195. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  196. package/codeyam-cli/src/webserver/backgroundServer.js +24 -0
  197. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  198. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CQ-wF3Tv.js +1 -0
  199. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-DsN1wKrm.js → EntityItem-HdckCi0m.js} +1 -1
  200. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-DLqD3qNt.js → EntityTypeBadge-Dh5RJMOE.js} +1 -1
  201. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-Ba2JVPzP.js → EntityTypeIcon-BnjjBHJu.js} +1 -1
  202. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-C8lyxW9k.js → InlineSpinner-CUSfu6W5.js} +1 -1
  203. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-aht4aafF.js → InteractivePreview-Coll1aD6.js} +2 -2
  204. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-CVtiBnY5.js → LibraryFunctionPreview-lYMY8h-y.js} +1 -1
  205. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-B0GLXMsr.js → LoadingDots-ay8XeA59.js} +1 -1
  206. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-xgeCVgSM.js → LogViewer-Dpul1_ik.js} +1 -1
  207. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-OApQuNyq.js → ReportIssueModal-CRBCfV2W.js} +3 -8
  208. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-DuDvi0jm.js → SafeScreenshot-DRTFDNFt.js} +1 -1
  209. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DzccYyI8.js → ScenarioViewer-d6PSFxhS.js} +2 -2
  210. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-DyFZkK0l.js → TruncatedFilePath-DDEOQ6Iw.js} +1 -1
  211. package/codeyam-cli/src/webserver/build/client/assets/{_index-BwqWJOgH.js → _index-CkziGg5F.js} +1 -1
  212. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BwavGCpm.js → activity.(_tab)-B2v1pm9w.js} +6 -11
  213. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-BXIaK8Md.js +11 -0
  214. package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
  215. package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
  216. package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
  217. package/codeyam-cli/src/webserver/build/client/assets/book-open-qbapxy6o.js +6 -0
  218. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-Cx24_aWc.js → chevron-down-C-mKrwr1.js} +1 -1
  219. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-CXRTFQ3F.js → chunk-JZWAC4HX-BAvUl1nT.js} +12 -12
  220. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BOARzkeR.js → circle-check-DlrT-SzI.js} +1 -1
  221. package/codeyam-cli/src/webserver/build/client/assets/copy-clIxnCqQ.js +11 -0
  222. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-BdhJEx6B.js → createLucideIcon-B931Etud.js} +1 -1
  223. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-BBnGWYga.js → dev.empty-BoPM6KnE.js} +1 -1
  224. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-oVRMh9Hl.js +16 -0
  225. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js → entity._sha.scenarios._scenarioId.fullscreen-BjyzwQ7H.js} +1 -1
  226. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-D1T4TGjf.js → entity._sha_.create-scenario-DxuyDmZA.js} +1 -1
  227. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CTBG2mmz.js → entity._sha_.edit._scenarioId-DESSZGQp.js} +1 -1
  228. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-CS2cb_eZ.js → entry.client-D5Yb90Ad.js} +1 -1
  229. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DMJ7zii9.js → fileTableUtils-DuObVYgh.js} +1 -1
  230. package/codeyam-cli/src/webserver/build/client/assets/{files-CJ6lTdTA.js → files-CDfz4Y-i.js} +1 -1
  231. package/codeyam-cli/src/webserver/build/client/assets/{git-CPTZZ-JZ.js → git-D6jOlDQw.js} +1 -1
  232. package/codeyam-cli/src/webserver/build/client/assets/globals-CKT08Djd.css +1 -0
  233. package/codeyam-cli/src/webserver/build/client/assets/{index-B1h680n5.js → index-DvOt1KIt.js} +1 -1
  234. package/codeyam-cli/src/webserver/build/client/assets/{index-lzqtyFU8.js → index-WfQFdoWK.js} +1 -1
  235. package/codeyam-cli/src/webserver/build/client/assets/labs-BbGyC1RY.js +1 -0
  236. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-B7B9V-bu.js → loader-circle-Bb7Y9k5O.js} +1 -1
  237. package/codeyam-cli/src/webserver/build/client/assets/manifest-fd06e67a.js +1 -0
  238. package/codeyam-cli/src/webserver/build/client/assets/memory-BXebUPaL.js +78 -0
  239. package/codeyam-cli/src/webserver/build/client/assets/pause-DaAHX2on.js +11 -0
  240. package/codeyam-cli/src/webserver/build/client/assets/root-CvNE9MaT.js +62 -0
  241. package/codeyam-cli/src/webserver/build/client/assets/{search-CxXUmBSd.js → search-DIqAPIrO.js} +1 -1
  242. package/codeyam-cli/src/webserver/build/client/assets/settings-DCIzBZM9.js +1 -0
  243. package/codeyam-cli/src/webserver/build/client/assets/{simulations-DwFIBT09.js → simulations-C6n_fNQY.js} +1 -1
  244. package/codeyam-cli/src/webserver/build/client/assets/terminal-CmPsszJy.js +11 -0
  245. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-B6LgvRJg.js → triangle-alert-Beg-oV50.js} +1 -1
  246. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-C1v1PQzo.js → useCustomSizes-D7TLbP3M.js} +1 -1
  247. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-aSv48UbS.js → useLastLogLine-Ce5rnai3.js} +1 -1
  248. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-DYxHZQuP.js → useReportContext-B4D3wj27.js} +1 -1
  249. package/codeyam-cli/src/webserver/build/client/assets/{useToast-mBRpZPiu.js → useToast-BDt_-DnY.js} +1 -1
  250. package/codeyam-cli/src/webserver/build/server/assets/{index-BM6TDT1Y.js → index-DDr9Cp9M.js} +1 -1
  251. package/codeyam-cli/src/webserver/build/server/assets/server-build-DjwiujaU.js +257 -0
  252. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  253. package/codeyam-cli/src/webserver/build-info.json +5 -5
  254. package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
  255. package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
  256. package/codeyam-cli/templates/codeyam-memory-hook.sh +19 -20
  257. package/codeyam-cli/templates/codeyam-memory.md +392 -0
  258. package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +2 -2
  259. package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
  260. package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
  261. package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
  262. package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
  263. package/codeyam-cli/templates/rule-notification-hook.py +56 -0
  264. package/codeyam-cli/templates/rule-reflection-hook.py +554 -87
  265. package/codeyam-cli/templates/rules-instructions.md +63 -24
  266. package/package.json +10 -10
  267. package/packages/ai/index.js +1 -1
  268. package/packages/ai/index.js.map +1 -1
  269. package/packages/ai/src/lib/analyzeScope.js +21 -1
  270. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  271. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
  272. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
  273. package/packages/ai/src/lib/astScopes/processExpression.js +78 -1
  274. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  275. package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
  276. package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
  277. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +262 -8
  278. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  279. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +5 -1
  280. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  281. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +11 -2
  282. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  283. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +2 -2
  284. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  285. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
  286. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
  287. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +122 -12
  288. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  289. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +15 -1
  290. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -1
  291. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +78 -17
  292. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  293. package/packages/ai/src/lib/dataStructureChunking.js +26 -11
  294. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
  295. package/packages/ai/src/lib/generateEntityDataStructure.js +46 -2
  296. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  297. package/packages/ai/src/lib/generateEntityScenarioData.js +212 -3
  298. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  299. package/packages/ai/src/lib/generateExecutionFlows.js +16 -2
  300. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  301. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +242 -81
  302. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  303. package/packages/ai/src/lib/isolateScopes.js +39 -3
  304. package/packages/ai/src/lib/isolateScopes.js.map +1 -1
  305. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
  306. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
  307. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
  308. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
  309. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +17 -2
  310. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  311. package/packages/analyze/index.js +1 -0
  312. package/packages/analyze/index.js.map +1 -1
  313. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +52 -2
  314. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  315. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +3 -0
  316. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  317. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js +880 -0
  318. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
  319. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +5 -1
  320. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  321. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +51 -14
  322. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  323. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +116 -13
  324. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  325. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +310 -45
  326. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  327. package/packages/analyze/src/lib/index.js +1 -0
  328. package/packages/analyze/src/lib/index.js.map +1 -1
  329. package/packages/database/src/lib/analysisBranchToDb.js +1 -1
  330. package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
  331. package/packages/database/src/lib/analysisToDb.js +1 -1
  332. package/packages/database/src/lib/analysisToDb.js.map +1 -1
  333. package/packages/database/src/lib/branchToDb.js +1 -1
  334. package/packages/database/src/lib/branchToDb.js.map +1 -1
  335. package/packages/database/src/lib/commitBranchToDb.js +1 -1
  336. package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
  337. package/packages/database/src/lib/commitToDb.js +1 -1
  338. package/packages/database/src/lib/commitToDb.js.map +1 -1
  339. package/packages/database/src/lib/fileToDb.js +1 -1
  340. package/packages/database/src/lib/fileToDb.js.map +1 -1
  341. package/packages/database/src/lib/kysely/db.js +3 -0
  342. package/packages/database/src/lib/kysely/db.js.map +1 -1
  343. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  344. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  345. package/packages/database/src/lib/projectToDb.js +1 -1
  346. package/packages/database/src/lib/projectToDb.js.map +1 -1
  347. package/packages/database/src/lib/saveFiles.js +1 -1
  348. package/packages/database/src/lib/saveFiles.js.map +1 -1
  349. package/packages/database/src/lib/scenarioToDb.js +1 -1
  350. package/packages/database/src/lib/scenarioToDb.js.map +1 -1
  351. package/packages/utils/src/lib/fs/rsyncCopy.js +93 -2
  352. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  353. package/scripts/finalize-analyzer.cjs +8 -76
  354. package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +0 -6
  355. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-BJUiQqZF.js +0 -23
  356. package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +0 -6
  357. package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +0 -1
  358. package/codeyam-cli/src/webserver/build/client/assets/manifest-a78b90a2.js +0 -1
  359. package/codeyam-cli/src/webserver/build/client/assets/memory--GCbFsBE.js +0 -92
  360. package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +0 -62
  361. package/codeyam-cli/src/webserver/build/client/assets/settings-CS5f3WzT.js +0 -1
  362. package/codeyam-cli/src/webserver/build/server/assets/server-build-dYC34MHw.js +0 -257
  363. package/codeyam-cli/templates/codeyam:diagnose.md +0 -803
  364. package/codeyam-cli/templates/codeyam:memory.md +0 -341
@@ -4,6 +4,7 @@ import {
4
4
  } from '~codeyam/ai';
5
5
  import { cleanKnownObjectFunctionsFromMapping } from '~codeyam/ai';
6
6
  import { DataStructure, Entity, ReadonlyAnalysis } from '~codeyam/types';
7
+ import { transformationTracer } from './TransformationTracer';
7
8
 
8
9
  export interface DataStructureInfo {
9
10
  signatureSchema: { [key: string]: string };
@@ -65,6 +66,13 @@ function isPrimitiveType(typeStr: string): boolean {
65
66
  return false;
66
67
  }
67
68
 
69
+ // Extract signature index from a path like "signature[0]" or "signature[0].foo"
70
+ // Returns the index number or undefined if not a signature path
71
+ function extractSignatureIndex(path: string): number | undefined {
72
+ const match = path.match(/^signature\[(\d+)\]/);
73
+ return match ? parseInt(match[1], 10) : undefined;
74
+ }
75
+
68
76
  // Check if a new schema path would go through a primitive type
69
77
  // e.g., if schema has 'entities[].scenarioCount': 'number', then
70
78
  // 'entities[].scenarioCount.sha' would go through a primitive and should be rejected
@@ -202,6 +210,23 @@ export default function mergeInDependentDataStructure({
202
210
  equivalentPostfixes: Record<string, string>;
203
211
  }[] = [];
204
212
 
213
+ // O(1) index for findOrCreateEquivalentSchemaPathsEntry.
214
+ // Maps "(rootPath)::(normalizedFuncName)" → the entry containing that root.
215
+ // This replaces the O(E) linear search that was causing O(E²) gather performance.
216
+ const espIndex = new Map<string, (typeof equivalentSchemaPaths)[0]>();
217
+ const espIndexKey = (path: string, functionName: string | undefined) => {
218
+ const normalized = cleanFunctionName(functionName);
219
+ const funcKey =
220
+ normalized === rootScopeName ? '__self__' : normalized || '__self__';
221
+ return `${path}::${funcKey}`;
222
+ };
223
+ const updateEspIndex = (entry: (typeof equivalentSchemaPaths)[0]) => {
224
+ for (const root of entry.equivalentRoots) {
225
+ const funcName = root.function?.name ?? rootScopeName;
226
+ espIndex.set(espIndexKey(root.schemaRootPath, funcName), entry);
227
+ }
228
+ };
229
+
205
230
  // Pre-build a lookup map from cleaned function name to dependency for O(1) lookups.
206
231
  // This avoids O(n) linear search in findRelevantDependency which was causing O(n²) performance.
207
232
  const dependencyByCleanedName = new Map<
@@ -253,8 +278,17 @@ export default function mergeInDependentDataStructure({
253
278
  return mergedDataStructure.dependencySchemas[filePath][name];
254
279
  };
255
280
 
256
- const cleanSchema = (schema: { [key: string]: string }) => {
257
- cleanKnownObjectFunctionsFromMapping(schema);
281
+ const cleanSchema = (
282
+ schema: { [key: string]: string },
283
+ context?: Record<string, any>,
284
+ ) => {
285
+ transformationTracer.traceSchemaTransform(
286
+ rootScopeName,
287
+ 'cleanKnownObjectFunctionsFromMapping',
288
+ schema,
289
+ cleanKnownObjectFunctionsFromMapping,
290
+ context,
291
+ );
258
292
  };
259
293
 
260
294
  const translatePath = (path: string, dependencyName: string) => {
@@ -307,6 +341,54 @@ export default function mergeInDependentDataStructure({
307
341
  ) => {
308
342
  if (!sourceAndUsageEquivalencies) return;
309
343
 
344
+ // Pre-computed normalized schema index cache.
345
+ // Avoids repeated splitOutsideParenthesesAndArrays calls and function-name
346
+ // normalization for the same schema paths across multiple equivalency iterations.
347
+ // The normalization depends on `functionName` (constant per gatherAllEquivalentSchemaPaths call),
348
+ // so this cache is scoped to this call.
349
+ type NormalizedEntry = { path: string; parts: string[] };
350
+ const normalizedSchemaCache = new Map<
351
+ object,
352
+ {
353
+ byFirstPart: Map<string, NormalizedEntry[]>;
354
+ }
355
+ >();
356
+ const getSchemaIndex = (
357
+ schema: Record<string, string> | undefined,
358
+ ): { byFirstPart: Map<string, NormalizedEntry[]> } => {
359
+ if (!schema) return { byFirstPart: new Map() };
360
+ const cached = normalizedSchemaCache.get(schema);
361
+ if (cached) return cached;
362
+ const byFirstPart = new Map<string, NormalizedEntry[]>();
363
+ for (const path in schema) {
364
+ let parts = splitOutsideParenthesesAndArrays(path);
365
+ if (parts[0].startsWith(functionName)) {
366
+ const baseName = cleanFunctionName(parts[0]);
367
+ if (!functionsWithMultipleTypeParams.has(baseName)) {
368
+ parts =
369
+ parts[1] === 'functionCallReturnValue'
370
+ ? ['returnValue', ...parts.slice(2)]
371
+ : parts.slice(1);
372
+ }
373
+ }
374
+ const entry: NormalizedEntry = { path, parts };
375
+ // Index by the base of the first part (before any function call args)
376
+ const firstPart = parts[0] ?? '';
377
+ const parenIdx = firstPart.indexOf('(');
378
+ const firstPartBase =
379
+ parenIdx >= 0 ? firstPart.slice(0, parenIdx) : firstPart;
380
+ let bucket = byFirstPart.get(firstPartBase);
381
+ if (!bucket) {
382
+ bucket = [];
383
+ byFirstPart.set(firstPartBase, bucket);
384
+ }
385
+ bucket.push(entry);
386
+ }
387
+ const result = { byFirstPart };
388
+ normalizedSchemaCache.set(schema, result);
389
+ return result;
390
+ };
391
+
310
392
  const findOrCreateEquivalentSchemaPathsEntry = (
311
393
  allPaths: { path: string; functionName?: string }[],
312
394
  ) => {
@@ -327,25 +409,102 @@ export default function mergeInDependentDataStructure({
327
409
  let equivalentSchemaPathsEntry:
328
410
  | (typeof equivalentSchemaPaths)[0]
329
411
  | undefined;
412
+
413
+ // Collect the signature indices from the new roots we want to add
414
+ const newRootSignatureIndices = new Set<number>();
415
+ for (const root of equivalentRoots) {
416
+ const idx = extractSignatureIndex(root.schemaRootPath);
417
+ if (idx !== undefined) {
418
+ newRootSignatureIndices.add(idx);
419
+ }
420
+ }
421
+
422
+ // Use espIndex Map for O(1) lookup instead of O(E) linear search.
423
+ // Falls back to linear search only when Map hit has a signature index conflict.
330
424
  for (const pathInfo of allPaths) {
331
- if (!equivalentSchemaPathsEntry) {
332
- equivalentSchemaPathsEntry = equivalentSchemaPaths.find((esp) =>
333
- esp.equivalentRoots.some(
334
- (er) =>
335
- er.schemaRootPath === pathInfo.path &&
336
- (er.function?.name ===
337
- cleanFunctionName(pathInfo.functionName) ||
338
- (!er.function &&
339
- cleanFunctionName(pathInfo.functionName) ===
340
- rootScopeName)),
341
- ),
342
- );
425
+ if (equivalentSchemaPathsEntry) break;
426
+ const candidate = espIndex.get(
427
+ espIndexKey(pathInfo.path, pathInfo.functionName),
428
+ );
429
+ if (!candidate) continue;
430
+
431
+ // Verify no signature index conflict with the candidate entry
432
+ if (newRootSignatureIndices.size > 0) {
433
+ const existingIndicesByFunction = new Map<string, Set<number>>();
434
+ for (const er of candidate.equivalentRoots) {
435
+ const funcKey = er.function
436
+ ? `${er.function.name}::${er.function.filePath}`
437
+ : '__self__';
438
+ const idx = extractSignatureIndex(er.schemaRootPath);
439
+ if (idx !== undefined) {
440
+ if (!existingIndicesByFunction.has(funcKey)) {
441
+ existingIndicesByFunction.set(funcKey, new Set());
442
+ }
443
+ existingIndicesByFunction.get(funcKey)!.add(idx);
444
+ }
445
+ }
446
+
447
+ let hasConflict = false;
448
+ for (const newRoot of equivalentRoots) {
449
+ const funcKey = newRoot.function
450
+ ? `${newRoot.function.name}::${newRoot.function.filePath}`
451
+ : '__self__';
452
+ const newIdx = extractSignatureIndex(newRoot.schemaRootPath);
453
+ if (newIdx !== undefined) {
454
+ const existingIndices = existingIndicesByFunction.get(funcKey);
455
+ if (existingIndices && existingIndices.size > 0) {
456
+ if (!existingIndices.has(newIdx)) {
457
+ hasConflict = true;
458
+ break;
459
+ }
460
+ }
461
+ }
462
+ }
463
+
464
+ if (hasConflict) continue;
343
465
  }
466
+
467
+ equivalentSchemaPathsEntry = candidate;
344
468
  }
345
469
 
346
470
  if (!equivalentSchemaPathsEntry) {
471
+ // Before creating a new entry, filter out roots that have conflicting
472
+ // signature indices from the same function. An entry should never contain
473
+ // roots with different signature indices from the same function.
474
+ // This prevents the bug where signature[1], signature[2], signature[4]
475
+ // all get merged together due to incorrect sourceEquivalencies.
476
+ let filteredRoots = equivalentRoots;
477
+ if (newRootSignatureIndices.size > 1) {
478
+ // There are multiple signature indices - we need to filter to keep only
479
+ // one consistent set. We'll keep the roots that match the PRIMARY index
480
+ // (the first signature index we encounter from self, or the lowest index).
481
+
482
+ // First, determine the primary index - prefer the self root's index
483
+ let primaryIndex: number | undefined;
484
+ for (const root of equivalentRoots) {
485
+ if (!root.function) {
486
+ // This is a self root
487
+ const idx = extractSignatureIndex(root.schemaRootPath);
488
+ if (idx !== undefined) {
489
+ primaryIndex = idx;
490
+ break;
491
+ }
492
+ }
493
+ }
494
+ // If no self root has a signature index, use the lowest index
495
+ if (primaryIndex === undefined) {
496
+ primaryIndex = Math.min(...newRootSignatureIndices);
497
+ }
498
+
499
+ // Filter roots: keep if no signature index OR signature index matches primary
500
+ filteredRoots = equivalentRoots.filter((root) => {
501
+ const idx = extractSignatureIndex(root.schemaRootPath);
502
+ return idx === undefined || idx === primaryIndex;
503
+ });
504
+ }
505
+
347
506
  equivalentSchemaPathsEntry = {
348
- equivalentRoots,
507
+ equivalentRoots: filteredRoots,
349
508
  equivalentPostfixes: {},
350
509
  };
351
510
  equivalentSchemaPaths.push(equivalentSchemaPathsEntry);
@@ -363,6 +522,9 @@ export default function mergeInDependentDataStructure({
363
522
  return true;
364
523
  });
365
524
 
525
+ // Keep the espIndex in sync after adding/deduplicating roots
526
+ updateEspIndex(equivalentSchemaPathsEntry);
527
+
366
528
  return equivalentSchemaPathsEntry;
367
529
  };
368
530
 
@@ -431,6 +593,8 @@ export default function mergeInDependentDataStructure({
431
593
  );
432
594
 
433
595
  const derivedBasePaths: { path: string; functionName?: string }[] = [];
596
+ const allPathSet = new Set(allPaths.map((p) => p.path));
597
+ const derivedBasePathSet = new Set<string>();
434
598
 
435
599
  // For each child path, find its equivalent parent path and derive bases
436
600
  for (const childPathInfo of childPaths) {
@@ -507,26 +671,28 @@ export default function mergeInDependentDataStructure({
507
671
  !childHasArrayIterator &&
508
672
  !childBaseIsGenericSignature
509
673
  ) {
510
- // Add child base if not already present
511
- const childBaseExists =
512
- allPaths.some((p) => p.path === childBase) ||
513
- derivedBasePaths.some((p) => p.path === childBase);
514
- if (!childBaseExists) {
674
+ // Add child base if not already present (O(1) Set lookup)
675
+ if (
676
+ !allPathSet.has(childBase) &&
677
+ !derivedBasePathSet.has(childBase)
678
+ ) {
515
679
  derivedBasePaths.push({
516
680
  path: childBase,
517
681
  functionName: childPathInfo.functionName,
518
682
  });
683
+ derivedBasePathSet.add(childBase);
519
684
  }
520
685
 
521
- // Add parent base if not already present
522
- const parentBaseExists =
523
- allPaths.some((p) => p.path === parentBase) ||
524
- derivedBasePaths.some((p) => p.path === parentBase);
525
- if (!parentBaseExists) {
686
+ // Add parent base if not already present (O(1) Set lookup)
687
+ if (
688
+ !allPathSet.has(parentBase) &&
689
+ !derivedBasePathSet.has(parentBase)
690
+ ) {
526
691
  derivedBasePaths.push({
527
692
  path: parentBase,
528
693
  functionName: parentPathInfo.functionName,
529
694
  });
695
+ derivedBasePathSet.add(parentBase);
530
696
  }
531
697
  }
532
698
  }
@@ -537,6 +703,26 @@ export default function mergeInDependentDataStructure({
537
703
  allPaths.push(...derivedBasePaths);
538
704
 
539
705
  const entry = findOrCreateEquivalentSchemaPathsEntry(allPaths);
706
+
707
+ // Trace equivalency gathering - helps debug why paths may not be connected
708
+ if (allPaths.length > 1) {
709
+ transformationTracer.operation(rootScopeName, {
710
+ operation: 'gatherEquivalency',
711
+ stage: 'gathering',
712
+ path: translatedPath,
713
+ context: {
714
+ sourceFunction: functionName,
715
+ equivalentPaths: allPaths.map((p) => ({
716
+ path: p.path,
717
+ function: p.functionName,
718
+ })),
719
+ equivalentRoots: entry.equivalentRoots.map((r) => ({
720
+ path: r.schemaRootPath,
721
+ function: r.function?.name,
722
+ })),
723
+ },
724
+ });
725
+ }
540
726
  for (const equivalentRoot of entry.equivalentRoots) {
541
727
  const dataStructures =
542
728
  equivalentRoot.function &&
@@ -584,21 +770,20 @@ export default function mergeInDependentDataStructure({
584
770
  }
585
771
 
586
772
  for (const schema of schemas) {
587
- for (const schemaPath in schema) {
588
- let schemaPathParts =
589
- splitOutsideParenthesesAndArrays(schemaPath);
590
-
591
- if (schemaPathParts[0].startsWith(functionName)) {
592
- // Only normalize if the function doesn't have multiple different type parameters
593
- const baseName = cleanFunctionName(schemaPathParts[0]);
594
- if (!functionsWithMultipleTypeParams.has(baseName)) {
595
- schemaPathParts =
596
- schemaPathParts[1] === 'functionCallReturnValue'
597
- ? ['returnValue', ...schemaPathParts.slice(2)]
598
- : schemaPathParts.slice(1);
599
- }
600
- }
601
-
773
+ // Use pre-computed index to only iterate schema entries whose
774
+ // normalized first part matches pathParts[0], instead of all entries.
775
+ const schemaIndex = getSchemaIndex(schema);
776
+ const lookupPart = pathParts[0] ?? '';
777
+ const lookupParenIdx = lookupPart.indexOf('(');
778
+ const lookupBase =
779
+ lookupParenIdx >= 0
780
+ ? lookupPart.slice(0, lookupParenIdx)
781
+ : lookupPart;
782
+ const candidates = schemaIndex.byFirstPart.get(lookupBase) || [];
783
+ for (const {
784
+ path: schemaPath,
785
+ parts: schemaPathParts,
786
+ } of candidates) {
602
787
  if (schemaPathParts.length < pathParts.length) continue;
603
788
 
604
789
  // Check if all path parts match (allowing function call variants)
@@ -667,13 +852,29 @@ export default function mergeInDependentDataStructure({
667
852
  schemaPathParts.slice(matchedUpToIndex),
668
853
  );
669
854
 
670
- entry.equivalentPostfixes[postfix] = entry
671
- .equivalentPostfixes[postfix]
672
- ? bestValueFromOptions([
673
- entry.equivalentPostfixes[postfix],
674
- schema[schemaPath],
675
- ])
676
- : schema[schemaPath];
855
+ const previousValue = entry.equivalentPostfixes[postfix];
856
+ const newValue = schema[schemaPath];
857
+ entry.equivalentPostfixes[postfix] = previousValue
858
+ ? bestValueFromOptions([previousValue, newValue])
859
+ : newValue;
860
+
861
+ // Trace postfix gathering - shows where type info comes from
862
+ if (entry.equivalentPostfixes[postfix] !== previousValue) {
863
+ transformationTracer.operation(rootScopeName, {
864
+ operation: 'gatherPostfix',
865
+ stage: 'gathering',
866
+ path: postfix || '(root)',
867
+ before: previousValue,
868
+ after: entry.equivalentPostfixes[postfix],
869
+ context: {
870
+ sourceSchemaPath: schemaPath,
871
+ sourceFunction:
872
+ equivalentRoot.function?.name || rootScopeName,
873
+ equivalentRootPath: equivalentRoot.schemaRootPath,
874
+ rawValue: newValue,
875
+ },
876
+ });
877
+ }
677
878
  }
678
879
  }
679
880
  }
@@ -710,10 +911,17 @@ export default function mergeInDependentDataStructure({
710
911
  const entry = findOrCreateEquivalentSchemaPathsEntry([
711
912
  { path: translatedBasePath, functionName: functionName },
712
913
  ]);
713
- entry.equivalentRoots.push({
914
+ const newRoot = {
714
915
  schemaRootPath: translatedBasePath,
715
916
  function: findRelevantDependency(functionName),
716
- });
917
+ };
918
+ entry.equivalentRoots.push(newRoot);
919
+ // Update index for the newly added root
920
+ const newRootFuncName = newRoot.function?.name ?? rootScopeName;
921
+ espIndex.set(
922
+ espIndexKey(newRoot.schemaRootPath, newRootFuncName),
923
+ entry,
924
+ );
717
925
 
718
926
  const basePathParts = splitOutsideParenthesesAndArrays(basePath);
719
927
  for (const schemaPath in dataStructure.returnValueSchema) {
@@ -733,14 +941,14 @@ export default function mergeInDependentDataStructure({
733
941
  const postfix = joinParenthesesAndArrays(
734
942
  schemaPathParts.slice(basePathParts.length),
735
943
  );
736
- entry.equivalentPostfixes[postfix] = entry.equivalentPostfixes[
737
- postfix
738
- ]
944
+ const newValue = entry.equivalentPostfixes[postfix]
739
945
  ? bestValueFromOptions([
740
946
  entry.equivalentPostfixes[postfix],
741
947
  dataStructure.returnValueSchema[schemaPath],
742
948
  ])
743
949
  : dataStructure.returnValueSchema[schemaPath];
950
+
951
+ entry.equivalentPostfixes[postfix] = newValue;
744
952
  }
745
953
  }
746
954
  }
@@ -795,6 +1003,10 @@ export default function mergeInDependentDataStructure({
795
1003
  equivalentRootFunction: (typeof equivalentSchemaPaths)[0]['equivalentRoots'][0]['function'],
796
1004
  ) => {
797
1005
  let postfix: string | undefined;
1006
+
1007
+ // Get the signature index we're looking for (if any)
1008
+ const lookingForSignatureIndex = extractSignatureIndex(schemaSubPath);
1009
+
798
1010
  const equivalentEntry = mergedEquivalentSchemaPaths.find((esp) =>
799
1011
  esp.equivalentRoots.some((er) => {
800
1012
  if (
@@ -807,6 +1019,35 @@ export default function mergeInDependentDataStructure({
807
1019
  }
808
1020
 
809
1021
  if (schemaSubPath === er.schemaRootPath) {
1022
+ // Additional check: if we're looking for a signature path, make sure
1023
+ // the entry doesn't already have DIFFERENT signature indices.
1024
+ // This prevents entries with signature[1], signature[2], signature[4]
1025
+ // from all being merged together.
1026
+ if (lookingForSignatureIndex !== undefined) {
1027
+ const hasConflictingSignatureIndex = esp.equivalentRoots.some(
1028
+ (otherRoot) => {
1029
+ // Only check roots from the same function
1030
+ if (
1031
+ otherRoot.function?.name !== equivalentRootFunction?.name ||
1032
+ otherRoot.function?.filePath !==
1033
+ equivalentRootFunction?.filePath
1034
+ ) {
1035
+ return false;
1036
+ }
1037
+ const otherIndex = extractSignatureIndex(
1038
+ otherRoot.schemaRootPath,
1039
+ );
1040
+ return (
1041
+ otherIndex !== undefined &&
1042
+ otherIndex !== lookingForSignatureIndex
1043
+ );
1044
+ },
1045
+ );
1046
+ if (hasConflictingSignatureIndex) {
1047
+ return false;
1048
+ }
1049
+ }
1050
+
810
1051
  postfix = er.postfix;
811
1052
  return true;
812
1053
  }
@@ -940,6 +1181,10 @@ export default function mergeInDependentDataStructure({
940
1181
 
941
1182
  equivalentSchemaPaths = mergeAllEquivalentSchemaPaths();
942
1183
 
1184
+ // Collect schemas that need cleaning — batch the calls for the end instead of
1185
+ // calling cleanSchema inside the inner root loop (which was O(roots * schemaSize)).
1186
+ const schemasToClean = new Set<{ [key: string]: string }>();
1187
+
943
1188
  for (const esp of equivalentSchemaPaths) {
944
1189
  // Pre-compute which postfixes have children to avoid O(n²) lookups in the inner loop.
945
1190
  // A postfix "has children" if there are other postfixes that extend it.
@@ -1037,6 +1282,15 @@ export default function mergeInDependentDataStructure({
1037
1282
  // Skip paths that would go through a primitive type
1038
1283
  // e.g., if schema has 'entities[].scenarioCount': 'number', skip 'entities[].scenarioCount.sha'
1039
1284
  if (wouldGoThroughPrimitive(newSchemaPath, schema)) {
1285
+ transformationTracer.operation(rootScopeName, {
1286
+ operation: 'skipPrimitivePath',
1287
+ stage: 'merged',
1288
+ path: newSchemaPath,
1289
+ context: {
1290
+ reason: 'would go through primitive type',
1291
+ postfixValue,
1292
+ },
1293
+ });
1040
1294
  continue;
1041
1295
  }
1042
1296
 
@@ -1060,6 +1314,16 @@ export default function mergeInDependentDataStructure({
1060
1314
  PRIMITIVE_TYPES.has(existingType) &&
1061
1315
  (postfixValue === 'object' || postfixValue === 'array')
1062
1316
  ) {
1317
+ transformationTracer.operation(rootScopeName, {
1318
+ operation: 'skipTypeDowngrade',
1319
+ stage: 'merged',
1320
+ path: newSchemaPath,
1321
+ context: {
1322
+ reason: 'would overwrite primitive with object/array',
1323
+ existingType,
1324
+ newType: postfixValue,
1325
+ },
1326
+ });
1063
1327
  continue;
1064
1328
  }
1065
1329
  // Don't overwrite a complex/union type with a primitive
@@ -1068,17 +1332,45 @@ export default function mergeInDependentDataStructure({
1068
1332
  !PRIMITIVE_TYPES.has(existingType) &&
1069
1333
  PRIMITIVE_TYPES.has(postfixValue)
1070
1334
  ) {
1335
+ transformationTracer.operation(rootScopeName, {
1336
+ operation: 'skipTypeDowngrade',
1337
+ stage: 'merged',
1338
+ path: newSchemaPath,
1339
+ context: {
1340
+ reason: 'would overwrite complex type with primitive',
1341
+ existingType,
1342
+ newType: postfixValue,
1343
+ },
1344
+ });
1071
1345
  continue;
1072
1346
  }
1073
1347
  }
1074
1348
 
1349
+ // Log the successful postfix merge
1350
+ transformationTracer.operation(rootScopeName, {
1351
+ operation: 'mergePostfix',
1352
+ stage: 'merged',
1353
+ path: newSchemaPath,
1354
+ before: existingType,
1355
+ after: postfixValue,
1356
+ context: {
1357
+ schemaRootPath: equivalentRoot.schemaRootPath,
1358
+ postfix: relevantPostfix,
1359
+ dependency: equivalentRoot.function?.name,
1360
+ },
1361
+ });
1075
1362
  schema[newSchemaPath] = postfixValue;
1076
1363
  }
1077
1364
 
1078
- cleanSchema(schema);
1365
+ schemasToClean.add(schema);
1079
1366
  }
1080
1367
  }
1081
1368
 
1369
+ // Batch-clean all modified schemas once (instead of once per root per ESP entry)
1370
+ for (const schema of schemasToClean) {
1371
+ cleanSchema(schema, { stage: 'afterMergePostfix' });
1372
+ }
1373
+
1082
1374
  // Propagate equivalency-derived attributes to generic function call variants.
1083
1375
  // When attributes are traced via equivalencies (e.g., fileComparisons from buildDataMap.signature[2]),
1084
1376
  // they get written to non-generic paths (returnValue.data.x or funcName().functionCallReturnValue.data.x).
@@ -1197,6 +1489,14 @@ export default function mergeInDependentDataStructure({
1197
1489
  `${dependency.name}().functionCallReturnValue`,
1198
1490
  );
1199
1491
  }
1492
+ transformationTracer.operation(rootScopeName, {
1493
+ operation: 'normalizeReturnValuePath',
1494
+ stage: 'merged',
1495
+ path: normalizedPath,
1496
+ before: path,
1497
+ after: normalizedPath,
1498
+ context: { dependency: dependency.name, value },
1499
+ });
1200
1500
  depSchema.returnValueSchema[normalizedPath] = value;
1201
1501
  }
1202
1502
 
@@ -1281,7 +1581,10 @@ export default function mergeInDependentDataStructure({
1281
1581
  }
1282
1582
  }
1283
1583
 
1284
- cleanSchema(depSchema.returnValueSchema);
1584
+ cleanSchema(depSchema.returnValueSchema, {
1585
+ stage: 'afterMockedDependencyMerge',
1586
+ dependency: dependency.name,
1587
+ });
1285
1588
 
1286
1589
  // Pull signature requirements from downstream functions into the mocked return value.
1287
1590
  // When a mocked function's return flows into another function's signature (via usageEquivalencies),
@@ -1358,7 +1661,10 @@ export default function mergeInDependentDataStructure({
1358
1661
  }
1359
1662
  }
1360
1663
 
1361
- cleanSchema(depSchema.returnValueSchema);
1664
+ cleanSchema(depSchema.returnValueSchema, {
1665
+ stage: 'afterSignatureRequirementsMerge',
1666
+ dependency: dependency.name,
1667
+ });
1362
1668
  }
1363
1669
 
1364
1670
  // Process the input dependencySchemas FIRST (before child dependentAnalyses).
@@ -1399,7 +1705,11 @@ export default function mergeInDependentDataStructure({
1399
1705
  // from the copied schema. Without this, method call paths on primitives like
1400
1706
  // "projectSlug.replace(...)" would cause convertDotNotation to create nested
1401
1707
  // object structures instead of preserving the primitive type.
1402
- cleanSchema(depSchema.returnValueSchema);
1708
+ cleanSchema(depSchema.returnValueSchema, {
1709
+ stage: 'afterDependencySchemaCopy',
1710
+ filePath,
1711
+ dependency: name,
1712
+ });
1403
1713
  }
1404
1714
 
1405
1715
  // TYPE REFINEMENT: Check if dependentAnalyses has a more specific type for this dependency.
@@ -1470,7 +1780,12 @@ export default function mergeInDependentDataStructure({
1470
1780
  srcSchema.returnValueSchema[path];
1471
1781
  }
1472
1782
  }
1473
- cleanSchema(variantSchema.returnValueSchema);
1783
+ cleanSchema(variantSchema.returnValueSchema, {
1784
+ stage: 'afterTypeVariantCopy',
1785
+ filePath,
1786
+ dependency: name,
1787
+ variant,
1788
+ });
1474
1789
  }
1475
1790
  }
1476
1791
  }
@@ -4,3 +4,4 @@ export { type FunctionDependenciesMap } from './asts/sourceFiles/getPseudoFile';
4
4
  export * as asts from './asts/index';
5
5
  export * as projects from './projects/index';
6
6
  export * as types from './types';
7
+ export { transformationTracer } from './files/scenarios/TransformationTracer';
@@ -15,7 +15,7 @@
15
15
  "@supabase/supabase-js": "2.88.0",
16
16
  "better-sqlite3": "^12.4.1",
17
17
  "fetch-retry": "^6.0.0",
18
- "kysely": "^0.28.5",
18
+ "kysely": "^0.28.11",
19
19
  "pg": "^8.16.3"
20
20
  },
21
21
  "jest": {
@@ -1,6 +1,6 @@
1
1
  import { AnalysisBranch } from '~codeyam/types';
2
2
  import { DbAnalysisBranch } from './kysely/tableRelations';
3
- import { randomUUID } from 'crypto';
3
+ const randomUUID = () => crypto.randomUUID();
4
4
  import { AnalysisBranchesTable } from './kysely/tables/analysisBranchesTable';
5
5
  import { type Insertable } from 'kysely';
6
6
 
@@ -1,7 +1,7 @@
1
1
  import { Analysis } from '~codeyam/types';
2
2
  import { type Insertable } from 'kysely';
3
3
  import { AnalysesTable } from './kysely/tables/analysesTable';
4
- import { randomUUID } from 'crypto';
4
+ const randomUUID = () => crypto.randomUUID();
5
5
 
6
6
  export default function analysisToDb(
7
7
  analysis: Analysis,
@@ -1,7 +1,7 @@
1
1
  import { Branch } from '~codeyam/types';
2
2
  import { type Insertable } from 'kysely';
3
3
  import { BranchesTable } from './kysely/tables/branchesTable';
4
- import { randomUUID } from 'crypto';
4
+ const randomUUID = () => crypto.randomUUID();
5
5
 
6
6
  export default function branchToDb(branch: Branch): Insertable<BranchesTable> {
7
7
  const { id, projectId, activeAt, contentChangedAt, metadata, ...remaining } =