@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.1a2737b

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 (654) 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 +19 -19
  4. package/analyzer-template/packages/ai/index.ts +16 -2
  5. package/analyzer-template/packages/ai/package.json +2 -2
  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 +98 -9
  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 +198 -34
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +1331 -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/convertDotNotation.ts +140 -14
  26. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +179 -0
  27. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
  28. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +393 -97
  29. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
  30. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
  31. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +183 -0
  32. package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
  33. package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
  34. package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +58 -3
  35. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +936 -7
  36. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
  37. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +515 -6
  38. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
  39. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1540 -75
  40. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
  41. package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +51 -3
  42. package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
  43. package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
  44. package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
  45. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
  46. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
  47. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
  48. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +44 -7
  49. package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
  50. package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
  51. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
  52. package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
  53. package/analyzer-template/packages/analyze/index.ts +2 -0
  54. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
  55. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
  56. package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
  57. package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
  58. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
  59. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
  60. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
  61. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
  62. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
  63. package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
  64. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +99 -22
  65. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +19 -4
  66. package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
  67. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
  68. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
  69. package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
  70. package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
  71. package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1315 -0
  72. package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +193 -76
  73. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +87 -25
  74. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +269 -22
  75. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
  76. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +647 -73
  77. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
  78. package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
  79. package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
  80. package/analyzer-template/packages/analyze/src/lib/index.ts +1 -0
  81. package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
  82. package/analyzer-template/packages/aws/package.json +10 -10
  83. package/analyzer-template/packages/database/package.json +1 -1
  84. package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
  85. package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
  86. package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
  87. package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
  88. package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
  89. package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
  90. package/analyzer-template/packages/database/src/lib/kysely/db.ts +14 -1
  91. package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
  92. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  93. package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
  94. package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
  95. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
  96. package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
  97. package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
  98. package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
  99. package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
  100. package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
  101. package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
  102. package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
  103. package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
  104. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
  105. package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
  106. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
  107. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
  108. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
  109. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
  110. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
  111. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
  112. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
  113. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
  114. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
  115. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
  116. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
  117. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
  118. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -0
  119. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
  120. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +11 -1
  121. package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
  122. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
  123. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
  124. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
  125. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
  126. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  127. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  128. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
  129. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
  130. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  131. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  132. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
  133. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
  134. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
  135. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
  136. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  137. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
  138. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  139. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
  140. package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
  141. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
  142. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
  143. package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
  144. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
  145. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
  146. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
  147. package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
  148. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
  149. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  150. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
  151. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  152. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
  153. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
  154. package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
  155. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
  156. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
  157. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
  158. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
  159. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
  160. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
  161. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
  162. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  163. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
  164. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  165. package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
  166. package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
  167. package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
  168. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
  169. package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
  170. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
  171. package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
  172. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  173. package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  174. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  175. package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  176. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  177. package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  178. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
  179. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  180. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
  181. package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
  182. package/analyzer-template/packages/github/package.json +1 -1
  183. package/analyzer-template/packages/types/index.ts +1 -0
  184. package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
  185. package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
  186. package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
  187. package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
  188. package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
  189. package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
  190. package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
  191. package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
  192. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
  193. package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
  194. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
  195. package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
  196. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +7 -0
  197. package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
  198. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
  199. package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
  200. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
  201. package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
  202. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  203. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +93 -2
  204. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  205. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
  206. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
  207. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
  208. package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
  209. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +108 -2
  210. package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
  211. package/analyzer-template/playwright/capture.ts +20 -8
  212. package/analyzer-template/playwright/captureStatic.ts +1 -1
  213. package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
  214. package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
  215. package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
  216. package/analyzer-template/project/constructMockCode.ts +436 -44
  217. package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
  218. package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
  219. package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
  220. package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
  221. package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
  222. package/analyzer-template/project/orchestrateCapture.ts +75 -7
  223. package/analyzer-template/project/reconcileMockDataKeys.ts +152 -9
  224. package/analyzer-template/project/runAnalysis.ts +4 -0
  225. package/analyzer-template/project/start.ts +35 -11
  226. package/analyzer-template/project/writeMockDataTsx.ts +295 -10
  227. package/analyzer-template/project/writeScenarioComponents.ts +237 -32
  228. package/analyzer-template/project/writeSimpleRoot.ts +21 -11
  229. package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
  230. package/background/src/lib/local/createLocalAnalyzer.js +1 -1
  231. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  232. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
  233. package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
  234. package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
  235. package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
  236. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
  237. package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
  238. package/background/src/lib/virtualized/project/constructMockCode.js +359 -14
  239. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  240. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
  241. package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
  242. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
  243. package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
  244. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
  245. package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
  246. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
  247. package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
  248. package/background/src/lib/virtualized/project/orchestrateCapture.js +62 -7
  249. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  250. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +126 -9
  251. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  252. package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
  253. package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
  254. package/background/src/lib/virtualized/project/start.js +32 -11
  255. package/background/src/lib/virtualized/project/start.js.map +1 -1
  256. package/background/src/lib/virtualized/project/writeMockDataTsx.js +251 -6
  257. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  258. package/background/src/lib/virtualized/project/writeScenarioComponents.js +173 -30
  259. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  260. package/background/src/lib/virtualized/project/writeSimpleRoot.js +21 -11
  261. package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
  262. package/codeyam-cli/scripts/apply-setup.js +180 -0
  263. package/codeyam-cli/scripts/apply-setup.js.map +1 -1
  264. package/codeyam-cli/src/cli.js +32 -18
  265. package/codeyam-cli/src/cli.js.map +1 -1
  266. package/codeyam-cli/src/codeyam-cli.js +18 -2
  267. package/codeyam-cli/src/codeyam-cli.js.map +1 -1
  268. package/codeyam-cli/src/commands/analyze.js +4 -2
  269. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  270. package/codeyam-cli/src/commands/baseline.js +2 -0
  271. package/codeyam-cli/src/commands/baseline.js.map +1 -1
  272. package/codeyam-cli/src/commands/debug.js +9 -5
  273. package/codeyam-cli/src/commands/debug.js.map +1 -1
  274. package/codeyam-cli/src/commands/default.js +31 -20
  275. package/codeyam-cli/src/commands/default.js.map +1 -1
  276. package/codeyam-cli/src/commands/detect-universal-mocks.js +2 -0
  277. package/codeyam-cli/src/commands/detect-universal-mocks.js.map +1 -1
  278. package/codeyam-cli/src/commands/init.js +49 -257
  279. package/codeyam-cli/src/commands/init.js.map +1 -1
  280. package/codeyam-cli/src/commands/memory.js +307 -0
  281. package/codeyam-cli/src/commands/memory.js.map +1 -0
  282. package/codeyam-cli/src/commands/recapture.js +2 -0
  283. package/codeyam-cli/src/commands/recapture.js.map +1 -1
  284. package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
  285. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  286. package/codeyam-cli/src/commands/setup-simulations.js +284 -0
  287. package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
  288. package/codeyam-cli/src/commands/test-startup.js +2 -0
  289. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  290. package/codeyam-cli/src/commands/verify.js +14 -2
  291. package/codeyam-cli/src/commands/verify.js.map +1 -1
  292. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +179 -0
  293. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
  294. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -82
  295. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  296. package/codeyam-cli/src/utils/analysisRunner.js +21 -2
  297. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  298. package/codeyam-cli/src/utils/analyzer.js +7 -0
  299. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  300. package/codeyam-cli/src/utils/backgroundServer.js +90 -19
  301. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  302. package/codeyam-cli/src/utils/generateReport.js +2 -2
  303. package/codeyam-cli/src/utils/install-skills.js +77 -38
  304. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  305. package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
  306. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
  307. package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
  308. package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
  309. package/codeyam-cli/src/utils/progress.js +7 -0
  310. package/codeyam-cli/src/utils/progress.js.map +1 -1
  311. package/codeyam-cli/src/utils/queue/job.js +5 -0
  312. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  313. package/codeyam-cli/src/utils/queue/manager.js +6 -0
  314. package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
  315. package/codeyam-cli/src/utils/requireSimulations.js +10 -0
  316. package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
  317. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
  318. package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
  319. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +230 -0
  320. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
  321. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
  322. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
  323. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
  324. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
  325. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
  326. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
  327. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
  328. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
  329. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +74 -0
  330. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
  331. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +376 -0
  332. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
  333. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +116 -0
  334. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
  335. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
  336. package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
  337. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
  338. package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
  339. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
  340. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
  341. package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
  342. package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
  343. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
  344. package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
  345. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
  346. package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
  347. package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
  348. package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
  349. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
  350. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
  351. package/codeyam-cli/src/utils/rules/index.js +6 -0
  352. package/codeyam-cli/src/utils/rules/index.js.map +1 -0
  353. package/codeyam-cli/src/utils/rules/parser.js +83 -0
  354. package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
  355. package/codeyam-cli/src/utils/rules/pathMatcher.js +18 -0
  356. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
  357. package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
  358. package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
  359. package/codeyam-cli/src/utils/rules/staleness.js +137 -0
  360. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
  361. package/codeyam-cli/src/utils/serverState.js +37 -10
  362. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  363. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -42
  364. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  365. package/codeyam-cli/src/utils/simulationGateMiddleware.js +138 -0
  366. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -0
  367. package/codeyam-cli/src/utils/syncMocksMiddleware.js +5 -24
  368. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  369. package/codeyam-cli/src/utils/versionInfo.js +25 -0
  370. package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
  371. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
  372. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
  373. package/codeyam-cli/src/webserver/app/lib/database.js +22 -6
  374. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  375. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  376. package/codeyam-cli/src/webserver/backgroundServer.js +50 -0
  377. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  378. package/codeyam-cli/src/webserver/bootstrap.js +51 -0
  379. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  380. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-jNYXRRNI.js +1 -0
  381. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-bwuHPyTa.js +11 -0
  382. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-CvzqMxcu.js} +1 -1
  383. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-BH0XDim7.js} +1 -1
  384. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CEleMv_j.js → InlineSpinner-EhOseatT.js} +1 -1
  385. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-yjIHlOGa.js} +2 -2
  386. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-Cq5o8jL4.js} +1 -1
  387. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-BvMu2i-g.js} +1 -1
  388. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-kgBTLoJD.js} +1 -1
  389. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-BzPgx-xO.js +11 -0
  390. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-CwZrv-Ok.js} +1 -1
  391. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-BX2Ny2Qj.js} +3 -13
  392. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-CDpEprKa.js} +1 -1
  393. package/codeyam-cli/src/webserver/build/client/assets/_index-BRx8ZGZo.js +11 -0
  394. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-4S4yPfFw.js +27 -0
  395. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +17 -0
  396. package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
  397. package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
  398. package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
  399. package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
  400. package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
  401. package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
  402. package/codeyam-cli/src/webserver/build/client/assets/book-open-D4IPYH_y.js +6 -0
  403. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-CG65viiV.js} +1 -1
  404. package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-JZWAC4HX-DB3aFuEO.js} +12 -12
  405. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-igfMr5DY.js} +1 -1
  406. package/codeyam-cli/src/webserver/build/client/assets/copy-Coc4o_8c.js +11 -0
  407. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-D1zB-pYc.js} +1 -1
  408. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-JTAjQ54M.js +1 -0
  409. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-B0h9AqE6.js} +12 -12
  410. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js → entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js} +1 -1
  411. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-wDWZZO1W.js → entity._sha_.create-scenario-CtYowLOt.js} +1 -1
  412. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-PePWg17F.js} +1 -1
  413. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-I-Wo99C_.js} +1 -1
  414. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-9sMMAiWJ.js} +1 -1
  415. package/codeyam-cli/src/webserver/build/client/assets/files-Co65J0s3.js +1 -0
  416. package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-BdHOxVfg.js} +8 -8
  417. package/codeyam-cli/src/webserver/build/client/assets/globals-BSZfYCkU.css +1 -0
  418. package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-CUM5iXwc.js} +1 -1
  419. package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-_417gcQW.js} +1 -1
  420. package/codeyam-cli/src/webserver/build/client/assets/labs-BK0C1H1T.js +1 -0
  421. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-TzRHMVog.js} +1 -1
  422. package/codeyam-cli/src/webserver/build/client/assets/manifest-040dab1c.js +1 -0
  423. package/codeyam-cli/src/webserver/build/client/assets/memory-UIDVz141.js +92 -0
  424. package/codeyam-cli/src/webserver/build/client/assets/pause-hjzB7t2z.js +11 -0
  425. package/codeyam-cli/src/webserver/build/client/assets/root-D1WadSdf.js +62 -0
  426. package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-DcAwD_Ln.js} +1 -1
  427. package/codeyam-cli/src/webserver/build/client/assets/settings-CclxrcPK.js +1 -0
  428. package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-DVNJVQgD.js} +1 -1
  429. package/codeyam-cli/src/webserver/build/client/assets/terminal-DbEAHMbA.js +11 -0
  430. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-CAD5b1o_.js} +1 -1
  431. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-BqgrAzs3.js} +1 -1
  432. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BUm0UVJm.js → useLastLogLine-DAFqfEDH.js} +1 -1
  433. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-DZlYx2c4.js} +1 -1
  434. package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-ihdMtlf6.js} +1 -1
  435. package/codeyam-cli/src/webserver/build/server/assets/index-B3dE0r28.js +1 -0
  436. package/codeyam-cli/src/webserver/build/server/assets/server-build-DYbfdxa3.js +273 -0
  437. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  438. package/codeyam-cli/src/webserver/build-info.json +5 -5
  439. package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +48 -4
  440. package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
  441. package/codeyam-cli/templates/codeyam-memory-hook.sh +199 -0
  442. package/codeyam-cli/templates/codeyam-memory.md +396 -0
  443. package/codeyam-cli/templates/codeyam-new-rule.md +13 -0
  444. package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
  445. package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
  446. package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
  447. package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
  448. package/codeyam-cli/templates/rule-notification-hook.py +56 -0
  449. package/codeyam-cli/templates/rule-reflection-hook.py +627 -0
  450. package/codeyam-cli/templates/rules-instructions.md +132 -0
  451. package/package.json +18 -15
  452. package/packages/ai/index.js +7 -3
  453. package/packages/ai/index.js.map +1 -1
  454. package/packages/ai/src/lib/analyzeScope.js +91 -30
  455. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  456. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
  457. package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
  458. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +78 -8
  459. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  460. package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
  461. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  462. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
  463. package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
  464. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
  465. package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
  466. package/packages/ai/src/lib/astScopes/processExpression.js +518 -28
  467. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  468. package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
  469. package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
  470. package/packages/ai/src/lib/completionCall.js +161 -30
  471. package/packages/ai/src/lib/completionCall.js.map +1 -1
  472. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +1061 -174
  473. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  474. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +5 -1
  475. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
  476. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
  477. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
  478. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
  479. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  480. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
  481. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
  482. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
  483. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
  484. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +52 -3
  485. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  486. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +106 -13
  487. package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
  488. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
  489. package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
  490. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +122 -12
  491. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  492. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +173 -0
  493. package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
  494. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
  495. package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
  496. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +333 -86
  497. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  498. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
  499. package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
  500. package/packages/ai/src/lib/dataStructureChunking.js +130 -0
  501. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
  502. package/packages/ai/src/lib/e2eDataTracking.js +241 -0
  503. package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
  504. package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
  505. package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
  506. package/packages/ai/src/lib/generateEntityDataStructure.js +46 -2
  507. package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
  508. package/packages/ai/src/lib/generateEntityScenarioData.js +734 -8
  509. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  510. package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
  511. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  512. package/packages/ai/src/lib/generateExecutionFlows.js +376 -4
  513. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  514. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +1124 -59
  515. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  516. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
  517. package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
  518. package/packages/ai/src/lib/isolateScopes.js +39 -3
  519. package/packages/ai/src/lib/isolateScopes.js.map +1 -1
  520. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
  521. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
  522. package/packages/ai/src/lib/mergeStatements.js +70 -51
  523. package/packages/ai/src/lib/mergeStatements.js.map +1 -1
  524. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
  525. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
  526. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
  527. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  528. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
  529. package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
  530. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +30 -7
  531. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  532. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
  533. package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
  534. package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
  535. package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
  536. package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
  537. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  538. package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
  539. package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
  540. package/packages/analyze/index.js +1 -0
  541. package/packages/analyze/index.js.map +1 -1
  542. package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
  543. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  544. package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
  545. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  546. package/packages/analyze/src/lib/analysisContext.js +30 -5
  547. package/packages/analyze/src/lib/analysisContext.js.map +1 -1
  548. package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
  549. package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
  550. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
  551. package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
  552. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
  553. package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
  554. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
  555. package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
  556. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
  557. package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
  558. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
  559. package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
  560. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
  561. package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
  562. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +72 -10
  563. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  564. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +17 -4
  565. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  566. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
  567. package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
  568. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
  569. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  570. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
  571. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  572. package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
  573. package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
  574. package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
  575. package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
  576. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js +880 -0
  577. package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
  578. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +164 -68
  579. package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
  580. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +75 -21
  581. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  582. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +185 -20
  583. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  584. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
  585. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  586. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +542 -53
  587. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  588. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
  589. package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
  590. package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
  591. package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
  592. package/packages/analyze/src/lib/index.js +1 -0
  593. package/packages/analyze/src/lib/index.js.map +1 -1
  594. package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
  595. package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
  596. package/packages/database/src/lib/analysisBranchToDb.js +1 -1
  597. package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
  598. package/packages/database/src/lib/analysisToDb.js +1 -1
  599. package/packages/database/src/lib/analysisToDb.js.map +1 -1
  600. package/packages/database/src/lib/branchToDb.js +1 -1
  601. package/packages/database/src/lib/branchToDb.js.map +1 -1
  602. package/packages/database/src/lib/commitBranchToDb.js +1 -1
  603. package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
  604. package/packages/database/src/lib/commitToDb.js +1 -1
  605. package/packages/database/src/lib/commitToDb.js.map +1 -1
  606. package/packages/database/src/lib/fileToDb.js +1 -1
  607. package/packages/database/src/lib/fileToDb.js.map +1 -1
  608. package/packages/database/src/lib/kysely/db.js +11 -1
  609. package/packages/database/src/lib/kysely/db.js.map +1 -1
  610. package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
  611. package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
  612. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
  613. package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
  614. package/packages/database/src/lib/loadAnalyses.js +45 -2
  615. package/packages/database/src/lib/loadAnalyses.js.map +1 -1
  616. package/packages/database/src/lib/loadAnalysis.js +8 -0
  617. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  618. package/packages/database/src/lib/loadBranch.js +11 -1
  619. package/packages/database/src/lib/loadBranch.js.map +1 -1
  620. package/packages/database/src/lib/loadCommit.js +7 -0
  621. package/packages/database/src/lib/loadCommit.js.map +1 -1
  622. package/packages/database/src/lib/loadCommits.js +22 -1
  623. package/packages/database/src/lib/loadCommits.js.map +1 -1
  624. package/packages/database/src/lib/loadEntities.js +23 -4
  625. package/packages/database/src/lib/loadEntities.js.map +1 -1
  626. package/packages/database/src/lib/loadEntityBranches.js +9 -0
  627. package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
  628. package/packages/database/src/lib/projectToDb.js +1 -1
  629. package/packages/database/src/lib/projectToDb.js.map +1 -1
  630. package/packages/database/src/lib/saveFiles.js +1 -1
  631. package/packages/database/src/lib/saveFiles.js.map +1 -1
  632. package/packages/database/src/lib/scenarioToDb.js +1 -1
  633. package/packages/database/src/lib/scenarioToDb.js.map +1 -1
  634. package/packages/database/src/lib/updateCommitMetadata.js +5 -4
  635. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  636. package/packages/types/index.js.map +1 -1
  637. package/packages/utils/src/lib/fs/rsyncCopy.js +93 -2
  638. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  639. package/packages/utils/src/lib/safeFileName.js +29 -3
  640. package/packages/utils/src/lib/safeFileName.js.map +1 -1
  641. package/scripts/finalize-analyzer.cjs +8 -76
  642. package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
  643. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
  644. package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
  645. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
  646. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
  647. package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
  648. package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
  649. package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
  650. package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
  651. package/codeyam-cli/src/webserver/build/client/assets/settings-B2eDuBj8.js +0 -1
  652. package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
  653. package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
  654. package/codeyam-cli/templates/codeyam:diagnose.md +0 -625
