@codeyam/codeyam-cli 0.1.0-staging.7c30edc → 0.1.0-staging.8421896
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +1 -1
- package/analyzer-template/packages/ai/index.ts +1 -0
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +14 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +29 -18
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +18 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +50 -25
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +153 -76
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +108 -2
- package/codeyam-cli/scripts/apply-setup.js +1 -1
- package/codeyam-cli/src/commands/analyze.js +2 -2
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +6 -1
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/setup-simulations.js +1 -1
- package/codeyam-cli/src/commands/verify.js +12 -2
- package/codeyam-cli/src/commands/verify.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +11 -11
- package/codeyam-cli/src/utils/backgroundServer.js +7 -1
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +2 -2
- package/codeyam-cli/src/utils/install-skills.js +13 -13
- package/codeyam-cli/src/utils/labsAutoCheck.js +0 -29
- package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +7 -7
- package/codeyam-cli/src/webserver/backgroundServer.js +0 -7
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CQ-wF3Tv.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-B86KKU7e.js → EntityItem-HdckCi0m.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-B5ctlSYt.js → EntityTypeBadge-Dh5RJMOE.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BqY8gDAW.js → EntityTypeIcon-BnjjBHJu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-ClaLpuOo.js → InlineSpinner-CUSfu6W5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-BDhPilK7.js → InteractivePreview-Coll1aD6.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-VeqEBv9v.js → LibraryFunctionPreview-lYMY8h-y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-Bs7Nn1Jr.js → LoadingDots-ay8XeA59.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-Bm3PmcCz.js → LogViewer-Dpul1_ik.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C6PKeMYR.js → ReportIssueModal-CRBCfV2W.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-Gq3Ocjo6.js → SafeScreenshot-DRTFDNFt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BNLaXBHR.js → ScenarioViewer-d6PSFxhS.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CiwXDxLh.js → TruncatedFilePath-DDEOQ6Iw.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-B3TDXxnk.js → _index-CkziGg5F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BtBFH820.js → activity.(_tab)-B2v1pm9w.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-CN61MOMa.js → agent-transcripts-BXIaK8Md.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-PttOB2SF.js → book-open-qbapxy6o.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-TJp6ofnp.js → chevron-down-C-mKrwr1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-JE9ZIoBl.js → chunk-JZWAC4HX-BAvUl1nT.js} +8 -8
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CXhHQYrI.js → circle-check-DlrT-SzI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-6y9ALfGT.js → copy-clIxnCqQ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Ca9fAY46.js → createLucideIcon-B931Etud.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C5lqplTC.js → dev.empty-BoPM6KnE.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-oVRMh9Hl.js +16 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js → entity._sha.scenarios._scenarioId.fullscreen-BjyzwQ7H.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DGgZjdFg.js → entity._sha_.create-scenario-DxuyDmZA.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-38yPijoD.js → entity._sha_.edit._scenarioId-DESSZGQp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-BSHEfydn.js → entry.client-D5Yb90Ad.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DCPhhSMo.js → fileTableUtils-DuObVYgh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{files-0N0YJQv7.js → files-CDfz4Y-i.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-DXnyr8uP.js → git-D6jOlDQw.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-CKT08Djd.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-ChN9-fAY.js → index-DvOt1KIt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-CcsFv748.js → index-WfQFdoWK.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-BbGyC1RY.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-CTqLEAGU.js → loader-circle-Bb7Y9k5O.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-fd06e67a.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-BXebUPaL.js +78 -0
- package/codeyam-cli/src/webserver/build/client/assets/{pause-D6vreykR.js → pause-DaAHX2on.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-F7e6dvys.js → root-CvNE9MaT.js} +9 -9
- package/codeyam-cli/src/webserver/build/client/assets/{search-B8VUL8nl.js → search-DIqAPIrO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-BejnUJ6R.js → settings-DCIzBZM9.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-CPoAg7Zo.js → simulations-C6n_fNQY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-BrCP7uQo.js → terminal-CmPsszJy.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BZz2NjYa.js → triangle-alert-Beg-oV50.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DNwUduNu.js → useCustomSizes-D7TLbP3M.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-COky1GVF.js → useLastLogLine-Ce5rnai3.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CpZgwliL.js → useReportContext-B4D3wj27.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bv9JFvUO.js → useToast-BDt_-DnY.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-CFKHuovO.js → index-DDr9Cp9M.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DjwiujaU.js +257 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/templates/{codeyam:debug.md → codeyam-debug.md} +1 -1
- package/codeyam-cli/templates/{codeyam:diagnose.md → codeyam-diagnose.md} +1 -1
- package/codeyam-cli/templates/{codeyam:memory.md → codeyam-memory.md} +2 -2
- package/codeyam-cli/templates/{codeyam:new-rule.md → codeyam-new-rule.md} +1 -1
- package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +1 -1
- package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
- package/package.json +9 -9
- 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/dataStructure/helpers/convertDotNotation.js +24 -16
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +11 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +42 -13
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +123 -67
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CA3JxPb7.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/api.labs-survey-l0sNRNKZ.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha._-n38keI1k.js +0 -23
- package/codeyam-cli/src/webserver/build/client/assets/globals-CuCsBc3b.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-CB3MGcys.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-de6ccaf4.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/memory-DCA-kLYt.js +0 -81
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BQe9Dh4p.js +0 -260
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-02-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-02-13T11:24:56.052Z",
|
|
3
|
+
"buildTime": 1770981896052,
|
|
4
|
+
"gitCommit": "84218967703e4bac51f7219e6e447b209b350d5f",
|
|
5
5
|
"nodeVersion": "v20.20.0",
|
|
6
|
-
"contentHash": "
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
6
|
+
"contentHash": "4e94e73e9be6ff27f80a8345110fe1d31d9863861a8966e4b17887ad7c6eff67",
|
|
7
|
+
"buildNumber": 619,
|
|
8
|
+
"semanticVersion": "0.1.619",
|
|
9
|
+
"version": "0.1.619 (2026-02-13T11:24+4e94e73)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[2/
|
|
3
|
-
[2/
|
|
2
|
+
[2/13/2026, 11:24:55 AM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[2/13/2026, 11:24:55 AM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[2/
|
|
6
|
+
[2/13/2026, 11:24:56 AM] Merged dependencies into root package.json
|
|
7
7
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@aws-sdk/client-cloudwatch-logs": "^3.980.0",
|
|
11
|
-
"@aws-sdk/client-cloudfront": "^3.
|
|
11
|
+
"@aws-sdk/client-cloudfront": "^3.985.0",
|
|
12
12
|
"@aws-sdk/client-codebuild": "^3.948.0",
|
|
13
13
|
"@aws-sdk/client-dynamodb": "^3.956.0",
|
|
14
14
|
"@aws-sdk/client-ec2": "^3.899.0",
|
|
@@ -43,6 +43,7 @@ export { default as isolateScopes } from './src/lib/isolateScopes';
|
|
|
43
43
|
export {
|
|
44
44
|
default as analyzeScope,
|
|
45
45
|
destroyWorkerPool,
|
|
46
|
+
skipWorkerPool,
|
|
46
47
|
} from './src/lib/analyzeScope';
|
|
47
48
|
export { default as logOrderedMap } from './src/lib/logOrderedMap';
|
|
48
49
|
export {
|
|
@@ -50,6 +50,19 @@ let workerPool: Piscina<
|
|
|
50
50
|
AnalyzeScopeWorkerOutput
|
|
51
51
|
> | null = null;
|
|
52
52
|
let workerPoolDestroyed = false;
|
|
53
|
+
let workerPoolSkipped = false;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Skip worker pool initialization for the current session.
|
|
57
|
+
*
|
|
58
|
+
* The worker thread creates its own ProjectAnalyzer (ts.Program), which takes
|
|
59
|
+
* 50-70s — far longer than the actual entity processing (<2s for typical batches).
|
|
60
|
+
* When the entity count is small, running analyzeScopeLocal on the main thread
|
|
61
|
+
* reuses the existing ProjectAnalyzer and avoids this overhead entirely.
|
|
62
|
+
*/
|
|
63
|
+
export function skipWorkerPool() {
|
|
64
|
+
workerPoolSkipped = true;
|
|
65
|
+
}
|
|
53
66
|
|
|
54
67
|
/**
|
|
55
68
|
* Check if we're in Node.js main thread
|
|
@@ -108,6 +121,7 @@ function ensureWorkerPool() {
|
|
|
108
121
|
'analyzeScope should not be called after data structure preparation completes.',
|
|
109
122
|
);
|
|
110
123
|
}
|
|
124
|
+
if (workerPoolSkipped) return;
|
|
111
125
|
if (workerPool !== null) return;
|
|
112
126
|
|
|
113
127
|
// Only initialize worker pool in Node.js environment
|
|
@@ -14,35 +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;
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
// Extract the base structural type from a potentially nullable type string.
|
|
35
49
|
// e.g., 'object | undefined' → 'object', 'array | null' → 'array'
|
|
36
50
|
function getBaseSkippableType(t: string): string {
|
|
37
|
-
|
|
38
|
-
const base = parts.filter((s) => s !== 'undefined' && s !== 'null');
|
|
39
|
-
return base[0];
|
|
51
|
+
return getTypeAnalysis(t).baseType;
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
// Check if a type string has nullable annotations (| undefined or | null)
|
|
43
55
|
function isNullableType(t: string): boolean {
|
|
44
|
-
|
|
45
|
-
return parts.includes('undefined') || parts.includes('null');
|
|
56
|
+
return getTypeAnalysis(t).isNullable;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
// Matches paths containing [][] — e.g., "items[][]" or "items[][].text"
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
getCompoundConditionals,
|
|
19
19
|
getChildBoundaryGatingConditions,
|
|
20
20
|
getJsxRenderingUsages,
|
|
21
|
+
skipWorkerPool,
|
|
21
22
|
} from '~codeyam/ai';
|
|
22
23
|
import type { AnalysisOptions } from '../analyzeEntities';
|
|
23
24
|
|
|
@@ -271,6 +272,23 @@ export default async function prepareEntityDataStructures(
|
|
|
271
272
|
};
|
|
272
273
|
|
|
273
274
|
const entities = Array.from(allEntities);
|
|
275
|
+
|
|
276
|
+
// The worker thread creates its own ProjectAnalyzer (ts.Program) on first use,
|
|
277
|
+
// which takes 50-70s. For small entity counts the overhead far exceeds the actual
|
|
278
|
+
// processing time (<2s). Skip the worker and run on the main thread instead,
|
|
279
|
+
// reusing the existing ProjectAnalyzer.
|
|
280
|
+
const entitiesNeedingGeneration = entities.filter(
|
|
281
|
+
(e) =>
|
|
282
|
+
!e.metadata?.isolatedDataStructure || options.force || options.forceAll,
|
|
283
|
+
).length;
|
|
284
|
+
const WORKER_ENTITY_THRESHOLD = 500;
|
|
285
|
+
if (entitiesNeedingGeneration < WORKER_ENTITY_THRESHOLD) {
|
|
286
|
+
console.log(
|
|
287
|
+
`CodeYam: Skipping worker thread for DS prep (${entitiesNeedingGeneration} entities < ${WORKER_ENTITY_THRESHOLD} threshold)`,
|
|
288
|
+
);
|
|
289
|
+
skipWorkerPool();
|
|
290
|
+
}
|
|
291
|
+
|
|
274
292
|
const sequential =
|
|
275
293
|
DEBUG_SEQUENTIAL_EXECUTION || options.sequentialDataStructurePrep;
|
|
276
294
|
|
|
@@ -353,8 +353,6 @@ function processCall(
|
|
|
353
353
|
// Preprocess to filter signatures and extract functionCallReturnValue
|
|
354
354
|
let preprocessedSchema = preprocessSchemaForMocks(mergedSchema);
|
|
355
355
|
|
|
356
|
-
const functionNames: string[] = [];
|
|
357
|
-
|
|
358
356
|
const isFunctionNameWithoutFunction = (
|
|
359
357
|
path: string,
|
|
360
358
|
functionName: string,
|
|
@@ -439,31 +437,58 @@ function processCall(
|
|
|
439
437
|
}
|
|
440
438
|
}
|
|
441
439
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
440
|
+
// Two-pass function name filtering to avoid O(k²) retroactive deletion.
|
|
441
|
+
// Pass 1: Discover all unique function names from paths ending with ')'
|
|
442
|
+
const functionNameSet = new Set<string>();
|
|
443
|
+
const schemaKeys = Object.keys(preprocessedSchema);
|
|
444
|
+
for (const path of schemaKeys) {
|
|
445
|
+
if (path.endsWith(')')) {
|
|
446
|
+
const pathParts = splitOutsideParenthesesAndArrays(path);
|
|
447
|
+
const functionName = joinParenthesesAndArrays([
|
|
448
|
+
...pathParts.slice(0, -1),
|
|
449
|
+
pathParts[pathParts.length - 1].split('(')[0],
|
|
450
|
+
]);
|
|
451
|
+
functionNameSet.add(functionName);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
457
454
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
455
|
+
// Index function names by first segment for O(1) bucket lookup instead of
|
|
456
|
+
// checking all function names for every path. Most paths only need to check
|
|
457
|
+
// 1-2 function names instead of all F.
|
|
458
|
+
const fnByFirstSegment = new Map<string, string[]>();
|
|
459
|
+
for (const fn of functionNameSet) {
|
|
460
|
+
const dotIdx = fn.indexOf('.');
|
|
461
|
+
const firstSeg = dotIdx >= 0 ? fn.slice(0, dotIdx) : fn;
|
|
462
|
+
let bucket = fnByFirstSegment.get(firstSeg);
|
|
463
|
+
if (!bucket) {
|
|
464
|
+
bucket = [];
|
|
465
|
+
fnByFirstSegment.set(firstSeg, bucket);
|
|
466
|
+
}
|
|
467
|
+
bucket.push(fn);
|
|
468
|
+
}
|
|
461
469
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
470
|
+
// Pass 2: Filter paths that match any discovered function name prefix.
|
|
471
|
+
// Use indexed lookup: extract path's first segment, check only matching function names.
|
|
472
|
+
const relevantMergedDependencySchema: Record<string, string> = {};
|
|
473
|
+
for (const path of schemaKeys) {
|
|
474
|
+
// Extract first segment of path (before first '.', '(', or '<')
|
|
475
|
+
const dotIdx = path.indexOf('.');
|
|
476
|
+
const parenIdx = path.indexOf('(');
|
|
477
|
+
const angleIdx = path.indexOf('<');
|
|
478
|
+
let minIdx = path.length;
|
|
479
|
+
if (dotIdx >= 0 && dotIdx < minIdx) minIdx = dotIdx;
|
|
480
|
+
if (parenIdx >= 0 && parenIdx < minIdx) minIdx = parenIdx;
|
|
481
|
+
if (angleIdx >= 0 && angleIdx < minIdx) minIdx = angleIdx;
|
|
482
|
+
const firstSeg = path.slice(0, minIdx);
|
|
483
|
+
|
|
484
|
+
const candidates = fnByFirstSegment.get(firstSeg);
|
|
485
|
+
if (
|
|
486
|
+
!candidates ||
|
|
487
|
+
!candidates.some((fn) => isFunctionNameWithoutFunction(path, fn))
|
|
488
|
+
) {
|
|
489
|
+
relevantMergedDependencySchema[path] = preprocessedSchema[path];
|
|
490
|
+
}
|
|
491
|
+
}
|
|
467
492
|
|
|
468
493
|
const filledSchema = fillInDirectSchemaGapsAndUnknowns({
|
|
469
494
|
scopeName: importedExport.name,
|
package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts
CHANGED
|
@@ -210,6 +210,23 @@ export default function mergeInDependentDataStructure({
|
|
|
210
210
|
equivalentPostfixes: Record<string, string>;
|
|
211
211
|
}[] = [];
|
|
212
212
|
|
|
213
|
+
// O(1) index for findOrCreateEquivalentSchemaPathsEntry.
|
|
214
|
+
// Maps "(rootPath)::(normalizedFuncName)" → the entry containing that root.
|
|
215
|
+
// This replaces the O(E) linear search that was causing O(E²) gather performance.
|
|
216
|
+
const espIndex = new Map<string, (typeof equivalentSchemaPaths)[0]>();
|
|
217
|
+
const espIndexKey = (path: string, functionName: string | undefined) => {
|
|
218
|
+
const normalized = cleanFunctionName(functionName);
|
|
219
|
+
const funcKey =
|
|
220
|
+
normalized === rootScopeName ? '__self__' : normalized || '__self__';
|
|
221
|
+
return `${path}::${funcKey}`;
|
|
222
|
+
};
|
|
223
|
+
const updateEspIndex = (entry: (typeof equivalentSchemaPaths)[0]) => {
|
|
224
|
+
for (const root of entry.equivalentRoots) {
|
|
225
|
+
const funcName = root.function?.name ?? rootScopeName;
|
|
226
|
+
espIndex.set(espIndexKey(root.schemaRootPath, funcName), entry);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
213
230
|
// Pre-build a lookup map from cleaned function name to dependency for O(1) lookups.
|
|
214
231
|
// This avoids O(n) linear search in findRelevantDependency which was causing O(n²) performance.
|
|
215
232
|
const dependencyByCleanedName = new Map<
|
|
@@ -324,6 +341,54 @@ export default function mergeInDependentDataStructure({
|
|
|
324
341
|
) => {
|
|
325
342
|
if (!sourceAndUsageEquivalencies) return;
|
|
326
343
|
|
|
344
|
+
// Pre-computed normalized schema index cache.
|
|
345
|
+
// Avoids repeated splitOutsideParenthesesAndArrays calls and function-name
|
|
346
|
+
// normalization for the same schema paths across multiple equivalency iterations.
|
|
347
|
+
// The normalization depends on `functionName` (constant per gatherAllEquivalentSchemaPaths call),
|
|
348
|
+
// so this cache is scoped to this call.
|
|
349
|
+
type NormalizedEntry = { path: string; parts: string[] };
|
|
350
|
+
const normalizedSchemaCache = new Map<
|
|
351
|
+
object,
|
|
352
|
+
{
|
|
353
|
+
byFirstPart: Map<string, NormalizedEntry[]>;
|
|
354
|
+
}
|
|
355
|
+
>();
|
|
356
|
+
const getSchemaIndex = (
|
|
357
|
+
schema: Record<string, string> | undefined,
|
|
358
|
+
): { byFirstPart: Map<string, NormalizedEntry[]> } => {
|
|
359
|
+
if (!schema) return { byFirstPart: new Map() };
|
|
360
|
+
const cached = normalizedSchemaCache.get(schema);
|
|
361
|
+
if (cached) return cached;
|
|
362
|
+
const byFirstPart = new Map<string, NormalizedEntry[]>();
|
|
363
|
+
for (const path in schema) {
|
|
364
|
+
let parts = splitOutsideParenthesesAndArrays(path);
|
|
365
|
+
if (parts[0].startsWith(functionName)) {
|
|
366
|
+
const baseName = cleanFunctionName(parts[0]);
|
|
367
|
+
if (!functionsWithMultipleTypeParams.has(baseName)) {
|
|
368
|
+
parts =
|
|
369
|
+
parts[1] === 'functionCallReturnValue'
|
|
370
|
+
? ['returnValue', ...parts.slice(2)]
|
|
371
|
+
: parts.slice(1);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const entry: NormalizedEntry = { path, parts };
|
|
375
|
+
// Index by the base of the first part (before any function call args)
|
|
376
|
+
const firstPart = parts[0] ?? '';
|
|
377
|
+
const parenIdx = firstPart.indexOf('(');
|
|
378
|
+
const firstPartBase =
|
|
379
|
+
parenIdx >= 0 ? firstPart.slice(0, parenIdx) : firstPart;
|
|
380
|
+
let bucket = byFirstPart.get(firstPartBase);
|
|
381
|
+
if (!bucket) {
|
|
382
|
+
bucket = [];
|
|
383
|
+
byFirstPart.set(firstPartBase, bucket);
|
|
384
|
+
}
|
|
385
|
+
bucket.push(entry);
|
|
386
|
+
}
|
|
387
|
+
const result = { byFirstPart };
|
|
388
|
+
normalizedSchemaCache.set(schema, result);
|
|
389
|
+
return result;
|
|
390
|
+
};
|
|
391
|
+
|
|
327
392
|
const findOrCreateEquivalentSchemaPathsEntry = (
|
|
328
393
|
allPaths: { path: string; functionName?: string }[],
|
|
329
394
|
) => {
|
|
@@ -354,62 +419,52 @@ export default function mergeInDependentDataStructure({
|
|
|
354
419
|
}
|
|
355
420
|
}
|
|
356
421
|
|
|
422
|
+
// Use espIndex Map for O(1) lookup instead of O(E) linear search.
|
|
423
|
+
// Falls back to linear search only when Map hit has a signature index conflict.
|
|
357
424
|
for (const pathInfo of allPaths) {
|
|
358
|
-
if (
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
// Get all signature indices in the existing entry (grouped by function)
|
|
376
|
-
const existingIndicesByFunction = new Map<string, Set<number>>();
|
|
377
|
-
for (const er of esp.equivalentRoots) {
|
|
378
|
-
const funcKey = er.function
|
|
379
|
-
? `${er.function.name}::${er.function.filePath}`
|
|
380
|
-
: '__self__';
|
|
381
|
-
const idx = extractSignatureIndex(er.schemaRootPath);
|
|
382
|
-
if (idx !== undefined) {
|
|
383
|
-
if (!existingIndicesByFunction.has(funcKey)) {
|
|
384
|
-
existingIndicesByFunction.set(funcKey, new Set());
|
|
385
|
-
}
|
|
386
|
-
existingIndicesByFunction.get(funcKey)!.add(idx);
|
|
387
|
-
}
|
|
425
|
+
if (equivalentSchemaPathsEntry) break;
|
|
426
|
+
const candidate = espIndex.get(
|
|
427
|
+
espIndexKey(pathInfo.path, pathInfo.functionName),
|
|
428
|
+
);
|
|
429
|
+
if (!candidate) continue;
|
|
430
|
+
|
|
431
|
+
// Verify no signature index conflict with the candidate entry
|
|
432
|
+
if (newRootSignatureIndices.size > 0) {
|
|
433
|
+
const existingIndicesByFunction = new Map<string, Set<number>>();
|
|
434
|
+
for (const er of candidate.equivalentRoots) {
|
|
435
|
+
const funcKey = er.function
|
|
436
|
+
? `${er.function.name}::${er.function.filePath}`
|
|
437
|
+
: '__self__';
|
|
438
|
+
const idx = extractSignatureIndex(er.schemaRootPath);
|
|
439
|
+
if (idx !== undefined) {
|
|
440
|
+
if (!existingIndicesByFunction.has(funcKey)) {
|
|
441
|
+
existingIndicesByFunction.set(funcKey, new Set());
|
|
388
442
|
}
|
|
443
|
+
existingIndicesByFunction.get(funcKey)!.add(idx);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
389
446
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// Conflict: entry has indices like [1] but we want to add [2]
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
447
|
+
let hasConflict = false;
|
|
448
|
+
for (const newRoot of equivalentRoots) {
|
|
449
|
+
const funcKey = newRoot.function
|
|
450
|
+
? `${newRoot.function.name}::${newRoot.function.filePath}`
|
|
451
|
+
: '__self__';
|
|
452
|
+
const newIdx = extractSignatureIndex(newRoot.schemaRootPath);
|
|
453
|
+
if (newIdx !== undefined) {
|
|
454
|
+
const existingIndices = existingIndicesByFunction.get(funcKey);
|
|
455
|
+
if (existingIndices && existingIndices.size > 0) {
|
|
456
|
+
if (!existingIndices.has(newIdx)) {
|
|
457
|
+
hasConflict = true;
|
|
458
|
+
break;
|
|
406
459
|
}
|
|
407
460
|
}
|
|
408
461
|
}
|
|
462
|
+
}
|
|
409
463
|
|
|
410
|
-
|
|
411
|
-
});
|
|
464
|
+
if (hasConflict) continue;
|
|
412
465
|
}
|
|
466
|
+
|
|
467
|
+
equivalentSchemaPathsEntry = candidate;
|
|
413
468
|
}
|
|
414
469
|
|
|
415
470
|
if (!equivalentSchemaPathsEntry) {
|
|
@@ -467,6 +522,9 @@ export default function mergeInDependentDataStructure({
|
|
|
467
522
|
return true;
|
|
468
523
|
});
|
|
469
524
|
|
|
525
|
+
// Keep the espIndex in sync after adding/deduplicating roots
|
|
526
|
+
updateEspIndex(equivalentSchemaPathsEntry);
|
|
527
|
+
|
|
470
528
|
return equivalentSchemaPathsEntry;
|
|
471
529
|
};
|
|
472
530
|
|
|
@@ -535,6 +593,8 @@ export default function mergeInDependentDataStructure({
|
|
|
535
593
|
);
|
|
536
594
|
|
|
537
595
|
const derivedBasePaths: { path: string; functionName?: string }[] = [];
|
|
596
|
+
const allPathSet = new Set(allPaths.map((p) => p.path));
|
|
597
|
+
const derivedBasePathSet = new Set<string>();
|
|
538
598
|
|
|
539
599
|
// For each child path, find its equivalent parent path and derive bases
|
|
540
600
|
for (const childPathInfo of childPaths) {
|
|
@@ -611,26 +671,28 @@ export default function mergeInDependentDataStructure({
|
|
|
611
671
|
!childHasArrayIterator &&
|
|
612
672
|
!childBaseIsGenericSignature
|
|
613
673
|
) {
|
|
614
|
-
// Add child base if not already present
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
674
|
+
// Add child base if not already present (O(1) Set lookup)
|
|
675
|
+
if (
|
|
676
|
+
!allPathSet.has(childBase) &&
|
|
677
|
+
!derivedBasePathSet.has(childBase)
|
|
678
|
+
) {
|
|
619
679
|
derivedBasePaths.push({
|
|
620
680
|
path: childBase,
|
|
621
681
|
functionName: childPathInfo.functionName,
|
|
622
682
|
});
|
|
683
|
+
derivedBasePathSet.add(childBase);
|
|
623
684
|
}
|
|
624
685
|
|
|
625
|
-
// Add parent base if not already present
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
686
|
+
// Add parent base if not already present (O(1) Set lookup)
|
|
687
|
+
if (
|
|
688
|
+
!allPathSet.has(parentBase) &&
|
|
689
|
+
!derivedBasePathSet.has(parentBase)
|
|
690
|
+
) {
|
|
630
691
|
derivedBasePaths.push({
|
|
631
692
|
path: parentBase,
|
|
632
693
|
functionName: parentPathInfo.functionName,
|
|
633
694
|
});
|
|
695
|
+
derivedBasePathSet.add(parentBase);
|
|
634
696
|
}
|
|
635
697
|
}
|
|
636
698
|
}
|
|
@@ -708,21 +770,20 @@ export default function mergeInDependentDataStructure({
|
|
|
708
770
|
}
|
|
709
771
|
|
|
710
772
|
for (const schema of schemas) {
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
773
|
+
// Use pre-computed index to only iterate schema entries whose
|
|
774
|
+
// normalized first part matches pathParts[0], instead of all entries.
|
|
775
|
+
const schemaIndex = getSchemaIndex(schema);
|
|
776
|
+
const lookupPart = pathParts[0] ?? '';
|
|
777
|
+
const lookupParenIdx = lookupPart.indexOf('(');
|
|
778
|
+
const lookupBase =
|
|
779
|
+
lookupParenIdx >= 0
|
|
780
|
+
? lookupPart.slice(0, lookupParenIdx)
|
|
781
|
+
: lookupPart;
|
|
782
|
+
const candidates = schemaIndex.byFirstPart.get(lookupBase) || [];
|
|
783
|
+
for (const {
|
|
784
|
+
path: schemaPath,
|
|
785
|
+
parts: schemaPathParts,
|
|
786
|
+
} of candidates) {
|
|
726
787
|
if (schemaPathParts.length < pathParts.length) continue;
|
|
727
788
|
|
|
728
789
|
// Check if all path parts match (allowing function call variants)
|
|
@@ -850,10 +911,17 @@ export default function mergeInDependentDataStructure({
|
|
|
850
911
|
const entry = findOrCreateEquivalentSchemaPathsEntry([
|
|
851
912
|
{ path: translatedBasePath, functionName: functionName },
|
|
852
913
|
]);
|
|
853
|
-
|
|
914
|
+
const newRoot = {
|
|
854
915
|
schemaRootPath: translatedBasePath,
|
|
855
916
|
function: findRelevantDependency(functionName),
|
|
856
|
-
}
|
|
917
|
+
};
|
|
918
|
+
entry.equivalentRoots.push(newRoot);
|
|
919
|
+
// Update index for the newly added root
|
|
920
|
+
const newRootFuncName = newRoot.function?.name ?? rootScopeName;
|
|
921
|
+
espIndex.set(
|
|
922
|
+
espIndexKey(newRoot.schemaRootPath, newRootFuncName),
|
|
923
|
+
entry,
|
|
924
|
+
);
|
|
857
925
|
|
|
858
926
|
const basePathParts = splitOutsideParenthesesAndArrays(basePath);
|
|
859
927
|
for (const schemaPath in dataStructure.returnValueSchema) {
|
|
@@ -1113,6 +1181,10 @@ export default function mergeInDependentDataStructure({
|
|
|
1113
1181
|
|
|
1114
1182
|
equivalentSchemaPaths = mergeAllEquivalentSchemaPaths();
|
|
1115
1183
|
|
|
1184
|
+
// Collect schemas that need cleaning — batch the calls for the end instead of
|
|
1185
|
+
// calling cleanSchema inside the inner root loop (which was O(roots * schemaSize)).
|
|
1186
|
+
const schemasToClean = new Set<{ [key: string]: string }>();
|
|
1187
|
+
|
|
1116
1188
|
for (const esp of equivalentSchemaPaths) {
|
|
1117
1189
|
// Pre-compute which postfixes have children to avoid O(n²) lookups in the inner loop.
|
|
1118
1190
|
// A postfix "has children" if there are other postfixes that extend it.
|
|
@@ -1290,10 +1362,15 @@ export default function mergeInDependentDataStructure({
|
|
|
1290
1362
|
schema[newSchemaPath] = postfixValue;
|
|
1291
1363
|
}
|
|
1292
1364
|
|
|
1293
|
-
|
|
1365
|
+
schemasToClean.add(schema);
|
|
1294
1366
|
}
|
|
1295
1367
|
}
|
|
1296
1368
|
|
|
1369
|
+
// Batch-clean all modified schemas once (instead of once per root per ESP entry)
|
|
1370
|
+
for (const schema of schemasToClean) {
|
|
1371
|
+
cleanSchema(schema, { stage: 'afterMergePostfix' });
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1297
1374
|
// Propagate equivalency-derived attributes to generic function call variants.
|
|
1298
1375
|
// When attributes are traced via equivalencies (e.g., fileComparisons from buildDataMap.signature[2]),
|
|
1299
1376
|
// they get written to non-generic paths (returnValue.data.x or funcName().functionCallReturnValue.data.x).
|
|
@@ -6,7 +6,7 @@ import { schemaField, defaultNow } from '../schemaHelpers';
|
|
|
6
6
|
/**
|
|
7
7
|
* Metadata for a debug bundle upload.
|
|
8
8
|
* Note: "bundle" refers to the tarball upload (base + delta).
|
|
9
|
-
* The markdown "debug report" from /codeyam
|
|
9
|
+
* The markdown "debug report" from /codeyam-diagnose is stored in feedback.debugReport.
|
|
10
10
|
*/
|
|
11
11
|
interface DebugBundleMetadata {
|
|
12
12
|
timestamp: string;
|
package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Generated, JSONColumnType } from 'kysely';
|
|
|
3
3
|
/**
|
|
4
4
|
* Metadata for a debug bundle upload.
|
|
5
5
|
* Note: "bundle" refers to the tarball upload (base + delta).
|
|
6
|
-
* The markdown "debug report" from /codeyam
|
|
6
|
+
* The markdown "debug report" from /codeyam-diagnose is stored in feedback.debugReport.
|
|
7
7
|
*/
|
|
8
8
|
interface DebugBundleMetadata {
|
|
9
9
|
timestamp: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rsyncCopy.d.ts","sourceRoot":"","sources":["../../../../../src/lib/fs/rsyncCopy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rsyncCopy.d.ts","sourceRoot":"","sources":["../../../../../src/lib/fs/rsyncCopy.ts"],"names":[],"mappings":"AAqFA,wBAA8B,SAAS,CAAC,EACtC,UAAU,EACV,eAAe,EACf,QAAa,EACb,YAAoB,EACpB,MAAc,EACd,SAAc,GACf,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEhB"}
|