@codeyam/codeyam-cli 0.1.0-staging.596f0eb → 0.1.0-staging.6e699e5

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 (696) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/common/execAsync.ts +1 -1
  3. package/analyzer-template/log.txt +3 -3
  4. package/analyzer-template/package.json +10 -6
  5. package/analyzer-template/packages/ai/index.ts +10 -3
  6. package/analyzer-template/packages/ai/package.json +1 -1
  7. package/analyzer-template/packages/ai/src/lib/__mocks__/completionCall.ts +122 -0
  8. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +128 -6
  9. package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
  10. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +138 -1
  11. package/analyzer-template/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.ts +644 -0
  12. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +140 -6
  13. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.ts +18 -0
  14. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.ts +38 -1
  15. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +181 -1
  16. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +1239 -104
  17. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +304 -0
  18. package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +29 -10
  19. package/analyzer-template/packages/ai/src/lib/completionCall.ts +216 -36
  20. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +1501 -138
  21. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +2 -1
  22. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +976 -0
  23. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +243 -77
  24. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +19 -1
  25. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +103 -6
  26. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +23 -0
  27. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.ts +98 -0
  28. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +42 -2
  29. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
  30. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +156 -0
  31. package/analyzer-template/packages/ai/src/lib/deepEqual.ts +30 -0
  32. package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
  33. package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
  34. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +74 -7
  35. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +89 -112
  36. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +6 -0
  37. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +1111 -91
  38. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +207 -104
  39. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +570 -0
  40. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +528 -0
  41. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1977 -0
  42. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
  43. package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +143 -31
  44. package/analyzer-template/packages/ai/src/lib/guessScenarioDataFromDescription.ts +8 -2
  45. package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +276 -3
  46. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +33 -3
  47. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +7 -0
  48. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +1 -1
  49. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +32 -102
  50. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
  51. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
  52. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +90 -6
  53. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +14 -53
  54. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.ts +58 -0
  55. package/analyzer-template/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.ts +28 -2
  56. package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
  57. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +812 -0
  58. package/analyzer-template/packages/ai/src/lib/splitOutsideParentheses.ts +5 -1
  59. package/analyzer-template/packages/ai/src/lib/validateExecutionFlowPaths.ts +531 -0
  60. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +123 -0
  61. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +8 -1
  62. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +14 -0
  63. package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
  64. package/analyzer-template/packages/analyze/src/lib/asts/nodes/index.ts +1 -0
  65. package/analyzer-template/packages/analyze/src/lib/asts/nodes/isAsyncFunction.ts +67 -0
  66. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +455 -267
  67. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +18 -0
  68. package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +3 -0
  69. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -7
  70. package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +31 -15
  71. package/analyzer-template/packages/analyze/src/lib/files/analyzeEntity.ts +11 -7
  72. package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +11 -12
  73. package/analyzer-template/packages/analyze/src/lib/files/enums/steps.ts +1 -1
  74. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +265 -0
  75. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.ts +102 -0
  76. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +588 -52
  77. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.ts +1 -1
  78. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.ts +28 -62
  79. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +336 -133
  80. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +156 -0
  81. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +78 -83
  82. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +4 -8
  83. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +461 -94
  84. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
  85. package/analyzer-template/packages/aws/codebuild/index.ts +1 -0
  86. package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts +11 -1
  87. package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts.map +1 -1
  88. package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js +29 -18
  89. package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js.map +1 -1
  90. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts +2 -2
  91. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts.map +1 -1
  92. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js +2 -2
  93. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js.map +1 -1
  94. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts +8 -18
  95. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts.map +1 -1
  96. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js +17 -61
  97. package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js.map +1 -1
  98. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts +15 -0
  99. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts.map +1 -0
  100. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js +31 -0
  101. package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js.map +1 -0
  102. package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.d.ts.map +1 -1
  103. package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js +8 -1
  104. package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js.map +1 -1
  105. package/analyzer-template/packages/aws/package.json +3 -3
  106. package/analyzer-template/packages/aws/s3/index.ts +1 -0
  107. package/analyzer-template/packages/aws/src/lib/codebuild/waitForBuild.ts +43 -19
  108. package/analyzer-template/packages/aws/src/lib/ecs/ecsDefineContainer.ts +3 -3
  109. package/analyzer-template/packages/aws/src/lib/ecs/ecsTaskFactory.ts +17 -69
  110. package/analyzer-template/packages/aws/src/lib/s3/checkS3ObjectExists.ts +47 -0
  111. package/analyzer-template/packages/aws/src/lib/s3/uploadFileToS3.ts +8 -1
  112. package/analyzer-template/packages/database/src/lib/kysely/db.ts +4 -4
  113. package/analyzer-template/packages/database/src/lib/kysely/tableRelations.ts +2 -2
  114. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +36 -9
  115. package/analyzer-template/packages/database/src/lib/loadReadyToBeCapturedAnalyses.ts +7 -3
  116. package/analyzer-template/packages/generate/index.ts +3 -0
  117. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +17 -1
  118. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.ts +193 -0
  119. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.ts +73 -0
  120. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +9 -4
  121. package/analyzer-template/packages/generate/src/lib/deepMerge.ts +26 -1
  122. package/analyzer-template/packages/generate/src/lib/scenarioComponentForServer.ts +114 -0
  123. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -2
  124. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +2 -2
  125. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tableRelations.d.ts +2 -2
  126. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts +1 -11
  127. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  128. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +30 -7
  129. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -1
  130. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
  131. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
  132. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts +1 -0
  133. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts.map +1 -1
  134. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts +2 -6
  135. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.map +1 -1
  136. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.d.ts.map +1 -1
  137. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js +7 -4
  138. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
  139. package/analyzer-template/packages/github/dist/generate/index.d.ts +3 -0
  140. package/analyzer-template/packages/github/dist/generate/index.d.ts.map +1 -1
  141. package/analyzer-template/packages/github/dist/generate/index.js +3 -0
  142. package/analyzer-template/packages/github/dist/generate/index.js.map +1 -1
  143. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
  144. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
  145. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  146. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts +9 -0
  147. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts.map +1 -0
  148. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
  149. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
  150. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts +20 -0
  151. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts.map +1 -0
  152. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
  153. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
  154. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
  155. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
  156. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  157. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.d.ts.map +1 -1
  158. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js +27 -1
  159. package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js.map +1 -1
  160. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts +8 -0
  161. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts.map +1 -0
  162. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js +89 -0
  163. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js.map +1 -0
  164. package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.d.ts.map +1 -1
  165. package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js +10 -0
  166. package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js.map +1 -1
  167. package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.d.ts.map +1 -1
  168. package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js +3 -0
  169. package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js.map +1 -1
  170. package/analyzer-template/packages/github/dist/types/index.d.ts +2 -2
  171. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  172. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  173. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +87 -13
  174. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  175. package/analyzer-template/packages/github/dist/types/src/types/Entity.d.ts +2 -0
  176. package/analyzer-template/packages/github/dist/types/src/types/Entity.d.ts.map +1 -1
  177. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts +11 -6
  178. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
  179. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +196 -0
  180. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  181. package/analyzer-template/packages/github/dist/types/src/types/StatementInfo.d.ts +2 -0
  182. package/analyzer-template/packages/github/dist/types/src/types/StatementInfo.d.ts.map +1 -1
  183. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  184. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
  185. package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  186. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
  187. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  188. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
  189. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
  190. package/analyzer-template/packages/github/src/lib/loadOrCreateCommit.ts +14 -0
  191. package/analyzer-template/packages/github/src/lib/syncPrimaryBranch.ts +2 -0
  192. package/analyzer-template/packages/process/index.ts +2 -0
  193. package/analyzer-template/packages/process/package.json +12 -0
  194. package/analyzer-template/packages/process/tsconfig.json +8 -0
  195. package/analyzer-template/packages/types/index.ts +5 -0
  196. package/analyzer-template/packages/types/src/types/Analysis.ts +104 -13
  197. package/analyzer-template/packages/types/src/types/Entity.ts +2 -0
  198. package/analyzer-template/packages/types/src/types/Scenario.ts +11 -10
  199. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +224 -0
  200. package/analyzer-template/packages/types/src/types/StatementInfo.ts +2 -0
  201. package/analyzer-template/packages/ui-components/src/components/ScenarioDetailInteractiveView.tsx +23 -7
  202. package/analyzer-template/packages/utils/dist/types/index.d.ts +2 -2
  203. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  204. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  205. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +87 -13
  206. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  207. package/analyzer-template/packages/utils/dist/types/src/types/Entity.d.ts +2 -0
  208. package/analyzer-template/packages/utils/dist/types/src/types/Entity.d.ts.map +1 -1
  209. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts +11 -6
  210. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
  211. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +196 -0
  212. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  213. package/analyzer-template/packages/utils/dist/types/src/types/StatementInfo.d.ts +2 -0
  214. package/analyzer-template/packages/utils/dist/types/src/types/StatementInfo.d.ts.map +1 -1
  215. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
  216. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
  217. package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  218. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
  219. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  220. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
  221. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
  222. package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +27 -0
  223. package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
  224. package/analyzer-template/playwright/capture.ts +37 -18
  225. package/analyzer-template/playwright/getCodeYamInfo.ts +12 -7
  226. package/analyzer-template/playwright/takeElementScreenshot.ts +26 -11
  227. package/analyzer-template/playwright/takeScreenshot.ts +9 -7
  228. package/analyzer-template/playwright/waitForServer.ts +21 -6
  229. package/analyzer-template/project/analyzeBaselineCommit.ts +4 -0
  230. package/analyzer-template/project/analyzeBranchCommit.ts +4 -0
  231. package/analyzer-template/project/analyzeFileEntities.ts +4 -0
  232. package/analyzer-template/project/analyzeRegularCommit.ts +4 -0
  233. package/analyzer-template/project/constructMockCode.ts +1181 -160
  234. package/analyzer-template/project/controller/startController.ts +16 -1
  235. package/analyzer-template/project/executeLibraryFunctionDirect.ts +7 -3
  236. package/analyzer-template/project/mocks/analyzeFileMock.ts +8 -7
  237. package/analyzer-template/project/orchestrateCapture/KyselyAnalysisLoader.ts +3 -6
  238. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +82 -36
  239. package/analyzer-template/project/orchestrateCapture.ts +36 -3
  240. package/analyzer-template/project/reconcileMockDataKeys.ts +245 -2
  241. package/analyzer-template/project/runAnalysis.ts +11 -0
  242. package/analyzer-template/project/runMultiScenarioServer.ts +11 -10
  243. package/analyzer-template/project/serverOnlyModules.ts +194 -21
  244. package/analyzer-template/project/start.ts +26 -4
  245. package/analyzer-template/project/startScenarioCapture.ts +79 -41
  246. package/analyzer-template/project/writeMockDataTsx.ts +232 -57
  247. package/analyzer-template/project/writeScenarioClientWrapper.ts +21 -0
  248. package/analyzer-template/project/writeScenarioComponents.ts +769 -181
  249. package/analyzer-template/project/writeScenarioFiles.ts +26 -0
  250. package/analyzer-template/project/writeSimpleRoot.ts +13 -15
  251. package/analyzer-template/scripts/comboWorkerLoop.cjs +1 -0
  252. package/analyzer-template/scripts/defaultCmd.sh +9 -0
  253. package/analyzer-template/tsconfig.json +2 -1
  254. package/background/src/lib/local/createLocalAnalyzer.js +1 -29
  255. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  256. package/background/src/lib/local/execAsync.js +1 -1
  257. package/background/src/lib/local/execAsync.js.map +1 -1
  258. package/background/src/lib/virtualized/common/execAsync.js +1 -1
  259. package/background/src/lib/virtualized/common/execAsync.js.map +1 -1
  260. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +2 -1
  261. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
  262. package/background/src/lib/virtualized/project/analyzeBranchCommit.js +2 -1
  263. package/background/src/lib/virtualized/project/analyzeBranchCommit.js.map +1 -1
  264. package/background/src/lib/virtualized/project/analyzeFileEntities.js +2 -1
  265. package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
  266. package/background/src/lib/virtualized/project/analyzeRegularCommit.js +2 -1
  267. package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
  268. package/background/src/lib/virtualized/project/constructMockCode.js +1053 -124
  269. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  270. package/background/src/lib/virtualized/project/controller/startController.js +11 -1
  271. package/background/src/lib/virtualized/project/controller/startController.js.map +1 -1
  272. package/background/src/lib/virtualized/project/executeLibraryFunctionDirect.js +6 -3
  273. package/background/src/lib/virtualized/project/executeLibraryFunctionDirect.js.map +1 -1
  274. package/background/src/lib/virtualized/project/mocks/analyzeFileMock.js +7 -7
  275. package/background/src/lib/virtualized/project/mocks/analyzeFileMock.js.map +1 -1
  276. package/background/src/lib/virtualized/project/orchestrateCapture/KyselyAnalysisLoader.js +3 -2
  277. package/background/src/lib/virtualized/project/orchestrateCapture/KyselyAnalysisLoader.js.map +1 -1
  278. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +69 -32
  279. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  280. package/background/src/lib/virtualized/project/orchestrateCapture.js +27 -4
  281. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  282. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +204 -2
  283. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  284. package/background/src/lib/virtualized/project/runAnalysis.js +9 -0
  285. package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
  286. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +11 -9
  287. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  288. package/background/src/lib/virtualized/project/serverOnlyModules.js +163 -23
  289. package/background/src/lib/virtualized/project/serverOnlyModules.js.map +1 -1
  290. package/background/src/lib/virtualized/project/start.js +21 -4
  291. package/background/src/lib/virtualized/project/start.js.map +1 -1
  292. package/background/src/lib/virtualized/project/startScenarioCapture.js +61 -31
  293. package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
  294. package/background/src/lib/virtualized/project/writeMockDataTsx.js +199 -50
  295. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  296. package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js +15 -0
  297. package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js.map +1 -0
  298. package/background/src/lib/virtualized/project/writeScenarioComponents.js +552 -125
  299. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  300. package/background/src/lib/virtualized/project/writeScenarioFiles.js +19 -0
  301. package/background/src/lib/virtualized/project/writeScenarioFiles.js.map +1 -1
  302. package/background/src/lib/virtualized/project/writeSimpleRoot.js +13 -13
  303. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  304. package/codeyam-cli/src/cli.js +7 -1
  305. package/codeyam-cli/src/cli.js.map +1 -1
  306. package/codeyam-cli/src/commands/analyze.js +1 -1
  307. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  308. package/codeyam-cli/src/commands/baseline.js +174 -0
  309. package/codeyam-cli/src/commands/baseline.js.map +1 -0
  310. package/codeyam-cli/src/commands/debug.js +40 -18
  311. package/codeyam-cli/src/commands/debug.js.map +1 -1
  312. package/codeyam-cli/src/commands/default.js +0 -15
  313. package/codeyam-cli/src/commands/default.js.map +1 -1
  314. package/codeyam-cli/src/commands/recapture.js +226 -0
  315. package/codeyam-cli/src/commands/recapture.js.map +1 -0
  316. package/codeyam-cli/src/commands/report.js +72 -24
  317. package/codeyam-cli/src/commands/report.js.map +1 -1
  318. package/codeyam-cli/src/commands/start.js +8 -12
  319. package/codeyam-cli/src/commands/start.js.map +1 -1
  320. package/codeyam-cli/src/commands/status.js +23 -1
  321. package/codeyam-cli/src/commands/status.js.map +1 -1
  322. package/codeyam-cli/src/commands/test-startup.js +1 -1
  323. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  324. package/codeyam-cli/src/commands/wipe.js +108 -0
  325. package/codeyam-cli/src/commands/wipe.js.map +1 -0
  326. package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js +81 -0
  327. package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js.map +1 -0
  328. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +31 -27
  329. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  330. package/codeyam-cli/src/utils/analysisRunner.js +8 -13
  331. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  332. package/codeyam-cli/src/utils/backgroundServer.js +14 -4
  333. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  334. package/codeyam-cli/src/utils/database.js +91 -5
  335. package/codeyam-cli/src/utils/database.js.map +1 -1
  336. package/codeyam-cli/src/utils/generateReport.js +253 -106
  337. package/codeyam-cli/src/utils/generateReport.js.map +1 -1
  338. package/codeyam-cli/src/utils/git.js +79 -0
  339. package/codeyam-cli/src/utils/git.js.map +1 -0
  340. package/codeyam-cli/src/utils/install-skills.js +31 -17
  341. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  342. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js +38 -0
  343. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
  344. package/codeyam-cli/src/utils/queue/job.js +245 -16
  345. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  346. package/codeyam-cli/src/utils/queue/manager.js +25 -7
  347. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  348. package/codeyam-cli/src/utils/queue/persistence.js.map +1 -1
  349. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  350. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +7 -5
  351. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  352. package/codeyam-cli/src/utils/versionInfo.js +25 -19
  353. package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
  354. package/codeyam-cli/src/utils/wipe.js +128 -0
  355. package/codeyam-cli/src/utils/wipe.js.map +1 -0
  356. package/codeyam-cli/src/webserver/app/lib/database.js +98 -1
  357. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  358. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  359. package/codeyam-cli/src/webserver/backgroundServer.js +5 -10
  360. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  361. package/codeyam-cli/src/webserver/bootstrap.js +49 -0
  362. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -0
  363. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-BXhEawa3.js +1 -0
  364. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-efWKDYMr.js → EntityTypeBadge-DLqD3qNt.js} +1 -1
  365. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-Ba2JVPzP.js +41 -0
  366. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-C8lyxW9k.js +34 -0
  367. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-aht4aafF.js +25 -0
  368. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-CVtiBnY5.js +3 -0
  369. package/codeyam-cli/src/webserver/build/client/assets/LoadingDots-B0GLXMsr.js +6 -0
  370. package/codeyam-cli/src/webserver/build/client/assets/LogViewer-xgeCVgSM.js +3 -0
  371. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-D4TZhLuw.js +21 -0
  372. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DuDvi0jm.js +1 -0
  373. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-DEx02QDa.js +10 -0
  374. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-COPstp9J.js → TruncatedFilePath-DyFZkK0l.js} +1 -1
  375. package/codeyam-cli/src/webserver/build/client/assets/_index-BwqWJOgH.js +11 -0
  376. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-DoLIqZX2.js +37 -0
  377. package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
  378. package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
  379. package/codeyam-cli/src/webserver/build/client/assets/api.rules-l0sNRNKZ.js +1 -0
  380. package/codeyam-cli/src/webserver/build/client/assets/chevron-down-Cx24_aWc.js +6 -0
  381. package/codeyam-cli/src/webserver/build/client/assets/chunk-EPOLDU6W-CXRTFQ3F.js +51 -0
  382. package/codeyam-cli/src/webserver/build/client/assets/circle-check-BOARzkeR.js +6 -0
  383. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-BdhJEx6B.js +21 -0
  384. package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-C1gnJVOL.svg → cy-logo-cli-CCKUIm0S.svg} +2 -2
  385. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +1 -0
  386. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BRb-0kQl.js +1 -0
  387. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-C2N4Op8e.js +23 -0
  388. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js +6 -0
  389. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-D1T4TGjf.js +6 -0
  390. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-CTBG2mmz.js +5 -0
  391. package/codeyam-cli/src/webserver/build/client/assets/entry.client-CS2cb_eZ.js +29 -0
  392. package/codeyam-cli/src/webserver/build/client/assets/executionFlowCoverage-BWhdfn70.js +1 -0
  393. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-DMJ7zii9.js +1 -0
  394. package/codeyam-cli/src/webserver/build/client/assets/files-Cs4MdYtv.js +1 -0
  395. package/codeyam-cli/src/webserver/build/client/assets/git-B4RJRvYB.js +15 -0
  396. package/codeyam-cli/src/webserver/build/client/assets/git-commit-horizontal-CysbcZxi.js +6 -0
  397. package/codeyam-cli/src/webserver/build/client/assets/globals-DMUaGAqV.css +1 -0
  398. package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-fmIEn3Bc.js +9 -0
  399. package/codeyam-cli/src/webserver/build/client/assets/index-B1h680n5.js +9 -0
  400. package/codeyam-cli/src/webserver/build/client/assets/index-lzqtyFU8.js +3 -0
  401. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-B7B9V-bu.js +6 -0
  402. package/codeyam-cli/src/webserver/build/client/assets/manifest-f874c610.js +1 -0
  403. package/codeyam-cli/src/webserver/build/client/assets/preload-helper-ckwbz45p.js +1 -0
  404. package/codeyam-cli/src/webserver/build/client/assets/root-Bz5TunQg.js +57 -0
  405. package/codeyam-cli/src/webserver/build/client/assets/rules-hEkvVw2-.js +97 -0
  406. package/codeyam-cli/src/webserver/build/client/assets/scenarioStatus-B_8jpV3e.js +1 -0
  407. package/codeyam-cli/src/webserver/build/client/assets/search-CxXUmBSd.js +6 -0
  408. package/codeyam-cli/src/webserver/build/client/assets/settings-CS5f3WzT.js +1 -0
  409. package/codeyam-cli/src/webserver/build/client/assets/simulations-DwFIBT09.js +1 -0
  410. package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-B6LgvRJg.js +6 -0
  411. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-C1v1PQzo.js +1 -0
  412. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-3pmpUQB-.js → useLastLogLine-aSv48UbS.js} +1 -1
  413. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-DYxHZQuP.js +1 -0
  414. package/codeyam-cli/src/webserver/build/client/assets/{useToast-DEyawJ8r.js → useToast-mBRpZPiu.js} +1 -1
  415. package/codeyam-cli/src/webserver/build/server/assets/index-967OuJoF.js +1 -0
  416. package/codeyam-cli/src/webserver/build/server/assets/server-build-DRTmerg9.js +257 -0
  417. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  418. package/codeyam-cli/src/webserver/build-info.json +5 -5
  419. package/codeyam-cli/src/webserver/devServer.js +1 -3
  420. package/codeyam-cli/src/webserver/devServer.js.map +1 -1
  421. package/codeyam-cli/src/webserver/server.js +35 -25
  422. package/codeyam-cli/src/webserver/server.js.map +1 -1
  423. package/codeyam-cli/templates/codeyam-power-rules-hook.sh +200 -0
  424. package/codeyam-cli/templates/{codeyam-debug-skill.md → codeyam:debug.md} +48 -4
  425. package/codeyam-cli/templates/codeyam:diagnose.md +650 -0
  426. package/codeyam-cli/templates/codeyam:new-rule.md +13 -0
  427. package/codeyam-cli/templates/codeyam:power-rules.md +447 -0
  428. package/codeyam-cli/templates/{codeyam-setup-skill.md → codeyam:setup.md} +139 -4
  429. package/codeyam-cli/templates/{codeyam-sim-skill.md → codeyam:sim.md} +1 -1
  430. package/codeyam-cli/templates/{codeyam-test-skill.md → codeyam:test.md} +1 -1
  431. package/codeyam-cli/templates/{codeyam-verify-skill.md → codeyam:verify.md} +1 -1
  432. package/package.json +17 -16
  433. package/packages/ai/index.js +5 -4
  434. package/packages/ai/index.js.map +1 -1
  435. package/packages/ai/src/lib/analyzeScope.js +99 -0
  436. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  437. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
  438. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
  439. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +100 -1
  440. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  441. package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js +435 -0
  442. package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js.map +1 -0
  443. package/packages/ai/src/lib/astScopes/methodSemantics.js +97 -6
  444. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  445. package/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.js +8 -0
  446. package/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.js.map +1 -1
  447. package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js +23 -0
  448. package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js.map +1 -1
  449. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +138 -1
  450. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
  451. package/packages/ai/src/lib/astScopes/processExpression.js +945 -87
  452. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  453. package/packages/ai/src/lib/checkAllAttributes.js +24 -9
  454. package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
  455. package/packages/ai/src/lib/completionCall.js +178 -31
  456. package/packages/ai/src/lib/completionCall.js.map +1 -1
  457. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +1198 -82
  458. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  459. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +2 -1
  460. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  461. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +661 -0
  462. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -0
  463. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +180 -56
  464. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  465. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +16 -1
  466. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  467. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +86 -4
  468. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  469. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +20 -0
  470. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  471. package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js +86 -0
  472. package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js.map +1 -0
  473. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +34 -3
  474. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  475. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
  476. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
  477. package/packages/ai/src/lib/dataStructureChunking.js +111 -0
  478. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
  479. package/packages/ai/src/lib/deepEqual.js +32 -0
  480. package/packages/ai/src/lib/deepEqual.js.map +1 -0
  481. package/packages/ai/src/lib/e2eDataTracking.js +241 -0
  482. package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
  483. package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
  484. package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
  485. package/packages/ai/src/lib/generateChangesEntityScenarioData.js +62 -5
  486. package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
  487. package/packages/ai/src/lib/generateChangesEntityScenarios.js +81 -90
  488. package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
  489. package/packages/ai/src/lib/generateEntityDataStructure.js +5 -0
  490. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  491. package/packages/ai/src/lib/generateEntityScenarioData.js +904 -84
  492. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  493. package/packages/ai/src/lib/generateEntityScenarios.js +186 -82
  494. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  495. package/packages/ai/src/lib/generateExecutionFlows.js +392 -0
  496. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -0
  497. package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js +380 -0
  498. package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js.map +1 -0
  499. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +1440 -0
  500. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -0
  501. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
  502. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
  503. package/packages/ai/src/lib/getConditionalUsagesFromCode.js +84 -14
  504. package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
  505. package/packages/ai/src/lib/guessScenarioDataFromDescription.js +2 -1
  506. package/packages/ai/src/lib/guessScenarioDataFromDescription.js.map +1 -1
  507. package/packages/ai/src/lib/isolateScopes.js +231 -4
  508. package/packages/ai/src/lib/isolateScopes.js.map +1 -1
  509. package/packages/ai/src/lib/mergeStatements.js +26 -3
  510. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  511. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +6 -0
  512. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  513. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +1 -1
  514. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
  515. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +21 -64
  516. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
  517. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
  518. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
  519. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +68 -6
  520. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  521. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +10 -34
  522. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
  523. package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js +45 -0
  524. package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js.map +1 -0
  525. package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js +16 -3
  526. package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js.map +1 -1
  527. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
  528. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
  529. package/packages/ai/src/lib/resolvePathToControllable.js +667 -0
  530. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -0
  531. package/packages/ai/src/lib/splitOutsideParentheses.js +3 -1
  532. package/packages/ai/src/lib/splitOutsideParentheses.js.map +1 -1
  533. package/packages/ai/src/lib/worker/SerializableDataStructure.js +29 -0
  534. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  535. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +4 -0
  536. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  537. package/packages/analyze/src/lib/FileAnalyzer.js +15 -0
  538. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  539. package/packages/analyze/src/lib/analysisContext.js +30 -5
  540. package/packages/analyze/src/lib/analysisContext.js.map +1 -1
  541. package/packages/analyze/src/lib/asts/nodes/index.js +1 -0
  542. package/packages/analyze/src/lib/asts/nodes/index.js.map +1 -1
  543. package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js +52 -0
  544. package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js.map +1 -0
  545. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +218 -50
  546. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  547. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +10 -0
  548. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  549. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +2 -0
  550. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
  551. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -7
  552. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  553. package/packages/analyze/src/lib/files/analyzeChange.js +21 -11
  554. package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
  555. package/packages/analyze/src/lib/files/analyzeEntity.js +9 -8
  556. package/packages/analyze/src/lib/files/analyzeEntity.js.map +1 -1
  557. package/packages/analyze/src/lib/files/analyzeInitial.js +9 -10
  558. package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
  559. package/packages/analyze/src/lib/files/enums/steps.js +1 -1
  560. package/packages/analyze/src/lib/files/enums/steps.js.map +1 -1
  561. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +209 -0
  562. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -0
  563. package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js +85 -0
  564. package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js.map +1 -0
  565. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +458 -48
  566. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  567. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js +1 -1
  568. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js.map +1 -1
  569. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js +29 -34
  570. package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js.map +1 -1
  571. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +264 -78
  572. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  573. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +96 -0
  574. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -0
  575. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +56 -69
  576. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
  577. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +4 -8
  578. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
  579. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +372 -89
  580. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  581. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
  582. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  583. package/packages/aws/src/lib/ecs/ecsDefineContainer.js +2 -2
  584. package/packages/aws/src/lib/ecs/ecsDefineContainer.js.map +1 -1
  585. package/packages/aws/src/lib/ecs/ecsTaskFactory.js +17 -61
  586. package/packages/aws/src/lib/ecs/ecsTaskFactory.js.map +1 -1
  587. package/packages/database/src/lib/kysely/db.js +2 -2
  588. package/packages/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
  589. package/packages/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
  590. package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js +7 -4
  591. package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
  592. package/packages/generate/index.js +3 -0
  593. package/packages/generate/index.js.map +1 -1
  594. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
  595. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  596. package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
  597. package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
  598. package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
  599. package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
  600. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
  601. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  602. package/packages/generate/src/lib/deepMerge.js +27 -1
  603. package/packages/generate/src/lib/deepMerge.js.map +1 -1
  604. package/packages/generate/src/lib/scenarioComponentForServer.js +89 -0
  605. package/packages/generate/src/lib/scenarioComponentForServer.js.map +1 -0
  606. package/packages/github/src/lib/loadOrCreateCommit.js +10 -0
  607. package/packages/github/src/lib/loadOrCreateCommit.js.map +1 -1
  608. package/packages/github/src/lib/syncPrimaryBranch.js +3 -0
  609. package/packages/github/src/lib/syncPrimaryBranch.js.map +1 -1
  610. package/packages/process/index.js +3 -0
  611. package/packages/process/index.js.map +1 -0
  612. package/packages/process/src/GlobalProcessManager.js.map +1 -0
  613. package/{background/src/lib/process → packages/process/src}/ProcessManager.js +1 -1
  614. package/packages/process/src/ProcessManager.js.map +1 -0
  615. package/packages/process/src/index.js.map +1 -0
  616. package/packages/process/src/managedExecAsync.js.map +1 -0
  617. package/packages/types/index.js.map +1 -1
  618. package/packages/utils/src/lib/lightweightEntityExtractor.js +25 -0
  619. package/packages/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
  620. package/packages/utils/src/lib/safeFileName.js +29 -3
  621. package/packages/utils/src/lib/safeFileName.js.map +1 -1
  622. package/scripts/finalize-analyzer.cjs +6 -4
  623. package/analyzer-template/packages/ai/src/lib/findMatchingAttribute.ts +0 -102
  624. package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +0 -197
  625. package/analyzer-template/packages/ai/src/lib/generateChangesEntityKeyAttributes.ts +0 -271
  626. package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +0 -294
  627. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.ts +0 -67
  628. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +0 -115
  629. package/analyzer-template/process/INTEGRATION_COMPLETE.md +0 -333
  630. package/analyzer-template/process/INTEGRATION_EXAMPLE.md +0 -525
  631. package/analyzer-template/process/README.md +0 -507
  632. package/background/src/lib/process/GlobalProcessManager.js.map +0 -1
  633. package/background/src/lib/process/ProcessManager.js.map +0 -1
  634. package/background/src/lib/process/index.js.map +0 -1
  635. package/background/src/lib/process/managedExecAsync.js.map +0 -1
  636. package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js +0 -238
  637. package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js.map +0 -1
  638. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-CVbSvOjo.js +0 -1
  639. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-DcwcHyl5.js +0 -1
  640. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-WgwC1GfJ.js +0 -26
  641. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-IEKom9O2.js +0 -3
  642. package/codeyam-cli/src/webserver/build/client/assets/LogViewer-BYnfxbUG.js +0 -3
  643. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-_lBPJCzG.js +0 -1
  644. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-lHVhvsu_.js +0 -1
  645. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-d_TBk4GQ.js +0 -5
  646. package/codeyam-cli/src/webserver/build/client/assets/_index-kGT7VUqj.js +0 -1
  647. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-DDGmhu7P.js +0 -7
  648. package/codeyam-cli/src/webserver/build/client/assets/chevron-down-n_HPRfM_.js +0 -1
  649. package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-CbVoyx1U.js +0 -26
  650. package/codeyam-cli/src/webserver/build/client/assets/circle-check-D1VOYveA.js +0 -1
  651. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-YR8jjAlu.js +0 -1
  652. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-B8vP3V_s.js +0 -1
  653. package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-CN6aLCT1.js +0 -16
  654. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DA5Jeu2P.js +0 -1
  655. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-BTeitalf.js +0 -5
  656. package/codeyam-cli/src/webserver/build/client/assets/entry.client-du6UEYD-.js +0 -13
  657. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-BpjkhMoi.js +0 -1
  658. package/codeyam-cli/src/webserver/build/client/assets/files-BQGvk4lJ.js +0 -1
  659. package/codeyam-cli/src/webserver/build/client/assets/git-DVdYRT-I.js +0 -12
  660. package/codeyam-cli/src/webserver/build/client/assets/globals-CO-U8Bpo.css +0 -1
  661. package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +0 -5
  662. package/codeyam-cli/src/webserver/build/client/assets/index-DCG-vks0.js +0 -1
  663. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-GazdNeLl.js +0 -1
  664. package/codeyam-cli/src/webserver/build/client/assets/manifest-0b694d28.js +0 -1
  665. package/codeyam-cli/src/webserver/build/client/assets/root-D3tQP7hx.js +0 -16
  666. package/codeyam-cli/src/webserver/build/client/assets/search-CIY6XmtE.js +0 -1
  667. package/codeyam-cli/src/webserver/build/client/assets/server-build-CMKNK2uU.css +0 -1
  668. package/codeyam-cli/src/webserver/build/client/assets/settings-CoMDgElu.js +0 -1
  669. package/codeyam-cli/src/webserver/build/client/assets/simulations-agkniXp2.js +0 -1
  670. package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-B2VUcygF.js +0 -1
  671. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-EvdK-zXP.js +0 -1
  672. package/codeyam-cli/src/webserver/build/server/assets/index-DGVHQEXD.js +0 -1
  673. package/codeyam-cli/src/webserver/build/server/assets/server-build-CghkTkIL.js +0 -166
  674. package/codeyam-cli/templates/debug-command.md +0 -303
  675. package/packages/ai/src/lib/findMatchingAttribute.js +0 -77
  676. package/packages/ai/src/lib/findMatchingAttribute.js.map +0 -1
  677. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +0 -136
  678. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +0 -1
  679. package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js +0 -220
  680. package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js.map +0 -1
  681. package/packages/ai/src/lib/generateEntityKeyAttributes.js +0 -241
  682. package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +0 -1
  683. package/packages/ai/src/lib/isFrontend.js +0 -5
  684. package/packages/ai/src/lib/isFrontend.js.map +0 -1
  685. package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js +0 -40
  686. package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js.map +0 -1
  687. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +0 -72
  688. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +0 -1
  689. /package/analyzer-template/{process → packages/process/src}/GlobalProcessManager.ts +0 -0
  690. /package/analyzer-template/{process → packages/process/src}/ProcessManager.ts +0 -0
  691. /package/analyzer-template/{process → packages/process/src}/index.ts +0 -0
  692. /package/analyzer-template/{process → packages/process/src}/managedExecAsync.ts +0 -0
  693. /package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CMKNK2uU.css → styles-CMKNK2uU.css} +0 -0
  694. /package/{background/src/lib/process → packages/process/src}/GlobalProcessManager.js +0 -0
  695. /package/{background/src/lib/process → packages/process/src}/index.js +0 -0
  696. /package/{background/src/lib/process → packages/process/src}/managedExecAsync.js +0 -0
