@codeyam/codeyam-cli 0.1.0-staging.036391e → 0.1.0-staging.03e0fb2

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 (320) 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 +14 -14
  4. package/analyzer-template/packages/ai/index.ts +1 -0
  5. package/analyzer-template/packages/ai/package.json +1 -1
  6. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +14 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +101 -0
  8. package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
  9. package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +6 -0
  10. package/analyzer-template/packages/ai/src/lib/completionCall.ts +102 -113
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +408 -13
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +70 -19
  13. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
  14. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +40 -13
  15. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +32 -5
  16. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +134 -2
  17. package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +359 -142
  18. package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
  19. package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
  20. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
  21. package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
  22. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +18 -0
  23. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +50 -25
  24. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +153 -76
  25. package/analyzer-template/packages/aws/package.json +10 -10
  26. package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
  27. package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
  28. package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
  29. package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
  30. package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
  31. package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
  32. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  33. package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
  34. package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
  35. package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
  36. package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
  37. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
  38. package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
  39. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
  40. package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
  41. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
  42. package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
  43. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
  44. package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
  45. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
  46. package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
  47. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
  48. package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
  49. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  50. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
  51. package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
  52. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
  53. package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
  54. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
  55. package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
  56. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  57. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +98 -3
  58. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  59. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +121 -3
  60. package/analyzer-template/project/constructMockCode.ts +34 -7
  61. package/analyzer-template/project/orchestrateCapture.ts +4 -1
  62. package/analyzer-template/project/writeScenarioComponents.ts +76 -12
  63. package/background/src/lib/local/createLocalAnalyzer.js +1 -1
  64. package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
  65. package/background/src/lib/virtualized/project/constructMockCode.js +30 -7
  66. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  67. package/background/src/lib/virtualized/project/orchestrateCapture.js +4 -1
  68. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  69. package/background/src/lib/virtualized/project/writeScenarioComponents.js +56 -7
  70. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  71. package/codeyam-cli/scripts/apply-setup.js +1 -1
  72. package/codeyam-cli/src/cli.js +31 -24
  73. package/codeyam-cli/src/cli.js.map +1 -1
  74. package/codeyam-cli/src/codeyam-cli.js +18 -2
  75. package/codeyam-cli/src/codeyam-cli.js.map +1 -1
  76. package/codeyam-cli/src/commands/analyze.js +4 -2
  77. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  78. package/codeyam-cli/src/commands/baseline.js +2 -0
  79. package/codeyam-cli/src/commands/baseline.js.map +1 -1
  80. package/codeyam-cli/src/commands/debug.js +2 -0
  81. package/codeyam-cli/src/commands/debug.js.map +1 -1
  82. package/codeyam-cli/src/commands/default.js +31 -20
  83. package/codeyam-cli/src/commands/default.js.map +1 -1
  84. package/codeyam-cli/src/commands/init.js +49 -257
  85. package/codeyam-cli/src/commands/init.js.map +1 -1
  86. package/codeyam-cli/src/commands/memory.js +95 -81
  87. package/codeyam-cli/src/commands/memory.js.map +1 -1
  88. package/codeyam-cli/src/commands/recapture.js +2 -0
  89. package/codeyam-cli/src/commands/recapture.js.map +1 -1
  90. package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
  91. package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
  92. package/codeyam-cli/src/commands/setup-simulations.js +284 -0
  93. package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
  94. package/codeyam-cli/src/commands/test-startup.js +2 -0
  95. package/codeyam-cli/src/commands/test-startup.js.map +1 -1
  96. package/codeyam-cli/src/commands/verify.js +14 -2
  97. package/codeyam-cli/src/commands/verify.js.map +1 -1
  98. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +185 -0
  99. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
  100. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -86
  101. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  102. package/codeyam-cli/src/utils/analyzer.js +7 -0
  103. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  104. package/codeyam-cli/src/utils/backgroundServer.js +90 -23
  105. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  106. package/codeyam-cli/src/utils/generateReport.js +2 -2
  107. package/codeyam-cli/src/utils/install-skills.js +43 -63
  108. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  109. package/codeyam-cli/src/utils/labsAutoCheck.js +0 -29
  110. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -1
  111. package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
  112. package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
  113. package/codeyam-cli/src/utils/progress.js +7 -0
  114. package/codeyam-cli/src/utils/progress.js.map +1 -1
  115. package/codeyam-cli/src/utils/requireSimulations.js +10 -0
  116. package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
  117. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +7 -8
  118. package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -1
  119. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +1 -1
  120. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -1
  121. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +0 -1
  122. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -1
  123. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +97 -6
  124. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -1
  125. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +4 -6
  126. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -1
  127. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +3 -3
  128. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -1
  129. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js +83 -0
  130. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js.map +1 -0
  131. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js +118 -0
  132. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js.map +1 -0
  133. package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js +72 -0
  134. package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js.map +1 -0
  135. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +23 -23
  136. package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -1
  137. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +76 -0
  138. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -0
  139. package/codeyam-cli/src/utils/rules/index.js +1 -0
  140. package/codeyam-cli/src/utils/rules/index.js.map +1 -1
  141. package/codeyam-cli/src/utils/rules/parser.js +19 -4
  142. package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
  143. package/codeyam-cli/src/utils/rules/pathMatcher.js +34 -3
  144. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -1
  145. package/codeyam-cli/src/utils/rules/rulePlacement.js +65 -0
  146. package/codeyam-cli/src/utils/rules/rulePlacement.js.map +1 -0
  147. package/codeyam-cli/src/utils/rules/ruleState.js +10 -10
  148. package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -1
  149. package/codeyam-cli/src/utils/rules/sourceFiles.js +43 -0
  150. package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -0
  151. package/codeyam-cli/src/utils/rules/staleness.js +6 -6
  152. package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
  153. package/codeyam-cli/src/utils/serverState.js +37 -10
  154. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  155. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -44
  156. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  157. package/codeyam-cli/src/utils/simulationGateMiddleware.js +159 -0
  158. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -0
  159. package/codeyam-cli/src/utils/syncMocksMiddleware.js +5 -24
  160. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  161. package/codeyam-cli/src/utils/transcriptPruning.js +67 -0
  162. package/codeyam-cli/src/utils/transcriptPruning.js.map +1 -0
  163. package/codeyam-cli/src/utils/versionInfo.js +46 -0
  164. package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
  165. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
  166. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
  167. package/codeyam-cli/src/webserver/app/lib/database.js +14 -3
  168. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  169. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  170. package/codeyam-cli/src/webserver/backgroundServer.js +36 -7
  171. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  172. package/codeyam-cli/src/webserver/bootstrap.js +11 -0
  173. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  174. package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CA3JxPb7.js → CopyButton-CtmbP4Gl.js} +1 -1
  175. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-B86KKU7e.js → EntityItem-DlMph_Hm.js} +1 -1
  176. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-B5ctlSYt.js → EntityTypeBadge-B-0PjGOU.js} +1 -1
  177. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BqY8gDAW.js → EntityTypeIcon-DN9eiJAO.js} +1 -1
  178. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-ClaLpuOo.js → InlineSpinner-C1rIyZdV.js} +1 -1
  179. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-BDhPilK7.js → InteractivePreview-rE_fI2h2.js} +2 -2
  180. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-VeqEBv9v.js → LibraryFunctionPreview-CnatsCw2.js} +1 -1
  181. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-Bs7Nn1Jr.js → LoadingDots-CSP6DZrh.js} +1 -1
  182. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-Bm3PmcCz.js → LogViewer-CMK8Q7yk.js} +1 -1
  183. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C6PKeMYR.js → ReportIssueModal-TCV_HBjy.js} +2 -2
  184. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Gq3Ocjo6.js → SafeScreenshot-CG2uh31y.js} +1 -1
  185. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BNLaXBHR.js → ScenarioViewer-CU_TDYd8.js} +2 -2
  186. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CiwXDxLh.js → TruncatedFilePath-D7IoaWUW.js} +1 -1
  187. package/codeyam-cli/src/webserver/build/client/assets/{_index-B3TDXxnk.js → _index-B8z7mjR-.js} +1 -1
  188. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BtBFH820.js → activity.(_tab)-DZu78RI1.js} +1 -1
  189. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-Dm5RS9il.js +22 -0
  190. package/codeyam-cli/src/webserver/build/client/assets/{book-open-PttOB2SF.js → book-open-Bp5FLkd4.js} +1 -1
  191. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-TJp6ofnp.js → chevron-down-DQJA9f4o.js} +1 -1
  192. package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-JE9ZIoBl.js → chunk-JZWAC4HX-7VptmeIr.js} +9 -9
  193. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CXhHQYrI.js → circle-check-B6C4LY9o.js} +1 -1
  194. package/codeyam-cli/src/webserver/build/client/assets/{copy-6y9ALfGT.js → copy-6nzYCu0G.js} +1 -1
  195. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Ca9fAY46.js → createLucideIcon-D-QUFOwe.js} +1 -1
  196. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C5lqplTC.js → dev.empty-DmzSmblj.js} +1 -1
  197. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-n38keI1k.js → entity._sha._-C6PQhwY5.js} +9 -9
  198. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js → entity._sha.scenarios._scenarioId.fullscreen-DVTcUnur.js} +1 -1
  199. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DGgZjdFg.js → entity._sha_.create-scenario-BVgNO76F.js} +1 -1
  200. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-38yPijoD.js → entity._sha_.edit._scenarioId-C7ysA4Jq.js} +1 -1
  201. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-BSHEfydn.js → entry.client-CU6EUArK.js} +1 -1
  202. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DCPhhSMo.js → fileTableUtils-EWpfFU4X.js} +1 -1
  203. package/codeyam-cli/src/webserver/build/client/assets/{files-0N0YJQv7.js → files-CrxAoWIL.js} +1 -1
  204. package/codeyam-cli/src/webserver/build/client/assets/{git-DXnyr8uP.js → git-BldHtKeW.js} +1 -1
  205. package/codeyam-cli/src/webserver/build/client/assets/globals-CLmFdUae.css +1 -0
  206. package/codeyam-cli/src/webserver/build/client/assets/{index-ChN9-fAY.js → index-7-1FmlHo.js} +1 -1
  207. package/codeyam-cli/src/webserver/build/client/assets/{index-CcsFv748.js → index-DuYcwYp_.js} +1 -1
  208. package/codeyam-cli/src/webserver/build/client/assets/labs-CPPVOSWB.js +1 -0
  209. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-CTqLEAGU.js → loader-circle-BnDcD54R.js} +1 -1
  210. package/codeyam-cli/src/webserver/build/client/assets/manifest-717e346a.js +1 -0
  211. package/codeyam-cli/src/webserver/build/client/assets/memory-0wMU4KXe.js +93 -0
  212. package/codeyam-cli/src/webserver/build/client/assets/{pause-D6vreykR.js → pause-DhQX2g22.js} +1 -1
  213. package/codeyam-cli/src/webserver/build/client/assets/root-DqfSDjyQ.js +62 -0
  214. package/codeyam-cli/src/webserver/build/client/assets/{search-B8VUL8nl.js → search-DborVoKD.js} +1 -1
  215. package/codeyam-cli/src/webserver/build/client/assets/settings-BWunYSXt.js +1 -0
  216. package/codeyam-cli/src/webserver/build/client/assets/{simulations-CPoAg7Zo.js → simulations-BtrtCYJg.js} +1 -1
  217. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BrCP7uQo.js → terminal-Bs4NC-VZ.js} +1 -1
  218. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BZz2NjYa.js → triangle-alert-DTf3Jojp.js} +1 -1
  219. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DNwUduNu.js → useCustomSizes-D_bDZyDU.js} +1 -1
  220. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-COky1GVF.js → useLastLogLine-DZp6rrQD.js} +1 -1
  221. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CpZgwliL.js → useReportContext-BsQb6rFd.js} +1 -1
  222. package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bv9JFvUO.js → useToast-BOur3mUv.js} +1 -1
  223. package/codeyam-cli/src/webserver/build/server/assets/{index-DV1ykEI6.js → index-B8jmgmn2.js} +1 -1
  224. package/codeyam-cli/src/webserver/build/server/assets/server-build-9OU4lmvL.js +285 -0
  225. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  226. package/codeyam-cli/src/webserver/build-info.json +5 -5
  227. package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
  228. package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
  229. package/codeyam-cli/templates/codeyam-memory-hook.sh +14 -14
  230. package/codeyam-cli/templates/{codeyam:memory.md → codeyam-memory.md} +16 -24
  231. package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +1 -3
  232. package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
  233. package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
  234. package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
  235. package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
  236. package/codeyam-cli/templates/hooks/staleness-check.sh +43 -0
  237. package/codeyam-cli/templates/prompts/conversation-guidance.txt +44 -0
  238. package/codeyam-cli/templates/prompts/conversation-prompt.txt +28 -0
  239. package/codeyam-cli/templates/prompts/interruption-prompt.txt +31 -0
  240. package/codeyam-cli/templates/prompts/stale-rules-prompt.txt +24 -0
  241. package/codeyam-cli/templates/rule-notification-hook.py +44 -17
  242. package/codeyam-cli/templates/rule-reflection-hook.py +88 -31
  243. package/codeyam-cli/templates/rules-instructions.md +45 -90
  244. package/package.json +12 -12
  245. package/packages/ai/index.js +1 -1
  246. package/packages/ai/index.js.map +1 -1
  247. package/packages/ai/src/lib/analyzeScope.js +14 -0
  248. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  249. package/packages/ai/src/lib/astScopes/processExpression.js +78 -1
  250. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  251. package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
  252. package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
  253. package/packages/ai/src/lib/completionCall.js +0 -5
  254. package/packages/ai/src/lib/completionCall.js.map +1 -1
  255. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +341 -10
  256. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  257. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +59 -17
  258. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  259. package/packages/ai/src/lib/dataStructureChunking.js +30 -11
  260. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
  261. package/packages/ai/src/lib/generateEntityScenarioData.js +22 -3
  262. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  263. package/packages/ai/src/lib/generateExecutionFlows.js +97 -2
  264. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  265. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +242 -81
  266. package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
  267. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
  268. package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
  269. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
  270. package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
  271. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +17 -2
  272. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  273. package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
  274. package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
  275. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +11 -1
  276. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  277. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +42 -13
  278. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  279. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +123 -67
  280. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  281. package/packages/database/src/lib/analysisBranchToDb.js +1 -1
  282. package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
  283. package/packages/database/src/lib/analysisToDb.js +1 -1
  284. package/packages/database/src/lib/analysisToDb.js.map +1 -1
  285. package/packages/database/src/lib/branchToDb.js +1 -1
  286. package/packages/database/src/lib/branchToDb.js.map +1 -1
  287. package/packages/database/src/lib/commitBranchToDb.js +1 -1
  288. package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
  289. package/packages/database/src/lib/commitToDb.js +1 -1
  290. package/packages/database/src/lib/commitToDb.js.map +1 -1
  291. package/packages/database/src/lib/fileToDb.js +1 -1
  292. package/packages/database/src/lib/fileToDb.js.map +1 -1
  293. package/packages/database/src/lib/projectToDb.js +1 -1
  294. package/packages/database/src/lib/projectToDb.js.map +1 -1
  295. package/packages/database/src/lib/saveFiles.js +1 -1
  296. package/packages/database/src/lib/saveFiles.js.map +1 -1
  297. package/packages/database/src/lib/scenarioToDb.js +1 -1
  298. package/packages/database/src/lib/scenarioToDb.js.map +1 -1
  299. package/packages/utils/src/lib/fs/rsyncCopy.js +98 -3
  300. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  301. package/scripts/finalize-analyzer.cjs +8 -76
  302. package/codeyam-cli/src/commands/detect-universal-mocks.js +0 -118
  303. package/codeyam-cli/src/commands/detect-universal-mocks.js.map +0 -1
  304. package/codeyam-cli/src/commands/list.js +0 -31
  305. package/codeyam-cli/src/commands/list.js.map +0 -1
  306. package/codeyam-cli/src/commands/webapp-info.js +0 -146
  307. package/codeyam-cli/src/commands/webapp-info.js.map +0 -1
  308. package/codeyam-cli/src/utils/universal-mocks.js +0 -152
  309. package/codeyam-cli/src/utils/universal-mocks.js.map +0 -1
  310. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DfKzxuoe.js +0 -11
  311. package/codeyam-cli/src/webserver/build/client/assets/globals-DoeDFXZN.css +0 -1
  312. package/codeyam-cli/src/webserver/build/client/assets/labs-CmBYA0PH.js +0 -1
  313. package/codeyam-cli/src/webserver/build/client/assets/manifest-76786b8e.js +0 -1
  314. package/codeyam-cli/src/webserver/build/client/assets/memory-CrNQfdMO.js +0 -76
  315. package/codeyam-cli/src/webserver/build/client/assets/root-QAY34PIo.js +0 -62
  316. package/codeyam-cli/src/webserver/build/client/assets/settings-eBI36Yv5.js +0 -1
  317. package/codeyam-cli/src/webserver/build/server/assets/server-build-BrcVrUEv.js +0 -260
  318. package/codeyam-cli/templates/codeyam-stop-hook.sh +0 -284
  319. package/codeyam-cli/templates/codeyam:diagnose.md +0 -805
  320. /package/codeyam-cli/src/webserver/build/client/assets/{api.labs-survey-l0sNRNKZ.js → api.rule-path-l0sNRNKZ.js} +0 -0
