@codeyam/codeyam-cli 0.1.0-staging.323686 → 0.1.0-staging.4813bf3

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 (444) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +5 -5
  4. package/analyzer-template/packages/ai/index.ts +7 -1
  5. package/analyzer-template/packages/ai/package.json +2 -2
  6. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +62 -18
  7. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +67 -9
  8. package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
  9. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +409 -50
  10. package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
  11. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +21 -6
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +992 -249
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +5 -1
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +31 -3
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +37 -15
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
  19. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +126 -11
  20. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +179 -0
  21. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
  22. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +367 -96
  23. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +33 -15
  24. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +58 -3
  25. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +315 -6
  26. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +9 -5
  27. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +49 -5
  28. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
  29. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +649 -142
  30. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +1 -1
  31. package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +51 -3
  32. package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
  33. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
  34. package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
  35. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
  36. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
  37. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +25 -13
  38. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +4 -3
  39. package/analyzer-template/packages/analyze/index.ts +2 -0
  40. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
  41. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
  42. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
  43. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
  44. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
  45. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
  46. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
  47. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
  48. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +89 -9
  49. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +19 -4
  50. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
  51. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +0 -3
  52. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
  53. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
  54. package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1315 -0
  55. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +61 -13
  56. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +37 -0
  57. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +229 -19
  58. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +117 -9
  59. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +459 -39
  60. package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
  61. package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
  62. package/analyzer-template/packages/analyze/src/lib/index.ts +1 -0
  63. package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
  64. package/analyzer-template/packages/aws/package.json +1 -1
  65. package/analyzer-template/packages/database/package.json +1 -1
  66. package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
  67. package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
  68. package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
  69. package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
  70. package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
  71. package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
  72. package/analyzer-template/packages/database/src/lib/kysely/db.ts +6 -0
  73. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  74. package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
  75. package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
  76. package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
  77. package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
  78. package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
  79. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
  80. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
  81. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
  82. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
  83. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
  84. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
  85. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
  86. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
  87. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
  88. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
  89. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
  90. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
  91. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -0
  92. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  93. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +3 -0
  94. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  95. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  96. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
  97. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
  98. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  99. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  100. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
  101. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
  102. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
  103. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
  104. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
  105. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
  106. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  107. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  108. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +5 -5
  109. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  110. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  111. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  112. package/analyzer-template/packages/github/package.json +1 -1
  113. package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
  114. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +6 -5
  115. package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
  116. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  117. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  118. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +5 -5
  119. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  120. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  121. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  122. package/analyzer-template/project/constructMockCode.ts +90 -10
  123. package/analyzer-template/project/writeMockDataTsx.ts +181 -8
  124. package/analyzer-template/project/writeScenarioComponents.ts +60 -12
  125. package/analyzer-template/project/writeSimpleRoot.ts +21 -11
  126. package/background/src/lib/local/createLocalAnalyzer.js +1 -1
  127. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  128. package/background/src/lib/virtualized/project/constructMockCode.js +75 -4
  129. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  130. package/background/src/lib/virtualized/project/writeMockDataTsx.js +162 -4
  131. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  132. package/background/src/lib/virtualized/project/writeScenarioComponents.js +60 -15
  133. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  134. package/background/src/lib/virtualized/project/writeSimpleRoot.js +21 -11
  135. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  136. package/codeyam-cli/scripts/apply-setup.js +180 -0
  137. package/codeyam-cli/scripts/apply-setup.js.map +1 -1
  138. package/codeyam-cli/src/cli.js +2 -0
  139. package/codeyam-cli/src/cli.js.map +1 -1
  140. package/codeyam-cli/src/codeyam-cli.js +18 -2
  141. package/codeyam-cli/src/codeyam-cli.js.map +1 -1
  142. package/codeyam-cli/src/commands/analyze.js +4 -2
  143. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  144. package/codeyam-cli/src/commands/baseline.js +2 -0
  145. package/codeyam-cli/src/commands/baseline.js.map +1 -1
  146. package/codeyam-cli/src/commands/debug.js +9 -5
  147. package/codeyam-cli/src/commands/debug.js.map +1 -1
  148. package/codeyam-cli/src/commands/default.js +31 -20
  149. package/codeyam-cli/src/commands/default.js.map +1 -1
  150. package/codeyam-cli/src/commands/detect-universal-mocks.js +2 -0
  151. package/codeyam-cli/src/commands/detect-universal-mocks.js.map +1 -1
  152. package/codeyam-cli/src/commands/init.js +49 -257
  153. package/codeyam-cli/src/commands/init.js.map +1 -1
  154. package/codeyam-cli/src/commands/memory.js +17 -26
  155. package/codeyam-cli/src/commands/memory.js.map +1 -1
  156. package/codeyam-cli/src/commands/recapture.js +2 -0
  157. package/codeyam-cli/src/commands/recapture.js.map +1 -1
  158. package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
  159. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  160. package/codeyam-cli/src/commands/setup-simulations.js +284 -0
  161. package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
  162. package/codeyam-cli/src/commands/test-startup.js +2 -0
  163. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  164. package/codeyam-cli/src/commands/verify.js +14 -2
  165. package/codeyam-cli/src/commands/verify.js.map +1 -1
  166. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -86
  167. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  168. package/codeyam-cli/src/utils/analyzer.js +7 -0
  169. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  170. package/codeyam-cli/src/utils/backgroundServer.js +5 -0
  171. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  172. package/codeyam-cli/src/utils/generateReport.js +2 -2
  173. package/codeyam-cli/src/utils/install-skills.js +70 -45
  174. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  175. package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
  176. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
  177. package/codeyam-cli/src/utils/progress.js +7 -0
  178. package/codeyam-cli/src/utils/progress.js.map +1 -1
  179. package/codeyam-cli/src/utils/queue/job.js +4 -0
  180. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  181. package/codeyam-cli/src/utils/requireSimulations.js +10 -0
  182. package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
  183. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
  184. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
  185. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +230 -0
  186. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
  187. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
  188. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
  189. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
  190. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
  191. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
  192. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
  193. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
  194. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
  195. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +75 -0
  196. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
  197. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +378 -0
  198. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
  199. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +115 -0
  200. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
  201. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
  202. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
  203. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
  204. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
  205. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
  206. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
  207. package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
  208. package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
  209. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
  210. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
  211. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
  212. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
  213. package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
  214. package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
  215. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
  216. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
  217. package/codeyam-cli/src/utils/rules/index.js +1 -0
  218. package/codeyam-cli/src/utils/rules/index.js.map +1 -1
  219. package/codeyam-cli/src/utils/rules/parser.js +2 -25
  220. package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
  221. package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
  222. package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
  223. package/codeyam-cli/src/utils/rules/staleness.js +16 -11
  224. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
  225. package/codeyam-cli/src/utils/serverState.js +37 -10
  226. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  227. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -44
  228. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  229. package/codeyam-cli/src/webserver/app/lib/database.js +15 -3
  230. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  231. package/codeyam-cli/src/webserver/backgroundServer.js +24 -0
  232. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  233. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CA3JxPb7.js +1 -0
  234. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-DsN1wKrm.js → EntityItem-B86KKU7e.js} +1 -1
  235. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-DLqD3qNt.js → EntityTypeBadge-B5ctlSYt.js} +1 -1
  236. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-Ba2JVPzP.js → EntityTypeIcon-BqY8gDAW.js} +1 -1
  237. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-C8lyxW9k.js → InlineSpinner-ClaLpuOo.js} +1 -1
  238. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-aht4aafF.js → InteractivePreview-BDhPilK7.js} +2 -2
  239. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-CVtiBnY5.js → LibraryFunctionPreview-VeqEBv9v.js} +1 -1
  240. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-B0GLXMsr.js → LoadingDots-Bs7Nn1Jr.js} +1 -1
  241. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-xgeCVgSM.js → LogViewer-Bm3PmcCz.js} +1 -1
  242. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-OApQuNyq.js → ReportIssueModal-CgMEzchJ.js} +3 -8
  243. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-DuDvi0jm.js → SafeScreenshot-Gq3Ocjo6.js} +1 -1
  244. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DzccYyI8.js → ScenarioViewer-CBui0id_.js} +2 -2
  245. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-DyFZkK0l.js → TruncatedFilePath-CiwXDxLh.js} +1 -1
  246. package/codeyam-cli/src/webserver/build/client/assets/{_index-BwqWJOgH.js → _index-B3TDXxnk.js} +1 -1
  247. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BwavGCpm.js → activity.(_tab)-BtBFH820.js} +6 -11
  248. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-CN61MOMa.js +11 -0
  249. package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
  250. package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
  251. package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
  252. package/codeyam-cli/src/webserver/build/client/assets/book-open-PttOB2SF.js +6 -0
  253. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-Cx24_aWc.js → chevron-down-TJp6ofnp.js} +1 -1
  254. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-CXRTFQ3F.js → chunk-JZWAC4HX-JE9ZIoBl.js} +12 -12
  255. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BOARzkeR.js → circle-check-CXhHQYrI.js} +1 -1
  256. package/codeyam-cli/src/webserver/build/client/assets/copy-6y9ALfGT.js +11 -0
  257. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-BdhJEx6B.js → createLucideIcon-Ca9fAY46.js} +1 -1
  258. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-BBnGWYga.js → dev.empty-C0epRiVn.js} +1 -1
  259. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BJUiQqZF.js → entity._sha._-BVnB8a9L.js} +10 -10
  260. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js → entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js} +1 -1
  261. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-D1T4TGjf.js → entity._sha_.create-scenario-DGgZjdFg.js} +1 -1
  262. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CTBG2mmz.js → entity._sha_.edit._scenarioId-38yPijoD.js} +1 -1
  263. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-CS2cb_eZ.js → entry.client-BSHEfydn.js} +1 -1
  264. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DMJ7zii9.js → fileTableUtils-DCPhhSMo.js} +1 -1
  265. package/codeyam-cli/src/webserver/build/client/assets/{files-CJ6lTdTA.js → files-0N0YJQv7.js} +1 -1
  266. package/codeyam-cli/src/webserver/build/client/assets/{git-CPTZZ-JZ.js → git-DXnyr8uP.js} +1 -1
  267. package/codeyam-cli/src/webserver/build/client/assets/globals-CKT08Djd.css +1 -0
  268. package/codeyam-cli/src/webserver/build/client/assets/{index-lzqtyFU8.js → index-CcsFv748.js} +1 -1
  269. package/codeyam-cli/src/webserver/build/client/assets/{index-B1h680n5.js → index-ChN9-fAY.js} +1 -1
  270. package/codeyam-cli/src/webserver/build/client/assets/labs-BLJ7HxOC.js +1 -0
  271. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-B7B9V-bu.js → loader-circle-CTqLEAGU.js} +1 -1
  272. package/codeyam-cli/src/webserver/build/client/assets/manifest-b171b9d3.js +1 -0
  273. package/codeyam-cli/src/webserver/build/client/assets/memory-CCQd4aZA.js +78 -0
  274. package/codeyam-cli/src/webserver/build/client/assets/pause-D6vreykR.js +11 -0
  275. package/codeyam-cli/src/webserver/build/client/assets/root-CHhiHoo_.js +62 -0
  276. package/codeyam-cli/src/webserver/build/client/assets/{search-CxXUmBSd.js → search-B8VUL8nl.js} +1 -1
  277. package/codeyam-cli/src/webserver/build/client/assets/settings-BejnUJ6R.js +1 -0
  278. package/codeyam-cli/src/webserver/build/client/assets/{simulations-DwFIBT09.js → simulations-CPoAg7Zo.js} +1 -1
  279. package/codeyam-cli/src/webserver/build/client/assets/terminal-BrCP7uQo.js +11 -0
  280. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-B6LgvRJg.js → triangle-alert-BZz2NjYa.js} +1 -1
  281. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-C1v1PQzo.js → useCustomSizes-DNwUduNu.js} +1 -1
  282. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-aSv48UbS.js → useLastLogLine-COky1GVF.js} +1 -1
  283. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-DYxHZQuP.js → useReportContext-CpZgwliL.js} +1 -1
  284. package/codeyam-cli/src/webserver/build/client/assets/{useToast-mBRpZPiu.js → useToast-Bv9JFvUO.js} +1 -1
  285. package/codeyam-cli/src/webserver/build/server/assets/{index-DVzYx8PN.js → index-8Fv-lH1-.js} +1 -1
  286. package/codeyam-cli/src/webserver/build/server/assets/server-build-Akn3iYFP.js +257 -0
  287. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  288. package/codeyam-cli/src/webserver/build-info.json +5 -5
  289. package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
  290. package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
  291. package/codeyam-cli/templates/codeyam-memory-hook.sh +19 -20
  292. package/codeyam-cli/templates/codeyam-memory.md +392 -0
  293. package/codeyam-cli/templates/codeyam-new-rule.md +13 -0
  294. package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
  295. package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
  296. package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
  297. package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
  298. package/codeyam-cli/templates/rule-notification-hook.py +56 -0
  299. package/codeyam-cli/templates/rule-reflection-hook.py +627 -0
  300. package/codeyam-cli/templates/rules-instructions.md +132 -0
  301. package/package.json +2 -2
  302. package/packages/ai/index.js +3 -2
  303. package/packages/ai/index.js.map +1 -1
  304. package/packages/ai/src/lib/analyzeScope.js +50 -13
  305. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  306. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +54 -8
  307. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  308. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
  309. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
  310. package/packages/ai/src/lib/astScopes/processExpression.js +317 -44
  311. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  312. package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
  313. package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
  314. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +763 -171
  315. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  316. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +5 -1
  317. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  318. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
  319. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
  320. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
  321. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
  322. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +33 -3
  323. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  324. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +36 -11
  325. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  326. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
  327. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
  328. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +113 -11
  329. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  330. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +173 -0
  331. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
  332. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
  333. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
  334. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +309 -84
  335. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  336. package/packages/ai/src/lib/dataStructureChunking.js +26 -11
  337. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
  338. package/packages/ai/src/lib/generateEntityDataStructure.js +46 -2
  339. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  340. package/packages/ai/src/lib/generateEntityScenarioData.js +227 -4
  341. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  342. package/packages/ai/src/lib/generateEntityScenarios.js +7 -1
  343. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  344. package/packages/ai/src/lib/generateExecutionFlows.js +26 -4
  345. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  346. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +447 -80
  347. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  348. package/packages/ai/src/lib/isolateScopes.js +39 -3
  349. package/packages/ai/src/lib/isolateScopes.js.map +1 -1
  350. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
  351. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
  352. package/packages/ai/src/lib/mergeStatements.js +70 -51
  353. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  354. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
  355. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
  356. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
  357. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  358. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +17 -2
  359. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  360. package/packages/ai/src/lib/resolvePathToControllable.js +24 -14
  361. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
  362. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  363. package/packages/analyze/index.js +1 -0
  364. package/packages/analyze/index.js.map +1 -1
  365. package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
  366. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  367. package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
  368. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  369. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
  370. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
  371. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
  372. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
  373. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
  374. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  375. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
  376. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
  377. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
  378. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
  379. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
  380. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
  381. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +65 -7
  382. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  383. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +17 -4
  384. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  385. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
  386. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  387. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +0 -3
  388. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  389. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
  390. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  391. package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
  392. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  393. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js +880 -0
  394. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
  395. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +56 -10
  396. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  397. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +33 -8
  398. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  399. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +150 -17
  400. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  401. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +56 -8
  402. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  403. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +399 -31
  404. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  405. package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
  406. package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
  407. package/packages/analyze/src/lib/index.js +1 -0
  408. package/packages/analyze/src/lib/index.js.map +1 -1
  409. package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
  410. package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
  411. package/packages/database/src/lib/analysisBranchToDb.js +1 -1
  412. package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
  413. package/packages/database/src/lib/analysisToDb.js +1 -1
  414. package/packages/database/src/lib/analysisToDb.js.map +1 -1
  415. package/packages/database/src/lib/branchToDb.js +1 -1
  416. package/packages/database/src/lib/branchToDb.js.map +1 -1
  417. package/packages/database/src/lib/commitBranchToDb.js +1 -1
  418. package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
  419. package/packages/database/src/lib/commitToDb.js +1 -1
  420. package/packages/database/src/lib/commitToDb.js.map +1 -1
  421. package/packages/database/src/lib/fileToDb.js +1 -1
  422. package/packages/database/src/lib/fileToDb.js.map +1 -1
  423. package/packages/database/src/lib/kysely/db.js +3 -0
  424. package/packages/database/src/lib/kysely/db.js.map +1 -1
  425. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  426. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  427. package/packages/database/src/lib/projectToDb.js +1 -1
  428. package/packages/database/src/lib/projectToDb.js.map +1 -1
  429. package/packages/database/src/lib/saveFiles.js +1 -1
  430. package/packages/database/src/lib/saveFiles.js.map +1 -1
  431. package/packages/database/src/lib/scenarioToDb.js +1 -1
  432. package/packages/database/src/lib/scenarioToDb.js.map +1 -1
  433. package/scripts/finalize-analyzer.cjs +8 -76
  434. package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +0 -6
  435. package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +0 -6
  436. package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +0 -1
  437. package/codeyam-cli/src/webserver/build/client/assets/manifest-7522edd4.js +0 -1
  438. package/codeyam-cli/src/webserver/build/client/assets/memory-yxFcrxBX.js +0 -92
  439. package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +0 -62
  440. package/codeyam-cli/src/webserver/build/client/assets/settings-CS5f3WzT.js +0 -1
  441. package/codeyam-cli/src/webserver/build/server/assets/server-build-4Cr0uToj.js +0 -257
  442. package/codeyam-cli/templates/codeyam:diagnose.md +0 -803
  443. package/codeyam-cli/templates/codeyam:memory.md +0 -462
  444. package/codeyam-cli/templates/codeyam:new-rule.md +0 -13
