@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
@@ -6,6 +6,85 @@ import { methodRegistry, ArrayPushSemantics } from "./methodSemantics.js";
6
6
  import { isArithmeticOperator, isAssignmentOperator, isBitwiseCompoundOperator, isComparisonOperator, isDefinedType, isNumericCompoundOperator, leftOrRightType, unwrapExpression, } from "./sharedPatterns.js";
7
7
  import { processBindingPattern } from "./processBindings.js";
8
8
  import { extractConditionalEffectsFromTernary, findUseStateSetters, } from "./conditionalEffectsExtractor.js";
9
+ import { detectArrayDerivedPattern } from "./arrayDerivationDetector.js";
10
+ /**
11
+ * Checks if a JSX element has props that reference variables from the parent scope.
12
+ * This is used to detect unconditionally-rendered children that should have their
13
+ * execution flows merged into the parent.
14
+ *
15
+ * We want to track children where the parent controls data that affects the child's
16
+ * conditional rendering. Static props (like title="Dashboard") don't need tracking
17
+ * because they don't create variable execution flows.
18
+ *
19
+ * Examples:
20
+ * - <WorkoutsView workouts={workouts} /> → true (workouts is a variable)
21
+ * - <ItemList items={items} count={count} /> → true (items, count are variables)
22
+ * - <Header title="Dashboard" /> → false (static string)
23
+ * - <Footer /> → false (no props)
24
+ * - <Button onClick={handleClick} /> → false (only callback, no data props)
25
+ *
26
+ * @returns true if the component has at least one prop that references a variable
27
+ * (excluding callbacks which typically start with 'on' or 'handle')
28
+ */
29
+ function hasDataPropsFromParent(node, componentName) {
30
+ const attributes = ts.isJsxElement(node)
31
+ ? node.openingElement.attributes.properties
32
+ : node.attributes.properties;
33
+ const dataProps = [];
34
+ for (const attr of attributes) {
35
+ // Spread attributes always reference parent data: {...props}
36
+ if (ts.isJsxSpreadAttribute(attr)) {
37
+ const spreadText = attr.expression?.getText() || '...spread';
38
+ dataProps.push(`{...${spreadText}}`);
39
+ console.log(`[UnconditionalChild] ${componentName}: Found spread attribute {${spreadText}}`);
40
+ continue;
41
+ }
42
+ if (ts.isJsxAttribute(attr)) {
43
+ const propName = attr.name.getText();
44
+ // Skip callback props - they don't create data-driven execution flows
45
+ // Callbacks typically start with 'on' (onClick, onChange) or 'handle' (handleSubmit)
46
+ if (propName.startsWith('on') ||
47
+ propName.startsWith('handle') ||
48
+ propName === 'ref') {
49
+ console.log(`[UnconditionalChild] ${componentName}: Skipping callback prop '${propName}'`);
50
+ continue;
51
+ }
52
+ // Check if the prop value is a JSX expression (references a variable)
53
+ // vs a string literal which is static
54
+ if (attr.initializer) {
55
+ if (ts.isJsxExpression(attr.initializer)) {
56
+ // JSX expression like prop={value} - this references a variable
57
+ // Could be a simple identifier, property access, or more complex expression
58
+ const expression = attr.initializer.expression;
59
+ if (expression) {
60
+ // Skip if it's just a function/arrow function (callback)
61
+ if (ts.isArrowFunction(expression) ||
62
+ ts.isFunctionExpression(expression)) {
63
+ console.log(`[UnconditionalChild] ${componentName}: Skipping inline callback prop '${propName}'`);
64
+ continue;
65
+ }
66
+ // This is a data prop that references parent state/props
67
+ const exprText = expression.getText();
68
+ dataProps.push(`${propName}={${exprText}}`);
69
+ console.log(`[UnconditionalChild] ${componentName}: Found data prop '${propName}' = {${exprText}}`);
70
+ }
71
+ }
72
+ else {
73
+ // String literals like prop="value" are static
74
+ console.log(`[UnconditionalChild] ${componentName}: Skipping static prop '${propName}'`);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ const hasDataProps = dataProps.length > 0;
80
+ if (hasDataProps) {
81
+ console.log(`[UnconditionalChild] ${componentName}: Has ${dataProps.length} data props: [${dataProps.join(', ')}]`);
82
+ }
83
+ else {
84
+ console.log(`[UnconditionalChild] ${componentName}: No data props found, will NOT track`);
85
+ }
86
+ return { hasDataProps, dataProps };
87
+ }
9
88
  /**
10
89
  * Extracts the component name from a JSX element.
11
90
  * Returns null for intrinsic elements (div, span, etc.) since we only care about
@@ -273,6 +352,123 @@ function getSourceLocation(node, sourceFile) {
273
352
  : codeSnippet,
274
353
  };
275
354
  }
355
+ /**
356
+ * Extracts the root array path from an expression that ends with .map().
357
+ * Handles chained methods like .filter().map(), .slice().map(), etc.
358
+ *
359
+ * Examples:
360
+ * - items.map(...) → "items"
361
+ * - data.users.map(...) → "data.users"
362
+ * - items.filter(...).map(...) → "items"
363
+ * - items.slice(0, 5).map(...) → "items"
364
+ */
365
+ function extractArrayPathFromMapCall(expr, sourceFile) {
366
+ // Walk up the chain to find the root array
367
+ let current = expr.expression;
368
+ while (ts.isPropertyAccessExpression(current)) {
369
+ const methodName = current.name.getText(sourceFile);
370
+ // Common array methods that return arrays (so we keep going up)
371
+ const arrayReturningMethods = [
372
+ 'map',
373
+ 'filter',
374
+ 'slice',
375
+ 'concat',
376
+ 'flat',
377
+ 'flatMap',
378
+ 'reverse',
379
+ 'sort',
380
+ 'toReversed',
381
+ 'toSorted',
382
+ 'toSpliced',
383
+ ];
384
+ if (arrayReturningMethods.includes(methodName)) {
385
+ const objectExpr = current.expression;
386
+ // If the object is a call expression (chained method), keep going
387
+ if (ts.isCallExpression(objectExpr)) {
388
+ current = objectExpr.expression;
389
+ }
390
+ else {
391
+ // Found the root - it's an identifier or property access
392
+ const path = StructuredPath.fromNode(objectExpr, sourceFile);
393
+ return path ? path.toString() : null;
394
+ }
395
+ }
396
+ else {
397
+ // Not an array method we recognize
398
+ break;
399
+ }
400
+ }
401
+ return null;
402
+ }
403
+ /**
404
+ * Extracts JSX rendering usages from a JSX expression.
405
+ * Detects:
406
+ * - array.map() calls → 'array-map' type
407
+ * - string interpolations (identifiers/property access) → 'text-interpolation' type
408
+ *
409
+ * Recursively searches inside && chains and ternary expressions.
410
+ *
411
+ * @param expr The expression inside {expr}
412
+ * @param context The analysis context
413
+ */
414
+ function extractJsxRenderingUsage(expr, context) {
415
+ const unwrapped = unwrapExpression(expr);
416
+ const sourceLocation = getSourceLocation(expr, context.sourceFile);
417
+ // Detect array.map() calls
418
+ if (ts.isCallExpression(unwrapped)) {
419
+ const calleeExpr = unwrapped.expression;
420
+ if (ts.isPropertyAccessExpression(calleeExpr)) {
421
+ const methodName = calleeExpr.name.getText(context.sourceFile);
422
+ if (methodName === 'map') {
423
+ const arrayPath = extractArrayPathFromMapCall(unwrapped, context.sourceFile);
424
+ if (arrayPath) {
425
+ context.addJsxRenderingUsage({
426
+ path: arrayPath,
427
+ renderingType: 'array-map',
428
+ valueType: 'array',
429
+ sourceLocation,
430
+ });
431
+ }
432
+ }
433
+ }
434
+ }
435
+ // Detect simple string interpolations: {title} or {user.name}
436
+ else if (ts.isIdentifier(unwrapped) ||
437
+ ts.isPropertyAccessExpression(unwrapped)) {
438
+ const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
439
+ if (path) {
440
+ const pathStr = path.toString();
441
+ const typeInfo = context.getTypeInfo(path);
442
+ // Only track as text interpolation if it's a string type
443
+ // Check for 'string' type, or types that contain 'string' (but not 'string[]')
444
+ if (typeInfo === 'string' ||
445
+ (typeInfo &&
446
+ typeInfo.includes('string') &&
447
+ !typeInfo.includes('string[]'))) {
448
+ context.addJsxRenderingUsage({
449
+ path: pathStr,
450
+ renderingType: 'text-interpolation',
451
+ valueType: 'string',
452
+ sourceLocation,
453
+ });
454
+ }
455
+ }
456
+ }
457
+ // Recursively search inside && chains: {showList && items.map(...)}
458
+ else if (ts.isBinaryExpression(unwrapped) &&
459
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
460
+ // Check the right side of the && chain (where .map() typically appears)
461
+ const rightSide = unwrapExpression(unwrapped.right);
462
+ extractJsxRenderingUsage(rightSide, context);
463
+ // Also check nested && chains on the left
464
+ extractJsxRenderingUsage(unwrapped.left, context);
465
+ }
466
+ // Recursively search inside ternaries: {isEmpty ? null : items.map(...)}
467
+ else if (ts.isConditionalExpression(unwrapped)) {
468
+ extractJsxRenderingUsage(unwrapped.whenTrue, context);
469
+ extractJsxRenderingUsage(unwrapped.whenFalse, context);
470
+ }
471
+ }
276
472
  /**
277
473
  * Counts the number of conditions in an && chain (excluding JSX consequence)
278
474
  */
@@ -330,6 +526,9 @@ function extractConditionalsFromJsx(node, context, parentConditions = []) {
330
526
  // Process JSX expressions: {expr}
331
527
  if (ts.isJsxExpression(child) && child.expression) {
332
528
  const expr = unwrapExpression(child.expression);
529
+ // Extract JSX rendering usages (array.map, text interpolation)
530
+ // This handles direct usages like {items.map(...)} or {user.name}
531
+ extractJsxRenderingUsage(expr, context);
333
532
  // If the expression is an && chain, extract its conditional usages
334
533
  if (ts.isBinaryExpression(expr) &&
335
534
  expr.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
@@ -568,8 +767,84 @@ function extractConditionalsFromJsx(node, context, parentConditions = []) {
568
767
  }
569
768
  // Recursively process nested JSX elements - Fix 32: pass parent conditions
570
769
  else if (ts.isJsxElement(child)) {
770
+ // Check if this is a user-defined component (vs intrinsic element like div)
771
+ const componentName = getComponentNameFromJsx(child);
772
+ if (componentName) {
773
+ if (parentConditions.length > 0) {
774
+ // If there are parent conditions, record them as gating conditions
775
+ console.log(`[ChildBoundary] ${componentName}: Conditionally rendered with ${parentConditions.length} gating conditions`);
776
+ for (const condition of parentConditions) {
777
+ console.log(`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`);
778
+ context.addChildBoundaryGatingCondition(componentName, {
779
+ path: condition.path,
780
+ conditionType: 'truthiness',
781
+ location: 'ternary',
782
+ sourceLocation: condition.sourceLocation,
783
+ controlsJsxRendering: true,
784
+ isNegated: condition.isNegated,
785
+ });
786
+ }
787
+ }
788
+ else {
789
+ // No parent conditions - check if it has data props for unconditional tracking
790
+ console.log(`[ChildBoundary] ${componentName}: Checking for unconditional rendering with data props...`);
791
+ const { hasDataProps, dataProps } = hasDataPropsFromParent(child, componentName);
792
+ if (hasDataProps) {
793
+ // Fix: Track unconditionally-rendered children that receive data props
794
+ // These need to be tracked for flow merging even without gating conditions
795
+ // Example: <WorkoutsView workouts={workouts} /> - parent controls workouts data
796
+ console.log(`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered with data props: [${dataProps.join(', ')}]`);
797
+ context.addChildBoundaryGatingCondition(componentName, {
798
+ path: '__unconditional__',
799
+ conditionType: 'truthiness',
800
+ location: 'unconditional',
801
+ controlsJsxRendering: true,
802
+ isNegated: false,
803
+ });
804
+ }
805
+ }
806
+ }
571
807
  extractConditionalsFromJsx(child, context, parentConditions);
572
808
  }
809
+ // Handle self-closing JSX elements (e.g., <ScenarioViewer />)
810
+ else if (ts.isJsxSelfClosingElement(child)) {
811
+ // Check if this is a user-defined component (vs intrinsic element like div)
812
+ const componentName = getComponentNameFromJsx(child);
813
+ if (componentName) {
814
+ if (parentConditions.length > 0) {
815
+ // If there are parent conditions, record them as gating conditions
816
+ console.log(`[ChildBoundary] ${componentName}: Conditionally rendered (self-closing) with ${parentConditions.length} gating conditions`);
817
+ for (const condition of parentConditions) {
818
+ console.log(`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`);
819
+ context.addChildBoundaryGatingCondition(componentName, {
820
+ path: condition.path,
821
+ conditionType: 'truthiness',
822
+ location: 'ternary',
823
+ sourceLocation: condition.sourceLocation,
824
+ controlsJsxRendering: true,
825
+ isNegated: condition.isNegated,
826
+ });
827
+ }
828
+ }
829
+ else {
830
+ // No parent conditions - check if it has data props for unconditional tracking
831
+ console.log(`[ChildBoundary] ${componentName}: Checking for unconditional rendering (self-closing) with data props...`);
832
+ const { hasDataProps, dataProps } = hasDataPropsFromParent(child, componentName);
833
+ if (hasDataProps) {
834
+ // Fix: Track unconditionally-rendered children that receive data props
835
+ console.log(`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered (self-closing) with data props: [${dataProps.join(', ')}]`);
836
+ context.addChildBoundaryGatingCondition(componentName, {
837
+ path: '__unconditional__',
838
+ conditionType: 'truthiness',
839
+ location: 'unconditional',
840
+ controlsJsxRendering: true,
841
+ isNegated: false,
842
+ });
843
+ }
844
+ }
845
+ }
846
+ // Self-closing elements have no children, so no recursion needed
847
+ }
573
848
  // Recursively process nested JSX fragments - Fix 32: pass parent conditions
574
849
  else if (ts.isJsxFragment(child)) {
575
850
  extractConditionalsFromJsx(child, context, parentConditions);
@@ -640,12 +915,33 @@ export function extractConditionalUsage(condition, context, location, options =
640
915
  return;
641
916
  }
642
917
  // Handle binary expressions with || (logical OR)
643
- // OR breaks the chain - each side is independent
918
+ // When OR is inside an && chain, we need to continue chain tracking
919
+ // and mark conditions as OR alternatives
644
920
  if (ts.isBinaryExpression(unwrapped) &&
645
921
  unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
646
- // Both sides of || are independent conditional checks (no chain tracking)
647
- extractWithChainTracking(unwrapped.left, null, false);
648
- extractWithChainTracking(unwrapped.right, null, false);
922
+ if (chainInfo) {
923
+ // We're inside an && chain - continue tracking but mark as OR alternatives
924
+ // Generate an orGroupId so conditions from both sides can be grouped
925
+ const orGroupId = chainInfo.currentOrGroupId ?? `or_${crypto.randomUUID().slice(0, 8)}`;
926
+ // Process left side with OR group tracking
927
+ const leftChainInfo = {
928
+ ...chainInfo,
929
+ currentOrGroupId: orGroupId,
930
+ };
931
+ extractWithChainTracking(unwrapped.left, leftChainInfo, false);
932
+ // Process right side with same OR group
933
+ // Note: we use leftChainInfo's currentPosition which may have been updated
934
+ const rightChainInfo = {
935
+ ...leftChainInfo,
936
+ currentPosition: chainInfo.currentPosition,
937
+ };
938
+ extractWithChainTracking(unwrapped.right, rightChainInfo, false);
939
+ }
940
+ else {
941
+ // Not inside a chain - OR breaks into independent conditional checks
942
+ extractWithChainTracking(unwrapped.left, null, false);
943
+ extractWithChainTracking(unwrapped.right, null, false);
944
+ }
649
945
  return;
650
946
  }
651
947
  // Handle comparison operators (===, !==, <, >, <=, >=)
@@ -671,7 +967,7 @@ export function extractConditionalUsage(condition, context, location, options =
671
967
  return literalValue;
672
968
  };
673
969
  // Helper to add a condition
674
- const addCondition = (path, conditionType, comparedValues, requiredValue) => {
970
+ const addCondition = (path, conditionType, comparedValues, requiredValue, sourceExpr) => {
675
971
  const usage = {
676
972
  path,
677
973
  conditionType,
@@ -681,6 +977,16 @@ export function extractConditionalUsage(condition, context, location, options =
681
977
  isNegated,
682
978
  controlsJsxRendering,
683
979
  };
980
+ // Check for inline array-derived patterns (.length) on the source expression
981
+ if (sourceExpr) {
982
+ const arrayDerived = detectArrayDerivedPattern(sourceExpr);
983
+ if (arrayDerived) {
984
+ usage.derivedFrom = {
985
+ operation: arrayDerived.operation,
986
+ sourcePath: arrayDerived.sourcePath,
987
+ };
988
+ }
989
+ }
684
990
  // Add chain info if part of a compound conditional
685
991
  if (chainInfo) {
686
992
  usage.chainId = chainInfo.chainId;
@@ -695,6 +1001,9 @@ export function extractConditionalUsage(condition, context, location, options =
695
1001
  comparedValues,
696
1002
  isNegated,
697
1003
  requiredValue,
1004
+ ...(chainInfo.currentOrGroupId && {
1005
+ orGroupId: chainInfo.currentOrGroupId,
1006
+ }),
698
1007
  });
699
1008
  }
700
1009
  context.addConditionalUsage(usage);
@@ -702,21 +1011,21 @@ export function extractConditionalUsage(condition, context, location, options =
702
1011
  // Check if left is a variable and right is a literal
703
1012
  if (leftPath && isLiteralExpression(unwrapped.right)) {
704
1013
  const literalValue = getLiteralValue(unwrapped.right, context);
705
- addCondition(leftPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated));
1014
+ addCondition(leftPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.left);
706
1015
  return;
707
1016
  }
708
1017
  // Check if right is a variable and left is a literal
709
1018
  if (rightPath && isLiteralExpression(unwrapped.left)) {
710
1019
  const literalValue = getLiteralValue(unwrapped.left, context);
711
- addCondition(rightPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated));
1020
+ addCondition(rightPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.right);
712
1021
  return;
713
1022
  }
714
1023
  // Both sides are variables - record both as comparisons without specific values
715
1024
  if (leftPath) {
716
- addCondition(leftPath.toLeftHandSideString(), 'comparison');
1025
+ addCondition(leftPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.left);
717
1026
  }
718
1027
  if (rightPath) {
719
- addCondition(rightPath.toLeftHandSideString(), 'comparison');
1028
+ addCondition(rightPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.right);
720
1029
  }
721
1030
  return;
722
1031
  }
@@ -740,6 +1049,15 @@ export function extractConditionalUsage(condition, context, location, options =
740
1049
  isNegated,
741
1050
  controlsJsxRendering,
742
1051
  };
1052
+ // Check for inline array-derived patterns (.some(), .every(), .includes(), .length)
1053
+ // This populates derivedFrom so downstream code can resolve to the base array path
1054
+ const arrayDerived = detectArrayDerivedPattern(unwrapped);
1055
+ if (arrayDerived) {
1056
+ usage.derivedFrom = {
1057
+ operation: arrayDerived.operation,
1058
+ sourcePath: arrayDerived.sourcePath,
1059
+ };
1060
+ }
743
1061
  // Add chain info if part of a compound conditional
744
1062
  if (chainInfo) {
745
1063
  usage.chainId = chainInfo.chainId;
@@ -754,6 +1072,9 @@ export function extractConditionalUsage(condition, context, location, options =
754
1072
  conditionType: 'truthiness',
755
1073
  isNegated,
756
1074
  requiredValue: !isNegated,
1075
+ ...(chainInfo.currentOrGroupId && {
1076
+ orGroupId: chainInfo.currentOrGroupId,
1077
+ }),
757
1078
  });
758
1079
  }
759
1080
  context.addConditionalUsage(usage);
@@ -885,15 +1206,21 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
885
1206
  const equivalentVariables = context.getEquivalentVariables();
886
1207
  const structure = context.getStructure();
887
1208
  // Propagate existing equivalencies for sub-properties
888
- for (const [key, value] of Object.entries(equivalentVariables)) {
1209
+ for (const [key, rawValue] of Object.entries(equivalentVariables)) {
889
1210
  // Check if this equivalency is for a sub-property of the identifier
890
1211
  // e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
891
1212
  if (key.startsWith(nodePathStr + '.') ||
892
1213
  key.startsWith(nodePathStr + '[')) {
893
1214
  const subPath = key.substring(nodePathStr.length);
894
1215
  const newTargetPath = StructuredPath.fromBase(targetPath.toString() + subPath);
895
- const valuePath = StructuredPath.fromBase(value);
896
- context.addEquivalence(newTargetPath, valuePath);
1216
+ // Handle both string and string[] values
1217
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
1218
+ for (const value of values) {
1219
+ if (typeof value === 'string') {
1220
+ const valuePath = StructuredPath.fromBase(value);
1221
+ context.addEquivalence(newTargetPath, valuePath);
1222
+ }
1223
+ }
897
1224
  }
898
1225
  }
899
1226
  // Propagate existing structure entries for sub-properties
@@ -1229,12 +1556,46 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
1229
1556
  }
1230
1557
  }
1231
1558
  else if (operatorKind === ts.SyntaxKind.BarBarToken) {
1232
- // For ||, also create an equivalence to the left side
1559
+ // For ||, create equivalences to BOTH sides
1233
1560
  // This enables data flow tracing through fallback expressions
1561
+ // e.g., `const item = items.find(...) || null` should trace to both:
1562
+ // - items[] (from the find result)
1563
+ // - null (from the fallback)
1234
1564
  if (targetPath) {
1235
- resultPath = StructuredPath.fromNode(unwrappedNode.left, context.sourceFile);
1565
+ // Get paths for both sides
1566
+ const leftPath = StructuredPath.fromNode(unwrappedNode.left, context.sourceFile);
1567
+ const rightPath = StructuredPath.fromNode(unwrappedNode.right, context.sourceFile);
1568
+ // Collect all valid paths
1569
+ const allPaths = [];
1570
+ if (leftPath)
1571
+ allPaths.push(leftPath);
1572
+ if (rightPath)
1573
+ allPaths.push(rightPath);
1574
+ // Add multiple equivalencies to track both sources
1575
+ if (allPaths.length > 0) {
1576
+ context.addMultipleEquivalencies(targetPath, allPaths);
1577
+ }
1578
+ // Process both sides to capture their internal structures
1579
+ processExpression({
1580
+ node: unwrappedNode.left,
1581
+ context,
1582
+ });
1583
+ processExpression({
1584
+ node: unwrappedNode.right,
1585
+ context,
1586
+ });
1587
+ // Register the type for the target path
1588
+ const leftType = context.inferTypeFromNode(unwrappedNode.left);
1589
+ const rightType = context.inferTypeFromNode(unwrappedNode.right);
1590
+ const orResultType = isDefinedType(leftType)
1591
+ ? leftType
1592
+ : rightType || 'unknown';
1593
+ context.addType(targetPath, orResultType);
1594
+ // Return early - we've already handled equivalencies with addMultipleEquivalencies
1595
+ // Don't fall through to the generic addEquivalence call below
1596
+ return true;
1236
1597
  }
1237
- // Note: Unlike ??, we don't set targetPath when there's no target
1598
+ // Note: When there's no targetPath, we don't recursively process
1238
1599
  // because || is often used in boolean contexts where the full expression matters
1239
1600
  }
1240
1601
  }
@@ -1312,18 +1673,44 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
1312
1673
  const semantics = semanticsList[0];
1313
1674
  // Get the source expression path (e.g., the object for obj.method())
1314
1675
  const sourceExpr = unwrappedNode.expression.expression;
1315
- const sourcePath = StructuredPath.fromNode(sourceExpr, context.sourceFile);
1316
- if (sourcePath) {
1317
- // For array-specific semantics (like push), verify the source is actually an array
1318
- // This prevents router.push() from being mistakenly treated as Array.push()
1319
- const isArraySemantics = semantics instanceof ArrayPushSemantics;
1320
- const shouldApply = !isArraySemantics ||
1321
- isLikelyArrayType(sourceExpr, context.typeChecker);
1322
- if (shouldApply) {
1323
- // Apply method semantics
1324
- semantics.addEquivalences(callPath, sourcePath, context);
1325
- returnType = semantics.getReturnType();
1326
- handledBySemantics = true;
1676
+ const unwrappedSourceExpr = unwrapExpression(sourceExpr);
1677
+ // When the source is a ternary expression like (cond ? arr : arr.slice()),
1678
+ // apply method semantics to BOTH branches directly. The ternary itself isn't
1679
+ // a variable - it's just a choice between two paths that both flow to the result.
1680
+ if (ts.isConditionalExpression(unwrappedSourceExpr)) {
1681
+ const branches = [
1682
+ unwrappedSourceExpr.whenTrue,
1683
+ unwrappedSourceExpr.whenFalse,
1684
+ ];
1685
+ for (const branch of branches) {
1686
+ const branchPath = StructuredPath.fromNode(branch, context.sourceFile);
1687
+ if (branchPath) {
1688
+ const isArraySemantics = semantics instanceof ArrayPushSemantics;
1689
+ const shouldApply = !isArraySemantics ||
1690
+ isLikelyArrayType(branch, context.typeChecker);
1691
+ if (shouldApply) {
1692
+ semantics.addEquivalences(callPath, branchPath, context);
1693
+ returnType = semantics.getReturnType();
1694
+ handledBySemantics = true;
1695
+ }
1696
+ }
1697
+ }
1698
+ }
1699
+ else {
1700
+ // Regular (non-ternary) source expression
1701
+ const sourcePath = StructuredPath.fromNode(sourceExpr, context.sourceFile);
1702
+ if (sourcePath) {
1703
+ // For array-specific semantics (like push), verify the source is actually an array
1704
+ // This prevents router.push() from being mistakenly treated as Array.push()
1705
+ const isArraySemantics = semantics instanceof ArrayPushSemantics;
1706
+ const shouldApply = !isArraySemantics ||
1707
+ isLikelyArrayType(sourceExpr, context.typeChecker);
1708
+ if (shouldApply) {
1709
+ // Apply method semantics
1710
+ semantics.addEquivalences(callPath, sourcePath, context);
1711
+ returnType = semantics.getReturnType();
1712
+ handledBySemantics = true;
1713
+ }
1327
1714
  }
1328
1715
  }
1329
1716
  }
@@ -1752,6 +2139,32 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
1752
2139
  }
1753
2140
  // Handle Arrow Functions: (p) => p.prop, (a, b) => { ... }
1754
2141
  if (ts.isArrowFunction(unwrappedNode)) {
2142
+ // If this arrow function is a child boundary (e.g., a .map() callback),
2143
+ // don't process its parameters here - they will be processed when the
2144
+ // child scope is analyzed separately. This prevents parameter variables
2145
+ // from leaking into the parent scope's equivalencies.
2146
+ // Check if this arrow function is a child boundary (i.e., should be processed
2147
+ // as a separate child scope, not here in the parent scope).
2148
+ //
2149
+ // We use two checks because childBoundary positions can be unreliable:
2150
+ // 1. Position-based check (standard isChildBoundary)
2151
+ // 2. Text-based check: if the arrow function text doesn't appear in the
2152
+ // statement text, it was replaced with a cyScope placeholder
2153
+ const isChildBoundary = context.isChildBoundary(unwrappedNode);
2154
+ // Text-based child scope detection for when positions are unreliable
2155
+ const arrowFnText = unwrappedNode.getText(context.sourceFile);
2156
+ const firstLine = arrowFnText.split('\n')[0].trim();
2157
+ const searchText = firstLine.substring(0, Math.min(20, firstLine.length));
2158
+ const isInStatementText = context.statementInfo.text.includes(searchText);
2159
+ const isChildScope = !isInStatementText && arrowFnText.length > 10;
2160
+ if (isChildBoundary || isChildScope) {
2161
+ // The method semantics (e.g., ArrayMapSemantics) have already established
2162
+ // the necessary equivalences between the child scope placeholder and array elements
2163
+ if (targetPath) {
2164
+ context.addType(targetPath, 'function');
2165
+ }
2166
+ return true;
2167
+ }
1755
2168
  // Create a path for the function
1756
2169
  const functionPath = StructuredPath.empty();
1757
2170
  // Process parameters