@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.27d5a59

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 (898) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +26 -26
  4. package/analyzer-template/packages/ai/index.ts +16 -2
  5. package/analyzer-template/packages/ai/package.json +3 -3
  6. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +110 -52
  7. package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
  8. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +132 -12
  9. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +139 -23
  10. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
  11. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +6 -126
  12. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +656 -28
  13. package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
  14. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +94 -7
  15. package/analyzer-template/packages/ai/src/lib/completionCall.ts +229 -64
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +1358 -254
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +5 -1
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +205 -0
  19. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +10 -2
  20. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
  21. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
  22. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +54 -3
  23. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +124 -17
  24. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
  25. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coercePrimitivesToArraysBySchema.ts +62 -0
  26. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +140 -14
  27. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +179 -0
  28. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
  29. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +393 -97
  30. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
  31. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
  32. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +183 -0
  33. package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
  34. package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
  35. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +58 -3
  36. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +1012 -7
  37. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
  38. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +515 -6
  39. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
  40. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1540 -75
  41. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
  42. package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +51 -3
  43. package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
  44. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
  45. package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
  46. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
  47. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
  48. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
  49. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +44 -7
  50. package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
  51. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
  52. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
  53. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
  54. package/analyzer-template/packages/analyze/index.ts +2 -0
  55. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
  56. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +132 -33
  57. package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
  58. package/analyzer-template/packages/analyze/src/lib/asts/index.ts +7 -2
  59. package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
  60. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
  61. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
  62. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
  63. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
  64. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
  65. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
  66. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +99 -22
  67. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +27 -4
  68. package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +12 -0
  69. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
  70. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
  71. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
  72. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
  73. package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1352 -0
  74. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +193 -76
  75. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +87 -25
  76. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +352 -22
  77. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
  78. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +667 -74
  79. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
  80. package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
  81. package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
  82. package/analyzer-template/packages/analyze/src/lib/index.ts +1 -0
  83. package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
  84. package/analyzer-template/packages/aws/package.json +10 -10
  85. package/analyzer-template/packages/database/index.ts +1 -0
  86. package/analyzer-template/packages/database/package.json +4 -4
  87. package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
  88. package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
  89. package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
  90. package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
  91. package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
  92. package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
  93. package/analyzer-template/packages/database/src/lib/kysely/db.ts +22 -1
  94. package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
  95. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  96. package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +62 -0
  97. package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
  98. package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
  99. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
  100. package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
  101. package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
  102. package/analyzer-template/packages/database/src/lib/loadCommits.ts +58 -19
  103. package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
  104. package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
  105. package/analyzer-template/packages/database/src/lib/loadReadyToBeCapturedAnalyses.ts +0 -5
  106. package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
  107. package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
  108. package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
  109. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +153 -144
  110. package/analyzer-template/packages/database/src/lib/updateFreshAnalysisStatus.ts +58 -42
  111. package/analyzer-template/packages/database/src/lib/updateFreshAnalysisStatusWithScenarios.ts +81 -65
  112. package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
  113. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.ts +29 -1
  114. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +33 -5
  115. package/analyzer-template/packages/github/dist/database/index.d.ts +1 -0
  116. package/analyzer-template/packages/github/dist/database/index.d.ts.map +1 -1
  117. package/analyzer-template/packages/github/dist/database/index.js +1 -0
  118. package/analyzer-template/packages/github/dist/database/index.js.map +1 -1
  119. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
  120. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
  121. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
  122. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
  123. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
  124. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
  125. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
  126. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
  127. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
  128. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
  129. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
  130. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
  131. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +4 -0
  132. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  133. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +16 -1
  134. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  135. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  136. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
  137. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
  138. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
  139. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  140. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  141. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +20 -0
  142. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -0
  143. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +45 -0
  144. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -0
  145. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
  146. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
  147. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  148. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  149. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts +5 -0
  150. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.map +1 -1
  151. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
  152. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
  153. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
  154. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
  155. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  156. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
  157. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  158. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
  159. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
  160. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
  161. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
  162. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
  163. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
  164. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
  165. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +45 -14
  166. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
  167. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
  168. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  169. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
  170. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  171. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
  172. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
  173. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
  174. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.d.ts.map +1 -1
  175. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js +1 -4
  176. package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
  177. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
  178. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
  179. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
  180. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
  181. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
  182. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
  183. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
  184. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  185. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +100 -88
  186. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  187. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatus.d.ts.map +1 -1
  188. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatus.js +41 -30
  189. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatus.js.map +1 -1
  190. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatusWithScenarios.d.ts.map +1 -1
  191. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatusWithScenarios.js +68 -57
  192. package/analyzer-template/packages/github/dist/database/src/lib/updateFreshAnalysisStatusWithScenarios.js.map +1 -1
  193. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts.map +1 -1
  194. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +29 -1
  195. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -1
  196. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
  197. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +33 -5
  198. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  199. package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
  200. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  201. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  202. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
  203. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  204. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
  205. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
  206. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +8 -0
  207. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  208. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts +10 -0
  209. package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
  210. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  211. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  212. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  213. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  214. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
  215. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  216. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
  217. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
  218. package/analyzer-template/packages/github/package.json +2 -2
  219. package/analyzer-template/packages/types/index.ts +1 -0
  220. package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
  221. package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
  222. package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +8 -0
  223. package/analyzer-template/packages/types/src/types/Scenario.ts +10 -0
  224. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
  225. package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
  226. package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
  227. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  228. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  229. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
  230. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  231. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
  232. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
  233. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +8 -0
  234. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  235. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts +10 -0
  236. package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
  237. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  238. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  239. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  240. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  241. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  242. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +98 -3
  243. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  244. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
  245. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  246. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
  247. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
  248. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +121 -3
  249. package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
  250. package/analyzer-template/playwright/capture.ts +20 -8
  251. package/analyzer-template/playwright/captureFromUrl.ts +89 -82
  252. package/analyzer-template/playwright/captureStatic.ts +1 -1
  253. package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
  254. package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
  255. package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
  256. package/analyzer-template/project/constructMockCode.ts +572 -87
  257. package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
  258. package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
  259. package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
  260. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
  261. package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
  262. package/analyzer-template/project/orchestrateCapture.ts +75 -7
  263. package/analyzer-template/project/reconcileMockDataKeys.ts +158 -10
  264. package/analyzer-template/project/runAnalysis.ts +4 -0
  265. package/analyzer-template/project/start.ts +38 -11
  266. package/analyzer-template/project/startScenarioCapture.ts +9 -0
  267. package/analyzer-template/project/writeClientLogRoute.ts +125 -0
  268. package/analyzer-template/project/writeMockDataTsx.ts +312 -10
  269. package/analyzer-template/project/writeScenarioComponents.ts +271 -37
  270. package/analyzer-template/project/writeSimpleRoot.ts +21 -11
  271. package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
  272. package/analyzer-template/tsconfig.json +13 -1
  273. package/background/src/lib/local/createLocalAnalyzer.js +1 -1
  274. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  275. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
  276. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
  277. package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
  278. package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
  279. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
  280. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
  281. package/background/src/lib/virtualized/project/constructMockCode.js +474 -48
  282. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  283. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
  284. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
  285. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
  286. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
  287. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
  288. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
  289. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
  290. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  291. package/background/src/lib/virtualized/project/orchestrateCapture.js +62 -7
  292. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  293. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +133 -10
  294. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  295. package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
  296. package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
  297. package/background/src/lib/virtualized/project/start.js +34 -11
  298. package/background/src/lib/virtualized/project/start.js.map +1 -1
  299. package/background/src/lib/virtualized/project/startScenarioCapture.js +5 -0
  300. package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
  301. package/background/src/lib/virtualized/project/writeClientLogRoute.js +110 -0
  302. package/background/src/lib/virtualized/project/writeClientLogRoute.js.map +1 -0
  303. package/background/src/lib/virtualized/project/writeMockDataTsx.js +263 -6
  304. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  305. package/background/src/lib/virtualized/project/writeScenarioComponents.js +200 -35
  306. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  307. package/background/src/lib/virtualized/project/writeSimpleRoot.js +21 -11
  308. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  309. package/codeyam-cli/scripts/apply-setup.js +386 -9
  310. package/codeyam-cli/scripts/apply-setup.js.map +1 -1
  311. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js +196 -0
  312. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js.map +1 -0
  313. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js +114 -0
  314. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js.map +1 -0
  315. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js +149 -0
  316. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js.map +1 -0
  317. package/codeyam-cli/src/cli.js +35 -24
  318. package/codeyam-cli/src/cli.js.map +1 -1
  319. package/codeyam-cli/src/codeyam-cli.js +18 -2
  320. package/codeyam-cli/src/codeyam-cli.js.map +1 -1
  321. package/codeyam-cli/src/commands/analyze.js +21 -9
  322. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  323. package/codeyam-cli/src/commands/baseline.js +2 -0
  324. package/codeyam-cli/src/commands/baseline.js.map +1 -1
  325. package/codeyam-cli/src/commands/debug.js +9 -5
  326. package/codeyam-cli/src/commands/debug.js.map +1 -1
  327. package/codeyam-cli/src/commands/default.js +37 -21
  328. package/codeyam-cli/src/commands/default.js.map +1 -1
  329. package/codeyam-cli/src/commands/editor.js +1982 -0
  330. package/codeyam-cli/src/commands/editor.js.map +1 -0
  331. package/codeyam-cli/src/commands/init.js +81 -260
  332. package/codeyam-cli/src/commands/init.js.map +1 -1
  333. package/codeyam-cli/src/commands/memory.js +278 -0
  334. package/codeyam-cli/src/commands/memory.js.map +1 -0
  335. package/codeyam-cli/src/commands/recapture.js +2 -0
  336. package/codeyam-cli/src/commands/recapture.js.map +1 -1
  337. package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
  338. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  339. package/codeyam-cli/src/commands/setup-simulations.js +284 -0
  340. package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
  341. package/codeyam-cli/src/commands/test-startup.js +2 -0
  342. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  343. package/codeyam-cli/src/commands/verify.js +14 -2
  344. package/codeyam-cli/src/commands/verify.js.map +1 -1
  345. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +246 -0
  346. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -0
  347. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js +126 -0
  348. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js.map +1 -0
  349. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js +295 -0
  350. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js.map +1 -0
  351. package/codeyam-cli/src/utils/__tests__/editorMockState.test.js +270 -0
  352. package/codeyam-cli/src/utils/__tests__/editorMockState.test.js.map +1 -0
  353. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js +100 -0
  354. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js.map +1 -0
  355. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +147 -0
  356. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -0
  357. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +76 -0
  358. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -0
  359. package/codeyam-cli/src/utils/__tests__/git.editor.test.js +134 -0
  360. package/codeyam-cli/src/utils/__tests__/git.editor.test.js.map +1 -0
  361. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +185 -0
  362. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
  363. package/codeyam-cli/src/utils/__tests__/pathIgnoring.test.js +9 -0
  364. package/codeyam-cli/src/utils/__tests__/pathIgnoring.test.js.map +1 -1
  365. package/codeyam-cli/src/utils/__tests__/project.test.js +65 -0
  366. package/codeyam-cli/src/utils/__tests__/project.test.js.map +1 -0
  367. package/codeyam-cli/src/utils/__tests__/scenarioMarkers.test.js +121 -0
  368. package/codeyam-cli/src/utils/__tests__/scenarioMarkers.test.js.map +1 -0
  369. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +154 -82
  370. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  371. package/codeyam-cli/src/utils/analysisRunner.js +21 -2
  372. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  373. package/codeyam-cli/src/utils/analyzer.js +7 -0
  374. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  375. package/codeyam-cli/src/utils/backgroundServer.js +109 -22
  376. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  377. package/codeyam-cli/src/utils/buildFlags.js +4 -0
  378. package/codeyam-cli/src/utils/buildFlags.js.map +1 -0
  379. package/codeyam-cli/src/utils/devModeEvents.js +40 -0
  380. package/codeyam-cli/src/utils/devModeEvents.js.map +1 -0
  381. package/codeyam-cli/src/utils/editorAudit.js +82 -0
  382. package/codeyam-cli/src/utils/editorAudit.js.map +1 -0
  383. package/codeyam-cli/src/utils/editorDevServer.js +98 -0
  384. package/codeyam-cli/src/utils/editorDevServer.js.map +1 -0
  385. package/codeyam-cli/src/utils/editorJournal.js +137 -0
  386. package/codeyam-cli/src/utils/editorJournal.js.map +1 -0
  387. package/codeyam-cli/src/utils/editorMockState.js +248 -0
  388. package/codeyam-cli/src/utils/editorMockState.js.map +1 -0
  389. package/codeyam-cli/src/utils/editorPreloadHelpers.js +64 -0
  390. package/codeyam-cli/src/utils/editorPreloadHelpers.js.map +1 -0
  391. package/codeyam-cli/src/utils/editorPreview.js +66 -0
  392. package/codeyam-cli/src/utils/editorPreview.js.map +1 -0
  393. package/codeyam-cli/src/utils/editorScenarios.js +56 -0
  394. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -0
  395. package/codeyam-cli/src/utils/fileMetadata.js +5 -0
  396. package/codeyam-cli/src/utils/fileMetadata.js.map +1 -1
  397. package/codeyam-cli/src/utils/fileWatcher.js +25 -9
  398. package/codeyam-cli/src/utils/fileWatcher.js.map +1 -1
  399. package/codeyam-cli/src/utils/generateReport.js +2 -2
  400. package/codeyam-cli/src/utils/git.js +103 -0
  401. package/codeyam-cli/src/utils/git.js.map +1 -1
  402. package/codeyam-cli/src/utils/install-skills.js +120 -39
  403. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  404. package/codeyam-cli/src/utils/interactiveSyncWatcher.js +126 -0
  405. package/codeyam-cli/src/utils/interactiveSyncWatcher.js.map +1 -0
  406. package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
  407. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
  408. package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
  409. package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
  410. package/codeyam-cli/src/utils/pathIgnoring.js +19 -7
  411. package/codeyam-cli/src/utils/pathIgnoring.js.map +1 -1
  412. package/codeyam-cli/src/utils/progress.js +7 -0
  413. package/codeyam-cli/src/utils/progress.js.map +1 -1
  414. package/codeyam-cli/src/utils/project.js +15 -5
  415. package/codeyam-cli/src/utils/project.js.map +1 -1
  416. package/codeyam-cli/src/utils/queue/__tests__/heartbeat.test.js +11 -11
  417. package/codeyam-cli/src/utils/queue/__tests__/heartbeat.test.js.map +1 -1
  418. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js +22 -0
  419. package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
  420. package/codeyam-cli/src/utils/queue/heartbeat.js +13 -5
  421. package/codeyam-cli/src/utils/queue/heartbeat.js.map +1 -1
  422. package/codeyam-cli/src/utils/queue/job.js +75 -1
  423. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  424. package/codeyam-cli/src/utils/queue/manager.js +7 -0
  425. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  426. package/codeyam-cli/src/utils/requireSimulations.js +10 -0
  427. package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
  428. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
  429. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
  430. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +229 -0
  431. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
  432. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
  433. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
  434. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
  435. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
  436. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
  437. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
  438. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
  439. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
  440. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +74 -0
  441. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
  442. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +376 -0
  443. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
  444. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +113 -0
  445. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
  446. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
  447. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
  448. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
  449. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
  450. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
  451. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
  452. package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
  453. package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
  454. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
  455. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
  456. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
  457. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
  458. package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
  459. package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
  460. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js +83 -0
  461. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js.map +1 -0
  462. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js +118 -0
  463. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js.map +1 -0
  464. package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js +72 -0
  465. package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js.map +1 -0
  466. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
  467. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
  468. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +76 -0
  469. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -0
  470. package/codeyam-cli/src/utils/rules/index.js +7 -0
  471. package/codeyam-cli/src/utils/rules/index.js.map +1 -0
  472. package/codeyam-cli/src/utils/rules/parser.js +93 -0
  473. package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
  474. package/codeyam-cli/src/utils/rules/pathMatcher.js +49 -0
  475. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
  476. package/codeyam-cli/src/utils/rules/rulePlacement.js +65 -0
  477. package/codeyam-cli/src/utils/rules/rulePlacement.js.map +1 -0
  478. package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
  479. package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
  480. package/codeyam-cli/src/utils/rules/sourceFiles.js +43 -0
  481. package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -0
  482. package/codeyam-cli/src/utils/rules/staleness.js +137 -0
  483. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
  484. package/codeyam-cli/src/utils/scenarioMarkers.js +134 -0
  485. package/codeyam-cli/src/utils/scenarioMarkers.js.map +1 -0
  486. package/codeyam-cli/src/utils/serverState.js +64 -12
  487. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  488. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +61 -41
  489. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  490. package/codeyam-cli/src/utils/simulationGateMiddleware.js +159 -0
  491. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -0
  492. package/codeyam-cli/src/utils/syncMocksMiddleware.js +5 -24
  493. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  494. package/codeyam-cli/src/utils/testRunner.js +158 -0
  495. package/codeyam-cli/src/utils/testRunner.js.map +1 -0
  496. package/codeyam-cli/src/utils/transcriptPruning.js +67 -0
  497. package/codeyam-cli/src/utils/transcriptPruning.js.map +1 -0
  498. package/codeyam-cli/src/utils/versionInfo.js +46 -0
  499. package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
  500. package/codeyam-cli/src/utils/webappDetection.js +14 -2
  501. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  502. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
  503. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
  504. package/codeyam-cli/src/webserver/app/lib/database.js +63 -33
  505. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  506. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  507. package/codeyam-cli/src/webserver/backgroundServer.js +166 -16
  508. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  509. package/codeyam-cli/src/webserver/bootstrap.js +51 -0
  510. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  511. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-DmJveP3T.js +1 -0
  512. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-C76mRRiF.js +11 -0
  513. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-g3saevPb.js} +1 -1
  514. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-CobE682z.js} +1 -1
  515. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-Bu6c6aDe.js +1 -0
  516. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-DYFW3lDD.js} +3 -3
  517. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-DLeucoVX.js} +1 -1
  518. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-BU_OAEMP.js} +1 -1
  519. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-ceAyBX-H.js} +1 -1
  520. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-djPLI-WV.js +11 -0
  521. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-BED4B6sP.js} +1 -1
  522. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-B76aig_2.js} +3 -13
  523. package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bb5uFQ5V.js +34 -0
  524. package/codeyam-cli/src/webserver/build/client/assets/Terminal-nZNBALox.js +41 -0
  525. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-C8OKAR5x.js} +1 -1
  526. package/codeyam-cli/src/webserver/build/client/assets/_index-C96V0n15.js +11 -0
  527. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BpKzcsJz.js +27 -0
  528. package/codeyam-cli/src/webserver/build/client/assets/addon-fit-CUXOrorO.js +1 -0
  529. package/codeyam-cli/src/webserver/build/client/assets/addon-web-links-Duc5hnl7.js +1 -0
  530. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-D9hemwl6.js +22 -0
  531. package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
  532. package/codeyam-cli/src/webserver/build/client/assets/api.dev-mode-events-l0sNRNKZ.js +1 -0
  533. package/codeyam-cli/src/webserver/build/client/assets/api.editor-audit-l0sNRNKZ.js +1 -0
  534. package/codeyam-cli/src/webserver/build/client/assets/api.editor-capture-scenario-l0sNRNKZ.js +1 -0
  535. package/codeyam-cli/src/webserver/build/client/assets/api.editor-client-errors-l0sNRNKZ.js +1 -0
  536. package/codeyam-cli/src/webserver/build/client/assets/api.editor-commit-l0sNRNKZ.js +1 -0
  537. package/codeyam-cli/src/webserver/build/client/assets/api.editor-dev-server-l0sNRNKZ.js +1 -0
  538. package/codeyam-cli/src/webserver/build/client/assets/api.editor-entity-status-l0sNRNKZ.js +1 -0
  539. package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-l0sNRNKZ.js +1 -0
  540. package/codeyam-cli/src/webserver/build/client/assets/api.editor-journal-entry-l0sNRNKZ.js +1 -0
  541. package/codeyam-cli/src/webserver/build/client/assets/api.editor-journal-image._-l0sNRNKZ.js +1 -0
  542. package/codeyam-cli/src/webserver/build/client/assets/api.editor-journal-l0sNRNKZ.js +1 -0
  543. package/codeyam-cli/src/webserver/build/client/assets/api.editor-journal-screenshot-l0sNRNKZ.js +1 -0
  544. package/codeyam-cli/src/webserver/build/client/assets/api.editor-journal-update-l0sNRNKZ.js +1 -0
  545. package/codeyam-cli/src/webserver/build/client/assets/api.editor-load-commit-l0sNRNKZ.js +1 -0
  546. package/codeyam-cli/src/webserver/build/client/assets/api.editor-refresh-l0sNRNKZ.js +1 -0
  547. package/codeyam-cli/src/webserver/build/client/assets/api.editor-register-scenario-l0sNRNKZ.js +1 -0
  548. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-data-l0sNRNKZ.js +1 -0
  549. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-image._-l0sNRNKZ.js +1 -0
  550. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenarios-l0sNRNKZ.js +1 -0
  551. package/codeyam-cli/src/webserver/build/client/assets/api.editor-switch-scenario-l0sNRNKZ.js +1 -0
  552. package/codeyam-cli/src/webserver/build/client/assets/api.editor-test-results-l0sNRNKZ.js +1 -0
  553. package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
  554. package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
  555. package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
  556. package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
  557. package/codeyam-cli/src/webserver/build/client/assets/api.rule-path-l0sNRNKZ.js +1 -0
  558. package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
  559. package/codeyam-cli/src/webserver/build/client/assets/book-open-D_nMCFmP.js +6 -0
  560. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-BH2h1Ea2.js} +1 -1
  561. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-JZWAC4HX-C4pqxYJB.js} +12 -12
  562. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-DyIKORY6.js} +1 -1
  563. package/codeyam-cli/src/webserver/build/client/assets/copy-NDbZjXao.js +11 -0
  564. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-CMT1jU2q.js} +1 -1
  565. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BiM6z3Do.js +1 -0
  566. package/codeyam-cli/src/webserver/build/client/assets/editor-B2KwhQph.js +8 -0
  567. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-CrjR3zZW.js} +12 -12
  568. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-DjACbfdI.js +6 -0
  569. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-C28BiQzt.js +6 -0
  570. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-p9hhkjJM.js +6 -0
  571. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-BMvVHNXU.js} +2 -2
  572. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-DTvKq3TY.js} +1 -1
  573. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-cPo8LiG3.js} +1 -1
  574. package/codeyam-cli/src/webserver/build/client/assets/files-DO4CZ16O.js +1 -0
  575. package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-CFCTYk9I.js} +8 -8
  576. package/codeyam-cli/src/webserver/build/client/assets/globals-B17TBSS6.css +1 -0
  577. package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-10oVnAAH.js} +1 -1
  578. package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-BcvgDzbZ.js} +1 -1
  579. package/codeyam-cli/src/webserver/build/client/assets/labs-Zk7ryIM1.js +1 -0
  580. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-BAXYRVEO.js} +1 -1
  581. package/codeyam-cli/src/webserver/build/client/assets/manifest-af20abcd.js +1 -0
  582. package/codeyam-cli/src/webserver/build/client/assets/memory-Dg0mvYrI.js +96 -0
  583. package/codeyam-cli/src/webserver/build/client/assets/pause-DTAcYxBt.js +11 -0
  584. package/codeyam-cli/src/webserver/build/client/assets/root-DUKqhFlb.js +67 -0
  585. package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-fKo7v0Zo.js} +1 -1
  586. package/codeyam-cli/src/webserver/build/client/assets/settings-DfuTtcJP.js +1 -0
  587. package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-B3aOzpCZ.js} +1 -1
  588. package/codeyam-cli/src/webserver/build/client/assets/terminal-BG4heKCG.js +11 -0
  589. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-DtSmdtM4.js} +1 -1
  590. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-ByhSyh0W.js} +1 -1
  591. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C14nCb1q.js +2 -0
  592. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-O-jkvSPx.js} +1 -1
  593. package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-9FIWuYfK.js} +1 -1
  594. package/codeyam-cli/src/webserver/build/client/assets/xterm-BqvuqXEL.js +27 -0
  595. package/codeyam-cli/src/webserver/build/server/assets/index-D_kZbNJs.js +1 -0
  596. package/codeyam-cli/src/webserver/build/server/assets/server-build-CWy5OIH9.js +366 -0
  597. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  598. package/codeyam-cli/src/webserver/build-info.json +5 -5
  599. package/codeyam-cli/src/webserver/devServer.js +39 -5
  600. package/codeyam-cli/src/webserver/devServer.js.map +1 -1
  601. package/codeyam-cli/src/webserver/editorProxy.js +440 -0
  602. package/codeyam-cli/src/webserver/editorProxy.js.map +1 -0
  603. package/codeyam-cli/src/webserver/scripts/codeyam-preload.mjs +175 -0
  604. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +140 -0
  605. package/codeyam-cli/src/webserver/server.js +226 -1
  606. package/codeyam-cli/src/webserver/server.js.map +1 -1
  607. package/codeyam-cli/src/webserver/terminalServer.js +698 -0
  608. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -0
  609. package/codeyam-cli/templates/codeyam-editor-claude.md +68 -0
  610. package/codeyam-cli/templates/codeyam-memory-hook.sh +199 -0
  611. package/codeyam-cli/templates/commands/codeyam-diagnose.md +481 -0
  612. package/codeyam-cli/templates/editor-step-hook.py +147 -0
  613. package/codeyam-cli/templates/hooks/staleness-check.sh +43 -0
  614. package/codeyam-cli/templates/isolation-route/next-app.tsx.template +80 -0
  615. package/codeyam-cli/templates/isolation-route/next-pages.tsx.template +79 -0
  616. package/codeyam-cli/templates/isolation-route/vite-react.tsx.template +78 -0
  617. package/codeyam-cli/templates/msw/browser-setup.ts.template +47 -0
  618. package/codeyam-cli/templates/msw/handler-router.ts.template +47 -0
  619. package/codeyam-cli/templates/msw/server-setup.ts.template +52 -0
  620. package/codeyam-cli/templates/nextjs-prisma-sqlite/PRISMA_SETUP.md +84 -0
  621. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/api/todos/route.ts +17 -0
  622. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/globals.css +26 -0
  623. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/layout.tsx +34 -0
  624. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/lib/prisma.ts +19 -0
  625. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/page.tsx +10 -0
  626. package/codeyam-cli/templates/nextjs-prisma-sqlite/eslint.config.mjs +11 -0
  627. package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +43 -0
  628. package/codeyam-cli/templates/nextjs-prisma-sqlite/next.config.ts +14 -0
  629. package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +35 -0
  630. package/codeyam-cli/templates/nextjs-prisma-sqlite/postcss.config.mjs +7 -0
  631. package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma/schema.prisma +27 -0
  632. package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma/seed.ts +37 -0
  633. package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma.config.ts +12 -0
  634. package/codeyam-cli/templates/nextjs-prisma-sqlite/tsconfig.json +34 -0
  635. package/codeyam-cli/templates/prompts/conversation-guidance.txt +44 -0
  636. package/codeyam-cli/templates/prompts/conversation-prompt.txt +28 -0
  637. package/codeyam-cli/templates/prompts/interruption-prompt.txt +31 -0
  638. package/codeyam-cli/templates/prompts/stale-rules-prompt.txt +24 -0
  639. package/codeyam-cli/templates/rule-notification-hook.py +83 -0
  640. package/codeyam-cli/templates/rule-reflection-hook.py +647 -0
  641. package/codeyam-cli/templates/rules-instructions.md +78 -0
  642. package/codeyam-cli/templates/{codeyam:debug.md → skills/codeyam-debug/SKILL.md} +48 -4
  643. package/codeyam-cli/templates/skills/codeyam-dev-mode/SKILL.md +237 -0
  644. package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +69 -0
  645. package/codeyam-cli/templates/skills/codeyam-memory/SKILL.md +611 -0
  646. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/deprecated-prompt.md +100 -0
  647. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.mjs +139 -0
  648. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.mjs +52 -0
  649. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/misleading-api-prompt.md +117 -0
  650. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/read-json-field.mjs +61 -0
  651. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/ripgrep-fallback.mjs +155 -0
  652. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/analyze-prompt.md +46 -0
  653. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.mjs +13 -0
  654. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter-session.mjs +95 -0
  655. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.mjs +160 -0
  656. package/codeyam-cli/templates/skills/codeyam-new-rule/SKILL.md +11 -0
  657. package/codeyam-cli/templates/{codeyam:setup.md → skills/codeyam-setup/SKILL.md} +13 -1
  658. package/codeyam-cli/templates/{codeyam:sim.md → skills/codeyam-sim/SKILL.md} +1 -1
  659. package/codeyam-cli/templates/{codeyam:test.md → skills/codeyam-test/SKILL.md} +1 -1
  660. package/codeyam-cli/templates/{codeyam:verify.md → skills/codeyam-verify/SKILL.md} +1 -1
  661. package/package.json +27 -22
  662. package/packages/ai/index.js +7 -3
  663. package/packages/ai/index.js.map +1 -1
  664. package/packages/ai/src/lib/analyzeScope.js +91 -30
  665. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  666. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
  667. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
  668. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +100 -12
  669. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  670. package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
  671. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  672. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
  673. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
  674. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
  675. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
  676. package/packages/ai/src/lib/astScopes/processExpression.js +518 -28
  677. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  678. package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
  679. package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
  680. package/packages/ai/src/lib/completionCall.js +171 -37
  681. package/packages/ai/src/lib/completionCall.js.map +1 -1
  682. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +1082 -174
  683. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  684. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +5 -1
  685. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  686. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
  687. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
  688. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
  689. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  690. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
  691. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
  692. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
  693. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
  694. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +52 -3
  695. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  696. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +106 -13
  697. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  698. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
  699. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
  700. package/packages/ai/src/lib/dataStructure/helpers/coercePrimitivesToArraysBySchema.js +54 -0
  701. package/packages/ai/src/lib/dataStructure/helpers/coercePrimitivesToArraysBySchema.js.map +1 -0
  702. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +122 -12
  703. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  704. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +173 -0
  705. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
  706. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
  707. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
  708. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +333 -86
  709. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  710. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
  711. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
  712. package/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.js +34 -0
  713. package/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.js.map +1 -0
  714. package/packages/ai/src/lib/dataStructureChunking.js +130 -0
  715. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
  716. package/packages/ai/src/lib/e2eDataTracking.js +241 -0
  717. package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
  718. package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
  719. package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
  720. package/packages/ai/src/lib/generateEntityDataStructure.js +46 -2
  721. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  722. package/packages/ai/src/lib/generateEntityScenarioData.js +789 -8
  723. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  724. package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
  725. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  726. package/packages/ai/src/lib/generateExecutionFlows.js +376 -4
  727. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  728. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +1124 -59
  729. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  730. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
  731. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
  732. package/packages/ai/src/lib/isolateScopes.js +39 -3
  733. package/packages/ai/src/lib/isolateScopes.js.map +1 -1
  734. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
  735. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
  736. package/packages/ai/src/lib/mergeStatements.js +70 -51
  737. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  738. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
  739. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
  740. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
  741. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  742. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
  743. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
  744. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +30 -7
  745. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  746. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
  747. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
  748. package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
  749. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
  750. package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
  751. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  752. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
  753. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  754. package/packages/analyze/index.js +1 -0
  755. package/packages/analyze/index.js.map +1 -1
  756. package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
  757. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  758. package/packages/analyze/src/lib/ProjectAnalyzer.js +109 -30
  759. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  760. package/packages/analyze/src/lib/analysisContext.js +30 -5
  761. package/packages/analyze/src/lib/analysisContext.js.map +1 -1
  762. package/packages/analyze/src/lib/asts/index.js +4 -2
  763. package/packages/analyze/src/lib/asts/index.js.map +1 -1
  764. package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
  765. package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
  766. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
  767. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
  768. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
  769. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
  770. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
  771. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  772. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
  773. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
  774. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
  775. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
  776. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
  777. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
  778. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +72 -10
  779. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  780. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +24 -4
  781. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  782. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +9 -0
  783. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
  784. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
  785. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  786. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
  787. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  788. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
  789. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  790. package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
  791. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  792. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js +907 -0
  793. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
  794. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +164 -68
  795. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  796. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +75 -21
  797. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  798. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +250 -20
  799. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  800. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
  801. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  802. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +558 -55
  803. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  804. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
  805. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  806. package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
  807. package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
  808. package/packages/analyze/src/lib/index.js +1 -0
  809. package/packages/analyze/src/lib/index.js.map +1 -1
  810. package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
  811. package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
  812. package/packages/database/index.js +1 -0
  813. package/packages/database/index.js.map +1 -1
  814. package/packages/database/src/lib/analysisBranchToDb.js +1 -1
  815. package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
  816. package/packages/database/src/lib/analysisToDb.js +1 -1
  817. package/packages/database/src/lib/analysisToDb.js.map +1 -1
  818. package/packages/database/src/lib/branchToDb.js +1 -1
  819. package/packages/database/src/lib/branchToDb.js.map +1 -1
  820. package/packages/database/src/lib/commitBranchToDb.js +1 -1
  821. package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
  822. package/packages/database/src/lib/commitToDb.js +1 -1
  823. package/packages/database/src/lib/commitToDb.js.map +1 -1
  824. package/packages/database/src/lib/fileToDb.js +1 -1
  825. package/packages/database/src/lib/fileToDb.js.map +1 -1
  826. package/packages/database/src/lib/kysely/db.js +16 -1
  827. package/packages/database/src/lib/kysely/db.js.map +1 -1
  828. package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
  829. package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  830. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +45 -0
  831. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -0
  832. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  833. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  834. package/packages/database/src/lib/loadAnalyses.js +45 -2
  835. package/packages/database/src/lib/loadAnalyses.js.map +1 -1
  836. package/packages/database/src/lib/loadAnalysis.js +8 -0
  837. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  838. package/packages/database/src/lib/loadBranch.js +11 -1
  839. package/packages/database/src/lib/loadBranch.js.map +1 -1
  840. package/packages/database/src/lib/loadCommit.js +7 -0
  841. package/packages/database/src/lib/loadCommit.js.map +1 -1
  842. package/packages/database/src/lib/loadCommits.js +45 -14
  843. package/packages/database/src/lib/loadCommits.js.map +1 -1
  844. package/packages/database/src/lib/loadEntities.js +23 -4
  845. package/packages/database/src/lib/loadEntities.js.map +1 -1
  846. package/packages/database/src/lib/loadEntityBranches.js +9 -0
  847. package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
  848. package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js +1 -4
  849. package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
  850. package/packages/database/src/lib/projectToDb.js +1 -1
  851. package/packages/database/src/lib/projectToDb.js.map +1 -1
  852. package/packages/database/src/lib/saveFiles.js +1 -1
  853. package/packages/database/src/lib/saveFiles.js.map +1 -1
  854. package/packages/database/src/lib/scenarioToDb.js +1 -1
  855. package/packages/database/src/lib/scenarioToDb.js.map +1 -1
  856. package/packages/database/src/lib/updateCommitMetadata.js +100 -88
  857. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  858. package/packages/database/src/lib/updateFreshAnalysisStatus.js +41 -30
  859. package/packages/database/src/lib/updateFreshAnalysisStatus.js.map +1 -1
  860. package/packages/database/src/lib/updateFreshAnalysisStatusWithScenarios.js +68 -57
  861. package/packages/database/src/lib/updateFreshAnalysisStatusWithScenarios.js.map +1 -1
  862. package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +29 -1
  863. package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -1
  864. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +33 -5
  865. package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
  866. package/packages/types/index.js.map +1 -1
  867. package/packages/utils/src/lib/fs/rsyncCopy.js +98 -3
  868. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  869. package/packages/utils/src/lib/safeFileName.js +29 -3
  870. package/packages/utils/src/lib/safeFileName.js.map +1 -1
  871. package/scripts/npm-post-install.cjs +34 -0
  872. package/codeyam-cli/src/commands/detect-universal-mocks.js +0 -118
  873. package/codeyam-cli/src/commands/detect-universal-mocks.js.map +0 -1
  874. package/codeyam-cli/src/commands/list.js +0 -31
  875. package/codeyam-cli/src/commands/list.js.map +0 -1
  876. package/codeyam-cli/src/commands/webapp-info.js +0 -146
  877. package/codeyam-cli/src/commands/webapp-info.js.map +0 -1
  878. package/codeyam-cli/src/utils/universal-mocks.js +0 -152
  879. package/codeyam-cli/src/utils/universal-mocks.js.map +0 -1
  880. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
  881. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-CEleMv_j.js +0 -34
  882. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
  883. package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
  884. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
  885. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
  886. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js +0 -6
  887. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-wDWZZO1W.js +0 -6
  888. package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
  889. package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
  890. package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
  891. package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
  892. package/codeyam-cli/src/webserver/build/client/assets/settings-B2eDuBj8.js +0 -1
  893. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-BUm0UVJm.js +0 -2
  894. package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
  895. package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
  896. package/codeyam-cli/templates/codeyam-stop-hook.sh +0 -284
  897. package/codeyam-cli/templates/codeyam:diagnose.md +0 -625
  898. package/scripts/finalize-analyzer.cjs +0 -81
