@codeyam/codeyam-cli 0.1.0-staging.ad88eeb → 0.1.0-staging.afbbaae

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 (516) 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 +6 -6
  4. package/analyzer-template/packages/ai/package.json +1 -1
  5. package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
  6. package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
  7. package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
  8. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +36 -9
  9. package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.ts +10 -3
  10. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +16 -6
  11. package/analyzer-template/packages/analyze/index.ts +4 -1
  12. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +28 -2
  13. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +5 -36
  14. package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +10 -6
  15. package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +9 -12
  16. package/analyzer-template/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.ts +21 -0
  17. package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +82 -10
  18. package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +4 -0
  19. package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +4 -0
  20. package/analyzer-template/packages/analyze/src/lib/files/analyzeNextRoute.ts +8 -3
  21. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +239 -58
  22. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1684 -1462
  23. package/analyzer-template/packages/aws/package.json +7 -7
  24. package/analyzer-template/packages/database/package.json +3 -3
  25. package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +82 -0
  26. package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +25 -15
  27. package/analyzer-template/packages/database/src/lib/loadEntities.ts +0 -6
  28. package/analyzer-template/packages/database/src/lib/loadEntity.ts +19 -8
  29. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +0 -65
  30. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +5 -0
  31. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -1
  32. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +84 -0
  33. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  34. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
  35. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
  36. package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
  37. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  38. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +0 -6
  39. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  40. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts +4 -1
  41. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.d.ts.map +1 -1
  42. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js +5 -5
  43. package/analyzer-template/packages/github/dist/database/src/lib/loadEntity.js.map +1 -1
  44. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  45. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +0 -25
  46. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  47. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts +3 -1
  48. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  49. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +22 -1
  50. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  51. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +27 -0
  52. package/analyzer-template/project/analyzeFileEntities.ts +26 -0
  53. package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
  54. package/background/src/lib/virtualized/project/analyzeFileEntities.js +22 -0
  55. package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
  56. package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
  57. package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
  58. package/codeyam-cli/src/cli.js +24 -0
  59. package/codeyam-cli/src/cli.js.map +1 -1
  60. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
  61. package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
  62. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +71 -0
  63. package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -0
  64. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
  65. package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
  66. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js +51 -0
  67. package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js.map +1 -0
  68. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js +55 -0
  69. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js.map +1 -0
  70. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +56 -0
  71. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
  72. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +137 -47
  73. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
  74. package/codeyam-cli/src/commands/editor.js +4254 -656
  75. package/codeyam-cli/src/commands/editor.js.map +1 -1
  76. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
  77. package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
  78. package/codeyam-cli/src/commands/editorIsolateArgs.js +25 -0
  79. package/codeyam-cli/src/commands/editorIsolateArgs.js.map +1 -0
  80. package/codeyam-cli/src/commands/init.js +89 -34
  81. package/codeyam-cli/src/commands/init.js.map +1 -1
  82. package/codeyam-cli/src/commands/telemetry.js +37 -0
  83. package/codeyam-cli/src/commands/telemetry.js.map +1 -0
  84. package/codeyam-cli/src/data/designSystems.js +27 -0
  85. package/codeyam-cli/src/data/designSystems.js.map +1 -0
  86. package/codeyam-cli/src/data/techStacks.js +3 -8
  87. package/codeyam-cli/src/data/techStacks.js.map +1 -1
  88. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +173 -0
  89. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
  90. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js +46 -0
  91. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js.map +1 -0
  92. package/codeyam-cli/src/utils/__tests__/devServerState.test.js +93 -1
  93. package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -1
  94. package/codeyam-cli/src/utils/__tests__/editorApi.test.js +62 -8
  95. package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -1
  96. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +3526 -1
  97. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  98. package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js +76 -0
  99. package/codeyam-cli/src/utils/__tests__/editorBroadcastViewport.test.js.map +1 -0
  100. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
  101. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
  102. package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js +100 -0
  103. package/codeyam-cli/src/utils/__tests__/editorDeleteScenario.test.js.map +1 -0
  104. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js +27 -2
  105. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js.map +1 -1
  106. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +76 -3
  107. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -1
  108. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +381 -0
  109. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -0
  110. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js +67 -0
  111. package/codeyam-cli/src/utils/__tests__/editorGuardMiddleware.test.js.map +1 -0
  112. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js +202 -1
  113. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js.map +1 -1
  114. package/codeyam-cli/src/utils/__tests__/editorMigration.test.js +435 -0
  115. package/codeyam-cli/src/utils/__tests__/editorMigration.test.js.map +1 -0
  116. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +96 -1
  117. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
  118. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +144 -1
  119. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -1
  120. package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js +1108 -0
  121. package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js.map +1 -0
  122. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +190 -0
  123. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
  124. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +1548 -1
  125. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
  126. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +201 -1
  127. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
  128. package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js +143 -0
  129. package/codeyam-cli/src/utils/__tests__/editorSeedAdapterPrismaValidation.test.js.map +1 -0
  130. package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js +66 -0
  131. package/codeyam-cli/src/utils/__tests__/editorSessionFilter.test.js.map +1 -0
  132. package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js +53 -0
  133. package/codeyam-cli/src/utils/__tests__/editorShouldRevalidate.test.js.map +1 -0
  134. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +395 -11
  135. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
  136. package/codeyam-cli/src/utils/__tests__/envFile.test.js +125 -0
  137. package/codeyam-cli/src/utils/__tests__/envFile.test.js.map +1 -0
  138. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
  139. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
  140. package/codeyam-cli/src/utils/__tests__/handoffContext.test.js +500 -0
  141. package/codeyam-cli/src/utils/__tests__/handoffContext.test.js.map +1 -0
  142. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +16 -1
  143. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -1
  144. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js +302 -0
  145. package/codeyam-cli/src/utils/__tests__/manualEntityAnalysis.test.js.map +1 -0
  146. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js +30 -2
  147. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js.map +1 -1
  148. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js +127 -0
  149. package/codeyam-cli/src/utils/__tests__/registerScenarioResult.test.js.map +1 -0
  150. package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js +118 -0
  151. package/codeyam-cli/src/utils/__tests__/routePatternMatching.test.js.map +1 -0
  152. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +284 -0
  153. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -0
  154. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +649 -223
  155. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
  156. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js +84 -0
  157. package/codeyam-cli/src/utils/__tests__/screenshotHash.test.js.map +1 -0
  158. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +1 -0
  159. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  160. package/codeyam-cli/src/utils/__tests__/telemetry.test.js +159 -0
  161. package/codeyam-cli/src/utils/__tests__/telemetry.test.js.map +1 -0
  162. package/codeyam-cli/src/utils/__tests__/testRunner.test.js +216 -0
  163. package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -0
  164. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +6 -0
  165. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -1
  166. package/codeyam-cli/src/utils/analysisRunner.js +39 -8
  167. package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
  168. package/codeyam-cli/src/utils/analyzer.js +19 -0
  169. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  170. package/codeyam-cli/src/utils/analyzerFinalization.js +100 -0
  171. package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
  172. package/codeyam-cli/src/utils/backgroundServer.js +93 -17
  173. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  174. package/codeyam-cli/src/utils/database.js +37 -2
  175. package/codeyam-cli/src/utils/database.js.map +1 -1
  176. package/codeyam-cli/src/utils/designSystemShowcase.js +810 -0
  177. package/codeyam-cli/src/utils/designSystemShowcase.js.map +1 -0
  178. package/codeyam-cli/src/utils/devServerState.js +32 -0
  179. package/codeyam-cli/src/utils/devServerState.js.map +1 -1
  180. package/codeyam-cli/src/utils/editorApi.js +27 -5
  181. package/codeyam-cli/src/utils/editorApi.js.map +1 -1
  182. package/codeyam-cli/src/utils/editorAudit.js +700 -10
  183. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  184. package/codeyam-cli/src/utils/editorBroadcastViewport.js +26 -0
  185. package/codeyam-cli/src/utils/editorBroadcastViewport.js.map +1 -0
  186. package/codeyam-cli/src/utils/editorDeleteScenario.js +67 -0
  187. package/codeyam-cli/src/utils/editorDeleteScenario.js.map +1 -0
  188. package/codeyam-cli/src/utils/editorDevServer.js +5 -1
  189. package/codeyam-cli/src/utils/editorDevServer.js.map +1 -1
  190. package/codeyam-cli/src/utils/editorEntityChangeStatus.js +13 -7
  191. package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -1
  192. package/codeyam-cli/src/utils/editorEntityHelpers.js +144 -0
  193. package/codeyam-cli/src/utils/editorEntityHelpers.js.map +1 -0
  194. package/codeyam-cli/src/utils/editorGuard.js +36 -0
  195. package/codeyam-cli/src/utils/editorGuard.js.map +1 -0
  196. package/codeyam-cli/src/utils/editorLoaderHelpers.js +72 -1
  197. package/codeyam-cli/src/utils/editorLoaderHelpers.js.map +1 -1
  198. package/codeyam-cli/src/utils/editorMigration.js +224 -0
  199. package/codeyam-cli/src/utils/editorMigration.js.map +1 -0
  200. package/codeyam-cli/src/utils/editorPreview.js +33 -0
  201. package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
  202. package/codeyam-cli/src/utils/editorRecapture.js +109 -0
  203. package/codeyam-cli/src/utils/editorRecapture.js.map +1 -0
  204. package/codeyam-cli/src/utils/editorRoadmap.js +574 -0
  205. package/codeyam-cli/src/utils/editorRoadmap.js.map +1 -0
  206. package/codeyam-cli/src/utils/editorScenarioSwitch.js +39 -2
  207. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
  208. package/codeyam-cli/src/utils/editorScenarios.js +591 -0
  209. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
  210. package/codeyam-cli/src/utils/editorSeedAdapter.js +308 -6
  211. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
  212. package/codeyam-cli/src/utils/editorShouldRevalidate.js +21 -0
  213. package/codeyam-cli/src/utils/editorShouldRevalidate.js.map +1 -0
  214. package/codeyam-cli/src/utils/entityChangeStatus.js +53 -6
  215. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
  216. package/codeyam-cli/src/utils/entityChangeStatus.server.js +72 -3
  217. package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -1
  218. package/codeyam-cli/src/utils/envFile.js +90 -0
  219. package/codeyam-cli/src/utils/envFile.js.map +1 -0
  220. package/codeyam-cli/src/utils/fileWatcher.js +38 -0
  221. package/codeyam-cli/src/utils/fileWatcher.js.map +1 -1
  222. package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
  223. package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
  224. package/codeyam-cli/src/utils/handoffContext.js +257 -0
  225. package/codeyam-cli/src/utils/handoffContext.js.map +1 -0
  226. package/codeyam-cli/src/utils/install-skills.js +50 -6
  227. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  228. package/codeyam-cli/src/utils/manualEntityAnalysis.js +196 -0
  229. package/codeyam-cli/src/utils/manualEntityAnalysis.js.map +1 -0
  230. package/codeyam-cli/src/utils/parseRegisterArg.js.map +1 -1
  231. package/codeyam-cli/src/utils/progress.js +2 -2
  232. package/codeyam-cli/src/utils/progress.js.map +1 -1
  233. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
  234. package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
  235. package/codeyam-cli/src/utils/queue/job.js +35 -6
  236. package/codeyam-cli/src/utils/queue/job.js.map +1 -1
  237. package/codeyam-cli/src/utils/registerScenarioResult.js +52 -0
  238. package/codeyam-cli/src/utils/registerScenarioResult.js.map +1 -0
  239. package/codeyam-cli/src/utils/routePatternMatching.js +129 -0
  240. package/codeyam-cli/src/utils/routePatternMatching.js.map +1 -0
  241. package/codeyam-cli/src/utils/scenarioCoverage.js +77 -0
  242. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -0
  243. package/codeyam-cli/src/utils/scenariosManifest.js +275 -74
  244. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
  245. package/codeyam-cli/src/utils/screenshotHash.js +26 -0
  246. package/codeyam-cli/src/utils/screenshotHash.js.map +1 -0
  247. package/codeyam-cli/src/utils/serverState.js +30 -0
  248. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  249. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +1 -0
  250. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  251. package/codeyam-cli/src/utils/simulationGateMiddleware.js +17 -1
  252. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
  253. package/codeyam-cli/src/utils/slugUtils.js +25 -0
  254. package/codeyam-cli/src/utils/slugUtils.js.map +1 -0
  255. package/codeyam-cli/src/utils/syncMocksMiddleware.js +2 -2
  256. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  257. package/codeyam-cli/src/utils/techStackConfig.js +38 -0
  258. package/codeyam-cli/src/utils/techStackConfig.js.map +1 -0
  259. package/codeyam-cli/src/utils/techStackConfig.test.js +85 -0
  260. package/codeyam-cli/src/utils/techStackConfig.test.js.map +1 -0
  261. package/codeyam-cli/src/utils/telemetry.js +106 -0
  262. package/codeyam-cli/src/utils/telemetry.js.map +1 -0
  263. package/codeyam-cli/src/utils/telemetryMiddleware.js +22 -0
  264. package/codeyam-cli/src/utils/telemetryMiddleware.js.map +1 -0
  265. package/codeyam-cli/src/utils/testResultCache.js +53 -0
  266. package/codeyam-cli/src/utils/testResultCache.js.map +1 -0
  267. package/codeyam-cli/src/utils/testResultCache.server.js +81 -0
  268. package/codeyam-cli/src/utils/testResultCache.server.js.map +1 -0
  269. package/codeyam-cli/src/utils/testResultCache.server.test.js +187 -0
  270. package/codeyam-cli/src/utils/testResultCache.server.test.js.map +1 -0
  271. package/codeyam-cli/src/utils/testResultCache.test.js +230 -0
  272. package/codeyam-cli/src/utils/testResultCache.test.js.map +1 -0
  273. package/codeyam-cli/src/utils/testRunner.js +193 -1
  274. package/codeyam-cli/src/utils/testRunner.js.map +1 -1
  275. package/codeyam-cli/src/utils/webappDetection.js +4 -2
  276. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  277. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +99 -0
  278. package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
  279. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js +153 -0
  280. package/codeyam-cli/src/webserver/__tests__/buildPtyEnv.test.js.map +1 -0
  281. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +107 -0
  282. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -0
  283. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +822 -0
  284. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
  285. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +315 -0
  286. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -0
  287. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js +135 -0
  288. package/codeyam-cli/src/webserver/__tests__/stripClaudeCommand.test.js.map +1 -0
  289. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +86 -0
  290. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -0
  291. package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
  292. package/codeyam-cli/src/webserver/app/lib/git.js +3 -2
  293. package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -1
  294. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
  295. package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
  296. package/codeyam-cli/src/webserver/app/types/editor.js +8 -0
  297. package/codeyam-cli/src/webserver/app/types/editor.js.map +1 -0
  298. package/codeyam-cli/src/webserver/backgroundServer.js +60 -61
  299. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  300. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-DTBZZfSk.js +1 -0
  301. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-BcgbViKV.js → EntityItem-BxclONWq.js} +3 -3
  302. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-CQgyEGV-.js +1 -0
  303. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CQIG2qda.js → EntityTypeIcon-BsnEOJZ_.js} +1 -1
  304. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-ByaELMbv.js +1 -0
  305. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-6WjVfhxX.js +25 -0
  306. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-ChX-Hp7W.js +3 -0
  307. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-BU_OAEMP.js → LoadingDots-By5zI316.js} +1 -1
  308. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-ceAyBX-H.js → LogViewer-C-9zQdXg.js} +3 -3
  309. package/codeyam-cli/src/webserver/build/client/assets/MiniClaudeChat-Bs2_Oua4.js +36 -0
  310. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-BzHcG7SE.js → ReportIssueModal-DQsceHVv.js} +2 -2
  311. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DThcm_9M.js +1 -0
  312. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-0DY_NKil.js → ScenarioViewer-Cl4oOA3A.js} +3 -3
  313. package/codeyam-cli/src/webserver/build/client/assets/Spinner-CIil5-gb.js +34 -0
  314. package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-CK7-NaPZ.js +1 -0
  315. package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-BqkA9zyZ.js +1 -0
  316. package/codeyam-cli/src/webserver/build/client/assets/{_index-DLxKhri3.js → _index-DnOgyseQ.js} +2 -2
  317. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BcY3q6nt.js → activity.(_tab)-DqM9hbNE.js} +3 -3
  318. package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-Duc5hnl7.js → addon-web-links-C58dYPwR.js} +1 -1
  319. package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-Bni3iiUj.js → agent-transcripts-B8NCeOrm.js} +3 -3
  320. package/codeyam-cli/src/webserver/build/client/assets/api.editor-database-verify-l0sNRNKZ.js +1 -0
  321. package/codeyam-cli/src/webserver/build/client/assets/api.editor-github-verify-l0sNRNKZ.js +1 -0
  322. package/codeyam-cli/src/webserver/build/client/assets/api.editor-handoff-l0sNRNKZ.js +1 -0
  323. package/codeyam-cli/src/webserver/build/client/assets/api.editor-hosting-verify-l0sNRNKZ.js +1 -0
  324. package/codeyam-cli/src/webserver/build/client/assets/api.editor-recapture-stale-l0sNRNKZ.js +1 -0
  325. package/codeyam-cli/src/webserver/build/client/assets/api.editor-rename-scenario-l0sNRNKZ.js +1 -0
  326. package/codeyam-cli/src/webserver/build/client/assets/api.editor-roadmap-l0sNRNKZ.js +1 -0
  327. package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-scenario-data-l0sNRNKZ.js +1 -0
  328. package/codeyam-cli/src/webserver/build/client/assets/api.editor-save-seed-state-l0sNRNKZ.js +1 -0
  329. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-coverage-l0sNRNKZ.js +1 -0
  330. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-prompt-l0sNRNKZ.js +1 -0
  331. package/codeyam-cli/src/webserver/build/client/assets/api.editor-schema-l0sNRNKZ.js +1 -0
  332. package/codeyam-cli/src/webserver/build/client/assets/api.editor-session-l0sNRNKZ.js +1 -0
  333. package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
  334. package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
  335. package/codeyam-cli/src/webserver/build/client/assets/{book-open-BYOypzCa.js → book-open-BFSIqZgO.js} +1 -1
  336. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-C_Pmso5S.js → chevron-down-B9fDzFVh.js} +1 -1
  337. package/codeyam-cli/src/webserver/build/client/assets/chunk-UVKPFVEO-Bmq2apuh.js +43 -0
  338. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BVMi9VA5.js → circle-check-DLPObLUx.js} +1 -1
  339. package/codeyam-cli/src/webserver/build/client/assets/{copy-n2FB0_Sw.js → copy-DXEmO0TD.js} +1 -1
  340. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-CC6AbExI.js → createLucideIcon-BwyFiRot.js} +1 -1
  341. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-Coe5NhbS.js +1 -0
  342. package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-CCKUIm0S.svg → cy-logo-cli-DoA97ML3.svg} +2 -2
  343. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-iRhRIFlp.js +1 -0
  344. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-BZPBzV73.js +1 -0
  345. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DhtVC4aI.js +161 -0
  346. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-C6fEYHrh.js +41 -0
  347. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BF4oLwaE.js → entity._sha._-pc-vc6wO.js} +13 -12
  348. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-C8AyYgYT.js +6 -0
  349. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DziaVQX1.js +6 -0
  350. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-BTcpgIpC.js +6 -0
  351. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMvVHNXU.js → entity._sha_.edit._scenarioId-D_O_ajfZ.js} +2 -2
  352. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-DTvKq3TY.js → entry.client-j1Vi0bco.js} +6 -6
  353. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-Daa96Fr1.js +1 -0
  354. package/codeyam-cli/src/webserver/build/client/assets/files-kuny2Q_s.js +1 -0
  355. package/codeyam-cli/src/webserver/build/client/assets/git-DgCZPMie.js +1 -0
  356. package/codeyam-cli/src/webserver/build/client/assets/globals-L-aUIeux.css +1 -0
  357. package/codeyam-cli/src/webserver/build/client/assets/{index-BcvgDzbZ.js → index-BliGSSpl.js} +1 -1
  358. package/codeyam-cli/src/webserver/build/client/assets/{index-yHOVb4rc.js → index-SqjQKTdH.js} +1 -1
  359. package/codeyam-cli/src/webserver/build/client/assets/{index-10oVnAAH.js → index-vyrZD2g4.js} +1 -1
  360. package/codeyam-cli/src/webserver/build/client/assets/jsx-runtime-D_zvdyIk.js +9 -0
  361. package/codeyam-cli/src/webserver/build/client/assets/labs-c3yLxSEp.js +1 -0
  362. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-DaAZ_H2w.js → loader-circle-D-q28GLF.js} +1 -1
  363. package/codeyam-cli/src/webserver/build/client/assets/manifest-79d0d81a.js +1 -0
  364. package/codeyam-cli/src/webserver/build/client/assets/memory-CEWIUC4t.js +101 -0
  365. package/codeyam-cli/src/webserver/build/client/assets/{pause-f5-1lKBt.js → pause-BP6fitdh.js} +1 -1
  366. package/codeyam-cli/src/webserver/build/client/assets/root-L2V0jea7.js +80 -0
  367. package/codeyam-cli/src/webserver/build/client/assets/{search-Di64LWVb.js → search-BooqacKS.js} +1 -1
  368. package/codeyam-cli/src/webserver/build/client/assets/settings-BM0nbryO.js +1 -0
  369. package/codeyam-cli/src/webserver/build/client/assets/simulations-ovy6FjRY.js +1 -0
  370. package/codeyam-cli/src/webserver/build/client/assets/{terminal-Br7MOqts.js → terminal-DHemCJIs.js} +1 -1
  371. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BLdiCuG-.js → triangle-alert-D87ekDl8.js} +1 -1
  372. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-Dk0Tciqg.js +1 -0
  373. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C8QvIe05.js +2 -0
  374. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-jkCytuYz.js +1 -0
  375. package/codeyam-cli/src/webserver/build/client/assets/useToast-BgqkixU9.js +1 -0
  376. package/codeyam-cli/src/webserver/build/client/sound-test.html +98 -0
  377. package/codeyam-cli/src/webserver/build/server/assets/analysisRunner-QgInFGdU.js +16 -0
  378. package/codeyam-cli/src/webserver/build/server/assets/index-zblh9auj.js +1 -0
  379. package/codeyam-cli/src/webserver/build/server/assets/init-DaE0CBjk.js +14 -0
  380. package/codeyam-cli/src/webserver/build/server/assets/progress-CHTtrxFG.js +1 -0
  381. package/codeyam-cli/src/webserver/build/server/assets/server-build-CNvgz1cC.js +853 -0
  382. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  383. package/codeyam-cli/src/webserver/build-info.json +5 -5
  384. package/codeyam-cli/src/webserver/editorProxy.js +675 -17
  385. package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
  386. package/codeyam-cli/src/webserver/idleDetector.js +130 -0
  387. package/codeyam-cli/src/webserver/idleDetector.js.map +1 -0
  388. package/codeyam-cli/src/webserver/mockStateEvents.js +28 -0
  389. package/codeyam-cli/src/webserver/mockStateEvents.js.map +1 -0
  390. package/codeyam-cli/src/webserver/public/sound-test.html +98 -0
  391. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +53 -0
  392. package/codeyam-cli/src/webserver/server.js +192 -4
  393. package/codeyam-cli/src/webserver/server.js.map +1 -1
  394. package/codeyam-cli/src/webserver/terminalServer.js +389 -52
  395. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  396. package/codeyam-cli/templates/__tests__/editor-step-hook.prompt-capture.test.ts +118 -0
  397. package/codeyam-cli/templates/chrome-extension-react/README.md +46 -0
  398. package/codeyam-cli/templates/chrome-extension-react/package.json +1 -0
  399. package/codeyam-cli/templates/chrome-extension-react/vite.config.ts +6 -0
  400. package/codeyam-cli/templates/codeyam-editor-claude.md +86 -5
  401. package/codeyam-cli/templates/codeyam-editor-codex.md +61 -0
  402. package/codeyam-cli/templates/codeyam-editor-gemini.md +59 -0
  403. package/codeyam-cli/templates/codeyam-editor-reference.md +216 -0
  404. package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
  405. package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
  406. package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
  407. package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
  408. package/codeyam-cli/templates/editor-step-hook.py +193 -56
  409. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +204 -5
  410. package/codeyam-cli/templates/expo-react-native/README.md +41 -0
  411. package/codeyam-cli/templates/expo-react-native/__tests__/.gitkeep +0 -0
  412. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +6 -3
  413. package/codeyam-cli/templates/expo-react-native/app/index.tsx +36 -0
  414. package/codeyam-cli/templates/expo-react-native/app.json +11 -0
  415. package/codeyam-cli/templates/expo-react-native/babel.config.js +1 -0
  416. package/codeyam-cli/templates/expo-react-native/gitignore +2 -0
  417. package/codeyam-cli/templates/expo-react-native/global.css +7 -0
  418. package/codeyam-cli/templates/expo-react-native/lib/theme.ts +73 -0
  419. package/codeyam-cli/templates/expo-react-native/package.json +33 -16
  420. package/codeyam-cli/templates/expo-react-native/patches/expo-modules-autolinking+3.0.24.patch +29 -0
  421. package/codeyam-cli/templates/isolation-route/expo-router.tsx.template +54 -0
  422. package/codeyam-cli/templates/nextjs-prisma-sqlite/DATABASE.md +14 -0
  423. package/codeyam-cli/templates/nextjs-prisma-sqlite/README.md +53 -0
  424. package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +1 -0
  425. package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +2 -1
  426. package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +88 -40
  427. package/codeyam-cli/templates/nextjs-prisma-supabase/README.md +52 -0
  428. package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +2 -1
  429. package/codeyam-cli/templates/seed-adapters/supabase.ts +475 -0
  430. package/codeyam-cli/templates/skills/codeyam-dev-mode/SKILL.md +1 -1
  431. package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +109 -10
  432. package/package.json +2 -1
  433. package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
  434. package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
  435. package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
  436. package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
  437. package/packages/ai/src/lib/astScopes/paths.js +12 -3
  438. package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
  439. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +27 -10
  440. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  441. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js +9 -2
  442. package/packages/ai/src/lib/dataStructure/equivalencyManagers/ParentScopeManager.js.map +1 -1
  443. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +14 -4
  444. package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
  445. package/packages/analyze/index.js +1 -1
  446. package/packages/analyze/index.js.map +1 -1
  447. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +16 -2
  448. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  449. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +6 -26
  450. package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
  451. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +3 -2
  452. package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
  453. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +9 -7
  454. package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
  455. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js +14 -0
  456. package/packages/analyze/src/lib/files/analyze/trackEntityCircularDependencies.js.map +1 -1
  457. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +44 -11
  458. package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
  459. package/packages/analyze/src/lib/files/analyzeChange.js +1 -0
  460. package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
  461. package/packages/analyze/src/lib/files/analyzeInitial.js +1 -0
  462. package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
  463. package/packages/analyze/src/lib/files/analyzeNextRoute.js +5 -1
  464. package/packages/analyze/src/lib/files/analyzeNextRoute.js.map +1 -1
  465. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +120 -28
  466. package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
  467. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1368 -1193
  468. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  469. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +84 -0
  470. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  471. package/packages/database/src/lib/loadAnalysis.js +7 -1
  472. package/packages/database/src/lib/loadAnalysis.js.map +1 -1
  473. package/packages/database/src/lib/loadEntities.js +0 -6
  474. package/packages/database/src/lib/loadEntities.js.map +1 -1
  475. package/packages/database/src/lib/loadEntity.js +5 -5
  476. package/packages/database/src/lib/loadEntity.js.map +1 -1
  477. package/packages/database/src/lib/updateCommitMetadata.js +0 -25
  478. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  479. package/packages/utils/src/lib/fs/rsyncCopy.js +22 -1
  480. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  481. package/codeyam-cli/src/webserver/build/client/assets/CopyButton-BPXZwM4t.js +0 -1
  482. package/codeyam-cli/src/webserver/build/client/assets/EntityTypeBadge-g3saevPb.js +0 -1
  483. package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-Bu6c6aDe.js +0 -1
  484. package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-DYFW3lDD.js +0 -25
  485. package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DLeucoVX.js +0 -3
  486. package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BED4B6sP.js +0 -1
  487. package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bb5uFQ5V.js +0 -34
  488. package/codeyam-cli/src/webserver/build/client/assets/TruncatedFilePath-C8OKAR5x.js +0 -1
  489. package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-oAf2Kqsf.js +0 -1
  490. package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-C4pqxYJB.js +0 -51
  491. package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +0 -1
  492. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Csi0_PMl.js +0 -1
  493. package/codeyam-cli/src/webserver/build/client/assets/editor-BuT_Huj0.js +0 -10
  494. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-B7ztwLut.js +0 -41
  495. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-D5rYBT5x.js +0 -6
  496. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-CF164ouH.js +0 -6
  497. package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-p9hhkjJM.js +0 -6
  498. package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-cPo8LiG3.js +0 -1
  499. package/codeyam-cli/src/webserver/build/client/assets/files-BZrlFE1F.js +0 -1
  500. package/codeyam-cli/src/webserver/build/client/assets/git-DdZcvjGh.js +0 -1
  501. package/codeyam-cli/src/webserver/build/client/assets/globals-BkWJ_UNc.css +0 -1
  502. package/codeyam-cli/src/webserver/build/client/assets/labs-Zk7ryIM1.js +0 -1
  503. package/codeyam-cli/src/webserver/build/client/assets/manifest-b0f1372e.js +0 -1
  504. package/codeyam-cli/src/webserver/build/client/assets/memory-Bl2rpw8u.js +0 -96
  505. package/codeyam-cli/src/webserver/build/client/assets/root-B_X8HS1x.js +0 -67
  506. package/codeyam-cli/src/webserver/build/client/assets/settings-0OrEMU6J.js +0 -1
  507. package/codeyam-cli/src/webserver/build/client/assets/simulations-DWT-CvLy.js +0 -1
  508. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-CrAK28Bc.js +0 -1
  509. package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-C14nCb1q.js +0 -2
  510. package/codeyam-cli/src/webserver/build/client/assets/useReportContext-O-jkvSPx.js +0 -1
  511. package/codeyam-cli/src/webserver/build/client/assets/useToast-9FIWuYfK.js +0 -1
  512. package/codeyam-cli/src/webserver/build/server/assets/index-CbF6h3dj.js +0 -1
  513. package/codeyam-cli/src/webserver/build/server/assets/server-build-DRFwTJqO.js +0 -367
  514. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +0 -33
  515. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +0 -12
  516. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +0 -12