@@ -18,6 +18,7 @@ import type {
18
18
  CompoundConditional,
19
19
  DerivedVariableOperation,
20
20
  DerivedVariableInfo,
21
+ JsxRenderingUsage,
21
22
  } from './astScopes/types';
22
23
  import type { EnrichedConditionalUsage } from './worker/SerializableDataStructure';
23
24
  import resolvePathToControllable from './resolvePathToControllable';
@@ -32,7 +33,7 @@ export interface ChildComponentConditionalData {
32
33
  /** Child's conditional usages keyed by variable name (may include sourceDataPath from enrichment) */
33
34
  conditionalUsages: Record<string, ExtendedConditionalUsage[]>;
34
35
  /** Child's equivalent signature variables (maps internal paths to prop paths) */
35
- equivalentSignatureVariables: Record<string, string>;
36
+ equivalentSignatureVariables: Record<string, string | string[]>;
36
37
  /** Child's compound conditionals */
37
38
  compoundConditionals: CompoundConditional[];
38
39
  /**
@@ -41,6 +42,11 @@ export interface ChildComponentConditionalData {
41
42
  * then `hasAnalysis` is a gating condition for all of ChildComponent's flows.
42
43
  */
43
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[];
44
50
  }
45
51
 
46
52
  export interface GenerateFlowsFromConditionalsArgs {
@@ -51,7 +57,7 @@ export interface GenerateFlowsFromConditionalsArgs {
51
57
  /** Map of controllable paths to their types */
52
58
  attributesMap: Record<string, string>;
53
59
  /** Map from local variable names to data sources */
54
- equivalentSignatureVariables: Record<string, string>;
60
+ equivalentSignatureVariables: Record<string, string | string[]>;
55
61
  /** Map from full paths to short paths */
56
62
  fullToShortPathMap: Record<string, string>;
57
63
  /**
@@ -73,6 +79,21 @@ export interface GenerateFlowsFromConditionalsArgs {
73
79
  * to `currentRun.entityShas` when `isInCurrentRun` isn't in conditionalUsages.
74
80
  */
75
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
+ >;
76
97
  }
77
98
 
78
99
  /**
@@ -117,7 +138,7 @@ function expandDerivedVariableToSources(
117
138
  path: string,
118
139
  conditionalUsages: Record<string, ConditionalUsage[]>,
119
140
  attributesMap: Record<string, string>,
120
- equivalentSignatureVariables: Record<string, string>,
141
+ equivalentSignatureVariables: Record<string, string | string[]>,
121
142
  fullToShortPathMap: Record<string, string>,
122
143
  visited: Set<string> = new Set(),
123
144
  derivedVariables?: Record<string, DerivedVariableInfo>,
@@ -238,11 +259,15 @@ function cleanSourceDataPath(sourceDataPath: string): string | null {
238
259
  sourceDataPath.match(/\.functionCallReturnValue/g) || []
239
260
  ).length;
240
261
 
241
- // If there are multiple functionCallReturnValue occurrences, this is a chained call
242
- // (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.
243
266
  if (fnCallReturnValues > 1 || emptyFnCalls !== 1) {
244
- // Multiple function calls - return null to use fallback resolution
245
- return null;
267
+ console.log(
268
+ `[cleanSourceDataPath] chained/non-standard path (fnCallRVs=${fnCallReturnValues}, emptyFnCalls=${emptyFnCalls}), returning original: "${sourceDataPath}"`,
269
+ );
270
+ return sourceDataPath;
246
271
  }
247
272
 
248
273
  // Find the "()" which marks the function call
@@ -287,6 +312,85 @@ function stripLengthSuffix(path: string): string {
287
312
  return path;
288
313
  }
289
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
+
290
394
  /**
291
395
  * Extract the controllable base path from a path that may contain method calls.
292
396
  *
@@ -329,13 +433,16 @@ function extractControllableBase(path: string): string {
329
433
  * The sourceDataPath contains full paths (e.g., "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha")
330
434
  * The fullToShortPathMap maps full paths to short paths
331
435
  */
332
- function findInAttributesMapForPath(
436
+ export function findInAttributesMapForPath(
333
437
  path: string,
334
438
  attributesMap: Record<string, string>,
335
439
  fullToShortPathMap: Record<string, string>,
336
440
  ): string | null {
337
441
  // Direct match in attributesMap (already a short path)
338
442
  if (path in attributesMap) {
443
+ console.log(
444
+ `[findInAttributesMapForPath] "${path}" → DIRECT match in attributesMap`,
445
+ );
339
446
  return path;
340
447
  }
341
448
 
@@ -344,19 +451,31 @@ function findInAttributesMapForPath(
344
451
  if (path in fullToShortPathMap) {
345
452
  const shortPath = fullToShortPathMap[path];
346
453
  if (shortPath in attributesMap) {
454
+ console.log(
455
+ `[findInAttributesMapForPath] "${path}" → fullToShortPathMap match: shortPath="${shortPath}" found in attributesMap`,
456
+ );
347
457
  return path; // Return FULL path to preserve data source context
348
458
  }
459
+ console.log(
460
+ `[findInAttributesMapForPath] "${path}" → fullToShortPathMap match shortPath="${shortPath}" but NOT in attributesMap`,
461
+ );
349
462
  }
350
463
 
351
464
  // Normalized match (array indices [N] → [])
352
465
  const normalizedPath = path.replace(/\[\d+\]/g, '[]');
353
466
  if (normalizedPath !== path) {
354
467
  if (normalizedPath in attributesMap) {
468
+ console.log(
469
+ `[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" DIRECT match in attributesMap`,
470
+ );
355
471
  return normalizedPath;
356
472
  }
357
473
  if (normalizedPath in fullToShortPathMap) {
358
474
  const shortPath = fullToShortPathMap[normalizedPath];
359
475
  if (shortPath in attributesMap) {
476
+ console.log(
477
+ `[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" fullToShortPathMap match: shortPath="${shortPath}"`,
478
+ );
360
479
  return normalizedPath; // Return normalized FULL path
361
480
  }
362
481
  }
@@ -368,25 +487,92 @@ function findInAttributesMapForPath(
368
487
  // and we need to find matching short path prefix
369
488
  for (const attrPath of Object.keys(attributesMap)) {
370
489
  if (path.startsWith(attrPath + '.') || path.startsWith(attrPath + '[')) {
371
- // The path is a child of a known attribute path
490
+ console.log(
491
+ `[findInAttributesMapForPath] "${path}" → PREFIX match: starts with attributesMap key "${attrPath}"`,
492
+ );
372
493
  return path;
373
494
  }
374
495
  }
375
496
 
376
497
  // Try suffix matching: if the path ends with ".X.Y.Z" and attributesMap has "X.Y.Z"
377
498
  // Return the FULL input path to preserve data source context
378
- for (const attrPath of Object.keys(attributesMap)) {
379
- if (
380
- path.endsWith('.' + attrPath) ||
381
- path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))
382
- ) {
383
- 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
+ }
516
+ }
517
+ }
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;
384
553
  }
385
554
  }
386
555
 
556
+ console.log(
557
+ `[findInAttributesMapForPath] "${path}" → NO MATCH (checked ${Object.keys(attributesMap).length} attributesMap keys, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap keys)`,
558
+ );
387
559
  return null;
388
560
  }
