@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
|
@@ -105,11 +105,13 @@ function cleanSourceDataPath(sourceDataPath) {
|
|
|
105
105
|
// 2. Patterns like functionName(...) - closing paren followed by dot or end
|
|
106
106
|
const emptyFnCalls = (sourceDataPath.match(/\(\)/g) || []).length;
|
|
107
107
|
const fnCallReturnValues = (sourceDataPath.match(/\.functionCallReturnValue/g) || []).length;
|
|
108
|
-
//
|
|
109
|
-
//
|
|
108
|
+
// For chained function calls (e.g., fetch().json()) or paths with non-standard
|
|
109
|
+
// fn call patterns, return the original path so findInAttributesMapForPath can
|
|
110
|
+
// try to look it up in fullToShortPathMap. If it doesn't match, the caller
|
|
111
|
+
// falls through to fallback resolution anyway.
|
|
110
112
|
if (fnCallReturnValues > 1 || emptyFnCalls !== 1) {
|
|
111
|
-
|
|
112
|
-
return
|
|
113
|
+
console.log(`[cleanSourceDataPath] chained/non-standard path (fnCallRVs=${fnCallReturnValues}, emptyFnCalls=${emptyFnCalls}), returning original: "${sourceDataPath}"`);
|
|
114
|
+
return sourceDataPath;
|
|
113
115
|
}
|
|
114
116
|
// Find the "()" which marks the function call
|
|
115
117
|
const fnCallIndex = sourceDataPath.indexOf('()');
|
|
@@ -146,6 +148,71 @@ function stripLengthSuffix(path) {
|
|
|
146
148
|
}
|
|
147
149
|
return path;
|
|
148
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Remove contradictory required values from a compound flow.
|
|
153
|
+
*
|
|
154
|
+
* When a lifecycle boolean (like isLoadingAuditData) is traced to a fetch call's
|
|
155
|
+
* return value, a negated condition (!isLoadingAuditData) produces "falsy" on
|
|
156
|
+
* the fetch path. But if another condition in the same compound requires data
|
|
157
|
+
* from a sub-path of that fetch (e.g., topPaths length > 0), the "falsy" on the
|
|
158
|
+
* parent path contradicts it — a null/falsy response has no .json() to call.
|
|
159
|
+
*
|
|
160
|
+
* This function removes "falsy" required values whose attributePath is a prefix
|
|
161
|
+
* of another required value's attributePath. The child data requirement already
|
|
162
|
+
* implies the parent (fetch) succeeded.
|
|
163
|
+
*/
|
|
164
|
+
function removeContradictoryFalsyValues(requiredValues) {
|
|
165
|
+
return requiredValues.filter((rv) => {
|
|
166
|
+
if (rv.comparison === 'falsy') {
|
|
167
|
+
const hasChildRequirement = requiredValues.some((other) => other !== rv &&
|
|
168
|
+
other.attributePath.startsWith(rv.attributePath + '.'));
|
|
169
|
+
if (hasChildRequirement) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Generate a human-readable description snippet for a required value,
|
|
178
|
+
* incorporating the comparison type so the LLM understands the intent.
|
|
179
|
+
*/
|
|
180
|
+
function describeRequiredValue(rv) {
|
|
181
|
+
const name = generateNameFromPath(rv.attributePath).toLowerCase();
|
|
182
|
+
switch (rv.comparison) {
|
|
183
|
+
case 'truthy':
|
|
184
|
+
return `${name} is present`;
|
|
185
|
+
case 'falsy':
|
|
186
|
+
return `${name} is absent`;
|
|
187
|
+
case 'length>':
|
|
188
|
+
return rv.value === '0'
|
|
189
|
+
? `${name} has items`
|
|
190
|
+
: `${name} has more than ${rv.value} items`;
|
|
191
|
+
case 'length<':
|
|
192
|
+
return `${name} has fewer than ${rv.value} items`;
|
|
193
|
+
case 'equals':
|
|
194
|
+
return `${name} is ${rv.value}`;
|
|
195
|
+
case 'exists':
|
|
196
|
+
return `${name} exists`;
|
|
197
|
+
case 'not-exists':
|
|
198
|
+
return `${name} does not exist`;
|
|
199
|
+
default:
|
|
200
|
+
return `${name} is ${rv.value}`;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Check whether a resolved path has child entries in the fullToShortPathMap.
|
|
205
|
+
*
|
|
206
|
+
* When a lifecycle boolean (e.g., isLoadingAuditData) resolves to a parent path
|
|
207
|
+
* like fetch(...).functionCallReturnValue, and that path has children (like
|
|
208
|
+
* .json().functionCallReturnValue.topPaths), individual truthy/falsy flows on
|
|
209
|
+
* the parent are misleading. Compound flows with specific child requirements
|
|
210
|
+
* provide better guidance for mock data generation.
|
|
211
|
+
*/
|
|
212
|
+
function hasChildPathsInMap(resolvedPath, fullToShortPathMap) {
|
|
213
|
+
return Object.keys(fullToShortPathMap).some((fullPath) => fullPath.startsWith(resolvedPath + '.') ||
|
|
214
|
+
fullPath.startsWith(resolvedPath + '['));
|
|
215
|
+
}
|
|
149
216
|
/**
|
|
150
217
|
* Extract the controllable base path from a path that may contain method calls.
|
|
151
218
|
*
|
|
@@ -184,9 +251,10 @@ function extractControllableBase(path) {
|
|
|
184
251
|
* The sourceDataPath contains full paths (e.g., "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha")
|
|
185
252
|
* The fullToShortPathMap maps full paths to short paths
|
|
186
253
|
*/
|
|
187
|
-
function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
|
|
254
|
+
export function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
|
|
188
255
|
// Direct match in attributesMap (already a short path)
|
|
189
256
|
if (path in attributesMap) {
|
|
257
|
+
console.log(`[findInAttributesMapForPath] "${path}" → DIRECT match in attributesMap`);
|
|
190
258
|
return path;
|
|
191
259
|
}
|
|
192
260
|
// Try looking up the path in fullToShortPathMap to verify it's controllable
|
|
@@ -194,18 +262,22 @@ function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
|
|
|
194
262
|
if (path in fullToShortPathMap) {
|
|
195
263
|
const shortPath = fullToShortPathMap[path];
|
|
196
264
|
if (shortPath in attributesMap) {
|
|
265
|
+
console.log(`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match: shortPath="${shortPath}" found in attributesMap`);
|
|
197
266
|
return path; // Return FULL path to preserve data source context
|
|
198
267
|
}
|
|
268
|
+
console.log(`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match shortPath="${shortPath}" but NOT in attributesMap`);
|
|
199
269
|
}
|
|
200
270
|
// Normalized match (array indices [N] → [])
|
|
201
271
|
const normalizedPath = path.replace(/\[\d+\]/g, '[]');
|
|
202
272
|
if (normalizedPath !== path) {
|
|
203
273
|
if (normalizedPath in attributesMap) {
|
|
274
|
+
console.log(`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" DIRECT match in attributesMap`);
|
|
204
275
|
return normalizedPath;
|
|
205
276
|
}
|
|
206
277
|
if (normalizedPath in fullToShortPathMap) {
|
|
207
278
|
const shortPath = fullToShortPathMap[normalizedPath];
|
|
208
279
|
if (shortPath in attributesMap) {
|
|
280
|
+
console.log(`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" fullToShortPathMap match: shortPath="${shortPath}"`);
|
|
209
281
|
return normalizedPath; // Return normalized FULL path
|
|
210
282
|
}
|
|
211
283
|
}
|
|
@@ -216,18 +288,55 @@ function findInAttributesMapForPath(path, attributesMap, fullToShortPathMap) {
|
|
|
216
288
|
// and we need to find matching short path prefix
|
|
217
289
|
for (const attrPath of Object.keys(attributesMap)) {
|
|
218
290
|
if (path.startsWith(attrPath + '.') || path.startsWith(attrPath + '[')) {
|
|
219
|
-
|
|
291
|
+
console.log(`[findInAttributesMapForPath] "${path}" → PREFIX match: starts with attributesMap key "${attrPath}"`);
|
|
220
292
|
return path;
|
|
221
293
|
}
|
|
222
294
|
}
|
|
223
295
|
// Try suffix matching: if the path ends with ".X.Y.Z" and attributesMap has "X.Y.Z"
|
|
224
296
|
// Return the FULL input path to preserve data source context
|
|
225
|
-
for
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
297
|
+
// Skip suffix matching for chained function calls (multiple .functionCallReturnValue segments)
|
|
298
|
+
// to avoid false matches: e.g., fetch(...).json().functionCallReturnValue.data falsely matching
|
|
299
|
+
// "data" from a completely different data source like useFetcher
|
|
300
|
+
const fnCallReturnValueCount = (path.match(/\.functionCallReturnValue/g) || []).length;
|
|
301
|
+
if (fnCallReturnValueCount <= 1) {
|
|
302
|
+
for (const attrPath of Object.keys(attributesMap)) {
|
|
303
|
+
if (path.endsWith('.' + attrPath) ||
|
|
304
|
+
path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))) {
|
|
305
|
+
console.log(`[findInAttributesMapForPath] "${path}" → SUFFIX match: ends with attributesMap key "${attrPath}"`);
|
|
306
|
+
return path; // Return FULL path, not short attrPath
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Try child path matching against fullToShortPathMap keys
|
|
311
|
+
// If the path starts with a known full path + '.' or '[', it's a child
|
|
312
|
+
// of a controllable path. Build the equivalent short child path.
|
|
313
|
+
// e.g., path = "fetch(...).fCRV.json().fCRV.topPaths.length"
|
|
314
|
+
// fullToShortPathMap has "fetch(...).fCRV.json().fCRV.topPaths" → "json().fCRV.topPaths"
|
|
315
|
+
// → check if "json().fCRV.topPaths.length" is in attributesMap
|
|
316
|
+
for (const [fullPath, shortPath] of Object.entries(fullToShortPathMap)) {
|
|
317
|
+
if (path.startsWith(fullPath + '.') || path.startsWith(fullPath + '[')) {
|
|
318
|
+
const suffix = path.slice(fullPath.length); // e.g., ".length"
|
|
319
|
+
const shortChildPath = shortPath + suffix;
|
|
320
|
+
if (shortChildPath in attributesMap) {
|
|
321
|
+
console.log(`[findInAttributesMapForPath] "${path}" → CHILD of fullToShortPathMap key "${fullPath}": shortChildPath="${shortChildPath}" found in attributesMap`);
|
|
322
|
+
return path; // Return full path to preserve data source context
|
|
323
|
+
}
|
|
324
|
+
// Also check if the base short path is an array and suffix is .length
|
|
325
|
+
if (suffix === '.length' && shortPath in attributesMap) {
|
|
326
|
+
console.log(`[findInAttributesMapForPath] "${path}" → CHILD .length of fullToShortPathMap key "${fullPath}": base shortPath="${shortPath}" is in attributesMap (array .length)`);
|
|
327
|
+
return path; // Array .length is controllable via the array
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Try parent matching: if the path is a prefix of any fullToShortPathMap key,
|
|
332
|
+
// it's a parent of controllable data and therefore controllable itself
|
|
333
|
+
for (const fullPath of Object.keys(fullToShortPathMap)) {
|
|
334
|
+
if (fullPath.startsWith(path + '.') || fullPath.startsWith(path + '[')) {
|
|
335
|
+
console.log(`[findInAttributesMapForPath] "${path}" → PARENT match: fullToShortPathMap key "${fullPath}" starts with this path`);
|
|
336
|
+
return path;
|
|
229
337
|
}
|
|
230
338
|
}
|
|
339
|
+
console.log(`[findInAttributesMapForPath] "${path}" → NO MATCH (checked ${Object.keys(attributesMap).length} attributesMap keys, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap keys)`);
|
|
231
340
|
return null;
|
|
232
341
|
}
|
|
233
342
|
/**
|
|
@@ -432,7 +541,17 @@ function generateFlowFromCompound(compound, resolvedPaths) {
|
|
|
432
541
|
condition.requiredValue?.toString() ??
|
|
433
542
|
condition.comparedValues?.[0] ??
|
|
434
543
|
'truthy';
|
|
435
|
-
comparison
|
|
544
|
+
// Map comparison operator to flow comparison type
|
|
545
|
+
const op = condition.comparisonOperator;
|
|
546
|
+
if (op === '>' || op === '>=') {
|
|
547
|
+
comparison = 'length>';
|
|
548
|
+
}
|
|
549
|
+
else if (op === '<' || op === '<=') {
|
|
550
|
+
comparison = 'length<';
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
comparison = 'equals';
|
|
554
|
+
}
|
|
436
555
|
}
|
|
437
556
|
requiredValues.push({
|
|
438
557
|
attributePath: stripLengthSuffix(resolvedPath),
|
|
@@ -441,20 +560,28 @@ function generateFlowFromCompound(compound, resolvedPaths) {
|
|
|
441
560
|
valueType: inferValueType(value),
|
|
442
561
|
});
|
|
443
562
|
}
|
|
444
|
-
//
|
|
445
|
-
const
|
|
563
|
+
// Remove contradictory "falsy" values where a child path requires data
|
|
564
|
+
const cleanedValues = removeContradictoryFalsyValues(requiredValues);
|
|
565
|
+
if (cleanedValues.length === 0) {
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
// Generate a combined ID from all paths + values to distinguish different comparisons
|
|
569
|
+
const pathParts = cleanedValues
|
|
446
570
|
.map((rv) => {
|
|
447
571
|
const name = generateNameFromPath(rv.attributePath);
|
|
448
|
-
|
|
572
|
+
const suffix = rv.comparison === 'truthy' || rv.comparison === 'falsy'
|
|
573
|
+
? `-${rv.comparison}`
|
|
574
|
+
: `-${rv.comparison}-${rv.value}`;
|
|
575
|
+
return name.toLowerCase().replace(/\s+/g, '-') + suffix;
|
|
449
576
|
})
|
|
450
577
|
.join('-and-');
|
|
451
578
|
return {
|
|
452
579
|
id: `compound-${pathParts}`,
|
|
453
|
-
name:
|
|
580
|
+
name: cleanedValues
|
|
454
581
|
.map((rv) => generateNameFromPath(rv.attributePath))
|
|
455
582
|
.join(' + '),
|
|
456
|
-
description: `When ${
|
|
457
|
-
requiredValues,
|
|
583
|
+
description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
|
|
584
|
+
requiredValues: cleanedValues,
|
|
458
585
|
impact,
|
|
459
586
|
sourceLocation: {
|
|
460
587
|
lineNumber: compound.sourceLocation.lineNumber,
|
|
@@ -603,6 +730,11 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
603
730
|
const { conditionalUsages, compoundConditionals, attributesMap, equivalentSignatureVariables, fullToShortPathMap, childComponentData, derivedVariables, sourceEquivalencies, } = args;
|
|
604
731
|
const flows = [];
|
|
605
732
|
const seenFlowIds = new Set();
|
|
733
|
+
console.log(`[genFlowsFromConditionals] INPUT: ${Object.keys(conditionalUsages).length} conditional paths, ${Object.keys(attributesMap).length} attributesMap entries, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap entries, ${Object.keys(equivalentSignatureVariables).length} equivSigVars, ${compoundConditionals.length} compound conditionals`);
|
|
734
|
+
console.log(`[genFlowsFromConditionals] conditionalUsages keys: [${Object.keys(conditionalUsages).join(', ')}]`);
|
|
735
|
+
console.log(`[genFlowsFromConditionals] attributesMap keys: [${Object.keys(attributesMap).join(', ')}]`);
|
|
736
|
+
console.log(`[genFlowsFromConditionals] fullToShortPathMap: ${JSON.stringify(fullToShortPathMap)}`);
|
|
737
|
+
console.log(`[genFlowsFromConditionals] equivalentSignatureVariables: ${JSON.stringify(equivalentSignatureVariables)}`);
|
|
606
738
|
// Track normalized resolved paths to prevent duplicate flows
|
|
607
739
|
// This handles the case where we have usages for both:
|
|
608
740
|
// - "hasNewerVersion" (short path from destructured variable)
|
|
@@ -616,8 +748,10 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
616
748
|
for (const usage of usages) {
|
|
617
749
|
// Skip usages that are part of compound conditionals (handled separately)
|
|
618
750
|
if (usage.chainId && compoundChainIds.has(usage.chainId)) {
|
|
751
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: part of compound conditional chain=${usage.chainId}`);
|
|
619
752
|
continue;
|
|
620
753
|
}
|
|
754
|
+
console.log(`[genFlowsFromConditionals] --- Processing "${usage.path}" (type=${usage.conditionType}, negated=${usage.isNegated}, sourceDataPath="${usage.sourceDataPath ?? '(none)'}", derivedFrom=${usage.derivedFrom ? JSON.stringify(usage.derivedFrom) : 'none'})`);
|
|
621
755
|
// First, try to use pre-computed sourceDataPath if available
|
|
622
756
|
let resolvedPath = null;
|
|
623
757
|
if (usage.sourceDataPath) {
|
|
@@ -626,9 +760,11 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
626
760
|
// should become "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
|
|
627
761
|
// Returns null for malformed paths (e.g., chained function calls like fetch().json())
|
|
628
762
|
const cleanedPath = cleanSourceDataPath(usage.sourceDataPath);
|
|
763
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" cleanSourceDataPath("${usage.sourceDataPath}") → "${cleanedPath}"`);
|
|
629
764
|
if (cleanedPath) {
|
|
630
765
|
// Verify the cleaned path exists in attributesMap
|
|
631
766
|
const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
|
|
767
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" findInAttributesMapForPath("${cleanedPath}") → ${pathMatch ? `"${pathMatch}"` : 'null (not found)'}`);
|
|
632
768
|
if (pathMatch) {
|
|
633
769
|
resolvedPath = pathMatch;
|
|
634
770
|
}
|
|
@@ -637,7 +773,9 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
637
773
|
}
|
|
638
774
|
// Fall back to resolution via equivalentSignatureVariables
|
|
639
775
|
if (!resolvedPath) {
|
|
776
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" sourceDataPath resolution failed, trying resolvePathToControllable("${usage.path}")...`);
|
|
640
777
|
const resolution = resolvePathToControllable(usage.path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
|
|
778
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" resolvePathToControllable → isControllable=${resolution.isControllable}, resolvedPath="${resolution.resolvedPath ?? '(none)'}"`);
|
|
641
779
|
if (resolution.isControllable && resolution.resolvedPath) {
|
|
642
780
|
resolvedPath = resolution.resolvedPath;
|
|
643
781
|
}
|
|
@@ -647,6 +785,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
647
785
|
// where hasAnalysis is not in attributesMap but analysis is
|
|
648
786
|
if (!resolvedPath && usage.derivedFrom) {
|
|
649
787
|
const { operation, sourcePath, sourcePaths, comparedValue } = usage.derivedFrom;
|
|
788
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" trying derivedFrom: operation=${operation}, sourcePath="${sourcePath ?? '(none)'}", sourcePaths=${sourcePaths ? JSON.stringify(sourcePaths) : '(none)'}, comparedValue="${comparedValue ?? '(none)'}"`);
|
|
650
789
|
// For single-source derivations (notNull, equals, etc.)
|
|
651
790
|
if (sourcePath) {
|
|
652
791
|
const resolution = resolvePathToControllable(sourcePath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
|
|
@@ -892,6 +1031,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
892
1031
|
}
|
|
893
1032
|
if (!resolvedPath) {
|
|
894
1033
|
// Path is not controllable - skip (no invalid flows possible)
|
|
1034
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: not controllable (no resolvedPath after all attempts)`);
|
|
895
1035
|
continue;
|
|
896
1036
|
}
|
|
897
1037
|
// Normalize the resolved path to detect duplicates
|
|
@@ -901,9 +1041,22 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
901
1041
|
// Skip if we've already generated flows for this normalized path
|
|
902
1042
|
// This prevents duplicate flows when we have usages for both short and full paths
|
|
903
1043
|
if (seenNormalizedPaths.has(normalizedPath)) {
|
|
1044
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: duplicate normalizedPath="${normalizedPath}" (resolvedPath="${resolvedPath}")`);
|
|
904
1045
|
continue;
|
|
905
1046
|
}
|
|
906
1047
|
seenNormalizedPaths.add(normalizedPath);
|
|
1048
|
+
// Skip individual truthy/falsy flows on parent paths that have child data entries.
|
|
1049
|
+
// Lifecycle booleans (like isLoadingAuditData) traced to fetch(...).functionCallReturnValue
|
|
1050
|
+
// produce misleading truthy/falsy flows: "truthy" can't show loading (mock resolves instantly),
|
|
1051
|
+
// "falsy" tells the LLM to return null (breaking .json()). Compound flows with specific child
|
|
1052
|
+
// data requirements provide the correct mock guidance.
|
|
1053
|
+
if (usage.conditionType === 'truthiness' &&
|
|
1054
|
+
resolvedPath &&
|
|
1055
|
+
hasChildPathsInMap(resolvedPath, fullToShortPathMap)) {
|
|
1056
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" SKIP: parent path "${resolvedPath}" has child data paths — compound flows will handle this`);
|
|
1057
|
+
continue;
|
|
1058
|
+
}
|
|
1059
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" RESOLVED → resolvedPath="${resolvedPath}", normalizedPath="${normalizedPath}" — generating flows`);
|
|
907
1060
|
// Generate flows for this controllable usage
|
|
908
1061
|
const usageFlows = generateFlowsFromUsage(usage, resolvedPath);
|
|
909
1062
|
for (const flow of usageFlows) {
|
|
@@ -911,6 +1064,7 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
911
1064
|
if (!seenFlowIds.has(flow.id)) {
|
|
912
1065
|
seenFlowIds.add(flow.id);
|
|
913
1066
|
flows.push(flow);
|
|
1067
|
+
console.log(`[genFlowsFromConditionals] "${usage.path}" FLOW ADDED: id="${flow.id}", requiredValues=${JSON.stringify(flow.requiredValues.map((rv) => ({ attr: rv.attributePath, val: rv.value })))}`);
|
|
914
1068
|
}
|
|
915
1069
|
}
|
|
916
1070
|
}
|
|
@@ -946,19 +1100,57 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
946
1100
|
resolvedPaths.set(condition.path, sources[0].path);
|
|
947
1101
|
}
|
|
948
1102
|
else {
|
|
949
|
-
// Derived variable
|
|
950
|
-
|
|
951
|
-
|
|
1103
|
+
// Derived variable expansion failed — try sourceDataPath fallback
|
|
1104
|
+
// This handles cases where the derivation chain goes through useMemo/useState
|
|
1105
|
+
// but the enriched sourceDataPath already traced to the actual data source
|
|
1106
|
+
const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
|
|
1107
|
+
let derivedFallbackPath = null;
|
|
1108
|
+
if (usageWithSource?.sourceDataPath) {
|
|
1109
|
+
const cleanedPath = cleanSourceDataPath(usageWithSource.sourceDataPath);
|
|
1110
|
+
if (cleanedPath) {
|
|
1111
|
+
const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
|
|
1112
|
+
if (pathMatch) {
|
|
1113
|
+
derivedFallbackPath = pathMatch;
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
if (derivedFallbackPath) {
|
|
1118
|
+
resolvedPaths.set(condition.path, derivedFallbackPath);
|
|
1119
|
+
console.log(`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived expansion failed but sourceDataPath fallback resolved → "${derivedFallbackPath}"`);
|
|
1120
|
+
}
|
|
1121
|
+
else {
|
|
1122
|
+
// Truly not controllable
|
|
1123
|
+
console.log(`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived but no controllable sources and no sourceDataPath fallback → NOT controllable`);
|
|
1124
|
+
allControllable = false;
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
952
1127
|
}
|
|
953
1128
|
}
|
|
954
1129
|
else {
|
|
955
1130
|
// Not a derived variable - resolve directly
|
|
956
|
-
|
|
957
|
-
|
|
1131
|
+
// First try sourceDataPath from the usage (same as individual processing)
|
|
1132
|
+
let compoundResolvedPath = null;
|
|
1133
|
+
const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
|
|
1134
|
+
if (usageWithSource?.sourceDataPath) {
|
|
1135
|
+
const cleanedPath = cleanSourceDataPath(usageWithSource.sourceDataPath);
|
|
1136
|
+
if (cleanedPath) {
|
|
1137
|
+
const pathMatch = findInAttributesMapForPath(cleanedPath, attributesMap, fullToShortPathMap);
|
|
1138
|
+
if (pathMatch) {
|
|
1139
|
+
compoundResolvedPath = pathMatch;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
if (!compoundResolvedPath) {
|
|
1144
|
+
const resolution = resolvePathToControllable(condition.path, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
|
|
1145
|
+
if (resolution.isControllable && resolution.resolvedPath) {
|
|
1146
|
+
compoundResolvedPath = resolution.resolvedPath;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
if (!compoundResolvedPath) {
|
|
958
1150
|
allControllable = false;
|
|
959
1151
|
break;
|
|
960
1152
|
}
|
|
961
|
-
resolvedPaths.set(condition.path,
|
|
1153
|
+
resolvedPaths.set(condition.path, compoundResolvedPath);
|
|
962
1154
|
}
|
|
963
1155
|
}
|
|
964
1156
|
// Only create a flow if ALL paths are controllable
|
|
@@ -1031,7 +1223,16 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1031
1223
|
condition.requiredValue?.toString() ??
|
|
1032
1224
|
condition.comparedValues?.[0] ??
|
|
1033
1225
|
'truthy';
|
|
1034
|
-
|
|
1226
|
+
const op = condition.comparisonOperator;
|
|
1227
|
+
if (op === '>' || op === '>=') {
|
|
1228
|
+
comparison = 'length>';
|
|
1229
|
+
}
|
|
1230
|
+
else if (op === '<' || op === '<=') {
|
|
1231
|
+
comparison = 'length<';
|
|
1232
|
+
}
|
|
1233
|
+
else {
|
|
1234
|
+
comparison = 'equals';
|
|
1235
|
+
}
|
|
1035
1236
|
}
|
|
1036
1237
|
requiredValues.push({
|
|
1037
1238
|
attributePath: stripLengthSuffix(resolvedPath),
|
|
@@ -1042,21 +1243,26 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1042
1243
|
}
|
|
1043
1244
|
}
|
|
1044
1245
|
}
|
|
1045
|
-
|
|
1246
|
+
// Remove contradictory "falsy" values where a child path requires data
|
|
1247
|
+
const cleanedValues = removeContradictoryFalsyValues(requiredValues);
|
|
1248
|
+
if (cleanedValues.length > 0) {
|
|
1046
1249
|
const impact = compound.controlsJsxRendering ? 'high' : 'medium';
|
|
1047
|
-
// Generate a combined ID from all paths
|
|
1048
|
-
const pathParts =
|
|
1250
|
+
// Generate a combined ID from all paths + values
|
|
1251
|
+
const pathParts = cleanedValues
|
|
1049
1252
|
.map((rv) => {
|
|
1050
1253
|
const name = generateNameFromPath(rv.attributePath);
|
|
1051
|
-
|
|
1254
|
+
const suffix = rv.comparison === 'truthy' || rv.comparison === 'falsy'
|
|
1255
|
+
? `-${rv.comparison}`
|
|
1256
|
+
: `-${rv.comparison}-${rv.value}`;
|
|
1257
|
+
return name.toLowerCase().replace(/\s+/g, '-') + suffix;
|
|
1052
1258
|
})
|
|
1053
1259
|
.join('-and-');
|
|
1054
1260
|
const compoundFlow = {
|
|
1055
|
-
id: `${pathParts}
|
|
1056
|
-
name: generateNameFromPath(
|
|
1057
|
-
description: `When ${
|
|
1261
|
+
id: `${pathParts}`,
|
|
1262
|
+
name: generateNameFromPath(cleanedValues[0].attributePath),
|
|
1263
|
+
description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
|
|
1058
1264
|
impact,
|
|
1059
|
-
requiredValues,
|
|
1265
|
+
requiredValues: cleanedValues,
|
|
1060
1266
|
sourceLocation: compound.sourceLocation,
|
|
1061
1267
|
};
|
|
1062
1268
|
if (!seenFlowIds.has(compoundFlow.id)) {
|
|
@@ -1216,8 +1422,6 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1216
1422
|
const childCompoundChainIds = new Set(childData.compoundConditionals.map((c) => c.chainId).filter(Boolean));
|
|
1217
1423
|
for (const [_path, usages] of Object.entries(childData.conditionalUsages)) {
|
|
1218
1424
|
for (const usage of usages) {
|
|
1219
|
-
// Debug logging (disabled - set to true for troubleshooting child flow resolution)
|
|
1220
|
-
const shouldDebugChild = false;
|
|
1221
1425
|
// Skip usages that are part of compound conditionals (handled separately)
|
|
1222
1426
|
// Fix 33: Only skip if the chainId is in the child's compound conditionals
|
|
1223
1427
|
if (usage.chainId && childCompoundChainIds.has(usage.chainId)) {
|
|
@@ -1229,43 +1433,23 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1229
1433
|
if (usage.derivedFrom?.sourcePath) {
|
|
1230
1434
|
childPath = usage.derivedFrom.sourcePath;
|
|
1231
1435
|
}
|
|
1232
|
-
if (shouldDebugChild) {
|
|
1233
|
-
console.log(`[DEBUG CHILD ${childName}] Processing usage path: ${usage.path}`);
|
|
1234
|
-
console.log(`[DEBUG CHILD ${childName}] childPath (after derivedFrom): ${childPath}`);
|
|
1235
|
-
console.log(`[DEBUG CHILD ${childName}] sourceDataPath: ${usage.sourceDataPath}`);
|
|
1236
|
-
}
|
|
1237
1436
|
// Translate the child path to a parent path
|
|
1238
1437
|
let translatedPath = translateChildPathToParent(childPath, childData.equivalentSignatureVariables, equivalentSignatureVariables, childName);
|
|
1239
|
-
if (shouldDebugChild) {
|
|
1240
|
-
console.log(`[DEBUG CHILD ${childName}] translatedPath (from translateChildPathToParent): ${translatedPath}`);
|
|
1241
|
-
}
|
|
1242
1438
|
// If translation failed but we have sourceDataPath, try to extract the prop path from it
|
|
1243
1439
|
// sourceDataPath format: "ChildName.signature[n].propPath.rest" → extract "propPath.rest"
|
|
1244
1440
|
if (!translatedPath && usage.sourceDataPath) {
|
|
1245
1441
|
const signatureMatch = usage.sourceDataPath.match(/\.signature\[\d+\]\.(.+)$/);
|
|
1246
1442
|
if (signatureMatch) {
|
|
1247
1443
|
translatedPath = signatureMatch[1];
|
|
1248
|
-
if (shouldDebugChild) {
|
|
1249
|
-
console.log(`[DEBUG CHILD ${childName}] translatedPath (from sourceDataPath regex): ${translatedPath}`);
|
|
1250
|
-
}
|
|
1251
1444
|
}
|
|
1252
1445
|
}
|
|
1253
1446
|
if (!translatedPath) {
|
|
1254
1447
|
// Could not translate - skip this usage
|
|
1255
|
-
if (shouldDebugChild) {
|
|
1256
|
-
console.log(`[DEBUG CHILD ${childName}] SKIPPED - no translation found`);
|
|
1257
|
-
}
|
|
1258
1448
|
continue;
|
|
1259
1449
|
}
|
|
1260
1450
|
// Now resolve the translated path in the parent context
|
|
1261
1451
|
// First, try standard resolution
|
|
1262
1452
|
const resolution = resolvePathToControllable(translatedPath, attributesMap, equivalentSignatureVariables, fullToShortPathMap);
|
|
1263
|
-
if (shouldDebugChild) {
|
|
1264
|
-
console.log(`[DEBUG CHILD ${childName}] resolvePathToControllable result:`);
|
|
1265
|
-
console.log(`[DEBUG CHILD ${childName}] isControllable: ${resolution.isControllable}`);
|
|
1266
|
-
console.log(`[DEBUG CHILD ${childName}] resolvedPath: ${resolution.resolvedPath}`);
|
|
1267
|
-
console.log(`[DEBUG CHILD ${childName}] chain: ${resolution.resolutionChain.join(' -> ')}`);
|
|
1268
|
-
}
|
|
1269
1453
|
// Only create flows for controllable paths (whitelist approach).
|
|
1270
1454
|
// If the path doesn't resolve to something in attributesMap, skip it.
|
|
1271
1455
|
// This prevents creating flows for useState values which are not
|
|
@@ -1292,19 +1476,10 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1292
1476
|
break;
|
|
1293
1477
|
}
|
|
1294
1478
|
}
|
|
1295
|
-
if (shouldDebugChild) {
|
|
1296
|
-
console.log(`[DEBUG CHILD ${childName}] useState fallback: looking for URL param`);
|
|
1297
|
-
console.log(`[DEBUG CHILD ${childName}] useStatePattern: ${useStatePattern}`);
|
|
1298
|
-
console.log(`[DEBUG CHILD ${childName}] useStateVarName: ${useStateVarName}`);
|
|
1299
|
-
}
|
|
1300
1479
|
if (useStateVarName) {
|
|
1301
1480
|
// Look for a related URL param like "varNameFromUrl"
|
|
1302
1481
|
const urlParamName = `${useStateVarName}FromUrl`;
|
|
1303
1482
|
const urlParamPath = equivalentSignatureVariables[urlParamName];
|
|
1304
|
-
if (shouldDebugChild) {
|
|
1305
|
-
console.log(`[DEBUG CHILD ${childName}] urlParamName: ${urlParamName}`);
|
|
1306
|
-
console.log(`[DEBUG CHILD ${childName}] urlParamPath: ${urlParamPath}`);
|
|
1307
|
-
}
|
|
1308
1483
|
if (urlParamPath) {
|
|
1309
1484
|
// For useState values initialized from URL params, use the
|
|
1310
1485
|
// URL param variable name directly (e.g., "viewModeFromUrl")
|
|
@@ -1315,9 +1490,6 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1315
1490
|
// The flow will use the URL param name as the attributePath,
|
|
1316
1491
|
// which gets properly resolved when generating mock data.
|
|
1317
1492
|
resolvedPath = urlParamName;
|
|
1318
|
-
if (shouldDebugChild) {
|
|
1319
|
-
console.log(`[DEBUG CHILD ${childName}] useState fallback SUCCESS: using URL param name ${resolvedPath}`);
|
|
1320
|
-
}
|
|
1321
1493
|
}
|
|
1322
1494
|
}
|
|
1323
1495
|
}
|
|
@@ -1358,27 +1530,18 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1358
1530
|
? childPath.slice(childPropName.length)
|
|
1359
1531
|
: '';
|
|
1360
1532
|
resolvedPath = dataSourceResolution.resolvedPath + suffix;
|
|
1361
|
-
if (shouldDebugChild) {
|
|
1362
|
-
console.log(`[DEBUG CHILD ${childName}] sourceEquivalencies fallback SUCCESS: using data source ${resolvedPath}`);
|
|
1363
|
-
}
|
|
1364
1533
|
}
|
|
1365
1534
|
}
|
|
1366
1535
|
}
|
|
1367
1536
|
}
|
|
1368
1537
|
// If still not resolved after fallback, skip
|
|
1369
1538
|
if (!resolvedPath) {
|
|
1370
|
-
if (shouldDebugChild) {
|
|
1371
|
-
console.log(`[DEBUG CHILD ${childName}] SKIPPED - path not controllable`);
|
|
1372
|
-
}
|
|
1373
1539
|
continue;
|
|
1374
1540
|
}
|
|
1375
1541
|
}
|
|
1376
1542
|
// Check for duplicates
|
|
1377
1543
|
const normalizedPath = normalizePathForDeduplication(resolvedPath, fullToShortPathMap);
|
|
1378
1544
|
if (seenNormalizedPaths.has(normalizedPath)) {
|
|
1379
|
-
if (shouldDebugChild) {
|
|
1380
|
-
console.log(`[DEBUG CHILD ${childName}] SKIPPED - duplicate normalized path: ${normalizedPath}`);
|
|
1381
|
-
}
|
|
1382
1545
|
continue;
|
|
1383
1546
|
}
|
|
1384
1547
|
seenNormalizedPaths.add(normalizedPath);
|
|
@@ -1389,12 +1552,6 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1389
1552
|
path: resolvedPath,
|
|
1390
1553
|
};
|
|
1391
1554
|
const usageFlows = generateFlowsFromUsage(translatedUsage, resolvedPath);
|
|
1392
|
-
if (shouldDebugChild) {
|
|
1393
|
-
console.log(`[DEBUG CHILD ${childName}] GENERATING ${usageFlows.length} flows with resolvedPath: ${resolvedPath}`);
|
|
1394
|
-
for (const f of usageFlows) {
|
|
1395
|
-
console.log(`[DEBUG CHILD ${childName}] - Flow ID: ${f.id}, path: ${f.requiredValues[0]?.attributePath}`);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
1555
|
// Add gating conditions to each flow
|
|
1399
1556
|
for (const flow of usageFlows) {
|
|
1400
1557
|
// Add gating required values to the flow
|
|
@@ -1641,6 +1798,10 @@ export default function generateExecutionFlowsFromConditionals(args) {
|
|
|
1641
1798
|
}
|
|
1642
1799
|
}
|
|
1643
1800
|
}
|
|
1801
|
+
console.log(`[genFlowsFromConditionals] RESULT: ${flows.length} total flows generated`);
|
|
1802
|
+
for (const flow of flows) {
|
|
1803
|
+
console.log(`[genFlowsFromConditionals] FLOW: id="${flow.id}" requiredValues=[${flow.requiredValues.map((rv) => `${rv.attributePath}=${rv.value}`).join(', ')}]`);
|
|
1804
|
+
}
|
|
1644
1805
|
return flows;
|
|
1645
1806
|
}
|
|
1646
1807
|
//# sourceMappingURL=generateExecutionFlowsFromConditionals.js.map
|