@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.2a88920

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 (437) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +5 -5
  4. package/analyzer-template/packages/ai/index.ts +15 -2
  5. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +87 -51
  6. package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +98 -9
  8. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +139 -23
  9. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +6 -126
  10. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +555 -28
  11. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +88 -7
  12. package/analyzer-template/packages/ai/src/lib/completionCall.ts +198 -34
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +772 -243
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +205 -0
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +10 -2
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +43 -1
  19. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +122 -15
  20. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +160 -0
  21. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
  22. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +319 -88
  23. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
  24. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +156 -0
  25. package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
  26. package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
  27. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +642 -7
  28. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
  29. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +383 -6
  30. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
  31. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1299 -51
  32. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
  33. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
  34. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
  35. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
  36. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
  37. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +23 -6
  38. package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
  39. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
  40. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
  41. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
  42. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
  43. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
  44. package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
  45. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
  46. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
  47. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
  48. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
  49. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
  50. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
  51. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +30 -19
  52. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +14 -4
  53. package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
  54. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
  55. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
  56. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
  57. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
  58. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +189 -76
  59. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +29 -0
  60. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +77 -9
  61. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
  62. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +276 -17
  63. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
  64. package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
  65. package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
  66. package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
  67. package/analyzer-template/packages/aws/package.json +2 -2
  68. package/analyzer-template/packages/database/src/lib/kysely/db.ts +8 -1
  69. package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
  70. package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
  71. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
  72. package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
  73. package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
  74. package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
  75. package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
  76. package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
  77. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
  78. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  79. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +8 -1
  80. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  81. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  82. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
  83. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
  84. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
  85. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  86. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
  87. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
  88. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
  89. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
  90. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  91. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
  92. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  93. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
  94. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
  95. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
  96. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
  97. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
  98. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
  99. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
  100. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
  101. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
  102. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
  103. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  104. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
  105. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  106. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
  107. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
  108. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
  109. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
  110. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  111. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
  112. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  113. package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
  114. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  115. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  116. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
  117. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  118. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
  119. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
  120. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  121. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  122. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  123. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  124. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
  125. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  126. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
  127. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
  128. package/analyzer-template/packages/github/package.json +1 -1
  129. package/analyzer-template/packages/types/index.ts +1 -0
  130. package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
  131. package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
  132. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
  133. package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
  134. package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
  135. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  136. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  137. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
  138. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  139. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
  140. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
  141. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  142. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  143. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  144. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  145. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
  146. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  147. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
  148. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
  149. package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
  150. package/analyzer-template/playwright/capture.ts +20 -8
  151. package/analyzer-template/playwright/captureStatic.ts +1 -1
  152. package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
  153. package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
  154. package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
  155. package/analyzer-template/project/constructMockCode.ts +367 -37
  156. package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
  157. package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
  158. package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
  159. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
  160. package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
  161. package/analyzer-template/project/orchestrateCapture.ts +71 -6
  162. package/analyzer-template/project/reconcileMockDataKeys.ts +152 -9
  163. package/analyzer-template/project/runAnalysis.ts +4 -0
  164. package/analyzer-template/project/start.ts +35 -11
  165. package/analyzer-template/project/writeMockDataTsx.ts +127 -4
  166. package/analyzer-template/project/writeScenarioComponents.ts +101 -8
  167. package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
  168. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
  169. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
  170. package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
  171. package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
  172. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
  173. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
  174. package/background/src/lib/virtualized/project/constructMockCode.js +300 -7
  175. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  176. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
  177. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
  178. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
  179. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
  180. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
  181. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
  182. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
  183. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  184. package/background/src/lib/virtualized/project/orchestrateCapture.js +58 -6
  185. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  186. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +126 -9
  187. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  188. package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
  189. package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
  190. package/background/src/lib/virtualized/project/start.js +32 -11
  191. package/background/src/lib/virtualized/project/start.js.map +1 -1
  192. package/background/src/lib/virtualized/project/writeMockDataTsx.js +101 -4
  193. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  194. package/background/src/lib/virtualized/project/writeScenarioComponents.js +57 -8
  195. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  196. package/codeyam-cli/src/cli.js +2 -0
  197. package/codeyam-cli/src/cli.js.map +1 -1
  198. package/codeyam-cli/src/commands/debug.js +7 -5
  199. package/codeyam-cli/src/commands/debug.js.map +1 -1
  200. package/codeyam-cli/src/commands/memory.js +273 -0
  201. package/codeyam-cli/src/commands/memory.js.map +1 -0
  202. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +4 -0
  203. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  204. package/codeyam-cli/src/utils/analysisRunner.js +21 -2
  205. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  206. package/codeyam-cli/src/utils/install-skills.js +42 -6
  207. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  208. package/codeyam-cli/src/utils/queue/job.js +1 -0
  209. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  210. package/codeyam-cli/src/utils/queue/manager.js +6 -0
  211. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  212. package/codeyam-cli/src/utils/rules/index.js +5 -0
  213. package/codeyam-cli/src/utils/rules/index.js.map +1 -0
  214. package/codeyam-cli/src/utils/rules/parser.js +106 -0
  215. package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
  216. package/codeyam-cli/src/utils/rules/pathMatcher.js +18 -0
  217. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
  218. package/codeyam-cli/src/utils/rules/staleness.js +132 -0
  219. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
  220. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +2 -0
  221. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  222. package/codeyam-cli/src/webserver/app/lib/database.js +7 -3
  223. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  224. package/codeyam-cli/src/webserver/bootstrap.js +40 -0
  225. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  226. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-DsN1wKrm.js +11 -0
  227. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-DLqD3qNt.js} +1 -1
  228. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-Ba2JVPzP.js} +1 -1
  229. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CEleMv_j.js → InlineSpinner-C8lyxW9k.js} +1 -1
  230. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-aht4aafF.js} +2 -2
  231. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-CVtiBnY5.js} +1 -1
  232. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-B0GLXMsr.js} +1 -1
  233. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-xgeCVgSM.js} +1 -1
  234. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-OApQuNyq.js +16 -0
  235. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-DuDvi0jm.js} +1 -1
  236. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-DzccYyI8.js} +3 -13
  237. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-DyFZkK0l.js} +1 -1
  238. package/codeyam-cli/src/webserver/build/client/assets/_index-BwqWJOgH.js +11 -0
  239. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BwavGCpm.js +32 -0
  240. package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
  241. package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
  242. package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
  243. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-Cx24_aWc.js} +1 -1
  244. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-EPOLDU6W-CXRTFQ3F.js} +1 -1
  245. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-BOARzkeR.js} +1 -1
  246. package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +6 -0
  247. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-BdhJEx6B.js} +1 -1
  248. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BBnGWYga.js +1 -0
  249. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-BJUiQqZF.js} +12 -12
  250. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js → entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js} +1 -1
  251. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-wDWZZO1W.js → entity._sha_.create-scenario-D1T4TGjf.js} +1 -1
  252. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-CTBG2mmz.js} +1 -1
  253. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-CS2cb_eZ.js} +1 -1
  254. package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +6 -0
  255. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-DMJ7zii9.js} +1 -1
  256. package/codeyam-cli/src/webserver/build/client/assets/files-CJ6lTdTA.js +1 -0
  257. package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-CPTZZ-JZ.js} +8 -8
  258. package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +1 -0
  259. package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-B1h680n5.js} +1 -1
  260. package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-lzqtyFU8.js} +1 -1
  261. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-B7B9V-bu.js} +1 -1
  262. package/codeyam-cli/src/webserver/build/client/assets/manifest-a78b90a2.js +1 -0
  263. package/codeyam-cli/src/webserver/build/client/assets/memory--GCbFsBE.js +92 -0
  264. package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +62 -0
  265. package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-CxXUmBSd.js} +1 -1
  266. package/codeyam-cli/src/webserver/build/client/assets/{settings-B2eDuBj8.js → settings-CS5f3WzT.js} +1 -1
  267. package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-DwFIBT09.js} +1 -1
  268. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-B6LgvRJg.js} +1 -1
  269. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-C1v1PQzo.js} +1 -1
  270. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BUm0UVJm.js → useLastLogLine-aSv48UbS.js} +1 -1
  271. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-DYxHZQuP.js} +1 -1
  272. package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-mBRpZPiu.js} +1 -1
  273. package/codeyam-cli/src/webserver/build/server/assets/index-BM6TDT1Y.js +1 -0
  274. package/codeyam-cli/src/webserver/build/server/assets/server-build-dYC34MHw.js +257 -0
  275. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  276. package/codeyam-cli/src/webserver/build-info.json +5 -5
  277. package/codeyam-cli/templates/codeyam-memory-hook.sh +200 -0
  278. package/codeyam-cli/templates/codeyam:debug.md +47 -3
  279. package/codeyam-cli/templates/codeyam:diagnose.md +203 -25
  280. package/codeyam-cli/templates/codeyam:memory.md +341 -0
  281. package/codeyam-cli/templates/codeyam:new-rule.md +13 -0
  282. package/codeyam-cli/templates/rule-reflection-hook.py +160 -0
  283. package/codeyam-cli/templates/rules-instructions.md +93 -0
  284. package/package.json +8 -5
  285. package/packages/ai/index.js +7 -3
  286. package/packages/ai/index.js.map +1 -1
  287. package/packages/ai/src/lib/analyzeScope.js +70 -29
  288. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  289. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
  290. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
  291. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +78 -8
  292. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  293. package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
  294. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  295. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
  296. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
  297. package/packages/ai/src/lib/astScopes/processExpression.js +440 -27
  298. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  299. package/packages/ai/src/lib/completionCall.js +161 -30
  300. package/packages/ai/src/lib/completionCall.js.map +1 -1
  301. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +589 -166
  302. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  303. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
  304. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
  305. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
  306. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  307. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
  308. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
  309. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
  310. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
  311. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +41 -1
  312. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  313. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +104 -11
  314. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  315. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +159 -0
  316. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
  317. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
  318. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
  319. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +265 -79
  320. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  321. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
  322. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
  323. package/packages/ai/src/lib/dataStructureChunking.js +111 -0
  324. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
  325. package/packages/ai/src/lib/e2eDataTracking.js +241 -0
  326. package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
  327. package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
  328. package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
  329. package/packages/ai/src/lib/generateEntityScenarioData.js +525 -8
  330. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  331. package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
  332. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  333. package/packages/ai/src/lib/generateExecutionFlows.js +281 -4
  334. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  335. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +946 -42
  336. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  337. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
  338. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
  339. package/packages/ai/src/lib/mergeStatements.js +70 -51
  340. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  341. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
  342. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  343. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
  344. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
  345. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +15 -7
  346. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  347. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
  348. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
  349. package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
  350. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
  351. package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
  352. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  353. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
  354. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  355. package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
  356. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  357. package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
  358. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  359. package/packages/analyze/src/lib/analysisContext.js +30 -5
  360. package/packages/analyze/src/lib/analysisContext.js.map +1 -1
  361. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
  362. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
  363. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
  364. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
  365. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
  366. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  367. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
  368. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
  369. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
  370. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
  371. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
  372. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
  373. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +21 -9
  374. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  375. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +14 -4
  376. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  377. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
  378. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
  379. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
  380. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  381. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
  382. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  383. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
  384. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  385. package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
  386. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  387. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +160 -68
  388. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  389. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +25 -8
  390. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  391. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +71 -9
  392. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  393. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
  394. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  395. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +233 -9
  396. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  397. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
  398. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  399. package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
  400. package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
  401. package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
  402. package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
  403. package/packages/database/src/lib/kysely/db.js +8 -1
  404. package/packages/database/src/lib/kysely/db.js.map +1 -1
  405. package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
  406. package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  407. package/packages/database/src/lib/loadAnalyses.js +45 -2
  408. package/packages/database/src/lib/loadAnalyses.js.map +1 -1
  409. package/packages/database/src/lib/loadAnalysis.js +8 -0
  410. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  411. package/packages/database/src/lib/loadBranch.js +11 -1
  412. package/packages/database/src/lib/loadBranch.js.map +1 -1
  413. package/packages/database/src/lib/loadCommit.js +7 -0
  414. package/packages/database/src/lib/loadCommit.js.map +1 -1
  415. package/packages/database/src/lib/loadCommits.js +22 -1
  416. package/packages/database/src/lib/loadCommits.js.map +1 -1
  417. package/packages/database/src/lib/loadEntities.js +23 -4
  418. package/packages/database/src/lib/loadEntities.js.map +1 -1
  419. package/packages/database/src/lib/loadEntityBranches.js +9 -0
  420. package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
  421. package/packages/database/src/lib/updateCommitMetadata.js +5 -4
  422. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  423. package/packages/types/index.js.map +1 -1
  424. package/packages/utils/src/lib/safeFileName.js +29 -3
  425. package/packages/utils/src/lib/safeFileName.js.map +1 -1
  426. package/scripts/finalize-analyzer.cjs +3 -3
  427. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
  428. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
  429. package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
  430. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
  431. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
  432. package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
  433. package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
  434. package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
  435. package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
  436. package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
  437. package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
