@codeyam/codeyam-cli 0.1.0-staging.e38f7bd → 0.1.0-staging.fef152f
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 +8 -8
- package/analyzer-template/common/execAsync.ts +1 -1
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +30 -26
- package/analyzer-template/packages/ai/index.ts +21 -5
- package/analyzer-template/packages/ai/package.json +4 -4
- package/analyzer-template/packages/ai/src/lib/__mocks__/completionCall.ts +122 -0
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +228 -24
- package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +205 -10
- package/analyzer-template/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.ts +644 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +181 -23
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.ts +18 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.ts +38 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +181 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +1619 -125
- package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +324 -5
- package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +29 -10
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +216 -36
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +2761 -390
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +21 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +976 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +243 -77
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +71 -2
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +161 -19
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +163 -14
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.ts +98 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +179 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +441 -82
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +183 -0
- package/analyzer-template/packages/ai/src/lib/deepEqual.ts +30 -0
- package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
- package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +74 -7
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +89 -112
- package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +63 -2
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +1419 -101
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +216 -109
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +710 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +528 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +2484 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
- package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +143 -31
- package/analyzer-template/packages/ai/src/lib/guessScenarioDataFromDescription.ts +8 -2
- package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +328 -7
- package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +111 -87
- package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +17 -7
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +32 -102
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +110 -6
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +14 -53
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.ts +58 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.ts +28 -2
- package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
- package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +824 -0
- package/analyzer-template/packages/ai/src/lib/splitOutsideParentheses.ts +5 -1
- package/analyzer-template/packages/ai/src/lib/validateExecutionFlowPaths.ts +531 -0
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +127 -3
- package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +121 -2
- package/analyzer-template/packages/analyze/index.ts +2 -0
- package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +79 -59
- package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
- package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
- package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/asts/nodes/index.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/asts/nodes/isAsyncFunction.ts +67 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +570 -180
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +54 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +3 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeChange.ts +31 -15
- package/analyzer-template/packages/analyze/src/lib/files/analyzeEntity.ts +11 -7
- package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +11 -12
- package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
- package/analyzer-template/packages/analyze/src/lib/files/enums/steps.ts +1 -1
- package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +22 -13
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1315 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +313 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.ts +102 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +711 -78
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.ts +1 -1
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.ts +28 -62
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +550 -137
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +264 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +78 -83
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +4 -8
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1067 -167
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
- package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/index.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
- package/analyzer-template/packages/aws/codebuild/index.ts +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts +11 -1
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js +29 -18
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts +2 -2
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js +2 -2
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts +8 -18
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js +17 -61
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts +15 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts.map +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js +31 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js.map +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js +8 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js.map +1 -1
- package/analyzer-template/packages/aws/package.json +10 -10
- package/analyzer-template/packages/aws/s3/index.ts +1 -0
- package/analyzer-template/packages/aws/src/lib/codebuild/waitForBuild.ts +43 -19
- package/analyzer-template/packages/aws/src/lib/ecs/ecsDefineContainer.ts +3 -3
- package/analyzer-template/packages/aws/src/lib/ecs/ecsTaskFactory.ts +17 -69
- package/analyzer-template/packages/aws/src/lib/s3/checkS3ObjectExists.ts +47 -0
- package/analyzer-template/packages/aws/src/lib/s3/uploadFileToS3.ts +8 -1
- package/analyzer-template/packages/database/package.json +1 -1
- package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/kysely/db.ts +18 -5
- package/analyzer-template/packages/database/src/lib/kysely/tableRelations.ts +2 -2
- package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +36 -9
- package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
- package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
- package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
- package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
- package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
- package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
- package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
- package/analyzer-template/packages/database/src/lib/loadReadyToBeCapturedAnalyses.ts +30 -5
- package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
- package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
- package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
- package/analyzer-template/packages/generate/index.ts +3 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +17 -1
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.ts +193 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.ts +73 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +9 -4
- package/analyzer-template/packages/generate/src/lib/deepMerge.ts +26 -1
- package/analyzer-template/packages/generate/src/lib/directExecutionScript.ts +17 -2
- package/analyzer-template/packages/generate/src/lib/getComponentScenarioPath.ts +8 -3
- package/analyzer-template/packages/generate/src/lib/scenarioComponentForServer.ts +114 -0
- package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +4 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +13 -3
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tableRelations.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts +1 -11
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +30 -7
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts +2 -6
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js +23 -5
- package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/index.d.ts +3 -0
- package/analyzer-template/packages/github/dist/generate/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/index.js +3 -0
- package/analyzer-template/packages/github/dist/generate/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts +9 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts +20 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js +27 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.js +10 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.js +7 -3
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts +8 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js +89 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js.map +1 -0
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js +10 -0
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js +3 -0
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts +2 -2
- package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +87 -13
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Entity.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/Entity.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +7 -0
- package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts +11 -6
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +199 -3
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/StatementInfo.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/StatementInfo.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js +26 -2
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/github/package.json +1 -1
- package/analyzer-template/packages/github/src/lib/loadOrCreateCommit.ts +14 -0
- package/analyzer-template/packages/github/src/lib/syncPrimaryBranch.ts +2 -0
- package/analyzer-template/packages/process/index.ts +2 -0
- package/analyzer-template/packages/process/package.json +12 -0
- package/analyzer-template/packages/process/tsconfig.json +8 -0
- package/analyzer-template/packages/types/index.ts +5 -0
- package/analyzer-template/packages/types/src/types/Analysis.ts +104 -13
- package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
- package/analyzer-template/packages/types/src/types/Entity.ts +2 -0
- package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
- package/analyzer-template/packages/types/src/types/Scenario.ts +11 -10
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +228 -3
- package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
- package/analyzer-template/packages/types/src/types/StatementInfo.ts +2 -0
- package/analyzer-template/packages/ui-components/package.json +4 -4
- package/analyzer-template/packages/ui-components/src/components/ScenarioDetailInteractiveView.tsx +23 -7
- package/analyzer-template/packages/utils/dist/types/index.d.ts +2 -2
- package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +87 -13
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Entity.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/Entity.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +7 -0
- package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts +11 -6
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +199 -3
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/StatementInfo.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/StatementInfo.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js +26 -2
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js.map +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 +98 -3
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/applyUniversalMocks.ts +28 -2
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +121 -3
- package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +27 -0
- package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
- package/analyzer-template/playwright/capture.ts +57 -26
- package/analyzer-template/playwright/captureStatic.ts +1 -1
- package/analyzer-template/playwright/getCodeYamInfo.ts +12 -7
- package/analyzer-template/playwright/takeElementScreenshot.ts +26 -11
- package/analyzer-template/playwright/takeScreenshot.ts +15 -9
- package/analyzer-template/playwright/waitForServer.ts +21 -6
- package/analyzer-template/project/TESTING.md +83 -0
- package/analyzer-template/project/analyzeBaselineCommit.ts +9 -0
- package/analyzer-template/project/analyzeBranchCommit.ts +4 -0
- package/analyzer-template/project/analyzeFileEntities.ts +4 -0
- package/analyzer-template/project/analyzeRegularCommit.ts +9 -0
- package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
- package/analyzer-template/project/constructMockCode.ts +1347 -159
- package/analyzer-template/project/controller/startController.ts +16 -1
- package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
- package/analyzer-template/project/executeLibraryFunctionDirect.ts +7 -3
- package/analyzer-template/project/loadReadyToBeCaptured.ts +82 -42
- package/analyzer-template/project/mocks/analyzeFileMock.ts +8 -7
- package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
- package/analyzer-template/project/orchestrateCapture/KyselyAnalysisLoader.ts +13 -9
- package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +93 -42
- package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
- package/analyzer-template/project/orchestrateCapture.ts +92 -13
- package/analyzer-template/project/reconcileMockDataKeys.ts +245 -2
- package/analyzer-template/project/runAnalysis.ts +11 -0
- package/analyzer-template/project/runMultiScenarioServer.ts +11 -10
- package/analyzer-template/project/serverOnlyModules.ts +413 -0
- package/analyzer-template/project/start.ts +72 -19
- package/analyzer-template/project/startScenarioCapture.ts +79 -41
- package/analyzer-template/project/writeMockDataTsx.ts +466 -73
- package/analyzer-template/project/writeScenarioClientWrapper.ts +21 -0
- package/analyzer-template/project/writeScenarioComponents.ts +1509 -226
- package/analyzer-template/project/writeScenarioFiles.ts +26 -0
- package/analyzer-template/project/writeSimpleRoot.ts +56 -22
- package/analyzer-template/project/writeUniversalMocks.ts +32 -11
- package/analyzer-template/scripts/comboWorkerLoop.cjs +99 -50
- package/analyzer-template/scripts/defaultCmd.sh +9 -0
- package/analyzer-template/tsconfig.json +2 -1
- package/background/src/lib/local/createLocalAnalyzer.js +2 -30
- package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
- package/background/src/lib/local/execAsync.js +1 -1
- package/background/src/lib/local/execAsync.js.map +1 -1
- package/background/src/lib/virtualized/common/execAsync.js +1 -1
- package/background/src/lib/virtualized/common/execAsync.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +7 -1
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeBranchCommit.js +2 -1
- package/background/src/lib/virtualized/project/analyzeBranchCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeFileEntities.js +2 -1
- package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js +7 -1
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
- package/background/src/lib/virtualized/project/constructMockCode.js +1194 -120
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/controller/startController.js +11 -1
- package/background/src/lib/virtualized/project/controller/startController.js.map +1 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
- package/background/src/lib/virtualized/project/executeLibraryFunctionDirect.js +6 -3
- package/background/src/lib/virtualized/project/executeLibraryFunctionDirect.js.map +1 -1
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +34 -9
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
- package/background/src/lib/virtualized/project/mocks/analyzeFileMock.js +7 -7
- package/background/src/lib/virtualized/project/mocks/analyzeFileMock.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/KyselyAnalysisLoader.js +12 -6
- package/background/src/lib/virtualized/project/orchestrateCapture/KyselyAnalysisLoader.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +73 -36
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js +76 -14
- package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +204 -2
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
- package/background/src/lib/virtualized/project/runAnalysis.js +9 -0
- package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +11 -9
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/background/src/lib/virtualized/project/serverOnlyModules.js +338 -0
- package/background/src/lib/virtualized/project/serverOnlyModules.js.map +1 -0
- package/background/src/lib/virtualized/project/start.js +62 -19
- package/background/src/lib/virtualized/project/start.js.map +1 -1
- package/background/src/lib/virtualized/project/startScenarioCapture.js +61 -31
- package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +404 -62
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js +15 -0
- package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js.map +1 -0
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +1112 -153
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioFiles.js +19 -0
- package/background/src/lib/virtualized/project/writeScenarioFiles.js.map +1 -1
- package/background/src/lib/virtualized/project/writeSimpleRoot.js +57 -20
- package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
- package/background/src/lib/virtualized/project/writeUniversalMocks.js +27 -12
- package/background/src/lib/virtualized/project/writeUniversalMocks.js.map +1 -1
- package/codeyam-cli/scripts/apply-setup.js +180 -0
- package/codeyam-cli/scripts/apply-setup.js.map +1 -1
- package/codeyam-cli/src/cli.js +38 -17
- package/codeyam-cli/src/cli.js.map +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 +5 -3
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/baseline.js +176 -0
- package/codeyam-cli/src/commands/baseline.js.map +1 -0
- package/codeyam-cli/src/commands/debug.js +44 -18
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +30 -34
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/detect-universal-mocks.js +2 -0
- package/codeyam-cli/src/commands/detect-universal-mocks.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +49 -257
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/commands/memory.js +254 -0
- package/codeyam-cli/src/commands/memory.js.map +1 -0
- package/codeyam-cli/src/commands/recapture.js +228 -0
- package/codeyam-cli/src/commands/recapture.js.map +1 -0
- package/codeyam-cli/src/commands/report.js +72 -24
- package/codeyam-cli/src/commands/report.js.map +1 -1
- package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
- package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
- package/codeyam-cli/src/commands/setup-simulations.js +284 -0
- package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
- package/codeyam-cli/src/commands/start.js +8 -12
- package/codeyam-cli/src/commands/start.js.map +1 -1
- package/codeyam-cli/src/commands/status.js +23 -1
- package/codeyam-cli/src/commands/status.js.map +1 -1
- package/codeyam-cli/src/commands/test-startup.js +3 -1
- package/codeyam-cli/src/commands/test-startup.js.map +1 -1
- package/codeyam-cli/src/commands/verify.js +14 -2
- package/codeyam-cli/src/commands/verify.js.map +1 -1
- package/codeyam-cli/src/commands/wipe.js +108 -0
- package/codeyam-cli/src/commands/wipe.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +185 -0
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js +81 -0
- package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -82
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/analysisRunner.js +29 -15
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/analyzer.js +7 -0
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/backgroundServer.js +104 -23
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/database.js +91 -5
- package/codeyam-cli/src/utils/database.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +253 -106
- package/codeyam-cli/src/utils/generateReport.js.map +1 -1
- package/codeyam-cli/src/utils/git.js +79 -0
- package/codeyam-cli/src/utils/git.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +76 -42
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
- package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
- package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
- package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
- package/codeyam-cli/src/utils/progress.js +7 -0
- package/codeyam-cli/src/utils/progress.js.map +1 -1
- package/codeyam-cli/src/utils/queue/__tests__/manager.test.js +38 -0
- package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +249 -16
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/queue/manager.js +103 -7
- package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
- package/codeyam-cli/src/utils/queue/persistence.js.map +1 -1
- package/codeyam-cli/src/utils/requireSimulations.js +10 -0
- package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +230 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +74 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +376 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +116 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
- package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
- package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
- package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
- package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
- package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js +84 -0
- package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +83 -0
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/index.js +7 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -0
- package/codeyam-cli/src/utils/rules/parser.js +83 -0
- package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js +28 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
- package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
- package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
- package/codeyam-cli/src/utils/rules/sourceFiles.js +47 -0
- package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +137 -0
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
- 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 +21 -42
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js +138 -0
- package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -0
- package/codeyam-cli/src/utils/syncMocksMiddleware.js +5 -24
- package/codeyam-cli/src/utils/syncMocksMiddleware.js.map +1 -1
- package/codeyam-cli/src/utils/versionInfo.js +67 -15
- package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
- package/codeyam-cli/src/utils/wipe.js +128 -0
- package/codeyam-cli/src/utils/wipe.js.map +1 -0
- 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/database.js +118 -6
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
- package/codeyam-cli/src/webserver/backgroundServer.js +55 -10
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +60 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-jNYXRRNI.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-bwuHPyTa.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-kykTbcnD.js → EntityTypeBadge-CvzqMxcu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-BH0XDim7.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-EhOseatT.js +34 -0
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-yjIHlOGa.js +25 -0
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-Cq5o8jL4.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/LoadingDots-BvMu2i-g.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-kgBTLoJD.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-BzPgx-xO.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-CwZrv-Ok.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-BX2Ny2Qj.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-C06nsHKY.js → TruncatedFilePath-CDpEprKa.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-BRx8ZGZo.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-4S4yPfFw.js +27 -0
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +17 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/book-open-D4IPYH_y.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-CG65viiV.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-DB3aFuEO.js +51 -0
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-igfMr5DY.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/copy-Coc4o_8c.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-D1zB-pYc.js +21 -0
- package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-C1gnJVOL.svg → cy-logo-cli-CCKUIm0S.svg} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-JTAjQ54M.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CYqBrC9s.js → entity._sha._-B0h9AqE6.js} +22 -15
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-CtYowLOt.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-PePWg17F.js +5 -0
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-I-Wo99C_.js +29 -0
- package/codeyam-cli/src/webserver/build/client/assets/executionFlowCoverage-BWhdfn70.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-9sMMAiWJ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/files-Co65J0s3.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/git-BdHOxVfg.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-Dzl-jeq-.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-fmIEn3Bc.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-CUM5iXwc.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-_417gcQW.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/labs-DAvt-sy-.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-TzRHMVog.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-2d0e2ebb.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-DVGtTawo.js +92 -0
- package/codeyam-cli/src/webserver/build/client/assets/pause-hjzB7t2z.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/preload-helper-ckwbz45p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-Bg3WICdl.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/scenarioStatus-B_8jpV3e.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/search-DcAwD_Ln.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/settings-CclxrcPK.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/simulations-DVNJVQgD.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/terminal-DbEAHMbA.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-CAD5b1o_.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BqgrAzs3.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-Blr5oZDE.js → useLastLogLine-DAFqfEDH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-DZlYx2c4.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bbf4Hokd.js → useToast-ihdMtlf6.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-CpreP2n8.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DyvoFrHR.js +273 -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/src/webserver/devServer.js +1 -3
- package/codeyam-cli/src/webserver/devServer.js.map +1 -1
- package/codeyam-cli/src/webserver/server.js +35 -25
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/templates/{codeyam-debug-skill.md → codeyam-debug.md} +48 -4
- package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
- package/codeyam-cli/templates/codeyam-memory-hook.sh +199 -0
- package/codeyam-cli/templates/codeyam-memory.md +396 -0
- package/codeyam-cli/templates/codeyam-new-rule.md +13 -0
- package/codeyam-cli/templates/{codeyam-setup-skill.md → codeyam-setup.md} +151 -4
- package/codeyam-cli/templates/{codeyam-sim-skill.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam-test-skill.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam-verify-skill.md → codeyam-verify.md} +1 -1
- package/codeyam-cli/templates/rule-notification-hook.py +56 -0
- package/codeyam-cli/templates/rule-reflection-hook.py +627 -0
- package/codeyam-cli/templates/rules-instructions.md +132 -0
- package/package.json +26 -23
- package/packages/ai/index.js +8 -6
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +181 -13
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +154 -9
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js +435 -0
- package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js.map +1 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js +138 -23
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
- package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.js +8 -0
- package/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js +23 -0
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +138 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +1235 -104
- 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/checkAllAttributes.js +24 -9
- package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
- package/packages/ai/src/lib/completionCall.js +178 -31
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +2171 -224
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +19 -4
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +661 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +180 -56
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +66 -2
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +139 -13
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
- package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +142 -12
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js +86 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +173 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +371 -73
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructureChunking.js +130 -0
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
- package/packages/ai/src/lib/deepEqual.js +32 -0
- package/packages/ai/src/lib/deepEqual.js.map +1 -0
- package/packages/ai/src/lib/e2eDataTracking.js +241 -0
- package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js +62 -5
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarios.js +81 -90
- package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js +50 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +1127 -91
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +193 -83
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +495 -0
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js +380 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +1807 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js +84 -14
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js +2 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js.map +1 -1
- package/packages/ai/src/lib/isolateScopes.js +270 -7
- package/packages/ai/src/lib/isolateScopes.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/mergeStatements.js +88 -46
- package/packages/ai/src/lib/mergeStatements.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/gatherAttributesMap.js +16 -4
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +21 -64
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +83 -6
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +10 -34
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js +45 -0
- package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js +16 -3
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
- package/packages/ai/src/lib/resolvePathToControllable.js +677 -0
- package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -0
- package/packages/ai/src/lib/splitOutsideParentheses.js +3 -1
- package/packages/ai/src/lib/splitOutsideParentheses.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js +29 -0
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js +98 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
- package/packages/analyze/index.js +1 -0
- package/packages/analyze/index.js.map +1 -1
- package/packages/analyze/src/lib/FileAnalyzer.js +75 -36
- package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
- package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/analysisContext.js +30 -5
- package/packages/analyze/src/lib/analysisContext.js.map +1 -1
- package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
- package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
- package/packages/analyze/src/lib/asts/nodes/index.js +1 -0
- package/packages/analyze/src/lib/asts/nodes/index.js.map +1 -1
- package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js +52 -0
- package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js.map +1 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +428 -123
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +42 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js +2 -0
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeChange.js +21 -11
- package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeEntity.js +9 -8
- package/packages/analyze/src/lib/files/analyzeEntity.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeInitial.js +9 -10
- package/packages/analyze/src/lib/files/analyzeInitial.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/enums/steps.js +1 -1
- package/packages/analyze/src/lib/files/enums/steps.js.map +1 -1
- package/packages/analyze/src/lib/files/getImportedExports.js +17 -8
- package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js +880 -0
- package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +255 -0
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js +85 -0
- package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +550 -62
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js +29 -34
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +404 -85
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +144 -0
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +56 -69
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +4 -8
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +875 -141
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
- package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/index.js +1 -0
- package/packages/analyze/src/lib/index.js.map +1 -1
- package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
- package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
- package/packages/aws/src/lib/ecs/ecsDefineContainer.js +2 -2
- package/packages/aws/src/lib/ecs/ecsDefineContainer.js.map +1 -1
- package/packages/aws/src/lib/ecs/ecsTaskFactory.js +17 -61
- package/packages/aws/src/lib/ecs/ecsTaskFactory.js.map +1 -1
- package/packages/database/src/lib/analysisBranchToDb.js +1 -1
- package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
- package/packages/database/src/lib/analysisToDb.js +1 -1
- package/packages/database/src/lib/analysisToDb.js.map +1 -1
- package/packages/database/src/lib/branchToDb.js +1 -1
- package/packages/database/src/lib/branchToDb.js.map +1 -1
- package/packages/database/src/lib/commitBranchToDb.js +1 -1
- package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
- package/packages/database/src/lib/commitToDb.js +1 -1
- package/packages/database/src/lib/commitToDb.js.map +1 -1
- package/packages/database/src/lib/fileToDb.js +1 -1
- package/packages/database/src/lib/fileToDb.js.map +1 -1
- package/packages/database/src/lib/kysely/db.js +13 -3
- package/packages/database/src/lib/kysely/db.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
- package/packages/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
- package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
- package/packages/database/src/lib/loadAnalyses.js +45 -2
- package/packages/database/src/lib/loadAnalyses.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +8 -0
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/packages/database/src/lib/loadBranch.js +11 -1
- package/packages/database/src/lib/loadBranch.js.map +1 -1
- package/packages/database/src/lib/loadCommit.js +7 -0
- package/packages/database/src/lib/loadCommit.js.map +1 -1
- package/packages/database/src/lib/loadCommits.js +22 -1
- package/packages/database/src/lib/loadCommits.js.map +1 -1
- package/packages/database/src/lib/loadEntities.js +23 -4
- package/packages/database/src/lib/loadEntities.js.map +1 -1
- package/packages/database/src/lib/loadEntityBranches.js +9 -0
- package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
- package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js +23 -5
- package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
- package/packages/database/src/lib/projectToDb.js +1 -1
- package/packages/database/src/lib/projectToDb.js.map +1 -1
- package/packages/database/src/lib/saveFiles.js +1 -1
- package/packages/database/src/lib/saveFiles.js.map +1 -1
- package/packages/database/src/lib/scenarioToDb.js +1 -1
- package/packages/database/src/lib/scenarioToDb.js.map +1 -1
- package/packages/database/src/lib/updateCommitMetadata.js +5 -4
- package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/packages/generate/index.js +3 -0
- package/packages/generate/index.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/packages/generate/src/lib/deepMerge.js +27 -1
- package/packages/generate/src/lib/deepMerge.js.map +1 -1
- package/packages/generate/src/lib/directExecutionScript.js +10 -1
- package/packages/generate/src/lib/directExecutionScript.js.map +1 -1
- package/packages/generate/src/lib/getComponentScenarioPath.js +7 -3
- package/packages/generate/src/lib/getComponentScenarioPath.js.map +1 -1
- package/packages/generate/src/lib/scenarioComponentForServer.js +89 -0
- package/packages/generate/src/lib/scenarioComponentForServer.js.map +1 -0
- package/packages/github/src/lib/loadOrCreateCommit.js +10 -0
- package/packages/github/src/lib/loadOrCreateCommit.js.map +1 -1
- package/packages/github/src/lib/syncPrimaryBranch.js +3 -0
- package/packages/github/src/lib/syncPrimaryBranch.js.map +1 -1
- package/packages/process/index.js +3 -0
- package/packages/process/index.js.map +1 -0
- package/packages/process/src/GlobalProcessManager.js.map +1 -0
- package/{background/src/lib/process → packages/process/src}/ProcessManager.js +1 -1
- package/packages/process/src/ProcessManager.js.map +1 -0
- package/packages/process/src/index.js.map +1 -0
- package/packages/process/src/managedExecAsync.js.map +1 -0
- package/packages/types/index.js.map +1 -1
- package/packages/utils/src/lib/applyUniversalMocks.js +26 -2
- package/packages/utils/src/lib/applyUniversalMocks.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +98 -3
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/packages/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/packages/utils/src/lib/lightweightEntityExtractor.js.map +1 -1
- package/packages/utils/src/lib/safeFileName.js +29 -3
- package/packages/utils/src/lib/safeFileName.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +8 -74
- package/analyzer-template/packages/ai/src/lib/findMatchingAttribute.ts +0 -102
- package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +0 -197
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityKeyAttributes.ts +0 -271
- package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +0 -294
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.ts +0 -67
- package/analyzer-template/packages/ai/src/lib/transformMockDataToMatchSchema.ts +0 -156
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +0 -115
- package/analyzer-template/process/INTEGRATION_COMPLETE.md +0 -333
- package/analyzer-template/process/INTEGRATION_EXAMPLE.md +0 -525
- package/analyzer-template/process/README.md +0 -507
- package/background/src/lib/process/GlobalProcessManager.js.map +0 -1
- package/background/src/lib/process/ProcessManager.js.map +0 -1
- package/background/src/lib/process/index.js.map +0 -1
- package/background/src/lib/process/managedExecAsync.js.map +0 -1
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js +0 -238
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js.map +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-D4htqD-x.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-Catz6XEN.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-TlHocYno.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-CVMmGuIc.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-JkfQ-VaI.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-CVZ0H4BL.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BrMAP1nP.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-CJhE4cCv.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/_index-faVIcr_i.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CLMa2sgx.js +0 -7
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-DwYjrK_h.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-CgXbbZRx.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-B2oHQ-zo.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-BBYuR56H.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-CT0Q5lVu.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-Bj5GHkhb.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-eW5z9AyZ.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-B9tSboXM.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-CmO-EZAB.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-DLinnTOx.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-CIxwBQvb.js +0 -12
- package/codeyam-cli/src/webserver/build/client/assets/globals-xPz593l2.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/index-_LjBsTxX.js +0 -8
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-D_EGChhq.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-ca438c41.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-CHHYHuzL.js +0 -16
- package/codeyam-cli/src/webserver/build/client/assets/search-DY8yoDpH.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/server-build-CMKNK2uU.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-BT6wVHd5.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/simulations-gv3H7JV7.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-BthANBVv.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-CANr3QJ5.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-BtBPtyHx.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-N2cTnejq.js +0 -166
- package/codeyam-cli/templates/debug-command.md +0 -141
- package/packages/ai/src/lib/findMatchingAttribute.js +0 -77
- package/packages/ai/src/lib/findMatchingAttribute.js.map +0 -1
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +0 -136
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js +0 -220
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/generateEntityKeyAttributes.js +0 -241
- package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/isFrontend.js +0 -5
- package/packages/ai/src/lib/isFrontend.js.map +0 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js +0 -40
- package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js.map +0 -1
- package/packages/ai/src/lib/transformMockDataToMatchSchema.js +0 -124
- package/packages/ai/src/lib/transformMockDataToMatchSchema.js.map +0 -1
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +0 -72
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +0 -1
- /package/analyzer-template/{process → packages/process/src}/GlobalProcessManager.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/ProcessManager.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/index.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/managedExecAsync.ts +0 -0
- /package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CMKNK2uU.css → styles-CMKNK2uU.css} +0 -0
- /package/{background/src/lib/process → packages/process/src}/GlobalProcessManager.js +0 -0
- /package/{background/src/lib/process → packages/process/src}/index.js +0 -0
- /package/{background/src/lib/process → packages/process/src}/managedExecAsync.js +0 -0
|
@@ -0,0 +1,2484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates execution flows from conditional usages using pure static analysis.
|
|
3
|
+
*
|
|
4
|
+
* This replaces LLM-driven flow generation with deterministic flow generation
|
|
5
|
+
* based on conditionalUsages extracted from the AST. Only paths that resolve
|
|
6
|
+
* to controllable data sources (exist in attributesMap) produce flows.
|
|
7
|
+
*
|
|
8
|
+
* Flow generation rules:
|
|
9
|
+
* - truthiness conditions → truthy flow + falsy flow
|
|
10
|
+
* - comparison conditions → one flow per compared value
|
|
11
|
+
* - switch conditions → one flow per case value
|
|
12
|
+
* - compound conditionals → one flow with all conditions (only if ALL paths controllable)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { ExecutionFlow } from '~codeyam/types';
|
|
16
|
+
import type {
|
|
17
|
+
ConditionalUsage,
|
|
18
|
+
CompoundConditional,
|
|
19
|
+
DerivedVariableOperation,
|
|
20
|
+
DerivedVariableInfo,
|
|
21
|
+
JsxRenderingUsage,
|
|
22
|
+
} from './astScopes/types';
|
|
23
|
+
import type { EnrichedConditionalUsage } from './worker/SerializableDataStructure';
|
|
24
|
+
import resolvePathToControllable from './resolvePathToControllable';
|
|
25
|
+
import cleanPathOfNonTransformingFunctions from './dataStructure/helpers/cleanPathOfNonTransformingFunctions';
|
|
26
|
+
|
|
27
|
+
/** Extended conditional usage type that may include sourceDataPath from enrichment */
|
|
28
|
+
type ExtendedConditionalUsage = ConditionalUsage &
|
|
29
|
+
Partial<EnrichedConditionalUsage>;
|
|
30
|
+
|
|
31
|
+
/** Child component conditional data for merging child flows into parent */
|
|
32
|
+
export interface ChildComponentConditionalData {
|
|
33
|
+
/** Child's conditional usages keyed by variable name (may include sourceDataPath from enrichment) */
|
|
34
|
+
conditionalUsages: Record<string, ExtendedConditionalUsage[]>;
|
|
35
|
+
/** Child's equivalent signature variables (maps internal paths to prop paths) */
|
|
36
|
+
equivalentSignatureVariables: Record<string, string | string[]>;
|
|
37
|
+
/** Child's compound conditionals */
|
|
38
|
+
compoundConditionals: CompoundConditional[];
|
|
39
|
+
/**
|
|
40
|
+
* Gating conditions - the parent's conditions required to render this child component.
|
|
41
|
+
* For example, if the parent has `{hasAnalysis && <ChildComponent />}`,
|
|
42
|
+
* then `hasAnalysis` is a gating condition for all of ChildComponent's flows.
|
|
43
|
+
*/
|
|
44
|
+
gatingConditions?: ConditionalUsage[];
|
|
45
|
+
/**
|
|
46
|
+
* Child's JSX rendering usages (arrays rendered via .map(), text interpolation).
|
|
47
|
+
* These generate "variation flows" for different array lengths.
|
|
48
|
+
*/
|
|
49
|
+
jsxRenderingUsages?: JsxRenderingUsage[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface GenerateFlowsFromConditionalsArgs {
|
|
53
|
+
/** Record of attribute paths to their conditional usages (may include sourceDataPath) */
|
|
54
|
+
conditionalUsages: Record<string, ExtendedConditionalUsage[]>;
|
|
55
|
+
/** Compound conditionals (&&-chained conditions) */
|
|
56
|
+
compoundConditionals: CompoundConditional[];
|
|
57
|
+
/** Map of controllable paths to their types */
|
|
58
|
+
attributesMap: Record<string, string>;
|
|
59
|
+
/** Map from local variable names to data sources */
|
|
60
|
+
equivalentSignatureVariables: Record<string, string | string[]>;
|
|
61
|
+
/** Map from full paths to short paths */
|
|
62
|
+
fullToShortPathMap: Record<string, string>;
|
|
63
|
+
/**
|
|
64
|
+
* Optional child component conditional data.
|
|
65
|
+
* Maps child component name to its conditional data.
|
|
66
|
+
* Used to merge child execution flows into parent.
|
|
67
|
+
*/
|
|
68
|
+
childComponentData?: Record<string, ChildComponentConditionalData>;
|
|
69
|
+
/**
|
|
70
|
+
* Optional map of derived variables to their derivation info.
|
|
71
|
+
* Used to trace intermediate derived variables that aren't directly
|
|
72
|
+
* used in conditionals but are sources for other derived variables.
|
|
73
|
+
*
|
|
74
|
+
* Example:
|
|
75
|
+
* - `isInCurrentRun = currentRun.entityShas.includes(sha)` → { sourcePath: 'currentRun.entityShas', operation: 'arrayIncludes' }
|
|
76
|
+
* - `isAnalyzing = isInCurrentRun || isInQueue` → { sourcePaths: ['isInCurrentRun', 'isInQueue'], operation: 'or' }
|
|
77
|
+
*
|
|
78
|
+
* Without this map, we can't trace from `isAnalyzing` through `isInCurrentRun`
|
|
79
|
+
* to `currentRun.entityShas` when `isInCurrentRun` isn't in conditionalUsages.
|
|
80
|
+
*/
|
|
81
|
+
derivedVariables?: Record<string, DerivedVariableInfo>;
|
|
82
|
+
/**
|
|
83
|
+
* Optional map of child prop paths to their actual data sources.
|
|
84
|
+
* Used when child props flow through useState but ultimately come from
|
|
85
|
+
* mockable data sources (e.g., API calls, fetchers).
|
|
86
|
+
*
|
|
87
|
+
* Example:
|
|
88
|
+
* - "WorkoutsView().signature[0].workouts" → "createClient()...functionCallReturnValue.data"
|
|
89
|
+
*
|
|
90
|
+
* When a child path translates to a useState value, we check this map
|
|
91
|
+
* to find the real data source that can be mocked.
|
|
92
|
+
*/
|
|
93
|
+
sourceEquivalencies?: Record<
|
|
94
|
+
string,
|
|
95
|
+
Array<{ scopeNodeName: string; schemaPath: string }>
|
|
96
|
+
>;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Resolved source info from expanding a derived variable.
|
|
101
|
+
* Contains the path and the operation that led to it.
|
|
102
|
+
*/
|
|
103
|
+
interface ResolvedSourceInfo {
|
|
104
|
+
path: string;
|
|
105
|
+
operation?:
|
|
106
|
+
| 'notNull'
|
|
107
|
+
| 'isNull'
|
|
108
|
+
| 'equals'
|
|
109
|
+
| 'notEquals'
|
|
110
|
+
| 'or'
|
|
111
|
+
| 'and'
|
|
112
|
+
| 'arrayIncludes'
|
|
113
|
+
| 'arraySome'
|
|
114
|
+
| 'arrayEvery'
|
|
115
|
+
| 'arrayLength';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Recursively expands a derived variable to its leaf data sources.
|
|
120
|
+
*
|
|
121
|
+
* For OR expressions like `isAnalyzing = a || b || c`:
|
|
122
|
+
* - Returns all source paths [a, b, c] so they can all be set appropriately
|
|
123
|
+
*
|
|
124
|
+
* For nested derivations like `isAnalyzing = isInCurrentRun || isInQueue`:
|
|
125
|
+
* - Where `isInCurrentRun` is derived from `currentRun.entityShas.includes(x)`
|
|
126
|
+
* - Returns the final data sources: [currentRun.entityShas, queueState.jobs]
|
|
127
|
+
*
|
|
128
|
+
* @param path The variable path to expand
|
|
129
|
+
* @param conditionalUsages All conditional usages (to look up derivedFrom info)
|
|
130
|
+
* @param attributesMap Map of controllable paths
|
|
131
|
+
* @param equivalentSignatureVariables Variable-to-path mappings
|
|
132
|
+
* @param fullToShortPathMap Full-to-short path mappings
|
|
133
|
+
* @param visited Set of already-visited paths (prevents infinite recursion)
|
|
134
|
+
* @param derivedVariables Optional map of all derived variables (for intermediate tracing)
|
|
135
|
+
* @returns Array of resolved source paths that are controllable
|
|
136
|
+
*/
|
|
137
|
+
function expandDerivedVariableToSources(
|
|
138
|
+
path: string,
|
|
139
|
+
conditionalUsages: Record<string, ConditionalUsage[]>,
|
|
140
|
+
attributesMap: Record<string, string>,
|
|
141
|
+
equivalentSignatureVariables: Record<string, string | string[]>,
|
|
142
|
+
fullToShortPathMap: Record<string, string>,
|
|
143
|
+
visited: Set<string> = new Set(),
|
|
144
|
+
derivedVariables?: Record<string, DerivedVariableInfo>,
|
|
145
|
+
): ResolvedSourceInfo[] {
|
|
146
|
+
// Prevent infinite recursion
|
|
147
|
+
if (visited.has(path)) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
visited.add(path);
|
|
151
|
+
|
|
152
|
+
// First, check if this path is directly controllable
|
|
153
|
+
const directResolution = resolvePathToControllable(
|
|
154
|
+
path,
|
|
155
|
+
attributesMap,
|
|
156
|
+
equivalentSignatureVariables,
|
|
157
|
+
fullToShortPathMap,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
if (directResolution.isControllable && directResolution.resolvedPath) {
|
|
161
|
+
return [{ path: directResolution.resolvedPath }];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Look up derivedFrom info for this path
|
|
165
|
+
// First check conditionalUsages, then fall back to derivedVariables
|
|
166
|
+
const usage = conditionalUsages[path]?.[0];
|
|
167
|
+
let derivedFrom = usage?.derivedFrom;
|
|
168
|
+
|
|
169
|
+
// CRITICAL: If not found in conditionalUsages, check derivedVariables
|
|
170
|
+
// This handles intermediate derived variables like `isInCurrentRun` that aren't
|
|
171
|
+
// directly used in conditionals but ARE derived from data sources
|
|
172
|
+
if (!derivedFrom && derivedVariables?.[path]) {
|
|
173
|
+
derivedFrom = derivedVariables[path];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!derivedFrom) {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const { operation, sourcePath, sourcePaths } = derivedFrom;
|
|
181
|
+
|
|
182
|
+
// For OR/AND operations, recursively expand all source paths
|
|
183
|
+
if ((operation === 'or' || operation === 'and') && sourcePaths) {
|
|
184
|
+
const allSources: ResolvedSourceInfo[] = [];
|
|
185
|
+
|
|
186
|
+
for (const sp of sourcePaths) {
|
|
187
|
+
const expanded = expandDerivedVariableToSources(
|
|
188
|
+
sp,
|
|
189
|
+
conditionalUsages,
|
|
190
|
+
attributesMap,
|
|
191
|
+
equivalentSignatureVariables,
|
|
192
|
+
fullToShortPathMap,
|
|
193
|
+
visited,
|
|
194
|
+
derivedVariables,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Add all expanded sources
|
|
198
|
+
for (const source of expanded) {
|
|
199
|
+
// Avoid duplicates
|
|
200
|
+
if (!allSources.some((s) => s.path === source.path)) {
|
|
201
|
+
allSources.push(source);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return allSources;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// For single-source operations (arrayIncludes, arraySome, notNull, etc.)
|
|
210
|
+
if (sourcePath) {
|
|
211
|
+
// Try to resolve the source path directly
|
|
212
|
+
const sourceResolution = resolvePathToControllable(
|
|
213
|
+
sourcePath,
|
|
214
|
+
attributesMap,
|
|
215
|
+
equivalentSignatureVariables,
|
|
216
|
+
fullToShortPathMap,
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
if (sourceResolution.isControllable && sourceResolution.resolvedPath) {
|
|
220
|
+
return [{ path: sourceResolution.resolvedPath, operation }];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// If not directly resolvable, recursively expand
|
|
224
|
+
return expandDerivedVariableToSources(
|
|
225
|
+
sourcePath,
|
|
226
|
+
conditionalUsages,
|
|
227
|
+
attributesMap,
|
|
228
|
+
equivalentSignatureVariables,
|
|
229
|
+
fullToShortPathMap,
|
|
230
|
+
visited,
|
|
231
|
+
derivedVariables,
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Clean up sourceDataPath by removing redundant scope prefixes.
|
|
240
|
+
*
|
|
241
|
+
* This function ONLY handles the specific pattern where a scope name is
|
|
242
|
+
* duplicated before the hook call:
|
|
243
|
+
*
|
|
244
|
+
* Example:
|
|
245
|
+
* "useLoaderData<LoaderData>.useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
|
|
246
|
+
* → "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
|
|
247
|
+
*
|
|
248
|
+
* For paths with multiple function calls (like fetch().json()), or paths
|
|
249
|
+
* that don't match the expected pattern, returns null to indicate the
|
|
250
|
+
* fallback resolution should be used.
|
|
251
|
+
*/
|
|
252
|
+
function cleanSourceDataPath(sourceDataPath: string): string | null {
|
|
253
|
+
// Count function call patterns - both empty () and with content (...)
|
|
254
|
+
// We detect multiple function calls by counting:
|
|
255
|
+
// 1. Empty () patterns
|
|
256
|
+
// 2. Patterns like functionName(...) - closing paren followed by dot or end
|
|
257
|
+
const emptyFnCalls = (sourceDataPath.match(/\(\)/g) || []).length;
|
|
258
|
+
const fnCallReturnValues = (
|
|
259
|
+
sourceDataPath.match(/\.functionCallReturnValue/g) || []
|
|
260
|
+
).length;
|
|
261
|
+
|
|
262
|
+
// For chained function calls (e.g., fetch().json()) or paths with non-standard
|
|
263
|
+
// fn call patterns, return the original path so findInAttributesMapForPath can
|
|
264
|
+
// try to look it up in fullToShortPathMap. If it doesn't match, the caller
|
|
265
|
+
// falls through to fallback resolution anyway.
|
|
266
|
+
if (fnCallReturnValues > 1 || emptyFnCalls !== 1) {
|
|
267
|
+
console.log(
|
|
268
|
+
`[cleanSourceDataPath] chained/non-standard path (fnCallRVs=${fnCallReturnValues}, emptyFnCalls=${emptyFnCalls}), returning original: "${sourceDataPath}"`,
|
|
269
|
+
);
|
|
270
|
+
return sourceDataPath;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Find the "()" which marks the function call
|
|
274
|
+
const fnCallIndex = sourceDataPath.indexOf('()');
|
|
275
|
+
|
|
276
|
+
// Find where the function name starts (go back to find the start of this segment)
|
|
277
|
+
const beforeFnCall = sourceDataPath.slice(0, fnCallIndex);
|
|
278
|
+
const lastDotBeforeFn = beforeFnCall.lastIndexOf('.');
|
|
279
|
+
|
|
280
|
+
if (lastDotBeforeFn === -1) {
|
|
281
|
+
return sourceDataPath;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Extract the scope prefix and the actual path
|
|
285
|
+
const scopePrefix = sourceDataPath.slice(0, lastDotBeforeFn);
|
|
286
|
+
const actualPath = sourceDataPath.slice(lastDotBeforeFn + 1);
|
|
287
|
+
|
|
288
|
+
// Verify this is actually a redundant scope prefix pattern
|
|
289
|
+
// The actualPath should start with something that matches the scopePrefix
|
|
290
|
+
// e.g., scopePrefix="useLoaderData<LoaderData>" and actualPath starts with "useLoaderData<LoaderData>()..."
|
|
291
|
+
if (!actualPath.startsWith(scopePrefix.split('.').pop() || '')) {
|
|
292
|
+
// Not a redundant prefix pattern - return the original path
|
|
293
|
+
return sourceDataPath;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return actualPath;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Strip .length suffix from a path if present.
|
|
301
|
+
*
|
|
302
|
+
* When we have a path like "items.length", the controllable attribute is "items"
|
|
303
|
+
* (the array), not "items.length". The length is derived from the array contents.
|
|
304
|
+
*
|
|
305
|
+
* This ensures that execution flows reference the actual controllable attribute
|
|
306
|
+
* rather than the derived .length property.
|
|
307
|
+
*/
|
|
308
|
+
function stripLengthSuffix(path: string): string {
|
|
309
|
+
if (path.endsWith('.length')) {
|
|
310
|
+
return path.slice(0, -7); // Remove ".length" (7 characters)
|
|
311
|
+
}
|
|
312
|
+
return path;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Remove contradictory required values from a compound flow.
|
|
317
|
+
*
|
|
318
|
+
* When a lifecycle boolean (like isLoadingAuditData) is traced to a fetch call's
|
|
319
|
+
* return value, a negated condition (!isLoadingAuditData) produces "falsy" on
|
|
320
|
+
* the fetch path. But if another condition in the same compound requires data
|
|
321
|
+
* from a sub-path of that fetch (e.g., topPaths length > 0), the "falsy" on the
|
|
322
|
+
* parent path contradicts it — a null/falsy response has no .json() to call.
|
|
323
|
+
*
|
|
324
|
+
* This function removes "falsy" required values whose attributePath is a prefix
|
|
325
|
+
* of another required value's attributePath. The child data requirement already
|
|
326
|
+
* implies the parent (fetch) succeeded.
|
|
327
|
+
*/
|
|
328
|
+
function removeContradictoryFalsyValues(
|
|
329
|
+
requiredValues: ExecutionFlow['requiredValues'],
|
|
330
|
+
): ExecutionFlow['requiredValues'] {
|
|
331
|
+
return requiredValues.filter((rv) => {
|
|
332
|
+
if (rv.comparison === 'falsy') {
|
|
333
|
+
const hasChildRequirement = requiredValues.some(
|
|
334
|
+
(other) =>
|
|
335
|
+
other !== rv &&
|
|
336
|
+
other.attributePath.startsWith(rv.attributePath + '.'),
|
|
337
|
+
);
|
|
338
|
+
if (hasChildRequirement) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return true;
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Generate a human-readable description snippet for a required value,
|
|
348
|
+
* incorporating the comparison type so the LLM understands the intent.
|
|
349
|
+
*/
|
|
350
|
+
function describeRequiredValue(rv: ExecutionFlow['requiredValues'][0]): string {
|
|
351
|
+
const name = generateNameFromPath(rv.attributePath).toLowerCase();
|
|
352
|
+
switch (rv.comparison) {
|
|
353
|
+
case 'truthy':
|
|
354
|
+
return `${name} is present`;
|
|
355
|
+
case 'falsy':
|
|
356
|
+
return `${name} is absent`;
|
|
357
|
+
case 'length>':
|
|
358
|
+
return rv.value === '0'
|
|
359
|
+
? `${name} has items`
|
|
360
|
+
: `${name} has more than ${rv.value} items`;
|
|
361
|
+
case 'length<':
|
|
362
|
+
return `${name} has fewer than ${rv.value} items`;
|
|
363
|
+
case 'equals':
|
|
364
|
+
return `${name} is ${rv.value}`;
|
|
365
|
+
case 'exists':
|
|
366
|
+
return `${name} exists`;
|
|
367
|
+
case 'not-exists':
|
|
368
|
+
return `${name} does not exist`;
|
|
369
|
+
default:
|
|
370
|
+
return `${name} is ${rv.value}`;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Check whether a resolved path has child entries in the fullToShortPathMap.
|
|
376
|
+
*
|
|
377
|
+
* When a lifecycle boolean (e.g., isLoadingAuditData) resolves to a parent path
|
|
378
|
+
* like fetch(...).functionCallReturnValue, and that path has children (like
|
|
379
|
+
* .json().functionCallReturnValue.topPaths), individual truthy/falsy flows on
|
|
380
|
+
* the parent are misleading. Compound flows with specific child requirements
|
|
381
|
+
* provide better guidance for mock data generation.
|
|
382
|
+
*/
|
|
383
|
+
function hasChildPathsInMap(
|
|
384
|
+
resolvedPath: string,
|
|
385
|
+
fullToShortPathMap: Record<string, string>,
|
|
386
|
+
): boolean {
|
|
387
|
+
return Object.keys(fullToShortPathMap).some(
|
|
388
|
+
(fullPath) =>
|
|
389
|
+
fullPath.startsWith(resolvedPath + '.') ||
|
|
390
|
+
fullPath.startsWith(resolvedPath + '['),
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Extract the controllable base path from a path that may contain method calls.
|
|
396
|
+
*
|
|
397
|
+
* This handles complex expressions like:
|
|
398
|
+
* - `scenarios.filter((s) => s.active).length` → `scenarios`
|
|
399
|
+
* - `users.some((u) => u.role === 'admin')` → `users`
|
|
400
|
+
* - `items.map(x => x.name).join(', ')` → `items`
|
|
401
|
+
*
|
|
402
|
+
* The controllable base is the path that can be mocked - we can control
|
|
403
|
+
* what `scenarios` contains, but we can't control what `.filter()` returns.
|
|
404
|
+
*
|
|
405
|
+
* @param path - The path that may contain method calls
|
|
406
|
+
* @returns The controllable base path with method calls stripped
|
|
407
|
+
*/
|
|
408
|
+
function extractControllableBase(path: string): string {
|
|
409
|
+
// First strip .length suffix if present
|
|
410
|
+
const pathWithoutLength = stripLengthSuffix(path);
|
|
411
|
+
|
|
412
|
+
// Use cleanPathOfNonTransformingFunctions to strip method calls like .filter(), .some()
|
|
413
|
+
const cleanedPath = cleanPathOfNonTransformingFunctions(pathWithoutLength);
|
|
414
|
+
|
|
415
|
+
// If the cleaned path is different, return it
|
|
416
|
+
if (cleanedPath !== pathWithoutLength) {
|
|
417
|
+
return cleanedPath;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Otherwise, return the path with just .length stripped
|
|
421
|
+
return pathWithoutLength;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Find a path in attributesMap, using fullToShortPathMap to verify the path is controllable.
|
|
426
|
+
*
|
|
427
|
+
* IMPORTANT: Returns the FULL path (preserving data source context) when possible.
|
|
428
|
+
* This ensures execution flows can be traced back to specific data sources,
|
|
429
|
+
* which is critical when multiple data sources have the same property names
|
|
430
|
+
* (e.g., multiple useFetcher hooks all having 'state' and 'data').
|
|
431
|
+
*
|
|
432
|
+
* The attributesMap contains short relative paths (e.g., "entity.sha")
|
|
433
|
+
* The sourceDataPath contains full paths (e.g., "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha")
|
|
434
|
+
* The fullToShortPathMap maps full paths to short paths
|
|
435
|
+
*/
|
|
436
|
+
export function findInAttributesMapForPath(
|
|
437
|
+
path: string,
|
|
438
|
+
attributesMap: Record<string, string>,
|
|
439
|
+
fullToShortPathMap: Record<string, string>,
|
|
440
|
+
): string | null {
|
|
441
|
+
// Direct match in attributesMap (already a short path)
|
|
442
|
+
if (path in attributesMap) {
|
|
443
|
+
console.log(
|
|
444
|
+
`[findInAttributesMapForPath] "${path}" → DIRECT match in attributesMap`,
|
|
445
|
+
);
|
|
446
|
+
return path;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Try looking up the path in fullToShortPathMap to verify it's controllable
|
|
450
|
+
// IMPORTANT: Return the FULL path, not the short path, to preserve data source context
|
|
451
|
+
if (path in fullToShortPathMap) {
|
|
452
|
+
const shortPath = fullToShortPathMap[path];
|
|
453
|
+
if (shortPath in attributesMap) {
|
|
454
|
+
console.log(
|
|
455
|
+
`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match: shortPath="${shortPath}" found in attributesMap`,
|
|
456
|
+
);
|
|
457
|
+
return path; // Return FULL path to preserve data source context
|
|
458
|
+
}
|
|
459
|
+
console.log(
|
|
460
|
+
`[findInAttributesMapForPath] "${path}" → fullToShortPathMap match shortPath="${shortPath}" but NOT in attributesMap`,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// Normalized match (array indices [N] → [])
|
|
465
|
+
const normalizedPath = path.replace(/\[\d+\]/g, '[]');
|
|
466
|
+
if (normalizedPath !== path) {
|
|
467
|
+
if (normalizedPath in attributesMap) {
|
|
468
|
+
console.log(
|
|
469
|
+
`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" DIRECT match in attributesMap`,
|
|
470
|
+
);
|
|
471
|
+
return normalizedPath;
|
|
472
|
+
}
|
|
473
|
+
if (normalizedPath in fullToShortPathMap) {
|
|
474
|
+
const shortPath = fullToShortPathMap[normalizedPath];
|
|
475
|
+
if (shortPath in attributesMap) {
|
|
476
|
+
console.log(
|
|
477
|
+
`[findInAttributesMapForPath] "${path}" → normalized "${normalizedPath}" fullToShortPathMap match: shortPath="${shortPath}"`,
|
|
478
|
+
);
|
|
479
|
+
return normalizedPath; // Return normalized FULL path
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Try prefix matching for child paths
|
|
485
|
+
// e.g., path is "entity.sha.something" and attributesMap has "entity.sha"
|
|
486
|
+
// OR path is a full path like "useLoaderData<...>().functionCallReturnValue.entity.sha"
|
|
487
|
+
// and we need to find matching short path prefix
|
|
488
|
+
for (const attrPath of Object.keys(attributesMap)) {
|
|
489
|
+
if (path.startsWith(attrPath + '.') || path.startsWith(attrPath + '[')) {
|
|
490
|
+
console.log(
|
|
491
|
+
`[findInAttributesMapForPath] "${path}" → PREFIX match: starts with attributesMap key "${attrPath}"`,
|
|
492
|
+
);
|
|
493
|
+
return path;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Try suffix matching: if the path ends with ".X.Y.Z" and attributesMap has "X.Y.Z"
|
|
498
|
+
// Return the FULL input path to preserve data source context
|
|
499
|
+
// Skip suffix matching for chained function calls (multiple .functionCallReturnValue segments)
|
|
500
|
+
// to avoid false matches: e.g., fetch(...).json().functionCallReturnValue.data falsely matching
|
|
501
|
+
// "data" from a completely different data source like useFetcher
|
|
502
|
+
const fnCallReturnValueCount = (
|
|
503
|
+
path.match(/\.functionCallReturnValue/g) || []
|
|
504
|
+
).length;
|
|
505
|
+
if (fnCallReturnValueCount <= 1) {
|
|
506
|
+
for (const attrPath of Object.keys(attributesMap)) {
|
|
507
|
+
if (
|
|
508
|
+
path.endsWith('.' + attrPath) ||
|
|
509
|
+
path.endsWith('.' + attrPath.replace(/\[\d+\]/g, '[]'))
|
|
510
|
+
) {
|
|
511
|
+
console.log(
|
|
512
|
+
`[findInAttributesMapForPath] "${path}" → SUFFIX match: ends with attributesMap key "${attrPath}"`,
|
|
513
|
+
);
|
|
514
|
+
return path; // Return FULL path, not short attrPath
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// Try child path matching against fullToShortPathMap keys
|
|
520
|
+
// If the path starts with a known full path + '.' or '[', it's a child
|
|
521
|
+
// of a controllable path. Build the equivalent short child path.
|
|
522
|
+
// e.g., path = "fetch(...).fCRV.json().fCRV.topPaths.length"
|
|
523
|
+
// fullToShortPathMap has "fetch(...).fCRV.json().fCRV.topPaths" → "json().fCRV.topPaths"
|
|
524
|
+
// → check if "json().fCRV.topPaths.length" is in attributesMap
|
|
525
|
+
for (const [fullPath, shortPath] of Object.entries(fullToShortPathMap)) {
|
|
526
|
+
if (path.startsWith(fullPath + '.') || path.startsWith(fullPath + '[')) {
|
|
527
|
+
const suffix = path.slice(fullPath.length); // e.g., ".length"
|
|
528
|
+
const shortChildPath = shortPath + suffix;
|
|
529
|
+
if (shortChildPath in attributesMap) {
|
|
530
|
+
console.log(
|
|
531
|
+
`[findInAttributesMapForPath] "${path}" → CHILD of fullToShortPathMap key "${fullPath}": shortChildPath="${shortChildPath}" found in attributesMap`,
|
|
532
|
+
);
|
|
533
|
+
return path; // Return full path to preserve data source context
|
|
534
|
+
}
|
|
535
|
+
// Also check if the base short path is an array and suffix is .length
|
|
536
|
+
if (suffix === '.length' && shortPath in attributesMap) {
|
|
537
|
+
console.log(
|
|
538
|
+
`[findInAttributesMapForPath] "${path}" → CHILD .length of fullToShortPathMap key "${fullPath}": base shortPath="${shortPath}" is in attributesMap (array .length)`,
|
|
539
|
+
);
|
|
540
|
+
return path; // Array .length is controllable via the array
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Try parent matching: if the path is a prefix of any fullToShortPathMap key,
|
|
546
|
+
// it's a parent of controllable data and therefore controllable itself
|
|
547
|
+
for (const fullPath of Object.keys(fullToShortPathMap)) {
|
|
548
|
+
if (fullPath.startsWith(path + '.') || fullPath.startsWith(path + '[')) {
|
|
549
|
+
console.log(
|
|
550
|
+
`[findInAttributesMapForPath] "${path}" → PARENT match: fullToShortPathMap key "${fullPath}" starts with this path`,
|
|
551
|
+
);
|
|
552
|
+
return path;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
console.log(
|
|
557
|
+
`[findInAttributesMapForPath] "${path}" → NO MATCH (checked ${Object.keys(attributesMap).length} attributesMap keys, ${Object.keys(fullToShortPathMap).length} fullToShortPathMap keys)`,
|
|
558
|
+
);
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Generate a slug from a path for use in flow IDs and exclusive groups.
|
|
564
|
+
*/
|
|
565
|
+
function pathToSlug(path: string): string {
|
|
566
|
+
return path
|
|
567
|
+
.replace(/\[\d+\]/g, '')
|
|
568
|
+
.replace(/\[\]/g, '')
|
|
569
|
+
.replace(/\(\)/g, '')
|
|
570
|
+
.replace(/\.functionCallReturnValue/g, '')
|
|
571
|
+
.replace(/[<>]/g, '')
|
|
572
|
+
.replace(/\./g, '-')
|
|
573
|
+
.toLowerCase();
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Generate a human-readable name from a path.
|
|
578
|
+
* Extracts the last meaningful part of the path.
|
|
579
|
+
*
|
|
580
|
+
* Examples:
|
|
581
|
+
* - "useFetcher<...>().functionCallReturnValue.state" → "state"
|
|
582
|
+
* - "useLoaderData<...>().functionCallReturnValue.user.isActive" → "isActive"
|
|
583
|
+
*/
|
|
584
|
+
function generateNameFromPath(path: string): string {
|
|
585
|
+
// Remove function call markers and get the last meaningful segment
|
|
586
|
+
const cleanPath = path
|
|
587
|
+
.replace(/\(\)/g, '')
|
|
588
|
+
.replace(/\.functionCallReturnValue/g, '');
|
|
589
|
+
const parts = cleanPath.split('.');
|
|
590
|
+
const lastPart = parts[parts.length - 1];
|
|
591
|
+
|
|
592
|
+
// Convert camelCase to Title Case with spaces
|
|
593
|
+
return lastPart
|
|
594
|
+
.replace(/([A-Z])/g, ' $1')
|
|
595
|
+
.replace(/^./, (str) => str.toUpperCase())
|
|
596
|
+
.trim();
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Generate a flow ID from path and value.
|
|
601
|
+
* Creates a unique, URL-safe identifier.
|
|
602
|
+
*/
|
|
603
|
+
function generateFlowId(path: string, value: string): string {
|
|
604
|
+
// Clean the path for use in ID
|
|
605
|
+
const cleanPath = path
|
|
606
|
+
.replace(/\(\)/g, '')
|
|
607
|
+
.replace(/\.functionCallReturnValue/g, '')
|
|
608
|
+
.replace(/[<>]/g, '')
|
|
609
|
+
.replace(/\./g, '-');
|
|
610
|
+
|
|
611
|
+
// Clean the value
|
|
612
|
+
const cleanValue = value
|
|
613
|
+
.toString()
|
|
614
|
+
.toLowerCase()
|
|
615
|
+
.replace(/[^a-z0-9]/g, '-')
|
|
616
|
+
.replace(/-+/g, '-')
|
|
617
|
+
.replace(/^-|-$/g, '');
|
|
618
|
+
|
|
619
|
+
return `${cleanPath}-${cleanValue}`.toLowerCase();
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Infer value type from a string value.
|
|
624
|
+
*/
|
|
625
|
+
function inferValueType(
|
|
626
|
+
value: string,
|
|
627
|
+
): 'string' | 'number' | 'boolean' | 'null' {
|
|
628
|
+
if (value === 'true' || value === 'false') return 'boolean';
|
|
629
|
+
if (value === 'null' || value === 'undefined') return 'null';
|
|
630
|
+
if (!isNaN(Number(value)) && value !== '') return 'number';
|
|
631
|
+
return 'string';
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Generate flows from a single conditional usage.
|
|
636
|
+
* Sets impact to 'high' if the conditional controls JSX rendering.
|
|
637
|
+
*
|
|
638
|
+
* When the usage has a `constraintExpression`, it represents a complex expression
|
|
639
|
+
* that can't be simply resolved (e.g., `scenarios.filter(x => x.active).length > 1`).
|
|
640
|
+
* In this case:
|
|
641
|
+
* - `attributePath` is set to the controllable base (e.g., `scenarios`)
|
|
642
|
+
* - `constraint` is set to the full expression for LLM reasoning
|
|
643
|
+
*/
|
|
644
|
+
function generateFlowsFromUsage(
|
|
645
|
+
usage: ConditionalUsage,
|
|
646
|
+
resolvedPath: string,
|
|
647
|
+
): ExecutionFlow[] {
|
|
648
|
+
const flows: ExecutionFlow[] = [];
|
|
649
|
+
const baseName = generateNameFromPath(resolvedPath);
|
|
650
|
+
|
|
651
|
+
// Determine impact based on whether this conditional controls JSX rendering
|
|
652
|
+
// Conditionals that control visual output are high-impact
|
|
653
|
+
const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
|
|
654
|
+
? 'high'
|
|
655
|
+
: 'medium';
|
|
656
|
+
|
|
657
|
+
// When there's a constraintExpression, use the controllable base for attributePath
|
|
658
|
+
// and pass through the constraint for LLM reasoning
|
|
659
|
+
const hasConstraint = !!usage.constraintExpression;
|
|
660
|
+
const attributePath = hasConstraint
|
|
661
|
+
? extractControllableBase(resolvedPath)
|
|
662
|
+
: stripLengthSuffix(resolvedPath);
|
|
663
|
+
const constraint = usage.constraintExpression;
|
|
664
|
+
|
|
665
|
+
if (usage.conditionType === 'truthiness') {
|
|
666
|
+
// Generate both truthy and falsy flows
|
|
667
|
+
const isNegated = usage.isNegated ?? false;
|
|
668
|
+
|
|
669
|
+
// Truthy flow (or falsy if negated)
|
|
670
|
+
flows.push({
|
|
671
|
+
id: generateFlowId(resolvedPath, isNegated ? 'falsy' : 'truthy'),
|
|
672
|
+
name: `${baseName} ${isNegated ? 'False' : 'True'}`,
|
|
673
|
+
description: `When ${baseName.toLowerCase()} is ${isNegated ? 'falsy' : 'truthy'}`,
|
|
674
|
+
requiredValues: [
|
|
675
|
+
{
|
|
676
|
+
attributePath,
|
|
677
|
+
value: isNegated ? 'falsy' : 'truthy',
|
|
678
|
+
comparison: isNegated ? 'falsy' : 'truthy',
|
|
679
|
+
valueType: 'boolean',
|
|
680
|
+
constraint,
|
|
681
|
+
},
|
|
682
|
+
],
|
|
683
|
+
impact,
|
|
684
|
+
sourceLocation: usage.sourceLocation
|
|
685
|
+
? {
|
|
686
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
687
|
+
column: usage.sourceLocation.column,
|
|
688
|
+
}
|
|
689
|
+
: undefined,
|
|
690
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
// Falsy flow (or truthy if negated)
|
|
694
|
+
flows.push({
|
|
695
|
+
id: generateFlowId(resolvedPath, isNegated ? 'truthy' : 'falsy'),
|
|
696
|
+
name: `${baseName} ${isNegated ? 'True' : 'False'}`,
|
|
697
|
+
description: `When ${baseName.toLowerCase()} is ${isNegated ? 'truthy' : 'falsy'}`,
|
|
698
|
+
requiredValues: [
|
|
699
|
+
{
|
|
700
|
+
attributePath,
|
|
701
|
+
value: isNegated ? 'truthy' : 'falsy',
|
|
702
|
+
comparison: isNegated ? 'truthy' : 'falsy',
|
|
703
|
+
valueType: 'boolean',
|
|
704
|
+
constraint,
|
|
705
|
+
},
|
|
706
|
+
],
|
|
707
|
+
impact,
|
|
708
|
+
sourceLocation: usage.sourceLocation
|
|
709
|
+
? {
|
|
710
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
711
|
+
column: usage.sourceLocation.column,
|
|
712
|
+
}
|
|
713
|
+
: undefined,
|
|
714
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
715
|
+
});
|
|
716
|
+
} else if (
|
|
717
|
+
usage.conditionType === 'comparison' ||
|
|
718
|
+
usage.conditionType === 'switch'
|
|
719
|
+
) {
|
|
720
|
+
// Generate one flow per compared value
|
|
721
|
+
const values = usage.comparedValues ?? [];
|
|
722
|
+
|
|
723
|
+
for (const value of values) {
|
|
724
|
+
flows.push({
|
|
725
|
+
id: generateFlowId(resolvedPath, value),
|
|
726
|
+
name: `${baseName}: ${value}`,
|
|
727
|
+
description: `When ${baseName.toLowerCase()} equals "${value}"`,
|
|
728
|
+
requiredValues: [
|
|
729
|
+
{
|
|
730
|
+
attributePath,
|
|
731
|
+
value: value,
|
|
732
|
+
comparison: 'equals',
|
|
733
|
+
valueType: inferValueType(value),
|
|
734
|
+
constraint,
|
|
735
|
+
},
|
|
736
|
+
],
|
|
737
|
+
impact,
|
|
738
|
+
sourceLocation: usage.sourceLocation
|
|
739
|
+
? {
|
|
740
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
741
|
+
column: usage.sourceLocation.column,
|
|
742
|
+
}
|
|
743
|
+
: undefined,
|
|
744
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return flows;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Generate a flow from a compound conditional (all conditions must be satisfied).
|
|
754
|
+
* Sets impact to 'high' if the compound conditional controls JSX rendering.
|
|
755
|
+
*/
|
|
756
|
+
function generateFlowFromCompound(
|
|
757
|
+
compound: CompoundConditional,
|
|
758
|
+
resolvedPaths: Map<string, string>,
|
|
759
|
+
): ExecutionFlow | null {
|
|
760
|
+
// Determine impact based on whether this compound conditional controls JSX rendering
|
|
761
|
+
const impact: ExecutionFlow['impact'] = compound.controlsJsxRendering
|
|
762
|
+
? 'high'
|
|
763
|
+
: 'medium';
|
|
764
|
+
const requiredValues: ExecutionFlow['requiredValues'] = [];
|
|
765
|
+
|
|
766
|
+
for (const condition of compound.conditions) {
|
|
767
|
+
const resolvedPath = resolvedPaths.get(condition.path);
|
|
768
|
+
if (!resolvedPath) {
|
|
769
|
+
// This shouldn't happen if we pre-filtered, but safety check
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Determine the required value based on condition type
|
|
774
|
+
let value: string;
|
|
775
|
+
let comparison: ExecutionFlow['requiredValues'][0]['comparison'];
|
|
776
|
+
|
|
777
|
+
if (condition.conditionType === 'truthiness') {
|
|
778
|
+
// If negated (!foo), we need falsy; otherwise truthy
|
|
779
|
+
value = condition.isNegated ? 'falsy' : 'truthy';
|
|
780
|
+
comparison = condition.isNegated ? 'falsy' : 'truthy';
|
|
781
|
+
} else {
|
|
782
|
+
// For comparison/switch, use the first compared value or required value
|
|
783
|
+
value =
|
|
784
|
+
condition.requiredValue?.toString() ??
|
|
785
|
+
condition.comparedValues?.[0] ??
|
|
786
|
+
'truthy';
|
|
787
|
+
// Map comparison operator to flow comparison type
|
|
788
|
+
const op = condition.comparisonOperator;
|
|
789
|
+
if (op === '>' || op === '>=') {
|
|
790
|
+
comparison = 'length>';
|
|
791
|
+
} else if (op === '<' || op === '<=') {
|
|
792
|
+
comparison = 'length<';
|
|
793
|
+
} else {
|
|
794
|
+
comparison = 'equals';
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
requiredValues.push({
|
|
799
|
+
attributePath: stripLengthSuffix(resolvedPath),
|
|
800
|
+
value,
|
|
801
|
+
comparison,
|
|
802
|
+
valueType: inferValueType(value),
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Remove contradictory "falsy" values where a child path requires data
|
|
807
|
+
const cleanedValues = removeContradictoryFalsyValues(requiredValues);
|
|
808
|
+
|
|
809
|
+
if (cleanedValues.length === 0) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Generate a combined ID from all paths + values to distinguish different comparisons
|
|
814
|
+
const pathParts = cleanedValues
|
|
815
|
+
.map((rv) => {
|
|
816
|
+
const name = generateNameFromPath(rv.attributePath);
|
|
817
|
+
const suffix =
|
|
818
|
+
rv.comparison === 'truthy' || rv.comparison === 'falsy'
|
|
819
|
+
? `-${rv.comparison}`
|
|
820
|
+
: `-${rv.comparison}-${rv.value}`;
|
|
821
|
+
return name.toLowerCase().replace(/\s+/g, '-') + suffix;
|
|
822
|
+
})
|
|
823
|
+
.join('-and-');
|
|
824
|
+
|
|
825
|
+
return {
|
|
826
|
+
id: `compound-${pathParts}`,
|
|
827
|
+
name: cleanedValues
|
|
828
|
+
.map((rv) => generateNameFromPath(rv.attributePath))
|
|
829
|
+
.join(' + '),
|
|
830
|
+
description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
|
|
831
|
+
requiredValues: cleanedValues,
|
|
832
|
+
impact,
|
|
833
|
+
sourceLocation: {
|
|
834
|
+
lineNumber: compound.sourceLocation.lineNumber,
|
|
835
|
+
column: compound.sourceLocation.column,
|
|
836
|
+
},
|
|
837
|
+
codeSnippet: compound.sourceLocation.codeSnippet,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Expand a compound conditional with OR groups into multiple condition sets.
|
|
843
|
+
*
|
|
844
|
+
* For a compound like `A && (B || C)`:
|
|
845
|
+
* - Conditions: [{ path: 'A' }, { path: 'B', orGroupId: 'or_xxx' }, { path: 'C', orGroupId: 'or_xxx' }]
|
|
846
|
+
* - Returns: [[A, B], [A, C]] - two sets of conditions
|
|
847
|
+
*
|
|
848
|
+
* For multiple OR groups like `A && (B || C) && (D || E)`:
|
|
849
|
+
* - Returns: [[A, B, D], [A, B, E], [A, C, D], [A, C, E]]
|
|
850
|
+
*/
|
|
851
|
+
function expandOrGroups(
|
|
852
|
+
conditions: CompoundConditional['conditions'],
|
|
853
|
+
): CompoundConditional['conditions'][] {
|
|
854
|
+
// Separate conditions into mandatory (no orGroupId) and OR groups
|
|
855
|
+
const mandatory = conditions.filter((c) => !c.orGroupId);
|
|
856
|
+
const orGroups = new Map<string, typeof conditions>();
|
|
857
|
+
|
|
858
|
+
for (const condition of conditions) {
|
|
859
|
+
if (condition.orGroupId) {
|
|
860
|
+
const group = orGroups.get(condition.orGroupId) ?? [];
|
|
861
|
+
group.push(condition);
|
|
862
|
+
orGroups.set(condition.orGroupId, group);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// If no OR groups, return the original conditions
|
|
867
|
+
if (orGroups.size === 0) {
|
|
868
|
+
return [conditions];
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// Generate all combinations by picking one condition from each OR group
|
|
872
|
+
const groupArrays = Array.from(orGroups.values());
|
|
873
|
+
const combinations: CompoundConditional['conditions'][] = [];
|
|
874
|
+
|
|
875
|
+
function generateCombinations(
|
|
876
|
+
index: number,
|
|
877
|
+
current: typeof conditions,
|
|
878
|
+
): void {
|
|
879
|
+
if (index === groupArrays.length) {
|
|
880
|
+
// We've picked one from each OR group - combine with mandatory conditions
|
|
881
|
+
combinations.push([...mandatory, ...current]);
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// Pick each option from the current OR group
|
|
886
|
+
for (const option of groupArrays[index]) {
|
|
887
|
+
generateCombinations(index + 1, [...current, option]);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
generateCombinations(0, []);
|
|
892
|
+
return combinations;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Generate execution flows from conditional usages using pure static analysis.
|
|
897
|
+
*
|
|
898
|
+
* Only generates flows where all paths resolve to controllable data sources.
|
|
899
|
+
* This ensures we never produce flows with invalid paths like useState variables.
|
|
900
|
+
*/
|
|
901
|
+
/**
|
|
902
|
+
* Normalize a resolved path to a canonical form for deduplication.
|
|
903
|
+
* Uses fullToShortPathMap to convert full paths to short paths.
|
|
904
|
+
* This ensures that both "hasNewerVersion" and
|
|
905
|
+
* "useLoaderData<LoaderData>().functionCallReturnValue.hasNewerVersion"
|
|
906
|
+
* normalize to the same canonical path.
|
|
907
|
+
*/
|
|
908
|
+
function normalizePathForDeduplication(
|
|
909
|
+
resolvedPath: string,
|
|
910
|
+
fullToShortPathMap: Record<string, string>,
|
|
911
|
+
): string {
|
|
912
|
+
// If the path is in fullToShortPathMap, use the short path as canonical
|
|
913
|
+
if (resolvedPath in fullToShortPathMap) {
|
|
914
|
+
return fullToShortPathMap[resolvedPath];
|
|
915
|
+
}
|
|
916
|
+
// Otherwise, the path itself is canonical
|
|
917
|
+
return resolvedPath;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Translate a child component path to a parent path using prop mappings.
|
|
922
|
+
*
|
|
923
|
+
* Given:
|
|
924
|
+
* - childPath: "selectedScenario.metadata.screenshotPaths[0]" (path in child's context)
|
|
925
|
+
* - childEquiv: { selectedScenario: "signature[0].selectedScenario" } (child's internal-to-prop mapping)
|
|
926
|
+
* - parentEquiv: { "ChildName().signature[0].selectedScenario": "selectedScenario" } (parent's prop assignments)
|
|
927
|
+
* - childName: "ChildName"
|
|
928
|
+
*
|
|
929
|
+
* Returns: "selectedScenario.metadata.screenshotPaths[0]" (path in parent's context)
|
|
930
|
+
*
|
|
931
|
+
* The translation works by:
|
|
932
|
+
* 1. Finding the root variable in the child path (e.g., "selectedScenario")
|
|
933
|
+
* 2. Looking up the child's equivalence to find the prop path (e.g., "signature[0].selectedScenario")
|
|
934
|
+
* 3. Building the full child prop path (e.g., "ChildName().signature[0].selectedScenario")
|
|
935
|
+
* 4. Looking up the parent's equivalence to find the parent path (e.g., "selectedScenario")
|
|
936
|
+
* 5. Replacing the root with the parent path and preserving the suffix
|
|
937
|
+
*/
|
|
938
|
+
function translateChildPathToParent(
|
|
939
|
+
childPath: string,
|
|
940
|
+
childEquivalentSignatureVariables: Record<string, string | string[]>,
|
|
941
|
+
parentEquivalentSignatureVariables: Record<string, string | string[]>,
|
|
942
|
+
childName: string,
|
|
943
|
+
): string | null {
|
|
944
|
+
// Extract the root variable from the child path
|
|
945
|
+
// e.g., "selectedScenario.metadata.screenshotPaths[0]" → "selectedScenario"
|
|
946
|
+
const dotIndex = childPath.indexOf('.');
|
|
947
|
+
const bracketIndex = childPath.indexOf('[');
|
|
948
|
+
let rootVar: string;
|
|
949
|
+
let suffix: string;
|
|
950
|
+
|
|
951
|
+
if (dotIndex === -1 && bracketIndex === -1) {
|
|
952
|
+
rootVar = childPath;
|
|
953
|
+
suffix = '';
|
|
954
|
+
} else if (dotIndex === -1) {
|
|
955
|
+
rootVar = childPath.slice(0, bracketIndex);
|
|
956
|
+
suffix = childPath.slice(bracketIndex);
|
|
957
|
+
} else if (bracketIndex === -1) {
|
|
958
|
+
rootVar = childPath.slice(0, dotIndex);
|
|
959
|
+
suffix = childPath.slice(dotIndex);
|
|
960
|
+
} else {
|
|
961
|
+
const firstIndex = Math.min(dotIndex, bracketIndex);
|
|
962
|
+
rootVar = childPath.slice(0, firstIndex);
|
|
963
|
+
suffix = childPath.slice(firstIndex);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// Look up the child's equivalence for this root variable
|
|
967
|
+
// e.g., childEquiv[selectedScenario] = "signature[0].selectedScenario"
|
|
968
|
+
// Handle array case (OR expressions) - use first element if array
|
|
969
|
+
const rawChildPropPath = childEquivalentSignatureVariables[rootVar];
|
|
970
|
+
const childPropPath = Array.isArray(rawChildPropPath)
|
|
971
|
+
? rawChildPropPath[0]
|
|
972
|
+
: rawChildPropPath;
|
|
973
|
+
|
|
974
|
+
if (!childPropPath) {
|
|
975
|
+
// No mapping found - this might be internal state, not a prop
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// Build the full child prop path as seen from parent
|
|
980
|
+
// e.g., "ChildName().signature[0].selectedScenario"
|
|
981
|
+
const fullChildPropPath = `${childName}().${childPropPath}`;
|
|
982
|
+
|
|
983
|
+
// Look up parent's equivalence to find what value was passed to this prop
|
|
984
|
+
// e.g., parentEquiv["ChildName().signature[0].selectedScenario"] = "selectedScenario"
|
|
985
|
+
// Handle array case (OR expressions) - use first element if array
|
|
986
|
+
const rawParentValue = parentEquivalentSignatureVariables[fullChildPropPath];
|
|
987
|
+
const parentValue = Array.isArray(rawParentValue)
|
|
988
|
+
? rawParentValue[0]
|
|
989
|
+
: rawParentValue;
|
|
990
|
+
|
|
991
|
+
if (!parentValue) {
|
|
992
|
+
// No parent mapping found - log ALL parent keys that contain the childName
|
|
993
|
+
const relevantParentKeys = Object.keys(
|
|
994
|
+
parentEquivalentSignatureVariables,
|
|
995
|
+
).filter((k) => k.includes(childName));
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Build the translated path: parentValue + suffix
|
|
1000
|
+
// e.g., "selectedScenario" + ".metadata.screenshotPaths[0]"
|
|
1001
|
+
const result = parentValue + suffix;
|
|
1002
|
+
return result;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
export default function generateExecutionFlowsFromConditionals(
|
|
1006
|
+
args: GenerateFlowsFromConditionalsArgs,
|
|
1007
|
+
): ExecutionFlow[] {
|
|
1008
|
+
const {
|
|
1009
|
+
conditionalUsages,
|
|
1010
|
+
compoundConditionals,
|
|
1011
|
+
attributesMap,
|
|
1012
|
+
equivalentSignatureVariables,
|
|
1013
|
+
fullToShortPathMap,
|
|
1014
|
+
childComponentData,
|
|
1015
|
+
derivedVariables,
|
|
1016
|
+
sourceEquivalencies,
|
|
1017
|
+
} = args;
|
|
1018
|
+
|
|
1019
|
+
const flows: ExecutionFlow[] = [];
|
|
1020
|
+
const seenFlowIds = new Set<string>();
|
|
1021
|
+
|
|
1022
|
+
console.log(
|
|
1023
|
+
`[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`,
|
|
1024
|
+
);
|
|
1025
|
+
console.log(
|
|
1026
|
+
`[genFlowsFromConditionals] conditionalUsages keys: [${Object.keys(conditionalUsages).join(', ')}]`,
|
|
1027
|
+
);
|
|
1028
|
+
console.log(
|
|
1029
|
+
`[genFlowsFromConditionals] attributesMap keys: [${Object.keys(attributesMap).join(', ')}]`,
|
|
1030
|
+
);
|
|
1031
|
+
console.log(
|
|
1032
|
+
`[genFlowsFromConditionals] fullToShortPathMap: ${JSON.stringify(fullToShortPathMap)}`,
|
|
1033
|
+
);
|
|
1034
|
+
console.log(
|
|
1035
|
+
`[genFlowsFromConditionals] equivalentSignatureVariables: ${JSON.stringify(equivalentSignatureVariables)}`,
|
|
1036
|
+
);
|
|
1037
|
+
|
|
1038
|
+
// Track normalized resolved paths to prevent duplicate flows
|
|
1039
|
+
// This handles the case where we have usages for both:
|
|
1040
|
+
// - "hasNewerVersion" (short path from destructured variable)
|
|
1041
|
+
// - "useLoaderData<LoaderData>().functionCallReturnValue.hasNewerVersion" (full path)
|
|
1042
|
+
// Both resolve to the same logical data source, so we only want ONE set of flows.
|
|
1043
|
+
const seenNormalizedPaths = new Set<string>();
|
|
1044
|
+
|
|
1045
|
+
// Track which usages are part of compound conditionals (to avoid duplicates)
|
|
1046
|
+
const compoundChainIds = new Set(
|
|
1047
|
+
compoundConditionals.map((c) => c.chainId).filter(Boolean),
|
|
1048
|
+
);
|
|
1049
|
+
|
|
1050
|
+
// Process individual conditional usages
|
|
1051
|
+
for (const [_path, usages] of Object.entries(conditionalUsages)) {
|
|
1052
|
+
for (const usage of usages) {
|
|
1053
|
+
// Skip usages that are part of compound conditionals (handled separately)
|
|
1054
|
+
if (usage.chainId && compoundChainIds.has(usage.chainId)) {
|
|
1055
|
+
console.log(
|
|
1056
|
+
`[genFlowsFromConditionals] "${usage.path}" SKIP: part of compound conditional chain=${usage.chainId}`,
|
|
1057
|
+
);
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
console.log(
|
|
1062
|
+
`[genFlowsFromConditionals] --- Processing "${usage.path}" (type=${usage.conditionType}, negated=${usage.isNegated}, sourceDataPath="${usage.sourceDataPath ?? '(none)'}", derivedFrom=${usage.derivedFrom ? JSON.stringify(usage.derivedFrom) : 'none'})`,
|
|
1063
|
+
);
|
|
1064
|
+
|
|
1065
|
+
// First, try to use pre-computed sourceDataPath if available
|
|
1066
|
+
let resolvedPath: string | null = null;
|
|
1067
|
+
|
|
1068
|
+
if (usage.sourceDataPath) {
|
|
1069
|
+
// Clean up the sourceDataPath - it may have redundant scope prefixes
|
|
1070
|
+
// e.g., "useLoaderData<LoaderData>.useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
|
|
1071
|
+
// should become "useLoaderData<LoaderData>().functionCallReturnValue.entity.sha"
|
|
1072
|
+
// Returns null for malformed paths (e.g., chained function calls like fetch().json())
|
|
1073
|
+
const cleanedPath = cleanSourceDataPath(usage.sourceDataPath);
|
|
1074
|
+
console.log(
|
|
1075
|
+
`[genFlowsFromConditionals] "${usage.path}" cleanSourceDataPath("${usage.sourceDataPath}") → "${cleanedPath}"`,
|
|
1076
|
+
);
|
|
1077
|
+
if (cleanedPath) {
|
|
1078
|
+
// Verify the cleaned path exists in attributesMap
|
|
1079
|
+
const pathMatch = findInAttributesMapForPath(
|
|
1080
|
+
cleanedPath,
|
|
1081
|
+
attributesMap,
|
|
1082
|
+
fullToShortPathMap,
|
|
1083
|
+
);
|
|
1084
|
+
console.log(
|
|
1085
|
+
`[genFlowsFromConditionals] "${usage.path}" findInAttributesMapForPath("${cleanedPath}") → ${pathMatch ? `"${pathMatch}"` : 'null (not found)'}`,
|
|
1086
|
+
);
|
|
1087
|
+
if (pathMatch) {
|
|
1088
|
+
resolvedPath = pathMatch;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
// If cleanedPath is null, fall through to use fallback resolution
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// Fall back to resolution via equivalentSignatureVariables
|
|
1095
|
+
if (!resolvedPath) {
|
|
1096
|
+
console.log(
|
|
1097
|
+
`[genFlowsFromConditionals] "${usage.path}" sourceDataPath resolution failed, trying resolvePathToControllable("${usage.path}")...`,
|
|
1098
|
+
);
|
|
1099
|
+
const resolution = resolvePathToControllable(
|
|
1100
|
+
usage.path,
|
|
1101
|
+
attributesMap,
|
|
1102
|
+
equivalentSignatureVariables,
|
|
1103
|
+
fullToShortPathMap,
|
|
1104
|
+
);
|
|
1105
|
+
console.log(
|
|
1106
|
+
`[genFlowsFromConditionals] "${usage.path}" resolvePathToControllable → isControllable=${resolution.isControllable}, resolvedPath="${resolution.resolvedPath ?? '(none)'}"`,
|
|
1107
|
+
);
|
|
1108
|
+
if (resolution.isControllable && resolution.resolvedPath) {
|
|
1109
|
+
resolvedPath = resolution.resolvedPath;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// If still not resolved, try using derivedFrom info to find the source path
|
|
1114
|
+
// This handles cases like: const hasAnalysis = analysis !== null
|
|
1115
|
+
// where hasAnalysis is not in attributesMap but analysis is
|
|
1116
|
+
if (!resolvedPath && usage.derivedFrom) {
|
|
1117
|
+
const { operation, sourcePath, sourcePaths, comparedValue } =
|
|
1118
|
+
usage.derivedFrom;
|
|
1119
|
+
console.log(
|
|
1120
|
+
`[genFlowsFromConditionals] "${usage.path}" trying derivedFrom: operation=${operation}, sourcePath="${sourcePath ?? '(none)'}", sourcePaths=${sourcePaths ? JSON.stringify(sourcePaths) : '(none)'}, comparedValue="${comparedValue ?? '(none)'}"`,
|
|
1121
|
+
);
|
|
1122
|
+
// For single-source derivations (notNull, equals, etc.)
|
|
1123
|
+
if (sourcePath) {
|
|
1124
|
+
const resolution = resolvePathToControllable(
|
|
1125
|
+
sourcePath,
|
|
1126
|
+
attributesMap,
|
|
1127
|
+
equivalentSignatureVariables,
|
|
1128
|
+
fullToShortPathMap,
|
|
1129
|
+
);
|
|
1130
|
+
if (resolution.isControllable && resolution.resolvedPath) {
|
|
1131
|
+
resolvedPath = resolution.resolvedPath;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// For equals/notEquals derivations with comparedValue, generate comparison flows
|
|
1136
|
+
// e.g., canEdit derived from user.role === 'admin'
|
|
1137
|
+
// When canEdit is used in truthiness check, we need:
|
|
1138
|
+
// - Truthy flow: user.role = 'admin' (comparison: 'equals')
|
|
1139
|
+
// - Falsy flow: user.role != 'admin' (comparison: 'notEquals')
|
|
1140
|
+
if (
|
|
1141
|
+
(operation === 'equals' || operation === 'notEquals') &&
|
|
1142
|
+
comparedValue !== undefined &&
|
|
1143
|
+
resolvedPath &&
|
|
1144
|
+
usage.conditionType === 'truthiness'
|
|
1145
|
+
) {
|
|
1146
|
+
const baseName = generateNameFromPath(usage.path);
|
|
1147
|
+
const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
|
|
1148
|
+
? 'high'
|
|
1149
|
+
: 'medium';
|
|
1150
|
+
|
|
1151
|
+
const isNegated = usage.isNegated ?? false;
|
|
1152
|
+
|
|
1153
|
+
// For equals derivation:
|
|
1154
|
+
// - Truthy check (!negated): needs value = comparedValue (equals)
|
|
1155
|
+
// - Falsy check (negated): needs value != comparedValue (notEquals)
|
|
1156
|
+
// For notEquals derivation: inverse of above
|
|
1157
|
+
const isEqualsDerivation = operation === 'equals';
|
|
1158
|
+
const truthyNeedsEquals = isEqualsDerivation !== isNegated;
|
|
1159
|
+
|
|
1160
|
+
// Generate truthy flow
|
|
1161
|
+
const truthyFlow: ExecutionFlow = {
|
|
1162
|
+
id: generateFlowId(usage.path, 'truthy'),
|
|
1163
|
+
name: `${baseName} True`,
|
|
1164
|
+
description: `When ${baseName.toLowerCase()} is truthy (${resolvedPath} ${truthyNeedsEquals ? '=' : '!='} ${comparedValue})`,
|
|
1165
|
+
requiredValues: [
|
|
1166
|
+
{
|
|
1167
|
+
attributePath: stripLengthSuffix(resolvedPath),
|
|
1168
|
+
value: comparedValue,
|
|
1169
|
+
comparison: truthyNeedsEquals ? 'equals' : 'notEquals',
|
|
1170
|
+
valueType: inferValueType(comparedValue),
|
|
1171
|
+
},
|
|
1172
|
+
],
|
|
1173
|
+
impact,
|
|
1174
|
+
sourceLocation: usage.sourceLocation
|
|
1175
|
+
? {
|
|
1176
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1177
|
+
column: usage.sourceLocation.column,
|
|
1178
|
+
}
|
|
1179
|
+
: undefined,
|
|
1180
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// Generate falsy flow
|
|
1184
|
+
const falsyFlow: ExecutionFlow = {
|
|
1185
|
+
id: generateFlowId(usage.path, 'falsy'),
|
|
1186
|
+
name: `${baseName} False`,
|
|
1187
|
+
description: `When ${baseName.toLowerCase()} is falsy (${resolvedPath} ${truthyNeedsEquals ? '!=' : '='} ${comparedValue})`,
|
|
1188
|
+
requiredValues: [
|
|
1189
|
+
{
|
|
1190
|
+
attributePath: stripLengthSuffix(resolvedPath),
|
|
1191
|
+
value: comparedValue,
|
|
1192
|
+
comparison: truthyNeedsEquals ? 'notEquals' : 'equals',
|
|
1193
|
+
valueType: inferValueType(comparedValue),
|
|
1194
|
+
},
|
|
1195
|
+
],
|
|
1196
|
+
impact,
|
|
1197
|
+
sourceLocation: usage.sourceLocation
|
|
1198
|
+
? {
|
|
1199
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1200
|
+
column: usage.sourceLocation.column,
|
|
1201
|
+
}
|
|
1202
|
+
: undefined,
|
|
1203
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
// Add flows and skip normal flow generation
|
|
1207
|
+
if (!seenFlowIds.has(truthyFlow.id)) {
|
|
1208
|
+
seenFlowIds.add(truthyFlow.id);
|
|
1209
|
+
flows.push(truthyFlow);
|
|
1210
|
+
}
|
|
1211
|
+
if (!seenFlowIds.has(falsyFlow.id)) {
|
|
1212
|
+
seenFlowIds.add(falsyFlow.id);
|
|
1213
|
+
flows.push(falsyFlow);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
// For OR derivations with negation, we need ALL sources to be falsy
|
|
1220
|
+
// e.g., !isBusy where isBusy = isRunning || isQueued || isPending
|
|
1221
|
+
// For the falsy flow, ALL sources must be falsy
|
|
1222
|
+
if (
|
|
1223
|
+
operation === 'or' &&
|
|
1224
|
+
usage.conditionType === 'truthiness' &&
|
|
1225
|
+
usage.isNegated === true &&
|
|
1226
|
+
sourcePaths &&
|
|
1227
|
+
sourcePaths.length > 0
|
|
1228
|
+
) {
|
|
1229
|
+
// Use expandDerivedVariableToSources to recursively resolve all sources
|
|
1230
|
+
const allSources = expandDerivedVariableToSources(
|
|
1231
|
+
usage.path,
|
|
1232
|
+
conditionalUsages,
|
|
1233
|
+
attributesMap,
|
|
1234
|
+
equivalentSignatureVariables,
|
|
1235
|
+
fullToShortPathMap,
|
|
1236
|
+
new Set(),
|
|
1237
|
+
derivedVariables,
|
|
1238
|
+
);
|
|
1239
|
+
|
|
1240
|
+
if (allSources.length > 0) {
|
|
1241
|
+
// Generate a compound-style flow with all sources set to falsy
|
|
1242
|
+
const baseName = generateNameFromPath(usage.path);
|
|
1243
|
+
const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
|
|
1244
|
+
? 'high'
|
|
1245
|
+
: 'medium';
|
|
1246
|
+
|
|
1247
|
+
const requiredValues: ExecutionFlow['requiredValues'] =
|
|
1248
|
+
allSources.map((source) => ({
|
|
1249
|
+
attributePath: source.path,
|
|
1250
|
+
value: 'falsy',
|
|
1251
|
+
comparison: 'falsy' as const,
|
|
1252
|
+
valueType: 'boolean' as const,
|
|
1253
|
+
}));
|
|
1254
|
+
|
|
1255
|
+
// Create a single falsy flow with all sources
|
|
1256
|
+
const falsyFlow: ExecutionFlow = {
|
|
1257
|
+
id: generateFlowId(usage.path, 'falsy'),
|
|
1258
|
+
name: `${baseName} False`,
|
|
1259
|
+
description: `When ${baseName.toLowerCase()} is falsy (all sources are falsy)`,
|
|
1260
|
+
requiredValues,
|
|
1261
|
+
impact,
|
|
1262
|
+
sourceLocation: usage.sourceLocation
|
|
1263
|
+
? {
|
|
1264
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1265
|
+
column: usage.sourceLocation.column,
|
|
1266
|
+
}
|
|
1267
|
+
: undefined,
|
|
1268
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1269
|
+
};
|
|
1270
|
+
|
|
1271
|
+
// Create a truthy flow - for OR, ANY source being truthy is sufficient
|
|
1272
|
+
// We use the first resolvable source for the truthy flow
|
|
1273
|
+
const firstSource = allSources[0];
|
|
1274
|
+
const truthyFlow: ExecutionFlow = {
|
|
1275
|
+
id: generateFlowId(usage.path, 'truthy'),
|
|
1276
|
+
name: `${baseName} True`,
|
|
1277
|
+
description: `When ${baseName.toLowerCase()} is truthy`,
|
|
1278
|
+
requiredValues: [
|
|
1279
|
+
{
|
|
1280
|
+
attributePath: firstSource.path,
|
|
1281
|
+
value: 'truthy',
|
|
1282
|
+
comparison: 'truthy',
|
|
1283
|
+
valueType: 'boolean',
|
|
1284
|
+
},
|
|
1285
|
+
],
|
|
1286
|
+
impact,
|
|
1287
|
+
sourceLocation: usage.sourceLocation
|
|
1288
|
+
? {
|
|
1289
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1290
|
+
column: usage.sourceLocation.column,
|
|
1291
|
+
}
|
|
1292
|
+
: undefined,
|
|
1293
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1294
|
+
};
|
|
1295
|
+
|
|
1296
|
+
// Add both flows (falsy needs all sources, truthy needs one)
|
|
1297
|
+
if (!seenFlowIds.has(falsyFlow.id)) {
|
|
1298
|
+
seenFlowIds.add(falsyFlow.id);
|
|
1299
|
+
flows.push(falsyFlow);
|
|
1300
|
+
}
|
|
1301
|
+
if (!seenFlowIds.has(truthyFlow.id)) {
|
|
1302
|
+
seenFlowIds.add(truthyFlow.id);
|
|
1303
|
+
flows.push(truthyFlow);
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// Skip the normal flow generation for this usage
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// For AND derivations without negation, we need ALL sources to be truthy
|
|
1312
|
+
// e.g., isReady where isReady = hasData && isLoaded && isValid
|
|
1313
|
+
// For the truthy flow, ALL sources must be truthy
|
|
1314
|
+
// For negated AND (!isReady), ANY source being falsy is sufficient (fallback behavior)
|
|
1315
|
+
if (
|
|
1316
|
+
operation === 'and' &&
|
|
1317
|
+
usage.conditionType === 'truthiness' &&
|
|
1318
|
+
usage.isNegated !== true &&
|
|
1319
|
+
sourcePaths &&
|
|
1320
|
+
sourcePaths.length > 0
|
|
1321
|
+
) {
|
|
1322
|
+
// Use expandDerivedVariableToSources to recursively resolve all sources
|
|
1323
|
+
const allSources = expandDerivedVariableToSources(
|
|
1324
|
+
usage.path,
|
|
1325
|
+
conditionalUsages,
|
|
1326
|
+
attributesMap,
|
|
1327
|
+
equivalentSignatureVariables,
|
|
1328
|
+
fullToShortPathMap,
|
|
1329
|
+
new Set(),
|
|
1330
|
+
derivedVariables,
|
|
1331
|
+
);
|
|
1332
|
+
|
|
1333
|
+
if (allSources.length > 0) {
|
|
1334
|
+
// Generate a compound-style flow with all sources set to truthy
|
|
1335
|
+
const baseName = generateNameFromPath(usage.path);
|
|
1336
|
+
const impact: ExecutionFlow['impact'] = usage.controlsJsxRendering
|
|
1337
|
+
? 'high'
|
|
1338
|
+
: 'medium';
|
|
1339
|
+
|
|
1340
|
+
const requiredValues: ExecutionFlow['requiredValues'] =
|
|
1341
|
+
allSources.map((source) => ({
|
|
1342
|
+
attributePath: source.path,
|
|
1343
|
+
value: 'truthy',
|
|
1344
|
+
comparison: 'truthy' as const,
|
|
1345
|
+
valueType: 'boolean' as const,
|
|
1346
|
+
}));
|
|
1347
|
+
|
|
1348
|
+
// Create a truthy flow with all sources
|
|
1349
|
+
const truthyFlow: ExecutionFlow = {
|
|
1350
|
+
id: generateFlowId(usage.path, 'truthy'),
|
|
1351
|
+
name: `${baseName} True`,
|
|
1352
|
+
description: `When ${baseName.toLowerCase()} is truthy (all sources are truthy)`,
|
|
1353
|
+
requiredValues,
|
|
1354
|
+
impact,
|
|
1355
|
+
sourceLocation: usage.sourceLocation
|
|
1356
|
+
? {
|
|
1357
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1358
|
+
column: usage.sourceLocation.column,
|
|
1359
|
+
}
|
|
1360
|
+
: undefined,
|
|
1361
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
// Create a falsy flow - for AND, ANY source being falsy is sufficient
|
|
1365
|
+
// We use the first resolvable source for the falsy flow
|
|
1366
|
+
const firstSource = allSources[0];
|
|
1367
|
+
const falsyFlow: ExecutionFlow = {
|
|
1368
|
+
id: generateFlowId(usage.path, 'falsy'),
|
|
1369
|
+
name: `${baseName} False`,
|
|
1370
|
+
description: `When ${baseName.toLowerCase()} is falsy`,
|
|
1371
|
+
requiredValues: [
|
|
1372
|
+
{
|
|
1373
|
+
attributePath: firstSource.path,
|
|
1374
|
+
value: 'falsy',
|
|
1375
|
+
comparison: 'falsy',
|
|
1376
|
+
valueType: 'boolean',
|
|
1377
|
+
},
|
|
1378
|
+
],
|
|
1379
|
+
impact,
|
|
1380
|
+
sourceLocation: usage.sourceLocation
|
|
1381
|
+
? {
|
|
1382
|
+
lineNumber: usage.sourceLocation.lineNumber,
|
|
1383
|
+
column: usage.sourceLocation.column,
|
|
1384
|
+
}
|
|
1385
|
+
: undefined,
|
|
1386
|
+
codeSnippet: usage.sourceLocation?.codeSnippet,
|
|
1387
|
+
};
|
|
1388
|
+
|
|
1389
|
+
// Add both flows (truthy needs all sources, falsy needs one)
|
|
1390
|
+
if (!seenFlowIds.has(truthyFlow.id)) {
|
|
1391
|
+
seenFlowIds.add(truthyFlow.id);
|
|
1392
|
+
flows.push(truthyFlow);
|
|
1393
|
+
}
|
|
1394
|
+
if (!seenFlowIds.has(falsyFlow.id)) {
|
|
1395
|
+
seenFlowIds.add(falsyFlow.id);
|
|
1396
|
+
flows.push(falsyFlow);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// Skip the normal flow generation for this usage
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
// For multi-source derivations (or, and) without special handling,
|
|
1405
|
+
// try the first resolvable path as a fallback
|
|
1406
|
+
if (!resolvedPath && sourcePaths && sourcePaths.length > 0) {
|
|
1407
|
+
for (const sp of sourcePaths) {
|
|
1408
|
+
const resolution = resolvePathToControllable(
|
|
1409
|
+
sp,
|
|
1410
|
+
attributesMap,
|
|
1411
|
+
equivalentSignatureVariables,
|
|
1412
|
+
fullToShortPathMap,
|
|
1413
|
+
);
|
|
1414
|
+
|
|
1415
|
+
if (resolution.isControllable && resolution.resolvedPath) {
|
|
1416
|
+
resolvedPath = resolution.resolvedPath;
|
|
1417
|
+
break;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
if (!resolvedPath) {
|
|
1424
|
+
// Path is not controllable - skip (no invalid flows possible)
|
|
1425
|
+
console.log(
|
|
1426
|
+
`[genFlowsFromConditionals] "${usage.path}" SKIP: not controllable (no resolvedPath after all attempts)`,
|
|
1427
|
+
);
|
|
1428
|
+
continue;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// Normalize the resolved path to detect duplicates
|
|
1432
|
+
// E.g., both "hasNewerVersion" and "useLoaderData<...>().hasNewerVersion"
|
|
1433
|
+
// should normalize to the same canonical path
|
|
1434
|
+
const normalizedPath = normalizePathForDeduplication(
|
|
1435
|
+
resolvedPath,
|
|
1436
|
+
fullToShortPathMap,
|
|
1437
|
+
);
|
|
1438
|
+
|
|
1439
|
+
// Skip if we've already generated flows for this normalized path
|
|
1440
|
+
// This prevents duplicate flows when we have usages for both short and full paths
|
|
1441
|
+
if (seenNormalizedPaths.has(normalizedPath)) {
|
|
1442
|
+
console.log(
|
|
1443
|
+
`[genFlowsFromConditionals] "${usage.path}" SKIP: duplicate normalizedPath="${normalizedPath}" (resolvedPath="${resolvedPath}")`,
|
|
1444
|
+
);
|
|
1445
|
+
continue;
|
|
1446
|
+
}
|
|
1447
|
+
seenNormalizedPaths.add(normalizedPath);
|
|
1448
|
+
|
|
1449
|
+
// Skip individual truthy/falsy flows on parent paths that have child data entries.
|
|
1450
|
+
// Lifecycle booleans (like isLoadingAuditData) traced to fetch(...).functionCallReturnValue
|
|
1451
|
+
// produce misleading truthy/falsy flows: "truthy" can't show loading (mock resolves instantly),
|
|
1452
|
+
// "falsy" tells the LLM to return null (breaking .json()). Compound flows with specific child
|
|
1453
|
+
// data requirements provide the correct mock guidance.
|
|
1454
|
+
if (
|
|
1455
|
+
usage.conditionType === 'truthiness' &&
|
|
1456
|
+
resolvedPath &&
|
|
1457
|
+
hasChildPathsInMap(resolvedPath, fullToShortPathMap)
|
|
1458
|
+
) {
|
|
1459
|
+
console.log(
|
|
1460
|
+
`[genFlowsFromConditionals] "${usage.path}" SKIP: parent path "${resolvedPath}" has child data paths — compound flows will handle this`,
|
|
1461
|
+
);
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
console.log(
|
|
1466
|
+
`[genFlowsFromConditionals] "${usage.path}" RESOLVED → resolvedPath="${resolvedPath}", normalizedPath="${normalizedPath}" — generating flows`,
|
|
1467
|
+
);
|
|
1468
|
+
|
|
1469
|
+
// Generate flows for this controllable usage
|
|
1470
|
+
const usageFlows = generateFlowsFromUsage(usage, resolvedPath);
|
|
1471
|
+
|
|
1472
|
+
for (const flow of usageFlows) {
|
|
1473
|
+
// Deduplicate by flow ID
|
|
1474
|
+
if (!seenFlowIds.has(flow.id)) {
|
|
1475
|
+
seenFlowIds.add(flow.id);
|
|
1476
|
+
flows.push(flow);
|
|
1477
|
+
console.log(
|
|
1478
|
+
`[genFlowsFromConditionals] "${usage.path}" FLOW ADDED: id="${flow.id}", requiredValues=${JSON.stringify(flow.requiredValues.map((rv) => ({ attr: rv.attributePath, val: rv.value })))}`,
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// Process compound conditionals
|
|
1486
|
+
for (const compound of compoundConditionals) {
|
|
1487
|
+
// Expand OR groups into separate condition sets
|
|
1488
|
+
// For example, `A && (B || C)` becomes [[A, B], [A, C]]
|
|
1489
|
+
const expandedConditionSets = expandOrGroups(compound.conditions);
|
|
1490
|
+
|
|
1491
|
+
// Process each expanded condition set as a separate potential flow
|
|
1492
|
+
for (const conditionSet of expandedConditionSets) {
|
|
1493
|
+
// First, check if ALL paths in this condition set are controllable (or can be expanded to controllable sources)
|
|
1494
|
+
const resolvedPaths = new Map<string, string>();
|
|
1495
|
+
// Track expanded sources for derived variables (path -> array of expanded sources)
|
|
1496
|
+
const expandedSources = new Map<
|
|
1497
|
+
string,
|
|
1498
|
+
Array<{ path: string; operation?: DerivedVariableOperation }>
|
|
1499
|
+
>();
|
|
1500
|
+
let allControllable = true;
|
|
1501
|
+
|
|
1502
|
+
for (const condition of conditionSet) {
|
|
1503
|
+
// Check if this condition path has derivation info
|
|
1504
|
+
// First check conditionalUsages, then fall back to derivedVariables
|
|
1505
|
+
const usagesForPath = conditionalUsages[condition.path];
|
|
1506
|
+
let derivedFromInfo = usagesForPath?.find(
|
|
1507
|
+
(u) => u.derivedFrom?.operation,
|
|
1508
|
+
)?.derivedFrom;
|
|
1509
|
+
|
|
1510
|
+
// CRITICAL: Also check derivedVariables for intermediate derived variables
|
|
1511
|
+
if (!derivedFromInfo && derivedVariables?.[condition.path]) {
|
|
1512
|
+
derivedFromInfo = derivedVariables[condition.path];
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
if (derivedFromInfo) {
|
|
1516
|
+
// This is a derived variable - expand to its sources
|
|
1517
|
+
const sources = expandDerivedVariableToSources(
|
|
1518
|
+
condition.path,
|
|
1519
|
+
conditionalUsages,
|
|
1520
|
+
attributesMap,
|
|
1521
|
+
equivalentSignatureVariables,
|
|
1522
|
+
fullToShortPathMap,
|
|
1523
|
+
new Set(),
|
|
1524
|
+
derivedVariables,
|
|
1525
|
+
);
|
|
1526
|
+
|
|
1527
|
+
if (sources.length > 0) {
|
|
1528
|
+
// Store the expanded sources for this condition
|
|
1529
|
+
expandedSources.set(condition.path, sources);
|
|
1530
|
+
// Use the first source's path for the resolvedPaths map (for ID generation)
|
|
1531
|
+
resolvedPaths.set(condition.path, sources[0].path);
|
|
1532
|
+
} else {
|
|
1533
|
+
// Derived variable expansion failed — try sourceDataPath fallback
|
|
1534
|
+
// This handles cases where the derivation chain goes through useMemo/useState
|
|
1535
|
+
// but the enriched sourceDataPath already traced to the actual data source
|
|
1536
|
+
const usageWithSource = usagesForPath?.find(
|
|
1537
|
+
(u) => u.sourceDataPath,
|
|
1538
|
+
);
|
|
1539
|
+
let derivedFallbackPath: string | null = null;
|
|
1540
|
+
|
|
1541
|
+
if (usageWithSource?.sourceDataPath) {
|
|
1542
|
+
const cleanedPath = cleanSourceDataPath(
|
|
1543
|
+
usageWithSource.sourceDataPath,
|
|
1544
|
+
);
|
|
1545
|
+
if (cleanedPath) {
|
|
1546
|
+
const pathMatch = findInAttributesMapForPath(
|
|
1547
|
+
cleanedPath,
|
|
1548
|
+
attributesMap,
|
|
1549
|
+
fullToShortPathMap,
|
|
1550
|
+
);
|
|
1551
|
+
if (pathMatch) {
|
|
1552
|
+
derivedFallbackPath = pathMatch;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
if (derivedFallbackPath) {
|
|
1558
|
+
resolvedPaths.set(condition.path, derivedFallbackPath);
|
|
1559
|
+
console.log(
|
|
1560
|
+
`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived expansion failed but sourceDataPath fallback resolved → "${derivedFallbackPath}"`,
|
|
1561
|
+
);
|
|
1562
|
+
} else {
|
|
1563
|
+
// Truly not controllable
|
|
1564
|
+
console.log(
|
|
1565
|
+
`[genFlowsFromConditionals] COMPOUND "${condition.path}" derived but no controllable sources and no sourceDataPath fallback → NOT controllable`,
|
|
1566
|
+
);
|
|
1567
|
+
allControllable = false;
|
|
1568
|
+
break;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
} else {
|
|
1572
|
+
// Not a derived variable - resolve directly
|
|
1573
|
+
// First try sourceDataPath from the usage (same as individual processing)
|
|
1574
|
+
let compoundResolvedPath: string | null = null;
|
|
1575
|
+
|
|
1576
|
+
const usageWithSource = usagesForPath?.find((u) => u.sourceDataPath);
|
|
1577
|
+
if (usageWithSource?.sourceDataPath) {
|
|
1578
|
+
const cleanedPath = cleanSourceDataPath(
|
|
1579
|
+
usageWithSource.sourceDataPath,
|
|
1580
|
+
);
|
|
1581
|
+
if (cleanedPath) {
|
|
1582
|
+
const pathMatch = findInAttributesMapForPath(
|
|
1583
|
+
cleanedPath,
|
|
1584
|
+
attributesMap,
|
|
1585
|
+
fullToShortPathMap,
|
|
1586
|
+
);
|
|
1587
|
+
if (pathMatch) {
|
|
1588
|
+
compoundResolvedPath = pathMatch;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
if (!compoundResolvedPath) {
|
|
1594
|
+
const resolution = resolvePathToControllable(
|
|
1595
|
+
condition.path,
|
|
1596
|
+
attributesMap,
|
|
1597
|
+
equivalentSignatureVariables,
|
|
1598
|
+
fullToShortPathMap,
|
|
1599
|
+
);
|
|
1600
|
+
|
|
1601
|
+
if (resolution.isControllable && resolution.resolvedPath) {
|
|
1602
|
+
compoundResolvedPath = resolution.resolvedPath;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
if (!compoundResolvedPath) {
|
|
1607
|
+
allControllable = false;
|
|
1608
|
+
break;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
resolvedPaths.set(condition.path, compoundResolvedPath);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
// Only create a flow if ALL paths are controllable
|
|
1616
|
+
if (allControllable && resolvedPaths.size > 0) {
|
|
1617
|
+
// If any conditions were expanded from derived variables, we need to build a custom flow
|
|
1618
|
+
if (expandedSources.size > 0) {
|
|
1619
|
+
const requiredValues: ExecutionFlow['requiredValues'] = [];
|
|
1620
|
+
|
|
1621
|
+
for (const condition of conditionSet) {
|
|
1622
|
+
const sources = expandedSources.get(condition.path);
|
|
1623
|
+
|
|
1624
|
+
if (sources) {
|
|
1625
|
+
// This condition was expanded - add all its sources
|
|
1626
|
+
// Determine the required value based on condition type and derivation operation
|
|
1627
|
+
const usagesForPath = conditionalUsages[condition.path];
|
|
1628
|
+
let expandedDerivedFrom = usagesForPath?.find(
|
|
1629
|
+
(u) => u.derivedFrom?.operation,
|
|
1630
|
+
)?.derivedFrom;
|
|
1631
|
+
|
|
1632
|
+
// Also check derivedVariables for intermediate derived variables
|
|
1633
|
+
if (!expandedDerivedFrom && derivedVariables?.[condition.path]) {
|
|
1634
|
+
expandedDerivedFrom = derivedVariables[condition.path];
|
|
1635
|
+
}
|
|
1636
|
+
const operation = expandedDerivedFrom?.operation;
|
|
1637
|
+
|
|
1638
|
+
for (const source of sources) {
|
|
1639
|
+
// For OR-derived truthy: ANY source truthy
|
|
1640
|
+
// For AND-derived truthy: ALL sources truthy
|
|
1641
|
+
// For negated: inverse
|
|
1642
|
+
let value: string;
|
|
1643
|
+
let comparison: ExecutionFlow['requiredValues'][0]['comparison'];
|
|
1644
|
+
|
|
1645
|
+
if (condition.conditionType === 'truthiness') {
|
|
1646
|
+
const isNegated = condition.isNegated === true;
|
|
1647
|
+
// For OR: truthy needs ANY source truthy, falsy needs ALL sources falsy
|
|
1648
|
+
// For AND: truthy needs ALL sources truthy, falsy needs ANY source falsy
|
|
1649
|
+
// In compound conditionals, we generate the truthy path by default
|
|
1650
|
+
// (the compound expression must be truthy)
|
|
1651
|
+
if (operation === 'or') {
|
|
1652
|
+
// For OR-derived, truthy means we need at least one source truthy
|
|
1653
|
+
// We'll use the first source as truthy (simplification)
|
|
1654
|
+
value = isNegated ? 'falsy' : 'truthy';
|
|
1655
|
+
} else if (operation === 'and') {
|
|
1656
|
+
// For AND-derived, truthy means ALL sources truthy
|
|
1657
|
+
value = isNegated ? 'falsy' : 'truthy';
|
|
1658
|
+
} else {
|
|
1659
|
+
value = isNegated ? 'falsy' : 'truthy';
|
|
1660
|
+
}
|
|
1661
|
+
comparison = isNegated ? 'falsy' : 'truthy';
|
|
1662
|
+
} else {
|
|
1663
|
+
value = 'truthy';
|
|
1664
|
+
comparison = 'truthy';
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
requiredValues.push({
|
|
1668
|
+
attributePath: source.path,
|
|
1669
|
+
value,
|
|
1670
|
+
comparison,
|
|
1671
|
+
valueType: 'boolean' as const,
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
} else {
|
|
1675
|
+
// This condition was resolved directly
|
|
1676
|
+
const resolvedPath = resolvedPaths.get(condition.path);
|
|
1677
|
+
if (resolvedPath) {
|
|
1678
|
+
let value: string;
|
|
1679
|
+
let comparison: ExecutionFlow['requiredValues'][0]['comparison'];
|
|
1680
|
+
|
|
1681
|
+
if (condition.conditionType === 'truthiness') {
|
|
1682
|
+
value = condition.isNegated ? 'falsy' : 'truthy';
|
|
1683
|
+
comparison = condition.isNegated ? 'falsy' : 'truthy';
|
|
1684
|
+
} else {
|
|
1685
|
+
value =
|
|
1686
|
+
condition.requiredValue?.toString() ??
|
|
1687
|
+
condition.comparedValues?.[0] ??
|
|
1688
|
+
'truthy';
|
|
1689
|
+
const op = condition.comparisonOperator;
|
|
1690
|
+
if (op === '>' || op === '>=') {
|
|
1691
|
+
comparison = 'length>';
|
|
1692
|
+
} else if (op === '<' || op === '<=') {
|
|
1693
|
+
comparison = 'length<';
|
|
1694
|
+
} else {
|
|
1695
|
+
comparison = 'equals';
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
requiredValues.push({
|
|
1700
|
+
attributePath: stripLengthSuffix(resolvedPath),
|
|
1701
|
+
value,
|
|
1702
|
+
comparison,
|
|
1703
|
+
valueType: inferValueType(value),
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
// Remove contradictory "falsy" values where a child path requires data
|
|
1710
|
+
const cleanedValues = removeContradictoryFalsyValues(requiredValues);
|
|
1711
|
+
|
|
1712
|
+
if (cleanedValues.length > 0) {
|
|
1713
|
+
const impact: ExecutionFlow['impact'] =
|
|
1714
|
+
compound.controlsJsxRendering ? 'high' : 'medium';
|
|
1715
|
+
|
|
1716
|
+
// Generate a combined ID from all paths + values
|
|
1717
|
+
const pathParts = cleanedValues
|
|
1718
|
+
.map((rv) => {
|
|
1719
|
+
const name = generateNameFromPath(rv.attributePath);
|
|
1720
|
+
const suffix =
|
|
1721
|
+
rv.comparison === 'truthy' || rv.comparison === 'falsy'
|
|
1722
|
+
? `-${rv.comparison}`
|
|
1723
|
+
: `-${rv.comparison}-${rv.value}`;
|
|
1724
|
+
return name.toLowerCase().replace(/\s+/g, '-') + suffix;
|
|
1725
|
+
})
|
|
1726
|
+
.join('-and-');
|
|
1727
|
+
|
|
1728
|
+
const compoundFlow: ExecutionFlow = {
|
|
1729
|
+
id: `${pathParts}`,
|
|
1730
|
+
name: generateNameFromPath(cleanedValues[0].attributePath),
|
|
1731
|
+
description: `When ${cleanedValues.map((rv) => describeRequiredValue(rv)).join(' and ')}`,
|
|
1732
|
+
impact,
|
|
1733
|
+
requiredValues: cleanedValues,
|
|
1734
|
+
sourceLocation: compound.sourceLocation,
|
|
1735
|
+
};
|
|
1736
|
+
|
|
1737
|
+
if (!seenFlowIds.has(compoundFlow.id)) {
|
|
1738
|
+
seenFlowIds.add(compoundFlow.id);
|
|
1739
|
+
flows.push(compoundFlow);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
} else {
|
|
1743
|
+
// No derived variables - use the original generateFlowFromCompound
|
|
1744
|
+
// Create a modified compound with just this condition set
|
|
1745
|
+
const modifiedCompound = {
|
|
1746
|
+
...compound,
|
|
1747
|
+
conditions: conditionSet,
|
|
1748
|
+
};
|
|
1749
|
+
const compoundFlow = generateFlowFromCompound(
|
|
1750
|
+
modifiedCompound,
|
|
1751
|
+
resolvedPaths,
|
|
1752
|
+
);
|
|
1753
|
+
if (compoundFlow && !seenFlowIds.has(compoundFlow.id)) {
|
|
1754
|
+
seenFlowIds.add(compoundFlow.id);
|
|
1755
|
+
flows.push(compoundFlow);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
// Process child component conditional usages
|
|
1763
|
+
// Translate child paths to parent paths and merge flows
|
|
1764
|
+
if (childComponentData) {
|
|
1765
|
+
for (const [childName, childData] of Object.entries(childComponentData)) {
|
|
1766
|
+
// First, resolve gating conditions to get required values that must be added to all child flows
|
|
1767
|
+
const gatingRequiredValues: Array<{
|
|
1768
|
+
attributePath: string;
|
|
1769
|
+
value: string;
|
|
1770
|
+
comparison:
|
|
1771
|
+
| 'truthy'
|
|
1772
|
+
| 'falsy'
|
|
1773
|
+
| 'equals'
|
|
1774
|
+
| 'length>'
|
|
1775
|
+
| 'length<'
|
|
1776
|
+
| 'exists'
|
|
1777
|
+
| 'not-exists';
|
|
1778
|
+
}> = [];
|
|
1779
|
+
|
|
1780
|
+
if (childData.gatingConditions) {
|
|
1781
|
+
for (const gatingCondition of childData.gatingConditions) {
|
|
1782
|
+
// Try to resolve via derivedFrom first
|
|
1783
|
+
let gatingPath = gatingCondition.path;
|
|
1784
|
+
if (gatingCondition.derivedFrom?.sourcePath) {
|
|
1785
|
+
gatingPath = gatingCondition.derivedFrom.sourcePath;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
// Fix 32: Handle comparison expressions like "activeTab === 'scenarios'"
|
|
1789
|
+
// Extract the variable name and the compared value
|
|
1790
|
+
const comparisonMatch = gatingPath.match(
|
|
1791
|
+
/^([a-zA-Z_][a-zA-Z0-9_]*)\s*(===?|!==?)\s*['"]?([^'"]+)['"]?$/,
|
|
1792
|
+
);
|
|
1793
|
+
if (comparisonMatch) {
|
|
1794
|
+
const [, varName, operator, comparedValue] = comparisonMatch;
|
|
1795
|
+
|
|
1796
|
+
// Try to resolve the variable name
|
|
1797
|
+
const varResolution = resolvePathToControllable(
|
|
1798
|
+
varName,
|
|
1799
|
+
attributesMap,
|
|
1800
|
+
equivalentSignatureVariables,
|
|
1801
|
+
fullToShortPathMap,
|
|
1802
|
+
);
|
|
1803
|
+
|
|
1804
|
+
// Only use controllable paths for gating conditions (whitelist approach).
|
|
1805
|
+
// Do NOT fall back to equivalentSignatureVariables because those may contain
|
|
1806
|
+
// uncontrollable paths like useState that cannot be mocked.
|
|
1807
|
+
let resolvedVarPath: string | null = null;
|
|
1808
|
+
if (varResolution.isControllable && varResolution.resolvedPath) {
|
|
1809
|
+
resolvedVarPath = varResolution.resolvedPath;
|
|
1810
|
+
}
|
|
1811
|
+
// Note: We intentionally do NOT fall back to equivalentSignatureVariables here
|
|
1812
|
+
// because that would allow uncontrollable paths (like useState) to be added
|
|
1813
|
+
// as gating conditions.
|
|
1814
|
+
|
|
1815
|
+
if (resolvedVarPath) {
|
|
1816
|
+
const isNegated = (gatingCondition as any).isNegated === true;
|
|
1817
|
+
const isNotEquals = operator === '!=' || operator === '!==';
|
|
1818
|
+
// Determine the effective value for this gating condition
|
|
1819
|
+
// If condition is "activeTab === 'scenarios'" and NOT negated, flow needs activeTab = 'scenarios'
|
|
1820
|
+
// If condition is "activeTab === 'scenarios'" and IS negated, flow needs activeTab != 'scenarios' (falsy/other value)
|
|
1821
|
+
// If condition is "activeTab !== 'scenarios'" and NOT negated, flow needs activeTab != 'scenarios'
|
|
1822
|
+
// XOR logic: isNegated XOR isNotEquals
|
|
1823
|
+
const needsExactValue = isNegated !== isNotEquals;
|
|
1824
|
+
|
|
1825
|
+
gatingRequiredValues.push({
|
|
1826
|
+
attributePath: resolvedVarPath,
|
|
1827
|
+
value: needsExactValue ? 'falsy' : comparedValue,
|
|
1828
|
+
comparison: needsExactValue ? 'falsy' : 'equals',
|
|
1829
|
+
});
|
|
1830
|
+
continue; // Skip to next gating condition
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// Fix 31: Handle compound gating conditions (containing && or ||)
|
|
1835
|
+
// e.g., "isEditMode && selectedScenario" should be parsed into individual paths
|
|
1836
|
+
const isAndExpression = gatingPath.includes(' && ');
|
|
1837
|
+
const isOrExpression = gatingPath.includes(' || ');
|
|
1838
|
+
const isCompoundExpression = isAndExpression || isOrExpression;
|
|
1839
|
+
|
|
1840
|
+
if (isCompoundExpression) {
|
|
1841
|
+
// Parse the compound expression into individual variable names
|
|
1842
|
+
// Split on && and || (with optional spaces)
|
|
1843
|
+
const parts = gatingPath.split(/\s*(?:&&|\|\|)\s*/);
|
|
1844
|
+
const isNegated = (gatingCondition as any).isNegated === true;
|
|
1845
|
+
|
|
1846
|
+
// Fix 37: Apply DeMorgan's law correctly for compound conditions
|
|
1847
|
+
// - !(A && B) = !A || !B: EITHER A is false OR B is false (can't know which)
|
|
1848
|
+
// - !(A || B) = !A && !B: BOTH must be false
|
|
1849
|
+
// - (A && B): BOTH must be true
|
|
1850
|
+
// - (A || B): EITHER is true (can't know which)
|
|
1851
|
+
//
|
|
1852
|
+
// We should only add gating requirements when we can definitively say
|
|
1853
|
+
// all parts must have the same value. This is true for:
|
|
1854
|
+
// - Non-negated &&: all parts must be truthy
|
|
1855
|
+
// - Negated ||: all parts must be falsy (DeMorgan: !(A || B) = !A && !B)
|
|
1856
|
+
//
|
|
1857
|
+
// We should NOT add gating requirements when either part could be true/false:
|
|
1858
|
+
// - Negated && (DeMorgan: !(A && B) = !A || !B): can't constrain both to falsy
|
|
1859
|
+
// - Non-negated ||: can't constrain both to truthy
|
|
1860
|
+
const shouldSkipGating =
|
|
1861
|
+
(isAndExpression && isNegated) || // !(A && B) - either could be falsy
|
|
1862
|
+
(isOrExpression && !isNegated); // (A || B) - either could be truthy
|
|
1863
|
+
|
|
1864
|
+
if (shouldSkipGating) {
|
|
1865
|
+
// Don't add gating requirements for this compound condition
|
|
1866
|
+
// The child flow's own requirements will determine what values are needed
|
|
1867
|
+
} else {
|
|
1868
|
+
for (const part of parts) {
|
|
1869
|
+
// Clean up the part (remove parentheses, negation, etc.)
|
|
1870
|
+
const cleanPart = part
|
|
1871
|
+
.replace(/^\(+|\)+$/g, '') // Remove leading/trailing parens
|
|
1872
|
+
.replace(/^!+/, '') // Remove leading negation
|
|
1873
|
+
.trim();
|
|
1874
|
+
|
|
1875
|
+
if (!cleanPart) continue;
|
|
1876
|
+
|
|
1877
|
+
// Try to resolve this individual path
|
|
1878
|
+
const partResolution = resolvePathToControllable(
|
|
1879
|
+
cleanPart,
|
|
1880
|
+
attributesMap,
|
|
1881
|
+
equivalentSignatureVariables,
|
|
1882
|
+
fullToShortPathMap,
|
|
1883
|
+
);
|
|
1884
|
+
|
|
1885
|
+
if (
|
|
1886
|
+
partResolution.isControllable &&
|
|
1887
|
+
partResolution.resolvedPath
|
|
1888
|
+
) {
|
|
1889
|
+
// For non-negated &&: all parts must be truthy
|
|
1890
|
+
// For negated ||: all parts must be falsy (DeMorgan: !(A || B) = !A && !B)
|
|
1891
|
+
gatingRequiredValues.push({
|
|
1892
|
+
attributePath: stripLengthSuffix(
|
|
1893
|
+
partResolution.resolvedPath,
|
|
1894
|
+
),
|
|
1895
|
+
value: isNegated ? 'falsy' : 'truthy',
|
|
1896
|
+
comparison: isNegated ? 'falsy' : 'truthy',
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
} else {
|
|
1902
|
+
// Simple gating condition (single path)
|
|
1903
|
+
// Resolve the gating path in parent context
|
|
1904
|
+
const gatingResolution = resolvePathToControllable(
|
|
1905
|
+
gatingPath,
|
|
1906
|
+
attributesMap,
|
|
1907
|
+
equivalentSignatureVariables,
|
|
1908
|
+
fullToShortPathMap,
|
|
1909
|
+
);
|
|
1910
|
+
|
|
1911
|
+
// Only use controllable paths for gating conditions (whitelist approach).
|
|
1912
|
+
// Do NOT fall back to equivalentSignatureVariables because those may contain
|
|
1913
|
+
// uncontrollable paths like useState that cannot be mocked.
|
|
1914
|
+
let resolvedGatingPath: string | null = null;
|
|
1915
|
+
if (
|
|
1916
|
+
gatingResolution.isControllable &&
|
|
1917
|
+
gatingResolution.resolvedPath
|
|
1918
|
+
) {
|
|
1919
|
+
resolvedGatingPath = gatingResolution.resolvedPath;
|
|
1920
|
+
}
|
|
1921
|
+
// Note: We intentionally do NOT fall back to equivalentSignatureVariables here
|
|
1922
|
+
// because that would allow uncontrollable paths (like useState) to be added
|
|
1923
|
+
// as gating conditions.
|
|
1924
|
+
|
|
1925
|
+
if (resolvedGatingPath) {
|
|
1926
|
+
// For truthiness conditions on gating, check if the condition is negated
|
|
1927
|
+
// e.g., ternary else branch: isError ? <ErrorView /> : <SuccessView />
|
|
1928
|
+
// SuccessView has isNegated: true, meaning it renders when isError is falsy
|
|
1929
|
+
const isNegated = (gatingCondition as any).isNegated === true;
|
|
1930
|
+
gatingRequiredValues.push({
|
|
1931
|
+
attributePath: resolvedGatingPath,
|
|
1932
|
+
value: isNegated ? 'falsy' : 'truthy',
|
|
1933
|
+
comparison: isNegated ? 'falsy' : 'truthy',
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
// Track which child usages are part of compound conditionals (to avoid duplicates)
|
|
1941
|
+
// Fix 33: Only skip usages that are part of compound conditionals, not all usages with chainIds
|
|
1942
|
+
const childCompoundChainIds = new Set(
|
|
1943
|
+
childData.compoundConditionals.map((c) => c.chainId).filter(Boolean),
|
|
1944
|
+
);
|
|
1945
|
+
|
|
1946
|
+
for (const [_path, usages] of Object.entries(
|
|
1947
|
+
childData.conditionalUsages,
|
|
1948
|
+
)) {
|
|
1949
|
+
for (const usage of usages) {
|
|
1950
|
+
// Skip usages that are part of compound conditionals (handled separately)
|
|
1951
|
+
// Fix 33: Only skip if the chainId is in the child's compound conditionals
|
|
1952
|
+
if (usage.chainId && childCompoundChainIds.has(usage.chainId)) {
|
|
1953
|
+
continue;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
// Determine the child path to translate
|
|
1957
|
+
let childPath = usage.path;
|
|
1958
|
+
|
|
1959
|
+
// If the usage has derivedFrom, use the source path instead
|
|
1960
|
+
if (usage.derivedFrom?.sourcePath) {
|
|
1961
|
+
childPath = usage.derivedFrom.sourcePath;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
// Translate the child path to a parent path
|
|
1965
|
+
let translatedPath = translateChildPathToParent(
|
|
1966
|
+
childPath,
|
|
1967
|
+
childData.equivalentSignatureVariables,
|
|
1968
|
+
equivalentSignatureVariables,
|
|
1969
|
+
childName,
|
|
1970
|
+
);
|
|
1971
|
+
|
|
1972
|
+
// If translation failed but we have sourceDataPath, try to extract the prop path from it
|
|
1973
|
+
// sourceDataPath format: "ChildName.signature[n].propPath.rest" → extract "propPath.rest"
|
|
1974
|
+
if (!translatedPath && usage.sourceDataPath) {
|
|
1975
|
+
const signatureMatch = usage.sourceDataPath.match(
|
|
1976
|
+
/\.signature\[\d+\]\.(.+)$/,
|
|
1977
|
+
);
|
|
1978
|
+
if (signatureMatch) {
|
|
1979
|
+
translatedPath = signatureMatch[1];
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
if (!translatedPath) {
|
|
1984
|
+
// Could not translate - skip this usage
|
|
1985
|
+
continue;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
// Now resolve the translated path in the parent context
|
|
1989
|
+
// First, try standard resolution
|
|
1990
|
+
const resolution = resolvePathToControllable(
|
|
1991
|
+
translatedPath,
|
|
1992
|
+
attributesMap,
|
|
1993
|
+
equivalentSignatureVariables,
|
|
1994
|
+
fullToShortPathMap,
|
|
1995
|
+
);
|
|
1996
|
+
|
|
1997
|
+
// Only create flows for controllable paths (whitelist approach).
|
|
1998
|
+
// If the path doesn't resolve to something in attributesMap, skip it.
|
|
1999
|
+
// This prevents creating flows for useState values which are not
|
|
2000
|
+
// controllable via mock data injection.
|
|
2001
|
+
let resolvedPath = resolution.resolvedPath;
|
|
2002
|
+
|
|
2003
|
+
if (!resolution.isControllable || !resolvedPath) {
|
|
2004
|
+
// Path is not controllable via standard resolution.
|
|
2005
|
+
// Try fallback: For useState values (cyScope*().functionCallReturnValue),
|
|
2006
|
+
// look for a related URL parameter like "varNameFromUrl" that might
|
|
2007
|
+
// control the initial state.
|
|
2008
|
+
//
|
|
2009
|
+
// Example: viewMode → cyScope20().functionCallReturnValue (useState value)
|
|
2010
|
+
// Fallback: viewModeFromUrl → segments[2] (URL param that initializes the useState)
|
|
2011
|
+
const useStateMatch = translatedPath.match(
|
|
2012
|
+
/^cyScope\d+\(\)\.functionCallReturnValue$/,
|
|
2013
|
+
);
|
|
2014
|
+
|
|
2015
|
+
if (useStateMatch) {
|
|
2016
|
+
// Find what variable this useState value corresponds to by looking
|
|
2017
|
+
// for entries like "varName": "cyScope20()" in equivalentSignatureVariables
|
|
2018
|
+
const useStatePattern = translatedPath.replace(
|
|
2019
|
+
/\.functionCallReturnValue$/,
|
|
2020
|
+
'',
|
|
2021
|
+
); // e.g., "cyScope20()"
|
|
2022
|
+
|
|
2023
|
+
// Find the variable name that maps to this useState
|
|
2024
|
+
let useStateVarName: string | null = null;
|
|
2025
|
+
for (const [varName, varPath] of Object.entries(
|
|
2026
|
+
equivalentSignatureVariables,
|
|
2027
|
+
)) {
|
|
2028
|
+
if (varPath === useStatePattern) {
|
|
2029
|
+
useStateVarName = varName;
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
if (useStateVarName) {
|
|
2035
|
+
// Look for a related URL param like "varNameFromUrl"
|
|
2036
|
+
const urlParamName = `${useStateVarName}FromUrl`;
|
|
2037
|
+
const urlParamPath = equivalentSignatureVariables[urlParamName];
|
|
2038
|
+
|
|
2039
|
+
if (urlParamPath) {
|
|
2040
|
+
// For useState values initialized from URL params, use the
|
|
2041
|
+
// URL param variable name directly (e.g., "viewModeFromUrl")
|
|
2042
|
+
// rather than fully resolving it. This keeps the path meaningful
|
|
2043
|
+
// for scenario generation and avoids overly generic paths like
|
|
2044
|
+
// "useParams().functionCallReturnValue.*".
|
|
2045
|
+
//
|
|
2046
|
+
// The flow will use the URL param name as the attributePath,
|
|
2047
|
+
// which gets properly resolved when generating mock data.
|
|
2048
|
+
resolvedPath = urlParamName;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
// Fallback 2: Try sourceEquivalencies to find the actual data source
|
|
2054
|
+
// This handles the case where props flow through useState but originate
|
|
2055
|
+
// from a mockable data source (e.g., API call, fetcher).
|
|
2056
|
+
//
|
|
2057
|
+
// Example: WorkoutsView receives `workouts` prop which in parent is stored
|
|
2058
|
+
// in useState, but ultimately comes from a Supabase query.
|
|
2059
|
+
// sourceEquivalencies tells us: "WorkoutsView().signature[0].workouts" → "createClient()...data"
|
|
2060
|
+
if (!resolvedPath && sourceEquivalencies) {
|
|
2061
|
+
// Build the child prop path to look up in sourceEquivalencies
|
|
2062
|
+
// Format: "ChildName().signature[0].propName"
|
|
2063
|
+
// First, find what prop this child path maps to
|
|
2064
|
+
let childPropName: string | null = null;
|
|
2065
|
+
for (const [varName, varPath] of Object.entries(
|
|
2066
|
+
childData.equivalentSignatureVariables,
|
|
2067
|
+
)) {
|
|
2068
|
+
// Check if childPath starts with this variable name
|
|
2069
|
+
// e.g., childPath = "workouts.length", varName = "workouts", varPath = "signature[0].workouts"
|
|
2070
|
+
if (
|
|
2071
|
+
childPath === varName ||
|
|
2072
|
+
childPath.startsWith(`${varName}.`)
|
|
2073
|
+
) {
|
|
2074
|
+
childPropName = varName;
|
|
2075
|
+
break;
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
if (childPropName) {
|
|
2080
|
+
// Build the full sourceEquivalencies key
|
|
2081
|
+
const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
|
|
2082
|
+
|
|
2083
|
+
const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
|
|
2084
|
+
if (sourceEquivEntry && sourceEquivEntry.length > 0) {
|
|
2085
|
+
const dataSourcePath = sourceEquivEntry[0].schemaPath;
|
|
2086
|
+
|
|
2087
|
+
// Check if this data source path is controllable
|
|
2088
|
+
const dataSourceResolution = resolvePathToControllable(
|
|
2089
|
+
dataSourcePath,
|
|
2090
|
+
attributesMap,
|
|
2091
|
+
equivalentSignatureVariables,
|
|
2092
|
+
fullToShortPathMap,
|
|
2093
|
+
);
|
|
2094
|
+
|
|
2095
|
+
if (
|
|
2096
|
+
dataSourceResolution.isControllable &&
|
|
2097
|
+
dataSourceResolution.resolvedPath
|
|
2098
|
+
) {
|
|
2099
|
+
// Preserve any suffix from the child path
|
|
2100
|
+
// e.g., childPath = "workouts.length" → suffix = ".length"
|
|
2101
|
+
const suffix = childPath.startsWith(`${childPropName}.`)
|
|
2102
|
+
? childPath.slice(childPropName.length)
|
|
2103
|
+
: '';
|
|
2104
|
+
resolvedPath = dataSourceResolution.resolvedPath + suffix;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
// If still not resolved after fallback, skip
|
|
2111
|
+
if (!resolvedPath) {
|
|
2112
|
+
continue;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
// Check for duplicates
|
|
2117
|
+
const normalizedPath = normalizePathForDeduplication(
|
|
2118
|
+
resolvedPath,
|
|
2119
|
+
fullToShortPathMap,
|
|
2120
|
+
);
|
|
2121
|
+
|
|
2122
|
+
if (seenNormalizedPaths.has(normalizedPath)) {
|
|
2123
|
+
continue;
|
|
2124
|
+
}
|
|
2125
|
+
seenNormalizedPaths.add(normalizedPath);
|
|
2126
|
+
|
|
2127
|
+
// Generate flows for this translated usage
|
|
2128
|
+
// Create a modified usage with the translated path for flow generation
|
|
2129
|
+
const translatedUsage: ConditionalUsage = {
|
|
2130
|
+
...usage,
|
|
2131
|
+
path: resolvedPath,
|
|
2132
|
+
};
|
|
2133
|
+
|
|
2134
|
+
const usageFlows = generateFlowsFromUsage(
|
|
2135
|
+
translatedUsage,
|
|
2136
|
+
resolvedPath,
|
|
2137
|
+
);
|
|
2138
|
+
|
|
2139
|
+
// Add gating conditions to each flow
|
|
2140
|
+
for (const flow of usageFlows) {
|
|
2141
|
+
// Add gating required values to the flow
|
|
2142
|
+
if (gatingRequiredValues.length > 0) {
|
|
2143
|
+
// Filter out any gating values that are already in the flow
|
|
2144
|
+
const existingPaths = new Set(
|
|
2145
|
+
flow.requiredValues.map((rv) => rv.attributePath),
|
|
2146
|
+
);
|
|
2147
|
+
const newGatingValues = gatingRequiredValues.filter(
|
|
2148
|
+
(gv) => !existingPaths.has(gv.attributePath),
|
|
2149
|
+
);
|
|
2150
|
+
flow.requiredValues = [
|
|
2151
|
+
...flow.requiredValues,
|
|
2152
|
+
...newGatingValues,
|
|
2153
|
+
];
|
|
2154
|
+
|
|
2155
|
+
// Update the flow ID to include gating conditions
|
|
2156
|
+
if (newGatingValues.length > 0) {
|
|
2157
|
+
const gatingIdPart = newGatingValues
|
|
2158
|
+
.map((gv) => `${gv.attributePath}-${gv.value}`)
|
|
2159
|
+
.join('-');
|
|
2160
|
+
flow.id = `${flow.id}-gated-${gatingIdPart}`;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
if (!seenFlowIds.has(flow.id)) {
|
|
2165
|
+
seenFlowIds.add(flow.id);
|
|
2166
|
+
flows.push(flow);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
// Process child's compound conditionals
|
|
2173
|
+
for (const compound of childData.compoundConditionals) {
|
|
2174
|
+
const resolvedPaths = new Map<string, string>();
|
|
2175
|
+
let allResolvable = true;
|
|
2176
|
+
|
|
2177
|
+
for (const condition of compound.conditions) {
|
|
2178
|
+
// Determine the child path to translate
|
|
2179
|
+
const childPath = condition.path;
|
|
2180
|
+
|
|
2181
|
+
// Translate the child path to a parent path
|
|
2182
|
+
const translatedPath = translateChildPathToParent(
|
|
2183
|
+
childPath,
|
|
2184
|
+
childData.equivalentSignatureVariables,
|
|
2185
|
+
equivalentSignatureVariables,
|
|
2186
|
+
childName,
|
|
2187
|
+
);
|
|
2188
|
+
|
|
2189
|
+
if (!translatedPath) {
|
|
2190
|
+
allResolvable = false;
|
|
2191
|
+
break;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
const resolution = resolvePathToControllable(
|
|
2195
|
+
translatedPath,
|
|
2196
|
+
attributesMap,
|
|
2197
|
+
equivalentSignatureVariables,
|
|
2198
|
+
fullToShortPathMap,
|
|
2199
|
+
);
|
|
2200
|
+
|
|
2201
|
+
// Only create flows for controllable paths (whitelist approach).
|
|
2202
|
+
// If the path doesn't resolve to something in attributesMap, skip it.
|
|
2203
|
+
// This prevents creating flows for useState values which are not
|
|
2204
|
+
// controllable via mock data injection.
|
|
2205
|
+
let resolvedPath = resolution.resolvedPath;
|
|
2206
|
+
|
|
2207
|
+
if (!resolution.isControllable || !resolvedPath) {
|
|
2208
|
+
// Path is not controllable via standard resolution.
|
|
2209
|
+
// Try fallback: For useState values (cyScope*().functionCallReturnValue),
|
|
2210
|
+
// look for a related URL parameter like "varNameFromUrl" that might
|
|
2211
|
+
// control the initial state.
|
|
2212
|
+
const useStateMatch = translatedPath.match(
|
|
2213
|
+
/^cyScope\d+\(\)\.functionCallReturnValue$/,
|
|
2214
|
+
);
|
|
2215
|
+
|
|
2216
|
+
if (useStateMatch) {
|
|
2217
|
+
const useStatePattern = translatedPath.replace(
|
|
2218
|
+
/\.functionCallReturnValue$/,
|
|
2219
|
+
'',
|
|
2220
|
+
);
|
|
2221
|
+
|
|
2222
|
+
// Find the variable name that maps to this useState
|
|
2223
|
+
let useStateVarName: string | null = null;
|
|
2224
|
+
for (const [varName, varPath] of Object.entries(
|
|
2225
|
+
equivalentSignatureVariables,
|
|
2226
|
+
)) {
|
|
2227
|
+
if (varPath === useStatePattern) {
|
|
2228
|
+
useStateVarName = varName;
|
|
2229
|
+
break;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
if (useStateVarName) {
|
|
2234
|
+
const urlParamName = `${useStateVarName}FromUrl`;
|
|
2235
|
+
const urlParamPath = equivalentSignatureVariables[urlParamName];
|
|
2236
|
+
|
|
2237
|
+
if (urlParamPath) {
|
|
2238
|
+
resolvedPath = urlParamName;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
if (!resolvedPath) {
|
|
2245
|
+
allResolvable = false;
|
|
2246
|
+
break;
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
resolvedPaths.set(condition.path, resolvedPath);
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
if (allResolvable && resolvedPaths.size > 0) {
|
|
2253
|
+
const compoundFlow = generateFlowFromCompound(
|
|
2254
|
+
compound,
|
|
2255
|
+
resolvedPaths,
|
|
2256
|
+
);
|
|
2257
|
+
if (compoundFlow) {
|
|
2258
|
+
// Add gating conditions to compound flow (same as regular usage flows)
|
|
2259
|
+
if (gatingRequiredValues.length > 0) {
|
|
2260
|
+
// Filter out any gating values that are already in the flow
|
|
2261
|
+
const existingPaths = new Set(
|
|
2262
|
+
compoundFlow.requiredValues.map((rv) => rv.attributePath),
|
|
2263
|
+
);
|
|
2264
|
+
const newGatingValues = gatingRequiredValues.filter(
|
|
2265
|
+
(gv) => !existingPaths.has(gv.attributePath),
|
|
2266
|
+
);
|
|
2267
|
+
compoundFlow.requiredValues = [
|
|
2268
|
+
...compoundFlow.requiredValues,
|
|
2269
|
+
...newGatingValues,
|
|
2270
|
+
];
|
|
2271
|
+
|
|
2272
|
+
// Update the flow ID to include gating conditions
|
|
2273
|
+
if (newGatingValues.length > 0) {
|
|
2274
|
+
const gatingIdPart = newGatingValues
|
|
2275
|
+
.map((gv) => `${gv.attributePath}-${gv.value}`)
|
|
2276
|
+
.join('-');
|
|
2277
|
+
compoundFlow.id = `${compoundFlow.id}-gated-${gatingIdPart}`;
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
if (!seenFlowIds.has(compoundFlow.id)) {
|
|
2282
|
+
seenFlowIds.add(compoundFlow.id);
|
|
2283
|
+
flows.push(compoundFlow);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
// Process child's jsxRenderingUsages (array.map flows)
|
|
2290
|
+
// This generates array variation flows (empty, few, many) for arrays rendered in child
|
|
2291
|
+
if (childData.jsxRenderingUsages) {
|
|
2292
|
+
for (const jsxUsage of childData.jsxRenderingUsages) {
|
|
2293
|
+
// Translate the child path to a parent path
|
|
2294
|
+
const translatedPath = translateChildPathToParent(
|
|
2295
|
+
jsxUsage.path,
|
|
2296
|
+
childData.equivalentSignatureVariables,
|
|
2297
|
+
equivalentSignatureVariables,
|
|
2298
|
+
childName,
|
|
2299
|
+
);
|
|
2300
|
+
|
|
2301
|
+
if (!translatedPath) {
|
|
2302
|
+
continue;
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
// Resolve to controllable path in parent context
|
|
2306
|
+
const resolution = resolvePathToControllable(
|
|
2307
|
+
translatedPath,
|
|
2308
|
+
attributesMap,
|
|
2309
|
+
equivalentSignatureVariables,
|
|
2310
|
+
fullToShortPathMap,
|
|
2311
|
+
);
|
|
2312
|
+
|
|
2313
|
+
let resolvedPath = resolution.resolvedPath;
|
|
2314
|
+
|
|
2315
|
+
// Try sourceEquivalencies fallback if not controllable
|
|
2316
|
+
if (!resolution.isControllable || !resolvedPath) {
|
|
2317
|
+
if (sourceEquivalencies) {
|
|
2318
|
+
// Build the sourceEquivalencies key
|
|
2319
|
+
// The child path (e.g., "workouts") maps to a prop path (e.g., "signature[0].workouts")
|
|
2320
|
+
let childPropName: string | null = null;
|
|
2321
|
+
for (const [varName, varPath] of Object.entries(
|
|
2322
|
+
childData.equivalentSignatureVariables,
|
|
2323
|
+
)) {
|
|
2324
|
+
if (
|
|
2325
|
+
jsxUsage.path === varName ||
|
|
2326
|
+
jsxUsage.path.startsWith(`${varName}.`)
|
|
2327
|
+
) {
|
|
2328
|
+
childPropName = varName;
|
|
2329
|
+
break;
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
if (childPropName) {
|
|
2334
|
+
const sourceEquivKey = `${childName}().signature[0].${childPropName}`;
|
|
2335
|
+
const sourceEquivEntry = sourceEquivalencies[sourceEquivKey];
|
|
2336
|
+
|
|
2337
|
+
if (sourceEquivEntry && sourceEquivEntry.length > 0) {
|
|
2338
|
+
const dataSourcePath = sourceEquivEntry[0].schemaPath;
|
|
2339
|
+
|
|
2340
|
+
const dataSourceResolution = resolvePathToControllable(
|
|
2341
|
+
dataSourcePath,
|
|
2342
|
+
attributesMap,
|
|
2343
|
+
equivalentSignatureVariables,
|
|
2344
|
+
fullToShortPathMap,
|
|
2345
|
+
);
|
|
2346
|
+
|
|
2347
|
+
if (
|
|
2348
|
+
dataSourceResolution.isControllable &&
|
|
2349
|
+
dataSourceResolution.resolvedPath
|
|
2350
|
+
) {
|
|
2351
|
+
resolvedPath = dataSourceResolution.resolvedPath;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
if (!resolvedPath) {
|
|
2359
|
+
continue;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
// Check for duplicates
|
|
2363
|
+
const normalizedPath = normalizePathForDeduplication(
|
|
2364
|
+
resolvedPath,
|
|
2365
|
+
fullToShortPathMap,
|
|
2366
|
+
);
|
|
2367
|
+
const dedupeKey = `${normalizedPath}:${jsxUsage.renderingType}`;
|
|
2368
|
+
if (seenNormalizedPaths.has(dedupeKey)) {
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
seenNormalizedPaths.add(dedupeKey);
|
|
2372
|
+
|
|
2373
|
+
// Generate array variation flows for array-map rendering
|
|
2374
|
+
if (jsxUsage.renderingType === 'array-map') {
|
|
2375
|
+
const baseName = generateNameFromPath(resolvedPath);
|
|
2376
|
+
const pathSlug = pathToSlug(resolvedPath);
|
|
2377
|
+
const exclusiveGroup = `array-length-${pathSlug}`;
|
|
2378
|
+
|
|
2379
|
+
// Empty array flow
|
|
2380
|
+
const emptyFlow: ExecutionFlow = {
|
|
2381
|
+
id: `${pathSlug}-empty-array`,
|
|
2382
|
+
name: `${baseName} Empty`,
|
|
2383
|
+
description: `When ${baseName.toLowerCase()} array is empty`,
|
|
2384
|
+
requiredValues: [
|
|
2385
|
+
{
|
|
2386
|
+
attributePath: resolvedPath,
|
|
2387
|
+
value: '0',
|
|
2388
|
+
comparison: 'length<',
|
|
2389
|
+
valueType: 'array',
|
|
2390
|
+
},
|
|
2391
|
+
...gatingRequiredValues,
|
|
2392
|
+
],
|
|
2393
|
+
impact: 'medium',
|
|
2394
|
+
exclusiveGroup,
|
|
2395
|
+
sourceLocation: jsxUsage.sourceLocation
|
|
2396
|
+
? {
|
|
2397
|
+
lineNumber: jsxUsage.sourceLocation.lineNumber,
|
|
2398
|
+
column: jsxUsage.sourceLocation.column,
|
|
2399
|
+
}
|
|
2400
|
+
: undefined,
|
|
2401
|
+
codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
|
|
2402
|
+
};
|
|
2403
|
+
|
|
2404
|
+
if (!seenFlowIds.has(emptyFlow.id)) {
|
|
2405
|
+
seenFlowIds.add(emptyFlow.id);
|
|
2406
|
+
flows.push(emptyFlow);
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
// Few items flow (1-3)
|
|
2410
|
+
const fewFlow: ExecutionFlow = {
|
|
2411
|
+
id: `${pathSlug}-few-items`,
|
|
2412
|
+
name: `${baseName} Few Items`,
|
|
2413
|
+
description: `When ${baseName.toLowerCase()} array has 1-3 items`,
|
|
2414
|
+
requiredValues: [
|
|
2415
|
+
{
|
|
2416
|
+
attributePath: resolvedPath,
|
|
2417
|
+
value: '3',
|
|
2418
|
+
comparison: 'length<',
|
|
2419
|
+
valueType: 'array',
|
|
2420
|
+
},
|
|
2421
|
+
...gatingRequiredValues,
|
|
2422
|
+
],
|
|
2423
|
+
impact: 'low',
|
|
2424
|
+
exclusiveGroup,
|
|
2425
|
+
sourceLocation: jsxUsage.sourceLocation
|
|
2426
|
+
? {
|
|
2427
|
+
lineNumber: jsxUsage.sourceLocation.lineNumber,
|
|
2428
|
+
column: jsxUsage.sourceLocation.column,
|
|
2429
|
+
}
|
|
2430
|
+
: undefined,
|
|
2431
|
+
codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
|
|
2432
|
+
};
|
|
2433
|
+
|
|
2434
|
+
if (!seenFlowIds.has(fewFlow.id)) {
|
|
2435
|
+
seenFlowIds.add(fewFlow.id);
|
|
2436
|
+
flows.push(fewFlow);
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
// Many items flow (10+)
|
|
2440
|
+
const manyFlow: ExecutionFlow = {
|
|
2441
|
+
id: `${pathSlug}-many-items`,
|
|
2442
|
+
name: `${baseName} Many Items`,
|
|
2443
|
+
description: `When ${baseName.toLowerCase()} array has many items`,
|
|
2444
|
+
requiredValues: [
|
|
2445
|
+
{
|
|
2446
|
+
attributePath: resolvedPath,
|
|
2447
|
+
value: '10',
|
|
2448
|
+
comparison: 'length>',
|
|
2449
|
+
valueType: 'array',
|
|
2450
|
+
},
|
|
2451
|
+
...gatingRequiredValues,
|
|
2452
|
+
],
|
|
2453
|
+
impact: 'low',
|
|
2454
|
+
exclusiveGroup,
|
|
2455
|
+
sourceLocation: jsxUsage.sourceLocation
|
|
2456
|
+
? {
|
|
2457
|
+
lineNumber: jsxUsage.sourceLocation.lineNumber,
|
|
2458
|
+
column: jsxUsage.sourceLocation.column,
|
|
2459
|
+
}
|
|
2460
|
+
: undefined,
|
|
2461
|
+
codeSnippet: jsxUsage.sourceLocation?.codeSnippet,
|
|
2462
|
+
};
|
|
2463
|
+
|
|
2464
|
+
if (!seenFlowIds.has(manyFlow.id)) {
|
|
2465
|
+
seenFlowIds.add(manyFlow.id);
|
|
2466
|
+
flows.push(manyFlow);
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
console.log(
|
|
2475
|
+
`[genFlowsFromConditionals] RESULT: ${flows.length} total flows generated`,
|
|
2476
|
+
);
|
|
2477
|
+
for (const flow of flows) {
|
|
2478
|
+
console.log(
|
|
2479
|
+
`[genFlowsFromConditionals] FLOW: id="${flow.id}" requiredValues=[${flow.requiredValues.map((rv) => `${rv.attributePath}=${rv.value}`).join(', ')}]`,
|
|
2480
|
+
);
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
return flows;
|
|
2484
|
+
}
|