389
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
+
390
576
  /**
391
577
  * Generate a human-readable name from a path.
392
578
  * Extracts the last meaningful part of the path.
@@ -598,7 +784,15 @@ function generateFlowFromCompound(
598
784
  condition.requiredValue?.toString() ??
599
785
  condition.comparedValues?.[0] ??
600
786
  'truthy';
601
- 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
+ }
602
796
  }
603
797
 
604
798
  requiredValues.push({
@@ -609,21 +803,32 @@ function generateFlowFromCompound(
609
803
  });
610
804
  }
611
805
 
612
- // Generate a combined ID from all paths
613
- 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
614
815
  .map((rv) => {
615
816
  const name = generateNameFromPath(rv.attributePath);
616
- 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;
617
822
  })
618
823
  .join('-and-');
619
824
 
620
825
  return {
621
826
  id: `compound-${pathParts}`,
622
- name: requiredValues
827
+ name: cleanedValues
623
828
  .map((rv) => generateNameFromPath(rv.attributePath))
624
829
  .join(' + '),
625
- description: `When ${requiredValues.map((rv) => `${generateNameFromPath(rv.attributePath).toLowerCase()} is ${rv.value}`).join(' and ')}`,
626
- requiredValues,
830
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
831
+ requiredValues: cleanedValues,
627
832
  impact,
628
833
  sourceLocation: {
629
834
  lineNumber: compound.sourceLocation.lineNumber,
@@ -732,8 +937,8 @@ function normalizePathForDeduplication(
732
937
  */