@@ -13,9 +13,16 @@
13
13
  */
14
14
 
15
15
  import type { ExecutionFlow } from '~codeyam/types';
16
- import type { ConditionalUsage, CompoundConditional } from './astScopes/types';
16
+ import type {
17
+ ConditionalUsage,
18
+ CompoundConditional,
19
+ DerivedVariableOperation,
20
+ DerivedVariableInfo,
21
+ JsxRenderingUsage,
22
+ } from './astScopes/types';
17
23
  import type { EnrichedConditionalUsage } from './worker/SerializableDataStructure';
18
24
  import resolvePathToControllable from './resolvePathToControllable';
25
+ import cleanPathOfNonTransformingFunctions from './dataStructure/helpers/cleanPathOfNonTransformingFunctions';
19
26
 
20
27
  /** Extended conditional usage type that may include sourceDataPath from enrichment */
21
28
  type ExtendedConditionalUsage = ConditionalUsage &
@@ -26,7 +33,7 @@ export interface ChildComponentConditionalData {
26
33
  /** Child's conditional usages keyed by variable name (may include sourceDataPath from enrichment) */
27
34
  conditionalUsages: Record<string, ExtendedConditionalUsage[]>;
28
35
  /** Child's equivalent signature variables (maps internal paths to prop paths) */
29
- equivalentSignatureVariables: Record<string, string>;
36
+ equivalentSignatureVariables: Record<string, string | string[]>;
30
37
  /** Child's compound conditionals */
31
38
  compoundConditionals: CompoundConditional[];
32
39
  /**
@@ -35,6 +42,11 @@ export interface ChildComponentConditionalData {
35
42
  * then `hasAnalysis` is a gating condition for all of ChildComponent's flows.
36
43
  */
37
44
  gatingConditions?: ConditionalUsage[];
45
+ /**
46
+ * Child's JSX rendering usages (arrays rendered via .map(), text interpolation).
47
+ * These generate "variation flows" for different array lengths.
48
+ */
49
+ jsxRenderingUsages?: JsxRenderingUsage[];
38
50
  }
