@codeyam/codeyam-cli 0.1.0-bleeding-edge.8afd3ee → 0.1.0-staging.09652b8

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 (220) 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 +1 -1
  4. package/analyzer-template/packages/ai/index.ts +0 -1
  5. package/analyzer-template/packages/ai/scripts/ai-test-matrix.mjs +424 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +6 -16
  7. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +197 -0
  8. package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +28 -2
  9. package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +113 -4
  10. package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +1 -3
  11. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +430 -7
  12. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +12 -6
  13. package/analyzer-template/packages/ai/src/lib/generateChangesEntityDocumentation.ts +20 -2
  14. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +56 -160
  15. package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +79 -265
  16. package/analyzer-template/packages/ai/src/lib/generateEntityDocumentation.ts +16 -2
  17. package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +53 -154
  18. package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +84 -254
  19. package/analyzer-template/packages/ai/src/lib/generateStatementAnalysis.ts +48 -71
  20. package/analyzer-template/packages/ai/src/lib/getLLMCallStats.ts +0 -14
  21. package/analyzer-template/packages/ai/src/lib/modelInfo.ts +15 -0
  22. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.ts +8 -33
  23. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +54 -62
  24. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +93 -109
  25. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.ts +8 -27
  26. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +33 -38
  27. package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +30 -30
  28. package/analyzer-template/packages/ai/src/lib/types/index.ts +2 -0
  29. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +15 -7
  30. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +28 -21
  31. package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.ts +18 -11
  32. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
  33. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
  34. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  35. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.d.ts.map +1 -1
  36. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
  37. package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
  38. package/analyzer-template/packages/github/dist/utils/index.d.ts +1 -0
  39. package/analyzer-template/packages/github/dist/utils/index.d.ts.map +1 -1
  40. package/analyzer-template/packages/github/dist/utils/index.js +1 -0
  41. package/analyzer-template/packages/github/dist/utils/index.js.map +1 -1
  42. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
  43. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  44. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  45. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
  46. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  47. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  48. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
  49. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
  50. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  51. package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  52. package/analyzer-template/packages/ui-components/src/scenario-editor/components/DataItemEditor.tsx +1 -1
  53. package/analyzer-template/packages/utils/dist/utils/index.d.ts +1 -0
  54. package/analyzer-template/packages/utils/dist/utils/index.d.ts.map +1 -1
  55. package/analyzer-template/packages/utils/dist/utils/index.js +1 -0
  56. package/analyzer-template/packages/utils/dist/utils/index.js.map +1 -1
  57. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
  58. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  59. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  60. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
  61. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  62. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  63. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
  64. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
  65. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  66. package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  67. package/analyzer-template/packages/utils/index.ts +1 -0
  68. package/analyzer-template/packages/utils/src/lib/frameworks/getNextRoutePath.ts +2 -1
  69. package/analyzer-template/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.ts +2 -1
  70. package/analyzer-template/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.ts +33 -0
  71. package/analyzer-template/project/startScenarioCapture.ts +24 -0
  72. package/analyzer-template/project/trackGeneratedFiles.ts +41 -0
  73. package/analyzer-template/project/writeMockDataTsx.ts +94 -4
  74. package/analyzer-template/project/writeScenarioComponents.ts +35 -27
  75. package/background/src/lib/virtualized/project/startScenarioCapture.js +18 -0
  76. package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
  77. package/background/src/lib/virtualized/project/trackGeneratedFiles.js +30 -0
  78. package/background/src/lib/virtualized/project/trackGeneratedFiles.js.map +1 -0
  79. package/background/src/lib/virtualized/project/writeMockDataTsx.js +71 -3
  80. package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
  81. package/background/src/lib/virtualized/project/writeScenarioComponents.js +15 -11
  82. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  83. package/codeyam-cli/src/commands/init.js +4 -23
  84. package/codeyam-cli/src/commands/init.js.map +1 -1
  85. package/codeyam-cli/src/utils/webappDetection.js +2 -1
  86. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  87. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-B9Sf8e9w.js +1 -0
  88. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-B0oiPem-.js → InteractivePreview-CDnfNKKQ.js} +3 -3
  89. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DUS-3h7I.js +3 -0
  90. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-BKKG1s2B.js → LogViewer-TJzDQku1.js} +1 -1
  91. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BgdlWM6p.js +1 -0
  92. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bl6GY-OE.js +6 -0
  93. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DmjXUj6m.js → ScenarioViewer-BDq8RX50.js} +1 -1
  94. package/codeyam-cli/src/webserver/build/client/assets/_index-Bh3y3Wsl.js +1 -0
  95. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-tq7Bl6-t.js +10 -0
  96. package/codeyam-cli/src/webserver/build/client/assets/{chart-column-VXBS6qOn.js → chart-column-q9_nHfwv.js} +1 -1
  97. package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-DvL0YqDJ.js +26 -0
  98. package/codeyam-cli/src/webserver/build/client/assets/{circle-alert-n5GUC2AS.js → circle-alert-CKMpA1v_.js} +1 -1
  99. package/codeyam-cli/src/webserver/build/client/assets/{clock-DKqtX8js.js → clock-Wnfog8Qw.js} +1 -1
  100. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-C_ixaqqh.js +1 -0
  101. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BHiWkb_W.js → entity._sha._-3bYjyojg.js} +10 -10
  102. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DtfwpN9J.js +1 -0
  103. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-QecTs_sq.js +5 -0
  104. package/codeyam-cli/src/webserver/build/client/assets/entry.client-hnkEgHrC.js +5 -0
  105. package/codeyam-cli/src/webserver/build/client/assets/file-text-CvCVdKLW.js +1 -0
  106. package/codeyam-cli/src/webserver/build/client/assets/files-DgUCYhbd.js +1 -0
  107. package/codeyam-cli/src/webserver/build/client/assets/git-WoKohOtW.js +12 -0
  108. package/codeyam-cli/src/webserver/build/client/assets/globals-DZfbt0u5.css +1 -0
  109. package/codeyam-cli/src/webserver/build/client/assets/index-Vvbl94Xc.js +8 -0
  110. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-v3c6DFp4.js → loader-circle-Bxm63UxG.js} +1 -1
  111. package/codeyam-cli/src/webserver/build/client/assets/manifest-c90b8608.js +1 -0
  112. package/codeyam-cli/src/webserver/build/client/assets/root-DrVZQamX.js +16 -0
  113. package/codeyam-cli/src/webserver/build/client/assets/{search-DA14wXpu.js → search-CJkk16Ct.js} +1 -1
  114. package/codeyam-cli/src/webserver/build/client/assets/{settings-COJUrwGu.js → settings-ConzHeiL.js} +1 -1
  115. package/codeyam-cli/src/webserver/build/client/assets/settings-LuiJ1UIm.js +1 -0
  116. package/codeyam-cli/src/webserver/build/client/assets/simulations-B9LRwAej.js +1 -0
  117. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-Lumm1t01.js → useLastLogLine-CpUcCv1V.js} +1 -1
  118. package/codeyam-cli/src/webserver/build/client/assets/useToast-DOxmMaSg.js +1 -0
  119. package/codeyam-cli/src/webserver/build/client/assets/{zap-BvukH0eN.js → zap-D5R1FAcH.js} +1 -1
  120. package/codeyam-cli/src/webserver/build/server/assets/index-DzbqTxoN.js +1 -0
  121. package/codeyam-cli/src/webserver/build/server/assets/server-build-DGGis3OZ.js +166 -0
  122. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  123. package/codeyam-cli/src/webserver/build-info.json +5 -5
  124. package/codeyam-cli/src/webserver/server.js +1 -1
  125. package/codeyam-cli/src/webserver/server.js.map +1 -1
  126. package/codeyam-cli/templates/codeyam-setup-skill.md +5 -0
  127. package/package.json +7 -7
  128. package/packages/ai/index.js +0 -1
  129. package/packages/ai/index.js.map +1 -1
  130. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +6 -15
  131. package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
  132. package/packages/ai/src/lib/astScopes/methodSemantics.js +134 -0
  133. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  134. package/packages/ai/src/lib/astScopes/paths.js +28 -3
  135. package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
  136. package/packages/ai/src/lib/astScopes/processExpression.js +99 -3
  137. package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
  138. package/packages/ai/src/lib/checkAllAttributes.js +1 -3
  139. package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
  140. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +308 -2
  141. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  142. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +12 -6
  143. package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
  144. package/packages/ai/src/lib/generateChangesEntityDocumentation.js +19 -1
  145. package/packages/ai/src/lib/generateChangesEntityDocumentation.js.map +1 -1
  146. package/packages/ai/src/lib/generateChangesEntityScenarioData.js +55 -156
  147. package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
  148. package/packages/ai/src/lib/generateChangesEntityScenarios.js +79 -262
  149. package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
  150. package/packages/ai/src/lib/generateEntityDocumentation.js +15 -1
  151. package/packages/ai/src/lib/generateEntityDocumentation.js.map +1 -1
  152. package/packages/ai/src/lib/generateEntityScenarioData.js +52 -152
  153. package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
  154. package/packages/ai/src/lib/generateEntityScenarios.js +88 -258
  155. package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
  156. package/packages/ai/src/lib/generateStatementAnalysis.js +46 -71
  157. package/packages/ai/src/lib/generateStatementAnalysis.js.map +1 -1
  158. package/packages/ai/src/lib/getLLMCallStats.js +0 -14
  159. package/packages/ai/src/lib/getLLMCallStats.js.map +1 -1
  160. package/packages/ai/src/lib/modelInfo.js +15 -0
  161. package/packages/ai/src/lib/modelInfo.js.map +1 -1
  162. package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js +8 -33
  163. package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js.map +1 -1
  164. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +35 -41
  165. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
  166. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +59 -72
  167. package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
  168. package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js +8 -27
  169. package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js.map +1 -1
  170. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +24 -27
  171. package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
  172. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +21 -22
  173. package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
  174. package/packages/ai/src/lib/types/index.js +2 -0
  175. package/packages/ai/src/lib/types/index.js.map +1 -1
  176. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +16 -7
  177. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  178. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
  179. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
  180. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
  181. package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
  182. package/packages/utils/index.js +1 -0
  183. package/packages/utils/index.js.map +1 -1
  184. package/packages/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
  185. package/packages/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
  186. package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
  187. package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
  188. package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
  189. package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
  190. package/analyzer-template/packages/ai/src/lib/generateEntityDataMap.ts +0 -375
  191. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-rqv54FUY.js +0 -1
  192. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DqXXjAJ7.js +0 -3
  193. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DU_jxCPD.js +0 -1
  194. package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-5DY-YIxu.js +0 -6
  195. package/codeyam-cli/src/webserver/build/client/assets/_index-DvSrcxsk.js +0 -1
  196. package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CsaMd9mb.js +0 -10
  197. package/codeyam-cli/src/webserver/build/client/assets/components-Dj-Ggnl2.js +0 -40
  198. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BbR3FwNc.js +0 -1
  199. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-L7M9Vr5z.js +0 -1
  200. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-C9w-q7P3.js +0 -5
  201. package/codeyam-cli/src/webserver/build/client/assets/entry.client-CdGoUs8A.js +0 -1
  202. package/codeyam-cli/src/webserver/build/client/assets/file-text-B6Er7j5k.js +0 -1
  203. package/codeyam-cli/src/webserver/build/client/assets/files-KcDVw1FY.js +0 -1
  204. package/codeyam-cli/src/webserver/build/client/assets/git-B9uZ8eSJ.js +0 -12
  205. package/codeyam-cli/src/webserver/build/client/assets/globals-B0f88RTV.css +0 -1
  206. package/codeyam-cli/src/webserver/build/client/assets/manifest-fca08d7e.js +0 -1
  207. package/codeyam-cli/src/webserver/build/client/assets/root-Cf8VBqIb.js +0 -16
  208. package/codeyam-cli/src/webserver/build/client/assets/settings-NU_ZquhK.js +0 -1
  209. package/codeyam-cli/src/webserver/build/client/assets/simulations-CNaMJ-nR.js +0 -1
  210. package/codeyam-cli/src/webserver/build/client/assets/useToast-BRShB17p.js +0 -1
  211. package/codeyam-cli/src/webserver/build/client/cy-logo-cli.svg +0 -13
  212. package/codeyam-cli/src/webserver/build/client/favicon.svg +0 -13
  213. package/codeyam-cli/src/webserver/build/server/assets/index-DHr4rT4u.js +0 -1
  214. package/codeyam-cli/src/webserver/build/server/assets/server-build-Bi1mj14J.js +0 -166
  215. package/codeyam-cli/src/webserver/public/cy-logo-cli.svg +0 -13
  216. package/codeyam-cli/src/webserver/public/favicon.svg +0 -13
  217. package/packages/ai/src/lib/generateEntityDataMap.js +0 -335
  218. package/packages/ai/src/lib/generateEntityDataMap.js.map +0 -1
  219. package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js +0 -17
  220. package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js.map +0 -1