@@ -397,6 +397,7 @@ const SILENTLY_IGNORED_EQUIVALENCY_REASONS = new Set([
397
397
  'transformed non-object function equivalency - implicit parent equivalency - rerouted via useCallback',
398
398
  'transformed non-object function equivalency - Array.from() equivalency',
399
399
  'Spread operator equivalency key update: Explicit array deconstruction equivalency value',
400
+ // 'transformed non-object function equivalency - Explicit array deconstruction equivalency value',
400
401
  ]);
401
402
 
402
403
  export class ScopeDataStructure {
@@ -2797,6 +2798,8 @@ export class ScopeDataStructure {
2797
2798
  usageEquivalency.scopeNodeName,
2798
2799
  ) as ScopeNode;
2799
2800
 
2801
+ if (!usageScopeNode) continue;
2802
+
2800
2803
  // Guard against infinite recursion by tracking which paths we've already
2801
2804
  // added from addComplexSourcePathVariables
2802
2805
  if (
@@ -2876,6 +2879,8 @@ export class ScopeDataStructure {
2876
2879
  usageEquivalency.scopeNodeName,
2877
2880
  ) as ScopeNode;
2878
2881
 
2882
+ if (!usageScopeNode) continue;
2883
+
2879
2884
  // This is put in place to avoid propagating array functions like 'filter' through complex equivalencies
2880
2885
  // but may cause problems if the funtion call is not on a known object (e.g. string or array)
2881
2886
  if (
@@ -3355,6 +3360,22 @@ export class ScopeDataStructure {
3355
3360
  * ensure all sub-paths of that variable are reflected under signature[N].
3356
3361
  */
3357
3362
  private propagateParameterToSignaturePaths(scopeNode: ScopeNode) {
3363
+ // Helper: check if a type is a concrete scalar that cannot have sub-properties.
3364
+ const SCALAR_TYPES = new Set([
3365
+ 'string',
3366
+ 'number',
3367
+ 'boolean',
3368
+ 'bigint',
3369
+ 'symbol',
3370
+ 'void',
3371
+ 'never',
3372
+ ]);
3373
+ const isDefinitelyScalar = (type: string): boolean => {
3374
+ const parts = type.split('|').map((s) => s.trim());
3375
+ const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
3376
+ return base.length > 0 && base.every((b) => SCALAR_TYPES.has(b));
3377
+ };
3378
+
3358
3379
  // Find variable → signature[N] equivalencies
3359
3380
  for (const [varName, equivalencies] of Object.entries(
3360
3381
  scopeNode.equivalencies,
@@ -3385,7 +3406,38 @@ export class ScopeDataStructure {
3385
3406
 
3386
3407
  // Only add if the signature path doesn't already exist
3387
3408
  if (!scopeNode.schema[sigKey]) {
3388
- scopeNode.schema[sigKey] = scopeNode.schema[key];
3409
+ // Check if this path represents variable conflation:
3410
+ // When a standalone variable (e.g., showWorkoutForm from useState)
3411
+ // appears as a sub-property of a scalar-typed ancestor (e.g.,
3412
+ // activity_type = "string"), it's from scope conflation, not real
3413
+ // property access. Block these while allowing legitimate built-in
3414
+ // accesses like string.length or string.slice.
3415
+ let isConflatedPath = false;
3416
+ let checkPos = signaturePath.length;
3417
+ while (true) {
3418
+ checkPos = sigKey.indexOf('.', checkPos + 1);
3419
+ if (checkPos === -1) break;
3420
+ const ancestorPath = sigKey.substring(0, checkPos);
3421
+ const ancestorType = scopeNode.schema[ancestorPath];
3422
+ if (ancestorType && isDefinitelyScalar(ancestorType)) {
3423
+ // Ancestor is scalar — check if the immediate sub-property
3424
+ // is also a standalone variable (indicating conflation)
3425
+ const afterDot = sigKey.substring(checkPos + 1);
3426
+ const nextSep = afterDot.search(/[.\[]/);
3427
+ const subPropName =
3428
+ nextSep === -1
3429
+ ? afterDot
3430
+ : afterDot.substring(0, nextSep);
3431
+ if (scopeNode.schema[subPropName] !== undefined) {
3432
+ isConflatedPath = true;
3433
+ break;
3434
+ }
3435
+ }
3436
+ }
3437
+
3438
+ if (!isConflatedPath) {
3439
+ scopeNode.schema[sigKey] = scopeNode.schema[key];
3440
+ }
3389
3441
  }
3390
3442
  }
3391
3443
  }
@@ -3898,25 +3950,116 @@ export class ScopeDataStructure {
3898
3950
  return [source];
3899
3951
  };
3900
3952
 
3901
- return entries.reduce(
3902
- (acc, entry) => {
3903
- if (entry.sourceCandidates.length === 0) return acc;
3953
+ const acc = entries.reduce(
3954
+ (result, entry) => {
3955
+ if (entry.sourceCandidates.length === 0) return result;
3904
3956
  const usages = entry.usages.filter(usageMatchesScope);
3905
3957
  for (const usage of usages) {
3906
- acc[usage.schemaPath] ||= [];
3958
+ result[usage.schemaPath] ||= [];
3907
3959
  // Resolve each source candidate through the equivalency chain
3908
3960
  for (const source of entry.sourceCandidates) {
3909
3961
  const resolvedSources = resolveToSignature(source, new Set());
3910
- acc[usage.schemaPath].push(...resolvedSources);
3962
+ result[usage.schemaPath].push(...resolvedSources);
3911
3963
  }
3912
3964
  }
3913
- return acc;
3965
+ return result;
3914
3966
  },
3915
3967
  {} as Record<
3916
3968
  string,
3917
3969
  Pick<ScopeVariable, 'scopeNodeName' | 'schemaPath'>[]
3918
3970
  >,
3919
3971
  );
3972
+
3973
+ // Post-processing: enrich useState-backed sources with co-located external
3974
+ // function calls. When a useState value resolves to a setter variable that
3975
+ // lives in the same scope as a fetch/API call, that fetch is a data source.
3976
+ this.enrichUseStateSourcesWithCoLocatedCalls(acc);
3977
+
3978
+ return acc;
3979
+ }
3980
+
3981
+ /**
3982
+ * For each source that ends at a useState path, check if the setter was called
3983
+ * from a scope that also contains external function calls (like fetch).
3984
+ * If so, add those external calls as additional source candidates.
3985
+ */
3986
+ private enrichUseStateSourcesWithCoLocatedCalls(
3987
+ acc: Record<string, Pick<ScopeVariable, 'scopeNodeName' | 'schemaPath'>[]>,
3988
+ ) {
3989
+ const rootScopeName = this.scopeTreeManager.getRootName();
3990
+ const rootScope = this.scopeNodes[rootScopeName];
3991
+ if (!rootScope) return;
3992
+
3993
+ // Collect all descendants for each scope node
3994
+ const getAllDescendants = (
3995
+ node: import('./helpers/ScopeTreeManager').ScopeTreeNode,
3996
+ ): Set<string> => {
3997
+ const names = new Set<string>([node.name]);
3998
+ for (const child of node.children) {
3999
+ for (const name of getAllDescendants(child)) {
4000
+ names.add(name);
4001
+ }
4002
+ }
4003
+ return names;
4004
+ };
4005
+
4006
+ for (const [usagePath, sources] of Object.entries(acc)) {
4007
+ const additionalSources: Pick<
4008
+ ScopeVariable,
4009
+ 'scopeNodeName' | 'schemaPath'
4010
+ >[] = [];
4011
+
4012
+ for (const source of sources) {
4013
+ // Check if this source is a useState-related terminal path
4014
+ // (e.g., useState(X).functionCallReturnValue[1] or useState(X).signature[0])
4015
+ if (!source.schemaPath.match(/^useState\([^)]*\)\./)) continue;
4016
+
4017
+ // Find the useState call from the source path
4018
+ const useStateCallMatch = source.schemaPath.match(
4019
+ /^(useState\([^)]*\))\./,
4020
+ );
4021
+ if (!useStateCallMatch) continue;
4022
+ const useStateCall = useStateCallMatch[1];
4023
+
4024
+ // Look in the root scope for the useState value equivalency
4025
+ // which tells us where the setter was called from
4026
+ const valuePath = `${useStateCall}.functionCallReturnValue[0]`;
4027
+ const valueEquivs = rootScope.equivalencies[valuePath];
4028
+ if (!valueEquivs) continue;
4029
+
4030
+ for (const equiv of valueEquivs) {
4031
+ // Find the scope where the setter was called
4032
+ const setterScopeName = equiv.scopeNodeName;
4033
+ const setterScopeTree =
4034
+ this.scopeTreeManager.findNode(setterScopeName);
4035
+ if (!setterScopeTree) continue;
4036
+
4037
+ // Get all descendant scope names from the setter scope
4038
+ const relatedScopes = getAllDescendants(setterScopeTree);
4039
+
4040
+ // Find external function calls in those scopes whose return values
4041
+ // are actually consumed (assigned to a variable). This excludes
4042
+ // fire-and-forget calls like analytics.track() or console.log().
4043
+ const coLocatedCalls = this.externalFunctionCalls.filter(
4044
+ (efc) =>
4045
+ relatedScopes.has(efc.callScope) &&
4046
+ efc.receivingVariableNames &&
4047
+ efc.receivingVariableNames.length > 0,
4048
+ );
4049
+
4050
+ for (const call of coLocatedCalls) {
4051
+ additionalSources.push({
4052
+ scopeNodeName: call.callScope,
4053
+ schemaPath: `${call.callSignature}.functionCallReturnValue`,
4054
+ });
4055
+ }
4056
+ }
4057
+ }
4058
+
4059
+ if (additionalSources.length > 0) {
4060
+ acc[usagePath].push(...additionalSources);
4061
+ }
4062
+ }
3920
4063
  }
3921
4064
 
3922
4065
  getUsageEquivalencies(functionName?: string) {
@@ -4069,6 +4212,24 @@ export class ScopeDataStructure {
4069
4212
  }
4070
4213
  }
4071
4214
 
4215
+ // Helper: check if a type is a concrete scalar that cannot have sub-properties.
4216
+ // e.g., "string", "number | undefined", "boolean | null" are scalar.
4217
+ // "object", "array", "function", "unknown", "Workout", etc. are NOT scalar.
4218
+ const SCALAR_TYPES = new Set([
4219
+ 'string',
4220
+ 'number',
4221
+ 'boolean',
4222
+ 'bigint',
4223
+ 'symbol',
4224
+ 'void',
4225
+ 'never',
4226
+ ]);
4227
+ const isDefinitelyScalarType = (type: string): boolean => {
4228
+ const parts = type.split('|').map((s) => s.trim());
4229
+ const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
4230
+ return base.length > 0 && base.every((b) => SCALAR_TYPES.has(b));
4231
+ };
4232
+
4072
4233
  // Propagate nested paths from variables to their signature equivalents
4073
4234
  // e.g., if workouts = signature[0].workouts, then workouts[].title becomes
4074
4235
  // signature[0].workouts[].title
@@ -4093,7 +4254,69 @@ export class ScopeDataStructure {
4093
4254
 
4094
4255
  // Add to schema if not already present
4095
4256
  if (!tempScopeNode.schema[signatureKey]) {
4096
- tempScopeNode.schema[signatureKey] = schema[schemaKey];
4257
+ // Check if this path represents variable conflation:
4258
+ // When a standalone variable (e.g., showWorkoutForm from useState)
4259
+ // appears as a sub-property of a scalar-typed ancestor (e.g.,
4260
+ // activity_type = "string"), it's from scope conflation, not real
4261
+ // property access. Block these while allowing legitimate built-in
4262
+ // accesses like string.length or string.slice.
4263
+ let isConflatedPath = false;
4264
+ let checkPos = signaturePath.length;
4265
+ while (true) {
4266
+ checkPos = signatureKey.indexOf('.', checkPos + 1);
4267
+ if (checkPos === -1) break;
4268
+ const ancestorPath = signatureKey.substring(0, checkPos);
4269
+ const ancestorType = tempScopeNode.schema[ancestorPath];
4270
+ if (ancestorType && isDefinitelyScalarType(ancestorType)) {
4271
+ // Ancestor is scalar — check if the immediate sub-property
4272
+ // is also a standalone variable (indicating conflation)
4273
+ const afterDot = signatureKey.substring(checkPos + 1);
4274
+ const nextSep = afterDot.search(/[.\[]/);
4275
+ const subPropName =
4276
+ nextSep === -1 ? afterDot : afterDot.substring(0, nextSep);
4277
+ if (schema[subPropName] !== undefined) {
4278
+ isConflatedPath = true;
4279
+ break;
4280
+ }
4281
+ }
4282
+ }
4283
+
4284
+ if (!isConflatedPath) {
4285
+ tempScopeNode.schema[signatureKey] = schema[schemaKey];
4286
+ }
4287
+ }
4288
+ }
4289
+ }
4290
+ }
4291
+
4292
+ // Post-process: filter out conflated signature paths.
4293
+ // During phase 2 scope analysis, useState(false) conflation can create
4294
+ // bad paths like signature[0].mockWorkouts[].activity_type.showWorkoutForm
4295
+ // directly in scopeNode.schema. These flow through signatureInSchema into
4296
+ // tempScopeNode.schema without any guard. Filter them out here by checking:
4297
+ // 1. An ancestor in the path has a concrete scalar type (string, number, boolean, etc.)
4298
+ // 2. The immediate sub-property of that scalar ancestor is also a standalone
4299
+ // variable in the schema (indicating conflation, not a real property access)
4300
+ for (const key of Object.keys(tempScopeNode.schema)) {
4301
+ if (!key.startsWith('signature[')) continue;
4302
+
4303
+ // Walk through the path looking for scalar-typed ancestors
4304
+ let pos = 0;
4305
+ while (true) {
4306
+ pos = key.indexOf('.', pos + 1);
4307
+ if (pos === -1) break;
4308
+ const ancestorPath = key.substring(0, pos);
4309
+ const ancestorType = tempScopeNode.schema[ancestorPath];
4310
+ if (ancestorType && isDefinitelyScalarType(ancestorType)) {
4311
+ // Found a scalar ancestor — check if the sub-property name
4312
+ // is a standalone variable in the getSchema() result
4313
+ const afterDot = key.substring(pos + 1);
4314
+ const nextSep = afterDot.search(/[.\[]/);
4315
+ const subPropName =
4316
+ nextSep === -1 ? afterDot : afterDot.substring(0, nextSep);
4317
+ if (schema[subPropName] !== undefined) {
4318
+ delete tempScopeNode.schema[key];
4319
+ break;
4097
4320
  }
4098
4321
  }
4099
4322
  }
@@ -4423,6 +4646,15 @@ export class ScopeDataStructure {
4423
4646
  !equivalentValue.schemaPath.startsWith('signature[') && // not a signature path
4424
4647
  !equivalentValue.schemaPath.endsWith('.functionCallReturnValue') // not already handled above
4425
4648
  ) {
4649
+ // Skip bare "returnValue" from child scopes — this is the child's return value,
4650
+ // not a meaningful data source path in the parent scope
4651
+ if (
4652
+ equivalentValue.schemaPath === 'returnValue' &&
4653
+ equivalentValue.scopeNodeName !==
4654
+ this.scopeTreeManager.getRootName()
4655
+ ) {
4656
+ continue;
4657
+ }
4426
4658
  // Add equivalency (will accumulate if multiple values for OR expressions)
4427
4659
  addEquivalency(path, equivalentValue.schemaPath);
4428
4660
  }
@@ -4824,9 +5056,109 @@ export class ScopeDataStructure {
4824
5056
  // Replace cyScope placeholders in all external function call data
4825
5057
  // This ensures call signatures and schema paths use actual callback text
4826
5058
  // instead of internal cyScope names, preventing mock data merge conflicts.
4827
- return this.externalFunctionCalls.map((efc) =>
4828
- this.cleanCyScopeFromFunctionCallInfo(efc),
4829
- );
5059
+ const rootScopeName = this.scopeTreeManager.getRootName();
5060
+ const rootSchema = this.scopeNodes[rootScopeName]?.schema ?? {};
5061
+
5062
+ return this.externalFunctionCalls.map((efc) => {
5063
+ const cleaned = this.cleanCyScopeFromFunctionCallInfo(efc);
5064
+ return this.filterConflatedExternalPaths(cleaned, rootSchema);
5065
+ });
5066
+ }
5067
+
5068
+ /**
5069
+ * Filters out conflated paths from external function call schemas.
5070
+ *
5071
+ * When multiple useState(false) calls create equivalency conflation during
5072
+ * Phase 1 analysis, standalone boolean state variables (like showWorkoutForm,
5073
+ * showGoalForm) can bleed into external function call schemas as sub-properties
5074
+ * of unrelated data fields (like data[].activity_type.showWorkoutForm).
5075
+ *
5076
+ * Detection: group sub-properties by parent path. If 2+ sub-properties of
5077
+ * the same parent all match standalone root scope variable names, treat them
5078
+ * as conflation artifacts and remove them.
5079
+ */
5080
+ private filterConflatedExternalPaths(
5081
+ efc: FunctionCallInfo,
5082
+ rootSchema: Record<string, string>,
5083
+ ): FunctionCallInfo {
5084
+ // Build a set of top-level root scope variable names (simple names, no dots/brackets)
5085
+ const topLevelRootVars = new Set<string>();
5086
+ for (const key of Object.keys(rootSchema)) {
5087
+ if (!key.includes('.') && !key.includes('[')) {
5088
+ topLevelRootVars.add(key);
5089
+ }
5090
+ }
5091
+
5092
+ if (topLevelRootVars.size === 0) return efc;
5093
+
5094
+ // Group sub-property matches by their parent path.
5095
+ // For a path like "...data[].activity_type.showWorkoutForm",
5096
+ // parent = "...data[].activity_type", child = "showWorkoutForm"
5097
+ const parentToConflatedKeys = new Map<string, string[]>();
5098
+
5099
+ for (const key of Object.keys(efc.schema)) {
5100
+ const lastDot = key.lastIndexOf('.');
5101
+ if (lastDot === -1) continue;
5102
+
5103
+ const parent = key.substring(0, lastDot);
5104
+ const child = key.substring(lastDot + 1);
5105
+
5106
+ // Skip array access or function call patterns
5107
+ if (child.includes('[') || child.includes('(')) continue;
5108
+
5109
+ // Only consider paths inside array element chains (contains []).
5110
+ // Direct children of functionCallReturnValue are legitimate destructured
5111
+ // return values, not conflation. Conflation happens deeper in the chain
5112
+ // when array element fields get corrupted sub-properties.
5113
+ if (!parent.includes('[')) continue;
5114
+
5115
+ if (topLevelRootVars.has(child)) {
5116
+ if (!parentToConflatedKeys.has(parent)) {
5117
+ parentToConflatedKeys.set(parent, []);
5118
+ }
5119
+ parentToConflatedKeys.get(parent)!.push(key);
5120
+ }
5121
+ }
5122
+
5123
+ // Only filter when 2+ sub-properties of the same parent match root scope vars.
5124
+ // This threshold avoids false positives from coincidental name matches.
5125
+ const keysToRemove = new Set<string>();
5126
+ const parentsToRestore = new Set<string>();
5127
+
5128
+ for (const [parent, conflatedKeys] of parentToConflatedKeys) {
5129
+ if (conflatedKeys.length >= 2) {
5130
+ for (const key of conflatedKeys) {
5131
+ keysToRemove.add(key);
5132
+ }
5133
+ parentsToRestore.add(parent);
5134
+ }
5135
+ }
5136
+
5137
+ if (keysToRemove.size === 0) return efc;
5138
+
5139
+ // Create a new schema without the conflated paths
5140
+ const newSchema: Record<string, string> = {};
5141
+ for (const [key, value] of Object.entries(efc.schema)) {
5142
+ if (keysToRemove.has(key)) continue;
5143
+
5144
+ // Restore parent type: if it was changed to "object" because of conflated
5145
+ // sub-properties, and now all those sub-properties are removed, change it
5146
+ // back to "unknown" (we don't know the original type)
5147
+ if (parentsToRestore.has(key) && value === 'object') {
5148
+ // Check if there are any remaining sub-properties
5149
+ const hasRemainingSubProps = Object.keys(efc.schema).some(
5150
+ (k) =>
5151
+ !keysToRemove.has(k) &&
5152
+ k !== key &&
5153
+ (k.startsWith(key + '.') || k.startsWith(key + '[')),
5154
+ );
5155
+ newSchema[key] = hasRemainingSubProps ? value : 'unknown';
5156
+ } else {
5157
+ newSchema[key] = value;
5158
+ }
5159
+ }
5160
+
5161
+ return { ...efc, schema: newSchema };
4830
5162
  }
4831
5163
 
4832
5164
  /**
@@ -5119,6 +5451,10 @@ export class ScopeDataStructure {
5119
5451
  getEnrichedConditionalUsages(): Record<string, EnrichedConditionalUsage[]> {
5120
5452
  const enriched: Record<string, EnrichedConditionalUsage[]> = {};
5121
5453
 
5454
+ console.log(
5455
+ `[getEnrichedConditionalUsages] Processing ${Object.keys(this.rawConditionalUsages).length} conditional paths: [${Object.keys(this.rawConditionalUsages).join(', ')}]`,
5456
+ );
5457
+
5122
5458
  for (const [path, usages] of Object.entries(this.rawConditionalUsages)) {
5123
5459
  // Try to trace this path back to a data source
5124
5460
  // First, try the root scope
@@ -5127,10 +5463,69 @@ export class ScopeDataStructure {
5127
5463
 
5128
5464
  let sourceDataPath: string | undefined;
5129
5465
  if (explanation.source) {
5130
- // Build the full data path: scopeName.path
5131
- sourceDataPath = `${explanation.source.scope}.${explanation.source.path}`;
5466
+ const { scope, path: sourcePath } = explanation.source;
5467
+
5468
+ // Build initial path — avoid redundant prefix when path already contains the scope call
5469
+ let fullPath: string;
5470
+ if (sourcePath.startsWith(`${scope}(`)) {
5471
+ fullPath = sourcePath;
5472
+ } else {
5473
+ fullPath = `${scope}.${sourcePath}`;
5474
+ }
5475
+
5476
+ sourceDataPath = fullPath;
5477
+ console.log(
5478
+ `[getEnrichedConditionalUsages] "${path}" explainPath → scope="${scope}", sourcePath="${sourcePath}" → sourceDataPath="${sourceDataPath}"`,
5479
+ );
5480
+ } else {
5481
+ console.log(
5482
+ `[getEnrichedConditionalUsages] "${path}" explainPath → no source found`,
5483
+ );
5484
+ }
5485
+
5486
+ // If explainPath didn't find a useful external source (e.g., it traced to
5487
+ // useState or just to the component scope itself), check sourceEquivalencies
5488
+ // for an external function call source like a fetch call
5489
+ const hasExternalSource = sourceDataPath?.includes(
5490
+ '.functionCallReturnValue',
5491
+ );
5492
+ if (!hasExternalSource) {
5493
+ console.log(
5494
+ `[getEnrichedConditionalUsages] "${path}" no external source (sourceDataPath="${sourceDataPath}"), checking sourceEquivalencies fallback...`,
5495
+ );
5496
+ const sourceEquiv = this.getSourceEquivalencies();
5497
+ const returnValueKey = `returnValue.${path}`;
5498
+ const sources = sourceEquiv[returnValueKey];
5499
+ if (sources) {
5500
+ console.log(
5501
+ `[getEnrichedConditionalUsages] "${path}" sourceEquivalencies["${returnValueKey}"] has ${sources.length} sources: [${sources.map((s: { schemaPath: string }) => s.schemaPath).join(', ')}]`,
5502
+ );
5503
+ const externalSource = sources.find(
5504
+ (s: { schemaPath: string }) =>
5505
+ s.schemaPath.includes('.functionCallReturnValue') &&
5506
+ !s.schemaPath.startsWith('useState('),
5507
+ );
5508
+ if (externalSource) {
5509
+ console.log(
5510
+ `[getEnrichedConditionalUsages] "${path}" sourceEquivalencies fallback found external source: "${externalSource.schemaPath}"`,
5511
+ );
5512
+ sourceDataPath = externalSource.schemaPath;
5513
+ } else {
5514
+ console.log(
5515
+ `[getEnrichedConditionalUsages] "${path}" sourceEquivalencies fallback found no external function call source`,
5516
+ );
5517
+ }
5518
+ } else {
5519
+ console.log(
5520
+ `[getEnrichedConditionalUsages] "${path}" sourceEquivalencies["${returnValueKey}"] not found`,
5521
+ );
5522
+ }
5132
5523
  }
5133
5524
 
5525
+ console.log(
5526
+ `[getEnrichedConditionalUsages] "${path}" FINAL sourceDataPath="${sourceDataPath ?? '(none)'}" (${usages.length} usages)`,
5527
+ );
5528
+
5134
5529
  enriched[path] = usages.map((usage) => ({
5135
5530
  ...usage,
5136
5531
  sourceDataPath,
@@ -14,21 +14,46 @@ const isStandaloneIndex = (s?: string) => !!s && STANDALONE_INDEX_RE.test(s);
14
14
  // The regex matches any path ending with .length that has [] somewhere before it
15
15
  const DYNAMIC_LENGTH_RE = /\[\].*\.length$/;
16
16
 
17
- // Treat these as structural placeholders (don't commit them as concrete leaves)
18
- function isSkippableLeafType(t: string) {
19
- // 'unknown' by itself is a placeholder (but 'boolean | unknown' is not)
20
- // Also handles optional variants like 'object | undefined', 'object | null',
21
- // 'array | undefined', etc. these are still structural placeholders that
22
- // should not overwrite already-populated structures.
17
+ // Cache for type string analysis to avoid repeated split/filter operations.
18
+ // These functions are called multiple times per path segment across thousands of paths.
19
+ const typeAnalysisCache = new Map<
20
+ string,
21
+ { isSkippable: boolean; baseType: string; isNullable: boolean }
22
+ >();
23
+
24
+ function getTypeAnalysis(t: string) {
25
+ const cached = typeAnalysisCache.get(t);
26
+ if (cached) return cached;
23
27
  const parts = t.split('|').map((s) => s.trim());
24
28
  const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
25
- return (
26
- base.length === 1 &&
27
- (base[0] === 'object' ||
28
- base[0] === 'array' ||
29
- base[0] === 'function' ||
30
- base[0] === 'unknown')
31
- );
29
+ const result = {
30
+ isSkippable:
31
+ base.length === 1 &&
32
+ (base[0] === 'object' ||
33
+ base[0] === 'array' ||
34
+ base[0] === 'function' ||
35
+ base[0] === 'unknown'),
36
+ baseType: base[0],
37
+ isNullable: parts.includes('undefined') || parts.includes('null'),
38
+ };
39
+ typeAnalysisCache.set(t, result);
40
+ return result;
41
+ }
42
+
43
+ // Treat these as structural placeholders (don't commit them as concrete leaves)
44
+ function isSkippableLeafType(t: string) {
45
+ return getTypeAnalysis(t).isSkippable;
46
+ }
47
+
48
+ // Extract the base structural type from a potentially nullable type string.
49
+ // e.g., 'object | undefined' → 'object', 'array | null' → 'array'
50
+ function getBaseSkippableType(t: string): string {
51
+ return getTypeAnalysis(t).baseType;
52
+ }
53
+
54
+ // Check if a type string has nullable annotations (| undefined or | null)
55
+ function isNullableType(t: string): boolean {
56
+ return getTypeAnalysis(t).isNullable;
32
57
  }
33
58
 
34
59
  // Matches paths containing [][] — e.g., "items[][]" or "items[][].text"
@@ -317,15 +342,41 @@ export default function convertDotNotation(
317
342
  cursor[key] = typ;
318
343
  } else {
319
344
  // Structural/placeholder terminal
320
- if (typ === 'array') {
345
+ const nullable = isNullableType(typ);
346
+ const baseType = getBaseSkippableType(typ);
347
+
348
+ if (baseType === 'array') {
321
349
  if (!Array.isArray(cursor[key])) cursor[key] = [];
350
+ if (nullable) {
351
+ (cursor[key] as any)._nullable = true;
352
+ }
322
353
  } else if (
323
- typ === 'object' ||
324
- typ === 'function' ||
325
- typ.trim() === 'unknown'
354
+ baseType === 'object' ||
355
+ baseType === 'function' ||
356
+ baseType === 'unknown'
326
357
  ) {
327
- if (cursor[key] === undefined) {
328
- cursor[key] = typ;
358
+ if (nullable) {
359
+ // Nullable object: ensure it's an actual object (not a string
360
+ // placeholder) so _nullable can be set and child paths can
361
+ // populate properties on it.
362
+ if (
363
+ cursor[key] === undefined ||
364
+ typeof cursor[key] === 'string'
365
+ ) {
366
+ cursor[key] = {};
367
+ }
368
+ if (
369
+ typeof cursor[key] === 'object' &&
370
+ cursor[key] !== null &&
371
+ !Array.isArray(cursor[key])
372
+ ) {
373
+ (cursor[key] as any)._nullable = true;
374
+ }
375
+ } else {
376
+ // Non-nullable: preserve existing behavior (string placeholder)
377
+ if (cursor[key] === undefined) {
378
+ cursor[key] = typ;
379
+ }
329
380
  }
330
381
  }
331
382
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Recursively strips `_nullable` keys from LLM-generated mock data.
3
+ *
4
+ * The `_nullable` marker is an internal CodeYam concept used in type definitions
5
+ * to indicate that a field can be null/undefined. The LLM sometimes includes
6
+ * these markers in its generated scenario data, which causes runtime errors
7
+ * when code iterates over object keys (e.g., `Object.keys(importedBy)` picks
8
+ * up `_nullable` as a key alongside real data).
9
+ *
10
+ * This function mutates the input object in-place, consistent with other
11
+ * post-processing helpers like `convertNullToUndefinedBySchema`.
12
+ */
13
+ export default function stripNullableMarkers(
14
+ data: Record<string, unknown>,
15
+ ): void {
16
+ if (data == null || typeof data !== 'object') return;
17
+
18
+ // Delete _nullable from this level
19
+ if ('_nullable' in data) {
20
+ delete data._nullable;
21
+ }
22
+
23
+ // Recurse into nested objects and arrays
24
+ for (const value of Object.values(data)) {
25
+ if (Array.isArray(value)) {
26
+ for (const item of value) {
27
+ if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
28
+ stripNullableMarkers(item as Record<string, unknown>);
29
+ }
30
+ }
31
+ } else if (value !== null && typeof value === 'object') {
32
+ stripNullableMarkers(value as Record<string, unknown>);
33
+ }
34
+ }
35
+ }