@@ -5,6 +5,7 @@ import path from 'path';
5
5
  import { getProjectRoot } from "../state.js";
6
6
  import { createMockStateManager, } from "../utils/editorMockState.js";
7
7
  import { computeEditorPorts } from "../utils/editorDevServer.js";
8
+ import { mockStateEventEmitter } from "./mockStateEvents.js";
8
9
  /**
9
10
  * Normalize a target URL by stripping trailing slashes for consistency.
10
11
  *
@@ -60,10 +61,128 @@ export async function resolveLoopbackAddress(port) {
60
61
  }
61
62
  // Global key so the proxy survives HMR
62
63
  const GLOBAL_KEY = '__codeyam_editor_proxy__';
64
+ // ─── Live Preview Health ─────────────────────────────────────────────
65
+ const PREVIEW_HEALTH_KEY = '__codeyam_preview_health__';
66
+ function getPreviewHealth() {
67
+ return globalThis[PREVIEW_HEALTH_KEY] ?? null;
68
+ }
69
+ function setPreviewHealth(report) {
70
+ globalThis[PREVIEW_HEALTH_KEY] = report;
71
+ }
72
+ /**
73
+ * Get the current live preview health report (read by API endpoint).
74
+ */
75
+ export function getPreviewHealthReport() {
76
+ return getPreviewHealth();
77
+ }
78
+ /**
79
+ * Reset preview health state (called when a new HTML page is served).
80
+ */
81
+ export function resetPreviewHealth() {
82
+ setPreviewHealth(null);
83
+ }
84
+ /**
85
+ * Error-catching script injected into HTML responses.
86
+ * Uses vanilla JS for maximum compatibility.
87
+ */
88
+ export const PREVIEW_HEALTH_SCRIPT = `<script data-codeyam-health>
89
+ (function() {
90
+ var errors = [];
91
+ var reported = false;
92
+ function report(type, msg, stack) {
93
+ errors.push({ type: type, message: msg, stack: stack, timestamp: Date.now() });
94
+ if (!reported) {
95
+ reported = true;
96
+ setTimeout(function() { flush(); }, 500);
97
+ }
98
+ }
99
+ function flush() {
100
+ fetch('/__codeyam__/preview-health', {
101
+ method: 'POST',
102
+ headers: { 'Content-Type': 'application/json' },
103
+ body: JSON.stringify({ errors: errors, url: location.href })
104
+ }).catch(function(){});
105
+ reported = false;
106
+ errors = [];
107
+ }
108
+ window.addEventListener('error', function(e) {
109
+ report('error', e.message, e.error && e.error.stack);
110
+ });
111
+ window.addEventListener('unhandledrejection', function(e) {
112
+ report('unhandledrejection', String(e.reason), e.reason && e.reason.stack);
113
+ });
114
+ var origError = console.error;
115
+ console.error = function() {
116
+ report('console.error', Array.prototype.join.call(arguments, ' '));
117
+ origError.apply(console, arguments);
118
+ };
119
+ window.addEventListener('load', function() {
120
+ setTimeout(function() {
121
+ var hasContent = document.body && document.body.innerText.trim().length > 0;
122
+ fetch('/__codeyam__/preview-health', {
123
+ method: 'POST',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify({
126
+ loaded: true,
127
+ hasContent: hasContent,
128
+ url: location.href,
129
+ errorCount: errors.length
130
+ })
131
+ }).catch(function(){});
132
+ }, 1000);
133
+ });
134
+
135
+ // Network-idle detection: notify the parent editor when all initial
136
+ // fetch requests have completed, so it can show the preview after
137
+ // client-side data (API calls) has arrived — not just when the DOM loads.
138
+ var inflight = 0;
139
+ var settled = false;
140
+ var settleTimer = null;
141
+ var origFetch = window.fetch;
142
+ window.fetch = function() {
143
+ if (!settled) inflight++;
144
+ return origFetch.apply(this, arguments).then(function(resp) {
145
+ if (!settled) { inflight--; checkSettle(); }
146
+ return resp;
147
+ }, function(err) {
148
+ if (!settled) { inflight--; checkSettle(); }
149
+ throw err;
150
+ });
151
+ };
152
+ function checkSettle() {
153
+ if (inflight <= 0 && !settled) {
154
+ clearTimeout(settleTimer);
155
+ // Small delay to allow React to re-render with the fetched data
156
+ settleTimer = setTimeout(function() {
157
+ if (inflight <= 0) {
158
+ settled = true;
159
+ try {
160
+ window.parent.postMessage({ type: 'codeyam-preview-ready' }, '*');
161
+ } catch(e) {}
162
+ }
163
+ }, 100);
164
+ }
165
+ }
166
+ // Fallback: if no fetches happen (static page), settle after load
167
+ window.addEventListener('load', function() {
168
+ setTimeout(function() { checkSettle(); }, 200);
169
+ });
170
+ })();
171
+ </script>`;
63
172
  const CACHE_TTL_MS = 500;