@@ -12,6 +12,78 @@
12
12
  * - compound conditionals → one flow with all conditions (only if ALL paths controllable)
13
13
  */
14
14
  import resolvePathToControllable from "./resolvePathToControllable.js";
15
+ import cleanPathOfNonTransformingFunctions from "./dataStructure/helpers/cleanPathOfNonTransformingFunctions.js";
16
+ /**
17
+ * Recursively expands a derived variable to its leaf data sources.
18
+ *
19
+ * For OR expressions like `isAnalyzing = a || b || c`:
20
+ * - Returns all source paths [a, b, c] so they can all be set appropriately
21
+ *
22
+ * For nested derivations like `isAnalyzing = isInCurrentRun || isInQueue`:
23
+ * - Where `isInCurrentRun` is derived from `currentRun.entityShas.includes(x)`
24
+ * - Returns the final data sources: [currentRun.entityShas, queueState.jobs]
25
+ *
26
+ * @param path The variable path to expand
27
+ * @param conditionalUsages All conditional usages (to look up derivedFrom info)
28
+ * @param attributesMap Map of controllable paths
29
+ * @param equivalentSignatureVariables Variable-to-path mappings
30
+ * @param fullToShortPathMap Full-to-short path mappings
31
+ * @param visited Set of already-visited paths (prevents infinite recursion)
32
+ * @param derivedVariables Optional map of all derived variables (for intermediate tracing)
33
+ * @returns Array of resolved source paths that are controllable
34
+ */
35
+ function expandDerivedVariableToSources(path, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, visited = new Set(), derivedVariables) {
36
+ // Prevent infinite recursion
37
+ if (visited.has(path)) {
38
+ return [];
39
+ }
40
+ visited.add(path);
41
+ // First, check if this path is directly controllable
42
+ const directResolution = resolvePathToControllable(path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
43
+ if (directResolution.isControllable && directResolution.resolvedPath) {
44
+ return [{ path: directResolution.resolvedPath }];
45
+ }
46
+ // Look up derivedFrom info for this path
47
+ // First check conditionalUsages, then fall back to derivedVariables
48
+ const usage = conditionalUsages[path]?.[0];
49
+ let derivedFrom = usage?.derivedFrom;
50
+ // CRITICAL: If not found in conditionalUsages, check derivedVariables
51
+ // This handles intermediate derived variables like `isInCurrentRun` that aren't
52
+ // directly used in conditionals but ARE derived from data sources
53
+ if (!derivedFrom && derivedVariables?.[path]) {
54
+ derivedFrom = derivedVariables[path];
55
+ }
56
+ if (!derivedFrom) {
57
+ return [];
58
+ }
59
+ const { operation, sourcePath, sourcePaths } = derivedFrom;
60
+ // For OR/AND operations, recursively expand all source paths
61
+ if ((operation === 'or' || operation === 'and') && sourcePaths) {
62
+ const allSources = [];
63
+ for (const sp of sourcePaths) {
64
+ const expanded = expandDerivedVariableToSources(sp, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, visited, derivedVariables);
65
+ // Add all expanded sources
66
+ for (const source of expanded) {
67
+ // Avoid duplicates
68
+ if (!allSources.some((s) => s.path === source.path)) {
69
+ allSources.push(source);
70
+ }
71
+ }
72
+ }
73
+ return allSources;
74
+ }
75
+ // For single-source operations (arrayIncludes, arraySome, notNull, etc.)
76
+ if (sourcePath) {
77
+ // Try to resolve the source path directly
78
+ const sourceResolution = resolvePathToControllable(sourcePath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
79
+ if (sourceResolution.isControllable && sourceResolution.resolvedPath) {
80
+ return [{ path: sourceResolution.resolvedPath, operation }];
81
+ }
82
+ // If not directly resolvable, recursively expand
83
+ return expandDerivedVariableToSources(sourcePath, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, visited, derivedVariables);
84
+ }
85
+ return [];
86
+ }
15
87
  /**
16
88
  * Clean up sourceDataPath by removing redundant scope prefixes.
17
89
  *
@@ -33,11 +105,13 @@ function cleanSourceDataPath(sourceDataPath) {
33
105
  // 2. Patterns like functionName(...) - closing paren followed by dot or end
34
106
  const emptyFnCalls = (sourceDataPath.match(/\(\)/g) || []).length;
35
107
  const fnCallReturnValues = (sourceDataPath.match(/\.functionCallReturnValue/g) || []).length;
36
- // If there are multiple functionCallReturnValue occurrences, this is a chained call
37
- // (e.g., fetch(...).functionCallReturnValue.json().functionCallReturnValue.data)
108
+ // For chained function calls (e.g., fetch().json()) or paths with non-standard
109
+ // fn call patterns, return the original path so findInAttributesMapForPath can
110
+ // try to look it up in fullToShortPathMap. If it doesn't match, the caller
111
+ // falls through to fallback resolution anyway.
38
112
  if (fnCallReturnValues > 1 || emptyFnCalls !== 1) {
39
- // Multiple function calls - return null to use fallback resolution
40
- return null;
113
+ console.log(`[cleanSourceDataPath] chained/non-standard path (fnCallRVs=${fnCallReturnValues}, emptyFnCalls=${emptyFnCalls}), returning original: "${sourceDataPath}"`);
114
+ return sourceDataPath;
41
115
  }
42
116
  // Find the "()" which marks the function call
43
117
  const fnCallIndex = sourceDataPath.indexOf('()');
@@ -59,6 +133,112 @@ function cleanSourceDataPath(sourceDataPath) {
59
133
  }
60
134
  return actualPath;
61
135
  }
136
+ /**
137
+ * Strip .length suffix from a path if present.
138
+ *
139
+ * When we have a path like "items.length", the controllable attribute is "items"
140
+ * (the array), not "items.length". The length is derived from the array contents.
141
+ *
142
+ * This ensures that execution flows reference the actual controllable attribute
143
+ * rather than the derived .length property.
144
+ */
145
+ function stripLengthSuffix(path) {
146
+ if (path.endsWith('.length')) {
147
+ return path.slice(0, -7); // Remove ".length" (7 characters)
148
+ }
149
+ return path;
150
+ }
151
+ /**
152
+ * Remove contradictory required values from a compound flow.
153
+ *
154
+ * When a lifecycle boolean (like isLoadingAuditData) is traced to a fetch call's
155
+ * return value, a negated condition (!isLoadingAuditData) produces "falsy" on
156
+ * the fetch path. But if another condition in the same compound requires data
157
+ * from a sub-path of that fetch (e.g., topPaths length > 0), the "falsy" on the
158
+ * parent path contradicts it — a null/falsy response has no .json() to call.
159
+ *
160
+ * This function removes "falsy" required values whose attributePath is a prefix
161
+ * of another required value's attributePath. The child data requirement already
162
+ * implies the parent (fetch) succeeded.
163
+ */
164
+ function removeContradictoryFalsyValues(requiredValues) {
165
+ return requiredValues.filter((rv) => {
166
+ if (rv.comparison === 'falsy') {
167
+ const hasChildRequirement = requiredValues.some((other) => other !== rv &&
168
+ other.attributePath.startsWith(rv.attributePath + '.'));
169
+ if (hasChildRequirement) {
170
+ return false;
171
+ }
172
+ }
173
+ return true;
174
+ });
175
+ }
176
+ /**
177
+ * Generate a human-readable description snippet for a required value,
178
+ * incorporating the comparison type so the LLM understands the intent.
179
+ */
180
+ function describeRequiredValue(rv) {
181
+ const name = generateNameFromPath(rv.attributePath).toLowerCase();
182
+ switch (rv.comparison) {
183
+ case 'truthy':
184
+ return `${name} is present`;
185
+ case 'falsy':
186
+ return `${name} is absent`;
187
+ case 'length>':
188
+ return rv.value === '0'
189
+ ? `${name} has items`
190
+ : `${name} has more than ${rv.value} items`;
191
+ case 'length<':
192
+ return `${name} has fewer than ${rv.value} items`;
193
+ case 'equals':
194
+ return `${name} is ${rv.value}`;
195
+ case 'exists':
196
+ return `${name} exists`;
197
+ case 'not-exists':
198
+ return `${name} does not exist`;
199
+ default:
200
+ return `${name} is ${rv.value}`;
201
+ }
202
+ }
203
+ /**
204
+ * Check whether a resolved path has child entries in the fullToShortPathMap.
205
+ *
206
+ * When a lifecycle boolean (e.g., isLoadingAuditData) resolves to a parent path
207
+ * like fetch(...).functionCallReturnValue, and that path has children (like
208
+ * .json().functionCallReturnValue.topPaths), individual truthy/falsy flows on
209
+ * the parent are misleading. Compound flows with specific child requirements
210
+ * provide better guidance for mock data generation.
211
+ */
212
+ function hasChildPathsInMap(resolvedPath, fullToShortPathMap) {
213
+ return Object.keys(fullToShortPathMap).some((fullPath) => fullPath.startsWith(resolvedPath + '.') ||
214
+ fullPath.startsWith(resolvedPath + '['));
215
+ }
216
+ /**
217
+ * Extract the controllable base path from a path that may contain method calls.
218
+ *
219
+ * This handles complex expressions like:
220
+ * - `scenarios.filter((s) => s.active).length` → `scenarios`
221
+ * - `users.some((u) => u.role === 'admin')` → `users`
222
+ * - `items.map(x => x.name).join(', ')` → `items`
223
+ *
224
+ * The controllable base is the path that can be mocked - we can control
225
+ * what `scenarios` contains, but we can't control what `.filter()` returns.
226
+ *
227
+ * @param path - The path that may contain method calls
228
+ * @returns The controllable base path with method calls stripped
229
+ */
230
+ function extractControllableBase(path) {
231
+ // First strip .length suffix if present
232
+ const pathWithoutLength = stripLengthSuffix(path);
233
+ // Use cleanPathOfNonTransformingFunctions to strip method calls like .filter(), .some()
234
+ const cleanedPath = cleanPathOfNonTransformingFunctions(pathWithoutLength);
235
+ // If the cleaned path is different, return it
236
+ if (cleanedPath !== pathWithoutLength) {
237
+ return cleanedPath;
238
+ }
239
+ // Otherwise, return the path with just .length stripped
240
+ return pathWithoutLength;
241
+ }
62
242
  /**
63
243
  * Find a path in attributesMap, using fullToShortPathMap to verify the path is controllable.
64
244
  *
@@ -71,9 +251,10 @@ function cleanSourceDataPath(sourceDataPath) {
71
251
  * The sourceDataPath contains full paths (e.g., "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha")
72
252
  * The fullToShortPathMap maps full paths to short paths
73
253
  */
74
- function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
254
+ export function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
75
255
  // Direct match in attributesMap (already a short path)
76
256
  if (path in attributesMap) {
257
+ console.log(`[findInAttributesMapForPath] "${path}" → DIRECT match in attributesMap`);
77
258
  return path;
78
259
  }
79
260
  // Try looking up the path in fullToShortPathMap to verify it's controllable
@@ -81,18 +262,22 @@ function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
81
262
  if (path in fullToShortPathMap) {
82
263
  const shortPath = fullToShortPathMap[path];
83
264
  if (shortPath in attributesMap) {
265
+ console.log(`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match: shortPath="${shortPath}" found in attributesMap`);
84
266
  return path; // Return FULL path to preserve data source context
85
267
  }
268
+ console.log(`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match shortPath="${shortPath}" but NOT in attributesMap`);
86
269
  }
87
270
  // Normalized match (array indices [N] → [])
88
271
  const normalizedPath = path.replace(/\[\d+\]/g, '[]');
89
272
  if (normalizedPath !== path) {
90
273
  if (normalizedPath in attributesMap) {
274
+ console.log(`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" DIRECT match in attributesMap`);
91
275
  return normalizedPath;
92
276
  }
93
277
  if (normalizedPath in fullToShortPathMap) {
94
278
  const shortPath = fullToShortPathMap[normalizedPath];
95
279
  if (shortPath in attributesMap) {
280
+ console.log(`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" fullToShortPathMap match: shortPath="${shortPath}"`);
96
281
  return normalizedPath; // Return normalized FULL path
97
282
  }
98
283
  }
@@ -103,20 +288,70 @@ function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
103
288
  // and we need to find matching short path prefix
104
289
  for (const attrPath of Object.keys(attributesMap)) {
105
290
  if (path.startsWith(attrPath + '.') || path.startsWith(attrPath + '[')) {
106
- // The path is a child of a known attribute path
291
+ console.log(`[findInAttributesMapForPath] "${path}" PREFIX match: starts with attributesMap key "${attrPath}"`);
107
292
  return path;
108
293
  }
109
294
  }
110
295
  // Try suffix matching: if the path ends with ".X.Y.Z" and attributesMap has "X.Y.Z"
111
296
  // Return the FULL input path to preserve data source context
112
- for (const attrPath of Object.keys(attributesMap)) {
113
- if (path.endsWith('.' + attrPath) ||
114
- path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))) {
115
- return path; // Return FULL path, not short attrPath
297
+ // Skip suffix matching for chained function calls (multiple .functionCallReturnValue segments)
298
+ // to avoid false matches: e.g., fetch(...).json().functionCallReturnValue.data falsely matching
299
+ // "data" from a completely different data source like useFetcher
300
+ const fnCallReturnValueCount = (path.match(/\.functionCallReturnValue/g) || []).length;
301
+ if (fnCallReturnValueCount <= 1) {
302
+ for (const attrPath of Object.keys(attributesMap)) {
303
+ if (path.endsWith('.' + attrPath) ||
304
+ path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))) {
305
+ console.log(`[findInAttributesMapForPath] "${path}" → SUFFIX match: ends with attributesMap key "${attrPath}"`);
306
+ return path; // Return FULL path, not short attrPath
307
+ }
308
+ }
309
+ }
310
+ // Try child path matching against fullToShortPathMap keys
311
+ // If the path starts with a known full path + '.' or '[', it's a child
312
+ // of a controllable path. Build the equivalent short child path.
313
+ // e.g., path = "fetch(...).fCRV.json().fCRV.topPaths.length"
314
+ // fullToShortPathMap has "fetch(...).fCRV.json().fCRV.topPaths" → "json().fCRV.topPaths"
315
+ // → check if "json().fCRV.topPaths.length" is in attributesMap
316
+ for (const [fullPath, shortPath] of Object.entries(fullToShortPathMap)) {
317
+ if (path.startsWith(fullPath + '.') || path.startsWith(fullPath + '[')) {
318
+ const suffix = path.slice(fullPath.length); // e.g., ".length"
319
+ const shortChildPath = shortPath + suffix;
320
+ if (shortChildPath in attributesMap) {
321
+ console.log(`[findInAttributesMapForPath] "${path}" → CHILD of fullToShortPathMap key "${fullPath}": shortChildPath="${shortChildPath}" found in attributesMap`);
322
+ return path; // Return full path to preserve data source context
323
+ }
324
+ // Also check if the base short path is an array and suffix is .length
325
+ if (suffix === '.length' && shortPath in attributesMap) {
326
+ console.log(`[findInAttributesMapForPath] "${path}" → CHILD .length of fullToShortPathMap key "${fullPath}": base shortPath="${shortPath}" is in attributesMap (array .length)`);
327
+ return path; // Array .length is controllable via the array
328
+ }
329
+ }
330
+ }
331
+ // Try parent matching: if the path is a prefix of any fullToShortPathMap key,
332
+ // it's a parent of controllable data and therefore controllable itself
333
+ for (const fullPath of Object.keys(fullToShortPathMap)) {
334
+ if (fullPath.startsWith(path + '.') || fullPath.startsWith(path + '[')) {
335
+ console.log(`[findInAttributesMapForPath] "${path}" → PARENT match: fullToShortPathMap key "${fullPath}" starts with this path`);
336
+ return path;
116
337
  }
117
338
  }
339
+ console.log(`[findInAttributesMapForPath] "${path}" → NO MATCH (checked ${Object.keys(attributesMap).length} attributesMap keys, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap keys)`);
118
340
  return null;
119
341
  }