39
51
 
40
52
  export interface GenerateFlowsFromConditionalsArgs {
@@ -45,7 +57,7 @@ export interface GenerateFlowsFromConditionalsArgs {
45
57
  /** Map of controllable paths to their types */
46
58
  attributesMap: Record<string, string>;
47
59
  /** Map from local variable names to data sources */
48
- equivalentSignatureVariables: Record<string, string>;
60
+ equivalentSignatureVariables: Record<string, string | string[]>;
49
61
  /** Map from full paths to short paths */
50
62
  fullToShortPathMap: Record<string, string>;
51
63
  /**
@@ -54,6 +66,173 @@ export interface GenerateFlowsFromConditionalsArgs {
54
66
  * Used to merge child execution flows into parent.
55
67
  */
56
68
  childComponentData?: Record<string, ChildComponentConditionalData>;
69
+ /**
70
+ * Optional map of derived variables to their derivation info.
71
+ * Used to trace intermediate derived variables that aren't directly
72
+ * used in conditionals but are sources for other derived variables.
73
+ *
74
+ * Example:
75
+ * - `isInCurrentRun = currentRun.entityShas.includes(sha)` → { sourcePath: 'currentRun.entityShas', operation: 'arrayIncludes' }
76
+ * - `isAnalyzing = isInCurrentRun || isInQueue` → { sourcePaths: ['isInCurrentRun', 'isInQueue'], operation: 'or' }
77
+ *
78
+ * Without this map, we can't trace from `isAnalyzing` through `isInCurrentRun`
79
+ * to `currentRun.entityShas` when `isInCurrentRun` isn't in conditionalUsages.
80
+ */
81
+ derivedVariables?: Record<string, DerivedVariableInfo>;
82
+ /**
83
+ * Optional map of child prop paths to their actual data sources.
84
+ * Used when child props flow through useState but ultimately come from
85
+ * mockable data sources (e.g., API calls, fetchers).
86
+ *
87
+ * Example:
88
+ * - "WorkoutsView().signature[0].workouts" → "createClient()...functionCallReturnValue.data"
89
+ *
90
+ * When a child path translates to a useState value, we check this map
91
+ * to find the real data source that can be mocked.
92
+ */
93
+ sourceEquivalencies?: Record<
94
+ string,
95
+ Array<{ scopeNodeName: string; schemaPath: string }>
96
+ >;
97
+ }
98
+
99
+ /**
100
+ * Resolved source info from expanding a derived variable.
101
+ * Contains the path and the operation that led to it.
102
+ */
103
+ interface ResolvedSourceInfo {
104
+ path: string;
105
+ operation?:
106
+ | 'notNull'
107
+ | 'isNull'
108
+ | 'equals'
109
+ | 'notEquals'
110
+ | 'or'
111
+ | 'and'
112
+ | 'arrayIncludes'
113
+ | 'arraySome'
114
+ | 'arrayEvery'
115
+ | 'arrayLength';
116
+ }
117
+
118
+ /**
119
+ * Recursively expands a derived variable to its leaf data sources.
120
+ *
121
+ * For OR expressions like `isAnalyzing = a || b || c`:
122
+ * - Returns all source paths [a, b, c] so they can all be set appropriately
123
+ *
124
+ * For nested derivations like `isAnalyzing = isInCurrentRun || isInQueue`:
125
+ * - Where `isInCurrentRun` is derived from `currentRun.entityShas.includes(x)`
126
+ * - Returns the final data sources: [currentRun.entityShas, queueState.jobs]
127
+ *
128
+ * @param path The variable path to expand
129
+ * @param conditionalUsages All conditional usages (to look up derivedFrom info)
130
+ * @param attributesMap Map of controllable paths
131
+ * @param equivalentSignatureVariables Variable-to-path mappings
132
+ * @param fullToShortPathMap Full-to-short path mappings
133
+ * @param visited Set of already-visited paths (prevents infinite recursion)
134
+ * @param derivedVariables Optional map of all derived variables (for intermediate tracing)
135
+ * @returns Array of resolved source paths that are controllable
136
+ */
137
+ function expandDerivedVariableToSources(
138
+ path: string,
139
+ conditionalUsages: Record<string, ConditionalUsage[]>,
140
+ attributesMap: Record<string, string>,
141
+ equivalentSignatureVariables: Record<string, string | string[]>,
142
+ fullToShortPathMap: Record<string, string>,
143
+ visited: Set<string> = new Set(),
144
+ derivedVariables?: Record<string, DerivedVariableInfo>,
145
+ ): ResolvedSourceInfo[] {
146
+ // Prevent infinite recursion
147
+ if (visited.has(path)) {
148
+ return [];
149
+ }
150
+ visited.add(path);
151
+
152
+ // First, check if this path is directly controllable
153
+ const directResolution = resolvePathToControllable(
154
+ path,
155
+ attributesMap,
156
+ equivalentSignatureVariables,
157
+ fullToShortPathMap,
158
+ );
159
+
160
+ if (directResolution.isControllable && directResolution.resolvedPath) {
161
+ return [{ path: directResolution.resolvedPath }];
162
+ }
163
+
164
+ // Look up derivedFrom info for this path
165
+ // First check conditionalUsages, then fall back to derivedVariables
166
+ const usage = conditionalUsages[path]?.[0];
167
+ let derivedFrom = usage?.derivedFrom;
168
+
169
+ // CRITICAL: If not found in conditionalUsages, check derivedVariables
170
+ // This handles intermediate derived variables like `isInCurrentRun` that aren't
171
+ // directly used in conditionals but ARE derived from data sources
172
+ if (!derivedFrom && derivedVariables?.[path]) {
173
+ derivedFrom = derivedVariables[path];
174
+ }
175
+
176
+ if (!derivedFrom) {
177
+ return [];
178
+ }
179
+
180
+ const { operation, sourcePath, sourcePaths } = derivedFrom;
181
+
182
+ // For OR/AND operations, recursively expand all source paths
183
+ if ((operation === 'or' || operation === 'and') && sourcePaths) {
184
+ const allSources: ResolvedSourceInfo[] = [];
185
+
186
+ for (const sp of sourcePaths) {
187
+ const expanded = expandDerivedVariableToSources(
188
+ sp,
189
+ conditionalUsages,
190
+ attributesMap,
191
+ equivalentSignatureVariables,
192
+ fullToShortPathMap,
193
+ visited,
194
+ derivedVariables,
195
+ );
196
+
197
+ // Add all expanded sources
198
+ for (const source of expanded) {
199
+ // Avoid duplicates
200
+ if (!allSources.some((s) => s.path === source.path)) {
201
+ allSources.push(source);
202
+ }
203
+ }
204
+ }
205
+
206
+ return allSources;
207
+ }
208
+
209
+ // For single-source operations (arrayIncludes, arraySome, notNull, etc.)
210
+ if (sourcePath) {
211
+ // Try to resolve the source path directly
212
+ const sourceResolution = resolvePathToControllable(
213
+ sourcePath,
214
+ attributesMap,
215
+ equivalentSignatureVariables,
216
+ fullToShortPathMap,
217
+ );
218
+
219
+ if (sourceResolution.isControllable && sourceResolution.resolvedPath) {
220
+ return [{ path: sourceResolution.resolvedPath, operation }];
221
+ }
222
+
223
+ // If not directly resolvable, recursively expand
224
+ return expandDerivedVariableToSources(
225
+ sourcePath,
226
+ conditionalUsages,
227
+ attributesMap,
228
+ equivalentSignatureVariables,
229
+ fullToShortPathMap,
230
+ visited,
231
+ derivedVariables,
232
+ );
233
+ }
234
+
235
+ return [];
57
236
  }
58
237
 
59
238
  /**
@@ -80,11 +259,15 @@ function cleanSourceDataPath(sourceDataPath: string): string | null {
80
259
  sourceDataPath.match(/\.functionCallReturnValue/g) || []
81
260
  ).length;
82
261
 
83
- // If there are multiple functionCallReturnValue occurrences, this is a chained call
84
- // (e.g., fetch(...).functionCallReturnValue.json().functionCallReturnValue.data)
262
+ // For chained function calls (e.g., fetch().json()) or paths with non-standard
263
+ // fn call patterns, return the original path so findInAttributesMapForPath can
264
+ // try to look it up in fullToShortPathMap. If it doesn't match, the caller
265
+ // falls through to fallback resolution anyway.
85
266
  if (fnCallReturnValues > 1 || emptyFnCalls !== 1) {
86
- // Multiple function calls - return null to use fallback resolution
87
- return null;
267
+ console.log(
268
+ `[cleanSourceDataPath] chained/non-standard path (fnCallRVs=${fnCallReturnValues}, emptyFnCalls=${emptyFnCalls}), returning original: "${sourceDataPath}"`,
269
+ );
270
+ return sourceDataPath;
88
271
  }
89
272
 
90
273
  // Find the "()" which marks the function call
@@ -113,6 +296,131 @@ function cleanSourceDataPath(sourceDataPath: string): string | null {
113
296
  return actualPath;
114
297
  }
115
298
 
299
+ /**
300
+ * Strip .length suffix from a path if present.
301
+ *
302
+ * When we have a path like "items.length", the controllable attribute is "items"
303
+ * (the array), not "items.length". The length is derived from the array contents.
304
+ *
305
+ * This ensures that execution flows reference the actual controllable attribute
306
+ * rather than the derived .length property.
307
+ */
308
+ function stripLengthSuffix(path: string): string {
309
+ if (path.endsWith('.length')) {
310
+ return path.slice(0, -7); // Remove ".length" (7 characters)
311
+ }
312
+ return path;
313
+ }
314
+
315
+ /**
316
+ * Remove contradictory required values from a compound flow.
317
+ *
318
+ * When a lifecycle boolean (like isLoadingAuditData) is traced to a fetch call's
319
+ * return value, a negated condition (!isLoadingAuditData) produces "falsy" on
320
+ * the fetch path. But if another condition in the same compound requires data
321
+ * from a sub-path of that fetch (e.g., topPaths length > 0), the "falsy" on the
322
+ * parent path contradicts it — a null/falsy response has no .json() to call.
323
+ *
324
+ * This function removes "falsy" required values whose attributePath is a prefix
325
+ * of another required value's attributePath. The child data requirement already
326
+ * implies the parent (fetch) succeeded.
327
+ */
328
+ function removeContradictoryFalsyValues(
329
+ requiredValues: ExecutionFlow['requiredValues'],
330
+ ): ExecutionFlow['requiredValues'] {
331
+ return requiredValues.filter((rv) => {
332
+ if (rv.comparison === 'falsy') {
333
+ const hasChildRequirement = requiredValues.some(
334
+ (other) =>
335
+ other !== rv &&
336
+ other.attributePath.startsWith(rv.attributePath + '.'),
337
+ );
338
+ if (hasChildRequirement) {
339
+ return false;
340
+ }
341
+ }
342
+ return true;
343
+ });
344
+ }
345
+
346
+ /**
347
+ * Generate a human-readable description snippet for a required value,
348
+ * incorporating the comparison type so the LLM understands the intent.
349
+ */
350
+ function describeRequiredValue(rv: ExecutionFlow['requiredValues'][0]): string {
351
+ const name = generateNameFromPath(rv.attributePath).toLowerCase();
352
+ switch (rv.comparison) {
353
+ case 'truthy':
354
+ return `${name} is present`;
355
+ case 'falsy':
356
+ return `${name} is absent`;
357
+ case 'length>':
358
+ return rv.value === '0'
359
+ ? `${name} has items`
360
+ : `${name} has more than ${rv.value} items`;
361
+ case 'length<':
362
+ return `${name} has fewer than ${rv.value} items`;
363
+ case 'equals':
364
+ return `${name} is ${rv.value}`;
365
+ case 'exists':
366
+ return `${name} exists`;
367
+ case 'not-exists':
368
+ return `${name} does not exist`;
369
+ default:
370
+ return `${name} is ${rv.value}`;
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Check whether a resolved path has child entries in the fullToShortPathMap.
376
+ *
377
+ * When a lifecycle boolean (e.g., isLoadingAuditData) resolves to a parent path
378
+ * like fetch(...).functionCallReturnValue, and that path has children (like
379
+ * .json().functionCallReturnValue.topPaths), individual truthy/falsy flows on
380
+ * the parent are misleading. Compound flows with specific child requirements
381
+ * provide better guidance for mock data generation.
382
+ */
383
+ function hasChildPathsInMap(
384
+ resolvedPath: string,
385
+ fullToShortPathMap: Record<string, string>,
386
+ ): boolean {
387
+ return Object.keys(fullToShortPathMap).some(
388
+ (fullPath) =>
389
+ fullPath.startsWith(resolvedPath + '.') ||
390
+ fullPath.startsWith(resolvedPath + '['),
391
+ );
392
+ }
393
+
394
+ /**
395
+ * Extract the controllable base path from a path that may contain method calls.
396
+ *
397
+ * This handles complex expressions like:
398
+ * - `scenarios.filter((s) => s.active).length` → `scenarios`
399
+ * - `users.some((u) => u.role === 'admin')` → `users`
400
+ * - `items.map(x => x.name).join(', ')` → `items`
401
+ *
402
+ * The controllable base is the path that can be mocked - we can control
403
+ * what `scenarios` contains, but we can't control what `.filter()` returns.
404
+ *
405
+ * @param path - The path that may contain method calls
406
+ * @returns The controllable base path with method calls stripped
407
+ */
408
+ function extractControllableBase(path: string): string {
409
+ // First strip .length suffix if present
410
+ const pathWithoutLength = stripLengthSuffix(path);
411
+
412
+ // Use cleanPathOfNonTransformingFunctions to strip method calls like .filter(), .some()
413
+ const cleanedPath = cleanPathOfNonTransformingFunctions(pathWithoutLength);
414
+
415
+ // If the cleaned path is different, return it
416
+ if (cleanedPath !== pathWithoutLength) {
417
+ return cleanedPath;
418
+ }
419
+
420
+ // Otherwise, return the path with just .length stripped
421
+ return pathWithoutLength;
422
+ }
423
+
116
424
  /**
117
425
  * Find a path in attributesMap, using fullToShortPathMap to verify the path is controllable.
118
426
  *
@@ -125,13 +433,16 @@ function cleanSourceDataPath(sourceDataPath: string): string | null {
125
433
  * The sourceDataPath contains full paths (e.g., "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha")
126
434
  * The fullToShortPathMap maps full paths to short paths
127
435
  */
128
- function findInAttributesMapForPath(
436
+ export function findInAttributesMapForPath(
129
437
  path: string,
130
438
  attributesMap: Record<string, string>,
131
439
  fullToShortPathMap: Record<string, string>,
132
440
  ): string | null {
133
441
  // Direct match in attributesMap (already a short path)
134
442
  if (path in attributesMap) {
443
+ console.log(
444
+ `[findInAttributesMapForPath] "${path}" → DIRECT match in attributesMap`,
445
+ );
135
446
  return path;
136
447
  }
137
448
 
@@ -140,19 +451,31 @@ function findInAttributesMapForPath(
140
451
  if (path in fullToShortPathMap) {
141
452
  const shortPath = fullToShortPathMap[path];
142
453
  if (shortPath in attributesMap) {
454
+ console.log(
455
+ `[findInAttributesMapForPath] "${path}" → fullToShortPathMap match: shortPath="${shortPath}" found in attributesMap`,
456
+ );
143
457
  return path; // Return FULL path to preserve data source context
144
458
  }
459
+ console.log(
460
+ `[findInAttributesMapForPath] "${path}" → fullToShortPathMap match shortPath="${shortPath}" but NOT in attributesMap`,
461
+ );
145
462
  }
146
463
 
147
464
  // Normalized match (array indices [N] → [])
148
465
  const normalizedPath = path.replace(/\[\d+\]/g, '[]');
149
466
  if (normalizedPath !== path) {
150
467
  if (normalizedPath in attributesMap) {
468
+ console.log(
469
+ `[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" DIRECT match in attributesMap`,
470
+ );
151
471
  return normalizedPath;
152
472
  }
153
473
  if (normalizedPath in fullToShortPathMap) {
154
474
  const shortPath = fullToShortPathMap[normalizedPath];
155
475
  if (shortPath in attributesMap) {
476
+ console.log(
477
+ `[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" fullToShortPathMap match: shortPath="${shortPath}"`,
478
+ );
156
479
  return normalizedPath; // Return normalized FULL path
157
480
  }
158
481
  }
@@ -164,25 +487,92 @@ function findInAttributesMapForPath(
164
487
  // and we need to find matching short path prefix
165
488
  for (const attrPath of Object.keys(attributesMap)) {
166
489
  if (path.startsWith(attrPath + '.') || path.startsWith(attrPath + '[')) {
167
- // The path is a child of a known attribute path
490
+ console.log(
491
+ `[findInAttributesMapForPath] "${path}" → PREFIX match: starts with attributesMap key "${attrPath}"`,
492
+ );
168
493
  return path;
169
494
  }
170
495
  }
171
496
 
172
497
  // Try suffix matching: if the path ends with ".X.Y.Z" and attributesMap has "X.Y.Z"
173
498
  // Return the FULL input path to preserve data source context
174
- for (const attrPath of Object.keys(attributesMap)) {
175
- if (
176
- path.endsWith('.' + attrPath) ||
177
- path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))
178
- ) {
179
- return path; // Return FULL path, not short attrPath
499
+ // Skip suffix matching for chained function calls (multiple .functionCallReturnValue segments)
500
+ // to avoid false matches: e.g., fetch(...).json().functionCallReturnValue.data falsely matching
501
+ // "data" from a completely different data source like useFetcher
502
+ const fnCallReturnValueCount = (
503
+ path.match(/\.functionCallReturnValue/g) || []
504
+ ).length;
505
+ if (fnCallReturnValueCount <= 1) {
506
+ for (const attrPath of Object.keys(attributesMap)) {
507
+ if (
508
+ path.endsWith('.' + attrPath) ||
509
+ path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))
510
+ ) {
511
+ console.log(
512
+ `[findInAttributesMapForPath] "${path}" → SUFFIX match: ends with attributesMap key "${attrPath}"`,
513
+ );
514
+ return path; // Return FULL path, not short attrPath
515
+ }
180
516
  }
181
517
  }
182
518
 
519
+ // Try child path matching against fullToShortPathMap keys
520
+ // If the path starts with a known full path + '.' or '[', it's a child
521
+ // of a controllable path. Build the equivalent short child path.
522
+ // e.g., path = "fetch(...).fCRV.json().fCRV.topPaths.length"
523
+ // fullToShortPathMap has "fetch(...).fCRV.json().fCRV.topPaths" → "json().fCRV.topPaths"
524
+ // → check if "json().fCRV.topPaths.length" is in attributesMap
525
+ for (const [fullPath, shortPath] of Object.entries(fullToShortPathMap)) {
526
+ if (path.startsWith(fullPath + '.') || path.startsWith(fullPath + '[')) {
527
+ const suffix = path.slice(fullPath.length); // e.g., ".length"
528
+ const shortChildPath = shortPath + suffix;
529
+ if (shortChildPath in attributesMap) {
530
+ console.log(
531
+ `[findInAttributesMapForPath] "${path}" → CHILD of fullToShortPathMap key "${fullPath}": shortChildPath="${shortChildPath}" found in attributesMap`,
532
+ );
533
+ return path; // Return full path to preserve data source context
534
+ }
535
+ // Also check if the base short path is an array and suffix is .length
536
+ if (suffix === '.length' && shortPath in attributesMap) {
537
+ console.log(
538
+ `[findInAttributesMapForPath] "${path}" → CHILD .length of fullToShortPathMap key "${fullPath}": base shortPath="${shortPath}" is in attributesMap (array .length)`,
539
+ );
540
+ return path; // Array .length is controllable via the array
541
+ }
542
+ }
543
+ }
544
+
545
+ // Try parent matching: if the path is a prefix of any fullToShortPathMap key,
546
+ // it's a parent of controllable data and therefore controllable itself
547
+ for (const fullPath of Object.keys(fullToShortPathMap)) {
548
+ if (fullPath.startsWith(path + '.') || fullPath.startsWith(path + '[')) {
549
+ console.log(
550
+ `[findInAttributesMapForPath] "${path}" → PARENT match: fullToShortPathMap key "${fullPath}" starts with this path`,
551
+ );
552
+ return path;
553
+ }
554
+ }
555
+
556
+ console.log(
557
+ `[findInAttributesMapForPath] "${path}" → NO MATCH (checked ${Object.keys(attributesMap).length} attributesMap keys, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap keys)`,
558
+ );
183
559
  return null;
184
560
  }
185
561
 
562
+ /**
563
+ * Generate a slug from a path for use in flow IDs and exclusive groups.
564
+ */
565
+ function pathToSlug(path: string): string {
566
+ return path
567
+ .replace(/\[\d+\]/g, '')
568
+ .replace(/\[\]/g, '')
569
+ .replace(/\(\)/g, '')
570
+ .replace(/\.functionCallReturnValue/g, '')
571
+ .replace(/[<>]/g, '')
572
+ .replace(/\./g, '-')
573
+ .toLowerCase();
574
+ }
575
+
186
576
  /**
187
577
  * Generate a human-readable name from a path.
188
578
  * Extracts the last meaningful part of the path.
@@ -244,6 +634,12 @@ function inferValueType(
244
634
  /**
245
635
  * Generate flows from a single conditional usage.
246
636
  * Sets impact to 'high' if the conditional controls JSX rendering.
637
+ *
638
+ * When the usage has a `constraintExpression`, it represents a complex expression
639
+ * that can't be simply resolved (e.g., `scenarios.filter(x => x.active).length > 1`).
640
+ * In this case:
641
+ * - `attributePath` is set to the controllable base (e.g., `scenarios`)
642
+ * - `constraint` is set to the full expression for LLM reasoning
247
643
  */
248
644
  function generateFlowsFromUsage(
249
645
  usage: ConditionalUsage,
@@ -258,6 +654,14 @@ function generateFlowsFromUsage(
258
654
  ? 'high'
259
655
  : 'medium';
260
656
 
657
+ // When there's a constraintExpression, use the controllable base for attributePath
658
+ // and pass through the constraint for LLM reasoning
659
+ const hasConstraint = !!usage.constraintExpression;
660
+ const attributePath = hasConstraint
661
+ ? extractControllableBase(resolvedPath)
662
+ : stripLengthSuffix(resolvedPath);
663
+ const constraint = usage.constraintExpression;
664
+
261
665
  if (usage.conditionType === 'truthiness') {
262
666
  // Generate both truthy and falsy flows
263
667
  const isNegated = usage.isNegated ?? false;
@@ -269,10 +673,11 @@ function generateFlowsFromUsage(
269
673
  description: `When ${baseName.toLowerCase()} is ${isNegated ? 'falsy' : 'truthy'}`,
270
674
  requiredValues: [
271
675
  {
272
- attributePath: resolvedPath,
676
+ attributePath,
273
677
  value: isNegated ? 'falsy' : 'truthy',
274
678
  comparison: isNegated ? 'falsy' : 'truthy',
275
679
  valueType: 'boolean',
680
+ constraint,
276
681
  },
277
682
  ],
278
683
  impact,
@@ -292,10 +697,11 @@ function generateFlowsFromUsage(
292
697
  description: `When ${baseName.toLowerCase()} is ${isNegated ? 'truthy' : 'falsy'}`,
293
698
  requiredValues: [
294
699
  {
295
- attributePath: resolvedPath,
700
+ attributePath,
296
701
  value: isNegated ? 'truthy' : 'falsy',
297
702
  comparison: isNegated ? 'truthy' : 'falsy',
298
703
  valueType: 'boolean',
704
+ constraint,
299
705
  },
300
706
  ],
301
707
  impact,
@@ -321,10 +727,11 @@ function generateFlowsFromUsage(
321
727
  description: `When ${baseName.toLowerCase()} equals "${value}"`,
322
728
  requiredValues: [
323
729
  {
324
- attributePath: resolvedPath,
730
+ attributePath,
325
731
  value: value,
326
732
  comparison: 'equals',
327
733
  valueType: inferValueType(value),
734
+ constraint,
328
735
  },
329
736
  ],
330
737
  impact,
@@ -377,32 +784,51 @@ function generateFlowFromCompound(
377
784
  condition.requiredValue?.toString() ??
378
785
  condition.comparedValues?.[0] ??
379
786
  'truthy';
380
- comparison = 'equals';
787
+ // Map comparison operator to flow comparison type
788
+ const op = condition.comparisonOperator;
789
+ if (op === '>' || op === '>=') {
790
+ comparison = 'length>';
791
+ } else if (op === '<' || op === '<=') {
792
+ comparison = 'length<';
793
+ } else {
794
+ comparison = 'equals';
795
+ }
381
796
  }
382
797
 
383
798
  requiredValues.push({
384
- attributePath: resolvedPath,
799
+ attributePath: stripLengthSuffix(resolvedPath),
385
800
  value,
386
801
  comparison,
387
802
  valueType: inferValueType(value),
388
803
  });
389
804
  }
390
805
 
391
- // Generate a combined ID from all paths
392
- const pathParts = requiredValues
806
+ // Remove contradictory "falsy" values where a child path requires data
807
+ const cleanedValues = removeContradictoryFalsyValues(requiredValues);
808
+
809
+ if (cleanedValues.length === 0) {
810
+ return null;
811
+ }
812
+
813
+ // Generate a combined ID from all paths + values to distinguish different comparisons
814
+ const pathParts = cleanedValues
393
815
  .map((rv) => {
394
816
  const name = generateNameFromPath(rv.attributePath);
395
- return name.toLowerCase().replace(/\s+/g, '-');
817
+ const suffix =
818
+ rv.comparison === 'truthy' || rv.comparison === 'falsy'
819
+ ? `-${rv.comparison}`
820
+ : `-${rv.comparison}-${rv.value}`;
821
+ return name.toLowerCase().replace(/\s+/g, '-') + suffix;
396
822
  })
397
823
  .join('-and-');
398
824
 
399
825
  return {
400
826
  id: `compound-${pathParts}`,
401
- name: requiredValues
827
+ name: cleanedValues
402
828
  .map((rv) => generateNameFromPath(rv.attributePath))
403
829
  .join(' + '),
404
- description: `When ${requiredValues.map((rv) => `${generateNameFromPath(rv.attributePath).toLowerCase()} is ${rv.value}`).join(' and ')}`,
405
- requiredValues,
830
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
831
+ requiredValues: cleanedValues,
406
832
  impact,
407
833
  sourceLocation: {
408
834
  lineNumber: compound.sourceLocation.lineNumber,
@@ -412,6 +838,60 @@ function generateFlowFromCompound(
412
838
  };
413
839
  }
414
840
 
841
+ /**
842
+ * Expand a compound conditional with OR groups into multiple condition sets.
843
+ *
844
+ * For a compound like `A && (B || C)`:
845
+ * - Conditions: [{ path: 'A' }, { path: 'B', orGroupId: 'or_xxx' }, { path: 'C', orGroupId: 'or_xxx' }]
846
+ * - Returns: [[A, B], [A, C]] - two sets of conditions
847
+ *
848
+ * For multiple OR groups like `A && (B || C) && (D || E)`:
849
+ * - Returns: [[A, B, D], [A, B, E], [A, C, D], [A, C, E]]
850
+ */
851
+ function expandOrGroups(
852
+ conditions: CompoundConditional['conditions'],
853
+ ): CompoundConditional['conditions'][] {
854
+ // Separate conditions into mandatory (no orGroupId) and OR groups
855
+ const mandatory = conditions.filter((c) => !c.orGroupId);
856
+ const orGroups = new Map<string, typeof conditions>();
857
+
858
+ for (const condition of conditions) {
859
+ if (condition.orGroupId) {
860
+ const group = orGroups.get(condition.orGroupId) ?? [];
861
+ group.push(condition);
862
+ orGroups.set(condition.orGroupId, group);
863
+ }
864
+ }
865
+
866
+ // If no OR groups, return the original conditions
867
+ if (orGroups.size === 0) {
868
+ return [conditions];
869
+ }
870
+
871
+ // Generate all combinations by picking one condition from each OR group
872
+ const groupArrays = Array.from(orGroups.values());
873
+ const combinations: CompoundConditional['conditions'][] = [];
874
+
875
+ function generateCombinations(
876
+ index: number,
877
+ current: typeof conditions,
878
+ ): void {
879
+ if (index === groupArrays.length) {
880
+ // We've picked one from each OR group - combine with mandatory conditions
881
+ combinations.push([...mandatory, ...current]);
882
+ return;
883
+ }
884
+
885
+ // Pick each option from the current OR group
886
+ for (const option of groupArrays[index]) {
887
+ generateCombinations(index + 1, [...current, option]);
888
+ }
889
+ }
890
+
891
+ generateCombinations(0, []);
892
+ return combinations;
893
+ }
894
+
415
895
  /**
416
896
  * Generate execution flows from conditional usages using pure static analysis.
417
897
  *
@@ -457,8 +937,8 @@ function normalizePathForDeduplication(
457
937
  */
458
938
  function translateChildPathToParent(
459
939
  childPath: string,
460
- childEquivalentSignatureVariables: Record<string, string>,
461
- parentEquivalentSignatureVariables: Record<string, string>,
940
+ childEquivalentSignatureVariables: Record<string, string | string[]>,
941
+ parentEquivalentSignatureVariables: Record<string, string | string[]>,
462
942
  childName: string,
463
943
  ): string | null {
464
944
  // Extract the root variable from the child path
@@ -485,7 +965,11 @@ function translateChildPathToParent(
485
965
 
486
966
  // Look up the child's equivalence for this root variable
487
967
  // e.g., childEquiv[selectedScenario] = "signature[0].selectedScenario"
488
- const childPropPath = childEquivalentSignatureVariables[rootVar];
968
+ // Handle array case (OR expressions) - use first element if array
969
+ const rawChildPropPath = childEquivalentSignatureVariables[rootVar];
970
+ const childPropPath = Array.isArray(rawChildPropPath)
971
+ ? rawChildPropPath[0]
972
+ : rawChildPropPath;
489
973
 
490
974
  if (!childPropPath) {
491
975
  // No mapping found - this might be internal state, not a prop
@@ -498,7 +982,11 @@ function translateChildPathToParent(
498
982
 
499
983
  // Look up parent's equivalence to find what value was passed to this prop
500
984
  // e.g., parentEquiv["ChildName().signature[0].selectedScenario"] = "selectedScenario"
501
- const parentValue = parentEquivalentSignatureVariables[fullChildPropPath];
985
+ // Handle array case (OR expressions) - use first element if array
986
+ const rawParentValue = parentEquivalentSignatureVariables[fullChildPropPath];
987
+ const parentValue = Array.isArray(rawParentValue)
988
+ ? rawParentValue[0]
989
+ : rawParentValue;
502
990
 
503
991
  if (!parentValue) {
504
992
  // No parent mapping found - log ALL parent keys that contain the childName
@@ -524,11 +1012,29 @@ export default function generateExecutionFlowsFromConditionals(
524
1012
  equivalentSignatureVariables,
525
1013
  fullToShortPathMap,
526
1014
  childComponentData,
1015
+ derivedVariables,
1016
+ sourceEquivalencies,
527
1017
  } = args;
528
1018
 
529
1019
  const flows: ExecutionFlow[] = [];
530
1020
  const seenFlowIds = new Set<string>();
531
1021
 
1022
+ console.log(
1023
+ `[genFlowsFromConditionals] INPUT: ${Object.keys(conditionalUsages).length} conditional paths, ${Object.keys(attributesMap).length} attributesMap entries, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap entries, ${Object.keys(equivalentSignatureVariables).length} equivSigVars, ${compoundConditionals.length} compound conditionals`,
1024
+ );
1025
+ console.log(
1026
+ `[genFlowsFromConditionals] conditionalUsages keys: [${Object.keys(conditionalUsages).join(', ')}]`,
1027
+ );
1028
+ console.log(
1029
+ `[genFlowsFromConditionals] attributesMap keys: [${Object.keys(attributesMap).join(', ')}]`,
1030
+ );
1031
+ console.log(
1032
+ `[genFlowsFromConditionals] fullToShortPathMap: ${JSON.stringify(fullToShortPathMap)}`,
1033
+ );
1034
+ console.log(
1035
+ `[genFlowsFromConditionals] equivalentSignatureVariables: ${JSON.stringify(equivalentSignatureVariables)}`,
1036
+ );
1037
+
532
1038
  // Track normalized resolved paths to prevent duplicate flows
533
1039
  // This handles the case where we have usages for both:
534
1040
  // - "hasNewerVersion" (short path from destructured variable)
@@ -546,9 +1052,16 @@ export default function generateExecutionFlowsFromConditionals(
546
1052
  for (const usage of usages) {
547
1053
  // Skip usages that are part of compound conditionals (handled separately)
548
1054
  if (usage.chainId && compoundChainIds.has(usage.chainId)) {
1055
+ console.log(
1056
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: part of compound conditional chain=${usage.chainId}`,
1057
+ );
549
1058
  continue;
550
1059
  }
551
1060
 
1061
+ console.log(
1062
+ `[genFlowsFromConditionals] --- Processing "${usage.path}" (type=${usage.conditionType}, negated=${usage.isNegated}, sourceDataPath="${usage.sourceDataPath ?? '(none)'}", derivedFrom=${usage.derivedFrom ? JSON.stringify(usage.derivedFrom) : 'none'})`,
1063
+ );
1064
+
552
1065
  // First, try to use pre-computed sourceDataPath if available
553
1066
  let resolvedPath: string | null = null;
554
1067
 
@@ -558,7 +1071,9 @@ export default function generateExecutionFlowsFromConditionals(
558
1071
  // should become "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
559
1072
  // Returns null for malformed paths (e.g., chained function calls like fetch().json())
560
1073
  const cleanedPath = cleanSourceDataPath(usage.sourceDataPath);
561
-
1074
+ console.log(
1075
+ `[genFlowsFromConditionals] "${usage.path}" cleanSourceDataPath("${usage.sourceDataPath}") → "${cleanedPath}"`,
1076
+ );
562
1077
  if (cleanedPath) {
563
1078
  // Verify the cleaned path exists in attributesMap
564
1079
  const pathMatch = findInAttributesMapForPath(
@@ -566,6 +1081,9 @@ export default function generateExecutionFlowsFromConditionals(
566
1081
  attributesMap,
567
1082
  fullToShortPathMap,
568
1083
  );
1084
+ console.log(
1085
+ `[genFlowsFromConditionals] "${usage.path}" findInAttributesMapForPath("${cleanedPath}") → ${pathMatch ? `"${pathMatch}"` : 'null (not found)'}`,
1086
+ );
569
1087
  if (pathMatch) {
570
1088
  resolvedPath = pathMatch;
571
1089
  }
@@ -575,13 +1093,18 @@ export default function generateExecutionFlowsFromConditionals(
575
1093
 
576
1094
  // Fall back to resolution via equivalentSignatureVariables
577
1095
  if (!resolvedPath) {
1096
+ console.log(
1097
+ `[genFlowsFromConditionals] "${usage.path}" sourceDataPath resolution failed, trying resolvePathToControllable("${usage.path}")...`,
1098
+ );
578
1099
  const resolution = resolvePathToControllable(
579
1100
  usage.path,
580
1101
  attributesMap,
581
1102
  equivalentSignatureVariables,
582
1103
  fullToShortPathMap,
583
1104
  );
584
-
1105
+ console.log(
1106
+ `[genFlowsFromConditionals] "${usage.path}" resolvePathToControllable → isControllable=${resolution.isControllable}, resolvedPath="${resolution.resolvedPath ?? '(none)'}"`,
1107
+ );
585
1108
  if (resolution.isControllable && resolution.resolvedPath) {
586
1109
  resolvedPath = resolution.resolvedPath;
587
1110
  }
@@ -591,8 +1114,11 @@ export default function generateExecutionFlowsFromConditionals(
591
1114
  // This handles cases like: const hasAnalysis = analysis !== null
592
1115
  // where hasAnalysis is not in attributesMap but analysis is
593
1116
  if (!resolvedPath && usage.derivedFrom) {
594
- const { sourcePath, sourcePaths } = usage.derivedFrom;
595
-
1117
+ const { operation, sourcePath, sourcePaths, comparedValue } =
1118
+ usage.derivedFrom;
1119
+ console.log(
1120
+ `[genFlowsFromConditionals] "${usage.path}" trying derivedFrom: operation=${operation}, sourcePath="${sourcePath ?? '(none)'}", sourcePaths=${sourcePaths ? JSON.stringify(sourcePaths) : '(none)'}, comparedValue="${comparedValue ?? '(none)'}"`,
1121
+ );
596
1122
  // For single-source derivations (notNull, equals, etc.)
597
1123
  if (sourcePath) {
598
1124
  const resolution = resolvePathToControllable(
@@ -601,14 +1127,282 @@ export default function generateExecutionFlowsFromConditionals(
601
1127
  equivalentSignatureVariables,
602
1128
  fullToShortPathMap,
603
1129
  );
604
-
605
1130
  if (resolution.isControllable && resolution.resolvedPath) {
606
1131
  resolvedPath = resolution.resolvedPath;
607
1132
  }
608
1133
  }
609
1134
 
610
- // For multi-source derivations (or, and), try the first resolvable path
611
- // This is a simplification - ideally we'd generate flows for each source
1135
+ // For equals/notEquals derivations with comparedValue, generate comparison flows
1136
+ // e.g., canEdit derived from user.role === 'admin'
1137
+ // When canEdit is used in truthiness check, we need:
1138
+ // - Truthy flow: user.role = 'admin' (comparison: 'equals')
1139
+ // - Falsy flow: user.role != 'admin' (comparison: 'notEquals')
1140
+ if (
1141
+ (operation === 'equals' || operation === 'notEquals') &&
1142
+ comparedValue !== undefined &&
1143
+ resolvedPath &&
1144
+ usage.conditionType === 'truthiness'
1145
+ ) {
1146
+ const baseName = generateNameFromPath(usage.path);
1147
+ const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
1148
+ ? 'high'
1149
+ : 'medium';
1150
+
1151
+ const isNegated = usage.isNegated ?? false;
1152
+
1153
+ // For equals derivation:
1154
+ // - Truthy check (!negated): needs value = comparedValue (equals)
1155
+ // - Falsy check (negated): needs value != comparedValue (notEquals)
1156
+ // For notEquals derivation: inverse of above
1157
+ const isEqualsDerivation = operation === 'equals';
1158
+ const truthyNeedsEquals = isEqualsDerivation !== isNegated;
1159
+
1160
+ // Generate truthy flow
1161
+ const truthyFlow: ExecutionFlow = {
1162
+ id: generateFlowId(usage.path, 'truthy'),
1163
+ name: `${baseName} True`,
1164
+ description: `When ${baseName.toLowerCase()} is truthy (${resolvedPath} ${truthyNeedsEquals ? '=' : '!='} ${comparedValue})`,
1165
+ requiredValues: [
1166
+ {
1167
+ attributePath: stripLengthSuffix(resolvedPath),
1168
+ value: comparedValue,
1169
+ comparison: truthyNeedsEquals ? 'equals' : 'notEquals',
1170
+ valueType: inferValueType(comparedValue),
1171
+ },
1172
+ ],
1173
+ impact,
1174
+ sourceLocation: usage.sourceLocation
1175
+ ? {
1176
+ lineNumber: usage.sourceLocation.lineNumber,
1177
+ column: usage.sourceLocation.column,
1178
+ }
1179
+ : undefined,
1180
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1181
+ };
1182
+
1183
+ // Generate falsy flow
1184
+ const falsyFlow: ExecutionFlow = {
1185
+ id: generateFlowId(usage.path, 'falsy'),
1186
+ name: `${baseName} False`,
1187
+ description: `When ${baseName.toLowerCase()} is falsy (${resolvedPath} ${truthyNeedsEquals ? '!=' : '='} ${comparedValue})`,
1188
+ requiredValues: [
1189
+ {
1190
+ attributePath: stripLengthSuffix(resolvedPath),
1191
+ value: comparedValue,
1192
+ comparison: truthyNeedsEquals ? 'notEquals' : 'equals',
1193
+ valueType: inferValueType(comparedValue),
1194
+ },
1195
+ ],
1196
+ impact,
1197
+ sourceLocation: usage.sourceLocation
1198
+ ? {
1199
+ lineNumber: usage.sourceLocation.lineNumber,
1200
+ column: usage.sourceLocation.column,
1201
+ }
1202
+ : undefined,
1203
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1204
+ };
1205
+
1206
+ // Add flows and skip normal flow generation
1207
+ if (!seenFlowIds.has(truthyFlow.id)) {
1208
+ seenFlowIds.add(truthyFlow.id);
1209
+ flows.push(truthyFlow);
1210
+ }
1211
+ if (!seenFlowIds.has(falsyFlow.id)) {
1212
+ seenFlowIds.add(falsyFlow.id);
1213
+ flows.push(falsyFlow);
1214
+ }
1215
+
1216
+ continue;
1217
+ }
1218
+
1219
+ // For OR derivations with negation, we need ALL sources to be falsy
1220
+ // e.g., !isBusy where isBusy = isRunning || isQueued || isPending
1221
+ // For the falsy flow, ALL sources must be falsy
1222
+ if (
1223
+ operation === 'or' &&
1224
+ usage.conditionType === 'truthiness' &&
1225
+ usage.isNegated === true &&
1226
+ sourcePaths &&
1227
+ sourcePaths.length > 0
1228
+ ) {
1229
+ // Use expandDerivedVariableToSources to recursively resolve all sources
1230
+ const allSources = expandDerivedVariableToSources(
1231
+ usage.path,
1232
+ conditionalUsages,
1233
+ attributesMap,
1234
+ equivalentSignatureVariables,
1235
+ fullToShortPathMap,
1236
+ new Set(),
1237
+ derivedVariables,
1238
+ );
1239
+
1240
+ if (allSources.length > 0) {
1241
+ // Generate a compound-style flow with all sources set to falsy
1242
+ const baseName = generateNameFromPath(usage.path);
1243
+ const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
1244
+ ? 'high'
1245
+ : 'medium';
1246
+
1247
+ const requiredValues: ExecutionFlow['requiredValues'] =
1248
+ allSources.map((source) => ({
1249
+ attributePath: source.path,
1250
+ value: 'falsy',
1251
+ comparison: 'falsy' as const,
1252
+ valueType: 'boolean' as const,
1253
+ }));
1254
+
1255
+ // Create a single falsy flow with all sources
1256
+ const falsyFlow: ExecutionFlow = {
1257
+ id: generateFlowId(usage.path, 'falsy'),
1258
+ name: `${baseName} False`,
1259
+ description: `When ${baseName.toLowerCase()} is falsy (all sources are falsy)`,
1260
+ requiredValues,
1261
+ impact,
1262
+ sourceLocation: usage.sourceLocation
1263
+ ? {
1264
+ lineNumber: usage.sourceLocation.lineNumber,
1265
+ column: usage.sourceLocation.column,
1266
+ }
1267
+ : undefined,
1268
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1269
+ };
1270
+
1271
+ // Create a truthy flow - for OR, ANY source being truthy is sufficient
1272
+ // We use the first resolvable source for the truthy flow
1273
+ const firstSource = allSources[0];
1274
+ const truthyFlow: ExecutionFlow = {
1275
+ id: generateFlowId(usage.path, 'truthy'),
1276
+ name: `${baseName} True`,
1277
+ description: `When ${baseName.toLowerCase()} is truthy`,
1278
+ requiredValues: [
1279
+ {
1280
+ attributePath: firstSource.path,
1281
+ value: 'truthy',
1282
+ comparison: 'truthy',
1283
+ valueType: 'boolean',
1284
+ },
1285
+ ],
1286
+ impact,
1287
+ sourceLocation: usage.sourceLocation
1288
+ ? {
1289
+ lineNumber: usage.sourceLocation.lineNumber,
1290
+ column: usage.sourceLocation.column,
1291
+ }
1292
+ : undefined,
1293
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1294
+ };
1295
+
1296
+ // Add both flows (falsy needs all sources, truthy needs one)
1297
+ if (!seenFlowIds.has(falsyFlow.id)) {
1298
+ seenFlowIds.add(falsyFlow.id);
1299
+ flows.push(falsyFlow);
1300
+ }
1301
+ if (!seenFlowIds.has(truthyFlow.id)) {
1302
+ seenFlowIds.add(truthyFlow.id);
1303
+ flows.push(truthyFlow);
1304
+ }
1305
+
1306
+ // Skip the normal flow generation for this usage
1307
+ continue;
1308
+ }
1309
+ }
1310
+
1311
+ // For AND derivations without negation, we need ALL sources to be truthy
1312
+ // e.g., isReady where isReady = hasData && isLoaded && isValid
1313
+ // For the truthy flow, ALL sources must be truthy
1314
+ // For negated AND (!isReady), ANY source being falsy is sufficient (fallback behavior)
1315
+ if (
1316
+ operation === 'and' &&
1317
+ usage.conditionType === 'truthiness' &&
1318
+ usage.isNegated !== true &&
1319
+ sourcePaths &&
1320
+ sourcePaths.length > 0
1321
+ ) {
1322
+ // Use expandDerivedVariableToSources to recursively resolve all sources
1323
+ const allSources = expandDerivedVariableToSources(
1324
+ usage.path,
1325
+ conditionalUsages,
1326
+ attributesMap,
1327
+ equivalentSignatureVariables,
1328
+ fullToShortPathMap,
1329
+ new Set(),
1330
+ derivedVariables,
1331
+ );
1332
+
1333
+ if (allSources.length > 0) {
1334
+ // Generate a compound-style flow with all sources set to truthy
1335
+ const baseName = generateNameFromPath(usage.path);
1336
+ const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
1337
+ ? 'high'
1338
+ : 'medium';
1339
+
1340
+ const requiredValues: ExecutionFlow['requiredValues'] =
1341
+ allSources.map((source) => ({
1342
+ attributePath: source.path,
1343
+ value: 'truthy',
1344
+ comparison: 'truthy' as const,
1345
+ valueType: 'boolean' as const,
1346
+ }));
1347
+
1348
+ // Create a truthy flow with all sources
1349
+ const truthyFlow: ExecutionFlow = {
1350
+ id: generateFlowId(usage.path, 'truthy'),
1351
+ name: `${baseName} True`,
1352
+ description: `When ${baseName.toLowerCase()} is truthy (all sources are truthy)`,
1353
+ requiredValues,
1354
+ impact,
1355
+ sourceLocation: usage.sourceLocation
1356
+ ? {
1357
+ lineNumber: usage.sourceLocation.lineNumber,
1358
+ column: usage.sourceLocation.column,
1359
+ }
1360
+ : undefined,
1361
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1362
+ };
1363
+
1364
+ // Create a falsy flow - for AND, ANY source being falsy is sufficient
1365
+ // We use the first resolvable source for the falsy flow
1366
+ const firstSource = allSources[0];
1367
+ const falsyFlow: ExecutionFlow = {
1368
+ id: generateFlowId(usage.path, 'falsy'),
1369
+ name: `${baseName} False`,
1370
+ description: `When ${baseName.toLowerCase()} is falsy`,
1371
+ requiredValues: [
1372
+ {
1373
+ attributePath: firstSource.path,
1374
+ value: 'falsy',
1375
+ comparison: 'falsy',
1376
+ valueType: 'boolean',
1377
+ },
1378
+ ],
1379
+ impact,
1380
+ sourceLocation: usage.sourceLocation
1381
+ ? {
1382
+ lineNumber: usage.sourceLocation.lineNumber,
1383
+ column: usage.sourceLocation.column,
1384
+ }
1385
+ : undefined,
1386
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1387
+ };
1388
+
1389
+ // Add both flows (truthy needs all sources, falsy needs one)
1390
+ if (!seenFlowIds.has(truthyFlow.id)) {
1391
+ seenFlowIds.add(truthyFlow.id);
1392
+ flows.push(truthyFlow);
1393
+ }
1394
+ if (!seenFlowIds.has(falsyFlow.id)) {
1395
+ seenFlowIds.add(falsyFlow.id);
1396
+ flows.push(falsyFlow);
1397
+ }
1398
+
1399
+ // Skip the normal flow generation for this usage
1400
+ continue;
1401
+ }
1402
+ }
1403
+
1404
+ // For multi-source derivations (or, and) without special handling,
1405
+ // try the first resolvable path as a fallback
612
1406
  if (!resolvedPath && sourcePaths && sourcePaths.length > 0) {
613
1407
  for (const sp of sourcePaths) {
614
1408
  const resolution = resolvePathToControllable(
@@ -628,6 +1422,9 @@ export default function generateExecutionFlowsFromConditionals(
628
1422
 
629
1423
  if (!resolvedPath) {
630
1424
  // Path is not controllable - skip (no invalid flows possible)
1425
+ console.log(
1426
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: not controllable (no resolvedPath after all attempts)`,
1427
+ );
631
1428
  continue;
632
1429
  }
633
1430
 
@@ -642,10 +1439,33 @@ export default function generateExecutionFlowsFromConditionals(
642
1439
  // Skip if we've already generated flows for this normalized path
643
1440
  // This prevents duplicate flows when we have usages for both short and full paths
644
1441
  if (seenNormalizedPaths.has(normalizedPath)) {
1442
+ console.log(
1443
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: duplicate normalizedPath="${normalizedPath}" (resolvedPath="${resolvedPath}")`,
1444
+ );
645
1445
  continue;
646
1446
  }
647
1447
  seenNormalizedPaths.add(normalizedPath);
648
1448
 
1449
+ // Skip individual truthy/falsy flows on parent paths that have child data entries.
1450
+ // Lifecycle booleans (like isLoadingAuditData) traced to fetch(...).functionCallReturnValue
1451
+ // produce misleading truthy/falsy flows: "truthy" can't show loading (mock resolves instantly),
1452
+ // "falsy" tells the LLM to return null (breaking .json()). Compound flows with specific child
1453
+ // data requirements provide the correct mock guidance.
1454
+ if (
1455
+ usage.conditionType === 'truthiness' &&
1456
+ resolvedPath &&
1457
+ hasChildPathsInMap(resolvedPath, fullToShortPathMap)
1458
+ ) {
1459
+ console.log(
1460
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: parent path "${resolvedPath}" has child data paths — compound flows will handle this`,
1461
+ );
1462
+ continue;
1463
+ }
1464
+
1465
+ console.log(
1466
+ `[genFlowsFromConditionals] "${usage.path}" RESOLVED → resolvedPath="${resolvedPath}", normalizedPath="${normalizedPath}" — generating flows`,
1467
+ );
1468
+
649
1469
  // Generate flows for this controllable usage
650
1470
  const usageFlows = generateFlowsFromUsage(usage, resolvedPath);
651
1471
 
@@ -654,6 +1474,9 @@ export default function generateExecutionFlowsFromConditionals(
654
1474
  if (!seenFlowIds.has(flow.id)) {
655
1475
  seenFlowIds.add(flow.id);
656
1476
  flows.push(flow);
1477
+ console.log(
1478
+ `[genFlowsFromConditionals] "${usage.path}" FLOW ADDED: id="${flow.id}", requiredValues=${JSON.stringify(flow.requiredValues.map((rv) => ({ attr: rv.attributePath, val: rv.value })))}`,
1479
+ );
657
1480
  }
658
1481
  }
659
1482
  }
@@ -661,32 +1484,277 @@ export default function generateExecutionFlowsFromConditionals(
661
1484
 
662
1485
  // Process compound conditionals
663
1486
  for (const compound of compoundConditionals) {
664
- // First, check if ALL paths in this compound are controllable
665
- const resolvedPaths = new Map<string, string>();
666
- let allControllable = true;
1487
+ // Expand OR groups into separate condition sets
1488
+ // For example, `A && (B || C)` becomes [[A, B], [A, C]]
1489
+ const expandedConditionSets = expandOrGroups(compound.conditions);
1490
+
1491
+ // Process each expanded condition set as a separate potential flow
1492
+ for (const conditionSet of expandedConditionSets) {
1493
+ // First, check if ALL paths in this condition set are controllable (or can be expanded to controllable sources)
1494
+ const resolvedPaths = new Map<string, string>();
1495
+ // Track expanded sources for derived variables (path -> array of expanded sources)
1496
+ const expandedSources = new Map<
1497
+ string,
1498
+ Array<{ path: string; operation?: DerivedVariableOperation }>
1499
+ >();
1500
+ let allControllable = true;
1501
+
1502
+ for (const condition of conditionSet) {
1503
+ // Check if this condition path has derivation info
1504
+ // First check conditionalUsages, then fall back to derivedVariables
1505
+ const usagesForPath = conditionalUsages[condition.path];
1506
+ let derivedFromInfo = usagesForPath?.find(
1507
+ (u) => u.derivedFrom?.operation,
1508
+ )?.derivedFrom;
1509
+
1510
+ // CRITICAL: Also check derivedVariables for intermediate derived variables
1511
+ if (!derivedFromInfo && derivedVariables?.[condition.path]) {
1512
+ derivedFromInfo = derivedVariables[condition.path];
1513
+ }
667
1514
 
668
- for (const condition of compound.conditions) {
669
- const resolution = resolvePathToControllable(
670
- condition.path,
671
- attributesMap,
672
- equivalentSignatureVariables,
673
- fullToShortPathMap,
674
- );
1515
+ if (derivedFromInfo) {
1516
+ // This is a derived variable - expand to its sources
1517
+ const sources = expandDerivedVariableToSources(
1518
+ condition.path,
1519
+ conditionalUsages,
1520
+ attributesMap,
1521
+ equivalentSignatureVariables,
1522
+ fullToShortPathMap,
1523
+ new Set(),
1524
+ derivedVariables,
1525
+ );
1526
+
1527
+ if (sources.length > 0) {
1528
+ // Store the expanded sources for this condition
1529
+ expandedSources.set(condition.path, sources);
1530
+ // Use the first source's path for the resolvedPaths map (for ID generation)
1531
+ resolvedPaths.set(condition.path, sources[0].path);
1532
+ } else {
1533
+ // Derived variable expansion failed — try sourceDataPath fallback
1534
+ // This handles cases where the derivation chain goes through useMemo/useState
1535
+ // but the enriched sourceDataPath already traced to the actual data source
1536
+ const usageWithSource = usagesForPath?.find(
1537
+ (u) => u.sourceDataPath,
1538
+ );
1539
+ let derivedFallbackPath: string | null = null;
1540
+
1541
+ if (usageWithSource?.sourceDataPath) {
1542
+ const cleanedPath = cleanSourceDataPath(
1543
+ usageWithSource.sourceDataPath,
1544
+ );
1545
+ if (cleanedPath) {
1546
+ const pathMatch = findInAttributesMapForPath(
1547
+ cleanedPath,
1548
+ attributesMap,
1549
+ fullToShortPathMap,
1550
+ );
1551
+ if (pathMatch) {
1552
+ derivedFallbackPath = pathMatch;
1553
+ }
1554
+ }
1555
+ }
1556
+
1557
+ if (derivedFallbackPath) {
1558
+ resolvedPaths.set(condition.path, derivedFallbackPath);
1559
+ console.log(
1560
+ `[genFlowsFromConditionals] COMPOUND "${condition.path}" derived expansion failed but sourceDataPath fallback resolved → "${derivedFallbackPath}"`,
1561
+ );
1562
+ } else {
1563
+ // Truly not controllable
1564
+ console.log(
1565
+ `[genFlowsFromConditionals] COMPOUND "${condition.path}" derived but no controllable sources and no sourceDataPath fallback → NOT controllable`,
1566
+ );
1567
+ allControllable = false;
1568
+ break;
1569
+ }
1570
+ }
1571
+ } else {
1572
+ // Not a derived variable - resolve directly
1573
+ // First try sourceDataPath from the usage (same as individual processing)
1574
+ let compoundResolvedPath: string | null = null;
1575
+
1576
+ const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
1577
+ if (usageWithSource?.sourceDataPath) {
1578
+ const cleanedPath = cleanSourceDataPath(
1579
+ usageWithSource.sourceDataPath,
1580
+ );
1581
+ if (cleanedPath) {
1582
+ const pathMatch = findInAttributesMapForPath(
1583
+ cleanedPath,
1584
+ attributesMap,
1585
+ fullToShortPathMap,
1586
+ );
1587
+ if (pathMatch) {
1588
+ compoundResolvedPath = pathMatch;
1589
+ }
1590
+ }
1591
+ }
1592
+
1593
+ if (!compoundResolvedPath) {
1594
+ const resolution = resolvePathToControllable(
1595
+ condition.path,
1596
+ attributesMap,
1597
+ equivalentSignatureVariables,
1598
+ fullToShortPathMap,
1599
+ );
675
1600
 
676
- if (!resolution.isControllable || !resolution.resolvedPath) {
677
- allControllable = false;
678
- break;
1601
+ if (resolution.isControllable && resolution.resolvedPath) {
1602
+ compoundResolvedPath = resolution.resolvedPath;
1603
+ }
1604
+ }
1605
+
1606
+ if (!compoundResolvedPath) {
1607
+ allControllable = false;
1608
+ break;
1609
+ }
1610
+
1611
+ resolvedPaths.set(condition.path, compoundResolvedPath);
1612
+ }
679
1613
  }
680
1614
 
681
- resolvedPaths.set(condition.path, resolution.resolvedPath);
682
- }
1615
+ // Only create a flow if ALL paths are controllable
1616
+ if (allControllable && resolvedPaths.size > 0) {
1617
+ // If any conditions were expanded from derived variables, we need to build a custom flow
1618
+ if (expandedSources.size > 0) {
1619
+ const requiredValues: ExecutionFlow['requiredValues'] = [];
1620
+
1621
+ for (const condition of conditionSet) {
1622
+ const sources = expandedSources.get(condition.path);
1623
+
1624
+ if (sources) {
1625
+ // This condition was expanded - add all its sources
1626
+ // Determine the required value based on condition type and derivation operation
1627
+ const usagesForPath = conditionalUsages[condition.path];
1628
+ let expandedDerivedFrom = usagesForPath?.find(
1629
+ (u) => u.derivedFrom?.operation,
1630
+ )?.derivedFrom;
1631
+
1632
+ // Also check derivedVariables for intermediate derived variables
1633
+ if (!expandedDerivedFrom && derivedVariables?.[condition.path]) {
1634
+ expandedDerivedFrom = derivedVariables[condition.path];
1635
+ }
1636
+ const operation = expandedDerivedFrom?.operation;
1637
+
1638
+ for (const source of sources) {
1639
+ // For OR-derived truthy: ANY source truthy
1640
+ // For AND-derived truthy: ALL sources truthy
1641
+ // For negated: inverse
1642
+ let value: string;
1643
+ let comparison: ExecutionFlow['requiredValues'][0]['comparison'];
1644
+
1645
+ if (condition.conditionType === 'truthiness') {
1646
+ const isNegated = condition.isNegated === true;
1647
+ // For OR: truthy needs ANY source truthy, falsy needs ALL sources falsy
1648
+ // For AND: truthy needs ALL sources truthy, falsy needs ANY source falsy
1649
+ // In compound conditionals, we generate the truthy path by default
1650
+ // (the compound expression must be truthy)
1651
+ if (operation === 'or') {
1652
+ // For OR-derived, truthy means we need at least one source truthy
1653
+ // We'll use the first source as truthy (simplification)
1654
+ value = isNegated ? 'falsy' : 'truthy';
1655
+ } else if (operation === 'and') {
1656
+ // For AND-derived, truthy means ALL sources truthy
1657
+ value = isNegated ? 'falsy' : 'truthy';
1658
+ } else {
1659
+ value = isNegated ? 'falsy' : 'truthy';
1660
+ }
1661
+ comparison = isNegated ? 'falsy' : 'truthy';
1662
+ } else {
1663
+ value = 'truthy';
1664
+ comparison = 'truthy';
1665
+ }
683
1666
 
684
- // Only create a flow if ALL paths are controllable
685
- if (allControllable && resolvedPaths.size > 0) {
686
- const compoundFlow = generateFlowFromCompound(compound, resolvedPaths);
687
- if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
688
- seenFlowIds.add(compoundFlow.id);
689
- flows.push(compoundFlow);
1667
+ requiredValues.push({
1668
+ attributePath: source.path,
1669
+ value,
1670
+ comparison,
1671
+ valueType: 'boolean' as const,
1672
+ });
1673
+ }
1674
+ } else {
1675
+ // This condition was resolved directly
1676
+ const resolvedPath = resolvedPaths.get(condition.path);
1677
+ if (resolvedPath) {
1678
+ let value: string;
1679
+ let comparison: ExecutionFlow['requiredValues'][0]['comparison'];
1680
+
1681
+ if (condition.conditionType === 'truthiness') {
1682
+ value = condition.isNegated ? 'falsy' : 'truthy';
1683
+ comparison = condition.isNegated ? 'falsy' : 'truthy';
1684
+ } else {
1685
+ value =
1686
+ condition.requiredValue?.toString() ??
1687
+ condition.comparedValues?.[0] ??
1688
+ 'truthy';
1689
+ const op = condition.comparisonOperator;
1690
+ if (op === '>' || op === '>=') {
1691
+ comparison = 'length>';
1692
+ } else if (op === '<' || op === '<=') {
1693
+ comparison = 'length<';
1694
+ } else {
1695
+ comparison = 'equals';
1696
+ }
1697
+ }
1698
+
1699
+ requiredValues.push({
1700
+ attributePath: stripLengthSuffix(resolvedPath),
1701
+ value,
1702
+ comparison,
1703
+ valueType: inferValueType(value),
1704
+ });
1705
+ }
1706
+ }
1707
+ }
1708
+
1709
+ // Remove contradictory "falsy" values where a child path requires data
1710
+ const cleanedValues = removeContradictoryFalsyValues(requiredValues);
1711
+
1712
+ if (cleanedValues.length > 0) {
1713
+ const impact: ExecutionFlow['impact'] =
1714
+ compound.controlsJsxRendering ? 'high' : 'medium';
1715
+
1716
+ // Generate a combined ID from all paths + values
1717
+ const pathParts = cleanedValues
1718
+ .map((rv) => {
1719
+ const name = generateNameFromPath(rv.attributePath);
1720
+ const suffix =
1721
+ rv.comparison === 'truthy' || rv.comparison === 'falsy'
1722
+ ? `-${rv.comparison}`
1723
+ : `-${rv.comparison}-${rv.value}`;
1724
+ return name.toLowerCase().replace(/\s+/g, '-') + suffix;
1725
+ })
1726
+ .join('-and-');
1727
+
1728
+ const compoundFlow: ExecutionFlow = {
1729
+ id: `${pathParts}`,
1730
+ name: generateNameFromPath(cleanedValues[0].attributePath),
1731
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
1732
+ impact,
1733
+ requiredValues: cleanedValues,
1734
+ sourceLocation: compound.sourceLocation,
1735
+ };
1736
+
1737
+ if (!seenFlowIds.has(compoundFlow.id)) {
1738
+ seenFlowIds.add(compoundFlow.id);
1739
+ flows.push(compoundFlow);
1740
+ }
1741
+ }
1742
+ } else {
1743
+ // No derived variables - use the original generateFlowFromCompound
1744
+ // Create a modified compound with just this condition set
1745
+ const modifiedCompound = {
1746
+ ...compound,
1747
+ conditions: conditionSet,
1748
+ };
1749
+ const compoundFlow = generateFlowFromCompound(
1750
+ modifiedCompound,
1751
+ resolvedPaths,
1752
+ );
1753
+ if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
1754
+ seenFlowIds.add(compoundFlow.id);
1755
+ flows.push(compoundFlow);
1756
+ }
1757
+ }
690
1758
  }
691
1759
  }
692
1760
  }
@@ -733,7 +1801,18 @@ export default function generateExecutionFlowsFromConditionals(
733
1801
  fullToShortPathMap,
734
1802
  );
735
1803
 
1804
+ // Only use controllable paths for gating conditions (whitelist approach).
1805
+ // Do NOT fall back to equivalentSignatureVariables because those may contain
1806
+ // uncontrollable paths like useState that cannot be mocked.
1807
+ let resolvedVarPath: string | null = null;
736
1808
  if (varResolution.isControllable && varResolution.resolvedPath) {
1809
+ resolvedVarPath = varResolution.resolvedPath;
1810
+ }
1811
+ // Note: We intentionally do NOT fall back to equivalentSignatureVariables here
1812
+ // because that would allow uncontrollable paths (like useState) to be added
1813
+ // as gating conditions.
1814
+
1815
+ if (resolvedVarPath) {
737
1816
  const isNegated = (gatingCondition as any).isNegated === true;
738
1817
  const isNotEquals = operator === '!=' || operator === '!==';
739
1818
  // Determine the effective value for this gating condition
@@ -744,7 +1823,7 @@ export default function generateExecutionFlowsFromConditionals(
744
1823
  const needsExactValue = isNegated !== isNotEquals;
745
1824
 
746
1825
  gatingRequiredValues.push({
747
- attributePath: varResolution.resolvedPath,
1826
+ attributePath: resolvedVarPath,
748
1827
  value: needsExactValue ? 'falsy' : comparedValue,
749
1828
  comparison: needsExactValue ? 'falsy' : 'equals',
750
1829
  });
@@ -810,7 +1889,9 @@ export default function generateExecutionFlowsFromConditionals(
810
1889
  // For non-negated &&: all parts must be truthy
811
1890
  // For negated ||: all parts must be falsy (DeMorgan: !(A || B) = !A && !B)
812
1891
  gatingRequiredValues.push({
813
- attributePath: partResolution.resolvedPath,
1892
+ attributePath: stripLengthSuffix(
1893
+ partResolution.resolvedPath,
1894
+ ),
814
1895
  value: isNegated ? 'falsy' : 'truthy',
815
1896
  comparison: isNegated ? 'falsy' : 'truthy',
816
1897
  });
@@ -827,16 +1908,27 @@ export default function generateExecutionFlowsFromConditionals(
827
1908
  fullToShortPathMap,
828
1909
  );
829
1910
 
1911
+ // Only use controllable paths for gating conditions (whitelist approach).
1912
+ // Do NOT fall back to equivalentSignatureVariables because those may contain
1913
+ // uncontrollable paths like useState that cannot be mocked.
1914
+ let resolvedGatingPath: string | null = null;
830
1915
  if (
831
1916
  gatingResolution.isControllable &&
832
1917
  gatingResolution.resolvedPath
833
1918
  ) {
1919
+ resolvedGatingPath = gatingResolution.resolvedPath;
1920
+ }
1921
+ // Note: We intentionally do NOT fall back to equivalentSignatureVariables here
1922
+ // because that would allow uncontrollable paths (like useState) to be added
1923
+ // as gating conditions.
1924
+
1925
+ if (resolvedGatingPath) {
834
1926
  // For truthiness conditions on gating, check if the condition is negated
835
1927
  // e.g., ternary else branch: isError ? <ErrorView /> : <SuccessView />
836
1928
  // SuccessView has isNegated: true, meaning it renders when isError is falsy
837
1929
  const isNegated = (gatingCondition as any).isNegated === true;
838
1930
  gatingRequiredValues.push({
839
- attributePath: gatingResolution.resolvedPath,
1931
+ attributePath: resolvedGatingPath,
840
1932
  value: isNegated ? 'falsy' : 'truthy',
841
1933
  comparison: isNegated ? 'falsy' : 'truthy',
842
1934
  });
@@ -894,6 +1986,7 @@ export default function generateExecutionFlowsFromConditionals(
894
1986
  }
895
1987
 
896
1988
  // Now resolve the translated path in the parent context
1989
+ // First, try standard resolution
897
1990
  const resolution = resolvePathToControllable(
898
1991
  translatedPath,
899
1992
  attributesMap,
@@ -901,12 +1994,124 @@ export default function generateExecutionFlowsFromConditionals(
901
1994
  fullToShortPathMap,
902
1995
  );
903
1996
 
904
- if (!resolution.isControllable || !resolution.resolvedPath) {
905
- // Path is not controllable in parent context
906
- continue;
907
- }
1997
+ // Only create flows for controllable paths (whitelist approach).
1998
+ // If the path doesn't resolve to something in attributesMap, skip it.
1999
+ // This prevents creating flows for useState values which are not
2000
+ // controllable via mock data injection.
2001
+ let resolvedPath = resolution.resolvedPath;
2002
+
2003
+ if (!resolution.isControllable || !resolvedPath) {
2004
+ // Path is not controllable via standard resolution.
2005
+ // Try fallback: For useState values (cyScope*().functionCallReturnValue),
2006
+ // look for a related URL parameter like "varNameFromUrl" that might
2007
+ // control the initial state.
2008
+ //
2009
+ // Example: viewMode → cyScope20().functionCallReturnValue (useState value)
2010
+ // Fallback: viewModeFromUrl → segments[2] (URL param that initializes the useState)
2011
+ const useStateMatch = translatedPath.match(
2012
+ /^cyScope\d+\(\)\.functionCallReturnValue$/,
2013
+ );
2014
+
2015
+ if (useStateMatch) {
2016
+ // Find what variable this useState value corresponds to by looking
2017
+ // for entries like "varName": "cyScope20()" in equivalentSignatureVariables
2018
+ const useStatePattern = translatedPath.replace(
2019
+ /\.functionCallReturnValue$/,
2020
+ '',
2021
+ ); // e.g., "cyScope20()"
2022
+
2023
+ // Find the variable name that maps to this useState
2024
+ let useStateVarName: string | null = null;
2025
+ for (const [varName, varPath] of Object.entries(
2026
+ equivalentSignatureVariables,
2027
+ )) {
2028
+ if (varPath === useStatePattern) {
2029
+ useStateVarName = varName;
2030
+ break;
2031
+ }
2032
+ }
2033
+
2034
+ if (useStateVarName) {
2035
+ // Look for a related URL param like "varNameFromUrl"
2036
+ const urlParamName = `${useStateVarName}FromUrl`;
2037
+ const urlParamPath = equivalentSignatureVariables[urlParamName];
2038
+
2039
+ if (urlParamPath) {
2040
+ // For useState values initialized from URL params, use the
2041
+ // URL param variable name directly (e.g., "viewModeFromUrl")
2042
+ // rather than fully resolving it. This keeps the path meaningful
2043
+ // for scenario generation and avoids overly generic paths like
2044
+ // "useParams().functionCallReturnValue.*".
2045
+ //
2046
+ // The flow will use the URL param name as the attributePath,
2047
+ // which gets properly resolved when generating mock data.
2048
+ resolvedPath = urlParamName;
2049
+ }
2050
+ }
2051
+ }
2052
+
2053
+ // Fallback 2: Try sourceEquivalencies to find the actual data source
2054
+ // This handles the case where props flow through useState but originate
2055
+ // from a mockable data source (e.g., API call, fetcher).
2056
+ //
2057
+ // Example: WorkoutsView receives `workouts` prop which in parent is stored
2058
+ // in useState, but ultimately comes from a Supabase query.
2059
+ // sourceEquivalencies tells us: "WorkoutsView().signature[0].workouts" → "createClient()...data"
2060
+ if (!resolvedPath && sourceEquivalencies) {
2061
+ // Build the child prop path to look up in sourceEquivalencies
2062
+ // Format: "ChildName().signature[0].propName"
2063
+ // First, find what prop this child path maps to
2064
+ let childPropName: string | null = null;
2065
+ for (const [varName, varPath] of Object.entries(
2066
+ childData.equivalentSignatureVariables,
2067
+ )) {
2068
+ // Check if childPath starts with this variable name
2069
+ // e.g., childPath = "workouts.length", varName = "workouts", varPath = "signature[0].workouts"
2070
+ if (
2071
+ childPath === varName ||
2072
+ childPath.startsWith(`${varName}.`)
2073
+ ) {
2074
+ childPropName = varName;
2075
+ break;
2076
+ }
2077
+ }
908
2078
 
909
- const resolvedPath = resolution.resolvedPath;
2079
+ if (childPropName) {
2080
+ // Build the full sourceEquivalencies key
2081
+ const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
2082
+
2083
+ const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
2084
+ if (sourceEquivEntry && sourceEquivEntry.length > 0) {
2085
+ const dataSourcePath = sourceEquivEntry[0].schemaPath;
2086
+
2087
+ // Check if this data source path is controllable
2088
+ const dataSourceResolution = resolvePathToControllable(
2089
+ dataSourcePath,
2090
+ attributesMap,
2091
+ equivalentSignatureVariables,
2092
+ fullToShortPathMap,
2093
+ );
2094
+
2095
+ if (
2096
+ dataSourceResolution.isControllable &&
2097
+ dataSourceResolution.resolvedPath
2098
+ ) {
2099
+ // Preserve any suffix from the child path
2100
+ // e.g., childPath = "workouts.length" → suffix = ".length"
2101
+ const suffix = childPath.startsWith(`${childPropName}.`)
2102
+ ? childPath.slice(childPropName.length)
2103
+ : '';
2104
+ resolvedPath = dataSourceResolution.resolvedPath + suffix;
2105
+ }
2106
+ }
2107
+ }
2108
+ }
2109
+
2110
+ // If still not resolved after fallback, skip
2111
+ if (!resolvedPath) {
2112
+ continue;
2113
+ }
2114
+ }
910
2115
 
911
2116
  // Check for duplicates
912
2117
  const normalizedPath = normalizePathForDeduplication(
@@ -967,7 +2172,7 @@ export default function generateExecutionFlowsFromConditionals(
967
2172
  // Process child's compound conditionals
968
2173
  for (const compound of childData.compoundConditionals) {
969
2174
  const resolvedPaths = new Map<string, string>();
970
- let allControllable = true;
2175
+ let allResolvable = true;
971
2176
 
972
2177
  for (const condition of compound.conditions) {
973
2178
  // Determine the child path to translate
@@ -982,7 +2187,7 @@ export default function generateExecutionFlowsFromConditionals(
982
2187
  );
983
2188
 
984
2189
  if (!translatedPath) {
985
- allControllable = false;
2190
+ allResolvable = false;
986
2191
  break;
987
2192
  }
988
2193
 
@@ -993,27 +2198,287 @@ export default function generateExecutionFlowsFromConditionals(
993
2198
  fullToShortPathMap,
994
2199
  );
995
2200
 
996
- if (!resolution.isControllable || !resolution.resolvedPath) {
997
- allControllable = false;
2201
+ // Only create flows for controllable paths (whitelist approach).
2202
+ // If the path doesn't resolve to something in attributesMap, skip it.
2203
+ // This prevents creating flows for useState values which are not
2204
+ // controllable via mock data injection.
2205
+ let resolvedPath = resolution.resolvedPath;
2206
+
2207
+ if (!resolution.isControllable || !resolvedPath) {
2208
+ // Path is not controllable via standard resolution.
2209
+ // Try fallback: For useState values (cyScope*().functionCallReturnValue),
2210
+ // look for a related URL parameter like "varNameFromUrl" that might
2211
+ // control the initial state.
2212
+ const useStateMatch = translatedPath.match(
2213
+ /^cyScope\d+\(\)\.functionCallReturnValue$/,
2214
+ );
2215
+
2216
+ if (useStateMatch) {
2217
+ const useStatePattern = translatedPath.replace(
2218
+ /\.functionCallReturnValue$/,
2219
+ '',
2220
+ );
2221
+
2222
+ // Find the variable name that maps to this useState
2223
+ let useStateVarName: string | null = null;
2224
+ for (const [varName, varPath] of Object.entries(
2225
+ equivalentSignatureVariables,
2226
+ )) {
2227
+ if (varPath === useStatePattern) {
2228
+ useStateVarName = varName;
2229
+ break;
2230
+ }
2231
+ }
2232
+
2233
+ if (useStateVarName) {
2234
+ const urlParamName = `${useStateVarName}FromUrl`;
2235
+ const urlParamPath = equivalentSignatureVariables[urlParamName];
2236
+
2237
+ if (urlParamPath) {
2238
+ resolvedPath = urlParamName;
2239
+ }
2240
+ }
2241
+ }
2242
+ }
2243
+
2244
+ if (!resolvedPath) {
2245
+ allResolvable = false;
998
2246
  break;
999
2247
  }
1000
2248
 
1001
- resolvedPaths.set(condition.path, resolution.resolvedPath);
2249
+ resolvedPaths.set(condition.path, resolvedPath);
1002
2250
  }
1003
2251
 
1004
- if (allControllable && resolvedPaths.size > 0) {
2252
+ if (allResolvable && resolvedPaths.size > 0) {
1005
2253
  const compoundFlow = generateFlowFromCompound(
1006
2254
  compound,
1007
2255
  resolvedPaths,
1008
2256
  );
1009
- if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
1010
- seenFlowIds.add(compoundFlow.id);
1011
- flows.push(compoundFlow);
2257
+ if (compoundFlow) {
2258
+ // Add gating conditions to compound flow (same as regular usage flows)
2259
+ if (gatingRequiredValues.length > 0) {
2260
+ // Filter out any gating values that are already in the flow
2261
+ const existingPaths = new Set(
2262
+ compoundFlow.requiredValues.map((rv) => rv.attributePath),
2263
+ );
2264
+ const newGatingValues = gatingRequiredValues.filter(
2265
+ (gv) => !existingPaths.has(gv.attributePath),
2266
+ );
2267
+ compoundFlow.requiredValues = [
2268
+ ...compoundFlow.requiredValues,
2269
+ ...newGatingValues,
2270
+ ];
2271
+
2272
+ // Update the flow ID to include gating conditions
2273
+ if (newGatingValues.length > 0) {
2274
+ const gatingIdPart = newGatingValues
2275
+ .map((gv) => `${gv.attributePath}-${gv.value}`)
2276
+ .join('-');
2277
+ compoundFlow.id = `${compoundFlow.id}-gated-${gatingIdPart}`;
2278
+ }
2279
+ }
2280
+
2281
+ if (!seenFlowIds.has(compoundFlow.id)) {
2282
+ seenFlowIds.add(compoundFlow.id);
2283
+ flows.push(compoundFlow);
2284
+ }
2285
+ }
2286
+ }
2287
+ }
2288
+
2289
+ // Process child's jsxRenderingUsages (array.map flows)
2290
+ // This generates array variation flows (empty, few, many) for arrays rendered in child
2291
+ if (childData.jsxRenderingUsages) {
2292
+ for (const jsxUsage of childData.jsxRenderingUsages) {
2293
+ // Translate the child path to a parent path
2294
+ const translatedPath = translateChildPathToParent(
2295
+ jsxUsage.path,
2296
+ childData.equivalentSignatureVariables,
2297
+ equivalentSignatureVariables,
2298
+ childName,
2299
+ );
2300
+
2301
+ if (!translatedPath) {
2302
+ continue;
2303
+ }
2304
+
2305
+ // Resolve to controllable path in parent context
2306
+ const resolution = resolvePathToControllable(
2307
+ translatedPath,
2308
+ attributesMap,
2309
+ equivalentSignatureVariables,
2310
+ fullToShortPathMap,
2311
+ );
2312
+
2313
+ let resolvedPath = resolution.resolvedPath;
2314
+
2315
+ // Try sourceEquivalencies fallback if not controllable
2316
+ if (!resolution.isControllable || !resolvedPath) {
2317
+ if (sourceEquivalencies) {
2318
+ // Build the sourceEquivalencies key
2319
+ // The child path (e.g., "workouts") maps to a prop path (e.g., "signature[0].workouts")
2320
+ let childPropName: string | null = null;
2321
+ for (const [varName, varPath] of Object.entries(
2322
+ childData.equivalentSignatureVariables,
2323
+ )) {
2324
+ if (
2325
+ jsxUsage.path === varName ||
2326
+ jsxUsage.path.startsWith(`${varName}.`)
2327
+ ) {
2328
+ childPropName = varName;
2329
+ break;
2330
+ }
2331
+ }
2332
+
2333
+ if (childPropName) {
2334
+ const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
2335
+ const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
2336
+
2337
+ if (sourceEquivEntry && sourceEquivEntry.length > 0) {
2338
+ const dataSourcePath = sourceEquivEntry[0].schemaPath;
2339
+
2340
+ const dataSourceResolution = resolvePathToControllable(
2341
+ dataSourcePath,
2342
+ attributesMap,
2343
+ equivalentSignatureVariables,
2344
+ fullToShortPathMap,
2345
+ );
2346
+
2347
+ if (
2348
+ dataSourceResolution.isControllable &&
2349
+ dataSourceResolution.resolvedPath
2350
+ ) {
2351
+ resolvedPath = dataSourceResolution.resolvedPath;
2352
+ }
2353
+ }
2354
+ }
2355
+ }
2356
+ }
2357
+
2358
+ if (!resolvedPath) {
2359
+ continue;
2360
+ }
2361
+
2362
+ // Check for duplicates
2363
+ const normalizedPath = normalizePathForDeduplication(
2364
+ resolvedPath,
2365
+ fullToShortPathMap,
2366
+ );
2367
+ const dedupeKey = `${normalizedPath}:${jsxUsage.renderingType}`;
2368
+ if (seenNormalizedPaths.has(dedupeKey)) {
2369
+ continue;
2370
+ }
2371
+ seenNormalizedPaths.add(dedupeKey);
2372
+
2373
+ // Generate array variation flows for array-map rendering
2374
+ if (jsxUsage.renderingType === 'array-map') {
2375
+ const baseName = generateNameFromPath(resolvedPath);
2376
+ const pathSlug = pathToSlug(resolvedPath);
2377
+ const exclusiveGroup = `array-length-${pathSlug}`;
2378
+
2379
+ // Empty array flow
2380
+ const emptyFlow: ExecutionFlow = {
2381
+ id: `${pathSlug}-empty-array`,
2382
+ name: `${baseName} Empty`,
2383
+ description: `When ${baseName.toLowerCase()} array is empty`,
2384
+ requiredValues: [
2385
+ {
2386
+ attributePath: resolvedPath,
2387
+ value: '0',
2388
+ comparison: 'length<',
2389
+ valueType: 'array',
2390
+ },
2391
+ ...gatingRequiredValues,
2392
+ ],
2393
+ impact: 'medium',
2394
+ exclusiveGroup,
2395
+ sourceLocation: jsxUsage.sourceLocation
2396
+ ? {
2397
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
2398
+ column: jsxUsage.sourceLocation.column,
2399
+ }
2400
+ : undefined,
2401
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
2402
+ };
2403
+
2404
+ if (!seenFlowIds.has(emptyFlow.id)) {
2405
+ seenFlowIds.add(emptyFlow.id);
2406
+ flows.push(emptyFlow);
2407
+ }
2408
+
2409
+ // Few items flow (1-3)
2410
+ const fewFlow: ExecutionFlow = {
2411
+ id: `${pathSlug}-few-items`,
2412
+ name: `${baseName} Few Items`,
2413
+ description: `When ${baseName.toLowerCase()} array has 1-3 items`,
2414
+ requiredValues: [
2415
+ {
2416
+ attributePath: resolvedPath,
2417
+ value: '3',
2418
+ comparison: 'length<',
2419
+ valueType: 'array',
2420
+ },
2421
+ ...gatingRequiredValues,
2422
+ ],
2423
+ impact: 'low',
2424
+ exclusiveGroup,
2425
+ sourceLocation: jsxUsage.sourceLocation
2426
+ ? {
2427
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
2428
+ column: jsxUsage.sourceLocation.column,
2429
+ }
2430
+ : undefined,
2431
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
2432
+ };
2433
+
2434
+ if (!seenFlowIds.has(fewFlow.id)) {
2435
+ seenFlowIds.add(fewFlow.id);
2436
+ flows.push(fewFlow);
2437
+ }
2438
+
2439
+ // Many items flow (10+)
2440
+ const manyFlow: ExecutionFlow = {
2441
+ id: `${pathSlug}-many-items`,
2442
+ name: `${baseName} Many Items`,
2443
+ description: `When ${baseName.toLowerCase()} array has many items`,
2444
+ requiredValues: [
2445
+ {
2446
+ attributePath: resolvedPath,
2447
+ value: '10',
2448
+ comparison: 'length>',
2449
+ valueType: 'array',
2450
+ },
2451
+ ...gatingRequiredValues,
2452
+ ],
2453
+ impact: 'low',
2454
+ exclusiveGroup,
2455
+ sourceLocation: jsxUsage.sourceLocation
2456
+ ? {
2457
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
2458
+ column: jsxUsage.sourceLocation.column,
2459
+ }
2460
+ : undefined,
2461
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
2462
+ };
2463
+
2464
+ if (!seenFlowIds.has(manyFlow.id)) {
2465
+ seenFlowIds.add(manyFlow.id);
2466
+ flows.push(manyFlow);
2467
+ }
1012
2468
  }
1013
2469
  }
1014
2470
  }
1015
2471
  }
1016
2472
  }
1017
2473
 
2474
+ console.log(
2475
+ `[genFlowsFromConditionals] RESULT: ${flows.length} total flows generated`,
2476
+ );
2477
+ for (const flow of flows) {
2478
+ console.log(
2479
+ `[genFlowsFromConditionals] FLOW: id="${flow.id}" requiredValues=[${flow.requiredValues.map((rv) => `${rv.attributePath}=${rv.value}`).join(', ')}]`,
2480
+ );
2481
+ }
2482
+
1018
2483
  return flows;
1019
2484
  }