@@ -23,6 +23,112 @@ import {
23
23
  extractConditionalEffectsFromTernary,
24
24
  findUseStateSetters,
25
25
  } from './conditionalEffectsExtractor';
26
+ import { detectArrayDerivedPattern } from './arrayDerivationDetector';
27
+
28
+ /**
29
+ * Checks if a JSX element has props that reference variables from the parent scope.
30
+ * This is used to detect unconditionally-rendered children that should have their
31
+ * execution flows merged into the parent.
32
+ *
33
+ * We want to track children where the parent controls data that affects the child's
34
+ * conditional rendering. Static props (like title="Dashboard") don't need tracking
35
+ * because they don't create variable execution flows.
36
+ *
37
+ * Examples:
38
+ * - <WorkoutsView workouts={workouts} /> → true (workouts is a variable)
39
+ * - <ItemList items={items} count={count} /> → true (items, count are variables)
40
+ * - <Header title="Dashboard" /> → false (static string)
41
+ * - <Footer /> → false (no props)
42
+ * - <Button onClick={handleClick} /> → false (only callback, no data props)
43
+ *
44
+ * @returns true if the component has at least one prop that references a variable
45
+ * (excluding callbacks which typically start with 'on' or 'handle')
46
+ */
47
+ function hasDataPropsFromParent(
48
+ node: ts.JsxElement | ts.JsxSelfClosingElement,
49
+ componentName: string,
50
+ ): { hasDataProps: boolean; dataProps: string[] } {
51
+ const attributes = ts.isJsxElement(node)
52
+ ? node.openingElement.attributes.properties
53
+ : node.attributes.properties;
54
+
55
+ const dataProps: string[] = [];
56
+
57
+ for (const attr of attributes) {
58
+ // Spread attributes always reference parent data: {...props}
59
+ if (ts.isJsxSpreadAttribute(attr)) {
60
+ const spreadText = attr.expression?.getText() || '...spread';
61
+ dataProps.push(`{...${spreadText}}`);
62
+ console.log(
63
+ `[UnconditionalChild] ${componentName}: Found spread attribute {${spreadText}}`,
64
+ );
65
+ continue;
66
+ }
67
+
68
+ if (ts.isJsxAttribute(attr)) {
69
+ const propName = attr.name.getText();
70
+
71
+ // Skip callback props - they don't create data-driven execution flows
72
+ // Callbacks typically start with 'on' (onClick, onChange) or 'handle' (handleSubmit)
73
+ if (
74
+ propName.startsWith('on') ||
75
+ propName.startsWith('handle') ||
76
+ propName === 'ref'
77
+ ) {
78
+ console.log(
79
+ `[UnconditionalChild] ${componentName}: Skipping callback prop '${propName}'`,
80
+ );
81
+ continue;
82
+ }
83
+
84
+ // Check if the prop value is a JSX expression (references a variable)
85
+ // vs a string literal which is static
86
+ if (attr.initializer) {
87
+ if (ts.isJsxExpression(attr.initializer)) {
88
+ // JSX expression like prop={value} - this references a variable
89
+ // Could be a simple identifier, property access, or more complex expression
90
+ const expression = attr.initializer.expression;
91
+ if (expression) {
92
+ // Skip if it's just a function/arrow function (callback)
93
+ if (
94
+ ts.isArrowFunction(expression) ||
95
+ ts.isFunctionExpression(expression)
96
+ ) {
97
+ console.log(
98
+ `[UnconditionalChild] ${componentName}: Skipping inline callback prop '${propName}'`,
99
+ );
100
+ continue;
101
+ }
102
+ // This is a data prop that references parent state/props
103
+ const exprText = expression.getText();
104
+ dataProps.push(`${propName}={${exprText}}`);
105
+ console.log(
106
+ `[UnconditionalChild] ${componentName}: Found data prop '${propName}' = {${exprText}}`,
107
+ );
108
+ }
109
+ } else {
110
+ // String literals like prop="value" are static
111
+ console.log(
112
+ `[UnconditionalChild] ${componentName}: Skipping static prop '${propName}'`,
113
+ );
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ const hasDataProps = dataProps.length > 0;
120
+ if (hasDataProps) {
121
+ console.log(
122
+ `[UnconditionalChild] ${componentName}: Has ${dataProps.length} data props: [${dataProps.join(', ')}]`,
123
+ );
124
+ } else {
125
+ console.log(
126
+ `[UnconditionalChild] ${componentName}: No data props found, will NOT track`,
127
+ );
128
+ }
129
+
130
+ return { hasDataProps, dataProps };
131
+ }
26
132
 
27
133
  /**
28
134
  * Extracts the component name from a JSX element.
@@ -368,6 +474,149 @@ function getSourceLocation(
368
474
  };
369
475
  }
370
476
 
477
+ /**
478
+ * Extracts the root array path from an expression that ends with .map().
479
+ * Handles chained methods like .filter().map(), .slice().map(), etc.
480
+ *
481
+ * Examples:
482
+ * - items.map(...) → "items"
483
+ * - data.users.map(...) → "data.users"
484
+ * - items.filter(...).map(...) → "items"
485
+ * - items.slice(0, 5).map(...) → "items"
486
+ */
487
+ function extractArrayPathFromMapCall(
488
+ expr: ts.CallExpression,
489
+ sourceFile: ts.SourceFile,
490
+ ): string | null {
491
+ // Walk up the chain to find the root array
492
+ let current: ts.Expression = expr.expression;
493
+
494
+ while (ts.isPropertyAccessExpression(current)) {
495
+ const methodName = current.name.getText(sourceFile);
496
+
497
+ // Common array methods that return arrays (so we keep going up)
498
+ const arrayReturningMethods = [
499
+ 'map',
500
+ 'filter',
501
+ 'slice',
502
+ 'concat',
503
+ 'flat',
504
+ 'flatMap',
505
+ 'reverse',
506
+ 'sort',
507
+ 'toReversed',
508
+ 'toSorted',
509
+ 'toSpliced',
510
+ ];
511
+
512
+ if (arrayReturningMethods.includes(methodName)) {
513
+ const objectExpr = current.expression;
514
+
515
+ // If the object is a call expression (chained method), keep going
516
+ if (ts.isCallExpression(objectExpr)) {
517
+ current = objectExpr.expression;
518
+ } else {
519
+ // Found the root - it's an identifier or property access
520
+ const path = StructuredPath.fromNode(objectExpr, sourceFile);
521
+ return path ? path.toString() : null;
522
+ }
523
+ } else {
524
+ // Not an array method we recognize
525
+ break;
526
+ }
527
+ }
528
+
529
+ return null;
530
+ }
531
+
532
+ /**
533
+ * Extracts JSX rendering usages from a JSX expression.
534
+ * Detects:
535
+ * - array.map() calls → 'array-map' type
536
+ * - string interpolations (identifiers/property access) → 'text-interpolation' type
537
+ *
538
+ * Recursively searches inside && chains and ternary expressions.
539
+ *
540
+ * @param expr The expression inside {expr}
541
+ * @param context The analysis context
542
+ */
543
+ function extractJsxRenderingUsage(
544
+ expr: ts.Expression,
545
+ context: AnalysisContext,
546
+ ): void {
547
+ const unwrapped = unwrapExpression(expr);
548
+ const sourceLocation = getSourceLocation(expr, context.sourceFile);
549
+
550
+ // Detect array.map() calls
551
+ if (ts.isCallExpression(unwrapped)) {
552
+ const calleeExpr = unwrapped.expression;
553
+
554
+ if (ts.isPropertyAccessExpression(calleeExpr)) {
555
+ const methodName = calleeExpr.name.getText(context.sourceFile);
556
+
557
+ if (methodName === 'map') {
558
+ const arrayPath = extractArrayPathFromMapCall(
559
+ unwrapped,
560
+ context.sourceFile,
561
+ );
562
+
563
+ if (arrayPath) {
564
+ context.addJsxRenderingUsage({
565
+ path: arrayPath,
566
+ renderingType: 'array-map',
567
+ valueType: 'array',
568
+ sourceLocation,
569
+ });
570
+ }
571
+ }
572
+ }
573
+ }
574
+ // Detect simple string interpolations: {title} or {user.name}
575
+ else if (
576
+ ts.isIdentifier(unwrapped) ||
577
+ ts.isPropertyAccessExpression(unwrapped)
578
+ ) {
579
+ const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
580
+
581
+ if (path) {
582
+ const pathStr = path.toString();
583
+ const typeInfo = context.getTypeInfo(path);
584
+
585
+ // Only track as text interpolation if it's a string type
586
+ // Check for 'string' type, or types that contain 'string' (but not 'string[]')
587
+ if (
588
+ typeInfo === 'string' ||
589
+ (typeInfo &&
590
+ typeInfo.includes('string') &&
591
+ !typeInfo.includes('string[]'))
592
+ ) {
593
+ context.addJsxRenderingUsage({
594
+ path: pathStr,
595
+ renderingType: 'text-interpolation',
596
+ valueType: 'string',
597
+ sourceLocation,
598
+ });
599
+ }
600
+ }
601
+ }
602
+ // Recursively search inside && chains: {showList && items.map(...)}
603
+ else if (
604
+ ts.isBinaryExpression(unwrapped) &&
605
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
606
+ ) {
607
+ // Check the right side of the && chain (where .map() typically appears)
608
+ const rightSide = unwrapExpression(unwrapped.right);
609
+ extractJsxRenderingUsage(rightSide, context);
610
+ // Also check nested && chains on the left
611
+ extractJsxRenderingUsage(unwrapped.left, context);
612
+ }
613
+ // Recursively search inside ternaries: {isEmpty ? null : items.map(...)}
614
+ else if (ts.isConditionalExpression(unwrapped)) {
615
+ extractJsxRenderingUsage(unwrapped.whenTrue, context);
616
+ extractJsxRenderingUsage(unwrapped.whenFalse, context);
617
+ }
618
+ }
619
+
371
620
  /**
372
621
  * Counts the number of conditions in an && chain (excluding JSX consequence)
373
622
  */
@@ -404,6 +653,12 @@ interface ChainInfo {
404
653
  chainExpression: string;
405
654
  currentPosition: number;
406
655
  compound: CompoundConditional;
656
+ /**
657
+ * When processing OR expressions within an && chain, this tracks the
658
+ * current OR group ID. Conditions added while this is set will be marked
659
+ * as OR alternatives (only one needs to be true).
660
+ */
661
+ currentOrGroupId?: string;
407
662
  }
408
663
 
409
664
  /**
@@ -460,6 +715,10 @@ function extractConditionalsFromJsx(
460
715
  if (ts.isJsxExpression(child) && child.expression) {
461
716
  const expr = unwrapExpression(child.expression);
462
717
 
718
+ // Extract JSX rendering usages (array.map, text interpolation)
719
+ // This handles direct usages like {items.map(...)} or {user.name}
720
+ extractJsxRenderingUsage(expr, context);
721
+
463
722
  // If the expression is an && chain, extract its conditional usages
464
723
  if (
465
724
  ts.isBinaryExpression(expr) &&
@@ -766,8 +1025,104 @@ function extractConditionalsFromJsx(
766
1025
  }
767
1026
  // Recursively process nested JSX elements - Fix 32: pass parent conditions
768
1027
  else if (ts.isJsxElement(child)) {
1028
+ // Check if this is a user-defined component (vs intrinsic element like div)
1029
+ const componentName = getComponentNameFromJsx(child);
1030
+ if (componentName) {
1031
+ if (parentConditions.length > 0) {
1032
+ // If there are parent conditions, record them as gating conditions
1033
+ console.log(
1034
+ `[ChildBoundary] ${componentName}: Conditionally rendered with ${parentConditions.length} gating conditions`,
1035
+ );
1036
+ for (const condition of parentConditions) {
1037
+ console.log(
1038
+ `[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`,
1039
+ );
1040
+ context.addChildBoundaryGatingCondition(componentName, {
1041
+ path: condition.path,
1042
+ conditionType: 'truthiness',
1043
+ location: 'ternary',
1044
+ sourceLocation: condition.sourceLocation,
1045
+ controlsJsxRendering: true,
1046
+ isNegated: condition.isNegated,
1047
+ });
1048
+ }
1049
+ } else {
1050
+ // No parent conditions - check if it has data props for unconditional tracking
1051
+ console.log(
1052
+ `[ChildBoundary] ${componentName}: Checking for unconditional rendering with data props...`,
1053
+ );
1054
+ const { hasDataProps, dataProps } = hasDataPropsFromParent(
1055
+ child,
1056
+ componentName,
1057
+ );
1058
+ if (hasDataProps) {
1059
+ // Fix: Track unconditionally-rendered children that receive data props
1060
+ // These need to be tracked for flow merging even without gating conditions
1061
+ // Example: <WorkoutsView workouts={workouts} /> - parent controls workouts data
1062
+ console.log(
1063
+ `[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered with data props: [${dataProps.join(', ')}]`,
1064
+ );
1065
+ context.addChildBoundaryGatingCondition(componentName, {
1066
+ path: '__unconditional__',
1067
+ conditionType: 'truthiness',
1068
+ location: 'unconditional',
1069
+ controlsJsxRendering: true,
1070
+ isNegated: false,
1071
+ });
1072
+ }
1073
+ }
1074
+ }
769
1075
  extractConditionalsFromJsx(child, context, parentConditions);
770
1076
  }
1077
+ // Handle self-closing JSX elements (e.g., <ScenarioViewer />)
1078
+ else if (ts.isJsxSelfClosingElement(child)) {
1079
+ // Check if this is a user-defined component (vs intrinsic element like div)
1080
+ const componentName = getComponentNameFromJsx(child);
1081
+ if (componentName) {
1082
+ if (parentConditions.length > 0) {
1083
+ // If there are parent conditions, record them as gating conditions
1084
+ console.log(
1085
+ `[ChildBoundary] ${componentName}: Conditionally rendered (self-closing) with ${parentConditions.length} gating conditions`,
1086
+ );
1087
+ for (const condition of parentConditions) {
1088
+ console.log(
1089
+ `[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`,
1090
+ );
1091
+ context.addChildBoundaryGatingCondition(componentName, {
1092
+ path: condition.path,
1093
+ conditionType: 'truthiness',
1094
+ location: 'ternary',
1095
+ sourceLocation: condition.sourceLocation,
1096
+ controlsJsxRendering: true,
1097
+ isNegated: condition.isNegated,
1098
+ });
1099
+ }
1100
+ } else {
1101
+ // No parent conditions - check if it has data props for unconditional tracking
1102
+ console.log(
1103
+ `[ChildBoundary] ${componentName}: Checking for unconditional rendering (self-closing) with data props...`,
1104
+ );
1105
+ const { hasDataProps, dataProps } = hasDataPropsFromParent(
1106
+ child,
1107
+ componentName,
1108
+ );
1109
+ if (hasDataProps) {
1110
+ // Fix: Track unconditionally-rendered children that receive data props
1111
+ console.log(
1112
+ `[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered (self-closing) with data props: [${dataProps.join(', ')}]`,
1113
+ );
1114
+ context.addChildBoundaryGatingCondition(componentName, {
1115
+ path: '__unconditional__',
1116
+ conditionType: 'truthiness',
1117
+ location: 'unconditional',
1118
+ controlsJsxRendering: true,
1119
+ isNegated: false,
1120
+ });
1121
+ }
1122
+ }
1123
+ }
1124
+ // Self-closing elements have no children, so no recursion needed
1125
+ }
771
1126
  // Recursively process nested JSX fragments - Fix 32: pass parent conditions
772
1127
  else if (ts.isJsxFragment(child)) {
773
1128
  extractConditionalsFromJsx(child, context, parentConditions);
@@ -870,14 +1225,37 @@ export function extractConditionalUsage(
870
1225
  }
871
1226
 
872
1227
  // Handle binary expressions with || (logical OR)
873
- // OR breaks the chain - each side is independent
1228
+ // When OR is inside an && chain, we need to continue chain tracking
1229
+ // and mark conditions as OR alternatives
874
1230
  if (
875
1231
  ts.isBinaryExpression(unwrapped) &&
876
1232
  unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken
877
1233
  ) {
878
- // Both sides of || are independent conditional checks (no chain tracking)
879
- extractWithChainTracking(unwrapped.left, null, false);
880
- extractWithChainTracking(unwrapped.right, null, false);
1234
+ if (chainInfo) {
1235
+ // We're inside an && chain - continue tracking but mark as OR alternatives
1236
+ // Generate an orGroupId so conditions from both sides can be grouped
1237
+ const orGroupId =
1238
+ chainInfo.currentOrGroupId ?? `or_${crypto.randomUUID().slice(0, 8)}`;
1239
+
1240
+ // Process left side with OR group tracking
1241
+ const leftChainInfo = {
1242
+ ...chainInfo,
1243
+ currentOrGroupId: orGroupId,
1244
+ };
1245
+ extractWithChainTracking(unwrapped.left, leftChainInfo, false);
1246
+
1247
+ // Process right side with same OR group
1248
+ // Note: we use leftChainInfo's currentPosition which may have been updated
1249
+ const rightChainInfo = {
1250
+ ...leftChainInfo,
1251
+ currentPosition: chainInfo.currentPosition,
1252
+ };
1253
+ extractWithChainTracking(unwrapped.right, rightChainInfo, false);
1254
+ } else {
1255
+ // Not inside a chain - OR breaks into independent conditional checks
1256
+ extractWithChainTracking(unwrapped.left, null, false);
1257
+ extractWithChainTracking(unwrapped.right, null, false);
1258
+ }
881
1259
  return;
882
1260
  }
883
1261
 
@@ -922,6 +1300,7 @@ export function extractConditionalUsage(
922
1300
  conditionType: 'comparison' | 'truthiness',
923
1301
  comparedValues?: string[],
924
1302
  requiredValue?: string | boolean,
1303
+ sourceExpr?: ts.Expression,
925
1304
  ) => {
926
1305
  const usage: ConditionalUsage = {
927
1306
  path,
@@ -933,6 +1312,17 @@ export function extractConditionalUsage(
933
1312
  controlsJsxRendering,
934
1313
  };
935
1314
 
1315
+ // Check for inline array-derived patterns (.length) on the source expression
1316
+ if (sourceExpr) {
1317
+ const arrayDerived = detectArrayDerivedPattern(sourceExpr);
1318
+ if (arrayDerived) {
1319
+ usage.derivedFrom = {
1320
+ operation: arrayDerived.operation,
1321
+ sourcePath: arrayDerived.sourcePath,
1322
+ };
1323
+ }
1324
+ }
1325
+
936
1326
  // Add chain info if part of a compound conditional
937
1327
  if (chainInfo) {
938
1328
  usage.chainId = chainInfo.chainId;
@@ -948,6 +1338,9 @@ export function extractConditionalUsage(
948
1338
  comparedValues,
949
1339
  isNegated,
950
1340
  requiredValue,
1341
+ ...(chainInfo.currentOrGroupId && {
1342
+ orGroupId: chainInfo.currentOrGroupId,
1343
+ }),
951
1344
  });
952
1345
  }
953
1346
 
@@ -962,6 +1355,7 @@ export function extractConditionalUsage(
962
1355
  'comparison',
963
1356
  literalValue !== undefined ? [literalValue] : undefined,
964
1357
  getRequiredValue(literalValue, isNegated),
1358
+ unwrapped.left, // Pass source expression for array derivation detection
965
1359
  );
966
1360
  return;
967
1361
  }
@@ -974,16 +1368,29 @@ export function extractConditionalUsage(
974
1368
  'comparison',
975
1369
  literalValue !== undefined ? [literalValue] : undefined,
976
1370
  getRequiredValue(literalValue, isNegated),
1371
+ unwrapped.right, // Pass source expression for array derivation detection
977
1372
  );
978
1373
  return;
979
1374
  }
980
1375
 
981
1376
  // Both sides are variables - record both as comparisons without specific values
982
1377
  if (leftPath) {
983
- addCondition(leftPath.toLeftHandSideString(), 'comparison');
1378
+ addCondition(
1379
+ leftPath.toLeftHandSideString(),
1380
+ 'comparison',
1381
+ undefined,
1382
+ undefined,
1383
+ unwrapped.left,
1384
+ );
984
1385
  }
985
1386
  if (rightPath) {
986
- addCondition(rightPath.toLeftHandSideString(), 'comparison');
1387
+ addCondition(
1388
+ rightPath.toLeftHandSideString(),
1389
+ 'comparison',
1390
+ undefined,
1391
+ undefined,
1392
+ unwrapped.right,
1393
+ );
987
1394
  }
988
1395
  return;
989
1396
  }
@@ -1012,6 +1419,16 @@ export function extractConditionalUsage(
1012
1419
  controlsJsxRendering,
1013
1420
  };
1014
1421
 
1422
+ // Check for inline array-derived patterns (.some(), .every(), .includes(), .length)
1423
+ // This populates derivedFrom so downstream code can resolve to the base array path
1424
+ const arrayDerived = detectArrayDerivedPattern(unwrapped);
1425
+ if (arrayDerived) {
1426
+ usage.derivedFrom = {
1427
+ operation: arrayDerived.operation,
1428
+ sourcePath: arrayDerived.sourcePath,
1429
+ };
1430
+ }
1431
+
1015
1432
  // Add chain info if part of a compound conditional
1016
1433
  if (chainInfo) {
1017
1434
  usage.chainId = chainInfo.chainId;
@@ -1027,6 +1444,9 @@ export function extractConditionalUsage(
1027
1444
  conditionType: 'truthiness',
1028
1445
  isNegated,
1029
1446
  requiredValue: !isNegated,
1447
+ ...(chainInfo.currentOrGroupId && {
1448
+ orGroupId: chainInfo.currentOrGroupId,
1449
+ }),
1030
1450
  });
1031
1451
  }
1032
1452
 
@@ -1196,7 +1616,7 @@ export function processExpression({
1196
1616
  const structure = context.getStructure();
1197
1617
 
1198
1618
  // Propagate existing equivalencies for sub-properties
1199
- for (const [key, value] of Object.entries(equivalentVariables)) {
1619
+ for (const [key, rawValue] of Object.entries(equivalentVariables)) {
1200
1620
  // Check if this equivalency is for a sub-property of the identifier
1201
1621
  // e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
1202
1622
  if (
@@ -1207,8 +1627,14 @@ export function processExpression({
1207
1627
  const newTargetPath = StructuredPath.fromBase(
1208
1628
  targetPath.toString() + subPath,
1209
1629
  );
1210
- const valuePath = StructuredPath.fromBase(value);
1211
- context.addEquivalence(newTargetPath, valuePath);
1630
+ // Handle both string and string[] values
1631
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
1632
+ for (const value of values) {
1633
+ if (typeof value === 'string') {
1634
+ const valuePath = StructuredPath.fromBase(value);
1635
+ context.addEquivalence(newTargetPath, valuePath);
1636
+ }
1637
+ }
1212
1638
  }
1213
1639
  }
1214
1640
 
@@ -1686,15 +2112,55 @@ export function processExpression({
1686
2112
  );
1687
2113
  }
1688
2114
  } else if (operatorKind === ts.SyntaxKind.BarBarToken) {
1689
- // For ||, also create an equivalence to the left side
2115
+ // For ||, create equivalences to BOTH sides
1690
2116
  // This enables data flow tracing through fallback expressions
2117
+ // e.g., `const item = items.find(...) || null` should trace to both:
2118
+ // - items[] (from the find result)
2119
+ // - null (from the fallback)
1691
2120
  if (targetPath) {
1692
- resultPath = StructuredPath.fromNode(
2121
+ // Get paths for both sides
2122
+ const leftPath = StructuredPath.fromNode(
1693
2123
  unwrappedNode.left,
1694
2124
  context.sourceFile,
1695
2125
  );
2126
+ const rightPath = StructuredPath.fromNode(
2127
+ unwrappedNode.right,
2128
+ context.sourceFile,
2129
+ );
2130
+
2131
+ // Collect all valid paths
2132
+ const allPaths: StructuredPath[] = [];
2133
+ if (leftPath) allPaths.push(leftPath);
2134
+ if (rightPath) allPaths.push(rightPath);
2135
+
2136
+ // Add multiple equivalencies to track both sources
2137
+ if (allPaths.length > 0) {
2138
+ context.addMultipleEquivalencies(targetPath, allPaths);
2139
+ }
2140
+
2141
+ // Process both sides to capture their internal structures
2142
+ processExpression({
2143
+ node: unwrappedNode.left,
2144
+ context,
2145
+ });
2146
+ processExpression({
2147
+ node: unwrappedNode.right,
2148
+ context,
2149
+ });
2150
+
2151
+ // Register the type for the target path
2152
+ const leftType = context.inferTypeFromNode(unwrappedNode.left);
2153
+ const rightType = context.inferTypeFromNode(unwrappedNode.right);
2154
+ const orResultType = isDefinedType(leftType)
2155
+ ? leftType
2156
+ : rightType || 'unknown';
2157
+ context.addType(targetPath, orResultType);
2158
+
2159
+ // Return early - we've already handled equivalencies with addMultipleEquivalencies
2160
+ // Don't fall through to the generic addEquivalence call below
2161
+ return true;
1696
2162
  }
1697
- // Note: Unlike ??, we don't set targetPath when there's no target
2163
+ // Note: When there's no targetPath, we don't recursively process
1698
2164
  // because || is often used in boolean contexts where the full expression matters
1699
2165
  }
1700
2166
  } else if (operatorKind === ts.SyntaxKind.InstanceOfKeyword) {
@@ -1802,24 +2268,56 @@ export function processExpression({
1802
2268
 
1803
2269
  // Get the source expression path (e.g., the object for obj.method())
1804
2270
  const sourceExpr = unwrappedNode.expression.expression;
1805
- const sourcePath = StructuredPath.fromNode(
1806
- sourceExpr,
1807
- context.sourceFile,
1808
- );
2271
+ const unwrappedSourceExpr = unwrapExpression(sourceExpr);
2272
+
2273
+ // When the source is a ternary expression like (cond ? arr : arr.slice()),
2274
+ // apply method semantics to BOTH branches directly. The ternary itself isn't
2275
+ // a variable - it's just a choice between two paths that both flow to the result.
2276
+ if (ts.isConditionalExpression(unwrappedSourceExpr)) {
2277
+ const branches = [
2278
+ unwrappedSourceExpr.whenTrue,
2279
+ unwrappedSourceExpr.whenFalse,
2280
+ ];
1809
2281
 
1810
- if (sourcePath) {
1811
- // For array-specific semantics (like push), verify the source is actually an array
1812
- // This prevents router.push() from being mistakenly treated as Array.push()
1813
- const isArraySemantics = semantics instanceof ArrayPushSemantics;
1814
- const shouldApply =
1815
- !isArraySemantics ||
1816
- isLikelyArrayType(sourceExpr, context.typeChecker);
2282
+ for (const branch of branches) {
2283
+ const branchPath = StructuredPath.fromNode(
2284
+ branch,
2285
+ context.sourceFile,
2286
+ );
2287
+ if (branchPath) {
2288
+ const isArraySemantics = semantics instanceof ArrayPushSemantics;
2289
+ const shouldApply =
2290
+ !isArraySemantics ||
2291
+ isLikelyArrayType(branch, context.typeChecker);
2292
+
2293
+ if (shouldApply) {
2294
+ semantics.addEquivalences(callPath, branchPath, context);
2295
+ returnType = semantics.getReturnType();
2296
+ handledBySemantics = true;
2297
+ }
2298
+ }
2299
+ }
2300
+ } else {
2301
+ // Regular (non-ternary) source expression
2302
+ const sourcePath = StructuredPath.fromNode(
2303
+ sourceExpr,
2304
+ context.sourceFile,
2305
+ );
1817
2306
 
1818
- if (shouldApply) {
1819
- // Apply method semantics
1820
- semantics.addEquivalences(callPath, sourcePath, context);
1821
- returnType = semantics.getReturnType();
1822
- handledBySemantics = true;
2307
+ if (sourcePath) {
2308
+ // For array-specific semantics (like push), verify the source is actually an array
2309
+ // This prevents router.push() from being mistakenly treated as Array.push()
2310
+ const isArraySemantics = semantics instanceof ArrayPushSemantics;
2311
+ const shouldApply =
2312
+ !isArraySemantics ||
2313
+ isLikelyArrayType(sourceExpr, context.typeChecker);
2314
+
2315
+ if (shouldApply) {
2316
+ // Apply method semantics
2317
+ semantics.addEquivalences(callPath, sourcePath, context);
2318
+ returnType = semantics.getReturnType();
2319
+ handledBySemantics = true;
2320
+ }
1823
2321
  }
1824
2322
  }
1825
2323
  }
@@ -2377,6 +2875,35 @@ export function processExpression({
2377
2875
 
2378
2876
  // Handle Arrow Functions: (p) => p.prop, (a, b) => { ... }
2379
2877
  if (ts.isArrowFunction(unwrappedNode)) {
2878
+ // If this arrow function is a child boundary (e.g., a .map() callback),
2879
+ // don't process its parameters here - they will be processed when the
2880
+ // child scope is analyzed separately. This prevents parameter variables
2881
+ // from leaking into the parent scope's equivalencies.
2882
+ // Check if this arrow function is a child boundary (i.e., should be processed
2883
+ // as a separate child scope, not here in the parent scope).
2884
+ //
2885
+ // We use two checks because childBoundary positions can be unreliable:
2886
+ // 1. Position-based check (standard isChildBoundary)
2887
+ // 2. Text-based check: if the arrow function text doesn't appear in the
2888
+ // statement text, it was replaced with a cyScope placeholder
2889
+ const isChildBoundary = context.isChildBoundary(unwrappedNode);
2890
+
2891
+ // Text-based child scope detection for when positions are unreliable
2892
+ const arrowFnText = unwrappedNode.getText(context.sourceFile);
2893
+ const firstLine = arrowFnText.split('\n')[0].trim();
2894
+ const searchText = firstLine.substring(0, Math.min(20, firstLine.length));
2895
+ const isInStatementText = context.statementInfo.text.includes(searchText);
2896
+ const isChildScope = !isInStatementText && arrowFnText.length > 10;
2897
+
2898
+ if (isChildBoundary || isChildScope) {
2899
+ // The method semantics (e.g., ArrayMapSemantics) have already established
2900
+ // the necessary equivalences between the child scope placeholder and array elements
2901
+ if (targetPath) {
2902
+ context.addType(targetPath, 'function');
2903
+ }
2904
+ return true;
2905
+ }
2906
+
2380
2907
  // Create a path for the function
2381
2908
  const functionPath = StructuredPath.empty();
2382
2909