@codeyam/codeyam-cli 0.1.0-staging.7c30edc → 0.1.0-staging.80e493d

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 (185) hide show
  1. package/analyzer-template/.build-info.json +7 -7
  2. package/analyzer-template/log.txt +3 -3
  3. package/analyzer-template/package.json +13 -13
  4. package/analyzer-template/packages/ai/index.ts +1 -0
  5. package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +14 -0
  6. package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +232 -5
  7. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +29 -18
  8. package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
  9. package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +15 -6
  10. package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +96 -0
  11. package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
  12. package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +18 -0
  13. package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +50 -25
  14. package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +153 -76
  15. package/analyzer-template/packages/aws/package.json +10 -10
  16. package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
  17. package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
  18. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
  19. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +98 -3
  20. package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  21. package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +121 -3
  22. package/analyzer-template/project/constructMockCode.ts +34 -7
  23. package/analyzer-template/project/orchestrateCapture.ts +4 -1
  24. package/analyzer-template/project/writeScenarioComponents.ts +76 -12
  25. package/background/src/lib/virtualized/project/constructMockCode.js +30 -7
  26. package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
  27. package/background/src/lib/virtualized/project/orchestrateCapture.js +4 -1
  28. package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
  29. package/background/src/lib/virtualized/project/writeScenarioComponents.js +56 -7
  30. package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
  31. package/codeyam-cli/scripts/apply-setup.js +1 -1
  32. package/codeyam-cli/src/cli.js +31 -20
  33. package/codeyam-cli/src/cli.js.map +1 -1
  34. package/codeyam-cli/src/commands/analyze.js +2 -2
  35. package/codeyam-cli/src/commands/analyze.js.map +1 -1
  36. package/codeyam-cli/src/commands/default.js +6 -1
  37. package/codeyam-cli/src/commands/default.js.map +1 -1
  38. package/codeyam-cli/src/commands/memory.js +64 -74
  39. package/codeyam-cli/src/commands/memory.js.map +1 -1
  40. package/codeyam-cli/src/commands/setup-simulations.js +1 -1
  41. package/codeyam-cli/src/commands/verify.js +12 -2
  42. package/codeyam-cli/src/commands/verify.js.map +1 -1
  43. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +185 -0
  44. package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
  45. package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +11 -11
  46. package/codeyam-cli/src/utils/backgroundServer.js +90 -23
  47. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  48. package/codeyam-cli/src/utils/generateReport.js +2 -2
  49. package/codeyam-cli/src/utils/install-skills.js +13 -13
  50. package/codeyam-cli/src/utils/labsAutoCheck.js +0 -29
  51. package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -1
  52. package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
  53. package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
  54. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +1 -1
  55. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -1
  56. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +0 -1
  57. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -1
  58. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +2 -4
  59. package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -1
  60. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +2 -1
  61. package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -1
  62. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +1 -1
  63. package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -1
  64. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js +83 -0
  65. package/codeyam-cli/src/utils/rules/__tests__/parser.test.js.map +1 -0
  66. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js +118 -0
  67. package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js.map +1 -0
  68. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +83 -0
  69. package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -0
  70. package/codeyam-cli/src/utils/rules/index.js +1 -0
  71. package/codeyam-cli/src/utils/rules/index.js.map +1 -1
  72. package/codeyam-cli/src/utils/rules/parser.js +14 -4
  73. package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
  74. package/codeyam-cli/src/utils/rules/pathMatcher.js +34 -3
  75. package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -1
  76. package/codeyam-cli/src/utils/rules/sourceFiles.js +47 -0
  77. package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -0
  78. package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +7 -7
  79. package/codeyam-cli/src/utils/simulationGateMiddleware.js +138 -0
  80. package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -0
  81. package/codeyam-cli/src/utils/syncMocksMiddleware.js +5 -24
  82. package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
  83. package/codeyam-cli/src/utils/versionInfo.js +46 -0
  84. package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
  85. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
  86. package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
  87. package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
  88. package/codeyam-cli/src/webserver/backgroundServer.js +26 -7
  89. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  90. package/codeyam-cli/src/webserver/bootstrap.js +11 -0
  91. package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
  92. package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CA3JxPb7.js → CopyButton-jNYXRRNI.js} +1 -1
  93. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-B86KKU7e.js → EntityItem-bwuHPyTa.js} +1 -1
  94. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-B5ctlSYt.js → EntityTypeBadge-CvzqMxcu.js} +1 -1
  95. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BqY8gDAW.js → EntityTypeIcon-BH0XDim7.js} +1 -1
  96. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-ClaLpuOo.js → InlineSpinner-EhOseatT.js} +1 -1
  97. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-BDhPilK7.js → InteractivePreview-yjIHlOGa.js} +2 -2
  98. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-VeqEBv9v.js → LibraryFunctionPreview-Cq5o8jL4.js} +1 -1
  99. package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-Bs7Nn1Jr.js → LoadingDots-BvMu2i-g.js} +1 -1
  100. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-Bm3PmcCz.js → LogViewer-kgBTLoJD.js} +1 -1
  101. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C6PKeMYR.js → ReportIssueModal-BzPgx-xO.js} +2 -2
  102. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Gq3Ocjo6.js → SafeScreenshot-CwZrv-Ok.js} +1 -1
  103. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BNLaXBHR.js → ScenarioViewer-BX2Ny2Qj.js} +2 -2
  104. package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CiwXDxLh.js → TruncatedFilePath-CDpEprKa.js} +1 -1
  105. package/codeyam-cli/src/webserver/build/client/assets/{_index-B3TDXxnk.js → _index-BRx8ZGZo.js} +1 -1
  106. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BtBFH820.js → activity.(_tab)-4S4yPfFw.js} +1 -1
  107. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +17 -0
  108. package/codeyam-cli/src/webserver/build/client/assets/{book-open-PttOB2SF.js → book-open-D4IPYH_y.js} +1 -1
  109. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-TJp6ofnp.js → chevron-down-CG65viiV.js} +1 -1
  110. package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-JE9ZIoBl.js → chunk-JZWAC4HX-DB3aFuEO.js} +9 -9
  111. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CXhHQYrI.js → circle-check-igfMr5DY.js} +1 -1
  112. package/codeyam-cli/src/webserver/build/client/assets/{copy-6y9ALfGT.js → copy-Coc4o_8c.js} +1 -1
  113. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Ca9fAY46.js → createLucideIcon-D1zB-pYc.js} +1 -1
  114. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C5lqplTC.js → dev.empty-JTAjQ54M.js} +1 -1
  115. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-n38keI1k.js → entity._sha._-B0h9AqE6.js} +2 -2
  116. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js → entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js} +1 -1
  117. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DGgZjdFg.js → entity._sha_.create-scenario-CtYowLOt.js} +1 -1
  118. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-38yPijoD.js → entity._sha_.edit._scenarioId-PePWg17F.js} +1 -1
  119. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-BSHEfydn.js → entry.client-I-Wo99C_.js} +1 -1
  120. package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DCPhhSMo.js → fileTableUtils-9sMMAiWJ.js} +1 -1
  121. package/codeyam-cli/src/webserver/build/client/assets/{files-0N0YJQv7.js → files-Co65J0s3.js} +1 -1
  122. package/codeyam-cli/src/webserver/build/client/assets/{git-DXnyr8uP.js → git-BdHOxVfg.js} +1 -1
  123. package/codeyam-cli/src/webserver/build/client/assets/globals-B4MPiL7S.css +1 -0
  124. package/codeyam-cli/src/webserver/build/client/assets/{index-ChN9-fAY.js → index-CUM5iXwc.js} +1 -1
  125. package/codeyam-cli/src/webserver/build/client/assets/{index-CcsFv748.js → index-_417gcQW.js} +1 -1
  126. package/codeyam-cli/src/webserver/build/client/assets/labs-DAvt-sy-.js +1 -0
  127. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-CTqLEAGU.js → loader-circle-TzRHMVog.js} +1 -1
  128. package/codeyam-cli/src/webserver/build/client/assets/manifest-e24d6600.js +1 -0
  129. package/codeyam-cli/src/webserver/build/client/assets/memory-bAp4y2hv.js +92 -0
  130. package/codeyam-cli/src/webserver/build/client/assets/{pause-D6vreykR.js → pause-hjzB7t2z.js} +1 -1
  131. package/codeyam-cli/src/webserver/build/client/assets/root-DoB3B10-.js +62 -0
  132. package/codeyam-cli/src/webserver/build/client/assets/{search-B8VUL8nl.js → search-DcAwD_Ln.js} +1 -1
  133. package/codeyam-cli/src/webserver/build/client/assets/{settings-BejnUJ6R.js → settings-CclxrcPK.js} +1 -1
  134. package/codeyam-cli/src/webserver/build/client/assets/{simulations-CPoAg7Zo.js → simulations-DVNJVQgD.js} +1 -1
  135. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BrCP7uQo.js → terminal-DbEAHMbA.js} +1 -1
  136. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BZz2NjYa.js → triangle-alert-CAD5b1o_.js} +1 -1
  137. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DNwUduNu.js → useCustomSizes-BqgrAzs3.js} +1 -1
  138. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-COky1GVF.js → useLastLogLine-DAFqfEDH.js} +1 -1
  139. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CpZgwliL.js → useReportContext-DZlYx2c4.js} +1 -1
  140. package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bv9JFvUO.js → useToast-ihdMtlf6.js} +1 -1
  141. package/codeyam-cli/src/webserver/build/server/assets/{index-CFKHuovO.js → index-C_nP9_jr.js} +1 -1
  142. package/codeyam-cli/src/webserver/build/server/assets/server-build-BEaMCeTu.js +273 -0
  143. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  144. package/codeyam-cli/src/webserver/build-info.json +5 -5
  145. package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
  146. package/codeyam-cli/templates/{codeyam:diagnose.md → codeyam-diagnose.md} +1 -1
  147. package/codeyam-cli/templates/{codeyam:memory.md → codeyam-memory.md} +7 -3
  148. package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +1 -1
  149. package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +1 -1
  150. package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
  151. package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
  152. package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
  153. package/codeyam-cli/templates/rule-reflection-hook.py +1 -1
  154. package/codeyam-cli/templates/rules-instructions.md +1 -1
  155. package/package.json +12 -12
  156. package/packages/ai/index.js +1 -1
  157. package/packages/ai/index.js.map +1 -1
  158. package/packages/ai/src/lib/analyzeScope.js +14 -0
  159. package/packages/ai/src/lib/analyzeScope.js.map +1 -1
  160. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +213 -3
  161. package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
  162. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +24 -16
  163. package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
  164. package/packages/ai/src/lib/dataStructureChunking.js +9 -5
  165. package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
  166. package/packages/ai/src/lib/generateExecutionFlows.js +81 -0
  167. package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
  168. package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
  169. package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
  170. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +11 -1
  171. package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
  172. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +42 -13
  173. package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
  174. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +123 -67
  175. package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
  176. package/packages/utils/src/lib/fs/rsyncCopy.js +98 -3
  177. package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
  178. package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-CN61MOMa.js +0 -11
  179. package/codeyam-cli/src/webserver/build/client/assets/api.labs-survey-l0sNRNKZ.js +0 -1
  180. package/codeyam-cli/src/webserver/build/client/assets/globals-CuCsBc3b.css +0 -1
  181. package/codeyam-cli/src/webserver/build/client/assets/labs-CB3MGcys.js +0 -1
  182. package/codeyam-cli/src/webserver/build/client/assets/manifest-de6ccaf4.js +0 -1
  183. package/codeyam-cli/src/webserver/build/client/assets/memory-DCA-kLYt.js +0 -81
  184. package/codeyam-cli/src/webserver/build/client/assets/root-F7e6dvys.js +0 -62
  185. package/codeyam-cli/src/webserver/build/server/assets/server-build-BQe9Dh4p.js +0 -260