733
938
  function translateChildPathToParent(
734
939
  childPath: string,
735
- childEquivalentSignatureVariables: Record<string, string>,
736
- parentEquivalentSignatureVariables: Record<string, string>,
940
+ childEquivalentSignatureVariables: Record<string, string | string[]>,
941
+ parentEquivalentSignatureVariables: Record<string, string | string[]>,
737
942
  childName: string,
738
943
  ): string | null {
739
944
  // Extract the root variable from the child path
@@ -760,7 +965,11 @@ function translateChildPathToParent(
760
965
 
761
966
  // Look up the child's equivalence for this root variable
762
967
  // e.g., childEquiv[selectedScenario] = "signature[0].selectedScenario"
763
- 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;
764
973
 
765
974
  if (!childPropPath) {
766
975
  // No mapping found - this might be internal state, not a prop
@@ -773,7 +982,11 @@ function translateChildPathToParent(
773
982
 
774
983
  // Look up parent's equivalence to find what value was passed to this prop
775
984
  // e.g., parentEquiv["ChildName().signature[0].selectedScenario"] = "selectedScenario"
776
- 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;
777
990
 
778
991
  if (!parentValue) {
779
992
  // No parent mapping found - log ALL parent keys that contain the childName
@@ -800,11 +1013,28 @@ export default function generateExecutionFlowsFromConditionals(
800
1013
  fullToShortPathMap,
801
1014
  childComponentData,
802
1015
  derivedVariables,
1016
+ sourceEquivalencies,
803
1017
  } = args;
804
1018
 
805
1019
  const flows: ExecutionFlow[] = [];
806
1020
  const seenFlowIds = new Set<string>();
807
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
+
808
1038
  // Track normalized resolved paths to prevent duplicate flows
809
1039
  // This handles the case where we have usages for both:
810
1040
  // - "hasNewerVersion" (short path from destructured variable)
@@ -822,9 +1052,16 @@ export default function generateExecutionFlowsFromConditionals(
822
1052
  for (const usage of usages) {
823
1053
  // Skip usages that are part of compound conditionals (handled separately)
824
1054
  if (usage.chainId && compoundChainIds.has(usage.chainId)) {
1055
+ console.log(
1056
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: part of compound conditional chain=${usage.chainId}`,
1057
+ );
825
1058
  continue;
826
1059
  }
827
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
+
828
1065
  // First, try to use pre-computed sourceDataPath if available
829
1066
  let resolvedPath: string | null = null;
830
1067
 
@@ -834,7 +1071,9 @@ export default function generateExecutionFlowsFromConditionals(
834
1071
  // should become "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
835
1072
  // Returns null for malformed paths (e.g., chained function calls like fetch().json())
836
1073
  const cleanedPath = cleanSourceDataPath(usage.sourceDataPath);
837
-
1074
+ console.log(
1075
+ `[genFlowsFromConditionals] "${usage.path}" cleanSourceDataPath("${usage.sourceDataPath}") → "${cleanedPath}"`,
1076
+ );
838
1077
  if (cleanedPath) {
839
1078
  // Verify the cleaned path exists in attributesMap
840
1079
  const pathMatch = findInAttributesMapForPath(
@@ -842,6 +1081,9 @@ export default function generateExecutionFlowsFromConditionals(
842
1081
  attributesMap,
843
1082
  fullToShortPathMap,
844
1083
  );
1084
+ console.log(
1085
+ `[genFlowsFromConditionals] "${usage.path}" findInAttributesMapForPath("${cleanedPath}") → ${pathMatch ? `"${pathMatch}"` : 'null (not found)'}`,
1086
+ );
845
1087
  if (pathMatch) {
846
1088
  resolvedPath = pathMatch;
847
1089
  }
@@ -851,13 +1093,18 @@ export default function generateExecutionFlowsFromConditionals(
851
1093
 
852
1094
  // Fall back to resolution via equivalentSignatureVariables
853
1095
  if (!resolvedPath) {
1096
+ console.log(
1097
+ `[genFlowsFromConditionals] "${usage.path}" sourceDataPath resolution failed, trying resolvePathToControllable("${usage.path}")...`,
1098
+ );
854
1099
  const resolution = resolvePathToControllable(
855
1100
  usage.path,
856
1101
  attributesMap,
857
1102
  equivalentSignatureVariables,
858
1103
  fullToShortPathMap,
859
1104
  );
860
-
1105
+ console.log(
1106
+ `[genFlowsFromConditionals] "${usage.path}" resolvePathToControllable → isControllable=${resolution.isControllable}, resolvedPath="${resolution.resolvedPath ?? '(none)'}"`,
1107
+ );
861
1108
  if (resolution.isControllable && resolution.resolvedPath) {
862
1109
  resolvedPath = resolution.resolvedPath;
863
1110
  }
@@ -869,7 +1116,9 @@ export default function generateExecutionFlowsFromConditionals(
869
1116
  if (!resolvedPath && usage.derivedFrom) {
870
1117
  const { operation, sourcePath, sourcePaths, comparedValue } =
871
1118
  usage.derivedFrom;
872
-
1119
+ console.log(
1120
+ `[genFlowsFromConditionals] "${usage.path}" trying derivedFrom: operation=${operation}, sourcePath="${sourcePath ?? '(none)'}", sourcePaths=${sourcePaths ? JSON.stringify(sourcePaths) : '(none)'}, comparedValue="${comparedValue ?? '(none)'}"`,
1121
+ );
873
1122
  // For single-source derivations (notNull, equals, etc.)
874
1123
  if (sourcePath) {
875
1124
  const resolution = resolvePathToControllable(
@@ -878,7 +1127,6 @@ export default function generateExecutionFlowsFromConditionals(
878
1127
  equivalentSignatureVariables,
879
1128
  fullToShortPathMap,
880
1129
  );
881
-
882
1130
  if (resolution.isControllable && resolution.resolvedPath) {
883
1131
  resolvedPath = resolution.resolvedPath;
884
1132
  }
@@ -1174,6 +1422,9 @@ export default function generateExecutionFlowsFromConditionals(
1174
1422
 
1175
1423
  if (!resolvedPath) {
1176
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
+ );
1177
1428
  continue;
1178
1429
  }
1179
1430
 
@@ -1188,10 +1439,33 @@ export default function generateExecutionFlowsFromConditionals(
1188
1439
  // Skip if we've already generated flows for this normalized path
1189
1440
  // This prevents duplicate flows when we have usages for both short and full paths
1190
1441
  if (seenNormalizedPaths.has(normalizedPath)) {
1442
+ console.log(
1443
+ `[genFlowsFromConditionals] "${usage.path}" SKIP: duplicate normalizedPath="${normalizedPath}" (resolvedPath="${resolvedPath}")`,
1444
+ );
1191
1445
  continue;
1192
1446
  }
1193
1447
  seenNormalizedPaths.add(normalizedPath);
1194
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
+
1195
1469
  // Generate flows for this controllable usage
1196
1470
  const usageFlows = generateFlowsFromUsage(usage, resolvedPath);
1197
1471
 
@@ -1200,6 +1474,9 @@ export default function generateExecutionFlowsFromConditionals(
1200
1474
  if (!seenFlowIds.has(flow.id)) {
1201
1475
  seenFlowIds.add(flow.id);
1202
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
+ );
1203
1480
  }
1204
1481
  }
1205
1482
  }
@@ -1253,25 +1530,85 @@ export default function generateExecutionFlowsFromConditionals(
1253
1530
  // Use the first source's path for the resolvedPaths map (for ID generation)
1254
1531
  resolvedPaths.set(condition.path, sources[0].path);
1255
1532
  } else {
1256
- // Derived variable but no controllable sources found
1257
- allControllable = false;
1258
- break;
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
+ }
1259
1570
  }
1260
1571
  } else {
1261
1572
  // Not a derived variable - resolve directly
1262
- const resolution = resolvePathToControllable(
1263
- condition.path,
1264
- attributesMap,
1265
- equivalentSignatureVariables,
1266
- fullToShortPathMap,
1267
- );
1573
+ // First try sourceDataPath from the usage (same as individual processing)
1574
+ let compoundResolvedPath: string | null = null;
1268
1575
 
1269
- if (!resolution.isControllable || !resolution.resolvedPath) {
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
+ );
1600
+
1601
+ if (resolution.isControllable && resolution.resolvedPath) {
1602
+ compoundResolvedPath = resolution.resolvedPath;
1603
+ }
1604
+ }
1605
+
1606
+ if (!compoundResolvedPath) {
1270
1607
  allControllable = false;
1271
1608
  break;
1272
1609
  }
1273
1610
 
1274
- resolvedPaths.set(condition.path, resolution.resolvedPath);
1611
+ resolvedPaths.set(condition.path, compoundResolvedPath);
1275
1612
  }
1276
1613
  }
1277
1614
 
@@ -1349,7 +1686,14 @@ export default function generateExecutionFlowsFromConditionals(
1349
1686
  condition.requiredValue?.toString() ??
1350
1687
  condition.comparedValues?.[0] ??
1351
1688
  'truthy';
1352
- comparison = 'equals';
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
+ }
1353
1697
  }
1354
1698
 
1355
1699
  requiredValues.push({
@@ -1362,24 +1706,31 @@ export default function generateExecutionFlowsFromConditionals(
1362
1706
  }
1363
1707
  }
1364
1708
 
1365
- if (requiredValues.length > 0) {
1709
+ // Remove contradictory "falsy" values where a child path requires data
1710
+ const cleanedValues = removeContradictoryFalsyValues(requiredValues);
1711
+
1712
+ if (cleanedValues.length > 0) {
1366
1713
  const impact: ExecutionFlow['impact'] =
1367
1714
  compound.controlsJsxRendering ? 'high' : 'medium';
1368
1715
 
1369
- // Generate a combined ID from all paths
1370
- const pathParts = requiredValues
1716
+ // Generate a combined ID from all paths + values
1717
+ const pathParts = cleanedValues
1371
1718
  .map((rv) => {
1372
1719
  const name = generateNameFromPath(rv.attributePath);
1373
- return name.toLowerCase().replace(/\s+/g, '-');
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;
1374
1725
  })
1375
1726
  .join('-and-');
1376
1727
 
1377
1728
  const compoundFlow: ExecutionFlow = {
1378
- id: `${pathParts}-${requiredValues.map((rv) => rv.value).join('-')}`,
1379
- name: generateNameFromPath(requiredValues[0].attributePath),
1380
- description: `When ${requiredValues.map((rv) => `${generateNameFromPath(rv.attributePath).toLowerCase()} is ${rv.value}`).join(' and ')}`,
1729
+ id: `${pathParts}`,
1730
+ name: generateNameFromPath(cleanedValues[0].attributePath),
1731
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
1381
1732
  impact,
1382
- requiredValues,
1733
+ requiredValues: cleanedValues,
1383
1734
  sourceLocation: compound.sourceLocation,
1384
1735
  };
1385
1736
 
@@ -1596,9 +1947,6 @@ export default function generateExecutionFlowsFromConditionals(
1596
1947
  childData.conditionalUsages,
1597
1948
  )) {
1598
1949
  for (const usage of usages) {
1599
- // Debug logging (disabled - set to true for troubleshooting child flow resolution)
1600
- const shouldDebugChild = false;
1601
-
1602
1950
  // Skip usages that are part of compound conditionals (handled separately)
1603
1951
  // Fix 33: Only skip if the chainId is in the child's compound conditionals
1604
1952
  if (usage.chainId && childCompoundChainIds.has(usage.chainId)) {
@@ -1613,18 +1961,6 @@ export default function generateExecutionFlowsFromConditionals(
1613
1961
  childPath = usage.derivedFrom.sourcePath;
1614
1962
  }
1615
1963
 
1616
- if (shouldDebugChild) {
1617
- console.log(
1618
- `[DEBUG CHILD ${childName}] Processing usage path: ${usage.path}`,
1619
- );
1620
- console.log(
1621
- `[DEBUG CHILD ${childName}] childPath (after derivedFrom): ${childPath}`,
1622
- );
1623
- console.log(
1624
- `[DEBUG CHILD ${childName}] sourceDataPath: ${usage.sourceDataPath}`,
1625
- );
1626
- }
1627
-
1628
1964
  // Translate the child path to a parent path
1629
1965
  let translatedPath = translateChildPathToParent(
1630
1966
  childPath,
@@ -1633,12 +1969,6 @@ export default function generateExecutionFlowsFromConditionals(
1633
1969
  childName,
1634
1970
  );
1635
1971
 
1636
- if (shouldDebugChild) {
1637
- console.log(
1638
- `[DEBUG CHILD ${childName}] translatedPath (from translateChildPathToParent): ${translatedPath}`,
1639
- );
1640
- }
1641
-
1642
1972
  // If translation failed but we have sourceDataPath, try to extract the prop path from it
1643
1973
  // sourceDataPath format: "ChildName.signature[n].propPath.rest" → extract "propPath.rest"
1644
1974
  if (!translatedPath && usage.sourceDataPath) {
@@ -1647,21 +1977,11 @@ export default function generateExecutionFlowsFromConditionals(
1647
1977
  );
1648
1978
  if (signatureMatch) {
1649
1979
  translatedPath = signatureMatch[1];
1650
- if (shouldDebugChild) {
1651
- console.log(
1652
- `[DEBUG CHILD ${childName}] translatedPath (from sourceDataPath regex): ${translatedPath}`,
1653
- );
1654
- }
1655
1980
  }
1656
1981
  }
1657
1982
 
1658
1983
  if (!translatedPath) {
1659
1984
  // Could not translate - skip this usage
1660
- if (shouldDebugChild) {
1661
- console.log(
1662
- `[DEBUG CHILD ${childName}] SKIPPED - no translation found`,
1663
- );
1664
- }
1665
1985
  continue;
1666
1986
  }
1667
1987
 
@@ -1674,21 +1994,6 @@ export default function generateExecutionFlowsFromConditionals(
1674
1994
  fullToShortPathMap,
1675
1995
  );
1676
1996
 
1677
- if (shouldDebugChild) {
1678
- console.log(
1679
- `[DEBUG CHILD ${childName}] resolvePathToControllable result:`,
1680
- );
1681
- console.log(
1682
- `[DEBUG CHILD ${childName}] isControllable: ${resolution.isControllable}`,
1683
- );
1684
- console.log(
1685
- `[DEBUG CHILD ${childName}] resolvedPath: ${resolution.resolvedPath}`,
1686
- );
1687
- console.log(
1688
- `[DEBUG CHILD ${childName}] chain: ${resolution.resolutionChain.join(' -> ')}`,
1689
- );
1690
- }
1691
-
1692
1997
  // Only create flows for controllable paths (whitelist approach).
1693
1998
  // If the path doesn't resolve to something in attributesMap, skip it.
1694
1999
  // This prevents creating flows for useState values which are not
@@ -1726,32 +2031,11 @@ export default function generateExecutionFlowsFromConditionals(
1726
2031
  }
1727
2032
  }
1728
2033
 
1729
- if (shouldDebugChild) {
1730
- console.log(
1731
- `[DEBUG CHILD ${childName}] useState fallback: looking for URL param`,
1732
- );
1733
- console.log(
1734
- `[DEBUG CHILD ${childName}] useStatePattern: ${useStatePattern}`,
1735
- );
1736
- console.log(
1737
- `[DEBUG CHILD ${childName}] useStateVarName: ${useStateVarName}`,
1738
- );
1739
- }
1740
-
1741
2034
  if (useStateVarName) {
1742
2035
  // Look for a related URL param like "varNameFromUrl"
1743
2036
  const urlParamName = `${useStateVarName}FromUrl`;
1744
2037
  const urlParamPath = equivalentSignatureVariables[urlParamName];
1745
2038
 
1746
- if (shouldDebugChild) {
1747
- console.log(
1748
- `[DEBUG CHILD ${childName}] urlParamName: ${urlParamName}`,
1749
- );
1750
- console.log(
1751
- `[DEBUG CHILD ${childName}] urlParamPath: ${urlParamPath}`,
1752
- );
1753
- }
1754
-
1755
2039
  if (urlParamPath) {
1756
2040
  // For useState values initialized from URL params, use the
1757
2041
  // URL param variable name directly (e.g., "viewModeFromUrl")
@@ -1762,10 +2046,62 @@ export default function generateExecutionFlowsFromConditionals(
1762
2046
  // The flow will use the URL param name as the attributePath,
1763
2047
  // which gets properly resolved when generating mock data.
1764
2048
  resolvedPath = urlParamName;
1765
- if (shouldDebugChild) {
1766
- console.log(
1767
- `[DEBUG CHILD ${childName}] useState fallback SUCCESS: using URL param name ${resolvedPath}`,
1768
- );
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
+ }
2078
+
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;
1769
2105
  }
1770
2106
  }
1771
2107
  }
@@ -1773,11 +2109,6 @@ export default function generateExecutionFlowsFromConditionals(
1773
2109
 
1774
2110
  // If still not resolved after fallback, skip
1775
2111
  if (!resolvedPath) {
1776
- if (shouldDebugChild) {
1777
- console.log(
1778
- `[DEBUG CHILD ${childName}] SKIPPED - path not controllable`,
1779
- );
1780
- }
1781
2112
  continue;
1782
2113
  }
1783
2114
  }
@@ -1789,11 +2120,6 @@ export default function generateExecutionFlowsFromConditionals(
1789
2120
  );
1790
2121
 
1791
2122
  if (seenNormalizedPaths.has(normalizedPath)) {
1792
- if (shouldDebugChild) {
1793
- console.log(
1794
- `[DEBUG CHILD ${childName}] SKIPPED - duplicate normalized path: ${normalizedPath}`,
1795
- );
1796
- }
1797
2123
  continue;
1798
2124
  }
1799
2125
  seenNormalizedPaths.add(normalizedPath);
@@ -1810,17 +2136,6 @@ export default function generateExecutionFlowsFromConditionals(
1810
2136
  resolvedPath,
1811
2137
  );
1812
2138
 
1813
- if (shouldDebugChild) {
1814
- console.log(
1815
- `[DEBUG CHILD ${childName}] GENERATING ${usageFlows.length} flows with resolvedPath: ${resolvedPath}`,
1816
- );
1817
- for (const f of usageFlows) {
1818
- console.log(
1819
- `[DEBUG CHILD ${childName}] - Flow ID: ${f.id}, path: ${f.requiredValues[0]?.attributePath}`,
1820
- );
1821
- }
1822
- }
1823
-
1824
2139
  // Add gating conditions to each flow
1825
2140
  for (const flow of usageFlows) {
1826
2141
  // Add gating required values to the flow
@@ -1970,8 +2285,200 @@ export default function generateExecutionFlowsFromConditionals(
1970
2285
  }
1971
2286
  }
1972
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
+ }
2468
+ }
2469
+ }
2470
+ }
1973
2471
  }
1974
2472
  }
1975
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
+
1976
2483
  return flows;
1977
2484
  }