gitnexus 1.6.3-rc.3 → 1.6.3-rc.5
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/dist/_shared/index.d.ts +10 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js +7 -0
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/scope-resolution/def-index.d.ts +36 -0
- package/dist/_shared/scope-resolution/def-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/def-index.js +51 -0
- package/dist/_shared/scope-resolution/def-index.js.map +1 -0
- package/dist/_shared/scope-resolution/module-scope-index.d.ts +38 -0
- package/dist/_shared/scope-resolution/module-scope-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/module-scope-index.js +50 -0
- package/dist/_shared/scope-resolution/module-scope-index.js.map +1 -0
- package/dist/_shared/scope-resolution/qualified-name-index.d.ts +44 -0
- package/dist/_shared/scope-resolution/qualified-name-index.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/qualified-name-index.js +75 -0
- package/dist/_shared/scope-resolution/qualified-name-index.js.map +1 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts +59 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.js +117 -0
- package/dist/_shared/scope-resolution/shadow/aggregate.js.map +1 -0
- package/dist/_shared/scope-resolution/shadow/diff.d.ts +59 -0
- package/dist/_shared/scope-resolution/shadow/diff.d.ts.map +1 -0
- package/dist/_shared/scope-resolution/shadow/diff.js +79 -0
- package/dist/_shared/scope-resolution/shadow/diff.js.map +1 -0
- package/dist/mcp/local/local-backend.js +10 -1
- package/package.json +1 -1
package/dist/_shared/index.d.ts
CHANGED
|
@@ -12,4 +12,14 @@ export { ORIGIN_PRIORITY } from './scope-resolution/origin-priority.js';
|
|
|
12
12
|
export type { OriginForTieBreak } from './scope-resolution/origin-priority.js';
|
|
13
13
|
export { LanguageClassifications, isProductionLanguage, } from './scope-resolution/language-classification.js';
|
|
14
14
|
export type { LanguageClassification } from './scope-resolution/language-classification.js';
|
|
15
|
+
export { buildDefIndex } from './scope-resolution/def-index.js';
|
|
16
|
+
export type { DefIndex } from './scope-resolution/def-index.js';
|
|
17
|
+
export { buildModuleScopeIndex } from './scope-resolution/module-scope-index.js';
|
|
18
|
+
export type { ModuleScopeIndex, ModuleScopeEntry } from './scope-resolution/module-scope-index.js';
|
|
19
|
+
export { buildQualifiedNameIndex } from './scope-resolution/qualified-name-index.js';
|
|
20
|
+
export type { QualifiedNameIndex } from './scope-resolution/qualified-name-index.js';
|
|
21
|
+
export { diffResolutions } from './scope-resolution/shadow/diff.js';
|
|
22
|
+
export type { ShadowAgreement, ShadowCallsite, ShadowDiff, } from './scope-resolution/shadow/diff.js';
|
|
23
|
+
export { aggregateDiffs } from './scope-resolution/shadow/aggregate.js';
|
|
24
|
+
export type { LanguageParityRow, ShadowParityReport } from './scope-resolution/shadow/aggregate.js';
|
|
15
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACjG,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAChF,YAAY,EACV,OAAO,EACP,KAAK,EACL,SAAS,EACT,KAAK,EACL,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,KAAK,EACL,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,QAAQ,GACT,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG/E,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACjG,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAChF,YAAY,EACV,OAAO,EACP,KAAK,EACL,SAAS,EACT,KAAK,EACL,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,KAAK,EACL,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,QAAQ,GACT,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG/E,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC;AAG5F,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,YAAY,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACnG,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,YAAY,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,YAAY,EACV,eAAe,EACf,cAAc,EACd,UAAU,GACX,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC"}
|
package/dist/_shared/index.js
CHANGED
|
@@ -8,4 +8,11 @@ export { EvidenceWeights, typeBindingWeightAtDepth } from './scope-resolution/ev
|
|
|
8
8
|
export { ORIGIN_PRIORITY } from './scope-resolution/origin-priority.js';
|
|
9
9
|
// Language classification (RFC §6.1 Ring 3/4 governance)
|
|
10
10
|
export { LanguageClassifications, isProductionLanguage, } from './scope-resolution/language-classification.js';
|
|
11
|
+
// Core indexes over per-file artifacts (RFC §3.1; Ring 2 SHARED #913)
|
|
12
|
+
export { buildDefIndex } from './scope-resolution/def-index.js';
|
|
13
|
+
export { buildModuleScopeIndex } from './scope-resolution/module-scope-index.js';
|
|
14
|
+
export { buildQualifiedNameIndex } from './scope-resolution/qualified-name-index.js';
|
|
15
|
+
// Shadow-mode diff + aggregation (RFC §6.3; Ring 2 SHARED #918)
|
|
16
|
+
export { diffResolutions } from './scope-resolution/shadow/diff.js';
|
|
17
|
+
export { aggregateDiffs } from './scope-resolution/shadow/aggregate.js';
|
|
11
18
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAiCjG,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAiCjG,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AAGvD,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,gEAAgE;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAMpE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `DefIndex` — O(1) `DefId → SymbolDefinition` materialization.
|
|
3
|
+
*
|
|
4
|
+
* The global "what is this id?" lookup. Every per-kind registry (ClassRegistry,
|
|
5
|
+
* MethodRegistry, FieldRegistry) returns `DefId[]` and resolves them back to
|
|
6
|
+
* full `SymbolDefinition` records through this index — one central hash map,
|
|
7
|
+
* one allocation per def.
|
|
8
|
+
*
|
|
9
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
10
|
+
*
|
|
11
|
+
* Consumed by: #917 (`Registry.lookup` implementations), #915 (SCC finalize).
|
|
12
|
+
*/
|
|
13
|
+
import type { SymbolDefinition } from './symbol-definition.js';
|
|
14
|
+
import type { DefId } from './types.js';
|
|
15
|
+
export interface DefIndex {
|
|
16
|
+
readonly byId: ReadonlyMap<DefId, SymbolDefinition>;
|
|
17
|
+
readonly size: number;
|
|
18
|
+
get(id: DefId): SymbolDefinition | undefined;
|
|
19
|
+
has(id: DefId): boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build a `DefIndex` from a flat list of `SymbolDefinition` records.
|
|
23
|
+
*
|
|
24
|
+
* **Collision policy: first-write-wins.** `DefId` is meant to be unique
|
|
25
|
+
* (`nodeId` is the stable graph identifier), so a collision indicates an
|
|
26
|
+
* upstream bug — most likely the same symbol parsed twice or a duplicate
|
|
27
|
+
* commit into the pipeline. Rather than silently overwriting with a later
|
|
28
|
+
* definition that may be partial or wrong, the first record wins and
|
|
29
|
+
* subsequent records for the same id are dropped. Pipeline bugs surface
|
|
30
|
+
* later as `has(id) === true` but the def looking older than expected,
|
|
31
|
+
* which is easier to debug than a silent overwrite.
|
|
32
|
+
*
|
|
33
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildDefIndex(defs: readonly SymbolDefinition[]): DefIndex;
|
|
36
|
+
//# sourceMappingURL=def-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"def-index.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/def-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,gBAAgB,GAAG,SAAS,CAAC;IAC7C,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,gBAAgB,EAAE,GAAG,QAAQ,CAOzE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `DefIndex` — O(1) `DefId → SymbolDefinition` materialization.
|
|
3
|
+
*
|
|
4
|
+
* The global "what is this id?" lookup. Every per-kind registry (ClassRegistry,
|
|
5
|
+
* MethodRegistry, FieldRegistry) returns `DefId[]` and resolves them back to
|
|
6
|
+
* full `SymbolDefinition` records through this index — one central hash map,
|
|
7
|
+
* one allocation per def.
|
|
8
|
+
*
|
|
9
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
10
|
+
*
|
|
11
|
+
* Consumed by: #917 (`Registry.lookup` implementations), #915 (SCC finalize).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Build a `DefIndex` from a flat list of `SymbolDefinition` records.
|
|
15
|
+
*
|
|
16
|
+
* **Collision policy: first-write-wins.** `DefId` is meant to be unique
|
|
17
|
+
* (`nodeId` is the stable graph identifier), so a collision indicates an
|
|
18
|
+
* upstream bug — most likely the same symbol parsed twice or a duplicate
|
|
19
|
+
* commit into the pipeline. Rather than silently overwriting with a later
|
|
20
|
+
* definition that may be partial or wrong, the first record wins and
|
|
21
|
+
* subsequent records for the same id are dropped. Pipeline bugs surface
|
|
22
|
+
* later as `has(id) === true` but the def looking older than expected,
|
|
23
|
+
* which is easier to debug than a silent overwrite.
|
|
24
|
+
*
|
|
25
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
26
|
+
*/
|
|
27
|
+
export function buildDefIndex(defs) {
|
|
28
|
+
const byId = new Map();
|
|
29
|
+
for (const def of defs) {
|
|
30
|
+
if (byId.has(def.nodeId))
|
|
31
|
+
continue; // first-write-wins
|
|
32
|
+
byId.set(def.nodeId, def);
|
|
33
|
+
}
|
|
34
|
+
return freezeIndex(byId);
|
|
35
|
+
}
|
|
36
|
+
// ─── Internal ───────────────────────────────────────────────────────────────
|
|
37
|
+
function freezeIndex(byId) {
|
|
38
|
+
return {
|
|
39
|
+
byId,
|
|
40
|
+
get size() {
|
|
41
|
+
return byId.size;
|
|
42
|
+
},
|
|
43
|
+
get(id) {
|
|
44
|
+
return byId.get(id);
|
|
45
|
+
},
|
|
46
|
+
has(id) {
|
|
47
|
+
return byId.has(id);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=def-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"def-index.js","sourceRoot":"","sources":["../../src/scope-resolution/def-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,IAAiC;IAC7D,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;IAChD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS,CAAC,mBAAmB;QACvD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,+EAA+E;AAE/E,SAAS,WAAW,CAAC,IAAkC;IACrD,OAAO;QACL,IAAI;QACJ,IAAI,IAAI;YACN,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;QACD,GAAG,CAAC,EAAS;YACX,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QACD,GAAG,CAAC,EAAS;YACX,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ModuleScopeIndex` — O(1) `filePath → moduleScopeId` lookup.
|
|
3
|
+
*
|
|
4
|
+
* Every file parsed produces exactly one `Module` scope at its root. The
|
|
5
|
+
* finalize algorithm needs to resolve `ImportEdge.targetFile` to a concrete
|
|
6
|
+
* module scope id in constant time during the link pass; this index is that
|
|
7
|
+
* mapping.
|
|
8
|
+
*
|
|
9
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
10
|
+
*
|
|
11
|
+
* Consumed by: #915 (SCC finalize link pass), #923 (shadow harness when
|
|
12
|
+
* resolving callsite file → enclosing module).
|
|
13
|
+
*/
|
|
14
|
+
import type { ScopeId } from './types.js';
|
|
15
|
+
export interface ModuleScopeIndex {
|
|
16
|
+
readonly byFilePath: ReadonlyMap<string, ScopeId>;
|
|
17
|
+
readonly size: number;
|
|
18
|
+
get(filePath: string): ScopeId | undefined;
|
|
19
|
+
has(filePath: string): boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface ModuleScopeEntry {
|
|
22
|
+
readonly filePath: string;
|
|
23
|
+
readonly moduleScopeId: ScopeId;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build a `ModuleScopeIndex` from a flat list of `{ filePath, moduleScopeId }`
|
|
27
|
+
* pairs.
|
|
28
|
+
*
|
|
29
|
+
* **Collision policy: first-write-wins.** A file should appear exactly once
|
|
30
|
+
* in a single ingestion run; collisions indicate the same file was parsed
|
|
31
|
+
* twice or a `filePath` normalization bug upstream. Dropping the later
|
|
32
|
+
* entry preserves the first-stable id the rest of the pipeline may already
|
|
33
|
+
* have registered against.
|
|
34
|
+
*
|
|
35
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildModuleScopeIndex(entries: readonly ModuleScopeEntry[]): ModuleScopeIndex;
|
|
38
|
+
//# sourceMappingURL=module-scope-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-scope-index.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/module-scope-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC3C,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GAAG,gBAAgB,CAO5F"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ModuleScopeIndex` — O(1) `filePath → moduleScopeId` lookup.
|
|
3
|
+
*
|
|
4
|
+
* Every file parsed produces exactly one `Module` scope at its root. The
|
|
5
|
+
* finalize algorithm needs to resolve `ImportEdge.targetFile` to a concrete
|
|
6
|
+
* module scope id in constant time during the link pass; this index is that
|
|
7
|
+
* mapping.
|
|
8
|
+
*
|
|
9
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
10
|
+
*
|
|
11
|
+
* Consumed by: #915 (SCC finalize link pass), #923 (shadow harness when
|
|
12
|
+
* resolving callsite file → enclosing module).
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Build a `ModuleScopeIndex` from a flat list of `{ filePath, moduleScopeId }`
|
|
16
|
+
* pairs.
|
|
17
|
+
*
|
|
18
|
+
* **Collision policy: first-write-wins.** A file should appear exactly once
|
|
19
|
+
* in a single ingestion run; collisions indicate the same file was parsed
|
|
20
|
+
* twice or a `filePath` normalization bug upstream. Dropping the later
|
|
21
|
+
* entry preserves the first-stable id the rest of the pipeline may already
|
|
22
|
+
* have registered against.
|
|
23
|
+
*
|
|
24
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
25
|
+
*/
|
|
26
|
+
export function buildModuleScopeIndex(entries) {
|
|
27
|
+
const byFilePath = new Map();
|
|
28
|
+
for (const { filePath, moduleScopeId } of entries) {
|
|
29
|
+
if (byFilePath.has(filePath))
|
|
30
|
+
continue; // first-write-wins
|
|
31
|
+
byFilePath.set(filePath, moduleScopeId);
|
|
32
|
+
}
|
|
33
|
+
return freezeIndex(byFilePath);
|
|
34
|
+
}
|
|
35
|
+
// ─── Internal ───────────────────────────────────────────────────────────────
|
|
36
|
+
function freezeIndex(byFilePath) {
|
|
37
|
+
return {
|
|
38
|
+
byFilePath,
|
|
39
|
+
get size() {
|
|
40
|
+
return byFilePath.size;
|
|
41
|
+
},
|
|
42
|
+
get(filePath) {
|
|
43
|
+
return byFilePath.get(filePath);
|
|
44
|
+
},
|
|
45
|
+
has(filePath) {
|
|
46
|
+
return byFilePath.has(filePath);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=module-scope-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-scope-index.js","sourceRoot":"","sources":["../../src/scope-resolution/module-scope-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgBH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAoC;IACxE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC9C,KAAK,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,OAAO,EAAE,CAAC;QAClD,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS,CAAC,mBAAmB;QAC3D,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,WAAW,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC;AAED,+EAA+E;AAE/E,SAAS,WAAW,CAAC,UAAgC;IACnD,OAAO;QACL,UAAU;QACV,IAAI,IAAI;YACN,OAAO,UAAU,CAAC,IAAI,CAAC;QACzB,CAAC;QACD,GAAG,CAAC,QAAgB;YAClB,OAAO,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;QACD,GAAG,CAAC,QAAgB;YAClB,OAAO,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `QualifiedNameIndex` — O(1) `qualifiedName → DefId[]` lookup across all kinds.
|
|
3
|
+
*
|
|
4
|
+
* Cross-kind fast path for qualified-name resolution
|
|
5
|
+
* (`lookupQualified(qname, scope, params)` in RFC §4.5). Class, method,
|
|
6
|
+
* field, and namespace defs all contribute to a single index here; consumers
|
|
7
|
+
* filter the returned `DefId[]` by `p.acceptedKinds` at the call site.
|
|
8
|
+
*
|
|
9
|
+
* Returns `DefId[]` (not a single `DefId`) because multiple defs can legally
|
|
10
|
+
* share a qualified name — partial classes in C#, method overloads, or
|
|
11
|
+
* accidental cross-kind collisions. The lookup caller filters to the expected
|
|
12
|
+
* kind(s) and ranks the survivors.
|
|
13
|
+
*
|
|
14
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
15
|
+
*
|
|
16
|
+
* Consumed by: #917 (`Registry.lookup` qualified fast path, `resolveTypeRef`
|
|
17
|
+
* dotted fallback via #916).
|
|
18
|
+
*/
|
|
19
|
+
import type { SymbolDefinition } from './symbol-definition.js';
|
|
20
|
+
import type { DefId } from './types.js';
|
|
21
|
+
export interface QualifiedNameIndex {
|
|
22
|
+
readonly byQualifiedName: ReadonlyMap<string, readonly DefId[]>;
|
|
23
|
+
readonly size: number;
|
|
24
|
+
/** Returns all `DefId`s registered under this qualified name; empty frozen
|
|
25
|
+
* array on miss so callers can iterate without null checks. */
|
|
26
|
+
get(qualifiedName: string): readonly DefId[];
|
|
27
|
+
has(qualifiedName: string): boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build a `QualifiedNameIndex` from a flat list of `SymbolDefinition` records.
|
|
31
|
+
*
|
|
32
|
+
* Only defs with a non-empty `qualifiedName` contribute; defs without one are
|
|
33
|
+
* silently skipped (not every kind carries a qualified name — anonymous or
|
|
34
|
+
* top-level symbols, dynamic-unresolved imports, etc.).
|
|
35
|
+
*
|
|
36
|
+
* **Duplicate policy: appended in input order.** Each unique `(qname, DefId)`
|
|
37
|
+
* pair contributes at most once — repeated entries for the same pair are
|
|
38
|
+
* deduplicated. Distinct `DefId`s sharing a `qname` accumulate in insertion
|
|
39
|
+
* order (stable output for deterministic lookup ranking at the call site).
|
|
40
|
+
*
|
|
41
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildQualifiedNameIndex(defs: readonly SymbolDefinition[]): QualifiedNameIndex;
|
|
44
|
+
//# sourceMappingURL=qualified-name-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualified-name-index.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/qualified-name-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;oEACgE;IAChE,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,KAAK,EAAE,CAAC;IAC7C,GAAG,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;CACrC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,gBAAgB,EAAE,GAAG,kBAAkB,CA2B7F"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `QualifiedNameIndex` — O(1) `qualifiedName → DefId[]` lookup across all kinds.
|
|
3
|
+
*
|
|
4
|
+
* Cross-kind fast path for qualified-name resolution
|
|
5
|
+
* (`lookupQualified(qname, scope, params)` in RFC §4.5). Class, method,
|
|
6
|
+
* field, and namespace defs all contribute to a single index here; consumers
|
|
7
|
+
* filter the returned `DefId[]` by `p.acceptedKinds` at the call site.
|
|
8
|
+
*
|
|
9
|
+
* Returns `DefId[]` (not a single `DefId`) because multiple defs can legally
|
|
10
|
+
* share a qualified name — partial classes in C#, method overloads, or
|
|
11
|
+
* accidental cross-kind collisions. The lookup caller filters to the expected
|
|
12
|
+
* kind(s) and ranks the survivors.
|
|
13
|
+
*
|
|
14
|
+
* Part of RFC #909 Ring 2 SHARED — #913.
|
|
15
|
+
*
|
|
16
|
+
* Consumed by: #917 (`Registry.lookup` qualified fast path, `resolveTypeRef`
|
|
17
|
+
* dotted fallback via #916).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Build a `QualifiedNameIndex` from a flat list of `SymbolDefinition` records.
|
|
21
|
+
*
|
|
22
|
+
* Only defs with a non-empty `qualifiedName` contribute; defs without one are
|
|
23
|
+
* silently skipped (not every kind carries a qualified name — anonymous or
|
|
24
|
+
* top-level symbols, dynamic-unresolved imports, etc.).
|
|
25
|
+
*
|
|
26
|
+
* **Duplicate policy: appended in input order.** Each unique `(qname, DefId)`
|
|
27
|
+
* pair contributes at most once — repeated entries for the same pair are
|
|
28
|
+
* deduplicated. Distinct `DefId`s sharing a `qname` accumulate in insertion
|
|
29
|
+
* order (stable output for deterministic lookup ranking at the call site).
|
|
30
|
+
*
|
|
31
|
+
* Pure function — safe to call repeatedly; no side effects.
|
|
32
|
+
*/
|
|
33
|
+
export function buildQualifiedNameIndex(defs) {
|
|
34
|
+
const byQualifiedName = new Map();
|
|
35
|
+
const seenPairs = new Set();
|
|
36
|
+
for (const def of defs) {
|
|
37
|
+
const qname = def.qualifiedName;
|
|
38
|
+
if (qname === undefined || qname.length === 0)
|
|
39
|
+
continue;
|
|
40
|
+
const pairKey = `${qname}\0${def.nodeId}`;
|
|
41
|
+
if (seenPairs.has(pairKey))
|
|
42
|
+
continue;
|
|
43
|
+
seenPairs.add(pairKey);
|
|
44
|
+
const bucket = byQualifiedName.get(qname);
|
|
45
|
+
if (bucket === undefined) {
|
|
46
|
+
byQualifiedName.set(qname, [def.nodeId]);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
bucket.push(def.nodeId);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Freeze bucket arrays so consumers can't mutate the index.
|
|
53
|
+
const frozen = new Map();
|
|
54
|
+
for (const [k, v] of byQualifiedName) {
|
|
55
|
+
frozen.set(k, Object.freeze(v.slice()));
|
|
56
|
+
}
|
|
57
|
+
return freezeIndex(frozen);
|
|
58
|
+
}
|
|
59
|
+
// ─── Internal ───────────────────────────────────────────────────────────────
|
|
60
|
+
const EMPTY = Object.freeze([]);
|
|
61
|
+
function freezeIndex(byQualifiedName) {
|
|
62
|
+
return {
|
|
63
|
+
byQualifiedName,
|
|
64
|
+
get size() {
|
|
65
|
+
return byQualifiedName.size;
|
|
66
|
+
},
|
|
67
|
+
get(qualifiedName) {
|
|
68
|
+
return byQualifiedName.get(qualifiedName) ?? EMPTY;
|
|
69
|
+
},
|
|
70
|
+
has(qualifiedName) {
|
|
71
|
+
return byQualifiedName.has(qualifiedName);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=qualified-name-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualified-name-index.js","sourceRoot":"","sources":["../../src/scope-resolution/qualified-name-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAiC;IACvE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAmB,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC;QAChC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAExD,MAAM,OAAO,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1C,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,SAAS;QACrC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IACnD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,+EAA+E;AAE/E,MAAM,KAAK,GAAqB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAElD,SAAS,WAAW,CAAC,eAA8C;IACjE,OAAO;QACL,eAAe;QACf,IAAI,IAAI;YACN,OAAO,eAAe,CAAC,IAAI,CAAC;QAC9B,CAAC;QACD,GAAG,CAAC,aAAqB;YACvB,OAAO,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;QACrD,CAAC;QACD,GAAG,CAAC,aAAqB;YACvB,OAAO,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-mode aggregation — per-language parity %, per-evidence-kind
|
|
3
|
+
* breakdown of divergences. Consumed by the parity dashboard (RING2-PKG-5).
|
|
4
|
+
*
|
|
5
|
+
* Pure functions; no I/O. The harness persists per-run JSON; the dashboard
|
|
6
|
+
* reads `.gitnexus/shadow-parity/latest.json` and renders.
|
|
7
|
+
*
|
|
8
|
+
* Part of RFC #909 Ring 2 SHARED — #918.
|
|
9
|
+
*/
|
|
10
|
+
import type { SupportedLanguages } from '../../languages.js';
|
|
11
|
+
import type { ResolutionEvidence } from '../types.js';
|
|
12
|
+
import type { ShadowAgreement, ShadowDiff } from './diff.js';
|
|
13
|
+
export interface LanguageParityRow {
|
|
14
|
+
readonly language: SupportedLanguages;
|
|
15
|
+
readonly totalCalls: number;
|
|
16
|
+
readonly bothAgree: number;
|
|
17
|
+
readonly onlyLegacy: number;
|
|
18
|
+
readonly onlyNew: number;
|
|
19
|
+
readonly bothDisagree: number;
|
|
20
|
+
readonly bothEmpty: number;
|
|
21
|
+
/**
|
|
22
|
+
* Fraction in [0, 1]. Numerator = `bothAgree`; denominator = "calls where
|
|
23
|
+
* at least one side resolved" = `totalCalls - bothEmpty`.
|
|
24
|
+
*
|
|
25
|
+
* When the denominator is 0 (all calls for this language were
|
|
26
|
+
* `both-empty`), returns 0. Callers rendering the dashboard should treat
|
|
27
|
+
* a 0 parity alongside `totalCalls === bothEmpty` as "no signal" rather
|
|
28
|
+
* than "total disagreement".
|
|
29
|
+
*/
|
|
30
|
+
readonly parity: number;
|
|
31
|
+
/**
|
|
32
|
+
* Divergence signals broken down by `ResolutionEvidence.kind`. Sourced
|
|
33
|
+
* from `ShadowDiff.evidenceDelta` on non-agreeing rows only — `both-agree`
|
|
34
|
+
* and `both-empty` do not contribute.
|
|
35
|
+
*/
|
|
36
|
+
readonly evidenceBreakdown: ReadonlyMap<ResolutionEvidence['kind'], number>;
|
|
37
|
+
}
|
|
38
|
+
export interface ShadowParityReport {
|
|
39
|
+
readonly generatedAt: string;
|
|
40
|
+
readonly perLanguage: readonly LanguageParityRow[];
|
|
41
|
+
readonly overall: Omit<LanguageParityRow, 'language' | 'evidenceBreakdown'>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Aggregate a stream of `ShadowDiff` records into a `ShadowParityReport`,
|
|
45
|
+
* bucketed by language. Pure function.
|
|
46
|
+
*
|
|
47
|
+
* - `perLanguage` rows are sorted alphabetically by `SupportedLanguages`
|
|
48
|
+
* value for stable JSON output (the dashboard reads
|
|
49
|
+
* `.gitnexus/shadow-parity/latest.json` and diffing snapshots is useful).
|
|
50
|
+
* - `overall` is the column-wise sum across languages.
|
|
51
|
+
* - `generatedAt` is injected via the `now` parameter so tests stay
|
|
52
|
+
* deterministic; production callers let it default to `new Date()`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function aggregateDiffs(diffs: readonly {
|
|
55
|
+
readonly language: SupportedLanguages;
|
|
56
|
+
readonly diff: ShadowDiff;
|
|
57
|
+
}[], now?: Date): ShadowParityReport;
|
|
58
|
+
export type { ShadowAgreement, ShadowDiff };
|
|
59
|
+
//# sourceMappingURL=aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../src/scope-resolution/shadow/aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAI7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,mBAAmB,CAAC,CAAC;CAC7E;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,EAAE,EACtF,GAAG,GAAE,IAAiB,GACrB,kBAAkB,CAuBpB;AAiGD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-mode aggregation — per-language parity %, per-evidence-kind
|
|
3
|
+
* breakdown of divergences. Consumed by the parity dashboard (RING2-PKG-5).
|
|
4
|
+
*
|
|
5
|
+
* Pure functions; no I/O. The harness persists per-run JSON; the dashboard
|
|
6
|
+
* reads `.gitnexus/shadow-parity/latest.json` and renders.
|
|
7
|
+
*
|
|
8
|
+
* Part of RFC #909 Ring 2 SHARED — #918.
|
|
9
|
+
*/
|
|
10
|
+
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Aggregate a stream of `ShadowDiff` records into a `ShadowParityReport`,
|
|
13
|
+
* bucketed by language. Pure function.
|
|
14
|
+
*
|
|
15
|
+
* - `perLanguage` rows are sorted alphabetically by `SupportedLanguages`
|
|
16
|
+
* value for stable JSON output (the dashboard reads
|
|
17
|
+
* `.gitnexus/shadow-parity/latest.json` and diffing snapshots is useful).
|
|
18
|
+
* - `overall` is the column-wise sum across languages.
|
|
19
|
+
* - `generatedAt` is injected via the `now` parameter so tests stay
|
|
20
|
+
* deterministic; production callers let it default to `new Date()`.
|
|
21
|
+
*/
|
|
22
|
+
export function aggregateDiffs(diffs, now = new Date()) {
|
|
23
|
+
const perLanguageMap = new Map();
|
|
24
|
+
for (const { language, diff } of diffs) {
|
|
25
|
+
let counts = perLanguageMap.get(language);
|
|
26
|
+
if (!counts) {
|
|
27
|
+
counts = makeEmptyCounts();
|
|
28
|
+
perLanguageMap.set(language, counts);
|
|
29
|
+
}
|
|
30
|
+
tallyDiff(counts, diff);
|
|
31
|
+
}
|
|
32
|
+
const perLanguage = Array.from(perLanguageMap.entries())
|
|
33
|
+
.map(([language, counts]) => buildRow(language, counts))
|
|
34
|
+
.sort((a, b) => a.language.localeCompare(b.language));
|
|
35
|
+
const overall = buildOverallRow(perLanguage);
|
|
36
|
+
return {
|
|
37
|
+
generatedAt: now.toISOString(),
|
|
38
|
+
perLanguage,
|
|
39
|
+
overall,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function makeEmptyCounts() {
|
|
43
|
+
return {
|
|
44
|
+
totalCalls: 0,
|
|
45
|
+
bothAgree: 0,
|
|
46
|
+
onlyLegacy: 0,
|
|
47
|
+
onlyNew: 0,
|
|
48
|
+
bothDisagree: 0,
|
|
49
|
+
bothEmpty: 0,
|
|
50
|
+
evidenceBreakdown: new Map(),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function tallyDiff(counts, diff) {
|
|
54
|
+
counts.totalCalls += 1;
|
|
55
|
+
incrementAgreement(counts, diff.agreement);
|
|
56
|
+
if (diff.agreement === 'both-agree' || diff.agreement === 'both-empty')
|
|
57
|
+
return;
|
|
58
|
+
for (const ev of diff.evidenceDelta) {
|
|
59
|
+
counts.evidenceBreakdown.set(ev.kind, (counts.evidenceBreakdown.get(ev.kind) ?? 0) + 1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function incrementAgreement(counts, agreement) {
|
|
63
|
+
switch (agreement) {
|
|
64
|
+
case 'both-agree':
|
|
65
|
+
counts.bothAgree += 1;
|
|
66
|
+
return;
|
|
67
|
+
case 'only-legacy':
|
|
68
|
+
counts.onlyLegacy += 1;
|
|
69
|
+
return;
|
|
70
|
+
case 'only-new':
|
|
71
|
+
counts.onlyNew += 1;
|
|
72
|
+
return;
|
|
73
|
+
case 'both-disagree':
|
|
74
|
+
counts.bothDisagree += 1;
|
|
75
|
+
return;
|
|
76
|
+
case 'both-empty':
|
|
77
|
+
counts.bothEmpty += 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function buildRow(language, counts) {
|
|
82
|
+
const resolved = counts.totalCalls - counts.bothEmpty;
|
|
83
|
+
const parity = resolved > 0 ? counts.bothAgree / resolved : 0;
|
|
84
|
+
return {
|
|
85
|
+
language,
|
|
86
|
+
totalCalls: counts.totalCalls,
|
|
87
|
+
bothAgree: counts.bothAgree,
|
|
88
|
+
onlyLegacy: counts.onlyLegacy,
|
|
89
|
+
onlyNew: counts.onlyNew,
|
|
90
|
+
bothDisagree: counts.bothDisagree,
|
|
91
|
+
bothEmpty: counts.bothEmpty,
|
|
92
|
+
parity,
|
|
93
|
+
// Freeze via `new Map` on a sorted-kind copy so downstream consumers
|
|
94
|
+
// can't mutate the aggregator's internal state.
|
|
95
|
+
evidenceBreakdown: new Map(Array.from(counts.evidenceBreakdown.entries()).sort(([a], [b]) => a.localeCompare(b))),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function buildOverallRow(perLanguage) {
|
|
99
|
+
let totalCalls = 0;
|
|
100
|
+
let bothAgree = 0;
|
|
101
|
+
let onlyLegacy = 0;
|
|
102
|
+
let onlyNew = 0;
|
|
103
|
+
let bothDisagree = 0;
|
|
104
|
+
let bothEmpty = 0;
|
|
105
|
+
for (const row of perLanguage) {
|
|
106
|
+
totalCalls += row.totalCalls;
|
|
107
|
+
bothAgree += row.bothAgree;
|
|
108
|
+
onlyLegacy += row.onlyLegacy;
|
|
109
|
+
onlyNew += row.onlyNew;
|
|
110
|
+
bothDisagree += row.bothDisagree;
|
|
111
|
+
bothEmpty += row.bothEmpty;
|
|
112
|
+
}
|
|
113
|
+
const resolved = totalCalls - bothEmpty;
|
|
114
|
+
const parity = resolved > 0 ? bothAgree / resolved : 0;
|
|
115
|
+
return { totalCalls, bothAgree, onlyLegacy, onlyNew, bothDisagree, bothEmpty, parity };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=aggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/scope-resolution/shadow/aggregate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-mode diff logic — RFC §6.3.
|
|
3
|
+
*
|
|
4
|
+
* Pure comparison logic for shadow mode. Takes two `Resolution[]` (legacy
|
|
5
|
+
* DAG result + new scope-based registry result) and produces a structured
|
|
6
|
+
* diff record for the parity dashboard.
|
|
7
|
+
*
|
|
8
|
+
* Consumed by the Ring 2 PKG shadow harness (#923), which dual-runs each
|
|
9
|
+
* call through legacy + new paths, diffs results, and persists per-run JSON
|
|
10
|
+
* for the parity dashboard.
|
|
11
|
+
*
|
|
12
|
+
* Part of RFC #909 Ring 2 SHARED — #918.
|
|
13
|
+
*/
|
|
14
|
+
import type { Resolution, ResolutionEvidence } from '../types.js';
|
|
15
|
+
export type ShadowAgreement = 'both-agree' | 'only-legacy' | 'only-new' | 'both-disagree' | 'both-empty';
|
|
16
|
+
export interface ShadowDiff {
|
|
17
|
+
readonly callsite: ShadowCallsite;
|
|
18
|
+
readonly legacy: Resolution | null;
|
|
19
|
+
readonly newResult: Resolution | null;
|
|
20
|
+
readonly agreement: ShadowAgreement;
|
|
21
|
+
/**
|
|
22
|
+
* Symmetric difference of the two top resolutions' `evidence` arrays,
|
|
23
|
+
* keyed on `ResolutionEvidence.kind`.
|
|
24
|
+
*
|
|
25
|
+
* - For `'both-agree'` and `'both-empty'` agreements, always empty.
|
|
26
|
+
* - For `'both-disagree'`, contains evidence kinds present on exactly one
|
|
27
|
+
* side (not in both).
|
|
28
|
+
* - For `'only-legacy'`, contains all of legacy's top evidence.
|
|
29
|
+
* - For `'only-new'`, contains all of new's top evidence.
|
|
30
|
+
*/
|
|
31
|
+
readonly evidenceDelta: readonly ResolutionEvidence[];
|
|
32
|
+
}
|
|
33
|
+
export interface ShadowCallsite {
|
|
34
|
+
readonly filePath: string;
|
|
35
|
+
readonly line: number;
|
|
36
|
+
readonly col: number;
|
|
37
|
+
readonly calledName: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compare two `Resolution[]` arrays (top matches at `[0]`) and produce a
|
|
41
|
+
* `ShadowDiff`. Pure function.
|
|
42
|
+
*
|
|
43
|
+
* Agreement rules:
|
|
44
|
+
* - both arrays empty → `'both-empty'`, `evidenceDelta: []`
|
|
45
|
+
* - legacy empty, new non-empty → `'only-new'`, `evidenceDelta` = new's top evidence
|
|
46
|
+
* - legacy non-empty, new empty → `'only-legacy'`, `evidenceDelta` = legacy's top evidence
|
|
47
|
+
* - both non-empty, same top `def.nodeId` → `'both-agree'`, `evidenceDelta: []`
|
|
48
|
+
* - both non-empty, different top `def.nodeId` → `'both-disagree'`,
|
|
49
|
+
* `evidenceDelta` = symmetric difference by `ResolutionEvidence.kind`
|
|
50
|
+
* (first occurrence of a kind-only-on-legacy then kind-only-on-new; order
|
|
51
|
+
* preserved from input arrays)
|
|
52
|
+
*
|
|
53
|
+
* Evidence-delta rationale: callers aggregating divergences want to know
|
|
54
|
+
* which signal kinds explain a disagreement. Keying on `kind` (not full
|
|
55
|
+
* equality over `weight`/`note`) avoids spurious deltas when the same
|
|
56
|
+
* signal fires with slightly different calibration weights on each side.
|
|
57
|
+
*/
|
|
58
|
+
export declare function diffResolutions(callsite: ShadowCallsite, legacy: readonly Resolution[], newResult: readonly Resolution[]): ShadowDiff;
|
|
59
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/scope-resolution/shadow/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIlE,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,aAAa,GACb,UAAU,GACV,eAAe,GACf,YAAY,CAAC;AAEjB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAID;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,SAAS,EAAE,SAAS,UAAU,EAAE,GAC/B,UAAU,CAoBZ"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow-mode diff logic — RFC §6.3.
|
|
3
|
+
*
|
|
4
|
+
* Pure comparison logic for shadow mode. Takes two `Resolution[]` (legacy
|
|
5
|
+
* DAG result + new scope-based registry result) and produces a structured
|
|
6
|
+
* diff record for the parity dashboard.
|
|
7
|
+
*
|
|
8
|
+
* Consumed by the Ring 2 PKG shadow harness (#923), which dual-runs each
|
|
9
|
+
* call through legacy + new paths, diffs results, and persists per-run JSON
|
|
10
|
+
* for the parity dashboard.
|
|
11
|
+
*
|
|
12
|
+
* Part of RFC #909 Ring 2 SHARED — #918.
|
|
13
|
+
*/
|
|
14
|
+
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* Compare two `Resolution[]` arrays (top matches at `[0]`) and produce a
|
|
17
|
+
* `ShadowDiff`. Pure function.
|
|
18
|
+
*
|
|
19
|
+
* Agreement rules:
|
|
20
|
+
* - both arrays empty → `'both-empty'`, `evidenceDelta: []`
|
|
21
|
+
* - legacy empty, new non-empty → `'only-new'`, `evidenceDelta` = new's top evidence
|
|
22
|
+
* - legacy non-empty, new empty → `'only-legacy'`, `evidenceDelta` = legacy's top evidence
|
|
23
|
+
* - both non-empty, same top `def.nodeId` → `'both-agree'`, `evidenceDelta: []`
|
|
24
|
+
* - both non-empty, different top `def.nodeId` → `'both-disagree'`,
|
|
25
|
+
* `evidenceDelta` = symmetric difference by `ResolutionEvidence.kind`
|
|
26
|
+
* (first occurrence of a kind-only-on-legacy then kind-only-on-new; order
|
|
27
|
+
* preserved from input arrays)
|
|
28
|
+
*
|
|
29
|
+
* Evidence-delta rationale: callers aggregating divergences want to know
|
|
30
|
+
* which signal kinds explain a disagreement. Keying on `kind` (not full
|
|
31
|
+
* equality over `weight`/`note`) avoids spurious deltas when the same
|
|
32
|
+
* signal fires with slightly different calibration weights on each side.
|
|
33
|
+
*/
|
|
34
|
+
export function diffResolutions(callsite, legacy, newResult) {
|
|
35
|
+
const legacyTop = legacy.length > 0 ? legacy[0] : null;
|
|
36
|
+
const newTop = newResult.length > 0 ? newResult[0] : null;
|
|
37
|
+
const agreement = (() => {
|
|
38
|
+
if (legacyTop === null && newTop === null)
|
|
39
|
+
return 'both-empty';
|
|
40
|
+
if (legacyTop === null)
|
|
41
|
+
return 'only-new';
|
|
42
|
+
if (newTop === null)
|
|
43
|
+
return 'only-legacy';
|
|
44
|
+
return legacyTop.def.nodeId === newTop.def.nodeId ? 'both-agree' : 'both-disagree';
|
|
45
|
+
})();
|
|
46
|
+
const evidenceDelta = computeEvidenceDelta(legacyTop, newTop, agreement);
|
|
47
|
+
return {
|
|
48
|
+
callsite,
|
|
49
|
+
legacy: legacyTop,
|
|
50
|
+
newResult: newTop,
|
|
51
|
+
agreement,
|
|
52
|
+
evidenceDelta,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// ─── Internal helpers ───────────────────────────────────────────────────────
|
|
56
|
+
/**
|
|
57
|
+
* Symmetric difference of two evidence arrays, keyed on
|
|
58
|
+
* `ResolutionEvidence.kind`. Preserves input order: legacy-only signals
|
|
59
|
+
* first (in legacy's original order), then new-only signals (in new's order).
|
|
60
|
+
*
|
|
61
|
+
* For `'both-agree'` / `'both-empty'` the delta is empty by contract. For
|
|
62
|
+
* `'only-legacy'` / `'only-new'` one side's evidence is the delta (nothing to
|
|
63
|
+
* subtract against).
|
|
64
|
+
*/
|
|
65
|
+
function computeEvidenceDelta(legacy, newResult, agreement) {
|
|
66
|
+
if (agreement === 'both-agree' || agreement === 'both-empty')
|
|
67
|
+
return [];
|
|
68
|
+
if (agreement === 'only-legacy')
|
|
69
|
+
return legacy.evidence;
|
|
70
|
+
if (agreement === 'only-new')
|
|
71
|
+
return newResult.evidence;
|
|
72
|
+
// both-disagree: symmetric difference keyed on `kind`
|
|
73
|
+
const legacyKinds = new Set(legacy.evidence.map((e) => e.kind));
|
|
74
|
+
const newKinds = new Set(newResult.evidence.map((e) => e.kind));
|
|
75
|
+
const onlyInLegacy = legacy.evidence.filter((e) => !newKinds.has(e.kind));
|
|
76
|
+
const onlyInNew = newResult.evidence.filter((e) => !legacyKinds.has(e.kind));
|
|
77
|
+
return [...onlyInLegacy, ...onlyInNew];
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/scope-resolution/shadow/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAsCH,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAwB,EACxB,MAA6B,EAC7B,SAAgC;IAEhC,MAAM,SAAS,GAAsB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,MAAM,MAAM,GAAsB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE7E,MAAM,SAAS,GAAoB,CAAC,GAAG,EAAE;QACvC,IAAI,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,YAAY,CAAC;QAC/D,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC;QAC1C,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,aAAa,CAAC;QAC1C,OAAO,SAAS,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC;IACrF,CAAC,CAAC,EAAE,CAAC;IAEL,MAAM,aAAa,GAAG,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAEzE,OAAO;QACL,QAAQ;QACR,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,MAAM;QACjB,SAAS;QACT,aAAa;KACd,CAAC;AACJ,CAAC;AAED,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,SAAS,oBAAoB,CAC3B,MAAyB,EACzB,SAA4B,EAC5B,SAA0B;IAE1B,IAAI,SAAS,KAAK,YAAY,IAAI,SAAS,KAAK,YAAY;QAAE,OAAO,EAAE,CAAC;IACxE,IAAI,SAAS,KAAK,aAAa;QAAE,OAAO,MAAO,CAAC,QAAQ,CAAC;IACzD,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,SAAU,CAAC,QAAQ,CAAC;IAEzD,sDAAsD;IACtD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEjE,MAAM,YAAY,GAAG,MAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,SAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAE9E,OAAO,CAAC,GAAG,YAAY,EAAE,GAAG,SAAS,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -1447,7 +1447,14 @@ export class LocalBackend {
|
|
|
1447
1447
|
}
|
|
1448
1448
|
let diffOutput;
|
|
1449
1449
|
try {
|
|
1450
|
-
|
|
1450
|
+
// maxBuffer raised from Node's 1MB default to 256MB to avoid ENOBUFS on
|
|
1451
|
+
// repos with large unstaged/untracked diffs (e.g. unignored build folders).
|
|
1452
|
+
// See issue: spawnSync git ENOBUFS in detect_changes(scope="unstaged").
|
|
1453
|
+
diffOutput = execFileSync('git', diffArgs, {
|
|
1454
|
+
cwd: repo.repoPath,
|
|
1455
|
+
encoding: 'utf-8',
|
|
1456
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
1457
|
+
});
|
|
1451
1458
|
}
|
|
1452
1459
|
catch (err) {
|
|
1453
1460
|
return { error: `Git diff failed: ${err.message}` };
|
|
@@ -1662,6 +1669,8 @@ export class LocalBackend {
|
|
|
1662
1669
|
cwd: repo.repoPath,
|
|
1663
1670
|
encoding: 'utf-8',
|
|
1664
1671
|
timeout: 5000,
|
|
1672
|
+
// Avoid ENOBUFS on large repos: rg -l can list many files.
|
|
1673
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
1665
1674
|
});
|
|
1666
1675
|
const files = output
|
|
1667
1676
|
.trim()
|
package/package.json
CHANGED