64
173
  let scenarioCache = { data: null, timestamp: 0 };
65
174
  // Session config extracted from the active scenario — drives cookie injection
66
175
  let sessionConfig = undefined;
176
+ /** Session cookies from the seed adapter (e.g. Supabase auth tokens). */
177
+ let seedSessionCookies = undefined;
178
+ // localStorage config extracted from the active scenario — drives HTML injection
179
+ let localStorageConfig = null;
180
+ // Active scenario ID — used to gate localStorage seeding (only re-seed on switch)
181
+ let activeScenarioId = null;
182
+ // Prototype ID — used to gate a one-time localStorage.clear() when a new project is scaffolded
183
+ let currentPrototypeId = null;
184
+ // Current scenario type — 'application'/'user' for seed-based, 'component' for mock-based
185
+ let currentScenarioType = null;
67
186
  // Max body size to buffer for mock matching (10MB)
68
187
  const MAX_BODY_SIZE = 10 * 1024 * 1024;
69
188
  function getProxyState() {
@@ -117,6 +236,8 @@ function readScenarioData() {
117
236
  const active = JSON.parse(fs.readFileSync(activeScenarioPath, 'utf-8'));
118
237
  const scenarioId = active.scenarioId;
119
238
  if (!scenarioId) {
239
+ // No active scenario — but may have a prototypeId for localStorage clearing
240
+ currentPrototypeId = active.prototypeId || null;
120
241
  scenarioCache = { data: null, timestamp: now };
121
242
  return null;
122
243
  }
@@ -129,8 +250,14 @@ function readScenarioData() {
129
250
  const rawData = JSON.parse(fs.readFileSync(dataFilePath, 'utf-8'));
130
251
  // Extract session config for cookie injection
131
252
  sessionConfig = rawData.session || null;
253
+ // Extract seed adapter session cookies (e.g. Supabase auth)
254
+ seedSessionCookies = rawData.sessionCookies || undefined;
255
+ // Extract localStorage config for HTML injection
256
+ localStorageConfig = rawData.localStorage || null;
257
+ activeScenarioId = scenarioId;
132
258
  // Type-aware: for seed-based scenarios, only serve externalApis via proxy
133
259
  const scenarioType = active.type || rawData.type || null;
260
+ currentScenarioType = scenarioType;
134
261
  let mockData;
135
262
  if ((scenarioType === 'application' || scenarioType === 'user') &&
136
263
  rawData.seed) {
@@ -204,6 +331,13 @@ function forwardBufferedRequest(req, res, targetUrl, bodyBuffer) {
204
331
  const target = new URL(targetUrl);
205
332
  const hostname = stripIPv6Brackets(target.hostname);
206
333
  const headers = { ...req.headers, host: `${target.hostname}:${target.port}` };
334
+ // Remove accept-encoding so the dev server returns uncompressed responses.
335
+ // The proxy injects a health script into HTML — this fails on compressed bodies.
336
+ delete headers['accept-encoding'];
337
+ // Inject session cookies into the request so the dev server sees auth
338
+ // on the first request after a scenario switch (before the browser has
339
+ // stored them from Set-Cookie responses).
340
+ injectRequestCookies(headers);
207
341
  // Update content-length if we have the body buffer
208
342
  if (bodyBuffer) {
209
343
  headers['content-length'] = String(bodyBuffer.length);
@@ -217,19 +351,70 @@ function forwardBufferedRequest(req, res, targetUrl, bodyBuffer) {
217
351
  };
218
352
  const proxyReq = http.request(options, (proxyRes) => {
219
353
  const status = proxyRes.statusCode || 200;
354
+ if (status >= 300 && status < 400) {
355
+ console.log(`[editorProxy] Target redirect ${status} for ${req.method} ${req.url} → ${proxyRes.headers.location}`);
356
+ }
220
357
  if (status >= 400) {
221
358
  console.warn(`[editorProxy] Target returned ${status} for ${req.method} ${req.url}`);
222
359
  }
223
360
  const headers = { ...proxyRes.headers };
224
361
  injectSessionCookie(headers);
362
+ // Check if response is HTML — if so, buffer and inject health script
363
+ const contentType = proxyRes.headers['content-type'] || '';
364
+ if (contentType.includes('text/html')) {
365
+ resetPreviewHealth();
366
+ const chunks = [];
367
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
368
+ proxyRes.on('end', () => {
369
+ const body = Buffer.concat(chunks).toString('utf-8');
370
+ delete headers['content-length'];
371
+ delete headers['content-encoding'];
372
+ headers['cache-control'] = 'no-store, must-revalidate';
373
+ // Serve a friendly error page for 5xx responses instead of
374
+ // forwarding the raw error HTML (e.g. Next.js "Internal Server Error")
375
+ if (status >= 500) {
376
+ const errorPage = buildErrorPage(status, 'Internal Server Error', body);
377
+ res.writeHead(status, headers);
378
+ res.end(errorPage);
379
+ return;
380
+ }
381
+ const lsScript = buildLocalStorageScript(localStorageConfig, activeScenarioId || '', currentPrototypeId);
382
+ const injected = injectHealthScript(body, lsScript);
383
+ res.writeHead(status, headers);
384
+ res.end(injected);
385
+ });
386
+ return;
387
+ }
388
+ // For 5xx responses without a content type or with text/plain,
389
+ // serve a friendly error page. These are typically broken dev servers
390
+ // (e.g. Next.js returning bare "Internal Server Error" with no headers).
391
+ // JSON API errors are left alone — they're legitimate responses.
392
+ if (status >= 500 && !contentType.includes('application/json')) {
393
+ const chunks = [];
394
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
395
+ proxyRes.on('end', () => {
396
+ const body = Buffer.concat(chunks).toString('utf-8');
397
+ const errorPage = buildErrorPage(status, 'Internal Server Error', body);
398
+ res.writeHead(status, {
399
+ 'Content-Type': 'text/html',
400
+ 'Cache-Control': 'no-store',
401
+ });
402
+ res.end(errorPage);
403
+ });
404
+ return;
405
+ }
225
406
  res.writeHead(status, headers);
226
407
  proxyRes.pipe(res, { end: true });
227
408
  });
228
409
  proxyReq.on('error', (err) => {
229
410
  console.warn(`[editorProxy] Forward error for ${req.method} ${req.url}: ${err.message}`);
230
411
  if (!res.headersSent) {
231
- res.writeHead(502, { 'Content-Type': 'text/plain' });
232
- res.end('Bad Gateway — dev server unreachable');
412
+ const errorPage = buildErrorPage(502, 'Dev Server Unreachable', `The proxy could not connect to the dev server. It may be starting up, restarting, or crashed.\n\n${err.message}`);
413
+ res.writeHead(502, {
414
+ 'Content-Type': 'text/html',
415
+ 'Cache-Control': 'no-store',
416
+ });
417
+ res.end(errorPage);
233
418
  }
234
419
  });
235
420
  if (bodyBuffer && bodyBuffer.length > 0) {
@@ -240,33 +425,97 @@ function forwardBufferedRequest(req, res, targetUrl, bodyBuffer) {
240
425
  }
241
426
  }
242
427
  /**
243
- * Forward an HTTP request to the target dev server (streaming, no body buffering).
428
+ * Forward an HTTP request to the target dev server.
429
+ * For HTML responses: buffers body to inject health-check script.
430
+ * For non-HTML responses: pipes directly (no buffering).
244
431
  */
245
432
  function forwardRequest(req, res, targetUrl) {
246
433
  const target = new URL(targetUrl);
247
434
  const hostname = stripIPv6Brackets(target.hostname);
435
+ // Build headers, stripping accept-encoding so the dev server returns uncompressed
436
+ // responses. The proxy injects a health script into HTML — this fails on compressed bodies.
437
+ const { 'accept-encoding': _ae, ...forwardHeaders } = req.headers;
438
+ const reqHeaders = {
439
+ ...forwardHeaders,
440
+ host: `${target.hostname}:${target.port}`,
441
+ };
442
+ // Inject session cookies into the request so the dev server sees auth
443
+ // on the first request after a scenario switch.
444
+ injectRequestCookies(reqHeaders);
248
445
  const options = {
249
446
  hostname,
250
447
  port: target.port,
251
448
  path: req.url,
252
449
  method: req.method,
253
- headers: { ...req.headers, host: `${target.hostname}:${target.port}` },
450
+ headers: reqHeaders,
254
451
  };
255
452
  const proxyReq = http.request(options, (proxyRes) => {
256
453
  const status = proxyRes.statusCode || 200;
454
+ if (status >= 300 && status < 400) {
455
+ console.log(`[editorProxy] Target redirect ${status} for ${req.method} ${req.url} → ${proxyRes.headers.location}`);
456
+ }
257
457
  if (status >= 400) {
258
458
  console.warn(`[editorProxy] Target returned ${status} for ${req.method} ${req.url}`);
259
459
  }
260
460
  const headers = { ...proxyRes.headers };
261
461
  injectSessionCookie(headers);
462
+ // Check if response is HTML — if so, buffer and inject health script
463
+ const contentType = proxyRes.headers['content-type'] || '';
464
+ if (contentType.includes('text/html')) {
465
+ // Reset health state for new page loads
466
+ resetPreviewHealth();
467
+ const chunks = [];
468
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
469
+ proxyRes.on('end', () => {
470
+ const body = Buffer.concat(chunks).toString('utf-8');
471
+ delete headers['content-length'];
472
+ delete headers['content-encoding'];
473
+ headers['cache-control'] = 'no-store, must-revalidate';
474
+ // Serve a friendly error page for 5xx responses instead of
475
+ // forwarding the raw error HTML (e.g. Next.js "Internal Server Error")
476
+ if (status >= 500) {
477
+ const errorPage = buildErrorPage(status, 'Internal Server Error', body);
478
+ res.writeHead(status, headers);
479
+ res.end(errorPage);
480
+ return;
481
+ }
482
+ const lsScript = buildLocalStorageScript(localStorageConfig, activeScenarioId || '', currentPrototypeId);
483
+ const injected = injectHealthScript(body, lsScript);
484
+ res.writeHead(status, headers);
485
+ res.end(injected);
486
+ });
487
+ return;
488
+ }
489
+ // For 5xx responses without a content type or with text/plain,
490
+ // serve a friendly error page. These are typically broken dev servers
491
+ // (e.g. Next.js returning bare "Internal Server Error" with no headers).
492
+ // JSON API errors are left alone — they're legitimate responses.
493
+ if (status >= 500 && !contentType.includes('application/json')) {
494
+ const chunks = [];
495
+ proxyRes.on('data', (chunk) => chunks.push(chunk));
496
+ proxyRes.on('end', () => {
497
+ const body = Buffer.concat(chunks).toString('utf-8');
498
+ const errorPage = buildErrorPage(status, 'Internal Server Error', body);
499
+ res.writeHead(status, {
500
+ 'Content-Type': 'text/html',
501
+ 'Cache-Control': 'no-store',
502
+ });
503
+ res.end(errorPage);
504
+ });
505
+ return;
506
+ }
262
507
  res.writeHead(status, headers);
263
508
  proxyRes.pipe(res, { end: true });
264
509
  });
265
510
  proxyReq.on('error', (err) => {
266
511
  console.warn(`[editorProxy] Forward error for ${req.method} ${req.url}: ${err.message}`);
267
512
  if (!res.headersSent) {
268
- res.writeHead(502, { 'Content-Type': 'text/plain' });
269
- res.end('Bad Gateway — dev server unreachable');
513
+ const errorPage = buildErrorPage(502, 'Dev Server Unreachable', `The proxy could not connect to the dev server. It may be starting up, restarting, or crashed.\n\n${err.message}`);
514
+ res.writeHead(502, {
515
+ 'Content-Type': 'text/html',
516
+ 'Cache-Control': 'no-store',
517
+ });
518
+ res.end(errorPage);
270
519
  }
271
520
  });
272
521
  req.pipe(proxyReq, { end: true });
@@ -278,25 +527,94 @@ function forwardRequest(req, res, targetUrl) {
278
527
  * When sessionConfig is undefined (no scenario loaded yet), does nothing.
279
528
  */
280
529
  function injectSessionCookie(headers) {
281
- if (sessionConfig === undefined)
282
- return;
283
- let cookie;
284
- if (sessionConfig?.cookieValue) {
285
- cookie = `session-token=${sessionConfig.cookieValue}; Path=/; SameSite=Lax`;
530
+ const cookies = [];
531
+ // Dev auth cookie (built-in session-token)
532
+ if (sessionConfig !== undefined) {
533
+ if (sessionConfig?.cookieValue) {
534
+ cookies.push(`session-token=${sessionConfig.cookieValue}; Path=/; SameSite=Lax`);
535
+ }
536
+ else {
537
+ cookies.push(`session-token=; Path=/; Max-Age=0`);
538
+ }
286
539
  }
287
- else {
288
- // No session config clear any existing session cookie
289
- cookie = `session-token=; Path=/; Max-Age=0`;
540
+ // Seed adapter session cookies (e.g. Supabase auth tokens)
541
+ if (seedSessionCookies && seedSessionCookies.length > 0) {
542
+ for (const sc of seedSessionCookies) {
543
+ const cookiePath = sc.path || '/';
544
+ const sameSite = sc.sameSite || 'Lax';
545
+ cookies.push(`${sc.name}=${sc.value}; Path=${cookiePath}; SameSite=${sameSite}`);
546
+ }
290
547
  }
548
+ if (cookies.length === 0)
549
+ return;
291
550
  const existing = headers['set-cookie'];
292
551
  if (existing) {
293
552
  headers['set-cookie'] = [
294
553
  ...(Array.isArray(existing) ? existing : [existing]),
295
- cookie,
554
+ ...cookies,
296
555
  ];
297
556
  }
298
557
  else {
299
- headers['set-cookie'] = [cookie];
558
+ headers['set-cookie'] = cookies;
559
+ }
560
+ }
561
+ /**
562
+ * Get session cookies that should be injected into requests forwarded to the
563
+ * dev server. Returns an array of {name, value} pairs, or null if no session
564
+ * cookies are configured.
565
+ *
566
+ * This is the counterpart to `injectSessionCookie()` (which adds Set-Cookie
567
+ * to responses). Without request-side injection, the first request after a
568
+ * scenario switch has no cookies — the dev server's auth middleware sees no
569
+ * session and redirects to the login page before the browser ever receives
570
+ * the Set-Cookie response.
571
+ */
572
+ export function getRequestCookieInjection() {
573
+ const cookies = [];
574
+ if (sessionConfig?.cookieValue) {
575
+ cookies.push({ name: 'session-token', value: sessionConfig.cookieValue });
576
+ }
577
+ if (seedSessionCookies && seedSessionCookies.length > 0) {
578
+ for (const sc of seedSessionCookies) {
579
+ cookies.push({ name: sc.name, value: sc.value });
580
+ }
581
+ }
582
+ return cookies.length > 0 ? cookies : null;
583
+ }
584
+ /**
585
+ * Inject session cookies into the request's Cookie header before forwarding
586
+ * to the dev server. This ensures the dev server sees auth cookies on the
587
+ * very first request after a scenario switch (before the browser has stored
588
+ * them from Set-Cookie responses).
589
+ */
590
+ function injectRequestCookies(headers) {
591
+ const injection = getRequestCookieInjection();
592
+ if (!injection)
593
+ return;
594
+ // Parse existing cookies from the request
595
+ const existing = typeof headers.cookie === 'string' ? headers.cookie : '';
596
+ const existingPairs = existing
597
+ ? existing.split(';').map((s) => s.trim())
598
+ : [];
599
+ // Build a map of existing cookies for deduplication
600
+ const cookieMap = new Map();
601
+ for (const pair of existingPairs) {
602
+ const eqIdx = pair.indexOf('=');
603
+ if (eqIdx !== -1) {
604
+ cookieMap.set(pair.slice(0, eqIdx), pair.slice(eqIdx + 1));
605
+ }
606
+ }
607
+ // Override with injected cookies
608
+ for (const { name, value } of injection) {
609
+ cookieMap.set(name, value);
610
+ }
611
+ // Reassemble
612
+ const parts = [];
613
+ for (const [k, v] of cookieMap) {
614
+ parts.push(`${k}=${v}`);
615
+ }
616
+ if (parts.length > 0) {
617
+ headers.cookie = parts.join('; ');
300
618
  }
301
619
  }
302
620
  /**
@@ -305,6 +623,324 @@ function injectSessionCookie(headers) {
305
623
  export function getSessionConfig() {
306
624
  return sessionConfig;
307
625
  }
626
+ /**
627
+ * Get the current localStorage config (for testing and script generation).
628
+ */
629
+ export function getLocalStorageConfig() {
630
+ return localStorageConfig;
631
+ }
632
+ /**
633
+ * Get the active scenario ID (for testing and script generation).
634
+ */
635
+ export function getActiveScenarioId() {
636
+ return activeScenarioId;
637
+ }
638
+ /**
639
+ * Get the current prototype ID (for testing).
640
+ */
641
+ export function getCurrentPrototypeId() {
642
+ return currentPrototypeId;
643
+ }
644
+ /**
645
+ * Simple djb2 hash — fast, deterministic, good enough for cache busting.
646
+ * Not cryptographic — just detects when localStorage config content changes.
647
+ */
648
+ function simpleHash(str) {
649
+ let hash = 5381;
650
+ for (let i = 0; i < str.length; i++) {
651
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;
652
+ }
653
+ return (hash >>> 0).toString(36);
654
+ }
655
+ /**
656
+ * Build a script tag that seeds localStorage with scenario data on first load.
657
+ * Gated by scenario ID — only seeds when the scenario changes, preserving
658
+ * interactive modifications across page reloads / HMR.
659
+ *
660
+ * Returns empty string if no localStorage config is provided.
661
+ */
662
+ export function buildLocalStorageScript(localStorageConfig, scenarioId, prototypeId) {
663
+ // null/undefined means no localStorage config at all — clean up keys
664
+ // that were set by a previous scenario so stale filter/sort state
665
+ // doesn't bleed through and hide data in the new scenario.
666
+ if (!localStorageConfig || typeof localStorageConfig !== 'object') {
667
+ // Always clean up previous scenario's keys, gated by scenarioId
668
+ // so it only runs once per switch (not on every HMR reload).
669
+ const guardValue = scenarioId ? `clear:${scenarioId}` : '';
670
+ if (prototypeId) {
671
+ return `<script data-codeyam-ls>
672
+ (function() {
673
+ if (localStorage.getItem('__codeyam_proto__') === ${JSON.stringify(prototypeId)}) return;
674
+ localStorage.clear();
675
+ localStorage.setItem('__codeyam_proto__', ${JSON.stringify(prototypeId)});
676
+ })();
677
+ </script>`;
678
+ }
679
+ if (scenarioId) {
680
+ // No prototypeId but we do have a scenarioId — clean up keys
681
+ // from the previous scenario without doing a full clear.
682
+ return `<script data-codeyam-ls>
683
+ (function() {
684
+ if (localStorage.getItem('__codeyam_ls_sid__') === ${JSON.stringify(guardValue)}) return;
685
+ var prev = JSON.parse(localStorage.getItem('__codeyam_ls_keys__') || '[]');
686
+ for (var i = 0; i < prev.length; i++) localStorage.removeItem(prev[i]);
687
+ localStorage.removeItem('__codeyam_ls_keys__');
688
+ localStorage.setItem('__codeyam_ls_sid__', ${JSON.stringify(guardValue)});
689
+ })();
690
+ </script>`;
691
+ }
692
+ return '';
693
+ }
694
+ // Even an empty object needs a cleanup script — switching from a scenario
695
+ // with localStorage data to one without must clear the previous keys.
696
+ const entries = Object.entries(localStorageConfig);
697
+ const keys = entries.map(([k]) => k);
698
+ // Build setItem calls — stringify non-string values
699
+ const setStatements = entries
700
+ .map(([key, value]) => {
701
+ const serialized = typeof value === 'string' ? value : JSON.stringify(value);
702
+ return `localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(serialized)});`;
703
+ })
704
+ .join('\n');
705
+ // Guard value includes a content hash so re-registering a scenario with
706
+ // updated data (same ID, different content) busts the cache. Without this,
707
+ // the browser skips re-seeding because the scenario ID hasn't changed,
708
+ // causing stale data in the live preview while screenshots show fresh data.
709
+ const contentHash = simpleHash(JSON.stringify(localStorageConfig));
710
+ const guardValue = `${scenarioId}:${contentHash}`;
711
+ return (`<script data-codeyam-ls>
712
+ (function() {
713
+ if (localStorage.getItem('__codeyam_ls_sid__') === ${JSON.stringify(guardValue)}) return;
714
+ var prev = JSON.parse(localStorage.getItem('__codeyam_ls_keys__') || '[]');
715
+ for (var i = 0; i < prev.length; i++) localStorage.removeItem(prev[i]);
716
+ ${setStatements}
717
+ localStorage.setItem('__codeyam_ls_keys__', ${JSON.stringify(JSON.stringify(keys))});
718
+ localStorage.setItem('__codeyam_ls_sid__', ${JSON.stringify(guardValue)});
719
+ })();
720
+ </script>` + buildLocalStorageWatcherScript());
721
+ }
722
+ /**
723
+ * Build a script that watches for localStorage mutations and notifies the parent
724
+ * frame via postMessage. Also responds to `codeyam-get-localstorage` requests so
725
+ * the editor can read the current localStorage state when saving.
726
+ */
727
+ function buildLocalStorageWatcherScript() {
728
+ return `<script data-codeyam-ls-watcher>
729
+ (function() {
730
+ if (window.__codeyam_ls_watcher_installed__) return;
731
+ window.__codeyam_ls_watcher_installed__ = true;
732
+
733
+ var origSet = localStorage.setItem.bind(localStorage);
734
+ var origRemove = localStorage.removeItem.bind(localStorage);
735
+ var origClear = localStorage.clear.bind(localStorage);
736
+ window.__codeyam_orig_setItem__ = origSet;
737
+ window.__codeyam_orig_removeItem__ = origRemove;
738
+ window.__codeyam_orig_clear__ = origClear;
739
+
740
+ function isInternal(key) {
741
+ return typeof key === 'string' && key.indexOf('__codeyam_') === 0;
742
+ }
743
+
744
+ localStorage.setItem = function(key, value) {
745
+ origSet(key, value);
746
+ if (!isInternal(key) && window.parent !== window) {
747
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'set', key: key }, '*');
748
+ }
749
+ };
750
+
751
+ localStorage.removeItem = function(key) {
752
+ origRemove(key);
753
+ if (!isInternal(key) && window.parent !== window) {
754
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'remove', key: key }, '*');
755
+ }
756
+ };
757
+
758
+ localStorage.clear = function() {
759
+ origClear();
760
+ if (window.parent !== window) {
761
+ window.parent.postMessage({ type: 'codeyam-localstorage-changed', action: 'clear' }, '*');
762
+ }
763
+ };
764
+
765
+ window.addEventListener('message', function(event) {
766
+ if (event.data && event.data.type === 'codeyam-get-localstorage') {
767
+ var data = {};
768
+ for (var i = 0; i < localStorage.length; i++) {
769
+ var k = localStorage.key(i);
770
+ if (k && !isInternal(k)) {
771
+ data[k] = localStorage.getItem(k);
772
+ }
773
+ }
774
+ event.source.postMessage({ type: 'codeyam-localstorage-state', data: data }, '*');
775
+ }
776
+ });
777
+ })();
778
+ </script>`;
779
+ }
780
+ /**
781
+ * Inject the health-check script (and optional localStorage script) into an HTML response body.
782
+ * Inserts before </head> if present, otherwise before </body>, otherwise appends.
783
+ * When a localStorageScript is provided, it's injected BEFORE the health script
784
+ * so localStorage is populated before the app loads.
785
+ */
786
+ export function injectHealthScript(html, localStorageScript) {
787
+ const scripts = (localStorageScript || '') + PREVIEW_HEALTH_SCRIPT;
788
+ if (html.includes('</head>')) {
789
+ return html.replace('</head>', scripts + '</head>');
790
+ }
791
+ if (html.includes('</body>')) {
792
+ return html.replace('</body>', scripts + '</body>');
793
+ }
794
+ return html + scripts;
795
+ }
796
+ /**
797
+ * Escape HTML special characters to prevent XSS when embedding
798
+ * dev server error output into the error page.
799
+ */
800
+ export function escapeHtml(str) {
801
+ return str
802
+ .replace(/&/g, '&amp;')
803
+ .replace(/</g, '&lt;')
804
+ .replace(/>/g, '&gt;')
805
+ .replace(/"/g, '&quot;')
806
+ .replace(/'/g, '&#39;');
807
+ }
808
+ /**
809
+ * Build a self-contained HTML error page for display in the preview iframe.
810
+ *
811
+ * - Sends `codeyam-server-error` postMessage to the parent editor on load
812
+ * so the editor can auto-restart the dev server.
813
+ * - Includes a "Retry" button that sends `codeyam-server-error-retry`.
814
+ * - Does NOT send `codeyam-preview-ready` (so the editor doesn't
815
+ * mistake the error page for a successful load).
816
+ */
817
+ export function buildErrorPage(statusCode, title, detail) {
818
+ const escapedDetail = escapeHtml(detail);
819
+ const escapedTitle = escapeHtml(title);
820
+ return `<!DOCTYPE html>
821
+ <html lang="en">
822
+ <head>
823
+ <meta charset="utf-8" />
824
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
825
+ <title>${escapedTitle}</title>
826
+ <style>
827
+ * { margin: 0; padding: 0; box-sizing: border-box; }
828
+ body {
829
+ background: #1e1e1e;
830
+ color: #e0e0e0;
831
+ font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
832
+ display: flex;
833
+ align-items: center;
834
+ justify-content: center;
835
+ min-height: 100vh;
836
+ padding: 24px;
837
+ }
838
+ .container {
839
+ max-width: 560px;
840
+ width: 100%;
841
+ text-align: center;
842
+ }
843
+ .status-code {
844
+ font-size: 48px;
845
+ font-weight: 600;
846
+ color: #f87171;
847
+ line-height: 1;
848
+ margin-bottom: 8px;
849
+ }
850
+ .title {
851
+ font-size: 18px;
852
+ font-weight: 500;
853
+ color: #f87171;
854
+ margin-bottom: 16px;
855
+ }
856
+ .detail {
857
+ background: #2a2a2a;
858
+ border: 1px solid #3a3a3a;
859
+ border-radius: 6px;
860
+ padding: 16px;
861
+ margin-bottom: 20px;
862
+ max-height: 240px;
863
+ overflow: auto;
864
+ text-align: left;
865
+ }
866
+ .detail pre {
867
+ font-family: 'IBM Plex Mono', monospace;
868
+ font-size: 12px;
869
+ color: #b0b0b0;
870
+ white-space: pre-wrap;
871
+ word-break: break-word;
872
+ }
873
+ .message {
874
+ font-size: 13px;
875
+ color: #888;
876
+ margin-bottom: 16px;
877
+ }
878
+ button {
879
+ background: #005c75;
880
+ color: white;
881
+ border: none;
882
+ border-radius: 4px;
883
+ padding: 8px 20px;
884
+ font-size: 14px;
885
+ font-weight: 500;
886
+ cursor: pointer;
887
+ transition: background 0.15s;
888
+ }
889
+ button:hover { background: #004d63; }
890
+ </style>
891
+ </head>
892
+ <body>
893
+ <div class="container">
894
+ <div class="status-code">${statusCode}</div>
895
+ <div class="title">${escapedTitle}</div>
896
+ <div class="detail"><pre>${escapedDetail}</pre></div>
897
+ <p class="message">Attempting to restart the dev server...</p>
898
+ <button onclick="window.parent.postMessage({type:'codeyam-server-error-retry'},'*')">Retry</button>
899
+ </div>
900
+ <script>
901
+ try { window.parent.postMessage({type:'codeyam-server-error',statusCode:${statusCode}},'*'); } catch(e) {}
902
+ </script>
903
+ </body>
904
+ </html>`;
905
+ }
906
+ /**
907
+ * Handle POST /__codeyam__/preview-health — store health data in globalThis.
908
+ */
909
+ function handlePreviewHealthPost(req, res) {
910
+ const chunks = [];
911
+ req.on('data', (chunk) => chunks.push(chunk));
912
+ req.on('end', () => {
913
+ try {
914
+ const body = JSON.parse(Buffer.concat(chunks).toString('utf-8'));
915
+ const current = getPreviewHealth() || {
916
+ errors: [],
917
+ loaded: false,
918
+ hasContent: false,
919
+ url: '',
920
+ lastUpdated: 0,
921
+ };
922
+ if (body.errors && Array.isArray(body.errors)) {
923
+ current.errors = current.errors.concat(body.errors);
924
+ }
925
+ if (body.loaded !== undefined) {
926
+ current.loaded = body.loaded;
927
+ }
928
+ if (body.hasContent !== undefined) {
929
+ current.hasContent = body.hasContent;
930
+ }
931
+ if (body.url) {
932
+ current.url = body.url;
933
+ }
934
+ current.lastUpdated = Date.now();
935
+ setPreviewHealth(current);
936
+ }
937
+ catch {
938
+ // Ignore malformed JSON
939
+ }
940
+ res.writeHead(204);
941
+ res.end();
942
+ });
943
+ }
308
944
  /**
309
945
  * Handle WebSocket upgrade by piping to the target dev server.
310
946
  */
@@ -375,7 +1011,13 @@ function removeProxyConfig() {
375
1011
  * Supports all HTTP methods (GET, POST, PUT, DELETE, PATCH) with body buffering.
376
1012
  */
377
1013
  export async function startEditorProxy(options) {
378
- // Stop existing proxy first
1014
+ // If proxy is already running, reuse it (prevents second tab from killing first tab's proxy)
1015
+ const existing = getProxyState();
1016
+ if (existing) {
1017
+ console.log(`[editorProxy] Proxy already running on port ${existing.port} → ${existing.targetUrl}`);
1018
+ return { port: existing.port };
1019
+ }
1020
+ // Stop any leftover state (shouldn't happen, but defensive)
379
1021
  await stopEditorProxy();
380
1022
  let targetUrl = normalizeTargetUrl(options.targetUrl);
381
1023
  let port = options.port;
@@ -415,6 +1057,11 @@ export async function startEditorProxy(options) {
415
1057
  res.end();
416
1058
  return;
417
1059
  }
1060
+ // Intercept preview health reports from the injected script
1061
+ if (method === 'POST' && pathname === '/__codeyam__/preview-health') {
1062
+ handlePreviewHealthPost(req, res);
1063
+ return;
1064
+ }
418
1065
  // Load scenario data (also feeds MockStateManager)
419
1066
  readScenarioData();
420
1067
  // For methods that may carry a body, buffer it first
@@ -446,11 +1093,17 @@ export async function startEditorProxy(options) {
446
1093
  'Content-Type': 'application/json',
447
1094
  'Access-Control-Allow-Origin': '*',
448
1095
  'X-CodeYam-Proxy': 'scenario-data',
1096
+ 'Cache-Control': 'no-store',
449
1097
  });
450
1098
  res.end(match.body != null ? JSON.stringify(match.body) : '');
451
1099
  return;
452
1100
  }
453
1101
  // No mock match — forward with buffered body
1102
+ if ((currentScenarioType === 'application' ||
1103
+ currentScenarioType === 'user') &&
1104
+ pathname.startsWith('/api/')) {
1105
+ mockStateEventEmitter.emitDataMutationForwarded(method, pathname);
1106
+ }
454
1107
  forwardBufferedRequest(req, res, targetUrl, bodyBuffer);
455
1108
  return;
456
1109
  }
@@ -462,6 +1115,7 @@ export async function startEditorProxy(options) {
462
1115
  'Content-Type': 'application/json',
463
1116
  'Access-Control-Allow-Origin': '*',
464
1117
  'X-CodeYam-Proxy': 'scenario-data',
1118
+ 'Cache-Control': 'no-store',
465
1119
  });
466
1120
  res.end(match.body != null ? JSON.stringify(match.body) : '');
467
1121
  return;
@@ -533,6 +1187,10 @@ export async function stopEditorProxy() {
533
1187
  export function invalidateScenarioCache() {
534
1188
  scenarioCache = { data: null, timestamp: 0 };
535
1189
  sessionConfig = undefined;
1190
+ seedSessionCookies = undefined;
1191
+ localStorageConfig = null;
1192
+ activeScenarioId = null;
1193
+ currentPrototypeId = null;
536
1194
  }
537
1195
  /**
538
1196
  * Verify that the proxy can successfully forward a request to the target dev server.