@@ -159,10 +159,12 @@ const ROOT_SCOPE_NAME = 'root';
159
159
  export let maxEquivalencyChainDepth = 0;
160
160
  export let addToSchemaCallCount = 0;
161
161
  export let followEquivalenciesCallCount = 0;
162
+ export let addEquivalencyCallCount = 0;
162
163
  export function resetScopeDataStructureMetrics() {
163
164
  maxEquivalencyChainDepth = 0;
164
165
  addToSchemaCallCount = 0;
165
166
  followEquivalenciesCallCount = 0;
167
+ addEquivalencyCallCount = 0;
166
168
  }
167
169
 
168
170
  export class ScopeDataStructure {
@@ -188,6 +190,10 @@ export class ScopeDataStructure {
188
190
  private intermediatesOrderIndex: Map<string, EquivalencyDatabaseEntry> =
189
191
  new Map();
190
192
  private globalVisited: Set<string> = new Set();
193
+ // Separate visited set for addComplexSourcePathVariables - uses scope::path only (not value)
194
+ // This allows addComplexSourcePathVariables to run for each unique scope+path combo,
195
+ // while the main globalVisited uses scope+path+value for fine-grained deduplication
196
+ private complexSourceVisited: Set<string> = new Set();
191
197
 
192
198
  constructor(
193
199
  managers: EquivalencyManager[],
@@ -382,6 +388,18 @@ export class ScopeDataStructure {
382
388
  traceId?: number;
383
389
  }) {
384
390
  addToSchemaCallCount++;
391
+ // DEBUG: Detect infinite loops
392
+ if (addToSchemaCallCount > 500000) {
393
+ console.error('INFINITE LOOP DETECTED in addToSchema', {
394
+ callCount: addToSchemaCallCount,
395
+ path,
396
+ value,
397
+ scopeNodeName: scopeNode?.name,
398
+ });
399
+ throw new Error(
400
+ `Infinite loop detected: addToSchema called ${addToSchemaCallCount} times`,
401
+ );
402
+ }
385
403
  // Track max chain depth
386
404
  if (equivalencyValueChain.length > maxEquivalencyChainDepth) {
387
405
  maxEquivalencyChainDepth = equivalencyValueChain.length;
@@ -477,6 +495,7 @@ export class ScopeDataStructure {
477
495
  path,
478
496
  );
479
497
 
498
+ // Call addComplexSourcePathVariables like the original code (before visited check)
480
499
  this.addComplexSourcePathVariables(
481
500
  equivalenciesDatabaseEntry,
482
501
  scopeNode,
@@ -708,6 +727,21 @@ export class ScopeDataStructure {
708
727
  equivalencyValueChain?: EquivalencyValueChainItem[],
709
728
  traceId?: number,
710
729
  ) {
730
+ // DEBUG: Detect infinite loops
731
+ addEquivalencyCallCount++;
732
+ if (addEquivalencyCallCount > 50000) {
733
+ console.error('INFINITE LOOP DETECTED in addEquivalency', {
734
+ callCount: addEquivalencyCallCount,
735
+ path,
736
+ equivalentPath,
737
+ equivalentScopeName,
738
+ scopeNodeName: scopeNode.name,
739
+ equivalencyReason,
740
+ });
741
+ throw new Error(
742
+ `Infinite loop detected: addEquivalency called ${addEquivalencyCallCount} times`,
743
+ );
744
+ }
711
745
  // Temporary debugging to track down unnecessary equivalencies
712
746
  if (
713
747
  ![
@@ -736,6 +770,8 @@ export class ScopeDataStructure {
736
770
  'implicit parent equivalency - rerouted via useCallback', // 1 failure
737
771
  'Spread operator equivalency key update: implicit parent equivalency', // 1 failure
738
772
  'Array.from() equivalency',
773
+ 'propagated sub-property equivalency',
774
+ 'propagated function call return sub-property equivalency',
739
775
  ].includes(equivalencyReason)
740
776
  ) {
741
777
  if (
@@ -771,13 +807,47 @@ export class ScopeDataStructure {
771
807
  scopeNode.equivalencies[path] ||= [];
772
808
 
773
809
  const existing = scopeNode.equivalencies[path];
774
- if (
775
- existing.find(
776
- (v) =>
777
- v.schemaPath === equivalentPath &&
778
- v.scopeNodeName === equivalentScopeName,
779
- )
780
- ) {
810
+ const existingEquivalency = existing.find(
811
+ (v) =>
812
+ v.schemaPath === equivalentPath &&
813
+ v.scopeNodeName === equivalentScopeName,
814
+ );
815
+ if (existingEquivalency) {
816
+ // During Phase 2 (onlyEquivalencies=false), we need to still process the equivalency
817
+ // to build the chain and add to the database, even if the equivalency already exists
818
+ if (!this.onlyEquivalencies) {
819
+ const equivalentScopeNode = this.getScopeOrFunctionCallInfo(
820
+ equivalentScopeName,
821
+ ) as ScopeNode;
822
+ if (equivalentScopeNode) {
823
+ // Extract function call name from path if it looks like a function call path
824
+ // e.g., "ChildComponent().signature[0].dataItem" -> "ChildComponent"
825
+ const pathMatch = path.match(/^([^().]+)\(\)/);
826
+ const previousPathScopeNodeName = pathMatch
827
+ ? pathMatch[1]
828
+ : scopeNode.name;
829
+
830
+ this.addToSchema({
831
+ path: equivalentPath,
832
+ value: 'unknown',
833
+ scopeNode: equivalentScopeNode,
834
+ equivalencyValueChain: [
835
+ ...(equivalencyValueChain ?? []),
836
+ {
837
+ id: existingEquivalency.id,
838
+ source: 'duplicate equivalency - Phase 2',
839
+ reason: equivalencyReason,
840
+ previousPath: {
841
+ scopeNodeName: previousPathScopeNodeName,
842
+ schemaPath: path,
843
+ value: scopeNode.schema[path],
844
+ },
845
+ },
846
+ ],
847
+ traceId,
848
+ });
849
+ }
850
+ }
781
851
  return;
782
852
  }
783
853
 
@@ -1317,6 +1387,84 @@ export class ScopeDataStructure {
1317
1387
  scopeNode,
1318
1388
  'original equivalency',
1319
1389
  );
1390
+
1391
+ // Propagate sub-property equivalencies when the equivalentValue is a simple variable
1392
+ // that has sub-properties defined in the isolatedEquivalentVariables.
1393
+ // This handles cases like: dataItem={{ structure: completeDataStructure }}
1394
+ // where completeDataStructure has sub-properties like completeDataStructure['Function Arguments']
1395
+ // We need to propagate these to create: dataItem.structure['Function Arguments'] equivalencies
1396
+ const isSimpleVariable =
1397
+ !equivalentValue.startsWith('signature[') &&
1398
+ !equivalentValue.includes('functionCallReturnValue') &&
1399
+ !equivalentValue.includes('.') &&
1400
+ !equivalentValue.includes('[');
1401
+
1402
+ if (isSimpleVariable) {
1403
+ // Look in current scope and all parent scopes for sub-properties
1404
+ const scopesToCheck = [scopeNode.name, ...scopeNode.tree];
1405
+ for (const scopeName of scopesToCheck) {
1406
+ const checkScope = this.scopeNodes[scopeName];
1407
+ if (!checkScope?.analysis?.isolatedEquivalentVariables) continue;
1408
+
1409
+ for (const [subPath, subValue] of Object.entries(
1410
+ checkScope.analysis.isolatedEquivalentVariables,
1411
+ )) {
1412
+ // Check if this is a sub-property of the equivalentValue variable
1413
+ // e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
1414
+ const matchesDot = subPath.startsWith(equivalentValue + '.');
1415
+ const matchesBracket = subPath.startsWith(equivalentValue + '[');
1416
+ if (matchesDot || matchesBracket) {
1417
+ const subPropertyPath = subPath.substring(
1418
+ equivalentValue.length,
1419
+ );
1420
+ const newPath = cleanPath(path + subPropertyPath, allPaths);
1421
+ const newEquivalentValue = cleanPath(
1422
+ (subValue as string).replace(/::cyDuplicateKey\d+::/g, ''),
1423
+ allPaths,
1424
+ );
1425
+
1426
+ if (
1427
+ newEquivalentValue &&
1428
+ this.isValidPath(newEquivalentValue)
1429
+ ) {
1430
+ this.addEquivalency(
1431
+ newPath,
1432
+ newEquivalentValue,
1433
+ checkScope.name, // Use the scope where the sub-property was found
1434
+ scopeNode,
1435
+ 'propagated sub-property equivalency',
1436
+ );
1437
+ }
1438
+ }
1439
+
1440
+ // Also check if equivalentValue itself maps to a functionCallReturnValue
1441
+ // e.g., result = useMemo(...).functionCallReturnValue
1442
+ if (
1443
+ subPath === equivalentValue &&
1444
+ typeof subValue === 'string' &&
1445
+ subValue.endsWith('.functionCallReturnValue')
1446
+ ) {
1447
+ this.propagateFunctionCallReturnSubProperties(
1448
+ path,
1449
+ subValue,
1450
+ scopeNode,
1451
+ allPaths,
1452
+ );
1453
+ }
1454
+ }
1455
+ }
1456
+ }
1457
+
1458
+ // Handle function call return values by propagating returnValue.* sub-properties
1459
+ // from the callback scope to the usage path
1460
+ if (equivalentValue.endsWith('.functionCallReturnValue')) {
1461
+ this.propagateFunctionCallReturnSubProperties(
1462
+ path,
1463
+ equivalentValue,
1464
+ scopeNode,
1465
+ allPaths,
1466
+ );
1467
+ }
1320
1468
  }
1321
1469
  }
1322
1470
 
@@ -1356,6 +1504,257 @@ export class ScopeDataStructure {
1356
1504
  this.validateSchema(scopeNode, false, false);
1357
1505
  }
1358
1506
 
1507
+ /**
1508
+ * Propagates returnValue.* sub-properties from a callback scope to the usage path.
1509
+ *
1510
+ * When we have an equivalency like:
1511
+ * DataItemEditor().signature[0].structure -> getData().functionCallReturnValue
1512
+ *
1513
+ * And the callback scope for getData has:
1514
+ * returnValue.args -> dataStructure.arguments
1515
+ *
1516
+ * This method creates the transitive equivalency:
1517
+ * DataItemEditor().signature[0].structure.args -> signature[0].dataStructure.arguments
1518
+ *
1519
+ * It also resolves variable references through parent scopes (e.g., dataStructure -> signature[0].dataStructure)
1520
+ * and ensures the database entry is updated with the usage path.
1521
+ */
1522
+ private propagateFunctionCallReturnSubProperties(
1523
+ path: string,
1524
+ equivalentValue: string,
1525
+ scopeNode: ScopeNode,
1526
+ allPaths: string[],
1527
+ ) {
1528
+ // Try to find the callback scope name from different patterns:
1529
+ // 1. "getData().functionCallReturnValue" → look up getData variable to find scope
1530
+ // 2. "useMemo(cyScope1(), [...]).functionCallReturnValue" → extract cyScope1 directly
1531
+ let callbackScopeName: string | undefined;
1532
+
1533
+ // Pattern 1: Simple function call like getData().functionCallReturnValue
1534
+ const simpleFunctionMatch = equivalentValue.match(
1535
+ /^(\w+)\(\)\.functionCallReturnValue$/,
1536
+ );
1537
+ if (simpleFunctionMatch) {
1538
+ const functionName = simpleFunctionMatch[1];
1539
+ // Find the function reference in current or parent scopes
1540
+ const scopesToCheck = [scopeNode.name, ...scopeNode.tree];
1541
+ for (const scopeName of scopesToCheck) {
1542
+ const checkScope = this.scopeNodes[scopeName];
1543
+ if (!checkScope?.analysis?.isolatedEquivalentVariables) continue;
1544
+
1545
+ const functionRef =
1546
+ checkScope.analysis.isolatedEquivalentVariables[functionName];
1547
+ if (typeof functionRef === 'string' && functionRef.endsWith('F')) {
1548
+ callbackScopeName = functionRef.slice(0, -1);
1549
+ break;
1550
+ }
1551
+ }
1552
+ }
1553
+
1554
+ // Pattern 2: useMemo/useCallback with callback scope
1555
+ // e.g., "useMemo(cyScope1(), [deps]).functionCallReturnValue"
1556
+ if (!callbackScopeName) {
1557
+ const useMemoMatch = equivalentValue.match(
1558
+ /^useMemo\((\w+)\(\),\s*\[.*\]\)\.functionCallReturnValue$/,
1559
+ );
1560
+ if (useMemoMatch) {
1561
+ callbackScopeName = useMemoMatch[1];
1562
+ }
1563
+ }
1564
+
1565
+ if (!callbackScopeName) return;
1566
+
1567
+ const callbackScope = this.scopeNodes[callbackScopeName];
1568
+ if (!callbackScope) return;
1569
+
1570
+ // Look for returnValue.* sub-properties in the callback scope
1571
+ if (!callbackScope.analysis?.isolatedEquivalentVariables) return;
1572
+
1573
+ const isolatedVars = callbackScope.analysis.isolatedEquivalentVariables;
1574
+
1575
+ // First, check if returnValue is an alias to another variable (e.g., returnValue = intermediate)
1576
+ // If so, we need to look for that variable's sub-properties too
1577
+ const returnValueAlias =
1578
+ typeof isolatedVars.returnValue === 'string' &&
1579
+ !isolatedVars.returnValue.includes('.')
1580
+ ? isolatedVars.returnValue
1581
+ : undefined;
1582
+
1583
+ // Pattern 3: Object.keys(X).reduce() - the reduce result has the same sub-properties as X
1584
+ // When returnValue = "Object.keys(source).reduce(...).functionCallReturnValue", look for source.* sub-properties
1585
+ let reduceSourceVar: string | undefined;
1586
+ if (typeof isolatedVars.returnValue === 'string') {
1587
+ const reduceMatch = isolatedVars.returnValue.match(
1588
+ /^Object\.keys\((\w+)\)\.reduce\(.*\)\.functionCallReturnValue$/,
1589
+ );
1590
+ if (reduceMatch) {
1591
+ reduceSourceVar = reduceMatch[1];
1592
+ }
1593
+ }
1594
+
1595
+ for (const [subPath, subValue] of Object.entries(isolatedVars)) {
1596
+ // Check for direct returnValue.* sub-properties
1597
+ const isReturnValueSub =
1598
+ subPath.startsWith('returnValue.') ||
1599
+ subPath.startsWith('returnValue[');
1600
+
1601
+ // Also check for alias.* sub-properties (e.g., intermediate.args when returnValue = intermediate)
1602
+ const isAliasSub =
1603
+ returnValueAlias &&
1604
+ (subPath.startsWith(returnValueAlias + '.') ||
1605
+ subPath.startsWith(returnValueAlias + '['));
1606
+
1607
+ // Also check for reduce source.* sub-properties (e.g., source['Function Arguments'] when returnValue = Object.keys(source).reduce())
1608
+ const isReduceSourceSub =
1609
+ reduceSourceVar &&
1610
+ (subPath.startsWith(reduceSourceVar + '.') ||
1611
+ subPath.startsWith(reduceSourceVar + '['));
1612
+
1613
+ if (
1614
+ typeof subValue !== 'string' ||
1615
+ (!isReturnValueSub && !isAliasSub && !isReduceSourceSub)
1616
+ )
1617
+ continue;
1618
+
1619
+ // Convert alias/reduceSource paths to returnValue paths
1620
+ let effectiveSubPath = subPath;
1621
+ if (isAliasSub && !isReturnValueSub) {
1622
+ // Replace the alias prefix with returnValue
1623
+ effectiveSubPath =
1624
+ 'returnValue' + subPath.substring(returnValueAlias!.length);
1625
+ } else if (isReduceSourceSub && !isReturnValueSub && !isAliasSub) {
1626
+ // Replace the reduce source prefix with returnValue
1627
+ effectiveSubPath =
1628
+ 'returnValue' + subPath.substring(reduceSourceVar!.length);
1629
+ }
1630
+ const subPropertyPath = effectiveSubPath.substring('returnValue'.length);
1631
+ const newPath = cleanPath(path + subPropertyPath, allPaths);
1632
+ let newEquivalentValue = cleanPath(
1633
+ subValue.replace(/::cyDuplicateKey\d+::/g, ''),
1634
+ allPaths,
1635
+ );
1636
+
1637
+ // Resolve variable references through parent scope equivalencies
1638
+ const resolved = this.resolveVariableThroughParentScopes(
1639
+ newEquivalentValue,
1640
+ callbackScope,
1641
+ allPaths,
1642
+ );
1643
+ newEquivalentValue = resolved.resolvedPath;
1644
+ const equivalentScopeName = resolved.scopeName;
1645
+
1646
+ if (!newEquivalentValue || !this.isValidPath(newEquivalentValue))
1647
+ continue;
1648
+
1649
+ this.addEquivalency(
1650
+ newPath,
1651
+ newEquivalentValue,
1652
+ equivalentScopeName,
1653
+ scopeNode,
1654
+ 'propagated function call return sub-property equivalency',
1655
+ );
1656
+
1657
+ // Ensure the database entry has the usage path
1658
+ this.addUsageToEquivalencyDatabaseEntry(
1659
+ newPath,
1660
+ newEquivalentValue,
1661
+ equivalentScopeName,
1662
+ scopeNode.name,
1663
+ );
1664
+ }
1665
+ }
1666
+
1667
+ /**
1668
+ * Resolves a variable path through parent scope equivalencies.
1669
+ *
1670
+ * For example, if the path is "dataStructure.arguments" and the parent scope has
1671
+ * dataStructure -> signature[0].dataStructure, this returns:
1672
+ * { resolvedPath: "signature[0].dataStructure.arguments", scopeName: "ParentScope" }
1673
+ */
1674
+ private resolveVariableThroughParentScopes(
1675
+ path: string | undefined,
1676
+ callbackScope: ScopeNode,
1677
+ allPaths: string[],
1678
+ ): { resolvedPath: string | undefined; scopeName: string } {
1679
+ if (!path)
1680
+ return { resolvedPath: undefined, scopeName: callbackScope.name };
1681
+
1682
+ // Extract the root variable name
1683
+ const dotIndex = path.indexOf('.');
1684
+ const bracketIndex = path.indexOf('[');
1685
+ let firstDelimiter = -1;
1686
+ if (dotIndex > -1 && bracketIndex > -1) {
1687
+ firstDelimiter = Math.min(dotIndex, bracketIndex);
1688
+ } else {
1689
+ firstDelimiter = dotIndex > -1 ? dotIndex : bracketIndex;
1690
+ }
1691
+
1692
+ if (firstDelimiter === -1)
1693
+ return { resolvedPath: path, scopeName: callbackScope.name };
1694
+
1695
+ const rootVar = path.substring(0, firstDelimiter);
1696
+ const restOfPath = path.substring(firstDelimiter);
1697
+
1698
+ // Look in parent scopes for the root variable's equivalency
1699
+ for (const parentScopeName of callbackScope.tree || []) {
1700
+ const parentScope = this.scopeNodes[parentScopeName];
1701
+ if (!parentScope?.analysis?.isolatedEquivalentVariables) continue;
1702
+
1703
+ const rootEquiv =
1704
+ parentScope.analysis.isolatedEquivalentVariables[rootVar];
1705
+ if (typeof rootEquiv === 'string') {
1706
+ return {
1707
+ resolvedPath: cleanPath(rootEquiv + restOfPath, allPaths),
1708
+ scopeName: parentScopeName,
1709
+ };
1710
+ }
1711
+ }
1712
+
1713
+ return { resolvedPath: path, scopeName: callbackScope.name };
1714
+ }
1715
+
1716
+ /**
1717
+ * Adds a usage path to the equivalency database entry that has the given source.
1718
+ *
1719
+ * The addEquivalency call creates the equivalency but doesn't always properly
1720
+ * link the usage in the database, so we need to do it explicitly.
1721
+ */
1722
+ private addUsageToEquivalencyDatabaseEntry(
1723
+ usagePath: string,
1724
+ sourcePath: string,
1725
+ sourceScopeName: string,
1726
+ fallbackScopeName: string,
1727
+ ) {
1728
+ const usageEntry = {
1729
+ scopeNodeName: usagePath.match(/^([^().]+)\(\)/)
1730
+ ? (usagePath.match(/^([^().]+)\(\)/)?.[1] ?? fallbackScopeName)
1731
+ : fallbackScopeName,
1732
+ schemaPath: usagePath,
1733
+ };
1734
+
1735
+ const sourceKey = `${sourceScopeName}::${sourcePath}`;
1736
+ for (const entry of this.equivalencyDatabase) {
1737
+ if (
1738
+ entry.intermediatesOrder[sourceKey] === 0 ||
1739
+ entry.sourceCandidates.some(
1740
+ (sc) =>
1741
+ sc.scopeNodeName === sourceScopeName &&
1742
+ sc.schemaPath === sourcePath,
1743
+ )
1744
+ ) {
1745
+ const usageExists = entry.usages.some(
1746
+ (u) =>
1747
+ u.scopeNodeName === usageEntry.scopeNodeName &&
1748
+ u.schemaPath === usageEntry.schemaPath,
1749
+ );
1750
+ if (!usageExists) {
1751
+ entry.usages.push(usageEntry);
1752
+ }
1753
+ break;
1754
+ }
1755
+ }
1756
+ }
1757
+
1359
1758
  private checkForArrayItemPath(
1360
1759
  pathParts: string[],
1361
1760
  scopeNode: ScopeNode,
@@ -1635,6 +2034,14 @@ export class ScopeDataStructure {
1635
2034
  usageEquivalency.scopeNodeName,
1636
2035
  ) as ScopeNode;
1637
2036
 
2037
+ // Guard against infinite recursion by tracking which paths we've already
2038
+ // added from addComplexSourcePathVariables
2039
+ const complexPathKey = `${usageScopeNode.name}::${newUsageEquivalentPath}`;
2040
+ if (this.complexSourceVisited.has(complexPathKey)) {
2041
+ continue;
2042
+ }
2043
+ this.complexSourceVisited.add(complexPathKey);
2044
+
1638
2045
  this.addToSchema({
1639
2046
  path: newUsageEquivalentPath,
1640
2047
  value: 'unknown',
@@ -1785,6 +2192,7 @@ export class ScopeDataStructure {
1785
2192
 
1786
2193
  for (let i = 0; i < cleanEquivalencyValueChain.length; ++i) {
1787
2194
  const pathInfo = cleanEquivalencyValueChain[i].currentPath;
2195
+ const previousPath = cleanEquivalencyValueChain[i].previousPath;
1788
2196
 
1789
2197
  const schemaPathParts = this.splitPath(pathInfo.schemaPath);
1790
2198
  const isSignaturePath =
@@ -1798,6 +2206,21 @@ export class ScopeDataStructure {
1798
2206
  databaseEntry.usages.push(pathInfo);
1799
2207
  }
1800
2208
 
2209
+ // Also add previousPath as a usage if it matches the criteria
2210
+ // This handles propagated sub-property equivalencies where the JSX prop path
2211
+ // is in previousPath and should be tracked as a usage
2212
+ if (previousPath) {
2213
+ const prevSchemaPathParts = this.splitPath(previousPath.schemaPath);
2214
+ const isPrevSignaturePath =
2215
+ prevSchemaPathParts.findIndex((p) => p.startsWith('signature[')) > 0;
2216
+ if (
2217
+ prevSchemaPathParts[0].startsWith('returnValue') ||
2218
+ isPrevSignaturePath
2219
+ ) {
2220
+ databaseEntry.usages.push(previousPath);
2221
+ }
2222
+ }
2223
+
1801
2224
  const pathId = this.uniqueId(pathInfo);
1802
2225
  let intermediateIndex = cleanEquivalencyValueChain.length - i - 1;
1803
2226
  const existingIntermediateIndex =
@@ -408,17 +408,26 @@ function checkIfObjectOrFunction(path: string, schema: ScopeNode['schema']) {
408
408
  }
409
409
  }
410
410
 
411
- // Methods that are ambiguous - used on both arrays and non-arrays (e.g., router.push, history.pop)
411
+ // Methods that are ambiguous - used on both arrays and non-arrays
412
+ // These methods exist on arrays but also on Map, Set, Headers, FormData, URLSearchParams, etc.
412
413
  // Don't infer array type from these alone without additional evidence
413
- const AMBIGUOUS_ARRAY_METHODS = new Set(['push', 'pop']);
414
+ const AMBIGUOUS_ARRAY_METHODS = new Set([
415
+ 'push',
416
+ 'pop',
417
+ 'entries',
418
+ 'keys',
419
+ 'values',
420
+ 'forEach',
421
+ ]);
414
422
 
415
423
  // Methods that are strongly indicative of arrays - only arrays have these
424
+ // Note: entries, keys, values, forEach are NOT in this list because they also exist
425
+ // on Map, Set, Headers, FormData, URLSearchParams, and other iterable types
416
426
  const STRONG_ARRAY_METHODS = new Set([
417
427
  'map',
418
428
  'filter',
419
429
  'reduce',
420
430
  'reduceRight',
421
- 'forEach',
422
431
  'every',
423
432
  'some',
424
433
  'find',
@@ -429,9 +438,6 @@ const STRONG_ARRAY_METHODS = new Set([
429
438
  'flatMap',
430
439
  'fill',
431
440
  'copyWithin',
432
- 'entries',
433
- 'keys',
434
- 'values',
435
441
  'toReversed',
436
442
  'toSorted',
437
443
  'toSpliced',
@@ -25,8 +25,7 @@ export default async function generateChangesEntityDocumentation({
25
25
 
26
26
  const { completion: documentation, stats } = await completionCall({
27
27
  type: 'entityDocumentation',
28
- systemMessage:
29
- 'You are an expert coder and educator. You think a lot about how people can understand new things, recognizing that it is a mixture of direct facts and numerous examples from different perspectives.',
28
+ systemMessage: SYSTEM_MESSAGE,
30
29
  prompt,
31
30
  model,
32
31
  jsonResponse: false,
@@ -62,3 +61,22 @@ export default async function generateChangesEntityDocumentation({
62
61
 
63
62
  return { documentation, llmCall };
64
63
  }
64
+
65
+ const SYSTEM_MESSAGE = `You are a technical documentation writer updating existing documentation after code changes.
66
+
67
+ ## When to Update
68
+ - If existing documentation is still accurate: respond with exactly "No changes needed"
69
+ - If code changed significantly: provide updated documentation
70
+
71
+ ## Style
72
+ - Be concise—use bullets, not paragraphs
73
+ - Provide diverse examples (no repetitive variations)
74
+ - In Overview, describe intent directly without mentioning the function name
75
+
76
+ ## Required Sections (when updating)
77
+ Return documentation with exactly these markdown headers:
78
+ - ## Overview
79
+ - ## Inputs
80
+ - ## Output
81
+ - ## Examples
82
+ `;