@codeyam/codeyam-cli 0.1.8 → 0.1.9

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 (335) 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/generateExecutionFlows.ts +0 -33
  5. package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +13 -7
  6. package/analyzer-template/packages/analyze/src/lib/asts/index.ts +7 -2
  7. package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +0 -98
  8. package/analyzer-template/packages/aws/package.json +1 -1
  9. package/analyzer-template/packages/database/src/lib/kysely/tables/editorScenariosTable.ts +31 -0
  10. package/analyzer-template/packages/database/src/lib/loadEntities.ts +0 -6
  11. package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +0 -65
  12. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts +5 -0
  13. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.d.ts.map +1 -1
  14. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js +31 -0
  15. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  16. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
  17. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +0 -6
  18. package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
  19. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
  20. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +0 -25
  21. package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
  22. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts +2 -0
  23. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
  24. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js +2 -0
  25. package/analyzer-template/packages/github/dist/types/src/enums/ProjectFramework.js.map +1 -1
  26. package/analyzer-template/packages/types/src/enums/ProjectFramework.ts +2 -0
  27. package/analyzer-template/packages/ui-components/package.json +1 -1
  28. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts +2 -0
  29. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.d.ts.map +1 -1
  30. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js +2 -0
  31. package/analyzer-template/packages/utils/dist/types/src/enums/ProjectFramework.js.map +1 -1
  32. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js +196 -0
  33. package/codeyam-cli/src/__tests__/memory-scripts/filter-session.test.js.map +1 -0
  34. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js +114 -0
  35. package/codeyam-cli/src/__tests__/memory-scripts/read-json-field.test.js.map +1 -0
  36. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js +149 -0
  37. package/codeyam-cli/src/__tests__/memory-scripts/ripgrep-fallback.test.js.map +1 -0
  38. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js +45 -0
  39. package/codeyam-cli/src/commands/__tests__/editor.stepDispatch.test.js.map +1 -0
  40. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js +101 -47
  41. package/codeyam-cli/src/commands/__tests__/init.gitignore.test.js.map +1 -1
  42. package/codeyam-cli/src/commands/default.js +3 -46
  43. package/codeyam-cli/src/commands/default.js.map +1 -1
  44. package/codeyam-cli/src/commands/editor.js +1619 -243
  45. package/codeyam-cli/src/commands/editor.js.map +1 -1
  46. package/codeyam-cli/src/commands/init.js +67 -34
  47. package/codeyam-cli/src/commands/init.js.map +1 -1
  48. package/codeyam-cli/src/data/techStacks.js +77 -0
  49. package/codeyam-cli/src/data/techStacks.js.map +1 -0
  50. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js +144 -0
  51. package/codeyam-cli/src/utils/__tests__/analyzerFinalization.test.js.map +1 -0
  52. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js +46 -0
  53. package/codeyam-cli/src/utils/__tests__/backgroundServer.test.js.map +1 -0
  54. package/codeyam-cli/src/utils/__tests__/devServerState.test.js +134 -0
  55. package/codeyam-cli/src/utils/__tests__/devServerState.test.js.map +1 -0
  56. package/codeyam-cli/src/utils/__tests__/editorApi.test.js +127 -0
  57. package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -0
  58. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +610 -1
  59. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  60. package/codeyam-cli/src/utils/__tests__/editorCapture.test.js +93 -0
  61. package/codeyam-cli/src/utils/__tests__/editorCapture.test.js.map +1 -0
  62. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js +181 -3
  63. package/codeyam-cli/src/utils/__tests__/editorDevServer.test.js.map +1 -1
  64. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +121 -0
  65. package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -0
  66. package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js +294 -0
  67. package/codeyam-cli/src/utils/__tests__/editorImageVerifier.test.js.map +1 -0
  68. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js +249 -2
  69. package/codeyam-cli/src/utils/__tests__/editorJournal.test.js.map +1 -1
  70. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js +520 -0
  71. package/codeyam-cli/src/utils/__tests__/editorLoaderHelpers.test.js.map +1 -0
  72. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js +118 -1
  73. package/codeyam-cli/src/utils/__tests__/editorPreloadHelpers.test.js.map +1 -1
  74. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js +195 -3
  75. package/codeyam-cli/src/utils/__tests__/editorPreview.test.js.map +1 -1
  76. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js +153 -0
  77. package/codeyam-cli/src/utils/__tests__/editorProxySession.test.js.map +1 -0
  78. package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js +139 -0
  79. package/codeyam-cli/src/utils/__tests__/editorScenarioLookup.test.js.map +1 -0
  80. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +221 -0
  81. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -0
  82. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +781 -2
  83. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
  84. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +213 -0
  85. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -0
  86. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +1742 -0
  87. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -0
  88. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js +107 -0
  89. package/codeyam-cli/src/utils/__tests__/journalCaptureStabilization.test.js.map +1 -0
  90. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js +101 -0
  91. package/codeyam-cli/src/utils/__tests__/parseRegisterArg.test.js.map +1 -0
  92. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +227 -0
  93. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -0
  94. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +300 -0
  95. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -0
  96. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +25 -5
  97. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
  98. package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js +51 -0
  99. package/codeyam-cli/src/utils/__tests__/templateConsistency.test.js.map +1 -0
  100. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js +142 -0
  101. package/codeyam-cli/src/utils/__tests__/webappDetection.test.js.map +1 -0
  102. package/codeyam-cli/src/utils/analyzer.js +9 -0
  103. package/codeyam-cli/src/utils/analyzer.js.map +1 -1
  104. package/codeyam-cli/src/utils/analyzerFinalization.js +96 -0
  105. package/codeyam-cli/src/utils/analyzerFinalization.js.map +1 -0
  106. package/codeyam-cli/src/utils/backgroundServer.js +94 -18
  107. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  108. package/codeyam-cli/src/utils/database.js +37 -2
  109. package/codeyam-cli/src/utils/database.js.map +1 -1
  110. package/codeyam-cli/src/utils/devServerState.js +71 -0
  111. package/codeyam-cli/src/utils/devServerState.js.map +1 -0
  112. package/codeyam-cli/src/utils/editorApi.js +73 -0
  113. package/codeyam-cli/src/utils/editorApi.js.map +1 -0
  114. package/codeyam-cli/src/utils/editorAudit.js +101 -7
  115. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  116. package/codeyam-cli/src/utils/editorCapture.js +102 -0
  117. package/codeyam-cli/src/utils/editorCapture.js.map +1 -0
  118. package/codeyam-cli/src/utils/editorDevServer.js +100 -1
  119. package/codeyam-cli/src/utils/editorDevServer.js.map +1 -1
  120. package/codeyam-cli/src/utils/editorEntityChangeStatus.js +44 -0
  121. package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -0
  122. package/codeyam-cli/src/utils/editorImageVerifier.js +155 -0
  123. package/codeyam-cli/src/utils/editorImageVerifier.js.map +1 -0
  124. package/codeyam-cli/src/utils/editorJournal.js +92 -4
  125. package/codeyam-cli/src/utils/editorJournal.js.map +1 -1
  126. package/codeyam-cli/src/utils/editorLoaderHelpers.js +113 -0
  127. package/codeyam-cli/src/utils/editorLoaderHelpers.js.map +1 -0
  128. package/codeyam-cli/src/utils/editorMockState.js +1 -1
  129. package/codeyam-cli/src/utils/editorPreloadHelpers.js +72 -1
  130. package/codeyam-cli/src/utils/editorPreloadHelpers.js.map +1 -1
  131. package/codeyam-cli/src/utils/editorPreview.js +67 -1
  132. package/codeyam-cli/src/utils/editorPreview.js.map +1 -1
  133. package/codeyam-cli/src/utils/editorScenarioSwitch.js +112 -0
  134. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -0
  135. package/codeyam-cli/src/utils/editorScenarios.js +276 -0
  136. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
  137. package/codeyam-cli/src/utils/editorSeedAdapter.js +173 -0
  138. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -0
  139. package/codeyam-cli/src/utils/entityChangeStatus.js +349 -0
  140. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -0
  141. package/codeyam-cli/src/utils/entityChangeStatus.server.js +158 -0
  142. package/codeyam-cli/src/utils/entityChangeStatus.server.js.map +1 -0
  143. package/codeyam-cli/src/utils/install-skills.js +1 -1
  144. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  145. package/codeyam-cli/src/utils/parseRegisterArg.js +31 -0
  146. package/codeyam-cli/src/utils/parseRegisterArg.js.map +1 -0
  147. package/codeyam-cli/src/utils/scenarioCoverage.js +75 -0
  148. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -0
  149. package/codeyam-cli/src/utils/scenariosManifest.js +159 -0
  150. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -0
  151. package/codeyam-cli/src/utils/serverState.js +30 -0
  152. package/codeyam-cli/src/utils/serverState.js.map +1 -1
  153. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +46 -16
  154. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
  155. package/codeyam-cli/src/utils/simulationGateMiddleware.js +8 -1
  156. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
  157. package/codeyam-cli/src/utils/slugUtils.js +25 -0
  158. package/codeyam-cli/src/utils/slugUtils.js.map +1 -0
  159. package/codeyam-cli/src/utils/syncMocksMiddleware.js +2 -2
  160. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  161. package/codeyam-cli/src/utils/webappDetection.js +21 -0
  162. package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
  163. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +40 -0
  164. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -0
  165. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +567 -0
  166. package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -0
  167. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +65 -0
  168. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -0
  169. package/codeyam-cli/src/webserver/app/lib/git.js +397 -0
  170. package/codeyam-cli/src/webserver/app/lib/git.js.map +1 -0
  171. package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-DmJveP3T.js → CopyButton-BPXZwM4t.js} +1 -1
  172. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-C76mRRiF.js → EntityItem-BcgbViKV.js} +3 -3
  173. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CobE682z.js → EntityTypeIcon-CQIG2qda.js} +9 -9
  174. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-djPLI-WV.js → ReportIssueModal-BzHcG7SE.js} +3 -3
  175. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-B76aig_2.js → ScenarioViewer-Bd-hxofb.js} +3 -3
  176. package/codeyam-cli/src/webserver/build/client/assets/ViewportInspectBar-oAf2Kqsf.js +1 -0
  177. package/codeyam-cli/src/webserver/build/client/assets/{_index-C96V0n15.js → _index-DLxKhri3.js} +3 -3
  178. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BpKzcsJz.js → activity.(_tab)-BcY3q6nt.js} +6 -6
  179. package/codeyam-cli/src/webserver/build/client/assets/addon-canvas-DpzMmAy5.js +1 -0
  180. package/codeyam-cli/src/webserver/build/client/assets/addon-fit-YJmn1quW.js +12 -0
  181. package/codeyam-cli/src/webserver/build/client/assets/addon-webgl-DI8QOUvO.js +58 -0
  182. package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-D9hemwl6.js → agent-transcripts-Bni3iiUj.js} +5 -5
  183. package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-diff-l0sNRNKZ.js +1 -0
  184. package/codeyam-cli/src/webserver/build/client/assets/api.editor-file-l0sNRNKZ.js +1 -0
  185. package/codeyam-cli/src/webserver/build/client/assets/api.editor-project-info-l0sNRNKZ.js +1 -0
  186. package/codeyam-cli/src/webserver/build/client/assets/api.editor-scenario-coverage-l0sNRNKZ.js +1 -0
  187. package/codeyam-cli/src/webserver/build/client/assets/{book-open-D_nMCFmP.js → book-open-BYOypzCa.js} +2 -2
  188. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-BH2h1Ea2.js → chevron-down-C_Pmso5S.js} +2 -2
  189. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-DyIKORY6.js → circle-check-BVMi9VA5.js} +2 -2
  190. package/codeyam-cli/src/webserver/build/client/assets/{copy-NDbZjXao.js → copy-n2FB0_Sw.js} +3 -3
  191. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CC6AbExI.js +41 -0
  192. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BsDh6TSF.js +1 -0
  193. package/codeyam-cli/src/webserver/build/client/assets/editor-PBc_6L9R.js +10 -0
  194. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-4FzHlcNn.js +41 -0
  195. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CrjR3zZW.js → entity._sha._-BsDXNp45.js} +3 -3
  196. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-BgAqUtTZ.js +6 -0
  197. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-Bmshgrij.js +6 -0
  198. package/codeyam-cli/src/webserver/build/client/assets/{files-DO4CZ16O.js → files-BZrlFE1F.js} +1 -1
  199. package/codeyam-cli/src/webserver/build/client/assets/git-DdZcvjGh.js +1 -0
  200. package/codeyam-cli/src/webserver/build/client/assets/globals-B8vTTNy2.css +1 -0
  201. package/codeyam-cli/src/webserver/build/client/assets/index-yHOVb4rc.js +15 -0
  202. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BAXYRVEO.js → loader-circle-DaAZ_H2w.js} +2 -2
  203. package/codeyam-cli/src/webserver/build/client/assets/manifest-65850841.js +1 -0
  204. package/codeyam-cli/src/webserver/build/client/assets/memory-9gnxSZlb.js +101 -0
  205. package/codeyam-cli/src/webserver/build/client/assets/{pause-DTAcYxBt.js → pause-f5-1lKBt.js} +3 -3
  206. package/codeyam-cli/src/webserver/build/client/assets/root-BwX8YgFb.js +67 -0
  207. package/codeyam-cli/src/webserver/build/client/assets/{search-fKo7v0Zo.js → search-Di64LWVb.js} +2 -2
  208. package/codeyam-cli/src/webserver/build/client/assets/{settings-DfuTtcJP.js → settings-0OrEMU6J.js} +1 -1
  209. package/codeyam-cli/src/webserver/build/client/assets/{simulations-B3aOzpCZ.js → simulations-DWT-CvLy.js} +1 -1
  210. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BG4heKCG.js → terminal-Br7MOqts.js} +3 -3
  211. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-DtSmdtM4.js → triangle-alert-BLdiCuG-.js} +2 -2
  212. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BE43Hjti.js +1 -0
  213. package/codeyam-cli/src/webserver/build/server/assets/index-DEEQf4pi.js +1 -0
  214. package/codeyam-cli/src/webserver/build/server/assets/init-CkWmyFY2.js +10 -0
  215. package/codeyam-cli/src/webserver/build/server/assets/server-build-BHi-9O8W.js +439 -0
  216. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  217. package/codeyam-cli/src/webserver/build-info.json +5 -5
  218. package/codeyam-cli/src/webserver/editorProxy.js +487 -50
  219. package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
  220. package/codeyam-cli/src/webserver/scripts/codeyam-preload.mjs +242 -3
  221. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +94 -4
  222. package/codeyam-cli/src/webserver/server.js +46 -14
  223. package/codeyam-cli/src/webserver/server.js.map +1 -1
  224. package/codeyam-cli/src/webserver/terminalServer.js +39 -11
  225. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  226. package/codeyam-cli/templates/chrome-extension-react/EXTENSION_SETUP.md +75 -0
  227. package/codeyam-cli/templates/chrome-extension-react/README.md +46 -0
  228. package/codeyam-cli/templates/chrome-extension-react/gitignore +15 -0
  229. package/codeyam-cli/templates/chrome-extension-react/index.html +12 -0
  230. package/codeyam-cli/templates/chrome-extension-react/package.json +27 -0
  231. package/codeyam-cli/templates/chrome-extension-react/popup.html +12 -0
  232. package/codeyam-cli/templates/chrome-extension-react/public/manifest.json +15 -0
  233. package/codeyam-cli/templates/chrome-extension-react/src/background/service-worker.ts +7 -0
  234. package/codeyam-cli/templates/chrome-extension-react/src/globals.css +6 -0
  235. package/codeyam-cli/templates/chrome-extension-react/src/lib/storage.ts +37 -0
  236. package/codeyam-cli/templates/chrome-extension-react/src/popup/App.tsx +12 -0
  237. package/codeyam-cli/templates/chrome-extension-react/src/popup/main.tsx +10 -0
  238. package/codeyam-cli/templates/chrome-extension-react/tsconfig.json +24 -0
  239. package/codeyam-cli/templates/chrome-extension-react/vite.config.ts +41 -0
  240. package/codeyam-cli/templates/codeyam-editor-claude.md +84 -5
  241. package/codeyam-cli/templates/editor-step-hook.py +97 -8
  242. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +89 -0
  243. package/codeyam-cli/templates/expo-react-native/README.md +41 -0
  244. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +33 -0
  245. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +12 -0
  246. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +12 -0
  247. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +12 -0
  248. package/codeyam-cli/templates/expo-react-native/app.json +18 -0
  249. package/codeyam-cli/templates/expo-react-native/babel.config.js +9 -0
  250. package/codeyam-cli/templates/expo-react-native/gitignore +12 -0
  251. package/codeyam-cli/templates/expo-react-native/global.css +3 -0
  252. package/codeyam-cli/templates/expo-react-native/lib/storage.ts +32 -0
  253. package/codeyam-cli/templates/expo-react-native/metro.config.js +6 -0
  254. package/codeyam-cli/templates/expo-react-native/nativewind-env.d.ts +1 -0
  255. package/codeyam-cli/templates/expo-react-native/package.json +38 -0
  256. package/codeyam-cli/templates/expo-react-native/tailwind.config.js +10 -0
  257. package/codeyam-cli/templates/expo-react-native/tsconfig.json +10 -0
  258. package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_PATTERNS.md +308 -0
  259. package/codeyam-cli/templates/nextjs-prisma-sqlite/AUTH_UPGRADE.md +304 -0
  260. package/codeyam-cli/templates/nextjs-prisma-sqlite/DATABASE.md +126 -0
  261. package/codeyam-cli/templates/nextjs-prisma-sqlite/FEATURE_PATTERNS.md +37 -0
  262. package/codeyam-cli/templates/nextjs-prisma-sqlite/README.md +53 -0
  263. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/codeyam-isolate/layout.tsx +12 -0
  264. package/codeyam-cli/templates/nextjs-prisma-sqlite/app/lib/prisma.ts +9 -4
  265. package/codeyam-cli/templates/nextjs-prisma-sqlite/env +4 -0
  266. package/codeyam-cli/templates/nextjs-prisma-sqlite/gitignore +21 -0
  267. package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +5 -1
  268. package/codeyam-cli/templates/nextjs-prisma-sqlite/prisma/seed.ts +4 -1
  269. package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +92 -0
  270. package/codeyam-cli/templates/nextjs-prisma-sqlite/vitest.config.ts +13 -0
  271. package/codeyam-cli/templates/nextjs-prisma-supabase/README.md +52 -0
  272. package/codeyam-cli/templates/{nextjs-prisma-sqlite/PRISMA_SETUP.md → nextjs-prisma-supabase/SUPABASE_SETUP.md} +37 -17
  273. package/codeyam-cli/templates/nextjs-prisma-supabase/app/api/todos/route.ts +17 -0
  274. package/codeyam-cli/templates/nextjs-prisma-supabase/app/globals.css +26 -0
  275. package/codeyam-cli/templates/nextjs-prisma-supabase/app/layout.tsx +34 -0
  276. package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/prisma.ts +20 -0
  277. package/codeyam-cli/templates/nextjs-prisma-supabase/app/lib/supabase.ts +12 -0
  278. package/codeyam-cli/templates/nextjs-prisma-supabase/app/page.tsx +10 -0
  279. package/codeyam-cli/templates/nextjs-prisma-supabase/env +9 -0
  280. package/codeyam-cli/templates/nextjs-prisma-supabase/eslint.config.mjs +11 -0
  281. package/codeyam-cli/templates/nextjs-prisma-supabase/gitignore +40 -0
  282. package/codeyam-cli/templates/nextjs-prisma-supabase/next.config.ts +11 -0
  283. package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +37 -0
  284. package/codeyam-cli/templates/nextjs-prisma-supabase/postcss.config.mjs +7 -0
  285. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/schema.prisma +27 -0
  286. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma/seed.ts +39 -0
  287. package/codeyam-cli/templates/nextjs-prisma-supabase/prisma.config.ts +12 -0
  288. package/codeyam-cli/templates/nextjs-prisma-supabase/tsconfig.json +34 -0
  289. package/codeyam-cli/templates/skills/codeyam-dev-mode/SKILL.md +2 -2
  290. package/codeyam-cli/templates/skills/codeyam-editor/SKILL.md +96 -17
  291. package/codeyam-cli/templates/skills/codeyam-memory/SKILL.md +10 -10
  292. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.mjs +139 -0
  293. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.mjs +52 -0
  294. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/read-json-field.mjs +61 -0
  295. package/codeyam-cli/templates/skills/codeyam-memory/scripts/lib/ripgrep-fallback.mjs +155 -0
  296. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.mjs +13 -0
  297. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter-session.mjs +95 -0
  298. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.mjs +160 -0
  299. package/package.json +14 -9
  300. package/packages/ai/src/lib/generateExecutionFlows.js +0 -11
  301. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  302. package/packages/analyze/src/lib/ProjectAnalyzer.js +10 -4
  303. package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
  304. package/packages/analyze/src/lib/asts/index.js +4 -2
  305. package/packages/analyze/src/lib/asts/index.js.map +1 -1
  306. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +0 -40
  307. package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
  308. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js +31 -0
  309. package/packages/database/src/lib/kysely/tables/editorScenariosTable.js.map +1 -1
  310. package/packages/database/src/lib/loadEntities.js +0 -6
  311. package/packages/database/src/lib/loadEntities.js.map +1 -1
  312. package/packages/database/src/lib/updateCommitMetadata.js +0 -25
  313. package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
  314. package/packages/types/src/enums/ProjectFramework.js +2 -0
  315. package/packages/types/src/enums/ProjectFramework.js.map +1 -1
  316. package/codeyam-cli/src/webserver/build/client/assets/Terminal-Dnj5CY9R.js +0 -41
  317. package/codeyam-cli/src/webserver/build/client/assets/addon-fit-CUXOrorO.js +0 -1
  318. package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-CMT1jU2q.js +0 -21
  319. package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BiM6z3Do.js +0 -1
  320. package/codeyam-cli/src/webserver/build/client/assets/editor-D1DAKXtT.js +0 -8
  321. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.dev-DkzqFzFj.js +0 -6
  322. package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-C28BiQzt.js +0 -6
  323. package/codeyam-cli/src/webserver/build/client/assets/git-CFCTYk9I.js +0 -15
  324. package/codeyam-cli/src/webserver/build/client/assets/globals-B17TBSS6.css +0 -1
  325. package/codeyam-cli/src/webserver/build/client/assets/manifest-a632de18.js +0 -1
  326. package/codeyam-cli/src/webserver/build/client/assets/memory-Dg0mvYrI.js +0 -96
  327. package/codeyam-cli/src/webserver/build/client/assets/root-DUKqhFlb.js +0 -67
  328. package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-ByhSyh0W.js +0 -1
  329. package/codeyam-cli/src/webserver/build/server/assets/index-HfLydfDq.js +0 -1
  330. package/codeyam-cli/src/webserver/build/server/assets/server-build-CUu_F-oo.js +0 -366
  331. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/detect-deprecated-patterns.sh +0 -108
  332. package/codeyam-cli/templates/skills/codeyam-memory/scripts/holistic-analysis/find-exports.sh +0 -69
  333. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/cleanup.sh +0 -12
  334. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/filter.jq +0 -45
  335. package/codeyam-cli/templates/skills/codeyam-memory/scripts/session-mining/preprocess.sh +0 -139