@@ -1,9 +1,188 @@
1
1
  import ts from 'typescript';
2
+ import * as crypto from 'crypto';
2
3
  import { StructuredPath } from "./paths.js";
3
4
  import { nodeToSource } from "./nodeToSource.js";
4
5
  import { methodRegistry, ArrayPushSemantics } from "./methodSemantics.js";
5
6
  import { isArithmeticOperator, isAssignmentOperator, isBitwiseCompoundOperator, isComparisonOperator, isDefinedType, isNumericCompoundOperator, leftOrRightType, unwrapExpression, } from "./sharedPatterns.js";
6
7
  import { processBindingPattern } from "./processBindings.js";
8
+ import { extractConditionalEffectsFromTernary, findUseStateSetters, } from "./conditionalEffectsExtractor.js";
9
+ import { detectArrayDerivedPattern } from "./arrayDerivationDetector.js";
10
+ /**
11
+ * Extracts the component name from a JSX element.
12
+ * Returns null for intrinsic elements (div, span, etc.) since we only care about
13
+ * custom components for gating condition tracking.
14
+ *
15
+ * Examples:
16
+ * - <ChildViewer /> → "ChildViewer"
17
+ * - <ScenarioViewer scenario={...} /> → "ScenarioViewer"
18
+ * - <div> → null (intrinsic element)
19
+ */
20
+ function getComponentNameFromJsx(node) {
21
+ let tagName;
22
+ if (ts.isJsxElement(node)) {
23
+ tagName = node.openingElement.tagName;
24
+ }
25
+ else {
26
+ tagName = node.tagName;
27
+ }
28
+ // Get the text of the tag name
29
+ const name = tagName.getText();
30
+ // Check if it's a custom component (starts with uppercase) vs intrinsic element
31
+ // Custom components start with uppercase: <MyComponent />
32
+ // Intrinsic elements start with lowercase: <div />
33
+ if (name &&
34
+ name[0] === name[0].toUpperCase() &&
35
+ name[0] !== name[0].toLowerCase()) {
36
+ return name;
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Extracts condition paths from a logical AND chain expression.
42
+ * Used for creating gating conditions for child components.
43
+ *
44
+ * Example: `hasData && isReady && <Component />` returns ['hasData', 'isReady']
45
+ */
46
+ function extractConditionPathsFromAndChain(expr, sourceFile) {
47
+ const paths = [];
48
+ const unwrapped = unwrapExpression(expr);
49
+ if (ts.isBinaryExpression(unwrapped) &&
50
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
51
+ // Recursively get conditions from left side
52
+ paths.push(...extractConditionPathsFromAndChain(unwrapped.left, sourceFile));
53
+ // Process right side if it's not JSX (JSX is the consequence, not a condition)
54
+ const rightUnwrapped = unwrapExpression(unwrapped.right);
55
+ if (!ts.isJsxElement(rightUnwrapped) &&
56
+ !ts.isJsxSelfClosingElement(rightUnwrapped) &&
57
+ !ts.isJsxFragment(rightUnwrapped)) {
58
+ paths.push(...extractConditionPathsFromAndChain(unwrapped.right, sourceFile));
59
+ }
60
+ }
61
+ else {
62
+ // Base case: extract path from this expression
63
+ const path = StructuredPath.fromNode(unwrapped, sourceFile);
64
+ if (path) {
65
+ paths.push(path.toString());
66
+ }
67
+ }
68
+ return paths;
69
+ }
70
+ /**
71
+ * Finds the rightmost JSX element in an && chain.
72
+ * Example: `a && b && <Component />` returns <Component />
73
+ */
74
+ function findJsxInAndChain(expr) {
75
+ const unwrapped = unwrapExpression(expr);
76
+ if (ts.isJsxElement(unwrapped) || ts.isJsxSelfClosingElement(unwrapped)) {
77
+ return unwrapped;
78
+ }
79
+ if (ts.isBinaryExpression(unwrapped) &&
80
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
81
+ // Check right side first (most common case: condition && <Jsx />)
82
+ const rightResult = findJsxInAndChain(unwrapped.right);
83
+ if (rightResult)
84
+ return rightResult;
85
+ // Also check left side for rare cases
86
+ return findJsxInAndChain(unwrapped.left);
87
+ }
88
+ return null;
89
+ }
90
+ /**
91
+ * Fix 32: Finds a JSX fragment in an && chain.
92
+ * Example: `activeTab && <><ChildA /><ChildB /></>` returns the fragment
93
+ * This is needed to propagate parent conditions through fragments.
94
+ */
95
+ function findJsxFragmentInAndChain(expr) {
96
+ const unwrapped = unwrapExpression(expr);
97
+ if (ts.isJsxFragment(unwrapped)) {
98
+ return unwrapped;
99
+ }
100
+ if (ts.isBinaryExpression(unwrapped) &&
101
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
102
+ // Check right side first (most common case: condition && <></>)
103
+ const rightResult = findJsxFragmentInAndChain(unwrapped.right);
104
+ if (rightResult)
105
+ return rightResult;
106
+ // Also check left side for rare cases
107
+ return findJsxFragmentInAndChain(unwrapped.left);
108
+ }
109
+ return null;
110
+ }
111
+ /**
112
+ * Detects if a property access looks like an environment variable store access.
113
+ * Matches patterns like `env.DATABASE_URL`, `env.IS_FORMBRICKS_CLOUD`, etc.
114
+ * where the object is named "env" and the property looks like an env var name.
115
+ */
116
+ function isEnvStoreAccess(fullText) {
117
+ // Match: env.SOME_VAR or env.someVar (but object must be exactly "env")
118
+ // This catches patterns from @t3-oss/env-nextjs and similar packages
119
+ const envStorePattern = /^env\.[A-Z_][A-Z0-9_]*$/;
120
+ return envStorePattern.test(fullText);
121
+ }
122
+ /**
123
+ * Converts a call expression argument to a StructuredPath.
124
+ *
125
+ * IMPORTANT: We always use the original source text for callbacks, never cyScope names.
126
+ * cyScope names are internal identifiers for child scopes and should NEVER appear
127
+ * in schema paths or call signatures. Using cyScope names causes data merge conflicts
128
+ * because the same callback gets different identifiers in different contexts.
129
+ */
130
+ function getArgPathForCallSignature(arg, context) {
131
+ // Always use the standard path conversion - never replace with cyScope names
132
+ return (StructuredPath.fromNode(arg, context.sourceFile) ||
133
+ nodeToSource(arg, context.sourceFile));
134
+ }
135
+ /**
136
+ * Builds a StructuredPath for a call expression using the original source text.
137
+ *
138
+ * IMPORTANT: This function ensures consistent call signatures by always using
139
+ * the original callback text, never cyScope names. This prevents schema path
140
+ * conflicts where the same call would have different paths.
141
+ */
142
+ function buildCallPathFromSource(node, context) {
143
+ const expression = node.expression;
144
+ // Convert arguments using original source text
145
+ const argPaths = node.arguments.map((arg) => getArgPathForCallSignature(arg, context));
146
+ // Handle type arguments if present
147
+ let typeArgs = undefined;
148
+ if (node.typeArguments && node.typeArguments.length > 0) {
149
+ typeArgs = node.typeArguments.map((typeArg) => typeArg.getText(context.sourceFile));
150
+ }
151
+ if (ts.isIdentifier(expression)) {
152
+ // Simple function call: func(arg1, arg2)
153
+ return StructuredPath.fromFunction(expression.text, argPaths, typeArgs);
154
+ }
155
+ else if (ts.isPropertyAccessExpression(expression)) {
156
+ // Method call: obj.method(arg1, arg2)
157
+ const objPath = StructuredPath.fromNode(expression.expression, context.sourceFile);
158
+ if (!objPath)
159
+ return null;
160
+ return objPath
161
+ .withProperty(expression.name.text)
162
+ .withFunctionCall(argPaths, typeArgs);
163
+ }
164
+ else if (ts.isCallExpression(expression)) {
165
+ // Chained call: func(arg1)(arg2)
166
+ const funcPath = buildCallPathFromSource(expression, context);
167
+ if (!funcPath)
168
+ return null;
169
+ return funcPath.withFunctionCall(argPaths, typeArgs);
170
+ }
171
+ else if (ts.isElementAccessExpression(expression)) {
172
+ // Element access call: obj[key](args)
173
+ const basePath = StructuredPath.fromNode(expression, context.sourceFile);
174
+ if (!basePath)
175
+ return null;
176
+ return basePath.withFunctionCall(argPaths, typeArgs);
177
+ }
178
+ else {
179
+ // Complex call expression
180
+ const basePath = StructuredPath.fromNode(expression, context.sourceFile);
181
+ if (!basePath)
182
+ return null;
183
+ return basePath.withFunctionCall(argPaths, typeArgs);
184
+ }
185
+ }
7
186
  /**
8
187
  * Checks if an expression is likely an array type.
9
188
  * Uses TypeScript's type checker when available, falls back to heuristics.
@@ -81,102 +260,708 @@ export function markConditionVariablesAsNullable(condition, context) {
81
260
  }
82
261
  }
83
262
  /**
84
- * Extracts conditional usages from a condition expression for key attribute detection.
85
- * This function identifies which attributes are used in conditionals and how they're used.
263
+ * Helper to extract source location from an AST node
264
+ */
265
+ function getSourceLocation(node, sourceFile) {
266
+ const start = node.getStart(sourceFile);
267
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(start);
268
+ const codeSnippet = node.getText(sourceFile);
269
+ return {
270
+ lineNumber: line + 1, // Convert to 1-based
271
+ column: character,
272
+ codeSnippet: codeSnippet.length > 100
273
+ ? codeSnippet.slice(0, 100) + '...'
274
+ : codeSnippet,
275
+ };
276
+ }
277
+ /**
278
+ * Extracts the root array path from an expression that ends with .map().
279
+ * Handles chained methods like .filter().map(), .slice().map(), etc.
86
280
  *
87
- * @param condition The condition expression to analyze
281
+ * Examples:
282
+ * - items.map(...) → "items"
283
+ * - data.users.map(...) → "data.users"
284
+ * - items.filter(...).map(...) → "items"
285
+ * - items.slice(0, 5).map(...) → "items"
286
+ */
287
+ function extractArrayPathFromMapCall(expr, sourceFile) {
288
+ // Walk up the chain to find the root array
289
+ let current = expr.expression;
290
+ while (ts.isPropertyAccessExpression(current)) {
291
+ const methodName = current.name.getText(sourceFile);
292
+ // Common array methods that return arrays (so we keep going up)
293
+ const arrayReturningMethods = [
294
+ 'map',
295
+ 'filter',
296
+ 'slice',
297
+ 'concat',
298
+ 'flat',
299
+ 'flatMap',
300
+ 'reverse',
301
+ 'sort',
302
+ 'toReversed',
303
+ 'toSorted',
304
+ 'toSpliced',
305
+ ];
306
+ if (arrayReturningMethods.includes(methodName)) {
307
+ const objectExpr = current.expression;
308
+ // If the object is a call expression (chained method), keep going
309
+ if (ts.isCallExpression(objectExpr)) {
310
+ current = objectExpr.expression;
311
+ }
312
+ else {
313
+ // Found the root - it's an identifier or property access
314
+ const path = StructuredPath.fromNode(objectExpr, sourceFile);
315
+ return path ? path.toString() : null;
316
+ }
317
+ }
318
+ else {
319
+ // Not an array method we recognize
320
+ break;
321
+ }
322
+ }
323
+ return null;
324
+ }
325
+ /**
326
+ * Extracts JSX rendering usages from a JSX expression.
327
+ * Detects:
328
+ * - array.map() calls → 'array-map' type
329
+ * - string interpolations (identifiers/property access) → 'text-interpolation' type
330
+ *
331
+ * Recursively searches inside && chains and ternary expressions.
332
+ *
333
+ * @param expr The expression inside {expr}
88
334
  * @param context The analysis context
89
- * @param location Where this condition appears (if, ternary, logical-and, switch)
90
335
  */
91
- export function extractConditionalUsage(condition, context, location) {
92
- const unwrapped = unwrapExpression(condition);
93
- // Handle binary expressions with && (logical AND chains)
94
- // Example: `a && b && <Component />` - both a and b are conditional checks
336
+ function extractJsxRenderingUsage(expr, context) {
337
+ const unwrapped = unwrapExpression(expr);
338
+ const sourceLocation = getSourceLocation(expr, context.sourceFile);
339
+ // Detect array.map() calls
340
+ if (ts.isCallExpression(unwrapped)) {
341
+ const calleeExpr = unwrapped.expression;
342
+ if (ts.isPropertyAccessExpression(calleeExpr)) {
343
+ const methodName = calleeExpr.name.getText(context.sourceFile);
344
+ if (methodName === 'map') {
345
+ const arrayPath = extractArrayPathFromMapCall(unwrapped, context.sourceFile);
346
+ if (arrayPath) {
347
+ context.addJsxRenderingUsage({
348
+ path: arrayPath,
349
+ renderingType: 'array-map',
350
+ valueType: 'array',
351
+ sourceLocation,
352
+ });
353
+ }
354
+ }
355
+ }
356
+ }
357
+ // Detect simple string interpolations: {title} or {user.name}
358
+ else if (ts.isIdentifier(unwrapped) ||
359
+ ts.isPropertyAccessExpression(unwrapped)) {
360
+ const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
361
+ if (path) {
362
+ const pathStr = path.toString();
363
+ const typeInfo = context.getTypeInfo(path);
364
+ // Only track as text interpolation if it's a string type
365
+ // Check for 'string' type, or types that contain 'string' (but not 'string[]')
366
+ if (typeInfo === 'string' ||
367
+ (typeInfo &&
368
+ typeInfo.includes('string') &&
369
+ !typeInfo.includes('string[]'))) {
370
+ context.addJsxRenderingUsage({
371
+ path: pathStr,
372
+ renderingType: 'text-interpolation',
373
+ valueType: 'string',
374
+ sourceLocation,
375
+ });
376
+ }
377
+ }
378
+ }
379
+ // Recursively search inside && chains: {showList && items.map(...)}
380
+ else if (ts.isBinaryExpression(unwrapped) &&
381
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
382
+ // Check the right side of the && chain (where .map() typically appears)
383
+ const rightSide = unwrapExpression(unwrapped.right);
384
+ extractJsxRenderingUsage(rightSide, context);
385
+ // Also check nested && chains on the left
386
+ extractJsxRenderingUsage(unwrapped.left, context);
387
+ }
388
+ // Recursively search inside ternaries: {isEmpty ? null : items.map(...)}
389
+ else if (ts.isConditionalExpression(unwrapped)) {
390
+ extractJsxRenderingUsage(unwrapped.whenTrue, context);
391
+ extractJsxRenderingUsage(unwrapped.whenFalse, context);
392
+ }
393
+ }
394
+ /**
395
+ * Counts the number of conditions in an && chain (excluding JSX consequence)
396
+ */
397
+ function countConditionsInAndChain(expr) {
398
+ const unwrapped = unwrapExpression(expr);
95
399
  if (ts.isBinaryExpression(unwrapped) &&
96
400
  unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
97
- // Recursively process left side
98
- extractConditionalUsage(unwrapped.left, context, location);
99
- // Process right side if it's not JSX (JSX is the consequence, not the condition)
401
+ const leftCount = countConditionsInAndChain(unwrapped.left);
100
402
  const rightUnwrapped = unwrapExpression(unwrapped.right);
101
403
  const isJsxConsequence = ts.isJsxElement(rightUnwrapped) ||
102
404
  ts.isJsxSelfClosingElement(rightUnwrapped) ||
103
405
  ts.isJsxFragment(rightUnwrapped);
104
- if (!isJsxConsequence) {
105
- extractConditionalUsage(unwrapped.right, context, location);
406
+ if (isJsxConsequence) {
407
+ return leftCount;
106
408
  }
107
- return;
409
+ return leftCount + countConditionsInAndChain(unwrapped.right);
108
410
  }
109
- // Handle binary expressions with || (logical OR)
110
- if (ts.isBinaryExpression(unwrapped) &&
111
- unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
112
- // Both sides of || are conditional checks
113
- extractConditionalUsage(unwrapped.left, context, location);
114
- extractConditionalUsage(unwrapped.right, context, location);
411
+ // Single condition (not an && chain)
412
+ return 1;
413
+ }
414
+ /**
415
+ * Extracts conditionals from JSX elements by recursively traversing children.
416
+ *
417
+ * This is CRITICAL for extracting compound conditionals from JSX expressions
418
+ * like `{hasNewerVersion && !isActive && <Banner />}`.
419
+ *
420
+ * This function is called BEFORE the child boundary check in processExpression
421
+ * because JSX elements are NOT scopes - their expressions use variables from
422
+ * the parent scope and should have their conditionals extracted regardless of
423
+ * whether the JSX is within a child boundary.
424
+ *
425
+ * Fix 32: Added parentConditions parameter to track gating conditions from
426
+ * parent && chains. When we find a component nested inside multiple conditionals
427
+ * like `{activeTab && <>{ternary ? ... : <Component />}</>}`, ALL parent
428
+ * conditions should be added as gating conditions for the component.
429
+ *
430
+ * @param node The JSX element, self-closing element, or fragment to traverse
431
+ * @param context The analysis context
432
+ * @param parentConditions Accumulated gating conditions from parent && chains
433
+ */
434
+ function extractConditionalsFromJsx(node, context, parentConditions = []) {
435
+ // Get children to process
436
+ let children;
437
+ if (ts.isJsxElement(node)) {
438
+ children = node.children;
439
+ }
440
+ else if (ts.isJsxFragment(node)) {
441
+ children = node.children;
442
+ }
443
+ // JsxSelfClosingElement has no children
444
+ if (!children) {
115
445
  return;
116
446
  }
117
- // Handle comparison operators (===, !==, <, >, <=, >=)
118
- // Example: `if (status === 'active')` - status is compared against 'active'
119
- if (ts.isBinaryExpression(unwrapped) &&
120
- isComparisonOperator(unwrapped.operatorToken.kind)) {
121
- // Try to extract the variable and the compared value
122
- const leftPath = StructuredPath.fromNode(unwrapped.left, context.sourceFile);
123
- const rightPath = StructuredPath.fromNode(unwrapped.right, context.sourceFile);
124
- // Check if left is a variable and right is a literal
125
- if (leftPath && isLiteralExpression(unwrapped.right)) {
126
- const literalValue = getLiteralValue(unwrapped.right, context);
127
- context.addConditionalUsage({
128
- path: leftPath.toLeftHandSideString(),
129
- conditionType: 'comparison',
130
- comparedValues: literalValue !== undefined ? [literalValue] : undefined,
131
- location,
132
- });
447
+ for (const child of children) {
448
+ // Process JSX expressions: {expr}
449
+ if (ts.isJsxExpression(child) && child.expression) {
450
+ const expr = unwrapExpression(child.expression);
451
+ // Extract JSX rendering usages (array.map, text interpolation)
452
+ // This handles direct usages like {items.map(...)} or {user.name}
453
+ extractJsxRenderingUsage(expr, context);
454
+ // If the expression is an && chain, extract its conditional usages
455
+ if (ts.isBinaryExpression(expr) &&
456
+ expr.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
457
+ // Mark nullable variables
458
+ markConditionVariablesAsNullable(expr, context);
459
+ // Extract conditional usage (this handles compound conditionals)
460
+ // Pass controlsJsxRendering: true since this conditional controls JSX rendering
461
+ extractConditionalUsage(expr, context, 'logical-and', {
462
+ controlsJsxRendering: true,
463
+ });
464
+ // Extract all condition paths from the && chain for gating tracking
465
+ const conditionPaths = extractConditionPathsFromAndChain(expr, context.sourceFile);
466
+ const sourceLocation = getSourceLocation(expr, context.sourceFile);
467
+ // Fix 32: Build accumulated conditions including parent conditions
468
+ const accumulatedConditions = [
469
+ ...parentConditions,
470
+ ...conditionPaths.map((path) => ({
471
+ path,
472
+ sourceLocation,
473
+ isNegated: false,
474
+ })),
475
+ ];
476
+ // Track gating conditions for child components
477
+ // Example: {hasAnalysis && <ScenarioViewer />}
478
+ const jsxElement = findJsxInAndChain(expr);
479
+ if (jsxElement) {
480
+ const componentName = getComponentNameFromJsx(jsxElement);
481
+ if (componentName) {
482
+ // Fix 32: Add ALL accumulated conditions (parent + current) as gating conditions
483
+ for (const condition of accumulatedConditions) {
484
+ context.addChildBoundaryGatingCondition(componentName, {
485
+ path: condition.path,
486
+ conditionType: 'truthiness',
487
+ location: 'logical-and',
488
+ sourceLocation: condition.sourceLocation,
489
+ controlsJsxRendering: true,
490
+ isNegated: condition.isNegated,
491
+ });
492
+ }
493
+ }
494
+ // Fix 32: Recursively process nested JSX with accumulated conditions
495
+ if (ts.isJsxElement(jsxElement) ||
496
+ ts.isJsxSelfClosingElement(jsxElement)) {
497
+ extractConditionalsFromJsx(jsxElement, context, accumulatedConditions);
498
+ }
499
+ }
500
+ // Fix 32: Also check for nested JSX fragments
501
+ const jsxFragment = findJsxFragmentInAndChain(expr);
502
+ if (jsxFragment) {
503
+ extractConditionalsFromJsx(jsxFragment, context, accumulatedConditions);
504
+ }
505
+ }
506
+ // If the expression is a ternary, extract its conditional
507
+ else if (ts.isConditionalExpression(expr)) {
508
+ // Pass controlsJsxRendering: true since this conditional controls JSX rendering
509
+ extractConditionalUsage(expr.condition, context, 'ternary', {
510
+ controlsJsxRendering: true,
511
+ });
512
+ // Track gating conditions for components in both branches of the ternary
513
+ // Example: {isError ? <ErrorView /> : <SuccessView />}
514
+ const conditionPath = StructuredPath.fromNode(unwrapExpression(expr.condition), context.sourceFile);
515
+ const sourceLocation = getSourceLocation(expr, context.sourceFile);
516
+ // Recursively process the whenTrue and whenFalse branches for JSX
517
+ const whenTrue = unwrapExpression(expr.whenTrue);
518
+ const whenFalse = unwrapExpression(expr.whenFalse);
519
+ // Fix 32: Build conditions for whenTrue branch (parent conditions + ternary condition truthy)
520
+ const whenTrueConditions = [
521
+ ...parentConditions,
522
+ ...(conditionPath
523
+ ? [
524
+ {
525
+ path: conditionPath.toString(),
526
+ sourceLocation,
527
+ isNegated: false,
528
+ },
529
+ ]
530
+ : []),
531
+ ];
532
+ // Fix 32: Build conditions for whenFalse branch (parent conditions + ternary condition falsy)
533
+ const whenFalseConditions = [
534
+ ...parentConditions,
535
+ ...(conditionPath
536
+ ? [
537
+ {
538
+ path: conditionPath.toString(),
539
+ sourceLocation,
540
+ isNegated: true,
541
+ },
542
+ ]
543
+ : []),
544
+ ];
545
+ // Handle whenTrue branch (condition is truthy)
546
+ if (ts.isJsxElement(whenTrue) || ts.isJsxSelfClosingElement(whenTrue)) {
547
+ const componentName = getComponentNameFromJsx(whenTrue);
548
+ if (componentName) {
549
+ // Fix 32: Add ALL conditions (parent + ternary) as gating conditions
550
+ for (const condition of whenTrueConditions) {
551
+ context.addChildBoundaryGatingCondition(componentName, {
552
+ path: condition.path,
553
+ conditionType: 'truthiness',
554
+ location: 'ternary',
555
+ sourceLocation: condition.sourceLocation,
556
+ controlsJsxRendering: true,
557
+ isNegated: condition.isNegated,
558
+ });
559
+ }
560
+ }
561
+ }
562
+ if (ts.isJsxElement(whenTrue) ||
563
+ ts.isJsxSelfClosingElement(whenTrue) ||
564
+ ts.isJsxFragment(whenTrue)) {
565
+ extractConditionalsFromJsx(whenTrue, context, whenTrueConditions);
566
+ }
567
+ // Handle whenFalse branch (condition is falsy/negated)
568
+ if (ts.isJsxElement(whenFalse) ||
569
+ ts.isJsxSelfClosingElement(whenFalse)) {
570
+ const componentName = getComponentNameFromJsx(whenFalse);
571
+ if (componentName) {
572
+ // Fix 32: Add ALL conditions (parent + ternary) as gating conditions
573
+ for (const condition of whenFalseConditions) {
574
+ context.addChildBoundaryGatingCondition(componentName, {
575
+ path: condition.path,
576
+ conditionType: 'truthiness',
577
+ location: 'ternary',
578
+ sourceLocation: condition.sourceLocation,
579
+ controlsJsxRendering: true,
580
+ isNegated: condition.isNegated,
581
+ });
582
+ }
583
+ }
584
+ }
585
+ if (ts.isJsxElement(whenFalse) ||
586
+ ts.isJsxSelfClosingElement(whenFalse) ||
587
+ ts.isJsxFragment(whenFalse)) {
588
+ extractConditionalsFromJsx(whenFalse, context, whenFalseConditions);
589
+ }
590
+ // Handle chained ternaries: a ? <A/> : b ? <B/> : <C/>
591
+ // When whenFalse is another ConditionalExpression, recursively process it
592
+ else if (ts.isConditionalExpression(whenFalse)) {
593
+ // Extract conditional usage for the nested ternary's condition
594
+ extractConditionalUsage(whenFalse.condition, context, 'ternary', {
595
+ controlsJsxRendering: true,
596
+ });
597
+ // Get the nested condition path
598
+ const nestedConditionPath = StructuredPath.fromNode(unwrapExpression(whenFalse.condition), context.sourceFile);
599
+ const nestedSourceLocation = getSourceLocation(whenFalse, context.sourceFile);
600
+ const nestedWhenTrue = unwrapExpression(whenFalse.whenTrue);
601
+ const nestedWhenFalse = unwrapExpression(whenFalse.whenFalse);
602
+ // Fix 32: Build conditions for nested whenTrue (parent falsy + nested truthy)
603
+ const nestedWhenTrueConditions = [
604
+ ...whenFalseConditions, // Parent ternary was falsy to get here
605
+ ...(nestedConditionPath
606
+ ? [
607
+ {
608
+ path: nestedConditionPath.toString(),
609
+ sourceLocation: nestedSourceLocation,
610
+ isNegated: false,
611
+ },
612
+ ]
613
+ : []),
614
+ ];
615
+ // Fix 32: Build conditions for nested whenFalse (parent falsy + nested falsy)
616
+ const nestedWhenFalseConditions = [
617
+ ...whenFalseConditions, // Parent ternary was falsy to get here
618
+ ...(nestedConditionPath
619
+ ? [
620
+ {
621
+ path: nestedConditionPath.toString(),
622
+ sourceLocation: nestedSourceLocation,
623
+ isNegated: true,
624
+ },
625
+ ]
626
+ : []),
627
+ ];
628
+ // Handle nested whenTrue branch
629
+ if (ts.isJsxElement(nestedWhenTrue) ||
630
+ ts.isJsxSelfClosingElement(nestedWhenTrue)) {
631
+ const componentName = getComponentNameFromJsx(nestedWhenTrue);
632
+ if (componentName) {
633
+ // Fix 32: Add ALL accumulated conditions
634
+ for (const condition of nestedWhenTrueConditions) {
635
+ context.addChildBoundaryGatingCondition(componentName, {
636
+ path: condition.path,
637
+ conditionType: 'truthiness',
638
+ location: 'ternary',
639
+ sourceLocation: condition.sourceLocation,
640
+ controlsJsxRendering: true,
641
+ isNegated: condition.isNegated,
642
+ });
643
+ }
644
+ }
645
+ }
646
+ if (ts.isJsxElement(nestedWhenTrue) ||
647
+ ts.isJsxSelfClosingElement(nestedWhenTrue) ||
648
+ ts.isJsxFragment(nestedWhenTrue)) {
649
+ extractConditionalsFromJsx(nestedWhenTrue, context, nestedWhenTrueConditions);
650
+ }
651
+ // Handle nested whenFalse branch (this could be another chained ternary or JSX)
652
+ if (ts.isJsxElement(nestedWhenFalse) ||
653
+ ts.isJsxSelfClosingElement(nestedWhenFalse)) {
654
+ const componentName = getComponentNameFromJsx(nestedWhenFalse);
655
+ if (componentName) {
656
+ // Fix 32: Add ALL accumulated conditions
657
+ for (const condition of nestedWhenFalseConditions) {
658
+ context.addChildBoundaryGatingCondition(componentName, {
659
+ path: condition.path,
660
+ conditionType: 'truthiness',
661
+ location: 'ternary',
662
+ sourceLocation: condition.sourceLocation,
663
+ controlsJsxRendering: true,
664
+ isNegated: condition.isNegated,
665
+ });
666
+ }
667
+ }
668
+ }
669
+ if (ts.isJsxElement(nestedWhenFalse) ||
670
+ ts.isJsxSelfClosingElement(nestedWhenFalse) ||
671
+ ts.isJsxFragment(nestedWhenFalse)) {
672
+ extractConditionalsFromJsx(nestedWhenFalse, context, nestedWhenFalseConditions);
673
+ }
674
+ // If nestedWhenFalse is yet another ConditionalExpression, the recursion
675
+ // will handle it on the next iteration when this function processes it
676
+ else if (ts.isConditionalExpression(nestedWhenFalse)) {
677
+ // Recursively handle deeper nesting by wrapping in a synthetic process
678
+ // We create a fake JsxExpression context to reuse the same logic
679
+ const syntheticChild = {
680
+ kind: ts.SyntaxKind.JsxExpression,
681
+ expression: nestedWhenFalse,
682
+ };
683
+ // Process via the main JSX expression handler by recursing
684
+ // For now, just extract conditionals directly
685
+ extractConditionalUsage(nestedWhenFalse.condition, context, 'ternary', { controlsJsxRendering: true });
686
+ }
687
+ }
688
+ }
689
+ }
690
+ // Recursively process nested JSX elements - Fix 32: pass parent conditions
691
+ else if (ts.isJsxElement(child)) {
692
+ // Check if this is a user-defined component (vs intrinsic element like div)
693
+ // If it's a component AND there are parent conditions, record the gating conditions
694
+ const componentName = getComponentNameFromJsx(child);
695
+ if (componentName && parentConditions.length > 0) {
696
+ for (const condition of parentConditions) {
697
+ context.addChildBoundaryGatingCondition(componentName, {
698
+ path: condition.path,
699
+ conditionType: 'truthiness',
700
+ location: 'ternary',
701
+ sourceLocation: condition.sourceLocation,
702
+ controlsJsxRendering: true,
703
+ isNegated: condition.isNegated,
704
+ });
705
+ }
706
+ }
707
+ extractConditionalsFromJsx(child, context, parentConditions);
708
+ }
709
+ // Handle self-closing JSX elements (e.g., <ScenarioViewer />)
710
+ else if (ts.isJsxSelfClosingElement(child)) {
711
+ // Check if this is a user-defined component (vs intrinsic element like div)
712
+ // If it's a component AND there are parent conditions, record the gating conditions
713
+ const componentName = getComponentNameFromJsx(child);
714
+ if (componentName && parentConditions.length > 0) {
715
+ for (const condition of parentConditions) {
716
+ context.addChildBoundaryGatingCondition(componentName, {
717
+ path: condition.path,
718
+ conditionType: 'truthiness',
719
+ location: 'ternary',
720
+ sourceLocation: condition.sourceLocation,
721
+ controlsJsxRendering: true,
722
+ isNegated: condition.isNegated,
723
+ });
724
+ }
725
+ }
726
+ // Self-closing elements have no children, so no recursion needed
727
+ }
728
+ // Recursively process nested JSX fragments - Fix 32: pass parent conditions
729
+ else if (ts.isJsxFragment(child)) {
730
+ extractConditionalsFromJsx(child, context, parentConditions);
731
+ }
732
+ }
733
+ }
734
+ /**
735
+ * Extracts conditional usages from a condition expression for key attribute detection.
736
+ * This function identifies which attributes are used in conditionals and how they're used.
737
+ * It also tracks compound conditionals (&&-chains) where all conditions must be true together.
738
+ *
739
+ * @param condition The condition expression to analyze
740
+ * @param context The analysis context
741
+ * @param location Where this condition appears (if, ternary, logical-and, switch)
742
+ * @param options Additional options including controlsJsxRendering flag
743
+ */
744
+ export function extractConditionalUsage(condition, context, location, options = {}) {
745
+ const { controlsJsxRendering } = options;
746
+ // Internal recursive function with chain tracking
747
+ function extractWithChainTracking(expr, chainInfo, isNegated) {
748
+ const unwrapped = unwrapExpression(expr);
749
+ // Handle binary expressions with && (logical AND chains)
750
+ // Example: `a && b && <Component />` - both a and b are conditional checks
751
+ if (ts.isBinaryExpression(unwrapped) &&
752
+ unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
753
+ // Track if we're creating the chain at this level (root of the chain)
754
+ const isChainRoot = !chainInfo;
755
+ // If no chainInfo, this is the root of a new chain
756
+ if (isChainRoot) {
757
+ const chainLength = countConditionsInAndChain(unwrapped);
758
+ // Only create chain tracking for chains with 2+ conditions
759
+ if (chainLength >= 2) {
760
+ const chainId = `chain_${crypto.randomUUID().slice(0, 8)}`;
761
+ const chainExpression = unwrapped.getText(context.sourceFile);
762
+ const compound = {
763
+ chainId,
764
+ expression: chainExpression.length > 200
765
+ ? chainExpression.slice(0, 200) + '...'
766
+ : chainExpression,
767
+ conditions: [],
768
+ location,
769
+ sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
770
+ controlsJsxRendering,
771
+ };
772
+ chainInfo = {
773
+ chainId,
774
+ chainLength,
775
+ chainExpression: compound.expression,
776
+ currentPosition: 0,
777
+ compound,
778
+ };
779
+ }
780
+ }
781
+ // Recursively process left side
782
+ extractWithChainTracking(unwrapped.left, chainInfo, false);
783
+ // Process right side if it's not JSX (JSX is the consequence, not the condition)
784
+ const rightUnwrapped = unwrapExpression(unwrapped.right);
785
+ const isJsxConsequence = ts.isJsxElement(rightUnwrapped) ||
786
+ ts.isJsxSelfClosingElement(rightUnwrapped) ||
787
+ ts.isJsxFragment(rightUnwrapped);
788
+ if (!isJsxConsequence) {
789
+ extractWithChainTracking(unwrapped.right, chainInfo, false);
790
+ }
791
+ // If this is the root of the chain, register the compound conditional
792
+ if (isChainRoot && chainInfo) {
793
+ context.addCompoundConditional(chainInfo.compound);
794
+ }
133
795
  return;
134
796
  }
135
- // Check if right is a variable and left is a literal
136
- if (rightPath && isLiteralExpression(unwrapped.left)) {
137
- const literalValue = getLiteralValue(unwrapped.left, context);
138
- context.addConditionalUsage({
139
- path: rightPath.toLeftHandSideString(),
140
- conditionType: 'comparison',
141
- comparedValues: literalValue !== undefined ? [literalValue] : undefined,
142
- location,
143
- });
797
+ // Handle binary expressions with || (logical OR)
798
+ // When OR is inside an && chain, we need to continue chain tracking
799
+ // and mark conditions as OR alternatives
800
+ if (ts.isBinaryExpression(unwrapped) &&
801
+ unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
802
+ if (chainInfo) {
803
+ // We're inside an && chain - continue tracking but mark as OR alternatives
804
+ // Generate an orGroupId so conditions from both sides can be grouped
805
+ const orGroupId = chainInfo.currentOrGroupId ?? `or_${crypto.randomUUID().slice(0, 8)}`;
806
+ // Process left side with OR group tracking
807
+ const leftChainInfo = {
808
+ ...chainInfo,
809
+ currentOrGroupId: orGroupId,
810
+ };
811
+ extractWithChainTracking(unwrapped.left, leftChainInfo, false);
812
+ // Process right side with same OR group
813
+ // Note: we use leftChainInfo's currentPosition which may have been updated
814
+ const rightChainInfo = {
815
+ ...leftChainInfo,
816
+ currentPosition: chainInfo.currentPosition,
817
+ };
818
+ extractWithChainTracking(unwrapped.right, rightChainInfo, false);
819
+ }
820
+ else {
821
+ // Not inside a chain - OR breaks into independent conditional checks
822
+ extractWithChainTracking(unwrapped.left, null, false);
823
+ extractWithChainTracking(unwrapped.right, null, false);
824
+ }
144
825
  return;
145
826
  }
146
- // Both sides are variables - record both as comparisons without specific values
147
- if (leftPath) {
148
- context.addConditionalUsage({
149
- path: leftPath.toLeftHandSideString(),
150
- conditionType: 'comparison',
151
- location,
152
- });
827
+ // Handle comparison operators (===, !==, <, >, <=, >=)
828
+ // Example: `if (status === 'active')` - status is compared against 'active'
829
+ if (ts.isBinaryExpression(unwrapped) &&
830
+ isComparisonOperator(unwrapped.operatorToken.kind)) {
831
+ // Try to extract the variable and the compared value
832
+ const leftPath = StructuredPath.fromNode(unwrapped.left, context.sourceFile);
833
+ const rightPath = StructuredPath.fromNode(unwrapped.right, context.sourceFile);
834
+ // Determine the compared value for computing requiredValue
835
+ const getRequiredValue = (literalValue, isNegatedComparison) => {
836
+ if (literalValue === undefined)
837
+ return undefined;
838
+ // For !== comparisons, the condition is true when NOT equal to the value
839
+ // For === comparisons, the condition is true when equal to the value
840
+ const isNotEqual = unwrapped.operatorToken.kind ===
841
+ ts.SyntaxKind.ExclamationEqualsEqualsToken ||
842
+ unwrapped.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
843
+ if (isNotEqual) {
844
+ // !== 'value' means requiredValue is NOT 'value', but we express this as "not 'value'"
845
+ return `not ${literalValue}`;
846
+ }
847
+ return literalValue;
848
+ };
849
+ // Helper to add a condition
850
+ const addCondition = (path, conditionType, comparedValues, requiredValue, sourceExpr) => {
851
+ const usage = {
852
+ path,
853
+ conditionType,
854
+ comparedValues,
855
+ location,
856
+ sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
857
+ isNegated,
858
+ controlsJsxRendering,
859
+ };
860
+ // Check for inline array-derived patterns (.length) on the source expression
861
+ if (sourceExpr) {
862
+ const arrayDerived = detectArrayDerivedPattern(sourceExpr);
863
+ if (arrayDerived) {
864
+ usage.derivedFrom = {
865
+ operation: arrayDerived.operation,
866
+ sourcePath: arrayDerived.sourcePath,
867
+ };
868
+ }
869
+ }
870
+ // Add chain info if part of a compound conditional
871
+ if (chainInfo) {
872
+ usage.chainId = chainInfo.chainId;
873
+ usage.chainPosition = chainInfo.currentPosition;
874
+ usage.chainLength = chainInfo.chainLength;
875
+ usage.chainExpression = chainInfo.chainExpression;
876
+ chainInfo.currentPosition++;
877
+ // Add to compound conditional conditions
878
+ chainInfo.compound.conditions.push({
879
+ path,
880
+ conditionType,
881
+ comparedValues,
882
+ isNegated,
883
+ requiredValue,
884
+ ...(chainInfo.currentOrGroupId && {
885
+ orGroupId: chainInfo.currentOrGroupId,
886
+ }),
887
+ });
888
+ }
889
+ context.addConditionalUsage(usage);
890
+ };
891
+ // Check if left is a variable and right is a literal
892
+ if (leftPath && isLiteralExpression(unwrapped.right)) {
893
+ const literalValue = getLiteralValue(unwrapped.right, context);
894
+ addCondition(leftPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.left);
895
+ return;
896
+ }
897
+ // Check if right is a variable and left is a literal
898
+ if (rightPath && isLiteralExpression(unwrapped.left)) {
899
+ const literalValue = getLiteralValue(unwrapped.left, context);
900
+ addCondition(rightPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.right);
901
+ return;
902
+ }
903
+ // Both sides are variables - record both as comparisons without specific values
904
+ if (leftPath) {
905
+ addCondition(leftPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.left);
906
+ }
907
+ if (rightPath) {
908
+ addCondition(rightPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.right);
909
+ }
910
+ return;
911
+ }
912
+ // Handle prefix unary NOT expression: !variable
913
+ // Example: `if (!isVisible)` - isVisible is a truthiness check (negated)
914
+ if (ts.isPrefixUnaryExpression(unwrapped) &&
915
+ unwrapped.operator === ts.SyntaxKind.ExclamationToken) {
916
+ extractWithChainTracking(unwrapped.operand, chainInfo, !isNegated);
917
+ return;
153
918
  }
154
- if (rightPath) {
155
- context.addConditionalUsage({
156
- path: rightPath.toLeftHandSideString(),
157
- conditionType: 'comparison',
919
+ // Handle simple identifiers or property accesses (truthiness checks)
920
+ // Example: `if (x)` or `x && <JSX />` - x is checked for truthiness
921
+ const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
922
+ if (path && !path.isLiteral()) {
923
+ const pathStr = path.toLeftHandSideString();
924
+ const usage = {
925
+ path: pathStr,
926
+ conditionType: 'truthiness',
158
927
  location,
159
- });
928
+ sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
929
+ isNegated,
930
+ controlsJsxRendering,
931
+ };
932
+ // Check for inline array-derived patterns (.some(), .every(), .includes(), .length)
933
+ // This populates derivedFrom so downstream code can resolve to the base array path
934
+ const arrayDerived = detectArrayDerivedPattern(unwrapped);
935
+ if (arrayDerived) {
936
+ usage.derivedFrom = {
937
+ operation: arrayDerived.operation,
938
+ sourcePath: arrayDerived.sourcePath,
939
+ };
940
+ }
941
+ // Add chain info if part of a compound conditional
942
+ if (chainInfo) {
943
+ usage.chainId = chainInfo.chainId;
944
+ usage.chainPosition = chainInfo.currentPosition;
945
+ usage.chainLength = chainInfo.chainLength;
946
+ usage.chainExpression = chainInfo.chainExpression;
947
+ chainInfo.currentPosition++;
948
+ // Add to compound conditional conditions
949
+ // For truthiness, requiredValue is true if not negated, false if negated
950
+ chainInfo.compound.conditions.push({
951
+ path: pathStr,
952
+ conditionType: 'truthiness',
953
+ isNegated,
954
+ requiredValue: !isNegated,
955
+ ...(chainInfo.currentOrGroupId && {
956
+ orGroupId: chainInfo.currentOrGroupId,
957
+ }),
958
+ });
959
+ }
960
+ context.addConditionalUsage(usage);
160
961
  }
161
- return;
162
- }
163
- // Handle prefix unary NOT expression: !variable
164
- // Example: `if (!isVisible)` - isVisible is a truthiness check
165
- if (ts.isPrefixUnaryExpression(unwrapped) &&
166
- unwrapped.operator === ts.SyntaxKind.ExclamationToken) {
167
- extractConditionalUsage(unwrapped.operand, context, location);
168
- return;
169
- }
170
- // Handle simple identifiers or property accesses (truthiness checks)
171
- // Example: `if (x)` or `x && <JSX />` - x is checked for truthiness
172
- const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
173
- if (path && !path.isLiteral()) {
174
- context.addConditionalUsage({
175
- path: path.toLeftHandSideString(),
176
- conditionType: 'truthiness',
177
- location,
178
- });
179
962
  }
963
+ // Start extraction with no chain info
964
+ extractWithChainTracking(condition, null, false);
180
965
  }
181
966
  /**
182
967
  * Helper to check if an expression is a literal value
@@ -254,7 +1039,24 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
254
1039
  unwrappedNode.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
255
1040
  markConditionVariablesAsNullable(unwrappedNode, context);
256
1041
  // Extract conditional usages for key attribute detection
257
- extractConditionalUsage(unwrappedNode, context, 'logical-and');
1042
+ // Only call from the OUTERMOST && expression to avoid duplicates
1043
+ // Check if parent is also a && (meaning we're nested)
1044
+ const parent = unwrappedNode.parent;
1045
+ const parentIsAndChain = parent &&
1046
+ ts.isBinaryExpression(parent) &&
1047
+ parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken;
1048
+ if (!parentIsAndChain) {
1049
+ extractConditionalUsage(unwrappedNode, context, 'logical-and');
1050
+ }
1051
+ }
1052
+ // CRITICAL: Extract conditionals from JSX BEFORE checking child boundaries
1053
+ // JSX elements are NOT scopes - their expressions use variables from the parent scope.
1054
+ // Even if the JSX element is within a child boundary (e.g., because it contains callbacks),
1055
+ // we must still extract conditionals from JSX expression children like {x && <div>...</div>}
1056
+ if (ts.isJsxElement(unwrappedNode) ||
1057
+ ts.isJsxSelfClosingElement(unwrappedNode) ||
1058
+ ts.isJsxFragment(unwrappedNode)) {
1059
+ extractConditionalsFromJsx(unwrappedNode, context);
258
1060
  }
259
1061
  // If the node falls within an excluded child scope, stop processing it.
260
1062
  if (context.isChildBoundary(node)) {
@@ -386,7 +1188,8 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
386
1188
  const propertyPath = objectPath.withProperty(unwrappedNode.name.text);
387
1189
  // Check if this is an environment variable access
388
1190
  const fullText = unwrappedNode.getText(context.sourceFile);
389
- if (fullText.includes('.env.') // simple heuristic for env var access but not great
1191
+ if (fullText.includes('.env.') || // process.env.X, window.env.X
1192
+ isEnvStoreAccess(fullText) // env.X where env is likely an env config object
390
1193
  ) {
391
1194
  context.addEnvironmentVariable(fullText);
392
1195
  }
@@ -610,6 +1413,13 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
610
1413
  // e.g., `const tab = segments[0] || 'default'` should trace tab back to segments[0]
611
1414
  if (operatorKind === ts.SyntaxKind.QuestionQuestionToken) {
612
1415
  // specifically for ?? we create an equivalence to the left side
1416
+ // IMPORTANT: Also process the left side recursively to apply method semantics
1417
+ // (e.g., for `const segments = splat?.split('/') ?? []`, we need split semantics)
1418
+ processExpression({
1419
+ node: unwrappedNode.left,
1420
+ context,
1421
+ // Don't pass targetPath here - we'll establish equivalence separately below
1422
+ });
613
1423
  if (targetPath) {
614
1424
  resultPath = StructuredPath.fromNode(unwrappedNode.left, context.sourceFile);
615
1425
  }
@@ -620,12 +1430,28 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
620
1430
  }
621
1431
  }
622
1432
  else if (operatorKind === ts.SyntaxKind.BarBarToken) {
623
- // For ||, also create an equivalence to the left side
1433
+ // For ||, create equivalences to BOTH sides
624
1434
  // This enables data flow tracing through fallback expressions
1435
+ // e.g., `const item = items.find(...) || null` should trace to both:
1436
+ // - items[] (from the find result)
1437
+ // - null (from the fallback)
625
1438
  if (targetPath) {
1439
+ // Process left side recursively to capture its full equivalency chain
1440
+ processExpression({
1441
+ node: unwrappedNode.left,
1442
+ context,
1443
+ targetPath,
1444
+ });
1445
+ // Process right side recursively for completeness
1446
+ processExpression({
1447
+ node: unwrappedNode.right,
1448
+ context,
1449
+ targetPath,
1450
+ });
1451
+ // Set resultPath to left side for type inference
626
1452
  resultPath = StructuredPath.fromNode(unwrappedNode.left, context.sourceFile);
627
1453
  }
628
- // Note: Unlike ??, we don't set targetPath when there's no target
1454
+ // Note: When there's no targetPath, we don't recursively process
629
1455
  // because || is often used in boolean contexts where the full expression matters
630
1456
  }
631
1457
  }
@@ -666,9 +1492,10 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
666
1492
  context.markUnsupported(unwrappedNode.expression, `processExpression: Couldn't get path for called expression: ${ts.SyntaxKind[unwrappedNode.expression.kind]}`, false);
667
1493
  return false;
668
1494
  }
669
- // Construct empty arguments list just to get the call path
670
- // We'll process each argument with its parameter path as targetPath
671
- const callPath = StructuredPath.fromNode(unwrappedNode, context.sourceFile);
1495
+ // Build call path using original source text for consistent schema paths.
1496
+ // IMPORTANT: Never use cyScope names in call paths - they are internal identifiers
1497
+ // that should not appear in schema paths or call signatures.
1498
+ const callPath = buildCallPathFromSource(unwrappedNode, context);
672
1499
  // 2. Process all arguments recursively WITH targetPath for proper equivalence
673
1500
  for (let i = 0; i < unwrappedNode.arguments.length; i++) {
674
1501
  const arg = unwrappedNode.arguments[i];
@@ -798,6 +1625,12 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
798
1625
  }
799
1626
  // Create a path for this property within the base
800
1627
  const propPath = targetPath.withProperty(propName);
1628
+ // Handle child boundaries (callback functions) in object properties
1629
+ // This establishes equivalency between the property path and the child scope
1630
+ // e.g., columns[0].renderCell → cyScope1()
1631
+ if (context.isChildBoundary(property.initializer)) {
1632
+ context.addChildBoundaryEquivalence(propPath, property.initializer);
1633
+ }
801
1634
  // Process the property value with propPath as targetPath
802
1635
  // This allows nested object literals to work correctly
803
1636
  processExpression({
@@ -1032,14 +1865,24 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
1032
1865
  markConditionVariablesAsNullable(unwrappedNode.condition, context);
1033
1866
  // Extract conditional usages for key attribute detection
1034
1867
  extractConditionalUsage(unwrappedNode.condition, context, 'ternary');
1868
+ // Extract conditional effects (setter calls in ternary branches)
1869
+ const knownSetters = findUseStateSetters(context.sourceFile);
1870
+ const effects = extractConditionalEffectsFromTernary(unwrappedNode, context, knownSetters);
1871
+ for (const effect of effects) {
1872
+ context.addConditionalEffect(effect);
1873
+ }
1035
1874
  // Process all parts recursively
1036
1875
  processExpression({
1037
1876
  node: unwrappedNode.condition,
1038
1877
  context,
1039
1878
  typeHint: 'boolean | unknown',
1040
1879
  }); //TODO: could we capture that this is evidence of a boolean type?
1041
- processExpression({ node: unwrappedNode.whenTrue, context });
1042
- processExpression({ node: unwrappedNode.whenFalse, context });
1880
+ // Process both branches WITH targetPath to establish equivalencies
1881
+ // This is critical for tracing nested properties through ternary assignments
1882
+ // e.g., const items = condition ? arr1 : arr2; items.map(i => i.prop)
1883
+ // We need items to be equivalent to both arr1 AND arr2 for proper tracing
1884
+ processExpression({ node: unwrappedNode.whenTrue, context, targetPath });
1885
+ processExpression({ node: unwrappedNode.whenFalse, context, targetPath });
1043
1886
  // Create a path for the whole expression
1044
1887
  const expressionSourcePath = nodeToSource(unwrappedNode, context.sourceFile);
1045
1888
  // Infer type based on branches
@@ -1054,10 +1897,22 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
1054
1897
  }
1055
1898
  // Register type for the expression
1056
1899
  context.addType(expressionSourcePath, resultType);
1057
- // If targetPath is provided, establish equivalence and register type
1900
+ // If targetPath is provided, only register type (don't overwrite branch equivalencies)
1901
+ // The equivalencies to individual branches (set above) are more useful for tracing
1902
+ // than an equivalency to the entire ternary expression text
1058
1903
  if (targetPath) {
1059
- context.addEquivalence(targetPath, expressionSourcePath);
1060
- context.addType(targetPath, resultType);
1904
+ // NOTE: We intentionally do NOT add equivalence here.
1905
+ // The branch processing above already added equivalencies:
1906
+ // targetPath -> whenTrue branch
1907
+ // targetPath -> whenFalse branch
1908
+ // Adding an equivalence to expressionSourcePath would overwrite those
1909
+ // with a useless equivalence to the ternary text itself.
1910
+ //
1911
+ // Use updateSchemaType instead of addType because:
1912
+ // 1. Branch processing may have already set a type on targetPath
1913
+ // 2. addType has a guard that prevents overwriting specific types with 'unknown'
1914
+ // 3. updateSchemaType bypasses this guard, ensuring the ternary's computed type is used
1915
+ context.updateSchemaType(targetPath, resultType);
1061
1916
  }
1062
1917
  return true;
1063
1918
  }
@@ -1618,6 +2473,9 @@ function processJsxAttribute(attr, context, componentPath, targetPath) {
1618
2473
  if (ts.isJsxExpression(attr.initializer) && attr.initializer.expression) {
1619
2474
  const expression = attr.initializer.expression;
1620
2475
  if (context.isChildBoundary(expression)) {
2476
+ // Create equivalency between attribute path and child scope
2477
+ // e.g., Grid().signature[0].renderRow → cyScope1()
2478
+ context.addChildBoundaryEquivalence(attributePath, expression);
1621
2479
  return true;
1622
2480
  }
1623
2481
  // Process the expression with attributePath as targetPath