@codeyam/codeyam-cli 0.1.0-staging.9574237 → 0.1.0-staging.a2f381a

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 (392) hide show
  1. package/analyzer-template/.build-info.json +8 -8
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +4 -4
  4. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
  5. package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
  7. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +36 -9
  8. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
  9. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
  10. package/analyzer-template/packages/analyze/index.ts +4 -1
  11. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
  12. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
  13. package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +10 -6
  14. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +9 -12
  15. package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
  16. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
  17. package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +4 -0
  18. package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +4 -0
  19. package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
  20. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +239 -58
  21. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1684 -1462
  22. package/analyzer-template/packages/aws/package.json +6 -6
  23. package/analyzer-template/packages/database/package.json +2 -2
  24. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +25 -15
  25. package/analyzer-template/packages/database/src/lib/loadEntity.ts +19 -8
  26. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  27. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
  28. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  29. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts +4 -1
  30. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts.map +1 -1
  31. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js +5 -5
  32. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js.map +1 -1
  33. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts +3 -1
  34. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  35. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +22 -1
  36. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  37. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +27 -0
  38. package/analyzer-template/project/analyzeFileEntities.ts +26 -0
  39. package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
  40. package/background/src/lib/virtualized/project/analyzeFileEntities.js +22 -0
  41. package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
  42. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
  43. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  44. package/codeyam-cli/src/cli.js +24 -0
  45. package/codeyam-cli/src/cli.js.map +1 -1
  46. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
  47. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
  48. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +71 -0
  49. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
  50. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
  51. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
  52. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js +51 -0
  53. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js.map +1 -0
  54. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js +55 -0
  55. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js.map +1 -0
  56. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +9 -9
  57. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +39 -3
  58. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
  59. package/codeyam-cli/src/commands/editor.js +2497 -467
  60. package/codeyam-cli/src/commands/editor.js.map +1 -1
  61. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
  62. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
  63. package/codeyam-cli/src/commands/editorIsolateArgs.js +25 -0
  64. package/codeyam-cli/src/commands/editorIsolateArgs.js.map +1 -0
  65. package/codeyam-cli/src/commands/init.js +21 -0
  66. package/codeyam-cli/src/commands/init.js.map +1 -1
  67. package/codeyam-cli/src/commands/telemetry.js +37 -0
  68. package/codeyam-cli/src/commands/telemetry.js.map +1 -0
  69. package/codeyam-cli/src/data/designSystems.js +27 -0
  70. package/codeyam-cli/src/data/designSystems.js.map +1 -0
  71. package/codeyam-cli/src/data/techStacks.js +1 -1
  72. package/codeyam-cli/src/utils/__tests__/devServerState.test.js +93 -1
  73. package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -1
  74. package/codeyam-cli/src/utils/__tests__/editorApi.test.js +44 -0
  75. package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -1
  76. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +3174 -1
  77. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  78. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
  79. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
  80. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +70 -0
  81. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -1
  82. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +163 -4
  83. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -1
  84. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js +67 -0
  85. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js.map +1 -0
  86. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +11 -3
  87. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
  88. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +98 -1
  89. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -1
  90. package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js +1108 -0
  91. package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js.map +1 -0
  92. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +190 -0
  93. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
  94. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +344 -7
  95. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
  96. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +134 -1
  97. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
  98. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +294 -2
  99. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
  100. package/codeyam-cli/src/utils/__tests__/envFile.test.js +125 -0
  101. package/codeyam-cli/src/utils/__tests__/envFile.test.js.map +1 -0
  102. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
  103. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
  104. package/codeyam-cli/src/utils/__tests__/handoffContext.test.js +500 -0
  105. package/codeyam-cli/src/utils/__tests__/handoffContext.test.js.map +1 -0
  106. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +16 -1
  107. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -1
  108. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
  109. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
  110. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js +127 -0
  111. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js.map +1 -0
  112. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +57 -0
  113. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -1
  114. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +180 -1
  115. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
  116. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js +84 -0
  117. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js.map +1 -0
  118. package/codeyam-cli/src/utils/__tests__/telemetry.test.js +159 -0
  119. package/codeyam-cli/src/utils/__tests__/telemetry.test.js.map +1 -0
  120. package/codeyam-cli/src/utils/__tests__/testRunner.test.js +216 -0
  121. package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
  122. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +6 -0
  123. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -1
  124. package/codeyam-cli/src/utils/analysisRunner.js +36 -7
  125. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  126. package/codeyam-cli/src/utils/analyzer.js +11 -1
  127. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  128. package/codeyam-cli/src/utils/backgroundServer.js +1 -1
  129. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  130. package/codeyam-cli/src/utils/designSystemShowcase.js +810 -0
  131. package/codeyam-cli/src/utils/designSystemShowcase.js.map +1 -0
  132. package/codeyam-cli/src/utils/devServerState.js +32 -0
  133. package/codeyam-cli/src/utils/devServerState.js.map +1 -1
  134. package/codeyam-cli/src/utils/editorApi.js +16 -0
  135. package/codeyam-cli/src/utils/editorApi.js.map +1 -1
  136. package/codeyam-cli/src/utils/editorAudit.js +649 -10
  137. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  138. package/codeyam-cli/src/utils/editorEntityChangeStatus.js +13 -7
  139. package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -1
  140. package/codeyam-cli/src/utils/editorEntityHelpers.js +18 -3
  141. package/codeyam-cli/src/utils/editorEntityHelpers.js.map +1 -1
  142. package/codeyam-cli/src/utils/editorGuard.js +36 -0
  143. package/codeyam-cli/src/utils/editorGuard.js.map +1 -0
  144. package/codeyam-cli/src/utils/editorPreview.js +5 -3
  145. package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
  146. package/codeyam-cli/src/utils/editorRecapture.js +109 -0
  147. package/codeyam-cli/src/utils/editorRecapture.js.map +1 -0
  148. package/codeyam-cli/src/utils/editorRoadmap.js +574 -0
  149. package/codeyam-cli/src/utils/editorRoadmap.js.map +1 -0
  150. package/codeyam-cli/src/utils/editorScenarioSwitch.js +39 -2
  151. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
  152. package/codeyam-cli/src/utils/editorScenarios.js +181 -17
  153. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
  154. package/codeyam-cli/src/utils/editorSeedAdapter.js +69 -16
  155. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
  156. package/codeyam-cli/src/utils/entityChangeStatus.js +39 -5
  157. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
  158. package/codeyam-cli/src/utils/entityChangeStatus.server.js +31 -0
  159. package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -1
  160. package/codeyam-cli/src/utils/envFile.js +90 -0
  161. package/codeyam-cli/src/utils/envFile.js.map +1 -0
  162. package/codeyam-cli/src/utils/fileWatcher.js +38 -0
  163. package/codeyam-cli/src/utils/fileWatcher.js.map +1 -1
  164. package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
  165. package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
  166. package/codeyam-cli/src/utils/handoffContext.js +257 -0
  167. package/codeyam-cli/src/utils/handoffContext.js.map +1 -0
  168. package/codeyam-cli/src/utils/install-skills.js +41 -6
  169. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  170. package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
  171. package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
  172. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
  173. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
  174. package/codeyam-cli/src/utils/queue/job.js +35 -6
  175. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  176. package/codeyam-cli/src/utils/registerScenarioResult.js +52 -0
  177. package/codeyam-cli/src/utils/registerScenarioResult.js.map +1 -0
  178. package/codeyam-cli/src/utils/scenarioCoverage.js +4 -1
  179. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -1
  180. package/codeyam-cli/src/utils/scenariosManifest.js +66 -2
  181. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
  182. package/codeyam-cli/src/utils/screenshotHash.js +26 -0
  183. package/codeyam-cli/src/utils/screenshotHash.js.map +1 -0
  184. package/codeyam-cli/src/utils/simulationGateMiddleware.js +9 -0
  185. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
  186. package/codeyam-cli/src/utils/techStackConfig.js +38 -0
  187. package/codeyam-cli/src/utils/techStackConfig.js.map +1 -0
  188. package/codeyam-cli/src/utils/techStackConfig.test.js +85 -0
  189. package/codeyam-cli/src/utils/techStackConfig.test.js.map +1 -0
  190. package/codeyam-cli/src/utils/telemetry.js +106 -0
  191. package/codeyam-cli/src/utils/telemetry.js.map +1 -0
  192. package/codeyam-cli/src/utils/telemetryMiddleware.js +22 -0
  193. package/codeyam-cli/src/utils/telemetryMiddleware.js.map +1 -0
  194. package/codeyam-cli/src/utils/testResultCache.js +53 -0
  195. package/codeyam-cli/src/utils/testResultCache.js.map +1 -0
  196. package/codeyam-cli/src/utils/testResultCache.server.js +81 -0
  197. package/codeyam-cli/src/utils/testResultCache.server.js.map +1 -0
  198. package/codeyam-cli/src/utils/testResultCache.server.test.js +187 -0
  199. package/codeyam-cli/src/utils/testResultCache.server.test.js.map +1 -0
  200. package/codeyam-cli/src/utils/testResultCache.test.js +230 -0
  201. package/codeyam-cli/src/utils/testResultCache.test.js.map +1 -0
  202. package/codeyam-cli/src/utils/testRunner.js +193 -1
  203. package/codeyam-cli/src/utils/testRunner.js.map +1 -1
  204. package/codeyam-cli/src/utils/webappDetection.js +4 -2
  205. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  206. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +99 -0
  207. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
  208. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js +119 -1
  209. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js.map +1 -1
  210. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +68 -1
  211. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -1
  212. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +442 -9
  213. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
  214. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +190 -21
  215. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
  216. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js +135 -0
  217. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js.map +1 -0
  218. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +22 -1
  219. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
  220. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  221. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
  222. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
  223. package/codeyam-cli/src/webserver/backgroundServer.js +42 -57
  224. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  225. package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CzTDWkF2.js → CopyButton-DTBZZfSk.js} +1 -1
  226. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-BFbq6iFk.js → EntityItem-BxclONWq.js} +1 -1
  227. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-B6OMi58N.js → EntityTypeIcon-BsnEOJZ_.js} +1 -1
  228. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-DuYodzo1.js → InlineSpinner-ByaELMbv.js} +1 -1
  229. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CXo9EeCl.js → InteractivePreview-6WjVfhxX.js} +2 -2
  230. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-DYCNb2It.js → LibraryFunctionPreview-ChX-Hp7W.js} +1 -1
  231. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CZgY3sxX.js → LogViewer-C-9zQdXg.js} +1 -1
  232. package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-Bs2_Oua4.js +36 -0
  233. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-CnYYwRDw.js → ReportIssueModal-DQsceHVv.js} +1 -1
  234. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CDoF7ZpU.js → SafeScreenshot-DThcm_9M.js} +1 -1
  235. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DrnfvaLL.js → ScenarioViewer-Cl4oOA3A.js} +1 -1
  236. package/codeyam-cli/src/webserver/build/client/assets/Spinner-CIil5-gb.js +34 -0
  237. package/codeyam-cli/src/webserver/build/client/assets/{ViewportInspectBar-DRKR9T0U.js → ViewportInspectBar-BqkA9zyZ.js} +1 -1
  238. package/codeyam-cli/src/webserver/build/client/assets/{_index-ClR-g3tY.js → _index-DnOgyseQ.js} +1 -1
  239. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-DTH6ydEA.js → activity.(_tab)-DqM9hbNE.js} +1 -1
  240. package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-74hnHF59.js → addon-web-links-C58dYPwR.js} +1 -1
  241. package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-B8CYhCO9.js → agent-transcripts-B8NCeOrm.js} +1 -1
  242. package/codeyam-cli/src/webserver/build/client/assets/api.editor-database-verify-l0sNRNKZ.js +1 -0
  243. package/codeyam-cli/src/webserver/build/client/assets/api.editor-github-verify-l0sNRNKZ.js +1 -0
  244. package/codeyam-cli/src/webserver/build/client/assets/api.editor-handoff-l0sNRNKZ.js +1 -0
  245. package/codeyam-cli/src/webserver/build/client/assets/api.editor-hosting-verify-l0sNRNKZ.js +1 -0
  246. package/codeyam-cli/src/webserver/build/client/assets/api.editor-recapture-stale-l0sNRNKZ.js +1 -0
  247. package/codeyam-cli/src/webserver/build/client/assets/api.editor-roadmap-l0sNRNKZ.js +1 -0
  248. package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-scenario-data-l0sNRNKZ.js +1 -0
  249. package/codeyam-cli/src/webserver/build/client/assets/api.editor-schema-l0sNRNKZ.js +1 -0
  250. package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
  251. package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
  252. package/codeyam-cli/src/webserver/build/client/assets/{book-open-CLaoh4ac.js → book-open-BFSIqZgO.js} +1 -1
  253. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-BZ2DZxbW.js → chevron-down-B9fDzFVh.js} +1 -1
  254. package/codeyam-cli/src/webserver/build/client/assets/chunk-UVKPFVEO-Bmq2apuh.js +43 -0
  255. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CT4unAk-.js → circle-check-DLPObLUx.js} +1 -1
  256. package/codeyam-cli/src/webserver/build/client/assets/{copy-zK0B6Nu-.js → copy-DXEmO0TD.js} +1 -1
  257. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-DJB0YQJL.js → createLucideIcon-BwyFiRot.js} +1 -1
  258. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
  259. package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CCKUIm0S.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
  260. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-CkXFP_i-.js → dev.empty-iRhRIFlp.js} +1 -1
  261. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-BZPBzV73.js +1 -0
  262. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DhtVC4aI.js +161 -0
  263. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-C6fEYHrh.js +41 -0
  264. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BqAN7hyG.js → entity._sha._-pc-vc6wO.js} +13 -12
  265. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-BOi8kpwd.js → entity._sha.scenarios._scenarioId.dev-C8AyYgYT.js} +1 -1
  266. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-Dg1NhIms.js → entity._sha.scenarios._scenarioId.fullscreen-DziaVQX1.js} +1 -1
  267. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-CJX6kkkV.js → entity._sha_.create-scenario-BTcpgIpC.js} +1 -1
  268. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BhVjZhKg.js → entity._sha_.edit._scenarioId-D_O_ajfZ.js} +1 -1
  269. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-_gzKltPN.js → entry.client-j1Vi0bco.js} +6 -6
  270. package/codeyam-cli/src/webserver/build/client/assets/{files-CV_17tZS.js → files-kuny2Q_s.js} +1 -1
  271. package/codeyam-cli/src/webserver/build/client/assets/{git-D-YXmMbR.js → git-DgCZPMie.js} +1 -1
  272. package/codeyam-cli/src/webserver/build/client/assets/globals-L-aUIeux.css +1 -0
  273. package/codeyam-cli/src/webserver/build/client/assets/{index-CCrgCshv.js → index-BliGSSpl.js} +1 -1
  274. package/codeyam-cli/src/webserver/build/client/assets/{index-Blo6EK8G.js → index-SqjQKTdH.js} +1 -1
  275. package/codeyam-cli/src/webserver/build/client/assets/{index-BsX0F-9C.js → index-vyrZD2g4.js} +1 -1
  276. package/codeyam-cli/src/webserver/build/client/assets/{labs-Byazq8Pv.js → labs-c3yLxSEp.js} +1 -1
  277. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-DVQ0oHR7.js → loader-circle-D-q28GLF.js} +1 -1
  278. package/codeyam-cli/src/webserver/build/client/assets/manifest-79d0d81a.js +1 -0
  279. package/codeyam-cli/src/webserver/build/client/assets/{memory-b-VmA2Vj.js → memory-CEWIUC4t.js} +1 -1
  280. package/codeyam-cli/src/webserver/build/client/assets/{pause-DGcndCAa.js → pause-BP6fitdh.js} +1 -1
  281. package/codeyam-cli/src/webserver/build/client/assets/root-L2V0jea7.js +80 -0
  282. package/codeyam-cli/src/webserver/build/client/assets/{search-C0Uw0bcK.js → search-BooqacKS.js} +1 -1
  283. package/codeyam-cli/src/webserver/build/client/assets/{settings-OoNgHIfW.js → settings-BM0nbryO.js} +1 -1
  284. package/codeyam-cli/src/webserver/build/client/assets/{simulations-Bcemfu8a.js → simulations-ovy6FjRY.js} +1 -1
  285. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BgMmG7R9.js → terminal-DHemCJIs.js} +1 -1
  286. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-Cs87hJYK.js → triangle-alert-D87ekDl8.js} +1 -1
  287. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-BR3Rs7JY.js → useCustomSizes-Dk0Tciqg.js} +1 -1
  288. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C8QvIe05.js +2 -0
  289. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-BermyNU5.js → useReportContext-jkCytuYz.js} +1 -1
  290. package/codeyam-cli/src/webserver/build/client/assets/{useToast-a_QN_W9_.js → useToast-BgqkixU9.js} +1 -1
  291. package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-QgInFGdU.js +16 -0
  292. package/codeyam-cli/src/webserver/build/server/assets/{index-CHSrVJtC.js → index-zblh9auj.js} +1 -1
  293. package/codeyam-cli/src/webserver/build/server/assets/init-DaE0CBjk.js +14 -0
  294. package/codeyam-cli/src/webserver/build/server/assets/server-build-CNvgz1cC.js +853 -0
  295. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  296. package/codeyam-cli/src/webserver/build-info.json +5 -5
  297. package/codeyam-cli/src/webserver/editorProxy.js +388 -26
  298. package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
  299. package/codeyam-cli/src/webserver/idleDetector.js +65 -8
  300. package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
  301. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +53 -0
  302. package/codeyam-cli/src/webserver/server.js +151 -14
  303. package/codeyam-cli/src/webserver/server.js.map +1 -1
  304. package/codeyam-cli/src/webserver/terminalServer.js +253 -41
  305. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  306. package/codeyam-cli/templates/__tests__/editor-step-hook.prompt-capture.test.ts +118 -0
  307. package/codeyam-cli/templates/codeyam-editor-claude.md +2 -0
  308. package/codeyam-cli/templates/codeyam-editor-codex.md +61 -0
  309. package/codeyam-cli/templates/codeyam-editor-gemini.md +59 -0
  310. package/codeyam-cli/templates/codeyam-editor-reference.md +216 -0
  311. package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
  312. package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
  313. package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
  314. package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
  315. package/codeyam-cli/templates/editor-step-hook.py +93 -46
  316. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +204 -5
  317. package/codeyam-cli/templates/expo-react-native/__tests__/.gitkeep +0 -0
  318. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +6 -3
  319. package/codeyam-cli/templates/expo-react-native/app/index.tsx +36 -0
  320. package/codeyam-cli/templates/expo-react-native/app.json +11 -0
  321. package/codeyam-cli/templates/expo-react-native/babel.config.js +1 -0
  322. package/codeyam-cli/templates/expo-react-native/gitignore +2 -0
  323. package/codeyam-cli/templates/expo-react-native/global.css +7 -0
  324. package/codeyam-cli/templates/expo-react-native/lib/theme.ts +73 -0
  325. package/codeyam-cli/templates/expo-react-native/package.json +32 -16
  326. package/codeyam-cli/templates/expo-react-native/patches/expo-modules-autolinking+3.0.24.patch +29 -0
  327. package/codeyam-cli/templates/isolation-route/expo-router.tsx.template +54 -0
  328. package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +1 -0
  329. package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +1 -1
  330. package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +47 -34
  331. package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +1 -1
  332. package/codeyam-cli/templates/seed-adapters/supabase.ts +271 -78
  333. package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +34 -1
  334. package/package.json +2 -1
  335. package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
  336. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  337. package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
  338. package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
  339. package/packages/ai/src/lib/astScopes/paths.js +12 -3
  340. package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
  341. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +27 -10
  342. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  343. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
  344. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
  345. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
  346. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  347. package/packages/analyze/index.js +1 -1
  348. package/packages/analyze/index.js.map +1 -1
  349. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
  350. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  351. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
  352. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  353. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +3 -2
  354. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
  355. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +9 -7
  356. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  357. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
  358. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
  359. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
  360. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  361. package/packages/analyze/src/lib/files/analyzeChange.js +1 -0
  362. package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
  363. package/packages/analyze/src/lib/files/analyzeInitial.js +1 -0
  364. package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
  365. package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
  366. package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
  367. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +120 -28
  368. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  369. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1368 -1193
  370. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  371. package/packages/database/src/lib/loadAnalysis.js +7 -1
  372. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  373. package/packages/database/src/lib/loadEntity.js +5 -5
  374. package/packages/database/src/lib/loadEntity.js.map +1 -1
  375. package/packages/utils/src/lib/fs/rsyncCopy.js +22 -1
  376. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  377. package/codeyam-cli/src/webserver/build/client/assets/Spinner-Df3UCi8k.js +0 -34
  378. package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-BBXArFPl.js +0 -43
  379. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +0 -1
  380. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-DPw7NZHc.js +0 -1
  381. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-Dmg9cGK3.js +0 -58
  382. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-DBa7T2FK.js +0 -41
  383. package/codeyam-cli/src/webserver/build/client/assets/globals-Bqg9V6XV.css +0 -1
  384. package/codeyam-cli/src/webserver/build/client/assets/manifest-422a3551.js +0 -1
  385. package/codeyam-cli/src/webserver/build/client/assets/root-ue8uWVRS.js +0 -67
  386. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-BxxP_XF9.js +0 -2
  387. package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-DXQyOV0G.js +0 -13
  388. package/codeyam-cli/src/webserver/build/server/assets/init-DL8vWZ6m.js +0 -10
  389. package/codeyam-cli/src/webserver/build/server/assets/server-build-BUKVjBSZ.js +0 -501
  390. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +0 -33
  391. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +0 -12
  392. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +0 -12