@@ -1,4 +1,4 @@
1
- import { isComponent, classifyGlossaryEntries, computeAudit, } from "../editorAudit.js";
1
+ import { isComponent, classifyGlossaryEntries, computeAudit, filterGlossaryByChangeStatus, resolveAuditSessionScope, } from "../editorAudit.js";
2
2
  describe('editorAudit', () => {
3
3
  describe('isComponent', () => {
4
4
  it('should return true for JSX.Element return type', () => {
@@ -241,6 +241,615 @@ describe('editorAudit', () => {
241
241
  expect(result.summary.functionsMissing).toBe(1);
242
242
  expect(result.summary.allPassing).toBe(false);
243
243
  });
244
+ // ── Test results integration ────────────────────────────────────
245
+ it('should mark function as ok when tests pass and describe matches entity name', () => {
246
+ const result = computeAudit({
247
+ components: [],
248
+ functions: [
249
+ {
250
+ name: 'calculatePrice',
251
+ filePath: 'app/lib/pricing.ts',
252
+ testFile: 'app/lib/pricing.test.ts',
253
+ },
254
+ ],
255
+ scenarioCounts: {},
256
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
257
+ testResults: {
258
+ 'app/lib/pricing.test.ts': {
259
+ passing: true,
260
+ hasEntityNameDescribe: true,
261
+ },
262
+ },
263
+ });
264
+ expect(result.functions[0].status).toBe('ok');
265
+ expect(result.functions[0].testsPassing).toBe(true);
266
+ expect(result.functions[0].testsVisibleInUi).toBe(true);
267
+ });
268
+ it('should mark function as failing when tests fail', () => {
269
+ const result = computeAudit({
270
+ components: [],
271
+ functions: [
272
+ {
273
+ name: 'calculatePrice',
274
+ filePath: 'app/lib/pricing.ts',
275
+ testFile: 'app/lib/pricing.test.ts',
276
+ },
277
+ ],
278
+ scenarioCounts: {},
279
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
280
+ testResults: {
281
+ 'app/lib/pricing.test.ts': {
282
+ passing: false,
283
+ hasEntityNameDescribe: true,
284
+ },
285
+ },
286
+ });
287
+ expect(result.functions[0].status).toBe('failing');
288
+ expect(result.functions[0].testsPassing).toBe(false);
289
+ expect(result.functions[0].testsVisibleInUi).toBe(true);
290
+ });
291
+ it('should mark function as name_mismatch when tests pass but no describe matches', () => {
292
+ const result = computeAudit({
293
+ components: [],
294
+ functions: [
295
+ {
296
+ name: 'useDrinks',
297
+ filePath: 'app/hooks/useDrinks.ts',
298
+ testFile: 'app/hooks/useDrinks.test.ts',
299
+ },
300
+ ],
301
+ scenarioCounts: {},
302
+ testFileExistence: { 'app/hooks/useDrinks.test.ts': true },
303
+ testResults: {
304
+ 'app/hooks/useDrinks.test.ts': {
305
+ passing: true,
306
+ hasEntityNameDescribe: false,
307
+ },
308
+ },
309
+ });
310
+ expect(result.functions[0].status).toBe('name_mismatch');
311
+ expect(result.functions[0].testsPassing).toBe(true);
312
+ expect(result.functions[0].testsVisibleInUi).toBe(false);
313
+ });
314
+ it('should still mark function as missing when test file does not exist even with testResults', () => {
315
+ const result = computeAudit({
316
+ components: [],
317
+ functions: [
318
+ {
319
+ name: 'calculatePrice',
320
+ filePath: 'app/lib/pricing.ts',
321
+ testFile: 'app/lib/pricing.test.ts',
322
+ },
323
+ ],
324
+ scenarioCounts: {},
325
+ testFileExistence: { 'app/lib/pricing.test.ts': false },
326
+ testResults: {},
327
+ });
328
+ expect(result.functions[0].status).toBe('missing');
329
+ expect(result.functions[0].testsPassing).toBeUndefined();
330
+ expect(result.functions[0].testsVisibleInUi).toBeUndefined();
331
+ });
332
+ it('should include functionsFailing and functionsNameMismatch in summary', () => {
333
+ const result = computeAudit({
334
+ components: [],
335
+ functions: [
336
+ {
337
+ name: 'fnOk',
338
+ filePath: 'a.ts',
339
+ testFile: 'a.test.ts',
340
+ },
341
+ {
342
+ name: 'fnFailing',
343
+ filePath: 'b.ts',
344
+ testFile: 'b.test.ts',
345
+ },
346
+ {
347
+ name: 'fnMismatch',
348
+ filePath: 'c.ts',
349
+ testFile: 'c.test.ts',
350
+ },
351
+ {
352
+ name: 'fnMissing',
353
+ filePath: 'd.ts',
354
+ testFile: 'd.test.ts',
355
+ },
356
+ ],
357
+ scenarioCounts: {},
358
+ testFileExistence: {
359
+ 'a.test.ts': true,
360
+ 'b.test.ts': true,
361
+ 'c.test.ts': true,
362
+ 'd.test.ts': false,
363
+ },
364
+ testResults: {
365
+ 'a.test.ts': { passing: true, hasEntityNameDescribe: true },
366
+ 'b.test.ts': { passing: false, hasEntityNameDescribe: true },
367
+ 'c.test.ts': { passing: true, hasEntityNameDescribe: false },
368
+ },
369
+ });
370
+ expect(result.summary.functionsOk).toBe(1);
371
+ expect(result.summary.functionsFailing).toBe(1);
372
+ expect(result.summary.functionsNameMismatch).toBe(1);
373
+ expect(result.summary.functionsMissing).toBe(1);
374
+ expect(result.summary.allPassing).toBe(false);
375
+ });
376
+ it('should set allPassing to true only when all functions are ok', () => {
377
+ const result = computeAudit({
378
+ components: [
379
+ { name: 'DrinkCard', filePath: 'app/components/DrinkCard.tsx' },
380
+ ],
381
+ functions: [
382
+ {
383
+ name: 'calculatePrice',
384
+ filePath: 'app/lib/pricing.ts',
385
+ testFile: 'app/lib/pricing.test.ts',
386
+ },
387
+ ],
388
+ scenarioCounts: { DrinkCard: 1 },
389
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
390
+ testResults: {
391
+ 'app/lib/pricing.test.ts': {
392
+ passing: true,
393
+ hasEntityNameDescribe: true,
394
+ },
395
+ },
396
+ });
397
+ expect(result.summary.allPassing).toBe(true);
398
+ });
399
+ it('should set allPassing to false when any function is failing', () => {
400
+ const result = computeAudit({
401
+ components: [],
402
+ functions: [
403
+ {
404
+ name: 'calculatePrice',
405
+ filePath: 'app/lib/pricing.ts',
406
+ testFile: 'app/lib/pricing.test.ts',
407
+ },
408
+ ],
409
+ scenarioCounts: {},
410
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
411
+ testResults: {
412
+ 'app/lib/pricing.test.ts': {
413
+ passing: false,
414
+ hasEntityNameDescribe: true,
415
+ },
416
+ },
417
+ });
418
+ expect(result.summary.allPassing).toBe(false);
419
+ });
420
+ it('should set allPassing to false when any function has name_mismatch', () => {
421
+ const result = computeAudit({
422
+ components: [],
423
+ functions: [
424
+ {
425
+ name: 'useDrinks',
426
+ filePath: 'app/hooks/useDrinks.ts',
427
+ testFile: 'app/hooks/useDrinks.test.ts',
428
+ },
429
+ ],
430
+ scenarioCounts: {},
431
+ testFileExistence: { 'app/hooks/useDrinks.test.ts': true },
432
+ testResults: {
433
+ 'app/hooks/useDrinks.test.ts': {
434
+ passing: true,
435
+ hasEntityNameDescribe: false,
436
+ },
437
+ },
438
+ });
439
+ expect(result.summary.allPassing).toBe(false);
440
+ });
441
+ it('should fall back to file-existence-only behavior when testResults is not provided', () => {
442
+ // Backward compat: no testResults → existing behavior
443
+ const result = computeAudit({
444
+ components: [],
445
+ functions: [
446
+ {
447
+ name: 'calculatePrice',
448
+ filePath: 'app/lib/pricing.ts',
449
+ testFile: 'app/lib/pricing.test.ts',
450
+ },
451
+ ],
452
+ scenarioCounts: {},
453
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
454
+ });
455
+ expect(result.functions[0].status).toBe('ok');
456
+ expect(result.functions[0].testsPassing).toBeUndefined();
457
+ expect(result.functions[0].testsVisibleInUi).toBeUndefined();
458
+ });
459
+ it('should fall back to file-existence-only when testResults is empty for a given file', () => {
460
+ const result = computeAudit({
461
+ components: [],
462
+ functions: [
463
+ {
464
+ name: 'calculatePrice',
465
+ filePath: 'app/lib/pricing.ts',
466
+ testFile: 'app/lib/pricing.test.ts',
467
+ },
468
+ ],
469
+ scenarioCounts: {},
470
+ testFileExistence: { 'app/lib/pricing.test.ts': true },
471
+ testResults: {},
472
+ });
473
+ // No test result for this file → fall back to existence check
474
+ expect(result.functions[0].status).toBe('ok');
475
+ expect(result.functions[0].testsPassing).toBeUndefined();
476
+ expect(result.functions[0].testsVisibleInUi).toBeUndefined();
477
+ });
478
+ // ── Client errors integration ─────────────────────────────────────
479
+ it('should mark component as has_errors when clientErrors reports errors', () => {
480
+ const result = computeAudit({
481
+ components: [
482
+ { name: 'DrinkInfo', filePath: 'app/components/DrinkInfo.tsx' },
483
+ ],
484
+ functions: [],
485
+ scenarioCounts: { DrinkInfo: 3 },
486
+ testFileExistence: {},
487
+ clientErrors: {
488
+ DrinkInfo: ['Cannot read properties of undefined'],
489
+ },
490
+ });
491
+ expect(result.components[0].status).toBe('has_errors');
492
+ expect(result.components[0].clientErrors).toEqual([
493
+ 'Cannot read properties of undefined',
494
+ ]);
495
+ expect(result.summary.componentsWithErrors).toBe(1);
496
+ expect(result.summary.allPassing).toBe(false);
497
+ });
498
+ it('should not count client errors for components with no scenarios', () => {
499
+ // If a component has no scenarios AND errors, it's still "missing"
500
+ // (errors come from scenarios, so if there are none, errors are stale)
501
+ const result = computeAudit({
502
+ components: [
503
+ { name: 'DrinkInfo', filePath: 'app/components/DrinkInfo.tsx' },
504
+ ],
505
+ functions: [],
506
+ scenarioCounts: {},
507
+ testFileExistence: {},
508
+ clientErrors: {
509
+ DrinkInfo: ['Cannot read properties of undefined'],
510
+ },
511
+ });
512
+ expect(result.components[0].status).toBe('missing');
513
+ });
514
+ it('should set allPassing false when any component has errors', () => {
515
+ const result = computeAudit({
516
+ components: [
517
+ { name: 'DrinkCard', filePath: 'app/components/DrinkCard.tsx' },
518
+ { name: 'DrinkInfo', filePath: 'app/components/DrinkInfo.tsx' },
519
+ ],
520
+ functions: [],
521
+ scenarioCounts: { DrinkCard: 2, DrinkInfo: 3 },
522
+ testFileExistence: {},
523
+ clientErrors: {
524
+ DrinkInfo: ['TypeError: something broke'],
525
+ },
526
+ });
527
+ expect(result.summary.allPassing).toBe(false);
528
+ expect(result.summary.componentsOk).toBe(1);
529
+ expect(result.summary.componentsWithErrors).toBe(1);
530
+ });
531
+ });
532
+ // ── filterGlossaryByChangeStatus ──────────────────────────────────
533
+ describe('filterGlossaryByChangeStatus', () => {
534
+ const allEntries = [
535
+ // Feature 1 components (unchanged)
536
+ {
537
+ name: 'StarRating',
538
+ filePath: 'app/components/StarRating.tsx',
539
+ returnType: 'JSX.Element',
540
+ },
541
+ {
542
+ name: 'CategoryBadge',
543
+ filePath: 'app/components/CategoryBadge.tsx',
544
+ returnType: 'JSX.Element',
545
+ },
546
+ {
547
+ name: 'DrinkCard',
548
+ filePath: 'app/components/DrinkCard.tsx',
549
+ returnType: 'JSX.Element',
550
+ },
551
+ // Feature 2 components (new)
552
+ {
553
+ name: 'HeroImage',
554
+ filePath: 'app/components/HeroImage.tsx',
555
+ returnType: 'JSX.Element',
556
+ },
557
+ {
558
+ name: 'ReviewCard',
559
+ filePath: 'app/components/ReviewCard.tsx',
560
+ returnType: 'JSX.Element',
561
+ },
562
+ // Feature 1 function (unchanged)
563
+ {
564
+ name: 'computeAvgRating',
565
+ filePath: 'app/lib/ratings.ts',
566
+ returnType: 'number',
567
+ testFile: 'app/lib/ratings.test.ts',
568
+ },
569
+ // Feature 2 function (new)
570
+ {
571
+ name: 'formatReviewCount',
572
+ filePath: 'app/lib/formatting.ts',
573
+ returnType: 'string',
574
+ testFile: 'app/lib/formatting.test.ts',
575
+ },
576
+ ];
577
+ it('should only include entries whose files are new, edited, or impacted', () => {
578
+ const entityChangeStatus = {
579
+ HeroImage: { status: 'new' },
580
+ ReviewCard: { status: 'new' },
581
+ formatReviewCount: { status: 'new' },
582
+ // DrinkCard edited because it now links to detail page
583
+ DrinkCard: { status: 'edited' },
584
+ // StarRating impacted because DrinkInfo uses it
585
+ StarRating: {
586
+ status: 'impacted',
587
+ impactedBy: [
588
+ {
589
+ name: 'DrinkInfo',
590
+ filePath: 'app/components/DrinkInfo.tsx',
591
+ changeType: 'new',
592
+ },
593
+ ],
594
+ },
595
+ };
596
+ const filtered = filterGlossaryByChangeStatus(allEntries, entityChangeStatus);
597
+ const names = filtered.map((e) => e.name).sort();
598
+ expect(names).toEqual([
599
+ 'DrinkCard',
600
+ 'HeroImage',
601
+ 'ReviewCard',
602
+ 'StarRating',
603
+ 'formatReviewCount',
604
+ ]);
605
+ });
606
+ it('should return all entries when entityChangeStatus is empty', () => {
607
+ // When there's no change status data (e.g., no git changes), fall back to auditing everything
608
+ const filtered = filterGlossaryByChangeStatus(allEntries, {});
609
+ expect(filtered).toEqual(allEntries);
610
+ });
611
+ it('should return all entries when entityChangeStatus is undefined', () => {
612
+ const filtered = filterGlossaryByChangeStatus(allEntries, undefined);
613
+ expect(filtered).toEqual(allEntries);
614
+ });
615
+ it('should exclude unchanged entries that have no status', () => {
616
+ const entityChangeStatus = {
617
+ HeroImage: { status: 'new' },
618
+ };
619
+ const filtered = filterGlossaryByChangeStatus(allEntries, entityChangeStatus);
620
+ expect(filtered).toHaveLength(1);
621
+ expect(filtered[0].name).toBe('HeroImage');
622
+ });
623
+ it('should match entries by filePath when name does not match any status key', () => {
624
+ // Sometimes entity names in entityChangeStatus are derived from file paths
625
+ // and may not exactly match glossary names. Fall back to filePath matching.
626
+ const entityChangeStatus = {
627
+ // Entity name derived differently, but filePath matches
628
+ 'app/components/DrinkCard.tsx': { status: 'edited' },
629
+ };
630
+ const filtered = filterGlossaryByChangeStatus(allEntries, entityChangeStatus);
631
+ expect(filtered.map((e) => e.name)).toContain('DrinkCard');
632
+ });
633
+ });
634
+ // ── resolveAuditSessionScope ──────────────────────────────────────
635
+ describe('resolveAuditSessionScope', () => {
636
+ it('should scope to session when entityChangeStatus has entries and featureStartedAt exists', () => {
637
+ const result = resolveAuditSessionScope({
638
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
639
+ entityChangeStatus: {
640
+ ArticleCard: { status: 'new' },
641
+ LibraryHeader: { status: 'new' },
642
+ },
643
+ });
644
+ expect(result.featureStartedAt).toBe('2026-03-12T14:01:31.291Z');
645
+ expect(result.entityChangeStatus).toEqual({
646
+ ArticleCard: { status: 'new' },
647
+ LibraryHeader: { status: 'new' },
648
+ });
649
+ });
650
+ it('should NOT scope scenario counts to session when entityChangeStatus is empty', () => {
651
+ // This is the testapp bug: entityChangeStatus computation returned empty,
652
+ // so the glossary filter falls back to "audit all components", but the
653
+ // scenario count query still filters by featureStartedAt — causing
654
+ // Feature 1 components to appear as "no scenarios" even though they have them.
655
+ const result = resolveAuditSessionScope({
656
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
657
+ entityChangeStatus: undefined,
658
+ });
659
+ // When we can't scope the glossary, we shouldn't scope scenario counts either
660
+ expect(result.featureStartedAt).toBeNull();
661
+ });
662
+ it('should NOT scope scenario counts to session when entityChangeStatus is an empty object', () => {
663
+ const result = resolveAuditSessionScope({
664
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
665
+ entityChangeStatus: {},
666
+ });
667
+ expect(result.featureStartedAt).toBeNull();
668
+ });
669
+ it('should return null featureStartedAt when none was provided', () => {
670
+ const result = resolveAuditSessionScope({
671
+ featureStartedAt: null,
672
+ entityChangeStatus: { Header: { status: 'new' } },
673
+ });
674
+ expect(result.featureStartedAt).toBeNull();
675
+ });
676
+ it('should pass through entityChangeStatus unchanged when it has entries', () => {
677
+ const ecs = {
678
+ ArticleCard: { status: 'new' },
679
+ Header: { status: 'edited' },
680
+ };
681
+ const result = resolveAuditSessionScope({
682
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
683
+ entityChangeStatus: ecs,
684
+ });
685
+ expect(result.entityChangeStatus).toBe(ecs);
686
+ });
687
+ describe('multi-feature audit scenario (testapp reproduction)', () => {
688
+ // Reproduces the exact testapp bug:
689
+ // - Feature 1 built 8 components with scenarios at 13:28-13:30
690
+ // - Feature 2 starts at 14:01, builds 4 new components with scenarios at 14:14-14:16
691
+ // - entityChangeStatus computation returns empty (fails/returns {})
692
+ // - Glossary includes ALL 12 components
693
+ // - Scenario counts only include Feature 2 scenarios (after 14:01)
694
+ // - Result: Feature 1's 8 components reported as "no scenarios"
695
+ const allComponents = [
696
+ // Feature 1 components
697
+ {
698
+ name: 'Header',
699
+ filePath: 'src/components/Header.tsx',
700
+ returnType: 'JSX.Element',
701
+ },
702
+ {
703
+ name: 'Logo',
704
+ filePath: 'src/components/Logo.tsx',
705
+ returnType: 'JSX.Element',
706
+ },
707
+ {
708
+ name: 'TabBar',
709
+ filePath: 'src/components/TabBar.tsx',
710
+ returnType: 'JSX.Element',
711
+ },
712
+ {
713
+ name: 'ArticlePreview',
714
+ filePath: 'src/components/ArticlePreview.tsx',
715
+ returnType: 'JSX.Element',
716
+ },
717
+ {
718
+ name: 'SaveButton',
719
+ filePath: 'src/components/SaveButton.tsx',
720
+ returnType: 'JSX.Element',
721
+ },
722
+ {
723
+ name: 'StatusBanner',
724
+ filePath: 'src/components/StatusBanner.tsx',
725
+ returnType: 'JSX.Element',
726
+ },
727
+ {
728
+ name: 'EmptyState',
729
+ filePath: 'src/components/EmptyState.tsx',
730
+ returnType: 'JSX.Element',
731
+ },
732
+ {
733
+ name: 'ArticleRow',
734
+ filePath: 'src/components/ArticleRow.tsx',
735
+ returnType: 'JSX.Element',
736
+ },
737
+ // Feature 2 components
738
+ {
739
+ name: 'ArticleCard',
740
+ filePath: 'src/components/ArticleCard.tsx',
741
+ returnType: 'JSX.Element',
742
+ },
743
+ {
744
+ name: 'LibraryHeader',
745
+ filePath: 'src/components/LibraryHeader.tsx',
746
+ returnType: 'JSX.Element',
747
+ },
748
+ {
749
+ name: 'ArticleCardGrid',
750
+ filePath: 'src/components/ArticleCardGrid.tsx',
751
+ returnType: 'JSX.Element',
752
+ },
753
+ {
754
+ name: 'OpenLibraryButton',
755
+ filePath: 'src/components/OpenLibraryButton.tsx',
756
+ returnType: 'JSX.Element',
757
+ },
758
+ ];
759
+ // All scenarios that exist in the DB (both features)
760
+ const allScenarioCounts = {
761
+ Header: 2,
762
+ Logo: 1,
763
+ TabBar: 3,
764
+ ArticlePreview: 4,
765
+ SaveButton: 2,
766
+ StatusBanner: 2,
767
+ EmptyState: 2,
768
+ ArticleRow: 3,
769
+ ArticleCard: 4,
770
+ LibraryHeader: 3,
771
+ ArticleCardGrid: 2,
772
+ OpenLibraryButton: 1,
773
+ };
774
+ // Only Feature 2 scenarios (created after featureStartedAt)
775
+ const sessionScopedCounts = {
776
+ ArticleCard: 4,
777
+ LibraryHeader: 3,
778
+ ArticleCardGrid: 2,
779
+ OpenLibraryButton: 1,
780
+ };
781
+ it('should pass audit when entityChangeStatus is empty and all scenarios are counted', () => {
782
+ // With the fix: resolveAuditSessionScope nullifies featureStartedAt
783
+ // when entityChangeStatus is empty, so ALL scenarios are counted
784
+ const scope = resolveAuditSessionScope({
785
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
786
+ entityChangeStatus: undefined,
787
+ });
788
+ // Glossary filter: returns all (no change status to filter by)
789
+ const filtered = filterGlossaryByChangeStatus(allComponents, scope.entityChangeStatus);
790
+ expect(filtered).toHaveLength(12);
791
+ // Since featureStartedAt is now null, the route would query ALL scenarios
792
+ // (not session-scoped), giving us allScenarioCounts
793
+ const countsToUse = scope.featureStartedAt
794
+ ? sessionScopedCounts
795
+ : allScenarioCounts;
796
+ const { components } = classifyGlossaryEntries(filtered);
797
+ const result = computeAudit({
798
+ components,
799
+ functions: [],
800
+ scenarioCounts: countsToUse,
801
+ testFileExistence: {},
802
+ });
803
+ // Every component should have scenarios
804
+ expect(result.summary.componentsMissing).toBe(0);
805
+ expect(result.summary.componentsOk).toBe(12);
806
+ expect(result.summary.allPassing).toBe(true);
807
+ });
808
+ it('demonstrates the bug: session-scoped counts with unscoped glossary fails Feature 1', () => {
809
+ // WITHOUT the fix: entityChangeStatus is empty so all 12 components are audited,
810
+ // but scenario counts are session-scoped so Feature 1 components get 0
811
+ const filtered = filterGlossaryByChangeStatus(allComponents, undefined);
812
+ expect(filtered).toHaveLength(12);
813
+ const { components } = classifyGlossaryEntries(filtered);
814
+ const result = computeAudit({
815
+ components,
816
+ functions: [],
817
+ scenarioCounts: sessionScopedCounts, // BUG: only Feature 2 scenarios
818
+ testFileExistence: {},
819
+ });
820
+ // This is the broken behavior — 8 components incorrectly flagged
821
+ expect(result.summary.componentsMissing).toBe(8);
822
+ expect(result.summary.allPassing).toBe(false);
823
+ });
824
+ it('should correctly scope audit when entityChangeStatus is available', () => {
825
+ // When entityChangeStatus works, only Feature 2 components are audited
826
+ // and only Feature 2 scenarios are counted — both filters agree
827
+ const ecs = {
828
+ ArticleCard: { status: 'new' },
829
+ LibraryHeader: { status: 'new' },
830
+ ArticleCardGrid: { status: 'new' },
831
+ OpenLibraryButton: { status: 'new' },
832
+ };
833
+ const scope = resolveAuditSessionScope({
834
+ featureStartedAt: '2026-03-12T14:01:31.291Z',
835
+ entityChangeStatus: ecs,
836
+ });
837
+ // featureStartedAt preserved — session scoping is valid
838
+ expect(scope.featureStartedAt).toBe('2026-03-12T14:01:31.291Z');
839
+ const filtered = filterGlossaryByChangeStatus(allComponents, scope.entityChangeStatus);
840
+ expect(filtered).toHaveLength(4); // Only Feature 2 components
841
+ const { components } = classifyGlossaryEntries(filtered);
842
+ const result = computeAudit({
843
+ components,
844
+ functions: [],
845
+ scenarioCounts: sessionScopedCounts,
846
+ testFileExistence: {},
847
+ });
848
+ expect(result.summary.componentsMissing).toBe(0);
849
+ expect(result.summary.componentsOk).toBe(4);
850
+ expect(result.summary.allPassing).toBe(true);
851
+ });
852
+ });
244
853
  });
245
854
  });
246
855
  //# sourceMappingURL=editorAudit.test.js.map