@codeyam/codeyam-cli 0.1.0-staging.09652b8 → 0.1.0-staging.28f73cf

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 (287) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +7 -6
  4. package/analyzer-template/packages/ai/index.ts +2 -0
  5. package/analyzer-template/packages/ai/package.json +2 -2
  6. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +24 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +14 -0
  8. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +1402 -546
  9. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/FunctionCallManager.ts +138 -0
  10. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +1 -1
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +139 -0
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/DebugTracer.ts +224 -0
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/PathManager.ts +203 -0
  14. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/README.md +294 -0
  15. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +161 -0
  16. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/VisitedTracker.ts +235 -0
  17. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +2 -0
  18. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/selectBestValue.ts +70 -0
  19. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/uniqueIdUtils.ts +113 -0
  20. package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +36 -0
  21. package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +32 -8
  22. package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +27 -6
  23. package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +42 -4
  24. package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +39 -0
  25. package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +18 -6
  26. package/analyzer-template/packages/analyze/src/lib/asts/nodes/index.ts +2 -1
  27. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +8 -10
  28. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +6 -1
  29. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +8 -6
  30. package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +5 -13
  31. package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +34 -15
  32. package/analyzer-template/packages/analyze/src/lib/files/analyzeEntity.ts +17 -3
  33. package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +35 -16
  34. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +7 -1
  35. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +9 -1
  36. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +6 -1
  37. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +9 -1
  38. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.d.ts +23 -0
  39. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.d.ts.map +1 -0
  40. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.js +30 -0
  41. package/analyzer-template/packages/aws/dist/src/lib/s3/getPresignedUrl.js.map +1 -0
  42. package/analyzer-template/packages/aws/package.json +5 -4
  43. package/analyzer-template/packages/aws/s3/index.ts +4 -0
  44. package/analyzer-template/packages/aws/src/lib/s3/getPresignedUrl.ts +62 -0
  45. package/analyzer-template/packages/generate/src/lib/scenarioComponent.ts +6 -3
  46. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponent.d.ts.map +1 -1
  47. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponent.js +5 -3
  48. package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponent.js.map +1 -1
  49. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/db.d.ts +2 -0
  50. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/db.d.ts.map +1 -1
  51. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/db.js +3 -0
  52. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/db.js.map +1 -1
  53. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tableRelations.d.ts +2 -0
  54. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tableRelations.d.ts.map +1 -1
  55. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tables/debugReportsTable.d.ts +37 -0
  56. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -0
  57. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tables/debugReportsTable.js +27 -0
  58. package/analyzer-template/packages/github/dist/supabase/src/lib/kysely/tables/debugReportsTable.js.map +1 -0
  59. package/analyzer-template/packages/github/dist/utils/index.d.ts +1 -0
  60. package/analyzer-template/packages/github/dist/utils/index.d.ts.map +1 -1
  61. package/analyzer-template/packages/github/dist/utils/index.js +1 -0
  62. package/analyzer-template/packages/github/dist/utils/index.js.map +1 -1
  63. package/analyzer-template/packages/github/dist/utils/src/lib/Semaphore.d.ts +25 -0
  64. package/analyzer-template/packages/github/dist/utils/src/lib/Semaphore.d.ts.map +1 -0
  65. package/analyzer-template/packages/github/dist/utils/src/lib/Semaphore.js +40 -0
  66. package/analyzer-template/packages/github/dist/utils/src/lib/Semaphore.js.map +1 -0
  67. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getRemixRoutePath.d.ts.map +1 -1
  68. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getRemixRoutePath.js +2 -1
  69. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getRemixRoutePath.js.map +1 -1
  70. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.d.ts.map +1 -1
  71. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.js +1 -0
  72. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.js.map +1 -1
  73. package/analyzer-template/packages/supabase/src/lib/kysely/db.ts +6 -0
  74. package/analyzer-template/packages/supabase/src/lib/kysely/tableRelations.ts +3 -0
  75. package/analyzer-template/packages/supabase/src/lib/kysely/tables/debugReportsTable.ts +61 -0
  76. package/analyzer-template/packages/utils/dist/utils/index.d.ts +1 -0
  77. package/analyzer-template/packages/utils/dist/utils/index.d.ts.map +1 -1
  78. package/analyzer-template/packages/utils/dist/utils/index.js +1 -0
  79. package/analyzer-template/packages/utils/dist/utils/index.js.map +1 -1
  80. package/analyzer-template/packages/utils/dist/utils/src/lib/Semaphore.d.ts +25 -0
  81. package/analyzer-template/packages/utils/dist/utils/src/lib/Semaphore.d.ts.map +1 -0
  82. package/analyzer-template/packages/utils/dist/utils/src/lib/Semaphore.js +40 -0
  83. package/analyzer-template/packages/utils/dist/utils/src/lib/Semaphore.js.map +1 -0
  84. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getRemixRoutePath.d.ts.map +1 -1
  85. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getRemixRoutePath.js +2 -1
  86. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getRemixRoutePath.js.map +1 -1
  87. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.d.ts.map +1 -1
  88. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.js +1 -0
  89. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/remixRouteFileNameToRoute.js.map +1 -1
  90. package/analyzer-template/packages/utils/index.ts +1 -0
  91. package/analyzer-template/packages/utils/src/lib/Semaphore.ts +42 -0
  92. package/analyzer-template/packages/utils/src/lib/frameworks/getRemixRoutePath.ts +2 -1
  93. package/analyzer-template/packages/utils/src/lib/frameworks/remixRouteFileNameToRoute.ts +1 -0
  94. package/analyzer-template/project/constructMockCode.ts +170 -6
  95. package/analyzer-template/project/reconcileMockDataKeys.ts +13 -0
  96. package/analyzer-template/project/start.ts +1 -11
  97. package/analyzer-template/project/writeMockDataTsx.ts +32 -1
  98. package/analyzer-template/project/writeScenarioComponents.ts +164 -18
  99. package/analyzer-template/project/writeUniversalMocks.ts +66 -8
  100. package/background/src/lib/virtualized/project/constructMockCode.js +158 -7
  101. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  102. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +12 -0
  103. package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
  104. package/background/src/lib/virtualized/project/start.js +1 -8
  105. package/background/src/lib/virtualized/project/start.js.map +1 -1
  106. package/background/src/lib/virtualized/project/writeMockDataTsx.js +25 -1
  107. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  108. package/background/src/lib/virtualized/project/writeScenarioComponents.js +129 -17
  109. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  110. package/background/src/lib/virtualized/project/writeUniversalMocks.js +56 -7
  111. package/background/src/lib/virtualized/project/writeUniversalMocks.js.map +1 -1
  112. package/codeyam-cli/src/cli.js +6 -0
  113. package/codeyam-cli/src/cli.js.map +1 -1
  114. package/codeyam-cli/src/codeyam-cli.js +0 -0
  115. package/codeyam-cli/src/commands/debug.js +221 -0
  116. package/codeyam-cli/src/commands/debug.js.map +1 -0
  117. package/codeyam-cli/src/commands/report.js +102 -0
  118. package/codeyam-cli/src/commands/report.js.map +1 -0
  119. package/codeyam-cli/src/commands/setup-sandbox.js +164 -0
  120. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -0
  121. package/codeyam-cli/src/utils/__tests__/cleanupAnalysisFiles.test.js +6 -6
  122. package/codeyam-cli/src/utils/__tests__/cleanupAnalysisFiles.test.js.map +1 -1
  123. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +8 -0
  124. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  125. package/codeyam-cli/src/utils/analyzer.js +30 -0
  126. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  127. package/codeyam-cli/src/utils/cleanupAnalysisFiles.js +2 -2
  128. package/codeyam-cli/src/utils/cleanupAnalysisFiles.js.map +1 -1
  129. package/codeyam-cli/src/utils/generateReport.js +219 -0
  130. package/codeyam-cli/src/utils/generateReport.js.map +1 -0
  131. package/codeyam-cli/src/utils/install-skills.js +7 -0
  132. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  133. package/codeyam-cli/src/utils/queue/__tests__/job.pidTracking.test.js +1 -0
  134. package/codeyam-cli/src/utils/queue/__tests__/job.pidTracking.test.js.map +1 -1
  135. package/codeyam-cli/src/utils/queue/job.js +5 -1
  136. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  137. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +4 -0
  138. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  139. package/codeyam-cli/src/webserver/app/lib/database.js +50 -2
  140. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  141. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-D5ZHFomX.js +1 -0
  142. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CDnfNKKQ.js → InteractivePreview-XDSzQLOY.js} +2 -2
  143. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-DUS-3h7I.js → LibraryFunctionPreview-BYVx9KFp.js} +1 -1
  144. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-TJzDQku1.js → LogViewer-CRcT5fOZ.js} +1 -1
  145. package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-BORLgi0X.js +1 -0
  146. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-BgdlWM6p.js → SafeScreenshot-Bual6h18.js} +1 -1
  147. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bi-YUMa-.js +6 -0
  148. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-4D2vLLJz.js +5 -0
  149. package/codeyam-cli/src/webserver/build/client/assets/_index-BC200mfN.js +1 -0
  150. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CxvZPkCv.js +10 -0
  151. package/codeyam-cli/src/webserver/build/client/assets/api.generate-report-l0sNRNKZ.js +1 -0
  152. package/codeyam-cli/src/webserver/build/client/assets/chart-column-B8fb6wnw.js +1 -0
  153. package/codeyam-cli/src/webserver/build/client/assets/{chunk-WWGJGFF6-DvL0YqDJ.js → chunk-WWGJGFF6-De6i8FUT.js} +1 -1
  154. package/codeyam-cli/src/webserver/build/client/assets/circle-alert-IdsgAK39.js +1 -0
  155. package/codeyam-cli/src/webserver/build/client/assets/circle-check-BACUUf75.js +1 -0
  156. package/codeyam-cli/src/webserver/build/client/assets/clock-vWeoCemX.js +1 -0
  157. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CS7XDrKv.js +1 -0
  158. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-DIOEw_3i.js +1 -0
  159. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-3bYjyojg.js → entity._sha._-8Els_3Wb.js} +10 -10
  160. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DtfwpN9J.js → entity._sha_.create-scenario-C3FZJx1w.js} +1 -1
  161. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-YJz_igar.js +5 -0
  162. package/codeyam-cli/src/webserver/build/client/assets/entityStatus-BEqj2qBy.js +1 -0
  163. package/codeyam-cli/src/webserver/build/client/assets/entry.client-DiP0q291.js +5 -0
  164. package/codeyam-cli/src/webserver/build/client/assets/file-text-LM0mgxXE.js +1 -0
  165. package/codeyam-cli/src/webserver/build/client/assets/files-Dxh9CcaV.js +1 -0
  166. package/codeyam-cli/src/webserver/build/client/assets/{git-WoKohOtW.js → git-BXmqrWCH.js} +10 -10
  167. package/codeyam-cli/src/webserver/build/client/assets/globals-BGS74ED-.css +1 -0
  168. package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +5 -0
  169. package/codeyam-cli/src/webserver/build/client/assets/{index-Vvbl94Xc.js → index-D-zYbzFZ.js} +2 -2
  170. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-BXPKbHEb.js +1 -0
  171. package/codeyam-cli/src/webserver/build/client/assets/manifest-1af162d4.js +1 -0
  172. package/codeyam-cli/src/webserver/build/client/assets/root-DB7VgjCY.js +16 -0
  173. package/codeyam-cli/src/webserver/build/client/assets/settings-5zF_GOcS.js +1 -0
  174. package/codeyam-cli/src/webserver/build/client/assets/{settings-LuiJ1UIm.js → settings-Dc4MlMpK.js} +1 -1
  175. package/codeyam-cli/src/webserver/build/client/assets/simulations-BQ-02-jB.js +1 -0
  176. package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-D7k-ArFa.js +1 -0
  177. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-CpUcCv1V.js → useLastLogLine-AlhS7g5F.js} +1 -1
  178. package/codeyam-cli/src/webserver/build/client/assets/useToast-Ddo4UQv7.js +1 -0
  179. package/codeyam-cli/src/webserver/build/client/assets/zap-_jw-9DCp.js +1 -0
  180. package/codeyam-cli/src/webserver/build/server/assets/{index-DzbqTxoN.js → index-D4JpXSIO.js} +1 -1
  181. package/codeyam-cli/src/webserver/build/server/assets/server-build-vwbN7n65.js +169 -0
  182. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  183. package/codeyam-cli/src/webserver/build-info.json +5 -5
  184. package/codeyam-cli/templates/codeyam-setup-skill.md +65 -85
  185. package/codeyam-cli/templates/debug-command.md +125 -0
  186. package/package.json +4 -6
  187. package/packages/ai/index.js +1 -1
  188. package/packages/ai/index.js.map +1 -1
  189. package/packages/ai/src/lib/analyzeScope.js +13 -0
  190. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  191. package/packages/ai/src/lib/astScopes/processExpression.js +12 -0
  192. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  193. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +1023 -405
  194. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  195. package/packages/ai/src/lib/dataStructure/equivalencyManagers/FunctionCallManager.js +137 -1
  196. package/packages/ai/src/lib/dataStructure/equivalencyManagers/FunctionCallManager.js.map +1 -1
  197. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +1 -1
  198. package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
  199. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +112 -0
  200. package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -0
  201. package/packages/ai/src/lib/dataStructure/helpers/DebugTracer.js +176 -0
  202. package/packages/ai/src/lib/dataStructure/helpers/DebugTracer.js.map +1 -0
  203. package/packages/ai/src/lib/dataStructure/helpers/PathManager.js +178 -0
  204. package/packages/ai/src/lib/dataStructure/helpers/PathManager.js.map +1 -0
  205. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +138 -0
  206. package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -0
  207. package/packages/ai/src/lib/dataStructure/helpers/VisitedTracker.js +199 -0
  208. package/packages/ai/src/lib/dataStructure/helpers/VisitedTracker.js.map +1 -0
  209. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +2 -0
  210. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  211. package/packages/ai/src/lib/dataStructure/helpers/selectBestValue.js +62 -0
  212. package/packages/ai/src/lib/dataStructure/helpers/selectBestValue.js.map +1 -0
  213. package/packages/ai/src/lib/dataStructure/helpers/uniqueIdUtils.js +90 -0
  214. package/packages/ai/src/lib/dataStructure/helpers/uniqueIdUtils.js.map +1 -0
  215. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +22 -0
  216. package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +1 -1
  217. package/packages/ai/src/lib/generateEntityKeyAttributes.js +32 -8
  218. package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +1 -1
  219. package/packages/ai/src/lib/getConditionalUsagesFromCode.js +13 -8
  220. package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
  221. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +36 -3
  222. package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
  223. package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
  224. package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
  225. package/packages/analyze/src/lib/FileAnalyzer.js +17 -5
  226. package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
  227. package/packages/analyze/src/lib/asts/nodes/index.js +2 -1
  228. package/packages/analyze/src/lib/asts/nodes/index.js.map +1 -1
  229. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +6 -8
  230. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  231. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +5 -1
  232. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  233. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +8 -2
  234. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  235. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +5 -8
  236. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
  237. package/packages/analyze/src/lib/files/analyzeChange.js +21 -9
  238. package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
  239. package/packages/analyze/src/lib/files/analyzeEntity.js +10 -4
  240. package/packages/analyze/src/lib/files/analyzeEntity.js.map +1 -1
  241. package/packages/analyze/src/lib/files/analyzeInitial.js +21 -9
  242. package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
  243. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +6 -1
  244. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  245. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +9 -1
  246. package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +1 -1
  247. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +5 -1
  248. package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
  249. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +9 -1
  250. package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
  251. package/packages/generate/src/lib/scenarioComponent.js +5 -3
  252. package/packages/generate/src/lib/scenarioComponent.js.map +1 -1
  253. package/packages/supabase/src/lib/kysely/db.js +3 -0
  254. package/packages/supabase/src/lib/kysely/db.js.map +1 -1
  255. package/packages/supabase/src/lib/kysely/tables/debugReportsTable.js +27 -0
  256. package/packages/supabase/src/lib/kysely/tables/debugReportsTable.js.map +1 -0
  257. package/packages/utils/index.js +1 -0
  258. package/packages/utils/index.js.map +1 -1
  259. package/packages/utils/src/lib/Semaphore.js +40 -0
  260. package/packages/utils/src/lib/Semaphore.js.map +1 -0
  261. package/packages/utils/src/lib/frameworks/getRemixRoutePath.js +2 -1
  262. package/packages/utils/src/lib/frameworks/getRemixRoutePath.js.map +1 -1
  263. package/packages/utils/src/lib/frameworks/remixRouteFileNameToRoute.js +1 -0
  264. package/packages/utils/src/lib/frameworks/remixRouteFileNameToRoute.js.map +1 -1
  265. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-B9Sf8e9w.js +0 -1
  266. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bl6GY-OE.js +0 -6
  267. package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-BDq8RX50.js +0 -5
  268. package/codeyam-cli/src/webserver/build/client/assets/_index-Bh3y3Wsl.js +0 -1
  269. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-tq7Bl6-t.js +0 -10
  270. package/codeyam-cli/src/webserver/build/client/assets/chart-column-q9_nHfwv.js +0 -1
  271. package/codeyam-cli/src/webserver/build/client/assets/circle-alert-CKMpA1v_.js +0 -1
  272. package/codeyam-cli/src/webserver/build/client/assets/clock-Wnfog8Qw.js +0 -1
  273. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-C_ixaqqh.js +0 -1
  274. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-QecTs_sq.js +0 -5
  275. package/codeyam-cli/src/webserver/build/client/assets/entry.client-hnkEgHrC.js +0 -5
  276. package/codeyam-cli/src/webserver/build/client/assets/file-text-CvCVdKLW.js +0 -1
  277. package/codeyam-cli/src/webserver/build/client/assets/files-DgUCYhbd.js +0 -1
  278. package/codeyam-cli/src/webserver/build/client/assets/globals-DZfbt0u5.css +0 -1
  279. package/codeyam-cli/src/webserver/build/client/assets/loader-circle-Bxm63UxG.js +0 -1
  280. package/codeyam-cli/src/webserver/build/client/assets/manifest-c90b8608.js +0 -1
  281. package/codeyam-cli/src/webserver/build/client/assets/root-DrVZQamX.js +0 -16
  282. package/codeyam-cli/src/webserver/build/client/assets/search-CJkk16Ct.js +0 -1
  283. package/codeyam-cli/src/webserver/build/client/assets/settings-ConzHeiL.js +0 -1
  284. package/codeyam-cli/src/webserver/build/client/assets/simulations-B9LRwAej.js +0 -1
  285. package/codeyam-cli/src/webserver/build/client/assets/useToast-DOxmMaSg.js +0 -1
  286. package/codeyam-cli/src/webserver/build/client/assets/zap-D5R1FAcH.js +0 -1
  287. package/codeyam-cli/src/webserver/build/server/assets/server-build-DGGis3OZ.js +0 -166