@@ -1,4 +1,87 @@
1
- import { spawn } from 'child_process';
1
+ import { execSync, spawn } from 'child_process';
2
+ import { existsSync, readdirSync, rmSync } from 'fs';
3
+ import { join } from 'path';
4
+
5
+ /**
6
+ * Try to use APFS copy-on-write clones on macOS for near-instant directory copies.
7
+ * Falls back to rsync on non-macOS or if the clone fails.
8
+ *
9
+ * Returns true if the clone succeeded (caller can skip rsync).
10
+ */
11
+ function tryApfsClone({
12
+ sourcePath,
13
+ destinationPath,
14
+ excludes,
15
+ silent,
16
+ }: {
17
+ sourcePath: string;
18
+ destinationPath: string;
19
+ excludes: string[];
20
+ silent: boolean;
21
+ }): boolean {
22
+ if (process.platform !== 'darwin') return false;
23
+
24
+ // APFS clone requires the destination to not exist.
25
+ // If it exists and is empty, remove it so we can clone into it.
26
+ if (existsSync(destinationPath)) {
27
+ try {
28
+ const contents = readdirSync(destinationPath);
29
+ if (contents.length > 0) {
30
+ // Destination is non-empty — can't use clone, fall back to rsync
31
+ return false;
32
+ }
33
+ rmSync(destinationPath, { recursive: true });
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+
39
+ try {
40
+ // cp -c -R: APFS copy-on-write clone (faster than rsync, avoids data copy)
41
+ execSync(`cp -c -R "${sourcePath}" "${destinationPath}"`, {
42
+ stdio: 'pipe',
43
+ timeout: 300_000, // 5 min safety timeout
44
+ });
45
+
46
+ // Remove excluded items from the clone
47
+ for (const exclude of excludes) {
48
+ if (exclude.includes('*')) {
49
+ // Glob pattern — use shell expansion
50
+ try {
51
+ execSync(`rm -rf "${join(destinationPath, exclude)}"`, {
52
+ stdio: 'pipe',
53
+ shell: '/bin/sh',
54
+ });
55
+ } catch {
56
+ // Glob matched nothing — fine
57
+ }
58
+ } else {
59
+ const excludePath = join(destinationPath, exclude);
60
+ if (existsSync(excludePath)) {
61
+ rmSync(excludePath, { recursive: true, force: true });
62
+ }
63
+ }
64
+ }
65
+
66
+ if (!silent) {
67
+ console.log(
68
+ `Directory cloned (APFS CoW) from ${sourcePath} to ${destinationPath}`,
69
+ );
70
+ }
71
+ return true;
72
+ } catch {
73
+ // Clone failed (cross-volume, non-APFS, etc.) — fall back to rsync
74
+ // Clean up any partial clone
75
+ if (existsSync(destinationPath)) {
76
+ try {
77
+ rmSync(destinationPath, { recursive: true });
78
+ } catch {
79
+ // Best effort cleanup
80
+ }
81
+ }
82
+ return false;
83
+ }
84
+ }
2
85
 
3
86
  export default async function rsyncCopy({
4
87
  sourcePath,
@@ -15,13 +98,38 @@ export default async function rsyncCopy({
15
98
  silent?: boolean;
16
99
  extraArgs?: string[];
17
100
  }): Promise<void> {
101
+ const startTime = Date.now();
102
+
103
+ // On macOS, try APFS copy-on-write clone first (near-instant).
104
+ // Skip when extraArgs are provided since those are rsync-specific flags
105
+ // that the clone path can't honor.
106
+ if (!keepExisting && extraArgs.length === 0) {
107
+ const cloned = tryApfsClone({
108
+ sourcePath,
109
+ destinationPath,
110
+ excludes,
111
+ silent,
112
+ });
113
+ if (cloned) {
114
+ if (!silent) {
115
+ const duration = ((Date.now() - startTime) / 1000).toFixed(1);
116
+ console.log(
117
+ `Directory synced from ${sourcePath} to ${destinationPath} [Time: ${duration}s]`,
118
+ );
119
+ }
120
+ return;
121
+ }
122
+ }
123
+
124
+ // Fall back to rsync
18
125
  return new Promise((resolve, reject) => {
19
126
  const source = sourcePath.endsWith('/') ? sourcePath : `${sourcePath}/`;
20
127
  const dest = destinationPath.endsWith('/')
21
128
  ? destinationPath
22
129
  : `${destinationPath}/`;
23
130
 
24
- const rsyncArgs = ['-a'];
131
+ // -a includes --specials which tries to copy sockets/FIFOs and can fail
132
+ const rsyncArgs = ['-a', '--no-specials'];
25
133
 
26
134
  if (!keepExisting) {
27
135
  rsyncArgs.push('--delete', '--force');
@@ -37,7 +145,6 @@ export default async function rsyncCopy({
37
145
 
38
146
  rsyncArgs.push(source, dest);
39
147
 
40
- const startTime = Date.now();
41
148
  const rsyncProcess = spawn('rsync', rsyncArgs);
42
149
 
43
150
  rsyncProcess.on('exit', (code) => {
@@ -50,6 +157,17 @@ export default async function rsyncCopy({
50
157
  }
51
158
  resolve();
52
159
  } else {
160
+ console.error(
161
+ `CodeYam Error: rsync failed with code: ${code}`,
162
+ JSON.stringify(
163
+ {
164
+ rsyncArgs,
165
+ },
166
+ null,
167
+ 2,
168
+ ),
169
+ );
170
+
53
171
  reject(new Error(`rsync failed with exit code ${code}`));
54
172
  }
55
173
  });
@@ -342,7 +342,7 @@ export default function constructMockCode(
342
342
  let foundEntityWithSignature = false;
343
343
  let signatureSchema: DataStructure['signatureSchema'] | undefined;
344
344
 
345
- for (const filePath in dependencySchemas) {
345
+ entitySearch: for (const filePath in dependencySchemas) {
346
346
  for (const entityName in dependencySchemas[filePath]) {
347
347
  // Match entity by base name (without generics/args)
348
348
  const entityBaseName = entityName.split(/[<(]/)[0];
@@ -386,7 +386,7 @@ export default function constructMockCode(
386
386
  // However, we still need to remove duplicate function calls that create invalid syntax
387
387
  removeDuplicateFunctionCalls(relevantReturnValueSchema);
388
388
  dataStructureValue = relevantReturnValueSchema?.[dataStructurePath];
389
- break;
389
+ break entitySearch;
390
390
  }
391
391
  }
392
392
  }
@@ -2288,6 +2288,23 @@ export default function constructMockCode(
2288
2288
  }
2289
2289
  }
2290
2290
 
2291
+ // Post-processing: When the root functionCallReturnValue is typed as "function" but the
2292
+ // return value also has nested properties (methods like .from(), .auth, etc.), it's actually
2293
+ // an object, not a function to be called. Clear returnsFunctionArgs to prevent double-wrapping
2294
+ // (adding an extra () => { return { ... } } wrapper and ["()"] data paths).
2295
+ // This handles cases like Supabase's createClient() which returns an object with methods.
2296
+ // Only applied to the root level - nested parts that are functions with methods (like
2297
+ // useSearchParams()[1] which is a setter function with .set() and .delete()) should keep
2298
+ // their returnsFunctionArgs since they genuinely ARE functions.
2299
+ if (
2300
+ returnValueParts.returnsFunctionArgs &&
2301
+ returnValueParts.returnsFunctionArgs.length === 0 &&
2302
+ returnValueParts.nested &&
2303
+ returnValueParts.nested.length > 0
2304
+ ) {
2305
+ returnValueParts.returnsFunctionArgs = undefined;
2306
+ }
2307
+
2291
2308
  const contents = constructReturnValueString(returnValueParts);
2292
2309
 
2293
2310
  if (mockNameParts.length > 1) {
@@ -2360,16 +2377,26 @@ export default function constructMockCode(
2360
2377
  const nameAssignment = isErrorSubclass
2361
2378
  ? `this.name = '${baseMockName}';`
2362
2379
  : '';
2363
- // Use the safe function name for the class definition
2364
- const className = mockNameIsCallSignature
2365
- ? derivedFunctionName
2366
- : baseMockName;
2380
+ // Use the base class name for the class definition, not the call-signature-derived name.
2381
+ // When mockName is "StatsCalculator(supabase)", baseMockName is "StatsCalculator"
2382
+ // and derivedFunctionName would be "StatsCalculator_supabase" which is wrong.
2383
+ // Classes are instantiated with `new ClassName(args)` so the name must match the original.
2384
+ const className = baseMockName;
2385
+
2386
+ // Use the already-generated contents (which has proper function wrappers for methods)
2387
+ // instead of raw scenarios().data() which would create non-callable string-keyed properties.
2388
+ // For classes with methods like calculateStats(), the contents will have:
2389
+ // { calculateStats: (...args) => scenarios().data()?.["key"]?.["calculateStats(...)"], ... }
2390
+ // which makes methods callable on the instance.
2391
+ const classContents = enhancedContents.trim().startsWith('{')
2392
+ ? enhancedContents
2393
+ : `scenarios().data()?.${quotePropertyKey(dataKey)} || {}`;
2367
2394
 
2368
2395
  return `class ${className}${isErrorSubclass ? ' extends Error' : ''} {
2369
2396
  constructor(message) {
2370
2397
  ${superCall}
2371
2398
  ${nameAssignment}
2372
- Object.assign(this, scenarios().data()?.${quotePropertyKey(dataKey)} || {});
2399
+ Object.assign(this, ${classContents});
2373
2400
  }
2374
2401
  }`;
2375
2402
  }
@@ -32,7 +32,10 @@ import type {
32
32
  } from './orchestrateCapture/taskRunner';
33
33
  import KyselyAnalysisLoader from './orchestrateCapture/KyselyAnalysisLoader';
34
34
 
35
- const MAX_BATCH_SIZE = 6;
35
+ // Temporarily set to 1 (effectively disabling batching) to work around reliability
36
+ // issues where multi-analysis batches cause cascading failures. Revisit once we
37
+ // reassess the SQS protocol and worker error handling.
38
+ const MAX_BATCH_SIZE = 1;
36
39
  const POLLING_INTERVAL = 30 * 1000; // 30 seconds
37
40
  const TASK_HEALTH_CHECK_INTERVAL = 60 * 1000; // 1 minute
38
41
  const ANALYSIS_TIMEOUT = 20 * 60 * 1000;
@@ -2020,20 +2020,25 @@ export default async function writeScenarioComponents({
2020
2020
  // that stubbing would break (e.g., Zod schemas with .superRefine())
2021
2021
  const isDataEntity = entityType === 'data' || entityType === 'type';
2022
2022
 
2023
- // Heuristic: Zod schemas are often misclassified as 'library' but should be preserved
2024
- // Detect by: name starts with Z + uppercase letter, AND has Zod method calls
2025
- const looksLikeZodSchema =
2026
- entityType === 'library' &&
2027
- /^Z[A-Z]/.test(importedExport.name) &&
2028
- importedExport.calls?.some((call: string) =>
2029
- /\.(superRefine|refine|transform|default|optional|nullable|array|object|string|number|boolean|parse|safeParse)\s*\(/.test(
2030
- call,
2031
- ),
2032
- );
2023
+ // If calls data shows the entity is only accessed via properties/methods
2024
+ // (e.g., formValidator.validate(), schema.superRefine()) and never directly
2025
+ // invoked (e.g., getInitialProps()), it's used as an object and should be
2026
+ // preserved rather than replaced with a Proxy stub.
2027
+ const onlyPropertyAccessed =
2028
+ importedExport.calls?.length > 0 &&
2029
+ !importedExport.calls.some((call: string) => {
2030
+ const afterName = call.slice(importedExport.name.length);
2031
+ return afterName.startsWith('(') || afterName.startsWith('<');
2032
+ });
2033
2033
 
2034
- // Callable entities can be safely stubbed (but not Zod schemas)
2034
+ // Callable entities can be safely stubbed. Entities that are only
2035
+ // property-accessed should be preserved (their methods need to work).
2036
+ // 'other' entities are unknown types — safer to preserve than stub.
2035
2037
  const isCallable =
2036
- !isDataEntity && !looksLikeZodSchema && entityType !== undefined;
2038
+ !isDataEntity &&
2039
+ !onlyPropertyAccessed &&
2040
+ entityType !== undefined &&
2041
+ entityType !== 'other';
2037
2042
 
2038
2043
  // Determine what action to take
2039
2044
  const shouldStripAndReplace = hasMock;
@@ -2733,6 +2738,20 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
2733
2738
  debugLog(
2734
2739
  `[REMAINING LOOP] import ${remainingImportIndex}/${remainingImportPaths.length}: ${importPath}`,
2735
2740
  );
2741
+
2742
+ // Skip imports that point to generated CodeYam files (same skip logic as
2743
+ // rewriteRelativeModuleImports). Without this, MockData files from earlier
2744
+ // captures that get discovered by the TypeScript compiler would be treated as
2745
+ // regular imports, creating transitive copies with stale content.
2746
+ const scenarioFilePattern = /[a-f0-9]{64}_\w+_[A-Z]\w*$/;
2747
+ const mockDataPattern = /__codeyamMocks__\//;
2748
+ if (
2749
+ scenarioFilePattern.test(importPath) ||
2750
+ mockDataPattern.test(importPath)
2751
+ ) {
2752
+ continue;
2753
+ }
2754
+
2736
2755
  // Resolve the import path to a project file path
2737
2756
  const resolvedFilePath = resolveImportPath(importPath, file.path, project);
2738
2757
 
@@ -3007,6 +3026,51 @@ ${exportKeyword}const ${functionName} = new Proxy(() => scenarios().data()?.["${
3007
3026
  }
3008
3027
  }
3009
3028
 
3029
+ // For route components (page.tsx, layout.tsx), the component IS the Next.js page.
3030
+ // There's no wrapper page to inject argumentsData as props (unlike non-route components
3031
+ // which get a scenarioComponent wrapper). We need to wrap the default export so that
3032
+ // the scenario's argumentsData is passed as props to the component.
3033
+ if (
3034
+ isFrameworkRoute(file, entity, framework, file === rootFile) &&
3035
+ rootAnalysis.metadata?.scenariosDataStructure?.arguments?.length > 0
3036
+ ) {
3037
+ const positionalArguments =
3038
+ rootAnalysis.metadata.scenariosDataStructure.arguments;
3039
+ const hasNamedArgs =
3040
+ positionalArguments.length === 1 &&
3041
+ typeof positionalArguments[0] === 'object';
3042
+
3043
+ if (hasNamedArgs) {
3044
+ // Match: export default function Name(
3045
+ // Also: export default async function Name(
3046
+ const defaultExportMatch = fileContent.match(
3047
+ /export\s+default\s+(async\s+)?function\s+(\w+)\s*\(/,
3048
+ );
3049
+
3050
+ if (defaultExportMatch) {
3051
+ const funcName = defaultExportMatch[2];
3052
+
3053
+ // Remove "export default" from the original function declaration
3054
+ fileContent = fileContent.replace(
3055
+ /export\s+default\s+(async\s+)?function\s+(\w+)\s*\(/,
3056
+ '$1function $2(',
3057
+ );
3058
+
3059
+ // Ensure scenarios import is present
3060
+ const mockDataPath = `${relativeMocksDir}/MockData_${safeFileName(scenario.name)}`;
3061
+ if (fileContent.indexOf('import { scenarios } from') === -1) {
3062
+ fileContent = `import { scenarios } from "${mockDataPath}";\n\n${fileContent}`;
3063
+ }
3064
+
3065
+ // Add wrapper default export that injects argumentsData as props
3066
+ fileContent += `\n\nexport default function _CYRouteWrapper(props: any) {
3067
+ const _cyArgs = scenarios().data()?.['arguments']?.[0] ?? {};
3068
+ return <${funcName} {...props} {..._cyArgs} />;
3069
+ }\n`;
3070
+ }
3071
+ }
3072
+ }
3073
+
3010
3074
  // Use the directive that was extracted at the beginning of processing
3011
3075
  // This ensures it stays at the very top even after imports are prepended
3012
3076
  // NOTE: We only preserve "use client" directives, NOT "use server" directives.
@@ -257,7 +257,7 @@ options) {
257
257
  let dataStructureValue;
258
258
  let foundEntityWithSignature = false;
259
259
  let signatureSchema;
260
- for (const filePath in dependencySchemas) {
260
+ entitySearch: for (const filePath in dependencySchemas) {
261
261
  for (const entityName in dependencySchemas[filePath]) {
262
262
  // Match entity by base name (without generics/args)
263
263
  const entityBaseName = entityName.split(/[<(]/)[0];
@@ -289,7 +289,7 @@ options) {
289
289
  // However, we still need to remove duplicate function calls that create invalid syntax
290
290
  removeDuplicateFunctionCalls(relevantReturnValueSchema);
291
291
  dataStructureValue = relevantReturnValueSchema?.[dataStructurePath];
292
- break;
292
+ break entitySearch;
293
293
  }
294
294
  }
295
295
  }
@@ -1917,6 +1917,20 @@ options) {
1917
1917
  returnValueSection = relevantPart;
1918
1918
  }
1919
1919
  }
1920
+ // Post-processing: When the root functionCallReturnValue is typed as "function" but the
1921
+ // return value also has nested properties (methods like .from(), .auth, etc.), it's actually
1922
+ // an object, not a function to be called. Clear returnsFunctionArgs to prevent double-wrapping
1923
+ // (adding an extra () => { return { ... } } wrapper and ["()"] data paths).
1924
+ // This handles cases like Supabase's createClient() which returns an object with methods.
1925
+ // Only applied to the root level - nested parts that are functions with methods (like
1926
+ // useSearchParams()[1] which is a setter function with .set() and .delete()) should keep
1927
+ // their returnsFunctionArgs since they genuinely ARE functions.
1928
+ if (returnValueParts.returnsFunctionArgs &&
1929
+ returnValueParts.returnsFunctionArgs.length === 0 &&
1930
+ returnValueParts.nested &&
1931
+ returnValueParts.nested.length > 0) {
1932
+ returnValueParts.returnsFunctionArgs = undefined;
1933
+ }
1920
1934
  const contents = constructReturnValueString(returnValueParts);
1921
1935
  if (mockNameParts.length > 1) {
1922
1936
  const originalLib = `${mockNameParts[0]}__cyOriginal`;
@@ -1978,15 +1992,24 @@ options) {
1978
1992
  const nameAssignment = isErrorSubclass
1979
1993
  ? `this.name = '${baseMockName}';`
1980
1994
  : '';
1981
- // Use the safe function name for the class definition
1982
- const className = mockNameIsCallSignature
1983
- ? derivedFunctionName
1984
- : baseMockName;
1995
+ // Use the base class name for the class definition, not the call-signature-derived name.
1996
+ // When mockName is "StatsCalculator(supabase)", baseMockName is "StatsCalculator"
1997
+ // and derivedFunctionName would be "StatsCalculator_supabase" which is wrong.
1998
+ // Classes are instantiated with `new ClassName(args)` so the name must match the original.
1999
+ const className = baseMockName;
2000
+ // Use the already-generated contents (which has proper function wrappers for methods)
2001
+ // instead of raw scenarios().data() which would create non-callable string-keyed properties.
2002
+ // For classes with methods like calculateStats(), the contents will have:
2003
+ // { calculateStats: (...args) => scenarios().data()?.["key"]?.["calculateStats(...)"], ... }
2004
+ // which makes methods callable on the instance.
2005
+ const classContents = enhancedContents.trim().startsWith('{')
2006
+ ? enhancedContents
2007
+ : `scenarios().data()?.${quotePropertyKey(dataKey)} || {}`;
1985
2008
  return `class ${className}${isErrorSubclass ? ' extends Error' : ''} {
1986
2009
  constructor(message) {
1987
2010
  ${superCall}
1988
2011
  ${nameAssignment}
1989
- Object.assign(this, scenarios().data()?.${quotePropertyKey(dataKey)} || {});
2012
+ Object.assign(this, ${classContents});
1990
2013
  }
1991
2014
  }`;
1992
2015
  }