@codeyam/codeyam-cli 0.1.0-staging.036391e → 0.1.0-staging.03e0fb2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +14 -14
- package/analyzer-template/packages/ai/index.ts +1 -0
- package/analyzer-template/packages/ai/package.json +1 -1
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +14 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +101 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +6 -0
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +102 -113
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +408 -13
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +70 -19
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/stripNullableMarkers.ts +35 -0
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +40 -13
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +32 -5
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +134 -2
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +359 -142
- package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
- package/analyzer-template/packages/analyze/src/lib/asts/nodes/getNodeType.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +18 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +50 -25
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +153 -76
- package/analyzer-template/packages/aws/package.json +10 -10
- 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/tables/debugReportsTable.ts +1 -1
- 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/userScenarioToDb.ts +1 -1
- 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/tables/debugReportsTable.d.ts +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/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/src/lib/fs/rsyncCopy.ts +121 -3
- package/analyzer-template/project/constructMockCode.ts +34 -7
- package/analyzer-template/project/orchestrateCapture.ts +4 -1
- package/analyzer-template/project/writeScenarioComponents.ts +76 -12
- package/background/src/lib/local/createLocalAnalyzer.js +1 -1
- package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
- package/background/src/lib/virtualized/project/constructMockCode.js +30 -7
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js +4 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +56 -7
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/codeyam-cli/scripts/apply-setup.js +1 -1
- package/codeyam-cli/src/cli.js +31 -24
- 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 +4 -2
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/baseline.js +2 -0
- package/codeyam-cli/src/commands/baseline.js.map +1 -1
- package/codeyam-cli/src/commands/debug.js +2 -0
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +31 -20
- package/codeyam-cli/src/commands/default.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 +95 -81
- package/codeyam-cli/src/commands/memory.js.map +1 -1
- package/codeyam-cli/src/commands/recapture.js +2 -0
- package/codeyam-cli/src/commands/recapture.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/test-startup.js +2 -0
- 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/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__/setupClaudeCodeSettings.test.js +128 -86
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.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 +90 -23
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +2 -2
- package/codeyam-cli/src/utils/install-skills.js +43 -63
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/labsAutoCheck.js +0 -29
- package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -1
- package/codeyam-cli/src/utils/npmVersionCheck.js +76 -0
- package/codeyam-cli/src/utils/npmVersionCheck.js.map +1 -0
- package/codeyam-cli/src/utils/progress.js +7 -0
- package/codeyam-cli/src/utils/progress.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__/contextBuilder.test.js +7 -8
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +0 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +97 -6
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +4 -6
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +3 -3
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -1
- package/codeyam-cli/src/utils/rules/__tests__/parser.test.js +83 -0
- package/codeyam-cli/src/utils/rules/__tests__/parser.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js +118 -0
- package/codeyam-cli/src/utils/rules/__tests__/pathMatcher.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js +72 -0
- package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +23 -23
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -1
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +76 -0
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/index.js +1 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -1
- package/codeyam-cli/src/utils/rules/parser.js +19 -4
- package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
- package/codeyam-cli/src/utils/rules/pathMatcher.js +34 -3
- package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -1
- package/codeyam-cli/src/utils/rules/rulePlacement.js +65 -0
- package/codeyam-cli/src/utils/rules/rulePlacement.js.map +1 -0
- package/codeyam-cli/src/utils/rules/ruleState.js +10 -10
- package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -1
- package/codeyam-cli/src/utils/rules/sourceFiles.js +43 -0
- package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +6 -6
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
- package/codeyam-cli/src/utils/serverState.js +37 -10
- package/codeyam-cli/src/utils/serverState.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -44
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js +159 -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/transcriptPruning.js +67 -0
- package/codeyam-cli/src/utils/transcriptPruning.js.map +1 -0
- package/codeyam-cli/src/utils/versionInfo.js +46 -0
- package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
- 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 +14 -3
- 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 +36 -7
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +11 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CA3JxPb7.js → CopyButton-CtmbP4Gl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-B86KKU7e.js → EntityItem-DlMph_Hm.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-B5ctlSYt.js → EntityTypeBadge-B-0PjGOU.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BqY8gDAW.js → EntityTypeIcon-DN9eiJAO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-ClaLpuOo.js → InlineSpinner-C1rIyZdV.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-BDhPilK7.js → InteractivePreview-rE_fI2h2.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-VeqEBv9v.js → LibraryFunctionPreview-CnatsCw2.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-Bs7Nn1Jr.js → LoadingDots-CSP6DZrh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-Bm3PmcCz.js → LogViewer-CMK8Q7yk.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C6PKeMYR.js → ReportIssueModal-TCV_HBjy.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Gq3Ocjo6.js → SafeScreenshot-CG2uh31y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BNLaXBHR.js → ScenarioViewer-CU_TDYd8.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CiwXDxLh.js → TruncatedFilePath-D7IoaWUW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-B3TDXxnk.js → _index-B8z7mjR-.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BtBFH820.js → activity.(_tab)-DZu78RI1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-Dm5RS9il.js +22 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-PttOB2SF.js → book-open-Bp5FLkd4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-TJp6ofnp.js → chevron-down-DQJA9f4o.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-JE9ZIoBl.js → chunk-JZWAC4HX-7VptmeIr.js} +9 -9
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CXhHQYrI.js → circle-check-B6C4LY9o.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-6y9ALfGT.js → copy-6nzYCu0G.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Ca9fAY46.js → createLucideIcon-D-QUFOwe.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C5lqplTC.js → dev.empty-DmzSmblj.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-n38keI1k.js → entity._sha._-C6PQhwY5.js} +9 -9
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js → entity._sha.scenarios._scenarioId.fullscreen-DVTcUnur.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DGgZjdFg.js → entity._sha_.create-scenario-BVgNO76F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-38yPijoD.js → entity._sha_.edit._scenarioId-C7ysA4Jq.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-BSHEfydn.js → entry.client-CU6EUArK.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DCPhhSMo.js → fileTableUtils-EWpfFU4X.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{files-0N0YJQv7.js → files-CrxAoWIL.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-DXnyr8uP.js → git-BldHtKeW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-CLmFdUae.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-ChN9-fAY.js → index-7-1FmlHo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-CcsFv748.js → index-DuYcwYp_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-CPPVOSWB.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-CTqLEAGU.js → loader-circle-BnDcD54R.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-717e346a.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-0wMU4KXe.js +93 -0
- package/codeyam-cli/src/webserver/build/client/assets/{pause-D6vreykR.js → pause-DhQX2g22.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-DqfSDjyQ.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-B8VUL8nl.js → search-DborVoKD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-BWunYSXt.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-CPoAg7Zo.js → simulations-BtrtCYJg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-BrCP7uQo.js → terminal-Bs4NC-VZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BZz2NjYa.js → triangle-alert-DTf3Jojp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DNwUduNu.js → useCustomSizes-D_bDZyDU.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-COky1GVF.js → useLastLogLine-DZp6rrQD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CpZgwliL.js → useReportContext-BsQb6rFd.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bv9JFvUO.js → useToast-BOur3mUv.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-DV1ykEI6.js → index-B8jmgmn2.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-9OU4lmvL.js +285 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
- package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
- package/codeyam-cli/templates/codeyam-memory-hook.sh +14 -14
- package/codeyam-cli/templates/{codeyam:memory.md → codeyam-memory.md} +16 -24
- package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +1 -3
- package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
- package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
- package/codeyam-cli/templates/hooks/staleness-check.sh +43 -0
- package/codeyam-cli/templates/prompts/conversation-guidance.txt +44 -0
- package/codeyam-cli/templates/prompts/conversation-prompt.txt +28 -0
- package/codeyam-cli/templates/prompts/interruption-prompt.txt +31 -0
- package/codeyam-cli/templates/prompts/stale-rules-prompt.txt +24 -0
- package/codeyam-cli/templates/rule-notification-hook.py +44 -17
- package/codeyam-cli/templates/rule-reflection-hook.py +88 -31
- package/codeyam-cli/templates/rules-instructions.md +45 -90
- package/package.json +12 -12
- package/packages/ai/index.js +1 -1
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +14 -0
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +78 -1
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
- package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
- package/packages/ai/src/lib/completionCall.js +0 -5
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +341 -10
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +59 -17
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructureChunking.js +30 -11
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +22 -3
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +97 -2
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +242 -81
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js +97 -0
- package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +17 -2
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/analyze/src/lib/asts/nodes/getNodeType.js +1 -0
- package/packages/analyze/src/lib/asts/nodes/getNodeType.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +11 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +42 -13
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +123 -67
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/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/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/utils/src/lib/fs/rsyncCopy.js +98 -3
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +8 -76
- package/codeyam-cli/src/commands/detect-universal-mocks.js +0 -118
- package/codeyam-cli/src/commands/detect-universal-mocks.js.map +0 -1
- package/codeyam-cli/src/commands/list.js +0 -31
- package/codeyam-cli/src/commands/list.js.map +0 -1
- package/codeyam-cli/src/commands/webapp-info.js +0 -146
- package/codeyam-cli/src/commands/webapp-info.js.map +0 -1
- package/codeyam-cli/src/utils/universal-mocks.js +0 -152
- package/codeyam-cli/src/utils/universal-mocks.js.map +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DfKzxuoe.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/globals-DoeDFXZN.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-CmBYA0PH.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-76786b8e.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/memory-CrNQfdMO.js +0 -76
- package/codeyam-cli/src/webserver/build/client/assets/root-QAY34PIo.js +0 -62
- package/codeyam-cli/src/webserver/build/client/assets/settings-eBI36Yv5.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BrcVrUEv.js +0 -260
- package/codeyam-cli/templates/codeyam-stop-hook.sh +0 -284
- package/codeyam-cli/templates/codeyam:diagnose.md +0 -805
- /package/codeyam-cli/src/webserver/build/client/assets/{api.labs-survey-l0sNRNKZ.js → api.rule-path-l0sNRNKZ.js} +0 -0
|
@@ -397,6 +397,7 @@ const SILENTLY_IGNORED_EQUIVALENCY_REASONS = new Set([
|
|
|
397
397
|
'transformed non-object function equivalency - implicit parent equivalency - rerouted via useCallback',
|
|
398
398
|
'transformed non-object function equivalency - Array.from() equivalency',
|
|
399
399
|
'Spread operator equivalency key update: Explicit array deconstruction equivalency value',
|
|
400
|
+
// 'transformed non-object function equivalency - Explicit array deconstruction equivalency value',
|
|
400
401
|
]);
|
|
401
402
|
|
|
402
403
|
export class ScopeDataStructure {
|
|
@@ -2797,6 +2798,8 @@ export class ScopeDataStructure {
|
|
|
2797
2798
|
usageEquivalency.scopeNodeName,
|
|
2798
2799
|
) as ScopeNode;
|
|
2799
2800
|
|
|
2801
|
+
if (!usageScopeNode) continue;
|
|
2802
|
+
|
|
2800
2803
|
// Guard against infinite recursion by tracking which paths we've already
|
|
2801
2804
|
// added from addComplexSourcePathVariables
|
|
2802
2805
|
if (
|
|
@@ -2876,6 +2879,8 @@ export class ScopeDataStructure {
|
|
|
2876
2879
|
usageEquivalency.scopeNodeName,
|
|
2877
2880
|
) as ScopeNode;
|
|
2878
2881
|
|
|
2882
|
+
if (!usageScopeNode) continue;
|
|
2883
|
+
|
|
2879
2884
|
// This is put in place to avoid propagating array functions like 'filter' through complex equivalencies
|
|
2880
2885
|
// but may cause problems if the funtion call is not on a known object (e.g. string or array)
|
|
2881
2886
|
if (
|
|
@@ -3355,6 +3360,22 @@ export class ScopeDataStructure {
|
|
|
3355
3360
|
* ensure all sub-paths of that variable are reflected under signature[N].
|
|
3356
3361
|
*/
|
|
3357
3362
|
private propagateParameterToSignaturePaths(scopeNode: ScopeNode) {
|
|
3363
|
+
// Helper: check if a type is a concrete scalar that cannot have sub-properties.
|
|
3364
|
+
const SCALAR_TYPES = new Set([
|
|
3365
|
+
'string',
|
|
3366
|
+
'number',
|
|
3367
|
+
'boolean',
|
|
3368
|
+
'bigint',
|
|
3369
|
+
'symbol',
|
|
3370
|
+
'void',
|
|
3371
|
+
'never',
|
|
3372
|
+
]);
|
|
3373
|
+
const isDefinitelyScalar = (type: string): boolean => {
|
|
3374
|
+
const parts = type.split('|').map((s) => s.trim());
|
|
3375
|
+
const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
|
|
3376
|
+
return base.length > 0 && base.every((b) => SCALAR_TYPES.has(b));
|
|
3377
|
+
};
|
|
3378
|
+
|
|
3358
3379
|
// Find variable → signature[N] equivalencies
|
|
3359
3380
|
for (const [varName, equivalencies] of Object.entries(
|
|
3360
3381
|
scopeNode.equivalencies,
|
|
@@ -3385,7 +3406,38 @@ export class ScopeDataStructure {
|
|
|
3385
3406
|
|
|
3386
3407
|
// Only add if the signature path doesn't already exist
|
|
3387
3408
|
if (!scopeNode.schema[sigKey]) {
|
|
3388
|
-
|
|
3409
|
+
// Check if this path represents variable conflation:
|
|
3410
|
+
// When a standalone variable (e.g., showWorkoutForm from useState)
|
|
3411
|
+
// appears as a sub-property of a scalar-typed ancestor (e.g.,
|
|
3412
|
+
// activity_type = "string"), it's from scope conflation, not real
|
|
3413
|
+
// property access. Block these while allowing legitimate built-in
|
|
3414
|
+
// accesses like string.length or string.slice.
|
|
3415
|
+
let isConflatedPath = false;
|
|
3416
|
+
let checkPos = signaturePath.length;
|
|
3417
|
+
while (true) {
|
|
3418
|
+
checkPos = sigKey.indexOf('.', checkPos + 1);
|
|
3419
|
+
if (checkPos === -1) break;
|
|
3420
|
+
const ancestorPath = sigKey.substring(0, checkPos);
|
|
3421
|
+
const ancestorType = scopeNode.schema[ancestorPath];
|
|
3422
|
+
if (ancestorType && isDefinitelyScalar(ancestorType)) {
|
|
3423
|
+
// Ancestor is scalar — check if the immediate sub-property
|
|
3424
|
+
// is also a standalone variable (indicating conflation)
|
|
3425
|
+
const afterDot = sigKey.substring(checkPos + 1);
|
|
3426
|
+
const nextSep = afterDot.search(/[.\[]/);
|
|
3427
|
+
const subPropName =
|
|
3428
|
+
nextSep === -1
|
|
3429
|
+
? afterDot
|
|
3430
|
+
: afterDot.substring(0, nextSep);
|
|
3431
|
+
if (scopeNode.schema[subPropName] !== undefined) {
|
|
3432
|
+
isConflatedPath = true;
|
|
3433
|
+
break;
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
|
|
3438
|
+
if (!isConflatedPath) {
|
|
3439
|
+
scopeNode.schema[sigKey] = scopeNode.schema[key];
|
|
3440
|
+
}
|
|
3389
3441
|
}
|
|
3390
3442
|
}
|
|
3391
3443
|
}
|
|
@@ -3898,25 +3950,116 @@ export class ScopeDataStructure {
|
|
|
3898
3950
|
return [source];
|
|
3899
3951
|
};
|
|
3900
3952
|
|
|
3901
|
-
|
|
3902
|
-
(
|
|
3903
|
-
if (entry.sourceCandidates.length === 0) return
|
|
3953
|
+
const acc = entries.reduce(
|
|
3954
|
+
(result, entry) => {
|
|
3955
|
+
if (entry.sourceCandidates.length === 0) return result;
|
|
3904
3956
|
const usages = entry.usages.filter(usageMatchesScope);
|
|
3905
3957
|
for (const usage of usages) {
|
|
3906
|
-
|
|
3958
|
+
result[usage.schemaPath] ||= [];
|
|
3907
3959
|
// Resolve each source candidate through the equivalency chain
|
|
3908
3960
|
for (const source of entry.sourceCandidates) {
|
|
3909
3961
|
const resolvedSources = resolveToSignature(source, new Set());
|
|
3910
|
-
|
|
3962
|
+
result[usage.schemaPath].push(...resolvedSources);
|
|
3911
3963
|
}
|
|
3912
3964
|
}
|
|
3913
|
-
return
|
|
3965
|
+
return result;
|
|
3914
3966
|
},
|
|
3915
3967
|
{} as Record<
|
|
3916
3968
|
string,
|
|
3917
3969
|
Pick<ScopeVariable, 'scopeNodeName' | 'schemaPath'>[]
|
|
3918
3970
|
>,
|
|
3919
3971
|
);
|
|
3972
|
+
|
|
3973
|
+
// Post-processing: enrich useState-backed sources with co-located external
|
|
3974
|
+
// function calls. When a useState value resolves to a setter variable that
|
|
3975
|
+
// lives in the same scope as a fetch/API call, that fetch is a data source.
|
|
3976
|
+
this.enrichUseStateSourcesWithCoLocatedCalls(acc);
|
|
3977
|
+
|
|
3978
|
+
return acc;
|
|
3979
|
+
}
|
|
3980
|
+
|
|
3981
|
+
/**
|
|
3982
|
+
* For each source that ends at a useState path, check if the setter was called
|
|
3983
|
+
* from a scope that also contains external function calls (like fetch).
|
|
3984
|
+
* If so, add those external calls as additional source candidates.
|
|
3985
|
+
*/
|
|
3986
|
+
private enrichUseStateSourcesWithCoLocatedCalls(
|
|
3987
|
+
acc: Record<string, Pick<ScopeVariable, 'scopeNodeName' | 'schemaPath'>[]>,
|
|
3988
|
+
) {
|
|
3989
|
+
const rootScopeName = this.scopeTreeManager.getRootName();
|
|
3990
|
+
const rootScope = this.scopeNodes[rootScopeName];
|
|
3991
|
+
if (!rootScope) return;
|
|
3992
|
+
|
|
3993
|
+
// Collect all descendants for each scope node
|
|
3994
|
+
const getAllDescendants = (
|
|
3995
|
+
node: import('./helpers/ScopeTreeManager').ScopeTreeNode,
|
|
3996
|
+
): Set<string> => {
|
|
3997
|
+
const names = new Set<string>([node.name]);
|
|
3998
|
+
for (const child of node.children) {
|
|
3999
|
+
for (const name of getAllDescendants(child)) {
|
|
4000
|
+
names.add(name);
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
return names;
|
|
4004
|
+
};
|
|
4005
|
+
|
|
4006
|
+
for (const [usagePath, sources] of Object.entries(acc)) {
|
|
4007
|
+
const additionalSources: Pick<
|
|
4008
|
+
ScopeVariable,
|
|
4009
|
+
'scopeNodeName' | 'schemaPath'
|
|
4010
|
+
>[] = [];
|
|
4011
|
+
|
|
4012
|
+
for (const source of sources) {
|
|
4013
|
+
// Check if this source is a useState-related terminal path
|
|
4014
|
+
// (e.g., useState(X).functionCallReturnValue[1] or useState(X).signature[0])
|
|
4015
|
+
if (!source.schemaPath.match(/^useState\([^)]*\)\./)) continue;
|
|
4016
|
+
|
|
4017
|
+
// Find the useState call from the source path
|
|
4018
|
+
const useStateCallMatch = source.schemaPath.match(
|
|
4019
|
+
/^(useState\([^)]*\))\./,
|
|
4020
|
+
);
|
|
4021
|
+
if (!useStateCallMatch) continue;
|
|
4022
|
+
const useStateCall = useStateCallMatch[1];
|
|
4023
|
+
|
|
4024
|
+
// Look in the root scope for the useState value equivalency
|
|
4025
|
+
// which tells us where the setter was called from
|
|
4026
|
+
const valuePath = `${useStateCall}.functionCallReturnValue[0]`;
|
|
4027
|
+
const valueEquivs = rootScope.equivalencies[valuePath];
|
|
4028
|
+
if (!valueEquivs) continue;
|
|
4029
|
+
|
|
4030
|
+
for (const equiv of valueEquivs) {
|
|
4031
|
+
// Find the scope where the setter was called
|
|
4032
|
+
const setterScopeName = equiv.scopeNodeName;
|
|
4033
|
+
const setterScopeTree =
|
|
4034
|
+
this.scopeTreeManager.findNode(setterScopeName);
|
|
4035
|
+
if (!setterScopeTree) continue;
|
|
4036
|
+
|
|
4037
|
+
// Get all descendant scope names from the setter scope
|
|
4038
|
+
const relatedScopes = getAllDescendants(setterScopeTree);
|
|
4039
|
+
|
|
4040
|
+
// Find external function calls in those scopes whose return values
|
|
4041
|
+
// are actually consumed (assigned to a variable). This excludes
|
|
4042
|
+
// fire-and-forget calls like analytics.track() or console.log().
|
|
4043
|
+
const coLocatedCalls = this.externalFunctionCalls.filter(
|
|
4044
|
+
(efc) =>
|
|
4045
|
+
relatedScopes.has(efc.callScope) &&
|
|
4046
|
+
efc.receivingVariableNames &&
|
|
4047
|
+
efc.receivingVariableNames.length > 0,
|
|
4048
|
+
);
|
|
4049
|
+
|
|
4050
|
+
for (const call of coLocatedCalls) {
|
|
4051
|
+
additionalSources.push({
|
|
4052
|
+
scopeNodeName: call.callScope,
|
|
4053
|
+
schemaPath: `${call.callSignature}.functionCallReturnValue`,
|
|
4054
|
+
});
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
if (additionalSources.length > 0) {
|
|
4060
|
+
acc[usagePath].push(...additionalSources);
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
3920
4063
|
}
|
|
3921
4064
|
|
|
3922
4065
|
getUsageEquivalencies(functionName?: string) {
|
|
@@ -4069,6 +4212,24 @@ export class ScopeDataStructure {
|
|
|
4069
4212
|
}
|
|
4070
4213
|
}
|
|
4071
4214
|
|
|
4215
|
+
// Helper: check if a type is a concrete scalar that cannot have sub-properties.
|
|
4216
|
+
// e.g., "string", "number | undefined", "boolean | null" are scalar.
|
|
4217
|
+
// "object", "array", "function", "unknown", "Workout", etc. are NOT scalar.
|
|
4218
|
+
const SCALAR_TYPES = new Set([
|
|
4219
|
+
'string',
|
|
4220
|
+
'number',
|
|
4221
|
+
'boolean',
|
|
4222
|
+
'bigint',
|
|
4223
|
+
'symbol',
|
|
4224
|
+
'void',
|
|
4225
|
+
'never',
|
|
4226
|
+
]);
|
|
4227
|
+
const isDefinitelyScalarType = (type: string): boolean => {
|
|
4228
|
+
const parts = type.split('|').map((s) => s.trim());
|
|
4229
|
+
const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
|
|
4230
|
+
return base.length > 0 && base.every((b) => SCALAR_TYPES.has(b));
|
|
4231
|
+
};
|
|
4232
|
+
|
|
4072
4233
|
// Propagate nested paths from variables to their signature equivalents
|
|
4073
4234
|
// e.g., if workouts = signature[0].workouts, then workouts[].title becomes
|
|
4074
4235
|
// signature[0].workouts[].title
|
|
@@ -4093,7 +4254,69 @@ export class ScopeDataStructure {
|
|
|
4093
4254
|
|
|
4094
4255
|
// Add to schema if not already present
|
|
4095
4256
|
if (!tempScopeNode.schema[signatureKey]) {
|
|
4096
|
-
|
|
4257
|
+
// Check if this path represents variable conflation:
|
|
4258
|
+
// When a standalone variable (e.g., showWorkoutForm from useState)
|
|
4259
|
+
// appears as a sub-property of a scalar-typed ancestor (e.g.,
|
|
4260
|
+
// activity_type = "string"), it's from scope conflation, not real
|
|
4261
|
+
// property access. Block these while allowing legitimate built-in
|
|
4262
|
+
// accesses like string.length or string.slice.
|
|
4263
|
+
let isConflatedPath = false;
|
|
4264
|
+
let checkPos = signaturePath.length;
|
|
4265
|
+
while (true) {
|
|
4266
|
+
checkPos = signatureKey.indexOf('.', checkPos + 1);
|
|
4267
|
+
if (checkPos === -1) break;
|
|
4268
|
+
const ancestorPath = signatureKey.substring(0, checkPos);
|
|
4269
|
+
const ancestorType = tempScopeNode.schema[ancestorPath];
|
|
4270
|
+
if (ancestorType && isDefinitelyScalarType(ancestorType)) {
|
|
4271
|
+
// Ancestor is scalar — check if the immediate sub-property
|
|
4272
|
+
// is also a standalone variable (indicating conflation)
|
|
4273
|
+
const afterDot = signatureKey.substring(checkPos + 1);
|
|
4274
|
+
const nextSep = afterDot.search(/[.\[]/);
|
|
4275
|
+
const subPropName =
|
|
4276
|
+
nextSep === -1 ? afterDot : afterDot.substring(0, nextSep);
|
|
4277
|
+
if (schema[subPropName] !== undefined) {
|
|
4278
|
+
isConflatedPath = true;
|
|
4279
|
+
break;
|
|
4280
|
+
}
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
|
|
4284
|
+
if (!isConflatedPath) {
|
|
4285
|
+
tempScopeNode.schema[signatureKey] = schema[schemaKey];
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
// Post-process: filter out conflated signature paths.
|
|
4293
|
+
// During phase 2 scope analysis, useState(false) conflation can create
|
|
4294
|
+
// bad paths like signature[0].mockWorkouts[].activity_type.showWorkoutForm
|
|
4295
|
+
// directly in scopeNode.schema. These flow through signatureInSchema into
|
|
4296
|
+
// tempScopeNode.schema without any guard. Filter them out here by checking:
|
|
4297
|
+
// 1. An ancestor in the path has a concrete scalar type (string, number, boolean, etc.)
|
|
4298
|
+
// 2. The immediate sub-property of that scalar ancestor is also a standalone
|
|
4299
|
+
// variable in the schema (indicating conflation, not a real property access)
|
|
4300
|
+
for (const key of Object.keys(tempScopeNode.schema)) {
|
|
4301
|
+
if (!key.startsWith('signature[')) continue;
|
|
4302
|
+
|
|
4303
|
+
// Walk through the path looking for scalar-typed ancestors
|
|
4304
|
+
let pos = 0;
|
|
4305
|
+
while (true) {
|
|
4306
|
+
pos = key.indexOf('.', pos + 1);
|
|
4307
|
+
if (pos === -1) break;
|
|
4308
|
+
const ancestorPath = key.substring(0, pos);
|
|
4309
|
+
const ancestorType = tempScopeNode.schema[ancestorPath];
|
|
4310
|
+
if (ancestorType && isDefinitelyScalarType(ancestorType)) {
|
|
4311
|
+
// Found a scalar ancestor — check if the sub-property name
|
|
4312
|
+
// is a standalone variable in the getSchema() result
|
|
4313
|
+
const afterDot = key.substring(pos + 1);
|
|
4314
|
+
const nextSep = afterDot.search(/[.\[]/);
|
|
4315
|
+
const subPropName =
|
|
4316
|
+
nextSep === -1 ? afterDot : afterDot.substring(0, nextSep);
|
|
4317
|
+
if (schema[subPropName] !== undefined) {
|
|
4318
|
+
delete tempScopeNode.schema[key];
|
|
4319
|
+
break;
|
|
4097
4320
|
}
|
|
4098
4321
|
}
|
|
4099
4322
|
}
|
|
@@ -4423,6 +4646,15 @@ export class ScopeDataStructure {
|
|
|
4423
4646
|
!equivalentValue.schemaPath.startsWith('signature[') && // not a signature path
|
|
4424
4647
|
!equivalentValue.schemaPath.endsWith('.functionCallReturnValue') // not already handled above
|
|
4425
4648
|
) {
|
|
4649
|
+
// Skip bare "returnValue" from child scopes — this is the child's return value,
|
|
4650
|
+
// not a meaningful data source path in the parent scope
|
|
4651
|
+
if (
|
|
4652
|
+
equivalentValue.schemaPath === 'returnValue' &&
|
|
4653
|
+
equivalentValue.scopeNodeName !==
|
|
4654
|
+
this.scopeTreeManager.getRootName()
|
|
4655
|
+
) {
|
|
4656
|
+
continue;
|
|
4657
|
+
}
|
|
4426
4658
|
// Add equivalency (will accumulate if multiple values for OR expressions)
|
|
4427
4659
|
addEquivalency(path, equivalentValue.schemaPath);
|
|
4428
4660
|
}
|
|
@@ -4824,9 +5056,109 @@ export class ScopeDataStructure {
|
|
|
4824
5056
|
// Replace cyScope placeholders in all external function call data
|
|
4825
5057
|
// This ensures call signatures and schema paths use actual callback text
|
|
4826
5058
|
// instead of internal cyScope names, preventing mock data merge conflicts.
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
5059
|
+
const rootScopeName = this.scopeTreeManager.getRootName();
|
|
5060
|
+
const rootSchema = this.scopeNodes[rootScopeName]?.schema ?? {};
|
|
5061
|
+
|
|
5062
|
+
return this.externalFunctionCalls.map((efc) => {
|
|
5063
|
+
const cleaned = this.cleanCyScopeFromFunctionCallInfo(efc);
|
|
5064
|
+
return this.filterConflatedExternalPaths(cleaned, rootSchema);
|
|
5065
|
+
});
|
|
5066
|
+
}
|
|
5067
|
+
|
|
5068
|
+
/**
|
|
5069
|
+
* Filters out conflated paths from external function call schemas.
|
|
5070
|
+
*
|
|
5071
|
+
* When multiple useState(false) calls create equivalency conflation during
|
|
5072
|
+
* Phase 1 analysis, standalone boolean state variables (like showWorkoutForm,
|
|
5073
|
+
* showGoalForm) can bleed into external function call schemas as sub-properties
|
|
5074
|
+
* of unrelated data fields (like data[].activity_type.showWorkoutForm).
|
|
5075
|
+
*
|
|
5076
|
+
* Detection: group sub-properties by parent path. If 2+ sub-properties of
|
|
5077
|
+
* the same parent all match standalone root scope variable names, treat them
|
|
5078
|
+
* as conflation artifacts and remove them.
|
|
5079
|
+
*/
|
|
5080
|
+
private filterConflatedExternalPaths(
|
|
5081
|
+
efc: FunctionCallInfo,
|
|
5082
|
+
rootSchema: Record<string, string>,
|
|
5083
|
+
): FunctionCallInfo {
|
|
5084
|
+
// Build a set of top-level root scope variable names (simple names, no dots/brackets)
|
|
5085
|
+
const topLevelRootVars = new Set<string>();
|
|
5086
|
+
for (const key of Object.keys(rootSchema)) {
|
|
5087
|
+
if (!key.includes('.') && !key.includes('[')) {
|
|
5088
|
+
topLevelRootVars.add(key);
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
|
|
5092
|
+
if (topLevelRootVars.size === 0) return efc;
|
|
5093
|
+
|
|
5094
|
+
// Group sub-property matches by their parent path.
|
|
5095
|
+
// For a path like "...data[].activity_type.showWorkoutForm",
|
|
5096
|
+
// parent = "...data[].activity_type", child = "showWorkoutForm"
|
|
5097
|
+
const parentToConflatedKeys = new Map<string, string[]>();
|
|
5098
|
+
|
|
5099
|
+
for (const key of Object.keys(efc.schema)) {
|
|
5100
|
+
const lastDot = key.lastIndexOf('.');
|
|
5101
|
+
if (lastDot === -1) continue;
|
|
5102
|
+
|
|
5103
|
+
const parent = key.substring(0, lastDot);
|
|
5104
|
+
const child = key.substring(lastDot + 1);
|
|
5105
|
+
|
|
5106
|
+
// Skip array access or function call patterns
|
|
5107
|
+
if (child.includes('[') || child.includes('(')) continue;
|
|
5108
|
+
|
|
5109
|
+
// Only consider paths inside array element chains (contains []).
|
|
5110
|
+
// Direct children of functionCallReturnValue are legitimate destructured
|
|
5111
|
+
// return values, not conflation. Conflation happens deeper in the chain
|
|
5112
|
+
// when array element fields get corrupted sub-properties.
|
|
5113
|
+
if (!parent.includes('[')) continue;
|
|
5114
|
+
|
|
5115
|
+
if (topLevelRootVars.has(child)) {
|
|
5116
|
+
if (!parentToConflatedKeys.has(parent)) {
|
|
5117
|
+
parentToConflatedKeys.set(parent, []);
|
|
5118
|
+
}
|
|
5119
|
+
parentToConflatedKeys.get(parent)!.push(key);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
|
|
5123
|
+
// Only filter when 2+ sub-properties of the same parent match root scope vars.
|
|
5124
|
+
// This threshold avoids false positives from coincidental name matches.
|
|
5125
|
+
const keysToRemove = new Set<string>();
|
|
5126
|
+
const parentsToRestore = new Set<string>();
|
|
5127
|
+
|
|
5128
|
+
for (const [parent, conflatedKeys] of parentToConflatedKeys) {
|
|
5129
|
+
if (conflatedKeys.length >= 2) {
|
|
5130
|
+
for (const key of conflatedKeys) {
|
|
5131
|
+
keysToRemove.add(key);
|
|
5132
|
+
}
|
|
5133
|
+
parentsToRestore.add(parent);
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
|
|
5137
|
+
if (keysToRemove.size === 0) return efc;
|
|
5138
|
+
|
|
5139
|
+
// Create a new schema without the conflated paths
|
|
5140
|
+
const newSchema: Record<string, string> = {};
|
|
5141
|
+
for (const [key, value] of Object.entries(efc.schema)) {
|
|
5142
|
+
if (keysToRemove.has(key)) continue;
|
|
5143
|
+
|
|
5144
|
+
// Restore parent type: if it was changed to "object" because of conflated
|
|
5145
|
+
// sub-properties, and now all those sub-properties are removed, change it
|
|
5146
|
+
// back to "unknown" (we don't know the original type)
|
|
5147
|
+
if (parentsToRestore.has(key) && value === 'object') {
|
|
5148
|
+
// Check if there are any remaining sub-properties
|
|
5149
|
+
const hasRemainingSubProps = Object.keys(efc.schema).some(
|
|
5150
|
+
(k) =>
|
|
5151
|
+
!keysToRemove.has(k) &&
|
|
5152
|
+
k !== key &&
|
|
5153
|
+
(k.startsWith(key + '.') || k.startsWith(key + '[')),
|
|
5154
|
+
);
|
|
5155
|
+
newSchema[key] = hasRemainingSubProps ? value : 'unknown';
|
|
5156
|
+
} else {
|
|
5157
|
+
newSchema[key] = value;
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
|
|
5161
|
+
return { ...efc, schema: newSchema };
|
|
4830
5162
|
}
|
|
4831
5163
|
|
|
4832
5164
|
/**
|
|
@@ -5119,6 +5451,10 @@ export class ScopeDataStructure {
|
|
|
5119
5451
|
getEnrichedConditionalUsages(): Record<string, EnrichedConditionalUsage[]> {
|
|
5120
5452
|
const enriched: Record<string, EnrichedConditionalUsage[]> = {};
|
|
5121
5453
|
|
|
5454
|
+
console.log(
|
|
5455
|
+
`[getEnrichedConditionalUsages] Processing ${Object.keys(this.rawConditionalUsages).length} conditional paths: [${Object.keys(this.rawConditionalUsages).join(', ')}]`,
|
|
5456
|
+
);
|
|
5457
|
+
|
|
5122
5458
|
for (const [path, usages] of Object.entries(this.rawConditionalUsages)) {
|
|
5123
5459
|
// Try to trace this path back to a data source
|
|
5124
5460
|
// First, try the root scope
|
|
@@ -5127,10 +5463,69 @@ export class ScopeDataStructure {
|
|
|
5127
5463
|
|
|
5128
5464
|
let sourceDataPath: string | undefined;
|
|
5129
5465
|
if (explanation.source) {
|
|
5130
|
-
|
|
5131
|
-
|
|
5466
|
+
const { scope, path: sourcePath } = explanation.source;
|
|
5467
|
+
|
|
5468
|
+
// Build initial path — avoid redundant prefix when path already contains the scope call
|
|
5469
|
+
let fullPath: string;
|
|
5470
|
+
if (sourcePath.startsWith(`${scope}(`)) {
|
|
5471
|
+
fullPath = sourcePath;
|
|
5472
|
+
} else {
|
|
5473
|
+
fullPath = `${scope}.${sourcePath}`;
|
|
5474
|
+
}
|
|
5475
|
+
|
|
5476
|
+
sourceDataPath = fullPath;
|
|
5477
|
+
console.log(
|
|
5478
|
+
`[getEnrichedConditionalUsages] "${path}" explainPath → scope="${scope}", sourcePath="${sourcePath}" → sourceDataPath="${sourceDataPath}"`,
|
|
5479
|
+
);
|
|
5480
|
+
} else {
|
|
5481
|
+
console.log(
|
|
5482
|
+
`[getEnrichedConditionalUsages] "${path}" explainPath → no source found`,
|
|
5483
|
+
);
|
|
5484
|
+
}
|
|
5485
|
+
|
|
5486
|
+
// If explainPath didn't find a useful external source (e.g., it traced to
|
|
5487
|
+
// useState or just to the component scope itself), check sourceEquivalencies
|
|
5488
|
+
// for an external function call source like a fetch call
|
|
5489
|
+
const hasExternalSource = sourceDataPath?.includes(
|
|
5490
|
+
'.functionCallReturnValue',
|
|
5491
|
+
);
|
|
5492
|
+
if (!hasExternalSource) {
|
|
5493
|
+
console.log(
|
|
5494
|
+
`[getEnrichedConditionalUsages] "${path}" no external source (sourceDataPath="${sourceDataPath}"), checking sourceEquivalencies fallback...`,
|
|
5495
|
+
);
|
|
5496
|
+
const sourceEquiv = this.getSourceEquivalencies();
|
|
5497
|
+
const returnValueKey = `returnValue.${path}`;
|
|
5498
|
+
const sources = sourceEquiv[returnValueKey];
|
|
5499
|
+
if (sources) {
|
|
5500
|
+
console.log(
|
|
5501
|
+
`[getEnrichedConditionalUsages] "${path}" sourceEquivalencies["${returnValueKey}"] has ${sources.length} sources: [${sources.map((s: { schemaPath: string }) => s.schemaPath).join(', ')}]`,
|
|
5502
|
+
);
|
|
5503
|
+
const externalSource = sources.find(
|
|
5504
|
+
(s: { schemaPath: string }) =>
|
|
5505
|
+
s.schemaPath.includes('.functionCallReturnValue') &&
|
|
5506
|
+
!s.schemaPath.startsWith('useState('),
|
|
5507
|
+
);
|
|
5508
|
+
if (externalSource) {
|
|
5509
|
+
console.log(
|
|
5510
|
+
`[getEnrichedConditionalUsages] "${path}" sourceEquivalencies fallback found external source: "${externalSource.schemaPath}"`,
|
|
5511
|
+
);
|
|
5512
|
+
sourceDataPath = externalSource.schemaPath;
|
|
5513
|
+
} else {
|
|
5514
|
+
console.log(
|
|
5515
|
+
`[getEnrichedConditionalUsages] "${path}" sourceEquivalencies fallback found no external function call source`,
|
|
5516
|
+
);
|
|
5517
|
+
}
|
|
5518
|
+
} else {
|
|
5519
|
+
console.log(
|
|
5520
|
+
`[getEnrichedConditionalUsages] "${path}" sourceEquivalencies["${returnValueKey}"] not found`,
|
|
5521
|
+
);
|
|
5522
|
+
}
|
|
5132
5523
|
}
|
|
5133
5524
|
|
|
5525
|
+
console.log(
|
|
5526
|
+
`[getEnrichedConditionalUsages] "${path}" FINAL sourceDataPath="${sourceDataPath ?? '(none)'}" (${usages.length} usages)`,
|
|
5527
|
+
);
|
|
5528
|
+
|
|
5134
5529
|
enriched[path] = usages.map((usage) => ({
|
|
5135
5530
|
...usage,
|
|
5136
5531
|
sourceDataPath,
|
|
@@ -14,21 +14,46 @@ const isStandaloneIndex = (s?: string) => !!s && STANDALONE_INDEX_RE.test(s);
|
|
|
14
14
|
// The regex matches any path ending with .length that has [] somewhere before it
|
|
15
15
|
const DYNAMIC_LENGTH_RE = /\[\].*\.length$/;
|
|
16
16
|
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
// Cache for type string analysis to avoid repeated split/filter operations.
|
|
18
|
+
// These functions are called multiple times per path segment across thousands of paths.
|
|
19
|
+
const typeAnalysisCache = new Map<
|
|
20
|
+
string,
|
|
21
|
+
{ isSkippable: boolean; baseType: string; isNullable: boolean }
|
|
22
|
+
>();
|
|
23
|
+
|
|
24
|
+
function getTypeAnalysis(t: string) {
|
|
25
|
+
const cached = typeAnalysisCache.get(t);
|
|
26
|
+
if (cached) return cached;
|
|
23
27
|
const parts = t.split('|').map((s) => s.trim());
|
|
24
28
|
const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
base[0] === '
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const result = {
|
|
30
|
+
isSkippable:
|
|
31
|
+
base.length === 1 &&
|
|
32
|
+
(base[0] === 'object' ||
|
|
33
|
+
base[0] === 'array' ||
|
|
34
|
+
base[0] === 'function' ||
|
|
35
|
+
base[0] === 'unknown'),
|
|
36
|
+
baseType: base[0],
|
|
37
|
+
isNullable: parts.includes('undefined') || parts.includes('null'),
|
|
38
|
+
};
|
|
39
|
+
typeAnalysisCache.set(t, result);
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Treat these as structural placeholders (don't commit them as concrete leaves)
|
|
44
|
+
function isSkippableLeafType(t: string) {
|
|
45
|
+
return getTypeAnalysis(t).isSkippable;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Extract the base structural type from a potentially nullable type string.
|
|
49
|
+
// e.g., 'object | undefined' → 'object', 'array | null' → 'array'
|
|
50
|
+
function getBaseSkippableType(t: string): string {
|
|
51
|
+
return getTypeAnalysis(t).baseType;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if a type string has nullable annotations (| undefined or | null)
|
|
55
|
+
function isNullableType(t: string): boolean {
|
|
56
|
+
return getTypeAnalysis(t).isNullable;
|
|
32
57
|
}
|
|
33
58
|
|
|
34
59
|
// Matches paths containing [][] — e.g., "items[][]" or "items[][].text"
|
|
@@ -317,15 +342,41 @@ export default function convertDotNotation(
|
|
|
317
342
|
cursor[key] = typ;
|
|
318
343
|
} else {
|
|
319
344
|
// Structural/placeholder terminal
|
|
320
|
-
|
|
345
|
+
const nullable = isNullableType(typ);
|
|
346
|
+
const baseType = getBaseSkippableType(typ);
|
|
347
|
+
|
|
348
|
+
if (baseType === 'array') {
|
|
321
349
|
if (!Array.isArray(cursor[key])) cursor[key] = [];
|
|
350
|
+
if (nullable) {
|
|
351
|
+
(cursor[key] as any)._nullable = true;
|
|
352
|
+
}
|
|
322
353
|
} else if (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
354
|
+
baseType === 'object' ||
|
|
355
|
+
baseType === 'function' ||
|
|
356
|
+
baseType === 'unknown'
|
|
326
357
|
) {
|
|
327
|
-
if (
|
|
328
|
-
|
|
358
|
+
if (nullable) {
|
|
359
|
+
// Nullable object: ensure it's an actual object (not a string
|
|
360
|
+
// placeholder) so _nullable can be set and child paths can
|
|
361
|
+
// populate properties on it.
|
|
362
|
+
if (
|
|
363
|
+
cursor[key] === undefined ||
|
|
364
|
+
typeof cursor[key] === 'string'
|
|
365
|
+
) {
|
|
366
|
+
cursor[key] = {};
|
|
367
|
+
}
|
|
368
|
+
if (
|
|
369
|
+
typeof cursor[key] === 'object' &&
|
|
370
|
+
cursor[key] !== null &&
|
|
371
|
+
!Array.isArray(cursor[key])
|
|
372
|
+
) {
|
|
373
|
+
(cursor[key] as any)._nullable = true;
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
// Non-nullable: preserve existing behavior (string placeholder)
|
|
377
|
+
if (cursor[key] === undefined) {
|
|
378
|
+
cursor[key] = typ;
|
|
379
|
+
}
|
|
329
380
|
}
|
|
330
381
|
}
|
|
331
382
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively strips `_nullable` keys from LLM-generated mock data.
|
|
3
|
+
*
|
|
4
|
+
* The `_nullable` marker is an internal CodeYam concept used in type definitions
|
|
5
|
+
* to indicate that a field can be null/undefined. The LLM sometimes includes
|
|
6
|
+
* these markers in its generated scenario data, which causes runtime errors
|
|
7
|
+
* when code iterates over object keys (e.g., `Object.keys(importedBy)` picks
|
|
8
|
+
* up `_nullable` as a key alongside real data).
|
|
9
|
+
*
|
|
10
|
+
* This function mutates the input object in-place, consistent with other
|
|
11
|
+
* post-processing helpers like `convertNullToUndefinedBySchema`.
|
|
12
|
+
*/
|
|
13
|
+
export default function stripNullableMarkers(
|
|
14
|
+
data: Record<string, unknown>,
|
|
15
|
+
): void {
|
|
16
|
+
if (data == null || typeof data !== 'object') return;
|
|
17
|
+
|
|
18
|
+
// Delete _nullable from this level
|
|
19
|
+
if ('_nullable' in data) {
|
|
20
|
+
delete data._nullable;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Recurse into nested objects and arrays
|
|
24
|
+
for (const value of Object.values(data)) {
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
for (const item of value) {
|
|
27
|
+
if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
|
|
28
|
+
stripNullableMarkers(item as Record<string, unknown>);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} else if (value !== null && typeof value === 'object') {
|
|
32
|
+
stripNullableMarkers(value as Record<string, unknown>);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|