@@ -0,0 +1,235 @@
1
+ /**
2
+ * VisitedTracker
3
+ *
4
+ * Manages visited state tracking for the ScopeDataStructure analysis.
5
+ * Prevents infinite loops and redundant processing by tracking which
6
+ * scope/path/value combinations have already been processed.
7
+ *
8
+ * ## Why This Exists
9
+ *
10
+ * The schema building process recursively follows equivalencies between
11
+ * data paths. Without cycle detection, circular references like:
12
+ * `user.profile` → `currentUser` → `user.profile`
13
+ * would cause infinite loops.
14
+ *
15
+ * ## Two Tracking Modes
16
+ *
17
+ * ### 1. Global Visited (scope::path::value)
18
+ * Fine-grained deduplication for `addToSchema()`. Tracks the complete
19
+ * tuple so the same path can be visited with different type values.
20
+ *
21
+ * Example: `myFunc::user.id::string` and `myFunc::user.id::number`
22
+ * are tracked separately, allowing both types to be recorded.
23
+ *
24
+ * ### 2. Complex Source Visited (scope::path)
25
+ * Coarser deduplication for `addComplexSourcePathVariables()`. Ignores
26
+ * the type value because complex source processing should happen once
27
+ * per path regardless of type.
28
+ *
29
+ * ## Lifecycle
30
+ *
31
+ * - Global visited is **reset** at the start of `captureCompleteSchema()`
32
+ * to allow re-processing in the schema building phase.
33
+ * - Complex source visited is **never reset** during normal operation.
34
+ *
35
+ * ## Related Modules
36
+ *
37
+ * - `ScopeDataStructure.addToSchema()` - Primary consumer of global visited
38
+ * - `ScopeDataStructure.addComplexSourcePathVariables()` - Uses complex source visited
39
+ */
40
+
41
+ /**
42
+ * Tracks visited state to prevent infinite loops during schema building.
43
+ */
44
+ export class VisitedTracker {
45
+ /**
46
+ * Fine-grained visited tracking using scope::path::value.
47
+ * Used by addToSchema to skip already-processed combinations.
48
+ */
49
+ private globalVisited: Set<string> = new Set();
50
+
51
+ /**
52
+ * Coarser visited tracking using scope::path only (without value).
53
+ * Used by addComplexSourcePathVariables to allow each unique
54
+ * scope+path combo to be processed once, regardless of value.
55
+ */
56
+ private complexSourceVisited: Set<string> = new Set();
57
+
58
+ /**
59
+ * Creates a unique key for global visited tracking.
60
+ * @param scopeNodeName - Name of the scope
61
+ * @param path - Schema path
62
+ * @param value - Type value
63
+ */
64
+ private makeGlobalKey(
65
+ scopeNodeName: string,
66
+ path: string,
67
+ value: string,
68
+ ): string {
69
+ return `${scopeNodeName}::${path}::${value}`;
70
+ }
71
+
72
+ /**
73
+ * Creates a unique key for complex source visited tracking.
74
+ * @param scopeNodeName - Name of the scope
75
+ * @param path - Schema path
76
+ */
77
+ private makeComplexKey(scopeNodeName: string, path: string): string {
78
+ return `${scopeNodeName}::${path}`;
79
+ }
80
+
81
+ /**
82
+ * Checks if a scope/path/value combination has been globally visited.
83
+ * Does NOT mark it as visited - use markGlobalVisited for that.
84
+ *
85
+ * @returns true if already visited
86
+ */
87
+ hasGlobalVisited(
88
+ scopeNodeName: string,
89
+ path: string,
90
+ value: string,
91
+ ): boolean {
92
+ return this.globalVisited.has(
93
+ this.makeGlobalKey(scopeNodeName, path, value),
94
+ );
95
+ }
96
+
97
+ /**
98
+ * Marks a scope/path/value combination as globally visited.
99
+ */
100
+ markGlobalVisited(scopeNodeName: string, path: string, value: string): void {
101
+ this.globalVisited.add(this.makeGlobalKey(scopeNodeName, path, value));
102
+ }
103
+
104
+ /**
105
+ * Checks and marks a scope/path/value combination as globally visited.
106
+ * This is a convenience method that combines check and mark.
107
+ *
108
+ * @returns true if was already visited (should skip processing)
109
+ */
110
+ checkAndMarkGlobalVisited(
111
+ scopeNodeName: string,
112
+ path: string,
113
+ value: string,
114
+ ): boolean {
115
+ const key = this.makeGlobalKey(scopeNodeName, path, value);
116
+ if (this.globalVisited.has(key)) {
117
+ return true; // Already visited
118
+ }
119
+ this.globalVisited.add(key);
120
+ return false; // Not visited, now marked
121
+ }
122
+
123
+ /**
124
+ * Checks if a scope/path combination has been visited for complex sources.
125
+ * Does NOT mark it as visited - use markComplexSourceVisited for that.
126
+ *
127
+ * @returns true if already visited
128
+ */
129
+ hasComplexSourceVisited(scopeNodeName: string, path: string): boolean {
130
+ return this.complexSourceVisited.has(
131
+ this.makeComplexKey(scopeNodeName, path),
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Marks a scope/path combination as visited for complex sources.
137
+ */
138
+ markComplexSourceVisited(scopeNodeName: string, path: string): void {
139
+ this.complexSourceVisited.add(this.makeComplexKey(scopeNodeName, path));
140
+ }
141
+
142
+ /**
143
+ * Checks and marks a scope/path combination as visited for complex sources.
144
+ * This is a convenience method that combines check and mark.
145
+ *
146
+ * @returns true if was already visited (should skip processing)
147
+ */
148
+ checkAndMarkComplexSourceVisited(
149
+ scopeNodeName: string,
150
+ path: string,
151
+ ): boolean {
152
+ const key = this.makeComplexKey(scopeNodeName, path);
153
+ if (this.complexSourceVisited.has(key)) {
154
+ return true; // Already visited
155
+ }
156
+ this.complexSourceVisited.add(key);
157
+ return false; // Not visited, now marked
158
+ }
159
+
160
+ /**
161
+ * Resets the global visited set.
162
+ * Called at the start of captureCompleteSchema() to allow
163
+ * re-processing in the second phase.
164
+ */
165
+ resetGlobalVisited(): void {
166
+ this.globalVisited.clear();
167
+ }
168
+
169
+ /**
170
+ * Resets the complex source visited set.
171
+ * Note: In the original code, this was never reset.
172
+ */
173
+ resetComplexSourceVisited(): void {
174
+ this.complexSourceVisited.clear();
175
+ }
176
+
177
+ /**
178
+ * Resets all visited tracking.
179
+ */
180
+ resetAll(): void {
181
+ this.globalVisited.clear();
182
+ this.complexSourceVisited.clear();
183
+ }
184
+
185
+ /**
186
+ * Returns statistics about the visited sets for debugging/monitoring.
187
+ */
188
+ getStats(): { globalVisited: number; complexSourceVisited: number } {
189
+ return {
190
+ globalVisited: this.globalVisited.size,
191
+ complexSourceVisited: this.complexSourceVisited.size,
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Checks if ANY variant of a scope/path was ever visited (ignores value).
197
+ * Useful for debugging to see if a path was processed at all.
198
+ *
199
+ * @returns true if any variant of this scope/path was visited
200
+ */
201
+ wasVisited(scopeNodeName: string, path: string): boolean {
202
+ const prefix = `${scopeNodeName}::${path}::`;
203
+ for (const key of this.globalVisited) {
204
+ if (key.startsWith(prefix)) {
205
+ return true;
206
+ }
207
+ }
208
+ return this.hasComplexSourceVisited(scopeNodeName, path);
209
+ }
210
+
211
+ /**
212
+ * Gets all visited entries for a scope (for debugging).
213
+ * Returns an array of {path, value} objects.
214
+ */
215
+ getVisitedForScope(
216
+ scopeNodeName: string,
217
+ ): Array<{ path: string; value: string }> {
218
+ const prefix = `${scopeNodeName}::`;
219
+ const results: Array<{ path: string; value: string }> = [];
220
+
221
+ for (const key of this.globalVisited) {
222
+ if (key.startsWith(prefix)) {
223
+ const parts = key.slice(prefix.length).split('::');
224
+ if (parts.length >= 2) {
225
+ results.push({
226
+ path: parts.slice(0, -1).join('::'), // Everything except last part
227
+ value: parts[parts.length - 1], // Last part is value
228
+ });
229
+ }
230
+ }
231
+ }
232
+
233
+ return results;
234
+ }
235
+ }
@@ -355,9 +355,11 @@ export function fillInDirectSchemaGapsAndUnknowns({
355
355
 
356
356
  // Don't set to 'function' if this is a promise method on an async function
357
357
  // (we want the awaited value, not the promise)
358
+ // Also don't overwrite 'array' - the function might return an array (e.g., getAll())
358
359
  if (
359
360
  schema[functionReturnValuePath] &&
360
361
  schema[functionReturnValuePath] !== 'function' &&
362
+ schema[functionReturnValuePath] !== 'array' &&
361
363
  !(isPromiseMethod && isPreviousAsync)
362
364
  ) {
363
365
  schema[functionReturnValuePath] = 'function';
@@ -0,0 +1,70 @@
1
+ /**
2
+ * selectBestValue
3
+ *
4
+ * Selects the most specific type value from two candidates.
5
+ * Prefers more specific types over 'unknown' values.
6
+ *
7
+ * ## Context
8
+ *
9
+ * During schema building, the same path may have type information from
10
+ * multiple sources (e.g., from a return statement and from a function call).
11
+ * When merging these, we want to keep the most specific type.
12
+ *
13
+ * "Specific" means:
14
+ * - `'string'` is more specific than `'unknown'`
15
+ * - `'string'` is more specific than `'unknown|string'`
16
+ * - `'string|number'` is equal specificity to `'number|string'`
17
+ *
18
+ * ## Selection Rules
19
+ *
20
+ * 1. If value1 exists and is not 'unknown', use value1
21
+ * 2. If value2 exists and is more specific (not 'unknown'), prefer value2
22
+ * 3. Otherwise use the first available value, or 'unknown' as default
23
+ *
24
+ * ## Where Used
25
+ *
26
+ * - `propagateSourceAndUsageEquivalencies.equateSchema()` - Merging schemas
27
+ * - `getReturnValue()` - Combining return type information
28
+ *
29
+ * ## Related Modules
30
+ *
31
+ * - `ensureSchemaConsistency.ts` - Also deals with type merging
32
+ * - `fillInSchemaGapsAndUnknowns.ts` - Fills in missing types after schema building
33
+ */
34
+
35
+ /**
36
+ * Selects the best (most specific) value between two type candidates.
37
+ *
38
+ * @param value1 - Primary value (preferred if specific)
39
+ * @param value2 - Secondary value (used if value1 is 'unknown')
40
+ * @param defaultValue - Default when both are undefined (defaults to 'unknown')
41
+ * @returns The most specific type value
42
+ *
43
+ * @example
44
+ * selectBestValue('string', 'number') // 'string' - value1 is specific
45
+ * selectBestValue('unknown', 'string') // 'string' - value2 is more specific
46
+ * selectBestValue(undefined, 'number') // 'number' - value1 undefined
47
+ * selectBestValue(undefined, undefined) // 'unknown' - default
48
+ * selectBestValue('unknown|string', 'string') // 'string' - value2 has no unknown
49
+ */
50
+ export default function selectBestValue(
51
+ value1: string | undefined,
52
+ value2: string | undefined,
53
+ defaultValue = 'unknown',
54
+ ): string {
55
+ let bestValue = value1 ?? value2 ?? defaultValue;
56
+
57
+ // Prefer value2 if:
58
+ // - value2 exists AND
59
+ // - bestValue is 'unknown' and value2 is not, OR
60
+ // - bestValue contains 'unknown' and value2 doesn't
61
+ if (
62
+ value2 &&
63
+ ((bestValue === 'unknown' && value2 !== 'unknown') ||
64
+ (bestValue.includes('unknown') && !value2.includes('unknown')))
65
+ ) {
66
+ bestValue = value2;
67
+ }
68
+
69
+ return bestValue;
70
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * UniqueIdUtils
3
+ *
4
+ * Utility functions for creating unique identifiers and deduplicating
5
+ * scope variables in the ScopeDataStructure analysis.
6
+ *
7
+ * ## Why Unique IDs Matter
8
+ *
9
+ * The analysis tracks data flow across many scopes and paths. When building
10
+ * equivalency chains or schemas, we need to:
11
+ * - Detect cycles (have we seen this scope+path+value before?)
12
+ * - Deduplicate results (don't report the same equivalency twice)
13
+ * - Index efficiently (O(1) lookups in large datasets)
14
+ *
15
+ * ## Key Format
16
+ *
17
+ * The unique ID format is `scopeNodeName::schemaPath[::value]`:
18
+ * - `myFunc::user.id` - Scope+path without type value
19
+ * - `myFunc::user.id::string` - Full tuple including type
20
+ *
21
+ * The `::` delimiter is chosen because:
22
+ * - Scope names never contain `::`
23
+ * - Schema paths use `.` and `[]` but not `::`
24
+ * - Type values may contain `:` (e.g., `union::type`) but only as the last part
25
+ *
26
+ * ## Performance
27
+ *
28
+ * `uniqueScopeAndPaths` uses O(n) Set-based deduplication instead of O(n²)
29
+ * array comparisons. This matters when processing thousands of equivalencies.
30
+ *
31
+ * ## Related Modules
32
+ *
33
+ * - `VisitedTracker.ts` - Uses similar key format for cycle detection
34
+ * - `ScopeDataStructure.equivalencyDatabase` - Indexed by these unique IDs
35
+ */
36
+
37
+ /**
38
+ * Interface for items that can be deduplicated by scope and path.
39
+ * Matches the ScopeVariable interface's required fields.
40
+ */
41
+ export interface ScopeAndPath {
42
+ scopeNodeName: string;
43
+ schemaPath: string;
44
+ }
45
+
46
+ /**
47
+ * Creates a unique identifier string from scope, path, and optional value.
48
+ * Used for tracking visited combinations and equivalency chains.
49
+ *
50
+ * @example
51
+ * uniqueId({ scopeNodeName: 'myFunc', schemaPath: 'user.id' }) // 'myFunc::user.id'
52
+ * uniqueId({ scopeNodeName: 'myFunc', schemaPath: 'user.id', value: 'string' }) // 'myFunc::user.id::string'
53
+ */
54
+ export function uniqueId({
55
+ scopeNodeName,
56
+ schemaPath,
57
+ value,
58
+ }: {
59
+ scopeNodeName: string;
60
+ schemaPath: string;
61
+ value?: string;
62
+ }): string {
63
+ const parts = [scopeNodeName, schemaPath, value].filter(Boolean);
64
+ return parts.join('::');
65
+ }
66
+
67
+ /**
68
+ * Removes duplicate scope variables from an array, keeping only the first occurrence
69
+ * of each unique scopeNodeName + schemaPath combination.
70
+ *
71
+ * This is a type-preserving version of uniqueScopeAndPaths that returns the full
72
+ * ScopeVariable objects (with id and equivalencyReason).
73
+ *
74
+ * @param scopeVariables - Array of scope variables to deduplicate
75
+ * @returns Deduplicated array preserving original type
76
+ */
77
+ export function uniqueScopeVariables<T extends ScopeAndPath>(
78
+ scopeVariables: T[],
79
+ ): T[] {
80
+ return uniqueScopeAndPaths(scopeVariables);
81
+ }
82
+
83
+ /**
84
+ * Removes duplicates from an array of objects with scopeNodeName and schemaPath.
85
+ * Uses O(n) Set-based deduplication for performance.
86
+ *
87
+ * @param scopeVariables - Array of objects to deduplicate
88
+ * @returns Deduplicated array preserving original type
89
+ *
90
+ * @example
91
+ * uniqueScopeAndPaths([
92
+ * { scopeNodeName: 'a', schemaPath: 'x' },
93
+ * { scopeNodeName: 'a', schemaPath: 'x' },
94
+ * { scopeNodeName: 'b', schemaPath: 'y' },
95
+ * ])
96
+ * // Returns: [{ scopeNodeName: 'a', schemaPath: 'x' }, { scopeNodeName: 'b', schemaPath: 'y' }]
97
+ */
98
+ export function uniqueScopeAndPaths<T extends ScopeAndPath>(
99
+ scopeVariables: T[] | undefined | null,
100
+ ): T[] {
101
+ if (!scopeVariables || scopeVariables.length === 0) return [];
102
+
103
+ // Optimize from O(n²) to O(n) using Set for deduplication
104
+ const seen = new Set<string>();
105
+ return scopeVariables.filter((varItem) => {
106
+ const key = `${varItem.scopeNodeName}::${varItem.schemaPath}`;
107
+ if (seen.has(key)) {
108
+ return false;
109
+ }
110
+ seen.add(key);
111
+ return true;
112
+ });
113
+ }
@@ -70,6 +70,42 @@ export default function gatherRelevantDependentKeyAttributes(
70
70
  const signatureSchema = dependencySchema?.signatureSchema;
71
71
  if (!signatureSchema) return;
72
72
 
73
+ const sourceEquivalencies = dependencySchema?.sourceEquivalencies ?? {};
74
+
75
+ // If sourceEquivalencies is empty but the child has mocked imports,
76
+ // propagate key attributes directly since they affect the parent's visual output
77
+ if (Object.keys(sourceEquivalencies).length === 0) {
78
+ // Check both importedExports and nodeModuleImports for mocked imports
79
+ const importedExports =
80
+ dependentAnalysis.entity?.metadata?.importedExports ?? [];
81
+ const nodeModuleImports =
82
+ dependentAnalysis.entity?.metadata?.nodeModuleImports ?? {};
83
+
84
+ const hasMockedImportedExports = importedExports.some(
85
+ (imp: { isMocked?: boolean }) => imp.isMocked,
86
+ );
87
+ const hasMockedNodeModuleImports = Object.values(
88
+ nodeModuleImports,
89
+ ).some((imports: any[]) =>
90
+ imports?.some((imp: { isMocked?: boolean }) => imp.isMocked),
91
+ );
92
+
93
+ const childHasMockedImports =
94
+ hasMockedImportedExports || hasMockedNodeModuleImports;
95
+
96
+ if (childHasMockedImports) {
97
+ for (const dependentKeyAttribute of dependentKeyAtttributes) {
98
+ relevantDependentKeyAttributes.push({
99
+ ...dependentKeyAttribute,
100
+ dependentEntityName: entityName,
101
+ originalEntityName: entityName,
102
+ filePath: path,
103
+ } as any);
104
+ }
105
+ }
106
+ return;
107
+ }
108
+
73
109
  for (const dependentKeyAttribute of dependentKeyAtttributes) {
74
110
  const dependentKeyAttributeExternalPathParts =
75
111
  splitOutsideParenthesesAndArrays(dependentKeyAttribute.externalPath);
@@ -57,8 +57,8 @@ export default async function generateEntityKeyAttributes({
57
57
  staticAnalysisContext,
58
58
  });
59
59
 
60
- console.info('Generated prompt for generateEntityKeyAttributes:');
61
- console.info(prompt);
60
+ console.log('Generated prompt for generateEntityKeyAttributes:');
61
+ console.log(prompt);
62
62
 
63
63
  const response = await completionCall({
64
64
  type: `generateEntityKeyAttributes`,
@@ -167,15 +167,26 @@ NOT key attributes:
167
167
  - Values that would cause errors if changed
168
168
  - Guard clauses that render literally nothing
169
169
 
170
- Note: A conditional that shows a different UI state (e.g., loading screen, redirect message) IS significant—include it.
170
+ ## Conditional Key Attributes
171
+
172
+ We've provided a list of variables that are used in conditional statements in the code. These are very likely key attributes.
173
+
174
+ Each conditional lists it's source and how it is used. This should help you identify which attributes to include and what values to suggest.
171
175
 
172
176
  ## Path Format
173
177
 
174
- Only return attributes from the "Attributes and Value Types" list—these are the only values we can control. Use the exact \`fullPath\` provided. Use \`functionCallReturnValue\` for function return values. Use \`[]\` for array items (e.g., \`items[]\`).
178
+ Only return attributes from the "Attributes and Value Types" list these are the only values we can control. Use the exact \`fullPath\` provided. Use \`functionCallReturnValue\` for function return values. Use \`[]\` for array items (e.g., \`items[]\`).
179
+
180
+ ## Valid Value Options
181
+
182
+ - For \`validValueOptions\`, include boundary/extreme values that trigger different behavior
183
+ - Be very specific with values. Do not make them ambiguous in any way
184
+ — Do NOT include values that would cause unexpected/unhandled errors.
185
+ - Ensure all values or value ranges that will trigger different rendering behavior are included
175
186
 
176
187
  ## Response Format
177
188
 
178
- For \`validValueOptions\`, include boundary/extreme values that trigger different behavior—but NOT values that would cause errors.
189
+ List all key attributes in order from most impactful to least impactful regarding how dramatically they will change the rendering of the component using the following format:
179
190
 
180
191
  \`\`\`json
181
192
  {
@@ -183,7 +194,7 @@ For \`validValueOptions\`, include boundary/extreme values that trigger differen
183
194
  {
184
195
  "fullPath": "signature[0].user",
185
196
  "description": "Controls whether the main form or redirect screen displays",
186
- "validValueOptions": ["truthy user object", "null/undefined"]
197
+ "validValueOptions": ["an empty object {}", "null/undefined"]
187
198
  }
188
199
  ]
189
200
  }
@@ -205,13 +216,26 @@ NOT key attributes:
205
216
  - Values that would cause errors if changed
206
217
  - Guard clauses that return nothing/minimal data
207
218
 
219
+ ## Conditional Key Attributes
220
+
221
+ We've provided a list of variables that are used in conditional statements in the code. These are very likely key attributes.
222
+
223
+ Each conditional lists it's source and how it is used. This should help you identify which attributes to include and what values to suggest.
224
+
208
225
  ## Path Format
209
226
 
210
- Only return attributes from the "Attributes and Value Types" list—these are the only values we can control. Use the exact \`fullPath\` provided. Use \`functionCallReturnValue\` for function return values. Use \`[]\` for array items (e.g., \`items[]\`).
227
+ Only return attributes from the "Attributes and Value Types" list these are the only values we can control. Use the exact \`fullPath\` provided. Use \`functionCallReturnValue\` for function return values. Use \`[]\` for array items (e.g., \`items[]\`).
228
+
229
+ ## Valid Value Options
230
+
231
+ - For \`validValueOptions\`, include boundary/extreme values that trigger different behavior
232
+ - Be very specific with values. Do not make them ambiguous in any way
233
+ — Do NOT include values that would cause unexpected/unhandled errors.
234
+ - Ensure all values or value ranges that will trigger different rendering behavior are included
211
235
 
212
236
  ## Response Format
213
237
 
214
- For \`validValueOptions\`, include boundary/extreme values that trigger different behavior—but NOT values that would cause errors.
238
+ List all key attributes in order from most impactful to least impactful using the following format:
215
239
 
216
240
  \`\`\`json
217
241
  {
@@ -259,8 +259,16 @@ function getLiteralValue(expr: ts.Expression): string | undefined {
259
259
  /**
260
260
  * Format conditional usages into a string for the LLM prompt
261
261
  */
262
+ /**
263
+ * Interface for conditional usages that may have source tracing information.
264
+ * This is a superset of ConditionalUsage that includes optional sourceDataPath.
265
+ */
266
+ interface EnrichedConditionalUsageInput extends ConditionalUsage {
267
+ sourceDataPath?: string;
268
+ }
269
+
262
270
  export function formatConditionalUsagesForPrompt(
263
- conditionalUsages: Record<string, ConditionalUsage[]>,
271
+ conditionalUsages: Record<string, EnrichedConditionalUsageInput[]>,
264
272
  ): string {
265
273
  const entries = Object.entries(conditionalUsages);
266
274
  if (entries.length === 0) {
@@ -270,7 +278,7 @@ export function formatConditionalUsagesForPrompt(
270
278
  const lines: string[] = [
271
279
  '\n## Static Analysis: Attributes Used in Conditionals',
272
280
  '',
273
- 'The following attributes were found to be used in conditional statements, making them potential key attributes:',
281
+ 'The following attributes were found to be used in conditional statements, making them very likely key attributes:',
274
282
  '',
275
283
  ];
276
284
 
@@ -281,20 +289,30 @@ export function formatConditionalUsagesForPrompt(
281
289
  .flatMap((u) => u.comparedValues || []);
282
290
  const uniqueValues = [...new Set(allComparedValues)];
283
291
 
284
- let description = `- "${path}": `;
292
+ // Get the source data path if available (traced back to data source)
293
+ const sourceDataPath = usages.find((u) => u.sourceDataPath)?.sourceDataPath;
294
+
295
+ let description = `- "${path}"`;
296
+
297
+ // If we have a source data path, show that the local variable derives from a data source
298
+ if (sourceDataPath) {
299
+ description += `\n - Source: "${sourceDataPath}"`;
300
+ }
301
+
302
+ description += '\n - ';
285
303
 
286
304
  if (uniqueTypes.includes('switch')) {
287
- description += 'used as switch discriminant';
305
+ description += 'Used as switch discriminant';
288
306
  if (uniqueValues.length > 0) {
289
307
  description += ` with cases: ${uniqueValues.map((v) => `"${v}"`).join(', ')}`;
290
308
  }
291
309
  } else if (uniqueTypes.includes('comparison')) {
292
- description += 'used in comparison';
310
+ description += 'Used in comparison';
293
311
  if (uniqueValues.length > 0) {
294
312
  description += ` against values: ${uniqueValues.map((v) => `"${v}"`).join(', ')}`;
295
313
  }
296
314
  } else {
297
- description += 'used in truthiness check (presence/absence matters)';
315
+ description += 'Used in truthiness check (presence/absence matters)';
298
316
  }
299
317
 
300
318
  lines.push(description);
@@ -304,6 +322,9 @@ export function formatConditionalUsagesForPrompt(
304
322
  lines.push(
305
323
  'Consider these attributes as candidates for key attributes, especially those with specific comparison values.',
306
324
  );
325
+ lines.push(
326
+ 'When a local variable derives from a data source, the data source is the key attribute.',
327
+ );
307
328
 
308
329
  return lines.join('\n');
309
330
  }
@@ -5,9 +5,44 @@ import {
5
5
  splitOutsideParenthesesAndArrays,
6
6
  } from '../splitOutsideParentheses';
7
7
 
8
+ /**
9
+ * Checks if a bracket-only path is a valid string key access (not just an index).
10
+ * Valid: ['*'], ['someKey'] - string key access
11
+ * Invalid: [0], [1] - numeric index only (meaningless without parent path)
12
+ */
13
+ function isValidBracketStringKey(attribute: string): boolean {
14
+ // Match ['string'] or ["string"] patterns
15
+ return /^\[['"][^'"]+['"]\]$/.test(attribute);
16
+ }
17
+
18
+ /**
19
+ * Extracts the string key from a bracket notation like ['*'] or ["key"]
20
+ * Returns the key without quotes and brackets, e.g., '*' or 'key'
21
+ */
22
+ function extractBracketStringKey(attribute: string): string | null {
23
+ const match = attribute.match(/^\[['"]([^'"]+)['"]\]$/);
24
+ return match ? match[1] : null;
25
+ }
26
+
27
+ /**
28
+ * Normalizes a path by extracting string keys from bracket notation.
29
+ * If the path is a single bracket string key like ['*'], returns the key ('*').
30
+ * Otherwise returns the path unchanged.
31
+ */
32
+ function normalizePathForInternalUse(path: string): string {
33
+ const extracted = extractBracketStringKey(path);
34
+ return extracted !== null ? extracted : path;
35
+ }
36
+
8
37
  function validAttribute(attribute: string) {
9
- if (!attribute || attribute.length === 0 || attribute.startsWith('['))
10
- return false;
38
+ if (!attribute || attribute.length === 0) return false;
39
+
40
+ // Allow string-key bracket access like ['*'] or ['someKey']
41
+ // These are valid data paths from objects with dynamic/special keys
42
+ if (attribute.startsWith('[')) {
43
+ return isValidBracketStringKey(attribute);
44
+ }
45
+
11
46
  const attributeParts = splitOutsideParenthesesAndArrays(attribute);
12
47
  if (
13
48
  attributeParts.some((part) =>
@@ -153,8 +188,11 @@ export function gatherAttributesMap(
153
188
  // Fall through to normal processing for other return value properties
154
189
  }
155
190
 
156
- const relativePath = joinParenthesesAndArrays(pathParts.slice(2));
157
- if (!validAttribute(relativePath)) continue;
191
+ const rawRelativePath = joinParenthesesAndArrays(pathParts.slice(2));
192
+ if (!validAttribute(rawRelativePath)) continue;
193
+
194
+ // Normalize the path for internal use (e.g., ['*'] -> '*')
195
+ const relativePath = normalizePathForInternalUse(rawRelativePath);
158
196
 
159
197
  attributesMap[relativePath] = returnValueDataStructure[path];
160
198
  associationMap[reverse ? relativePath : path] = reverse