@codeyam/codeyam-cli 0.1.0-staging.c9dc00c → 0.1.0-staging.d3e886e
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.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +1 -1
- package/analyzer-template/packages/ai/index.ts +1 -0
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +14 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +101 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +6 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +172 -8
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +70 -19
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +40 -13
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +32 -5
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +134 -2
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +359 -142
- package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +18 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +50 -25
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +153 -76
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +108 -2
- package/analyzer-template/project/constructMockCode.ts +2 -2
- package/analyzer-template/project/writeScenarioComponents.ts +14 -0
- package/background/src/lib/virtualized/project/constructMockCode.js +2 -2
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +10 -0
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/codeyam-cli/scripts/apply-setup.js +1 -1
- package/codeyam-cli/src/codeyam-cli.js +18 -2
- package/codeyam-cli/src/codeyam-cli.js.map +1 -1
- package/codeyam-cli/src/commands/analyze.js +2 -2
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +18 -17
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +27 -93
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/commands/memory.js +9 -9
- package/codeyam-cli/src/commands/memory.js.map +1 -1
- package/codeyam-cli/src/commands/setup-simulations.js +1 -1
- package/codeyam-cli/src/commands/verify.js +12 -2
- package/codeyam-cli/src/commands/verify.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +179 -0
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +11 -11
- package/codeyam-cli/src/utils/backgroundServer.js +90 -23
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +2 -2
- package/codeyam-cli/src/utils/install-skills.js +13 -13
- package/codeyam-cli/src/utils/labsAutoCheck.js +0 -29
- package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -1
- package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
- package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +4 -4
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +2 -2
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +4 -4
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +3 -3
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -1
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +23 -23
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -1
- package/codeyam-cli/src/utils/rules/ruleState.js +10 -10
- package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -1
- package/codeyam-cli/src/utils/rules/staleness.js +6 -6
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
- package/codeyam-cli/src/utils/serverState.js +37 -10
- package/codeyam-cli/src/utils/serverState.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +7 -7
- package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
- package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
- package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
- package/codeyam-cli/src/webserver/backgroundServer.js +26 -7
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +11 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CA3JxPb7.js → CopyButton-jNYXRRNI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-B86KKU7e.js → EntityItem-bwuHPyTa.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-B5ctlSYt.js → EntityTypeBadge-CvzqMxcu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BqY8gDAW.js → EntityTypeIcon-BH0XDim7.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-ClaLpuOo.js → InlineSpinner-EhOseatT.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-BDhPilK7.js → InteractivePreview-yjIHlOGa.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-VeqEBv9v.js → LibraryFunctionPreview-Cq5o8jL4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-Bs7Nn1Jr.js → LoadingDots-BvMu2i-g.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-Bm3PmcCz.js → LogViewer-kgBTLoJD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C6PKeMYR.js → ReportIssueModal-BzPgx-xO.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Gq3Ocjo6.js → SafeScreenshot-CwZrv-Ok.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BNLaXBHR.js → ScenarioViewer-BX2Ny2Qj.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CiwXDxLh.js → TruncatedFilePath-CDpEprKa.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-B3TDXxnk.js → _index-BRx8ZGZo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BtBFH820.js → activity.(_tab)-4S4yPfFw.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +17 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-PttOB2SF.js → book-open-D4IPYH_y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-TJp6ofnp.js → chevron-down-CG65viiV.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-JE9ZIoBl.js → chunk-JZWAC4HX-DB3aFuEO.js} +9 -9
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CXhHQYrI.js → circle-check-igfMr5DY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-6y9ALfGT.js → copy-Coc4o_8c.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Ca9fAY46.js → createLucideIcon-D1zB-pYc.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C5lqplTC.js → dev.empty-JTAjQ54M.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-n38keI1k.js → entity._sha._-B0h9AqE6.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js → entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DGgZjdFg.js → entity._sha_.create-scenario-CtYowLOt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-38yPijoD.js → entity._sha_.edit._scenarioId-PePWg17F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-BSHEfydn.js → entry.client-I-Wo99C_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DCPhhSMo.js → fileTableUtils-9sMMAiWJ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{files-0N0YJQv7.js → files-Co65J0s3.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-DXnyr8uP.js → git-BdHOxVfg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-CCgBKWy4.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-ChN9-fAY.js → index-CUM5iXwc.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-CcsFv748.js → index-_417gcQW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-BK0C1H1T.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-CTqLEAGU.js → loader-circle-TzRHMVog.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-390cb8fa.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-CzZySbBE.js +78 -0
- package/codeyam-cli/src/webserver/build/client/assets/{pause-D6vreykR.js → pause-hjzB7t2z.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-DnbDhvTU.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-B8VUL8nl.js → search-DcAwD_Ln.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-CclxrcPK.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-CPoAg7Zo.js → simulations-DVNJVQgD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-BrCP7uQo.js → terminal-DbEAHMbA.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BZz2NjYa.js → triangle-alert-CAD5b1o_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DNwUduNu.js → useCustomSizes-BqgrAzs3.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-COky1GVF.js → useLastLogLine-DAFqfEDH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CpZgwliL.js → useReportContext-DZlYx2c4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bv9JFvUO.js → useToast-ihdMtlf6.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-Cz2RkDCa.js → index-CxaRxKVt.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-D4DT0nM_.js +259 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
- package/codeyam-cli/templates/{codeyam:diagnose.md → codeyam-diagnose.md} +1 -1
- package/codeyam-cli/templates/codeyam-memory-hook.sh +14 -14
- package/codeyam-cli/templates/{codeyam:memory.md → codeyam-memory.md} +16 -23
- package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +1 -1
- package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +1 -1
- package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
- package/codeyam-cli/templates/rule-reflection-hook.py +5 -5
- package/codeyam-cli/templates/rules-instructions.md +11 -15
- package/package.json +8 -8
- package/packages/ai/index.js +1 -1
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +14 -0
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +78 -1
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
- package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +124 -7
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +59 -17
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructureChunking.js +30 -11
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +22 -3
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +97 -2
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +242 -81
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
- package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +17 -2
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +11 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +42 -13
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +123 -67
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-CN61MOMa.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/api.labs-survey-l0sNRNKZ.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-EVn6Z9pz.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-CmBYA0PH.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-aa4ff97b.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/memory-BSlqS1QA.js +0 -81
- package/codeyam-cli/src/webserver/build/client/assets/root-DVAbJY8B.js +0 -62
- package/codeyam-cli/src/webserver/build/client/assets/settings-BK-cnzp-.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-CUVsWicu.js +0 -260
|
@@ -3,9 +3,11 @@ import type { ExecutionFlow, ScenariosDataStructure } from '~codeyam/types';
|
|
|
3
3
|
// Type for a single required value from ExecutionFlow
|
|
4
4
|
type RequiredValue = NonNullable<ExecutionFlow['requiredValues']>[number];
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const DEFAULT_MAX_CHUNK_SIZE = 10_000; // ~10K chars per chunk
|
|
7
|
+
const DEFAULT_MAX_KEYS_PER_CHUNK = 20;
|
|
7
8
|
|
|
8
9
|
export interface ChunkOptions {
|
|
10
|
+
maxChunkSize?: number;
|
|
9
11
|
maxKeysPerChunk?: number;
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -15,8 +17,12 @@ export interface ChunkOptions {
|
|
|
15
17
|
* Large schemas overwhelm LLMs, causing them to make mistakes on some keys.
|
|
16
18
|
* By processing smaller chunks, each key gets more focused attention.
|
|
17
19
|
*
|
|
20
|
+
* Uses cumulative JSON size to decide chunk boundaries rather than a fixed
|
|
21
|
+
* key count, so a single oversized key gets its own chunk while many small
|
|
22
|
+
* keys are grouped together efficiently.
|
|
23
|
+
*
|
|
18
24
|
* @param dataForMocks - The full data structure schema
|
|
19
|
-
* @param options - Chunking options (
|
|
25
|
+
* @param options - Chunking options (maxChunkSize defaults to 10_000)
|
|
20
26
|
* @returns Array of smaller data structure chunks
|
|
21
27
|
*/
|
|
22
28
|
export function chunkDataStructure(
|
|
@@ -27,27 +33,48 @@ export function chunkDataStructure(
|
|
|
27
33
|
return [dataForMocks];
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
const {
|
|
36
|
+
const {
|
|
37
|
+
maxChunkSize = DEFAULT_MAX_CHUNK_SIZE,
|
|
38
|
+
maxKeysPerChunk = DEFAULT_MAX_KEYS_PER_CHUNK,
|
|
39
|
+
} = options;
|
|
31
40
|
const keys = Object.keys(dataForMocks);
|
|
32
41
|
|
|
33
|
-
//
|
|
34
|
-
|
|
42
|
+
// Calculate total size to see if chunking is needed
|
|
43
|
+
const totalSize = JSON.stringify(dataForMocks).length;
|
|
44
|
+
if (totalSize <= maxChunkSize && keys.length <= maxKeysPerChunk) {
|
|
35
45
|
return [dataForMocks];
|
|
36
46
|
}
|
|
37
47
|
|
|
48
|
+
// Greedily pack keys into chunks by cumulative size and key count
|
|
38
49
|
const chunks: Array<ScenariosDataStructure['dataForMocks']> = [];
|
|
50
|
+
let currentChunk: Record<string, unknown> = {};
|
|
51
|
+
let currentSize = 0;
|
|
52
|
+
|
|
53
|
+
for (const key of keys) {
|
|
54
|
+
const keySize = JSON.stringify(
|
|
55
|
+
(dataForMocks as Record<string, unknown>)[key],
|
|
56
|
+
).length;
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
const chunkKeys = keys.slice(i, i + maxKeysPerChunk);
|
|
42
|
-
const chunk: ScenariosDataStructure['dataForMocks'] = {};
|
|
58
|
+
const currentKeyCount = Object.keys(currentChunk).length;
|
|
43
59
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
60
|
+
// If adding this key would exceed size or key count limit AND chunk isn't empty, start a new chunk
|
|
61
|
+
if (
|
|
62
|
+
currentSize > 0 &&
|
|
63
|
+
(currentSize + keySize > maxChunkSize ||
|
|
64
|
+
currentKeyCount >= maxKeysPerChunk)
|
|
65
|
+
) {
|
|
66
|
+
chunks.push(currentChunk as ScenariosDataStructure['dataForMocks']);
|
|
67
|
+
currentChunk = {};
|
|
68
|
+
currentSize = 0;
|
|
48
69
|
}
|
|
49
70
|
|
|
50
|
-
|
|
71
|
+
currentChunk[key] = (dataForMocks as Record<string, unknown>)[key];
|
|
72
|
+
currentSize += keySize;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Push the last chunk
|
|
76
|
+
if (Object.keys(currentChunk).length > 0) {
|
|
77
|
+
chunks.push(currentChunk as ScenariosDataStructure['dataForMocks']);
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
return chunks;
|
|
@@ -294,11 +294,13 @@ function generateDefaultForSchemaType(schemaType: unknown): unknown {
|
|
|
294
294
|
if (schemaType.includes('| null')) return null;
|
|
295
295
|
return schemaType; // Return the type as a string placeholder
|
|
296
296
|
}
|
|
297
|
-
if (
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
297
|
+
if (Array.isArray(schemaType)) {
|
|
298
|
+
if (schemaType.length === 0) return [];
|
|
299
|
+
// Generate a single default element based on the first element's schema
|
|
300
|
+
const elementDefault = generateDefaultForSchemaType(schemaType[0]);
|
|
301
|
+
return elementDefault !== undefined ? [elementDefault] : [];
|
|
302
|
+
}
|
|
303
|
+
if (typeof schemaType === 'object' && schemaType !== null) {
|
|
302
304
|
// Recursively generate defaults for nested objects
|
|
303
305
|
const result: Record<string, unknown> = {};
|
|
304
306
|
for (const [key, value] of Object.entries(schemaType)) {
|
|
@@ -426,6 +428,8 @@ function fillMissingMockDataKeysWithDefaults(
|
|
|
426
428
|
const missingKeys: string[] = [];
|
|
427
429
|
|
|
428
430
|
for (const key of Object.keys(dataForMocks)) {
|
|
431
|
+
if (key === '_nullable') continue; // Internal marker, not a data key
|
|
432
|
+
|
|
429
433
|
const fullPath = pathPrefix ? `${pathPrefix}.${key}` : key;
|
|
430
434
|
|
|
431
435
|
if (mockData[key] === undefined) {
|
|
@@ -841,6 +845,29 @@ export async function generateDataForScenario({
|
|
|
841
845
|
}
|
|
842
846
|
}
|
|
843
847
|
|
|
848
|
+
// Detect keys that were lost from failed or partial chunk responses
|
|
849
|
+
// and fill them with schema-based defaults so they aren't permanently lost.
|
|
850
|
+
const allChunkedKeys = chunks.flatMap((c) => Object.keys(c || {}));
|
|
851
|
+
const returnedKeys = new Set(Object.keys(chunkedMockData));
|
|
852
|
+
const missingChunkKeys = allChunkedKeys.filter(
|
|
853
|
+
(k) => !returnedKeys.has(k),
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
if (missingChunkKeys.length > 0) {
|
|
857
|
+
awsLog(
|
|
858
|
+
`Chunked processing: ${missingChunkKeys.length} key(s) missing from chunk results, filling with defaults: ${missingChunkKeys.join(', ')}`,
|
|
859
|
+
);
|
|
860
|
+
const dataForMocksRecord = structure.dataForMocks as Record<
|
|
861
|
+
string,
|
|
862
|
+
unknown
|
|
863
|
+
>;
|
|
864
|
+
for (const key of missingChunkKeys) {
|
|
865
|
+
chunkedMockData[key] = generateDefaultForSchemaType(
|
|
866
|
+
dataForMocksRecord[key],
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
844
871
|
awsLog(
|
|
845
872
|
`Chunked processing complete. Generated ${Object.keys(chunkedMockData).length} keys total`,
|
|
846
873
|
);
|
|
@@ -32,6 +32,30 @@ import resolvePathToControllable from './resolvePathToControllable';
|
|
|
32
32
|
import { AI } from '~codeyam/ai';
|
|
33
33
|
import type { JsxRenderingUsage, ConditionalUsage } from './astScopes/types';
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Patterns that indicate a child component is a modal/overlay/blocking element.
|
|
37
|
+
* Same patterns used in generateExecutionFlowsFromConditionalEffects.ts for
|
|
38
|
+
* state variable names — here applied to child component names.
|
|
39
|
+
*/
|
|
40
|
+
const BLOCKING_CHILD_PATTERNS = [
|
|
41
|
+
/modal/i,
|
|
42
|
+
/overlay/i,
|
|
43
|
+
/dialog/i,
|
|
44
|
+
/popup/i,
|
|
45
|
+
/drawer/i,
|
|
46
|
+
/sheet/i,
|
|
47
|
+
/lightbox/i,
|
|
48
|
+
/backdrop/i,
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Check if a child component name suggests it's a blocking/modal element.
|
|
53
|
+
* Exported for testing.
|
|
54
|
+
*/
|
|
55
|
+
export function isBlockingChildComponent(componentName: string): boolean {
|
|
56
|
+
return BLOCKING_CHILD_PATTERNS.some((pattern) => pattern.test(componentName));
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
interface GenerateExecutionFlowsArgs {
|
|
36
60
|
entity: Pick<Entity, 'sha' | 'name' | 'filePath' | 'code' | 'metadata'>;
|
|
37
61
|
mergedDataStructure: Omit<DataStructure, 'equivalentSignatureVariables'>;
|
|
@@ -105,6 +129,19 @@ export default function generateExecutionFlows({
|
|
|
105
129
|
fullToShortPathMap[fullPath] = shortPath;
|
|
106
130
|
}
|
|
107
131
|
|
|
132
|
+
console.log(
|
|
133
|
+
`[generateExecutionFlows] ${entity.name}: attributesMap has ${Object.keys(resolvedAttributesMap).length} keys, fullToShortPathMap has ${Object.keys(fullToShortPathMap).length} entries`,
|
|
134
|
+
);
|
|
135
|
+
console.log(
|
|
136
|
+
`[generateExecutionFlows] ${entity.name}: attributesMap keys: [${Object.keys(resolvedAttributesMap).join(', ')}]`,
|
|
137
|
+
);
|
|
138
|
+
console.log(
|
|
139
|
+
`[generateExecutionFlows] ${entity.name}: fullToShortPathMap: ${JSON.stringify(fullToShortPathMap)}`,
|
|
140
|
+
);
|
|
141
|
+
console.log(
|
|
142
|
+
`[generateExecutionFlows] ${entity.name}: equivalentSignatureVariables: ${JSON.stringify(equivalentSignatureVariables)}`,
|
|
143
|
+
);
|
|
144
|
+
|
|
108
145
|
// Get pre-computed conditional data from metadata
|
|
109
146
|
const conditionalUsages: Record<string, ConditionalUsage[]> =
|
|
110
147
|
entity.metadata?.isolatedDataStructure?.conditionalUsages ?? {};
|
|
@@ -149,6 +186,26 @@ export default function generateExecutionFlows({
|
|
|
149
186
|
}
|
|
150
187
|
}
|
|
151
188
|
|
|
189
|
+
console.log(
|
|
190
|
+
`[generateExecutionFlows] ${entity.name}: conditionalUsages keys: [${Object.keys(conditionalUsages).join(', ')}]`,
|
|
191
|
+
);
|
|
192
|
+
console.log(
|
|
193
|
+
`[generateExecutionFlows] ${entity.name}: conditionalUsages sourceDataPaths: ${JSON.stringify(
|
|
194
|
+
Object.fromEntries(
|
|
195
|
+
Object.entries(conditionalUsages).map(([k, v]) => [
|
|
196
|
+
k,
|
|
197
|
+
(v as any[]).map((u: any) => u.sourceDataPath ?? '(none)'),
|
|
198
|
+
]),
|
|
199
|
+
),
|
|
200
|
+
)}`,
|
|
201
|
+
);
|
|
202
|
+
console.log(
|
|
203
|
+
`[generateExecutionFlows] ${entity.name}: compoundConditionals count: ${compoundConditionals.length}`,
|
|
204
|
+
);
|
|
205
|
+
console.log(
|
|
206
|
+
`[generateExecutionFlows] ${entity.name}: sourceEquivalencies keys count: ${Object.keys(mergedDataStructure.sourceEquivalencies ?? {}).length}`,
|
|
207
|
+
);
|
|
208
|
+
|
|
152
209
|
const conditionalsBasedFlows = generateExecutionFlowsFromConditionals({
|
|
153
210
|
conditionalUsages,
|
|
154
211
|
compoundConditionals,
|
|
@@ -240,6 +297,11 @@ export default function generateExecutionFlows({
|
|
|
240
297
|
calculateFlowPriority(flow, gatingPathToChildren);
|
|
241
298
|
}
|
|
242
299
|
|
|
300
|
+
// Assign exclusiveGroup for truthy/falsy flow pairs that control child components.
|
|
301
|
+
// When the same gating path produces both a truthy flow (show component) and a
|
|
302
|
+
// falsy flow (hide component), they are mutually exclusive and should be grouped.
|
|
303
|
+
assignExclusiveGroupsForGatingPairs(allFlows);
|
|
304
|
+
|
|
243
305
|
// Sort flows by priority (highest first)
|
|
244
306
|
allFlows.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
245
307
|
|
|
@@ -328,6 +390,60 @@ function buildGatingPathToChildrenMap(
|
|
|
328
390
|
return gatingPathToChildren;
|
|
329
391
|
}
|
|
330
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Assign exclusiveGroup for truthy/falsy flow pairs that control child components.
|
|
395
|
+
*
|
|
396
|
+
* When the same attribute path produces both a truthy and falsy flow (e.g.,
|
|
397
|
+
* {diffView && <DiffModal/>}), they are mutually exclusive — only one can be
|
|
398
|
+
* active at a time. Grouping them ensures the scenario generator treats them
|
|
399
|
+
* as alternative states rather than combining them.
|
|
400
|
+
*/
|
|
401
|
+
function assignExclusiveGroupsForGatingPairs(flows: ExecutionFlow[]): void {
|
|
402
|
+
// Build a map: attributePath -> flows with truthy or falsy comparison for that path
|
|
403
|
+
const pathToFlows = new Map<
|
|
404
|
+
string,
|
|
405
|
+
{ truthy: ExecutionFlow[]; falsy: ExecutionFlow[] }
|
|
406
|
+
>();
|
|
407
|
+
|
|
408
|
+
for (const flow of flows) {
|
|
409
|
+
// Only consider flows that control child components
|
|
410
|
+
if (!flow.childComponentsControlled?.length) continue;
|
|
411
|
+
|
|
412
|
+
for (const rv of flow.requiredValues) {
|
|
413
|
+
if (rv.comparison === 'truthy' || rv.comparison === 'falsy') {
|
|
414
|
+
if (!pathToFlows.has(rv.attributePath)) {
|
|
415
|
+
pathToFlows.set(rv.attributePath, { truthy: [], falsy: [] });
|
|
416
|
+
}
|
|
417
|
+
pathToFlows.get(rv.attributePath)![rv.comparison].push(flow);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Also check falsy flows that DON'T have childComponentsControlled —
|
|
423
|
+
// they still pair with truthy flows that do
|
|
424
|
+
for (const flow of flows) {
|
|
425
|
+
if (flow.childComponentsControlled?.length) continue; // Already processed
|
|
426
|
+
|
|
427
|
+
for (const rv of flow.requiredValues) {
|
|
428
|
+
if (rv.comparison === 'falsy' && pathToFlows.has(rv.attributePath)) {
|
|
429
|
+
pathToFlows.get(rv.attributePath)!.falsy.push(flow);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Assign exclusiveGroup where both truthy and falsy flows exist
|
|
435
|
+
for (const [attributePath, { truthy, falsy }] of pathToFlows) {
|
|
436
|
+
if (truthy.length > 0 && falsy.length > 0) {
|
|
437
|
+
const groupName = `gating:${attributePath}`;
|
|
438
|
+
for (const flow of [...truthy, ...falsy]) {
|
|
439
|
+
if (!flow.exclusiveGroup) {
|
|
440
|
+
flow.exclusiveGroup = groupName;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
331
447
|
/**
|
|
332
448
|
* Calculate priority and childComponentsControlled for a flow.
|
|
333
449
|
*
|
|
@@ -382,6 +498,19 @@ function calculateFlowPriority(
|
|
|
382
498
|
if (flow.impact !== 'high') {
|
|
383
499
|
flow.impact = 'high';
|
|
384
500
|
}
|
|
501
|
+
|
|
502
|
+
// Check if any controlled child component is a modal/dialog/overlay.
|
|
503
|
+
// Only truthy flows (which SHOW the component) should be marked as blocking.
|
|
504
|
+
// Falsy flows (which HIDE the component) should not be blocking.
|
|
505
|
+
const isTruthyFlow = flow.requiredValues.some(
|
|
506
|
+
(rv) => rv.comparison === 'truthy' || rv.comparison === 'equals',
|
|
507
|
+
);
|
|
508
|
+
if (
|
|
509
|
+
isTruthyFlow &&
|
|
510
|
+
Array.from(childComponentsControlled).some(isBlockingChildComponent)
|
|
511
|
+
) {
|
|
512
|
+
flow.blocksOtherFlows = true;
|
|
513
|
+
}
|
|
385
514
|
}
|
|
386
515
|
|
|
387
516
|
// Calculate priority score
|
|
@@ -503,8 +632,11 @@ function buildValueGroupMap(flows: ExecutionFlow[]): Map<string, string[]> {
|
|
|
503
632
|
for (const [, flowValues] of pathToValues) {
|
|
504
633
|
// Only create groups if there are multiple different values for the same path
|
|
505
634
|
const uniqueValues = new Set(flowValues.map((fv) => fv.value));
|
|
506
|
-
if (uniqueValues.size > 1) {
|
|
507
|
-
// This attribute has multiple values, so all flows are siblings
|
|
635
|
+
if (uniqueValues.size > 1 && flowValues.length <= 10) {
|
|
636
|
+
// This attribute has multiple values, so all flows are siblings.
|
|
637
|
+
// Skip large groups (>10 flows) — these are typically shared gating conditions
|
|
638
|
+
// (like route params) that would dominate the selection by pulling in too many
|
|
639
|
+
// siblings and displacing higher-priority flows.
|
|
508
640
|
const siblingIds = flowValues.map((fv) => fv.flowId);
|
|
509
641
|
for (const fv of flowValues) {
|
|
510
642
|
valueGroupMap.set(
|