342
+ /**
343
+ * Generate a slug from a path for use in flow IDs and exclusive groups.
344
+ */
345
+ function pathToSlug(path) {
346
+ return path
347
+ .replace(/\[\d+\]/g, '')
348
+ .replace(/\[\]/g, '')
349
+ .replace(/\(\)/g, '')
350
+ .replace(/\.functionCallReturnValue/g, '')
351
+ .replace(/[<>]/g, '')
352
+ .replace(/\./g, '-')
353
+ .toLowerCase();
354
+ }
120
355
  /**
121
356
  * Generate a human-readable name from a path.
122
357
  * Extracts the last meaningful part of the path.
@@ -173,6 +408,12 @@ function inferValueType(value) {
173
408
  /**
174
409
  * Generate flows from a single conditional usage.
175
410
  * Sets impact to 'high' if the conditional controls JSX rendering.
411
+ *
412
+ * When the usage has a `constraintExpression`, it represents a complex expression
413
+ * that can't be simply resolved (e.g., `scenarios.filter(x => x.active).length > 1`).
414
+ * In this case:
415
+ * - `attributePath` is set to the controllable base (e.g., `scenarios`)
416
+ * - `constraint` is set to the full expression for LLM reasoning
176
417
  */
177
418
  function generateFlowsFromUsage(usage, resolvedPath) {
178
419
  const flows = [];
@@ -182,6 +423,13 @@ function generateFlowsFromUsage(usage, resolvedPath) {
182
423
  const impact = usage.controlsJsxRendering
183
424
  ? 'high'
184
425
  : 'medium';
426
+ // When there's a constraintExpression, use the controllable base for attributePath
427
+ // and pass through the constraint for LLM reasoning
428
+ const hasConstraint = !!usage.constraintExpression;
429
+ const attributePath = hasConstraint
430
+ ? extractControllableBase(resolvedPath)
431
+ : stripLengthSuffix(resolvedPath);
432
+ const constraint = usage.constraintExpression;
185
433
  if (usage.conditionType === 'truthiness') {
186
434
  // Generate both truthy and falsy flows
187
435
  const isNegated = usage.isNegated ?? false;
@@ -192,10 +440,11 @@ function generateFlowsFromUsage(usage, resolvedPath) {
192
440
  description: `When ${baseName.toLowerCase()} is ${isNegated ? 'falsy' : 'truthy'}`,
193
441
  requiredValues: [
194
442
  {
195
- attributePath: resolvedPath,
443
+ attributePath,
196
444
  value: isNegated ? 'falsy' : 'truthy',
197
445
  comparison: isNegated ? 'falsy' : 'truthy',
198
446
  valueType: 'boolean',
447
+ constraint,
199
448
  },
200
449
  ],
201
450
  impact,
@@ -214,10 +463,11 @@ function generateFlowsFromUsage(usage, resolvedPath) {
214
463
  description: `When ${baseName.toLowerCase()} is ${isNegated ? 'truthy' : 'falsy'}`,
215
464
  requiredValues: [
216
465
  {
217
- attributePath: resolvedPath,
466
+ attributePath,
218
467
  value: isNegated ? 'truthy' : 'falsy',
219
468
  comparison: isNegated ? 'truthy' : 'falsy',
220
469
  valueType: 'boolean',
470
+ constraint,
221
471
  },
222
472
  ],
223
473
  impact,
@@ -241,10 +491,11 @@ function generateFlowsFromUsage(usage, resolvedPath) {
241
491
  description: `When ${baseName.toLowerCase()} equals "${value}"`,
242
492
  requiredValues: [
243
493
  {
244
- attributePath: resolvedPath,
494
+ attributePath,
245
495
  value: value,
246
496
  comparison: 'equals',
247
497
  valueType: inferValueType(value),
498
+ constraint,
248
499
  },
249
500
  ],
250
501
  impact,
@@ -290,29 +541,47 @@ function generateFlowFromCompound(compound, resolvedPaths) {
290
541
  condition.requiredValue?.toString() ??
291
542
  condition.comparedValues?.[0] ??
292
543
  'truthy';
293
- comparison = 'equals';
544
+ // Map comparison operator to flow comparison type
545
+ const op = condition.comparisonOperator;
546
+ if (op === '>' || op === '>=') {
547
+ comparison = 'length>';
548
+ }
549
+ else if (op === '<' || op === '<=') {
550
+ comparison = 'length<';
551
+ }
552
+ else {
553
+ comparison = 'equals';
554
+ }
294
555
  }
295
556
  requiredValues.push({
296
- attributePath: resolvedPath,
557
+ attributePath: stripLengthSuffix(resolvedPath),
297
558
  value,
298
559
  comparison,
299
560
  valueType: inferValueType(value),
300
561
  });
301
562
  }
302
- // Generate a combined ID from all paths
303
- const pathParts = requiredValues
563
+ // Remove contradictory "falsy" values where a child path requires data
564
+ const cleanedValues = removeContradictoryFalsyValues(requiredValues);
565
+ if (cleanedValues.length === 0) {
566
+ return null;
567
+ }
568
+ // Generate a combined ID from all paths + values to distinguish different comparisons
569
+ const pathParts = cleanedValues
304
570
  .map((rv) => {
305
571
  const name = generateNameFromPath(rv.attributePath);
306
- return name.toLowerCase().replace(/\s+/g, '-');
572
+ const suffix = rv.comparison === 'truthy' || rv.comparison === 'falsy'
573
+ ? `-${rv.comparison}`
574
+ : `-${rv.comparison}-${rv.value}`;
575
+ return name.toLowerCase().replace(/\s+/g, '-') + suffix;
307
576
  })
308
577
  .join('-and-');
309
578
  return {
310
579
  id: `compound-${pathParts}`,
311
- name: requiredValues
580
+ name: cleanedValues
312
581
  .map((rv) => generateNameFromPath(rv.attributePath))
313
582
  .join(' + '),
314
- description: `When ${requiredValues.map((rv) => `${generateNameFromPath(rv.attributePath).toLowerCase()} is ${rv.value}`).join(' and ')}`,
315
- requiredValues,
583
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
584
+ requiredValues: cleanedValues,
316
585
  impact,
317
586
  sourceLocation: {
318
587
  lineNumber: compound.sourceLocation.lineNumber,
@@ -321,6 +590,48 @@ function generateFlowFromCompound(compound, resolvedPaths) {
321
590
  codeSnippet: compound.sourceLocation.codeSnippet,
322
591
  };
323
592
  }
593
+ /**
594
+ * Expand a compound conditional with OR groups into multiple condition sets.
595
+ *
596
+ * For a compound like `A && (B || C)`:
597
+ * - Conditions: [{ path: 'A' }, { path: 'B', orGroupId: 'or_xxx' }, { path: 'C', orGroupId: 'or_xxx' }]
598
+ * - Returns: [[A, B], [A, C]] - two sets of conditions
599
+ *
600
+ * For multiple OR groups like `A && (B || C) && (D || E)`:
601
+ * - Returns: [[A, B, D], [A, B, E], [A, C, D], [A, C, E]]
602
+ */
603
+ function expandOrGroups(conditions) {
604
+ // Separate conditions into mandatory (no orGroupId) and OR groups
605
+ const mandatory = conditions.filter((c) => !c.orGroupId);
606
+ const orGroups = new Map();
607
+ for (const condition of conditions) {
608
+ if (condition.orGroupId) {
609
+ const group = orGroups.get(condition.orGroupId) ?? [];
610
+ group.push(condition);
611
+ orGroups.set(condition.orGroupId, group);
612
+ }
613
+ }
614
+ // If no OR groups, return the original conditions
615
+ if (orGroups.size === 0) {
616
+ return [conditions];
617
+ }
618
+ // Generate all combinations by picking one condition from each OR group
619
+ const groupArrays = Array.from(orGroups.values());
620
+ const combinations = [];
621
+ function generateCombinations(index, current) {
622
+ if (index === groupArrays.length) {
623
+ // We've picked one from each OR group - combine with mandatory conditions
624
+ combinations.push([...mandatory, ...current]);
625
+ return;
626
+ }
627
+ // Pick each option from the current OR group
628
+ for (const option of groupArrays[index]) {
629
+ generateCombinations(index + 1, [...current, option]);
630
+ }
631
+ }
632
+ generateCombinations(0, []);
633
+ return combinations;
634
+ }
324
635
  /**
325
636
  * Generate execution flows from conditional usages using pure static analysis.
326
637
  *
@@ -386,7 +697,11 @@ function translateChildPathToParent(childPath, childEquivalentSignatureVariables
386
697
  }
387
698
  // Look up the child's equivalence for this root variable
388
699
  // e.g., childEquiv[selectedScenario] = "signature[0].selectedScenario"
389
- const childPropPath = childEquivalentSignatureVariables[rootVar];
700
+ // Handle array case (OR expressions) - use first element if array
701
+ const rawChildPropPath = childEquivalentSignatureVariables[rootVar];
702
+ const childPropPath = Array.isArray(rawChildPropPath)
703
+ ? rawChildPropPath[0]
704
+ : rawChildPropPath;
390
705
  if (!childPropPath) {
391
706
  // No mapping found - this might be internal state, not a prop
392
707
  return null;
@@ -396,7 +711,11 @@ function translateChildPathToParent(childPath, childEquivalentSignatureVariables
396
711
  const fullChildPropPath = `${childName}().${childPropPath}`;
397
712
  // Look up parent's equivalence to find what value was passed to this prop
398
713
  // e.g., parentEquiv["ChildName().signature[0].selectedScenario"] = "selectedScenario"
399
- const parentValue = parentEquivalentSignatureVariables[fullChildPropPath];
714
+ // Handle array case (OR expressions) - use first element if array
715
+ const rawParentValue = parentEquivalentSignatureVariables[fullChildPropPath];
716
+ const parentValue = Array.isArray(rawParentValue)
717
+ ? rawParentValue[0]
718
+ : rawParentValue;
400
719
  if (!parentValue) {
401
720
  // No parent mapping found - log ALL parent keys that contain the childName
402
721
  const relevantParentKeys = Object.keys(parentEquivalentSignatureVariables).filter((k) => k.includes(childName));
@@ -408,9 +727,14 @@ function translateChildPathToParent(childPath, childEquivalentSignatureVariables
408
727
  return result;
409
728
  }
410
729
  export default function generateExecutionFlowsFromConditionals(args) {
411
- const { conditionalUsages, compoundConditionals, attributesMap, equivalentSignatureVariables, fullToShortPathMap, childComponentData, } = args;
730
+ const { conditionalUsages, compoundConditionals, attributesMap, equivalentSignatureVariables, fullToShortPathMap, childComponentData, derivedVariables, sourceEquivalencies, } = args;
412
731
  const flows = [];
413
732
  const seenFlowIds = new Set();
733
+ console.log(`[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`);
734
+ console.log(`[genFlowsFromConditionals] conditionalUsages keys: [${Object.keys(conditionalUsages).join(', ')}]`);
735
+ console.log(`[genFlowsFromConditionals] attributesMap keys: [${Object.keys(attributesMap).join(', ')}]`);
736
+ console.log(`[genFlowsFromConditionals] fullToShortPathMap: ${JSON.stringify(fullToShortPathMap)}`);
737
+ console.log(`[genFlowsFromConditionals] equivalentSignatureVariables: ${JSON.stringify(equivalentSignatureVariables)}`);
414
738
  // Track normalized resolved paths to prevent duplicate flows
415
739
  // This handles the case where we have usages for both:
416
740
  // - "hasNewerVersion" (short path from destructured variable)
@@ -424,8 +748,10 @@ export default function generateExecutionFlowsFromConditionals(args) {
424
748
  for (const usage of usages) {
425
749
  // Skip usages that are part of compound conditionals (handled separately)
426
750
  if (usage.chainId && compoundChainIds.has(usage.chainId)) {
751
+ console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: part of compound conditional chain=${usage.chainId}`);
427
752
  continue;
428
753
  }
754
+ console.log(`[genFlowsFromConditionals] --- Processing "${usage.path}" (type=${usage.conditionType}, negated=${usage.isNegated}, sourceDataPath="${usage.sourceDataPath ?? '(none)'}", derivedFrom=${usage.derivedFrom ? JSON.stringify(usage.derivedFrom) : 'none'})`);
429
755
  // First, try to use pre-computed sourceDataPath if available
430
756
  let resolvedPath = null;
431
757
  if (usage.sourceDataPath) {
@@ -434,9 +760,11 @@ export default function generateExecutionFlowsFromConditionals(args) {
434
760
  // should become "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
435
761
  // Returns null for malformed paths (e.g., chained function calls like fetch().json())
436
762
  const cleanedPath = cleanSourceDataPath(usage.sourceDataPath);
763
+ console.log(`[genFlowsFromConditionals] "${usage.path}" cleanSourceDataPath("${usage.sourceDataPath}") → "${cleanedPath}"`);
437
764
  if (cleanedPath) {
438
765
  // Verify the cleaned path exists in attributesMap
439
766
  const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
767
+ console.log(`[genFlowsFromConditionals] "${usage.path}" findInAttributesMapForPath("${cleanedPath}") → ${pathMatch ? `"${pathMatch}"` : 'null (not found)'}`);
440
768
  if (pathMatch) {
441
769
  resolvedPath = pathMatch;
442
770
  }
@@ -445,7 +773,9 @@ export default function generateExecutionFlowsFromConditionals(args) {
445
773
  }
446
774
  // Fall back to resolution via equivalentSignatureVariables
447
775
  if (!resolvedPath) {
776
+ console.log(`[genFlowsFromConditionals] "${usage.path}" sourceDataPath resolution failed, trying resolvePathToControllable("${usage.path}")...`);
448
777
  const resolution = resolvePathToControllable(usage.path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
778
+ console.log(`[genFlowsFromConditionals] "${usage.path}" resolvePathToControllable → isControllable=${resolution.isControllable}, resolvedPath="${resolution.resolvedPath ?? '(none)'}"`);
449
779
  if (resolution.isControllable && resolution.resolvedPath) {
450
780
  resolvedPath = resolution.resolvedPath;
451
781
  }
@@ -454,7 +784,8 @@ export default function generateExecutionFlowsFromConditionals(args) {
454
784
  // This handles cases like: const hasAnalysis = analysis !== null
455
785
  // where hasAnalysis is not in attributesMap but analysis is
456
786
  if (!resolvedPath && usage.derivedFrom) {
457
- const { sourcePath, sourcePaths } = usage.derivedFrom;
787
+ const { operation, sourcePath, sourcePaths, comparedValue } = usage.derivedFrom;
788
+ console.log(`[genFlowsFromConditionals] "${usage.path}" trying derivedFrom: operation=${operation}, sourcePath="${sourcePath ?? '(none)'}", sourcePaths=${sourcePaths ? JSON.stringify(sourcePaths) : '(none)'}, comparedValue="${comparedValue ?? '(none)'}"`);
458
789
  // For single-source derivations (notNull, equals, etc.)
459
790
  if (sourcePath) {
460
791
  const resolution = resolvePathToControllable(sourcePath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
@@ -462,8 +793,232 @@ export default function generateExecutionFlowsFromConditionals(args) {
462
793
  resolvedPath = resolution.resolvedPath;
463
794
  }
464
795
  }
465
- // For multi-source derivations (or, and), try the first resolvable path
466
- // This is a simplification - ideally we'd generate flows for each source
796
+ // For equals/notEquals derivations with comparedValue, generate comparison flows
797
+ // e.g., canEdit derived from user.role === 'admin'
798
+ // When canEdit is used in truthiness check, we need:
799
+ // - Truthy flow: user.role = 'admin' (comparison: 'equals')
800
+ // - Falsy flow: user.role != 'admin' (comparison: 'notEquals')
801
+ if ((operation === 'equals' || operation === 'notEquals') &&
802
+ comparedValue !== undefined &&
803
+ resolvedPath &&
804
+ usage.conditionType === 'truthiness') {
805
+ const baseName = generateNameFromPath(usage.path);
806
+ const impact = usage.controlsJsxRendering
807
+ ? 'high'
808
+ : 'medium';
809
+ const isNegated = usage.isNegated ?? false;
810
+ // For equals derivation:
811
+ // - Truthy check (!negated): needs value = comparedValue (equals)
812
+ // - Falsy check (negated): needs value != comparedValue (notEquals)
813
+ // For notEquals derivation: inverse of above
814
+ const isEqualsDerivation = operation === 'equals';
815
+ const truthyNeedsEquals = isEqualsDerivation !== isNegated;
816
+ // Generate truthy flow
817
+ const truthyFlow = {
818
+ id: generateFlowId(usage.path, 'truthy'),
819
+ name: `${baseName} True`,
820
+ description: `When ${baseName.toLowerCase()} is truthy (${resolvedPath} ${truthyNeedsEquals ? '=' : '!='} ${comparedValue})`,
821
+ requiredValues: [
822
+ {
823
+ attributePath: stripLengthSuffix(resolvedPath),
824
+ value: comparedValue,
825
+ comparison: truthyNeedsEquals ? 'equals' : 'notEquals',
826
+ valueType: inferValueType(comparedValue),
827
+ },
828
+ ],
829
+ impact,
830
+ sourceLocation: usage.sourceLocation
831
+ ? {
832
+ lineNumber: usage.sourceLocation.lineNumber,
833
+ column: usage.sourceLocation.column,
834
+ }
835
+ : undefined,
836
+ codeSnippet: usage.sourceLocation?.codeSnippet,
837
+ };
838
+ // Generate falsy flow
839
+ const falsyFlow = {
840
+ id: generateFlowId(usage.path, 'falsy'),
841
+ name: `${baseName} False`,
842
+ description: `When ${baseName.toLowerCase()} is falsy (${resolvedPath} ${truthyNeedsEquals ? '!=' : '='} ${comparedValue})`,
843
+ requiredValues: [
844
+ {
845
+ attributePath: stripLengthSuffix(resolvedPath),
846
+ value: comparedValue,
847
+ comparison: truthyNeedsEquals ? 'notEquals' : 'equals',
848
+ valueType: inferValueType(comparedValue),
849
+ },
850
+ ],
851
+ impact,
852
+ sourceLocation: usage.sourceLocation
853
+ ? {
854
+ lineNumber: usage.sourceLocation.lineNumber,
855
+ column: usage.sourceLocation.column,
856
+ }
857
+ : undefined,
858
+ codeSnippet: usage.sourceLocation?.codeSnippet,
859
+ };
860
+ // Add flows and skip normal flow generation
861
+ if (!seenFlowIds.has(truthyFlow.id)) {
862
+ seenFlowIds.add(truthyFlow.id);
863
+ flows.push(truthyFlow);
864
+ }
865
+ if (!seenFlowIds.has(falsyFlow.id)) {
866
+ seenFlowIds.add(falsyFlow.id);
867
+ flows.push(falsyFlow);
868
+ }
869
+ continue;
870
+ }
871
+ // For OR derivations with negation, we need ALL sources to be falsy
872
+ // e.g., !isBusy where isBusy = isRunning || isQueued || isPending
873
+ // For the falsy flow, ALL sources must be falsy
874
+ if (operation === 'or' &&
875
+ usage.conditionType === 'truthiness' &&
876
+ usage.isNegated === true &&
877
+ sourcePaths &&
878
+ sourcePaths.length > 0) {
879
+ // Use expandDerivedVariableToSources to recursively resolve all sources
880
+ const allSources = expandDerivedVariableToSources(usage.path, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, new Set(), derivedVariables);
881
+ if (allSources.length > 0) {
882
+ // Generate a compound-style flow with all sources set to falsy
883
+ const baseName = generateNameFromPath(usage.path);
884
+ const impact = usage.controlsJsxRendering
885
+ ? 'high'
886
+ : 'medium';
887
+ const requiredValues = allSources.map((source) => ({
888
+ attributePath: source.path,
889
+ value: 'falsy',
890
+ comparison: 'falsy',
891
+ valueType: 'boolean',
892
+ }));
893
+ // Create a single falsy flow with all sources
894
+ const falsyFlow = {
895
+ id: generateFlowId(usage.path, 'falsy'),
896
+ name: `${baseName} False`,
897
+ description: `When ${baseName.toLowerCase()} is falsy (all sources are falsy)`,
898
+ requiredValues,
899
+ impact,
900
+ sourceLocation: usage.sourceLocation
901
+ ? {
902
+ lineNumber: usage.sourceLocation.lineNumber,
903
+ column: usage.sourceLocation.column,
904
+ }
905
+ : undefined,
906
+ codeSnippet: usage.sourceLocation?.codeSnippet,
907
+ };
908
+ // Create a truthy flow - for OR, ANY source being truthy is sufficient
909
+ // We use the first resolvable source for the truthy flow
910
+ const firstSource = allSources[0];
911
+ const truthyFlow = {
912
+ id: generateFlowId(usage.path, 'truthy'),
913
+ name: `${baseName} True`,
914
+ description: `When ${baseName.toLowerCase()} is truthy`,
915
+ requiredValues: [
916
+ {
917
+ attributePath: firstSource.path,
918
+ value: 'truthy',
919
+ comparison: 'truthy',
920
+ valueType: 'boolean',
921
+ },
922
+ ],
923
+ impact,
924
+ sourceLocation: usage.sourceLocation
925
+ ? {
926
+ lineNumber: usage.sourceLocation.lineNumber,
927
+ column: usage.sourceLocation.column,
928
+ }
929
+ : undefined,
930
+ codeSnippet: usage.sourceLocation?.codeSnippet,
931
+ };
932
+ // Add both flows (falsy needs all sources, truthy needs one)
933
+ if (!seenFlowIds.has(falsyFlow.id)) {
934
+ seenFlowIds.add(falsyFlow.id);
935
+ flows.push(falsyFlow);
936
+ }
937
+ if (!seenFlowIds.has(truthyFlow.id)) {
938
+ seenFlowIds.add(truthyFlow.id);
939
+ flows.push(truthyFlow);
940
+ }
941
+ // Skip the normal flow generation for this usage
942
+ continue;
943
+ }
944
+ }
945
+ // For AND derivations without negation, we need ALL sources to be truthy
946
+ // e.g., isReady where isReady = hasData && isLoaded && isValid
947
+ // For the truthy flow, ALL sources must be truthy
948
+ // For negated AND (!isReady), ANY source being falsy is sufficient (fallback behavior)
949
+ if (operation === 'and' &&
950
+ usage.conditionType === 'truthiness' &&
951
+ usage.isNegated !== true &&
952
+ sourcePaths &&
953
+ sourcePaths.length > 0) {
954
+ // Use expandDerivedVariableToSources to recursively resolve all sources
955
+ const allSources = expandDerivedVariableToSources(usage.path, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, new Set(), derivedVariables);
956
+ if (allSources.length > 0) {
957
+ // Generate a compound-style flow with all sources set to truthy
958
+ const baseName = generateNameFromPath(usage.path);
959
+ const impact = usage.controlsJsxRendering
960
+ ? 'high'
961
+ : 'medium';
962
+ const requiredValues = allSources.map((source) => ({
963
+ attributePath: source.path,
964
+ value: 'truthy',
965
+ comparison: 'truthy',
966
+ valueType: 'boolean',
967
+ }));
968
+ // Create a truthy flow with all sources
969
+ const truthyFlow = {
970
+ id: generateFlowId(usage.path, 'truthy'),
971
+ name: `${baseName} True`,
972
+ description: `When ${baseName.toLowerCase()} is truthy (all sources are truthy)`,
973
+ requiredValues,
974
+ impact,
975
+ sourceLocation: usage.sourceLocation
976
+ ? {
977
+ lineNumber: usage.sourceLocation.lineNumber,
978
+ column: usage.sourceLocation.column,
979
+ }
980
+ : undefined,
981
+ codeSnippet: usage.sourceLocation?.codeSnippet,
982
+ };
983
+ // Create a falsy flow - for AND, ANY source being falsy is sufficient
984
+ // We use the first resolvable source for the falsy flow
985
+ const firstSource = allSources[0];
986
+ const falsyFlow = {
987
+ id: generateFlowId(usage.path, 'falsy'),
988
+ name: `${baseName} False`,
989
+ description: `When ${baseName.toLowerCase()} is falsy`,
990
+ requiredValues: [
991
+ {
992
+ attributePath: firstSource.path,
993
+ value: 'falsy',
994
+ comparison: 'falsy',
995
+ valueType: 'boolean',
996
+ },
997
+ ],
998
+ impact,
999
+ sourceLocation: usage.sourceLocation
1000
+ ? {
1001
+ lineNumber: usage.sourceLocation.lineNumber,
1002
+ column: usage.sourceLocation.column,
1003
+ }
1004
+ : undefined,
1005
+ codeSnippet: usage.sourceLocation?.codeSnippet,
1006
+ };
1007
+ // Add both flows (truthy needs all sources, falsy needs one)
1008
+ if (!seenFlowIds.has(truthyFlow.id)) {
1009
+ seenFlowIds.add(truthyFlow.id);
1010
+ flows.push(truthyFlow);
1011
+ }
1012
+ if (!seenFlowIds.has(falsyFlow.id)) {
1013
+ seenFlowIds.add(falsyFlow.id);
1014
+ flows.push(falsyFlow);
1015
+ }
1016
+ // Skip the normal flow generation for this usage
1017
+ continue;
1018
+ }
1019
+ }
1020
+ // For multi-source derivations (or, and) without special handling,
1021
+ // try the first resolvable path as a fallback
467
1022
  if (!resolvedPath && sourcePaths && sourcePaths.length > 0) {
468
1023
  for (const sp of sourcePaths) {
469
1024
  const resolution = resolvePathToControllable(sp, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
@@ -476,6 +1031,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
476
1031
  }
477
1032
  if (!resolvedPath) {
478
1033
  // Path is not controllable - skip (no invalid flows possible)
1034
+ console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: not controllable (no resolvedPath after all attempts)`);
479
1035
  continue;
480
1036
  }
481
1037
  // Normalize the resolved path to detect duplicates
@@ -485,9 +1041,22 @@ export default function generateExecutionFlowsFromConditionals(args) {
485
1041
  // Skip if we've already generated flows for this normalized path
486
1042
  // This prevents duplicate flows when we have usages for both short and full paths
487
1043
  if (seenNormalizedPaths.has(normalizedPath)) {
1044
+ console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: duplicate normalizedPath="${normalizedPath}" (resolvedPath="${resolvedPath}")`);
488
1045
  continue;
489
1046
  }
490
1047
  seenNormalizedPaths.add(normalizedPath);
1048
+ // Skip individual truthy/falsy flows on parent paths that have child data entries.
1049
+ // Lifecycle booleans (like isLoadingAuditData) traced to fetch(...).functionCallReturnValue
1050
+ // produce misleading truthy/falsy flows: "truthy" can't show loading (mock resolves instantly),
1051
+ // "falsy" tells the LLM to return null (breaking .json()). Compound flows with specific child
1052
+ // data requirements provide the correct mock guidance.
1053
+ if (usage.conditionType === 'truthiness' &&
1054
+ resolvedPath &&
1055
+ hasChildPathsInMap(resolvedPath, fullToShortPathMap)) {
1056
+ console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: parent path "${resolvedPath}" has child data paths — compound flows will handle this`);
1057
+ continue;
1058
+ }
1059
+ console.log(`[genFlowsFromConditionals] "${usage.path}" RESOLVED → resolvedPath="${resolvedPath}", normalizedPath="${normalizedPath}" — generating flows`);
491
1060
  // Generate flows for this controllable usage
492
1061
  const usageFlows = generateFlowsFromUsage(usage, resolvedPath);
493
1062
  for (const flow of usageFlows) {
@@ -495,29 +1064,226 @@ export default function generateExecutionFlowsFromConditionals(args) {
495
1064
  if (!seenFlowIds.has(flow.id)) {
496
1065
  seenFlowIds.add(flow.id);
497
1066
  flows.push(flow);
1067
+ console.log(`[genFlowsFromConditionals] "${usage.path}" FLOW ADDED: id="${flow.id}", requiredValues=${JSON.stringify(flow.requiredValues.map((rv) => ({ attr: rv.attributePath, val: rv.value })))}`);
498
1068
  }
499
1069
  }
500
1070
  }
501
1071
  }
502
1072
  // Process compound conditionals
503
1073
  for (const compound of compoundConditionals) {
504
- // First, check if ALL paths in this compound are controllable
505
- const resolvedPaths = new Map();
506
- let allControllable = true;
507
- for (const condition of compound.conditions) {
508
- const resolution = resolvePathToControllable(condition.path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
509
- if (!resolution.isControllable || !resolution.resolvedPath) {
510
- allControllable = false;
511
- break;
1074
+ // Expand OR groups into separate condition sets
1075
+ // For example, `A && (B || C)` becomes [[A, B], [A, C]]
1076
+ const expandedConditionSets = expandOrGroups(compound.conditions);
1077
+ // Process each expanded condition set as a separate potential flow
1078
+ for (const conditionSet of expandedConditionSets) {
1079
+ // First, check if ALL paths in this condition set are controllable (or can be expanded to controllable sources)
1080
+ const resolvedPaths = new Map();
1081
+ // Track expanded sources for derived variables (path -> array of expanded sources)
1082
+ const expandedSources = new Map();
1083
+ let allControllable = true;
1084
+ for (const condition of conditionSet) {
1085
+ // Check if this condition path has derivation info
1086
+ // First check conditionalUsages, then fall back to derivedVariables
1087
+ const usagesForPath = conditionalUsages[condition.path];
1088
+ let derivedFromInfo = usagesForPath?.find((u) => u.derivedFrom?.operation)?.derivedFrom;
1089
+ // CRITICAL: Also check derivedVariables for intermediate derived variables
1090
+ if (!derivedFromInfo && derivedVariables?.[condition.path]) {
1091
+ derivedFromInfo = derivedVariables[condition.path];
1092
+ }
1093
+ if (derivedFromInfo) {
1094
+ // This is a derived variable - expand to its sources
1095
+ const sources = expandDerivedVariableToSources(condition.path, conditionalUsages, attributesMap, equivalentSignatureVariables, fullToShortPathMap, new Set(), derivedVariables);
1096
+ if (sources.length > 0) {
1097
+ // Store the expanded sources for this condition
1098
+ expandedSources.set(condition.path, sources);
1099
+ // Use the first source's path for the resolvedPaths map (for ID generation)
1100
+ resolvedPaths.set(condition.path, sources[0].path);
1101
+ }
1102
+ else {
1103
+ // Derived variable expansion failed — try sourceDataPath fallback
1104
+ // This handles cases where the derivation chain goes through useMemo/useState
1105
+ // but the enriched sourceDataPath already traced to the actual data source
1106
+ const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
1107
+ let derivedFallbackPath = null;
1108
+ if (usageWithSource?.sourceDataPath) {
1109
+ const cleanedPath = cleanSourceDataPath(usageWithSource.sourceDataPath);
1110
+ if (cleanedPath) {
1111
+ const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
1112
+ if (pathMatch) {
1113
+ derivedFallbackPath = pathMatch;
1114
+ }
1115
+ }
1116
+ }
1117
+ if (derivedFallbackPath) {
1118
+ resolvedPaths.set(condition.path, derivedFallbackPath);
1119
+ console.log(`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived expansion failed but sourceDataPath fallback resolved → "${derivedFallbackPath}"`);
1120
+ }
1121
+ else {
1122
+ // Truly not controllable
1123
+ console.log(`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived but no controllable sources and no sourceDataPath fallback → NOT controllable`);
1124
+ allControllable = false;
1125
+ break;
1126
+ }
1127
+ }
1128
+ }
1129
+ else {
1130
+ // Not a derived variable - resolve directly
1131
+ // First try sourceDataPath from the usage (same as individual processing)
1132
+ let compoundResolvedPath = null;
1133
+ const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
1134
+ if (usageWithSource?.sourceDataPath) {
1135
+ const cleanedPath = cleanSourceDataPath(usageWithSource.sourceDataPath);
1136
+ if (cleanedPath) {
1137
+ const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
1138
+ if (pathMatch) {
1139
+ compoundResolvedPath = pathMatch;
1140
+ }
1141
+ }
1142
+ }
1143
+ if (!compoundResolvedPath) {
1144
+ const resolution = resolvePathToControllable(condition.path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1145
+ if (resolution.isControllable && resolution.resolvedPath) {
1146
+ compoundResolvedPath = resolution.resolvedPath;
1147
+ }
1148
+ }
1149
+ if (!compoundResolvedPath) {
1150
+ allControllable = false;
1151
+ break;
1152
+ }
1153
+ resolvedPaths.set(condition.path, compoundResolvedPath);
1154
+ }
512
1155
  }
513
- resolvedPaths.set(condition.path, resolution.resolvedPath);
514
- }
515
- // Only create a flow if ALL paths are controllable
516
- if (allControllable && resolvedPaths.size > 0) {
517
- const compoundFlow = generateFlowFromCompound(compound, resolvedPaths);
518
- if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
519
- seenFlowIds.add(compoundFlow.id);
520
- flows.push(compoundFlow);
1156
+ // Only create a flow if ALL paths are controllable
1157
+ if (allControllable && resolvedPaths.size > 0) {
1158
+ // If any conditions were expanded from derived variables, we need to build a custom flow
1159
+ if (expandedSources.size > 0) {
1160
+ const requiredValues = [];
1161
+ for (const condition of conditionSet) {
1162
+ const sources = expandedSources.get(condition.path);
1163
+ if (sources) {
1164
+ // This condition was expanded - add all its sources
1165
+ // Determine the required value based on condition type and derivation operation
1166
+ const usagesForPath = conditionalUsages[condition.path];
1167
+ let expandedDerivedFrom = usagesForPath?.find((u) => u.derivedFrom?.operation)?.derivedFrom;
1168
+ // Also check derivedVariables for intermediate derived variables
1169
+ if (!expandedDerivedFrom && derivedVariables?.[condition.path]) {
1170
+ expandedDerivedFrom = derivedVariables[condition.path];
1171
+ }
1172
+ const operation = expandedDerivedFrom?.operation;
1173
+ for (const source of sources) {
1174
+ // For OR-derived truthy: ANY source truthy
1175
+ // For AND-derived truthy: ALL sources truthy
1176
+ // For negated: inverse
1177
+ let value;
1178
+ let comparison;
1179
+ if (condition.conditionType === 'truthiness') {
1180
+ const isNegated = condition.isNegated === true;
1181
+ // For OR: truthy needs ANY source truthy, falsy needs ALL sources falsy
1182
+ // For AND: truthy needs ALL sources truthy, falsy needs ANY source falsy
1183
+ // In compound conditionals, we generate the truthy path by default
1184
+ // (the compound expression must be truthy)
1185
+ if (operation === 'or') {
1186
+ // For OR-derived, truthy means we need at least one source truthy
1187
+ // We'll use the first source as truthy (simplification)
1188
+ value = isNegated ? 'falsy' : 'truthy';
1189
+ }
1190
+ else if (operation === 'and') {
1191
+ // For AND-derived, truthy means ALL sources truthy
1192
+ value = isNegated ? 'falsy' : 'truthy';
1193
+ }
1194
+ else {
1195
+ value = isNegated ? 'falsy' : 'truthy';
1196
+ }
1197
+ comparison = isNegated ? 'falsy' : 'truthy';
1198
+ }
1199
+ else {
1200
+ value = 'truthy';
1201
+ comparison = 'truthy';
1202
+ }
1203
+ requiredValues.push({
1204
+ attributePath: source.path,
1205
+ value,
1206
+ comparison,
1207
+ valueType: 'boolean',
1208
+ });
1209
+ }
1210
+ }
1211
+ else {
1212
+ // This condition was resolved directly
1213
+ const resolvedPath = resolvedPaths.get(condition.path);
1214
+ if (resolvedPath) {
1215
+ let value;
1216
+ let comparison;
1217
+ if (condition.conditionType === 'truthiness') {
1218
+ value = condition.isNegated ? 'falsy' : 'truthy';
1219
+ comparison = condition.isNegated ? 'falsy' : 'truthy';
1220
+ }
1221
+ else {
1222
+ value =
1223
+ condition.requiredValue?.toString() ??
1224
+ condition.comparedValues?.[0] ??
1225
+ 'truthy';
1226
+ const op = condition.comparisonOperator;
1227
+ if (op === '>' || op === '>=') {
1228
+ comparison = 'length>';
1229
+ }
1230
+ else if (op === '<' || op === '<=') {
1231
+ comparison = 'length<';
1232
+ }
1233
+ else {
1234
+ comparison = 'equals';
1235
+ }
1236
+ }
1237
+ requiredValues.push({
1238
+ attributePath: stripLengthSuffix(resolvedPath),
1239
+ value,
1240
+ comparison,
1241
+ valueType: inferValueType(value),
1242
+ });
1243
+ }
1244
+ }
1245
+ }
1246
+ // Remove contradictory "falsy" values where a child path requires data
1247
+ const cleanedValues = removeContradictoryFalsyValues(requiredValues);
1248
+ if (cleanedValues.length > 0) {
1249
+ const impact = compound.controlsJsxRendering ? 'high' : 'medium';
1250
+ // Generate a combined ID from all paths + values
1251
+ const pathParts = cleanedValues
1252
+ .map((rv) => {
1253
+ const name = generateNameFromPath(rv.attributePath);
1254
+ const suffix = rv.comparison === 'truthy' || rv.comparison === 'falsy'
1255
+ ? `-${rv.comparison}`
1256
+ : `-${rv.comparison}-${rv.value}`;
1257
+ return name.toLowerCase().replace(/\s+/g, '-') + suffix;
1258
+ })
1259
+ .join('-and-');
1260
+ const compoundFlow = {
1261
+ id: `${pathParts}`,
1262
+ name: generateNameFromPath(cleanedValues[0].attributePath),
1263
+ description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
1264
+ impact,
1265
+ requiredValues: cleanedValues,
1266
+ sourceLocation: compound.sourceLocation,
1267
+ };
1268
+ if (!seenFlowIds.has(compoundFlow.id)) {
1269
+ seenFlowIds.add(compoundFlow.id);
1270
+ flows.push(compoundFlow);
1271
+ }
1272
+ }
1273
+ }
1274
+ else {
1275
+ // No derived variables - use the original generateFlowFromCompound
1276
+ // Create a modified compound with just this condition set
1277
+ const modifiedCompound = {
1278
+ ...compound,
1279
+ conditions: conditionSet,
1280
+ };
1281
+ const compoundFlow = generateFlowFromCompound(modifiedCompound, resolvedPaths);
1282
+ if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
1283
+ seenFlowIds.add(compoundFlow.id);
1284
+ flows.push(compoundFlow);
1285
+ }
1286
+ }
521
1287
  }
522
1288
  }
523
1289
  }
@@ -541,7 +1307,17 @@ export default function generateExecutionFlowsFromConditionals(args) {
541
1307
  const [, varName, operator, comparedValue] = comparisonMatch;
542
1308
  // Try to resolve the variable name
543
1309
  const varResolution = resolvePathToControllable(varName, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1310
+ // Only use controllable paths for gating conditions (whitelist approach).
1311
+ // Do NOT fall back to equivalentSignatureVariables because those may contain
1312
+ // uncontrollable paths like useState that cannot be mocked.
1313
+ let resolvedVarPath = null;
544
1314
  if (varResolution.isControllable && varResolution.resolvedPath) {
1315
+ resolvedVarPath = varResolution.resolvedPath;
1316
+ }
1317
+ // Note: We intentionally do NOT fall back to equivalentSignatureVariables here
1318
+ // because that would allow uncontrollable paths (like useState) to be added
1319
+ // as gating conditions.
1320
+ if (resolvedVarPath) {
545
1321
  const isNegated = gatingCondition.isNegated === true;
546
1322
  const isNotEquals = operator === '!=' || operator === '!==';
547
1323
  // Determine the effective value for this gating condition
@@ -551,7 +1327,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
551
1327
  // XOR logic: isNegated XOR isNotEquals
552
1328
  const needsExactValue = isNegated !== isNotEquals;
553
1329
  gatingRequiredValues.push({
554
- attributePath: varResolution.resolvedPath,
1330
+ attributePath: resolvedVarPath,
555
1331
  value: needsExactValue ? 'falsy' : comparedValue,
556
1332
  comparison: needsExactValue ? 'falsy' : 'equals',
557
1333
  });
@@ -604,7 +1380,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
604
1380
  // For non-negated &&: all parts must be truthy
605
1381
  // For negated ||: all parts must be falsy (DeMorgan: !(A || B) = !A && !B)
606
1382
  gatingRequiredValues.push({
607
- attributePath: partResolution.resolvedPath,
1383
+ attributePath: stripLengthSuffix(partResolution.resolvedPath),
608
1384
  value: isNegated ? 'falsy' : 'truthy',
609
1385
  comparison: isNegated ? 'falsy' : 'truthy',
610
1386
  });
@@ -616,14 +1392,24 @@ export default function generateExecutionFlowsFromConditionals(args) {
616
1392
  // Simple gating condition (single path)
617
1393
  // Resolve the gating path in parent context
618
1394
  const gatingResolution = resolvePathToControllable(gatingPath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1395
+ // Only use controllable paths for gating conditions (whitelist approach).
1396
+ // Do NOT fall back to equivalentSignatureVariables because those may contain
1397
+ // uncontrollable paths like useState that cannot be mocked.
1398
+ let resolvedGatingPath = null;
619
1399
  if (gatingResolution.isControllable &&
620
1400
  gatingResolution.resolvedPath) {
1401
+ resolvedGatingPath = gatingResolution.resolvedPath;
1402
+ }
1403
+ // Note: We intentionally do NOT fall back to equivalentSignatureVariables here
1404
+ // because that would allow uncontrollable paths (like useState) to be added
1405
+ // as gating conditions.
1406
+ if (resolvedGatingPath) {
621
1407
  // For truthiness conditions on gating, check if the condition is negated
622
1408
  // e.g., ternary else branch: isError ? <ErrorView /> : <SuccessView />
623
1409
  // SuccessView has isNegated: true, meaning it renders when isError is falsy
624
1410
  const isNegated = gatingCondition.isNegated === true;
625
1411
  gatingRequiredValues.push({
626
- attributePath: gatingResolution.resolvedPath,
1412
+ attributePath: resolvedGatingPath,
627
1413
  value: isNegated ? 'falsy' : 'truthy',
628
1414
  comparison: isNegated ? 'falsy' : 'truthy',
629
1415
  });
@@ -662,12 +1448,97 @@ export default function generateExecutionFlowsFromConditionals(args) {
662
1448
  continue;
663
1449
  }
664
1450
  // Now resolve the translated path in the parent context
1451
+ // First, try standard resolution
665
1452
  const resolution = resolvePathToControllable(translatedPath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
666
- if (!resolution.isControllable || !resolution.resolvedPath) {
667
- // Path is not controllable in parent context
668
- continue;
1453
+ // Only create flows for controllable paths (whitelist approach).
1454
+ // If the path doesn't resolve to something in attributesMap, skip it.
1455
+ // This prevents creating flows for useState values which are not
1456
+ // controllable via mock data injection.
1457
+ let resolvedPath = resolution.resolvedPath;
1458
+ if (!resolution.isControllable || !resolvedPath) {
1459
+ // Path is not controllable via standard resolution.
1460
+ // Try fallback: For useState values (cyScope*().functionCallReturnValue),
1461
+ // look for a related URL parameter like "varNameFromUrl" that might
1462
+ // control the initial state.
1463
+ //
1464
+ // Example: viewMode → cyScope20().functionCallReturnValue (useState value)
1465
+ // Fallback: viewModeFromUrl → segments[2] (URL param that initializes the useState)
1466
+ const useStateMatch = translatedPath.match(/^cyScope\d+\(\)\.functionCallReturnValue$/);
1467
+ if (useStateMatch) {
1468
+ // Find what variable this useState value corresponds to by looking
1469
+ // for entries like "varName": "cyScope20()" in equivalentSignatureVariables
1470
+ const useStatePattern = translatedPath.replace(/\.functionCallReturnValue$/, ''); // e.g., "cyScope20()"
1471
+ // Find the variable name that maps to this useState
1472
+ let useStateVarName = null;
1473
+ for (const [varName, varPath] of Object.entries(equivalentSignatureVariables)) {
1474
+ if (varPath === useStatePattern) {
1475
+ useStateVarName = varName;
1476
+ break;
1477
+ }
1478
+ }
1479
+ if (useStateVarName) {
1480
+ // Look for a related URL param like "varNameFromUrl"
1481
+ const urlParamName = `${useStateVarName}FromUrl`;
1482
+ const urlParamPath = equivalentSignatureVariables[urlParamName];
1483
+ if (urlParamPath) {
1484
+ // For useState values initialized from URL params, use the
1485
+ // URL param variable name directly (e.g., "viewModeFromUrl")
1486
+ // rather than fully resolving it. This keeps the path meaningful
1487
+ // for scenario generation and avoids overly generic paths like
1488
+ // "useParams().functionCallReturnValue.*".
1489
+ //
1490
+ // The flow will use the URL param name as the attributePath,
1491
+ // which gets properly resolved when generating mock data.
1492
+ resolvedPath = urlParamName;
1493
+ }
1494
+ }
1495
+ }
1496
+ // Fallback 2: Try sourceEquivalencies to find the actual data source
1497
+ // This handles the case where props flow through useState but originate
1498
+ // from a mockable data source (e.g., API call, fetcher).
1499
+ //
1500
+ // Example: WorkoutsView receives `workouts` prop which in parent is stored
1501
+ // in useState, but ultimately comes from a Supabase query.
1502
+ // sourceEquivalencies tells us: "WorkoutsView().signature[0].workouts" → "createClient()...data"
1503
+ if (!resolvedPath && sourceEquivalencies) {
1504
+ // Build the child prop path to look up in sourceEquivalencies
1505
+ // Format: "ChildName().signature[0].propName"
1506
+ // First, find what prop this child path maps to
1507
+ let childPropName = null;
1508
+ for (const [varName, varPath] of Object.entries(childData.equivalentSignatureVariables)) {
1509
+ // Check if childPath starts with this variable name
1510
+ // e.g., childPath = "workouts.length", varName = "workouts", varPath = "signature[0].workouts"
1511
+ if (childPath === varName ||
1512
+ childPath.startsWith(`${varName}.`)) {
1513
+ childPropName = varName;
1514
+ break;
1515
+ }
1516
+ }
1517
+ if (childPropName) {
1518
+ // Build the full sourceEquivalencies key
1519
+ const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
1520
+ const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
1521
+ if (sourceEquivEntry && sourceEquivEntry.length > 0) {
1522
+ const dataSourcePath = sourceEquivEntry[0].schemaPath;
1523
+ // Check if this data source path is controllable
1524
+ const dataSourceResolution = resolvePathToControllable(dataSourcePath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1525
+ if (dataSourceResolution.isControllable &&
1526
+ dataSourceResolution.resolvedPath) {
1527
+ // Preserve any suffix from the child path
1528
+ // e.g., childPath = "workouts.length" → suffix = ".length"
1529
+ const suffix = childPath.startsWith(`${childPropName}.`)
1530
+ ? childPath.slice(childPropName.length)
1531
+ : '';
1532
+ resolvedPath = dataSourceResolution.resolvedPath + suffix;
1533
+ }
1534
+ }
1535
+ }
1536
+ }
1537
+ // If still not resolved after fallback, skip
1538
+ if (!resolvedPath) {
1539
+ continue;
1540
+ }
669
1541
  }
670
- const resolvedPath = resolution.resolvedPath;
671
1542
  // Check for duplicates
672
1543
  const normalizedPath = normalizePathForDeduplication(resolvedPath, fullToShortPathMap);
673
1544
  if (seenNormalizedPaths.has(normalizedPath)) {
@@ -710,33 +1581,227 @@ export default function generateExecutionFlowsFromConditionals(args) {
710
1581
  // Process child's compound conditionals
711
1582
  for (const compound of childData.compoundConditionals) {
712
1583
  const resolvedPaths = new Map();
713
- let allControllable = true;
1584
+ let allResolvable = true;
714
1585
  for (const condition of compound.conditions) {
715
1586
  // Determine the child path to translate
716
1587
  const childPath = condition.path;
717
1588
  // Translate the child path to a parent path
718
1589
  const translatedPath = translateChildPathToParent(childPath, childData.equivalentSignatureVariables, equivalentSignatureVariables, childName);
719
1590
  if (!translatedPath) {
720
- allControllable = false;
1591
+ allResolvable = false;
721
1592
  break;
722
1593
  }
723
1594
  const resolution = resolvePathToControllable(translatedPath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
724
- if (!resolution.isControllable || !resolution.resolvedPath) {
725
- allControllable = false;
1595
+ // Only create flows for controllable paths (whitelist approach).
1596
+ // If the path doesn't resolve to something in attributesMap, skip it.
1597
+ // This prevents creating flows for useState values which are not
1598
+ // controllable via mock data injection.
1599
+ let resolvedPath = resolution.resolvedPath;
1600
+ if (!resolution.isControllable || !resolvedPath) {
1601
+ // Path is not controllable via standard resolution.
1602
+ // Try fallback: For useState values (cyScope*().functionCallReturnValue),
1603
+ // look for a related URL parameter like "varNameFromUrl" that might
1604
+ // control the initial state.
1605
+ const useStateMatch = translatedPath.match(/^cyScope\d+\(\)\.functionCallReturnValue$/);
1606
+ if (useStateMatch) {
1607
+ const useStatePattern = translatedPath.replace(/\.functionCallReturnValue$/, '');
1608
+ // Find the variable name that maps to this useState
1609
+ let useStateVarName = null;
1610
+ for (const [varName, varPath] of Object.entries(equivalentSignatureVariables)) {
1611
+ if (varPath === useStatePattern) {
1612
+ useStateVarName = varName;
1613
+ break;
1614
+ }
1615
+ }
1616
+ if (useStateVarName) {
1617
+ const urlParamName = `${useStateVarName}FromUrl`;
1618
+ const urlParamPath = equivalentSignatureVariables[urlParamName];
1619
+ if (urlParamPath) {
1620
+ resolvedPath = urlParamName;
1621
+ }
1622
+ }
1623
+ }
1624
+ }
1625
+ if (!resolvedPath) {
1626
+ allResolvable = false;
726
1627
  break;
727
1628
  }
728
- resolvedPaths.set(condition.path, resolution.resolvedPath);
1629
+ resolvedPaths.set(condition.path, resolvedPath);
729
1630
  }
730
- if (allControllable && resolvedPaths.size > 0) {
1631
+ if (allResolvable && resolvedPaths.size > 0) {
731
1632
  const compoundFlow = generateFlowFromCompound(compound, resolvedPaths);
732
- if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
733
- seenFlowIds.add(compoundFlow.id);
734
- flows.push(compoundFlow);
1633
+ if (compoundFlow) {
1634
+ // Add gating conditions to compound flow (same as regular usage flows)
1635
+ if (gatingRequiredValues.length > 0) {
1636
+ // Filter out any gating values that are already in the flow
1637
+ const existingPaths = new Set(compoundFlow.requiredValues.map((rv) => rv.attributePath));
1638
+ const newGatingValues = gatingRequiredValues.filter((gv) => !existingPaths.has(gv.attributePath));
1639
+ compoundFlow.requiredValues = [
1640
+ ...compoundFlow.requiredValues,
1641
+ ...newGatingValues,
1642
+ ];
1643
+ // Update the flow ID to include gating conditions
1644
+ if (newGatingValues.length > 0) {
1645
+ const gatingIdPart = newGatingValues
1646
+ .map((gv) => `${gv.attributePath}-${gv.value}`)
1647
+ .join('-');
1648
+ compoundFlow.id = `${compoundFlow.id}-gated-${gatingIdPart}`;
1649
+ }
1650
+ }
1651
+ if (!seenFlowIds.has(compoundFlow.id)) {
1652
+ seenFlowIds.add(compoundFlow.id);
1653
+ flows.push(compoundFlow);
1654
+ }
1655
+ }
1656
+ }
1657
+ }
1658
+ // Process child's jsxRenderingUsages (array.map flows)
1659
+ // This generates array variation flows (empty, few, many) for arrays rendered in child
1660
+ if (childData.jsxRenderingUsages) {
1661
+ for (const jsxUsage of childData.jsxRenderingUsages) {
1662
+ // Translate the child path to a parent path
1663
+ const translatedPath = translateChildPathToParent(jsxUsage.path, childData.equivalentSignatureVariables, equivalentSignatureVariables, childName);
1664
+ if (!translatedPath) {
1665
+ continue;
1666
+ }
1667
+ // Resolve to controllable path in parent context
1668
+ const resolution = resolvePathToControllable(translatedPath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1669
+ let resolvedPath = resolution.resolvedPath;
1670
+ // Try sourceEquivalencies fallback if not controllable
1671
+ if (!resolution.isControllable || !resolvedPath) {
1672
+ if (sourceEquivalencies) {
1673
+ // Build the sourceEquivalencies key
1674
+ // The child path (e.g., "workouts") maps to a prop path (e.g., "signature[0].workouts")
1675
+ let childPropName = null;
1676
+ for (const [varName, varPath] of Object.entries(childData.equivalentSignatureVariables)) {
1677
+ if (jsxUsage.path === varName ||
1678
+ jsxUsage.path.startsWith(`${varName}.`)) {
1679
+ childPropName = varName;
1680
+ break;
1681
+ }
1682
+ }
1683
+ if (childPropName) {
1684
+ const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
1685
+ const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
1686
+ if (sourceEquivEntry && sourceEquivEntry.length > 0) {
1687
+ const dataSourcePath = sourceEquivEntry[0].schemaPath;
1688
+ const dataSourceResolution = resolvePathToControllable(dataSourcePath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
1689
+ if (dataSourceResolution.isControllable &&
1690
+ dataSourceResolution.resolvedPath) {
1691
+ resolvedPath = dataSourceResolution.resolvedPath;
1692
+ }
1693
+ }
1694
+ }
1695
+ }
1696
+ }
1697
+ if (!resolvedPath) {
1698
+ continue;
1699
+ }
1700
+ // Check for duplicates
1701
+ const normalizedPath = normalizePathForDeduplication(resolvedPath, fullToShortPathMap);
1702
+ const dedupeKey = `${normalizedPath}:${jsxUsage.renderingType}`;
1703
+ if (seenNormalizedPaths.has(dedupeKey)) {
1704
+ continue;
1705
+ }
1706
+ seenNormalizedPaths.add(dedupeKey);
1707
+ // Generate array variation flows for array-map rendering
1708
+ if (jsxUsage.renderingType === 'array-map') {
1709
+ const baseName = generateNameFromPath(resolvedPath);
1710
+ const pathSlug = pathToSlug(resolvedPath);
1711
+ const exclusiveGroup = `array-length-${pathSlug}`;
1712
+ // Empty array flow
1713
+ const emptyFlow = {
1714
+ id: `${pathSlug}-empty-array`,
1715
+ name: `${baseName} Empty`,
1716
+ description: `When ${baseName.toLowerCase()} array is empty`,
1717
+ requiredValues: [
1718
+ {
1719
+ attributePath: resolvedPath,
1720
+ value: '0',
1721
+ comparison: 'length<',
1722
+ valueType: 'array',
1723
+ },
1724
+ ...gatingRequiredValues,
1725
+ ],
1726
+ impact: 'medium',
1727
+ exclusiveGroup,
1728
+ sourceLocation: jsxUsage.sourceLocation
1729
+ ? {
1730
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
1731
+ column: jsxUsage.sourceLocation.column,
1732
+ }
1733
+ : undefined,
1734
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
1735
+ };
1736
+ if (!seenFlowIds.has(emptyFlow.id)) {
1737
+ seenFlowIds.add(emptyFlow.id);
1738
+ flows.push(emptyFlow);
1739
+ }
1740
+ // Few items flow (1-3)
1741
+ const fewFlow = {
1742
+ id: `${pathSlug}-few-items`,
1743
+ name: `${baseName} Few Items`,
1744
+ description: `When ${baseName.toLowerCase()} array has 1-3 items`,
1745
+ requiredValues: [
1746
+ {
1747
+ attributePath: resolvedPath,
1748
+ value: '3',
1749
+ comparison: 'length<',
1750
+ valueType: 'array',
1751
+ },
1752
+ ...gatingRequiredValues,
1753
+ ],
1754
+ impact: 'low',
1755
+ exclusiveGroup,
1756
+ sourceLocation: jsxUsage.sourceLocation
1757
+ ? {
1758
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
1759
+ column: jsxUsage.sourceLocation.column,
1760
+ }
1761
+ : undefined,
1762
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
1763
+ };
1764
+ if (!seenFlowIds.has(fewFlow.id)) {
1765
+ seenFlowIds.add(fewFlow.id);
1766
+ flows.push(fewFlow);
1767
+ }
1768
+ // Many items flow (10+)
1769
+ const manyFlow = {
1770
+ id: `${pathSlug}-many-items`,
1771
+ name: `${baseName} Many Items`,
1772
+ description: `When ${baseName.toLowerCase()} array has many items`,
1773
+ requiredValues: [
1774
+ {
1775
+ attributePath: resolvedPath,
1776
+ value: '10',
1777
+ comparison: 'length>',
1778
+ valueType: 'array',
1779
+ },
1780
+ ...gatingRequiredValues,
1781
+ ],
1782
+ impact: 'low',
1783
+ exclusiveGroup,
1784
+ sourceLocation: jsxUsage.sourceLocation
1785
+ ? {
1786
+ lineNumber: jsxUsage.sourceLocation.lineNumber,
1787
+ column: jsxUsage.sourceLocation.column,
1788
+ }
1789
+ : undefined,
1790
+ codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
1791
+ };
1792
+ if (!seenFlowIds.has(manyFlow.id)) {
1793
+ seenFlowIds.add(manyFlow.id);
1794
+ flows.push(manyFlow);
1795
+ }
735
1796
  }
736
1797
  }
737
1798
  }
738
1799
  }
739
1800
  }
1801
+ console.log(`[genFlowsFromConditionals] RESULT: ${flows.length} total flows generated`);
1802
+ for (const flow of flows) {
1803
+ console.log(`[genFlowsFromConditionals] FLOW: id="${flow.id}" requiredValues=[${flow.requiredValues.map((rv) => `${rv.attributePath}=${rv.value}`).join(', ')}]`);
1804
+ }
740
1805
  return flows;
741
1806
  }
742
1807
  //# sourceMappingURL=generateExecutionFlowsFromConditionals.js.map