@@ -3,7 +3,7 @@ import os from 'os';
3
3
  import path from 'path';
4
4
  import Database from 'better-sqlite3';
5
5
  import { Kysely, SqliteDialect } from 'kysely';
6
- import { deduplicateByName, generateScenarioSlug, convertIsoToSqliteTimestamp, determineCaptureUrl, resolvePreviewNavPath, clearEditorState, clearEditorUserPrompt, readDefaultScreenSize, readScreenSizes, resolveScenarioViewport, resolveViewportWithProjectDefault, upsertEditorScenario, cleanupScenarioFiles, readPreservedConfigProperties, validateStepTransition, slugifyDimension, isRowInFeatureSession, backfillEntityShaOnScenarios, countScenariosNeedingEntityBackfill, validateEntityLinkageForAppScenario, } from "../editorScenarios.js";
6
+ import { deduplicateByName, generateScenarioSlug, convertIsoToSqliteTimestamp, determineCaptureUrl, resolvePreviewNavPath, clearEditorState, clearEditorUserPrompt, readDefaultScreenSize, readScreenSizes, resolveScenarioViewport, resolveViewportWithProjectDefault, upsertEditorScenario, cleanupScenarioFiles, readPreservedConfigProperties, validateStepTransition, slugifyDimension, isRowInFeatureSession, backfillEntityShaOnScenarios, countScenariosNeedingEntityBackfill, validateEntityLinkageForAppScenario, validateScenarioCategorization, resolveSeedFrom, } from "../editorScenarios.js";
7
7
  describe('editorScenarios', () => {
8
8
  describe('deduplicateByName', () => {
9
9
  it('should keep only the last item for each key', () => {
@@ -1009,6 +1009,26 @@ describe('editorScenarios', () => {
1009
1009
  expect(err).not.toBeNull();
1010
1010
  expect(err).toContain('step 14');
1011
1011
  });
1012
+ it('should reject rapid-fire advance when step started < 3s ago', () => {
1013
+ const recentStart = new Date(Date.now() - 1000).toISOString(); // 1s ago
1014
+ const err = validateStepTransition(4, 3, recentStart);
1015
+ expect(err).not.toBeNull();
1016
+ expect(err).toContain('only 1s ago');
1017
+ expect(err).toContain('checklist');
1018
+ });
1019
+ it('should allow advance when step started > 3s ago', () => {
1020
+ const oldStart = new Date(Date.now() - 5000).toISOString(); // 5s ago
1021
+ expect(validateStepTransition(4, 3, oldStart)).toBeNull();
1022
+ });
1023
+ it('should not enforce time guard on step 1 → 2 transition', () => {
1024
+ const recentStart = new Date(Date.now() - 2000).toISOString();
1025
+ // currentStep=1, so guard only applies for currentStep >= 2
1026
+ expect(validateStepTransition(2, 1, recentStart)).toBeNull();
1027
+ });
1028
+ it('should not enforce time guard when re-running the same step', () => {
1029
+ const recentStart = new Date(Date.now() - 2000).toISOString();
1030
+ expect(validateStepTransition(5, 5, recentStart)).toBeNull();
1031
+ });
1012
1032
  });
1013
1033
  describe('isRowInFeatureSession', () => {
1014
1034
  const featureStart = '2026-03-12 14:01:31';
@@ -1238,24 +1258,41 @@ describe('editorScenarios', () => {
1238
1258
  // display_name derived from page_file_path via routeDisplayName(buildRoutePattern())
1239
1259
  expect(row.display_name).toBe('Feedback');
1240
1260
  });
1241
- it('should skip scenarios that already have entity_sha', async () => {
1261
+ it('should update scenarios with stale entity_sha to latest', async () => {
1262
+ // Margo bug: entity code changes create new versions with new SHAs,
1263
+ // but scenarios still point to the old SHA. Since journals preserve
1264
+ // screenshots and everything is in git, we always want scenarios
1265
+ // pointing to the latest entity version.
1242
1266
  rawDb
1243
1267
  .prepare(`INSERT INTO editor_scenarios (id, project_id, name, component_name, component_path, url, type, viewport_width, viewport_height, entity_sha, display_name)
1244
1268
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1245
- .run('sc-3', projectId, 'Header - Dark', 'Header', 'src/components/Header.tsx', '/isolated-components/Header', 'component', 1280, 720, 'existing-sha', 'Header');
1269
+ .run('sc-3', projectId, 'Header - Dark', 'Header', 'src/components/Header.tsx', '/isolated-components/Header', 'component', 1280, 720, 'old-sha', 'Header');
1246
1270
  const result = await backfillEntityShaOnScenarios(db, [
1247
1271
  {
1248
- sha: 'new-sha',
1272
+ sha: 'latest-sha',
1249
1273
  name: 'Header',
1250
1274
  filePath: 'src/components/Header.tsx',
1251
1275
  },
1252
1276
  ]);
1253
- expect(result.updated).toBe(0);
1254
- // Should not have changed the existing sha
1277
+ expect(result.updated).toBe(1);
1255
1278
  const row = rawDb
1256
1279
  .prepare('SELECT entity_sha FROM editor_scenarios WHERE id = ?')
1257
1280
  .get('sc-3');
1258
- expect(row.entity_sha).toBe('existing-sha');
1281
+ expect(row.entity_sha).toBe('latest-sha');
1282
+ });
1283
+ it('should not update scenarios already pointing to the latest SHA', async () => {
1284
+ rawDb
1285
+ .prepare(`INSERT INTO editor_scenarios (id, project_id, name, component_name, component_path, url, type, viewport_width, viewport_height, entity_sha, display_name)
1286
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1287
+ .run('sc-3b', projectId, 'Header - Dark', 'Header', 'src/components/Header.tsx', '/isolated-components/Header', 'component', 1280, 720, 'current-sha', 'Header');
1288
+ const result = await backfillEntityShaOnScenarios(db, [
1289
+ {
1290
+ sha: 'current-sha',
1291
+ name: 'Header',
1292
+ filePath: 'src/components/Header.tsx',
1293
+ },
1294
+ ]);
1295
+ expect(result.updated).toBe(0);
1259
1296
  });
1260
1297
  it('should skip scenarios with no matching entity', async () => {
1261
1298
  rawDb
@@ -1276,6 +1313,117 @@ describe('editorScenarios', () => {
1276
1313
  .get('sc-4');
1277
1314
  expect(row.entity_sha).toBeNull();
1278
1315
  });
1316
+ it('should match component scenarios by name+path, not just path (multi-entity files)', async () => {
1317
+ // A single file can export multiple components (e.g., FullPageLibrary.tsx
1318
+ // exports FullPageLibrary, FullPageEmptyState, FullPageArticleCard).
1319
+ // Each component scenario should get the SHA for its specific entity,
1320
+ // not whichever entity happens to be last in the map.
1321
+ rawDb
1322
+ .prepare(`INSERT INTO editor_scenarios (id, project_id, name, component_name, component_path, url, type, viewport_width, viewport_height, entity_sha)
1323
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1324
+ .run('sc-fplib', projectId, 'FullPageLibrary - Default', 'FullPageLibrary', 'src/library/FullPageLibrary.tsx', '/isolated-components/FullPageLibrary', 'component', 1280, 720, 'old-fplib-sha');
1325
+ rawDb
1326
+ .prepare(`INSERT INTO editor_scenarios (id, project_id, name, component_name, component_path, url, type, viewport_width, viewport_height, entity_sha)
1327
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1328
+ .run('sc-fpempty', projectId, 'FullPageEmptyState - Default', 'FullPageEmptyState', 'src/library/FullPageLibrary.tsx', '/isolated-components/FullPageEmptyState', 'component', 1280, 720, 'old-fpempty-sha');
1329
+ const result = await backfillEntityShaOnScenarios(db, [
1330
+ {
1331
+ sha: 'new-fplib-sha',
1332
+ name: 'FullPageLibrary',
1333
+ filePath: 'src/library/FullPageLibrary.tsx',
1334
+ },
1335
+ {
1336
+ sha: 'new-fpempty-sha',
1337
+ name: 'FullPageEmptyState',
1338
+ filePath: 'src/library/FullPageLibrary.tsx',
1339
+ },
1340
+ ]);
1341
+ expect(result.updated).toBe(2);
1342
+ const fplib = rawDb
1343
+ .prepare('SELECT entity_sha FROM editor_scenarios WHERE id = ?')
1344
+ .get('sc-fplib');
1345
+ expect(fplib.entity_sha).toBe('new-fplib-sha');
1346
+ const fpempty = rawDb
1347
+ .prepare('SELECT entity_sha FROM editor_scenarios WHERE id = ?')
1348
+ .get('sc-fpempty');
1349
+ expect(fpempty.entity_sha).toBe('new-fpempty-sha');
1350
+ });
1351
+ it('should prefer default export entity for page scenarios when file has multiple entities', async () => {
1352
+ // Bug: src/popup/App.tsx has multiple entities (App visual, getInitialView library,
1353
+ // View type). Page scenarios should link to the default export (App), not whichever
1354
+ // entity happens to come first in the array.
1355
+ rawDb
1356
+ .prepare(`INSERT INTO editor_scenarios (id, project_id, name, page_file_path, url, type, viewport_width, viewport_height)
1357
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
1358
+ .run('sc-page-1', projectId, 'Save View - First Time User', 'src/popup/App.tsx', '/', 'application', 400, 600);
1359
+ // Pass multiple entities for the same file — default export should win
1360
+ // regardless of order. Here the default export (App) appears first but
1361
+ // gets overwritten by later non-default entities in the naive set() impl.
1362
+ const result = await backfillEntityShaOnScenarios(db, [
1363
+ {
1364
+ sha: 'app-sha',
1365
+ name: 'App',
1366
+ filePath: 'src/popup/App.tsx',
1367
+ isDefaultExport: true,
1368
+ },
1369
+ {
1370
+ sha: 'get-initial-view-sha',
1371
+ name: 'getInitialView',
1372
+ filePath: 'src/popup/App.tsx',
1373
+ isDefaultExport: false,
1374
+ },
1375
+ {
1376
+ sha: 'view-type-sha',
1377
+ name: 'View',
1378
+ filePath: 'src/popup/App.tsx',
1379
+ isDefaultExport: false,
1380
+ },
1381
+ ]);
1382
+ expect(result.updated).toBe(1);
1383
+ const row = rawDb
1384
+ .prepare('SELECT entity_sha FROM editor_scenarios WHERE id = ?')
1385
+ .get('sc-page-1');
1386
+ expect(row.entity_sha).toBe('app-sha');
1387
+ });
1388
+ it('should update page scenario to latest entity version when multiple versions exist', async () => {
1389
+ // Real-world bug: App.tsx entity gets versioned (code changes create new SHAs).
1390
+ // The scenario points to the oldest version's SHA. When sync receives all 3
1391
+ // versions of the same default-export entity, it should update the scenario
1392
+ // to the LATEST version, not keep it stuck on the oldest.
1393
+ rawDb
1394
+ .prepare(`INSERT INTO editor_scenarios (id, project_id, name, page_file_path, url, type, viewport_width, viewport_height, entity_sha, display_name)
1395
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1396
+ .run('sc-home', projectId, 'Welcome Screen — First Install', 'src/popup/App.tsx', '/', 'application', 400, 600, 'version-1-sha', // stale — points to oldest version
1397
+ 'Home');
1398
+ // Pass all 3 versions — all default exports for the same file.
1399
+ // The sync should pick the LAST one (latest) since callers pass
1400
+ // entities in creation order.
1401
+ const result = await backfillEntityShaOnScenarios(db, [
1402
+ {
1403
+ sha: 'version-1-sha',
1404
+ name: 'App',
1405
+ filePath: 'src/popup/App.tsx',
1406
+ isDefaultExport: true,
1407
+ },
1408
+ {
1409
+ sha: 'version-2-sha',
1410
+ name: 'App',
1411
+ filePath: 'src/popup/App.tsx',
1412
+ isDefaultExport: true,
1413
+ },
1414
+ {
1415
+ sha: 'version-3-sha',
1416
+ name: 'App',
1417
+ filePath: 'src/popup/App.tsx',
1418
+ isDefaultExport: true,
1419
+ },
1420
+ ]);
1421
+ expect(result.updated).toBe(1);
1422
+ const row = rawDb
1423
+ .prepare('SELECT entity_sha FROM editor_scenarios WHERE id = ?')
1424
+ .get('sc-home');
1425
+ expect(row.entity_sha).toBe('version-3-sha');
1426
+ });
1279
1427
  });
1280
1428
  describe('countScenariosNeedingEntityBackfill', () => {
1281
1429
  let db;
@@ -1427,5 +1575,194 @@ describe('editorScenarios', () => {
1427
1575
  expect(result.error).toContain('No glossary entry found');
1428
1576
  });
1429
1577
  });
1578
+ describe('validateScenarioCategorization', () => {
1579
+ it('should reject componentName with non-isolation URL', () => {
1580
+ const result = validateScenarioCategorization({
1581
+ componentName: 'Library',
1582
+ url: '/library',
1583
+ });
1584
+ expect(result.valid).toBe(false);
1585
+ expect(result.error).toBeDefined();
1586
+ expect(result.error).toContain('componentName');
1587
+ });
1588
+ it('should accept componentName with /isolated-components/ URL', () => {
1589
+ const result = validateScenarioCategorization({
1590
+ componentName: 'Library',
1591
+ url: '/isolated-components/Library?s=Default',
1592
+ });
1593
+ expect(result.valid).toBe(true);
1594
+ });
1595
+ it('should accept componentName with /codeyam-isolate/ URL', () => {
1596
+ const result = validateScenarioCategorization({
1597
+ componentName: 'Library',
1598
+ url: '/codeyam-isolate/Library?s=Default',
1599
+ });
1600
+ expect(result.valid).toBe(true);
1601
+ });
1602
+ it('should accept application scenario without componentName', () => {
1603
+ const result = validateScenarioCategorization({
1604
+ url: '/library',
1605
+ type: 'application',
1606
+ });
1607
+ expect(result.valid).toBe(true);
1608
+ });
1609
+ it('should accept component with no URL', () => {
1610
+ const result = validateScenarioCategorization({
1611
+ componentName: 'Library',
1612
+ url: null,
1613
+ });
1614
+ expect(result.valid).toBe(true);
1615
+ });
1616
+ it('should suggest both fixes in error message', () => {
1617
+ const result = validateScenarioCategorization({
1618
+ componentName: 'Library',
1619
+ url: '/library',
1620
+ });
1621
+ expect(result.valid).toBe(false);
1622
+ // Should suggest changing URL to isolation route
1623
+ expect(result.error).toContain('/isolated-components/');
1624
+ // Should suggest removing componentName
1625
+ expect(result.error).toContain('remove');
1626
+ });
1627
+ });
1628
+ describe('resolveSeedFrom', () => {
1629
+ let tmpDir;
1630
+ let db;
1631
+ beforeEach(() => {
1632
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'seedfrom-'));
1633
+ fs.mkdirSync(path.join(tmpDir, '.codeyam', 'editor-scenarios'), {
1634
+ recursive: true,
1635
+ });
1636
+ const raw = new Database(':memory:');
1637
+ raw.exec(`
1638
+ CREATE TABLE editor_scenarios (
1639
+ id TEXT PRIMARY KEY,
1640
+ project_id TEXT,
1641
+ name TEXT,
1642
+ description TEXT,
1643
+ component_name TEXT,
1644
+ component_path TEXT,
1645
+ url TEXT,
1646
+ type TEXT,
1647
+ screenshot_path TEXT,
1648
+ viewport_width INTEGER,
1649
+ viewport_height INTEGER,
1650
+ dimensions TEXT,
1651
+ screenshot_paths TEXT,
1652
+ page_file_path TEXT,
1653
+ entity_sha TEXT,
1654
+ display_name TEXT,
1655
+ created_at TEXT DEFAULT (datetime('now')),
1656
+ updated_at TEXT DEFAULT (datetime('now'))
1657
+ )
1658
+ `);
1659
+ db = new Kysely({ dialect: new SqliteDialect({ database: raw }) });
1660
+ });
1661
+ afterEach(() => {
1662
+ fs.rmSync(tmpDir, { recursive: true, force: true });
1663
+ });
1664
+ it('should resolve seed data by scenario ID', async () => {
1665
+ const scenarioId = 'aaaa-bbbb-cccc-dddd';
1666
+ const seedData = { article: [{ id: '1', title: 'Test' }] };
1667
+ // Write the seed file
1668
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.seed.json`), JSON.stringify(seedData));
1669
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1670
+ expect(result).toEqual(seedData);
1671
+ });
1672
+ it('should resolve seed data by scenario name', async () => {
1673
+ const scenarioId = 'eeee-ffff-1111-2222';
1674
+ const seedData = { user: [{ id: '1', name: 'Alice' }] };
1675
+ // Write the seed file
1676
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.seed.json`), JSON.stringify(seedData));
1677
+ // Insert scenario into DB so name lookup works
1678
+ await db
1679
+ .insertInto('editor_scenarios')
1680
+ .values({
1681
+ id: scenarioId,
1682
+ project_id: 'proj-1',
1683
+ name: 'Library - Rich Data',
1684
+ viewport_width: 1280,
1685
+ viewport_height: 720,
1686
+ })
1687
+ .execute();
1688
+ const result = await resolveSeedFrom(tmpDir, db, 'Library - Rich Data');
1689
+ expect(result).toEqual(seedData);
1690
+ });
1691
+ it('should fall back to seed from scenario data file when no .seed.json exists', async () => {
1692
+ const scenarioId = 'cccc-dddd-eeee-ffff';
1693
+ const seedData = { tag: [{ id: '1', name: 'AI' }] };
1694
+ // Write the scenario data file (not the .seed.json)
1695
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.json`), JSON.stringify({ seed: seedData, _metadata: { name: 'Test' } }));
1696
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1697
+ expect(result).toEqual(seedData);
1698
+ });
1699
+ it('should return null when scenario not found', async () => {
1700
+ const result = await resolveSeedFrom(tmpDir, db, 'nonexistent');
1701
+ expect(result).toBeNull();
1702
+ });
1703
+ it('should return null when scenario exists but has no seed data', async () => {
1704
+ const scenarioId = 'no-seed-1111-2222';
1705
+ // Scenario data file with no seed
1706
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.json`), JSON.stringify({ _metadata: { name: 'No Seed' } }));
1707
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1708
+ expect(result).toBeNull();
1709
+ });
1710
+ it('should return null when seed.json contains invalid JSON', async () => {
1711
+ const scenarioId = 'bad-json-1111';
1712
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.seed.json`), '{ this is not valid json }}}');
1713
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1714
+ expect(result).toBeNull();
1715
+ });
1716
+ it('should return null when scenario data file contains invalid JSON', async () => {
1717
+ const scenarioId = 'bad-data-2222';
1718
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.json`), 'not json at all');
1719
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1720
+ expect(result).toBeNull();
1721
+ });
1722
+ it('should pick the most recent scenario when multiple share the same name', async () => {
1723
+ const oldId = 'old-scenario-1111';
1724
+ const newId = 'new-scenario-2222';
1725
+ const oldSeed = { article: [{ id: '1', title: 'Old' }] };
1726
+ const newSeed = { article: [{ id: '2', title: 'New' }] };
1727
+ // Write seed files for both
1728
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${oldId}.seed.json`), JSON.stringify(oldSeed));
1729
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${newId}.seed.json`), JSON.stringify(newSeed));
1730
+ // Insert both with the same name, different created_at
1731
+ await db
1732
+ .insertInto('editor_scenarios')
1733
+ .values({
1734
+ id: oldId,
1735
+ project_id: 'proj-1',
1736
+ name: 'Shared Name',
1737
+ viewport_width: 1280,
1738
+ viewport_height: 720,
1739
+ created_at: '2026-01-01 00:00:00',
1740
+ })
1741
+ .execute();
1742
+ await db
1743
+ .insertInto('editor_scenarios')
1744
+ .values({
1745
+ id: newId,
1746
+ project_id: 'proj-1',
1747
+ name: 'Shared Name',
1748
+ viewport_width: 1280,
1749
+ viewport_height: 720,
1750
+ created_at: '2026-03-01 00:00:00',
1751
+ })
1752
+ .execute();
1753
+ const result = await resolveSeedFrom(tmpDir, db, 'Shared Name');
1754
+ expect(result).toEqual(newSeed);
1755
+ });
1756
+ it('should prefer .seed.json over inline seed in data file', async () => {
1757
+ const scenarioId = 'prefer-seed-file';
1758
+ const seedFileData = { article: [{ id: '1', title: 'From seed file' }] };
1759
+ const inlineData = { article: [{ id: '2', title: 'From inline' }] };
1760
+ // Write both files
1761
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.seed.json`), JSON.stringify(seedFileData));
1762
+ fs.writeFileSync(path.join(tmpDir, '.codeyam', 'editor-scenarios', `${scenarioId}.json`), JSON.stringify({ seed: inlineData }));
1763
+ const result = await resolveSeedFrom(tmpDir, db, scenarioId);
1764
+ expect(result).toEqual(seedFileData);
1765
+ });
1766
+ });
1430
1767
  });
1431
1768
  //# sourceMappingURL=editorScenarios.test.js.map