gitnexus 1.6.7-rc.1 → 1.6.7-rc.3
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/graph/types.d.ts +18 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +2 -2
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +10 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/cli/analyze.js +7 -5
- package/dist/cli/optional-grammars.d.ts +18 -4
- package/dist/cli/optional-grammars.js +51 -8
- package/dist/core/ingestion/languages/dart/query.js +11 -3
- package/dist/core/ingestion/languages/kotlin/query.js +11 -3
- package/dist/core/ingestion/languages/swift/query.js +11 -3
- package/dist/core/ingestion/model/registration-table.js +3 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +11 -3
- package/dist/core/ingestion/pipeline-phases/registry.d.ts +56 -0
- package/dist/core/ingestion/pipeline-phases/registry.js +48 -0
- package/dist/core/ingestion/pipeline.d.ts +21 -0
- package/dist/core/ingestion/pipeline.js +28 -20
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +11 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +36 -0
- package/dist/core/ingestion/taint/source-sink-config.js +16 -0
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +27 -0
- package/dist/core/ingestion/taint/source-sink-registry.js +35 -0
- package/dist/core/ingestion/workers/parse-worker.js +13 -0
- package/dist/core/lbug/csv-generator.js +14 -0
- package/dist/core/lbug/lbug-adapter.js +12 -0
- package/dist/core/lbug/schema.d.ts +2 -1
- package/dist/core/lbug/schema.js +22 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +8 -0
- package/dist/core/tree-sitter/parser-loader.js +70 -0
- package/dist/server/api.d.ts +1 -0
- package/dist/server/api.js +17 -2
- package/package.json +1 -1
- package/scripts/spikes/s1-reaching-def-index-bench.ts +151 -0
- package/scripts/spikes/s2-postdom-prototype.ts +162 -0
- package/web/assets/{agent-EkX7webX.js → agent-CKPMqImC.js} +1 -1
- package/web/assets/{architectureDiagram-UL44E2DR-BoczH8cv.js → architectureDiagram-UL44E2DR-D1EXI0zA.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-By5HB3b-.js → chunk-LCXTWHL2-Dfmux4m1.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-BQE_DkpL.js → chunk-RG4AUYOV-CAkzcoRj.js} +1 -1
- package/web/assets/{classDiagram-KGZ6W3CR-Dj_02GUH.js → classDiagram-KGZ6W3CR-Bv93af_b.js} +1 -1
- package/web/assets/{classDiagram-v2-72OJOZXJ-D-NArMpf.js → classDiagram-v2-72OJOZXJ-CLfEqHUa.js} +1 -1
- package/web/assets/{diagram-3NCE3AQN-VXtXDO95.js → diagram-3NCE3AQN-BqAtKUpW.js} +1 -1
- package/web/assets/{diagram-GF46GFSD-B1qab2Ah.js → diagram-GF46GFSD-CaBG6n6o.js} +1 -1
- package/web/assets/{diagram-QXG6HAR7-BSCHGzzT.js → diagram-QXG6HAR7-CZ-O3rcV.js} +1 -1
- package/web/assets/{diagram-WEQXMOUZ-DHtknmNT.js → diagram-WEQXMOUZ-P4lSL4GH.js} +1 -1
- package/web/assets/{erDiagram-L5TCEMPS-Db-IYTmm.js → erDiagram-L5TCEMPS-QN2eEP1e.js} +1 -1
- package/web/assets/{flowDiagram-H6V6AXG4-BHDoyVoW.js → flowDiagram-H6V6AXG4-CXbXImlN.js} +1 -1
- package/web/assets/{index-BR0IhgbR.js → index-CG6q8eTs.js} +6 -6
- package/web/assets/{infoDiagram-3YFTVSEB-6h8wbWEe.js → infoDiagram-3YFTVSEB-DmLICZx1.js} +1 -1
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-Dx2OkPk1.js → ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-CIIEZfqV.js → kanban-definition-75IXJCU3-DgDi9oJT.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-DUAqydRq.js → mindmap-definition-2TDM6QVE-CwR5sBB-.js} +1 -1
- package/web/assets/{pieDiagram-CU6KROY3-BntYuYZa.js → pieDiagram-CU6KROY3-By8g6f6B.js} +1 -1
- package/web/assets/{requirementDiagram-JXO7QTGE-QCD6I29n.js → requirementDiagram-JXO7QTGE-7oDcJ1_J.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-DScFwLz2.js → sequenceDiagram-VS2MUI6T-FySeKCUy.js} +1 -1
- package/web/assets/{stateDiagram-7D4R322I-AkRAm6Hl.js → stateDiagram-7D4R322I-CB2nABwH.js} +1 -1
- package/web/assets/{stateDiagram-v2-36443NZ5-BCK1vigR.js → stateDiagram-v2-36443NZ5-COBGd2RL.js} +1 -1
- package/web/assets/{timeline-definition-O6YCAMPW-BvpIVXjX.js → timeline-definition-O6YCAMPW-Ds2CnVZK.js} +1 -1
- package/web/assets/{vennDiagram-MWXL3ELB-BYGWk6dK.js → vennDiagram-MWXL3ELB-DUIEwXWp.js} +1 -1
- package/web/assets/{wardleyDiagram-CUQ6CDDI-Dk1z7H2T.js → wardleyDiagram-CUQ6CDDI-DEiFPQih.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-2N6NCSWN.js → xychartDiagram-N2JHSOCM-BUbayhST.js} +1 -1
- package/web/index.html +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Do NOT add Node.js-specific or browser-specific imports here.
|
|
6
6
|
*/
|
|
7
7
|
import { SupportedLanguages } from '../languages.js';
|
|
8
|
-
export type NodeLabel = 'Project' | 'Package' | 'Module' | 'Folder' | 'File' | 'Class' | 'Function' | 'Method' | 'Variable' | 'Interface' | 'Enum' | 'Decorator' | 'Import' | 'Type' | 'CodeElement' | 'Community' | 'Process' | 'Struct' | 'Macro' | 'Typedef' | 'Union' | 'Namespace' | 'Trait' | 'Impl' | 'TypeAlias' | 'Const' | 'Static' | 'Property' | 'Record' | 'Delegate' | 'Annotation' | 'Constructor' | 'Template' | 'Section' | 'Route' | 'Tool';
|
|
8
|
+
export type NodeLabel = 'Project' | 'Package' | 'Module' | 'Folder' | 'File' | 'Class' | 'Function' | 'Method' | 'Variable' | 'Interface' | 'Enum' | 'Decorator' | 'Import' | 'Type' | 'CodeElement' | 'Community' | 'Process' | 'Struct' | 'Macro' | 'Typedef' | 'Union' | 'Namespace' | 'Trait' | 'Impl' | 'TypeAlias' | 'Const' | 'Static' | 'Property' | 'Record' | 'Delegate' | 'Annotation' | 'Constructor' | 'Template' | 'Section' | 'Route' | 'Tool' | 'BasicBlock';
|
|
9
9
|
export type NodeProperties = {
|
|
10
10
|
name: string;
|
|
11
11
|
filePath: string;
|
|
@@ -45,6 +45,7 @@ export type NodeProperties = {
|
|
|
45
45
|
responseKeys?: string[];
|
|
46
46
|
errorKeys?: string[];
|
|
47
47
|
middleware?: string[];
|
|
48
|
+
text?: string;
|
|
48
49
|
[key: string]: unknown;
|
|
49
50
|
};
|
|
50
51
|
export type RelationshipType = 'CONTAINS' | 'CALLS' | 'INHERITS' | 'METHOD_OVERRIDES' | 'METHOD_IMPLEMENTS' | 'IMPORTS' | 'USES' | 'DEFINES' | 'DECORATES' | 'IMPLEMENTS' | 'EXTENDS' | 'HAS_METHOD' | 'HAS_PROPERTY' | 'ACCESSES' | 'MEMBER_OF' | 'STEP_IN_PROCESS' | 'HANDLES_ROUTE' | 'FETCHES' | 'HANDLES_TOOL' | 'ENTRY_POINT_OF' | 'WRAPS' | 'QUERIES'
|
|
@@ -63,7 +64,22 @@ export type RelationshipType = 'CONTAINS' | 'CALLS' | 'INHERITS' | 'METHOD_OVERR
|
|
|
63
64
|
* `reason` encodes the event name: `vue-emit: <eventName>`.
|
|
64
65
|
* Complements `BINDS_EVENT_HANDLER`; a Cypher query joining on the
|
|
65
66
|
* component File node reveals all (emitter, handler) pairs. */
|
|
66
|
-
| 'EMITS_EVENT'
|
|
67
|
+
| 'EMITS_EVENT'
|
|
68
|
+
/** Control-flow edge between two BasicBlock nodes (intra-procedural CFG). */
|
|
69
|
+
| 'CFG'
|
|
70
|
+
/** Data-dependence edge: a definition of `variable` reaches a use of it.
|
|
71
|
+
* The `variable` name is stored in the relation's existing `reason` column
|
|
72
|
+
* (M0/S1 verdict: LadybugDB has no secondary index on relationship
|
|
73
|
+
* properties, so a dedicated indexed column would not speed the
|
|
74
|
+
* variable-filtered path query). */
|
|
75
|
+
| 'REACHING_DEF'
|
|
76
|
+
/** A tainted value flows from source toward sink. */
|
|
77
|
+
| 'TAINTED'
|
|
78
|
+
/** A sanitizer clears taint along a flow. */
|
|
79
|
+
| 'SANITIZES'
|
|
80
|
+
/** Materialized source→sink taint path. Working name — final name/representation
|
|
81
|
+
* is confirmed when M3/M4 emits it; no persisted edge exists before then. */
|
|
82
|
+
| 'TAINT_PATH';
|
|
67
83
|
export interface GraphNode {
|
|
68
84
|
id: string;
|
|
69
85
|
label: NodeLabel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,UAAU,GACV,WAAW,GACX,MAAM,GACN,WAAW,GACX,QAAQ,GACR,MAAM,GACN,aAAa,GACb,WAAW,GACX,SAAS,GAET,QAAQ,GACR,OAAO,GACP,SAAS,GACT,OAAO,GACP,WAAW,GACX,OAAO,GACP,MAAM,GACN,WAAW,GACX,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,aAAa,GACb,UAAU,GACV,SAAS,GACT,OAAO,GACP,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
* Full DDL schemas remain in each package's own schema.ts because
|
|
8
8
|
* the CLI uses native LadybugDB and the web uses WASM.
|
|
9
9
|
*/
|
|
10
|
-
export declare const NODE_TABLES: readonly ["File", "Folder", "Function", "Class", "Interface", "Method", "CodeElement", "Community", "Process", "Section", "Struct", "Enum", "Macro", "Typedef", "Union", "Namespace", "Trait", "Impl", "TypeAlias", "Const", "Static", "Variable", "Property", "Record", "Delegate", "Annotation", "Constructor", "Template", "Module", "Route", "Tool"];
|
|
10
|
+
export declare const NODE_TABLES: readonly ["File", "Folder", "Function", "Class", "Interface", "Method", "CodeElement", "Community", "Process", "Section", "Struct", "Enum", "Macro", "Typedef", "Union", "Namespace", "Trait", "Impl", "TypeAlias", "Const", "Static", "Variable", "Property", "Record", "Delegate", "Annotation", "Constructor", "Template", "Module", "Route", "Tool", "BasicBlock"];
|
|
11
11
|
export type NodeTableName = (typeof NODE_TABLES)[number];
|
|
12
12
|
export declare const REL_TABLE_NAME = "CodeRelation";
|
|
13
|
-
export declare const REL_TYPES: readonly ["CONTAINS", "DEFINES", "IMPORTS", "CALLS", "EXTENDS", "IMPLEMENTS", "HAS_METHOD", "HAS_PROPERTY", "ACCESSES", "METHOD_OVERRIDES", "OVERRIDES", "METHOD_IMPLEMENTS", "MEMBER_OF", "STEP_IN_PROCESS", "HANDLES_ROUTE", "FETCHES", "HANDLES_TOOL", "ENTRY_POINT_OF", "WRAPS", "QUERIES"];
|
|
13
|
+
export declare const REL_TYPES: readonly ["CONTAINS", "DEFINES", "IMPORTS", "CALLS", "EXTENDS", "IMPLEMENTS", "HAS_METHOD", "HAS_PROPERTY", "ACCESSES", "METHOD_OVERRIDES", "OVERRIDES", "METHOD_IMPLEMENTS", "MEMBER_OF", "STEP_IN_PROCESS", "HANDLES_ROUTE", "FETCHES", "HANDLES_TOOL", "ENTRY_POINT_OF", "WRAPS", "QUERIES", "CFG", "REACHING_DEF", "TAINTED", "SANITIZES", "TAINT_PATH"];
|
|
14
14
|
export type RelType = (typeof REL_TYPES)[number];
|
|
15
15
|
export declare const EMBEDDING_TABLE_NAME = "CodeEmbedding";
|
|
16
16
|
//# sourceMappingURL=schema-constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-constants.d.ts","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"schema-constants.d.ts","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,wWAkCd,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C,eAAO,MAAM,SAAS,8VA6BZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC"}
|
|
@@ -39,6 +39,8 @@ export const NODE_TABLES = [
|
|
|
39
39
|
'Module',
|
|
40
40
|
'Route',
|
|
41
41
|
'Tool',
|
|
42
|
+
// Taint/PDG substrate (issue #2080) — inert until M1 (#2081) emits blocks.
|
|
43
|
+
'BasicBlock',
|
|
42
44
|
];
|
|
43
45
|
export const REL_TABLE_NAME = 'CodeRelation';
|
|
44
46
|
export const REL_TYPES = [
|
|
@@ -62,6 +64,14 @@ export const REL_TYPES = [
|
|
|
62
64
|
'ENTRY_POINT_OF',
|
|
63
65
|
'WRAPS',
|
|
64
66
|
'QUERIES',
|
|
67
|
+
// Taint/PDG substrate (issue #2080) — reserved edge types, emitted by no
|
|
68
|
+
// phase yet (CFG → M1, REACHING_DEF → M2, TAINTED/SANITIZES/TAINT_PATH →
|
|
69
|
+
// M3/M4). REACHING_DEF's variable name rides the relation's `reason` column.
|
|
70
|
+
'CFG',
|
|
71
|
+
'REACHING_DEF',
|
|
72
|
+
'TAINTED',
|
|
73
|
+
'SANITIZES',
|
|
74
|
+
'TAINT_PATH',
|
|
65
75
|
];
|
|
66
76
|
export const EMBEDDING_TABLE_NAME = 'CodeEmbedding';
|
|
67
77
|
//# sourceMappingURL=schema-constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-constants.js","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,WAAW;IACX,QAAQ;IACR,aAAa;IACb,WAAW;IACX,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;
|
|
1
|
+
{"version":3,"file":"schema-constants.js","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,WAAW;IACX,QAAQ;IACR,aAAa;IACb,WAAW;IACX,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;IACN,2EAA2E;IAC3E,YAAY;CACJ,CAAC;AAIX,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;IACP,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,UAAU;IACV,kBAAkB;IAClB,WAAW,EAAE,mEAAmE;IAChF,mBAAmB;IACnB,WAAW;IACX,iBAAiB;IACjB,eAAe;IACf,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,OAAO;IACP,SAAS;IACT,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,KAAK;IACL,cAAc;IACd,SAAS;IACT,WAAW;IACX,YAAY;CACJ,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC"}
|
package/dist/cli/analyze.js
CHANGED
|
@@ -19,7 +19,7 @@ import { getGitRoot, hasGitDir, getDefaultBranch } from '../storage/git.js';
|
|
|
19
19
|
import { loadAnalyzeConfig, mergeAnalyzeOptions, resolveDefaultBranch, validateBranchName, GitNexusRcError, } from './analyze-config.js';
|
|
20
20
|
import { runFullAnalysis } from '../core/run-analyze.js';
|
|
21
21
|
import { getMaxFileSizeBannerMessage } from '../core/ingestion/utils/max-file-size.js';
|
|
22
|
-
import { warnMissingOptionalGrammars } from './optional-grammars.js';
|
|
22
|
+
import { warnMissingOptionalGrammars, getOptionalGrammarExtensions } from './optional-grammars.js';
|
|
23
23
|
import { glob } from 'glob';
|
|
24
24
|
import fs from 'fs/promises';
|
|
25
25
|
import { cliError } from './cli-message.js';
|
|
@@ -691,11 +691,13 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
|
|
|
691
691
|
console.log(' Note: --index-only overrides --skills; community skill files will not be written.\n');
|
|
692
692
|
}
|
|
693
693
|
// If the target repo contains files an optional grammar would parse but
|
|
694
|
-
// that grammar's native binding is absent
|
|
695
|
-
//
|
|
696
|
-
// degraded index.
|
|
694
|
+
// that grammar's native binding is absent (or disabled via
|
|
695
|
+
// GITNEXUS_SKIP_OPTIONAL_GRAMMARS), warn before analysis so users learn why
|
|
696
|
+
// those files end up unparsed instead of silently getting a degraded index.
|
|
697
|
+
// The extension set is derived from OPTIONAL_GRAMMARS so it can't drift.
|
|
697
698
|
try {
|
|
698
|
-
const
|
|
699
|
+
const optionalGlobs = getOptionalGrammarExtensions().map((e) => `**/*${e}`);
|
|
700
|
+
const matches = await glob(optionalGlobs, {
|
|
699
701
|
cwd: repoPath,
|
|
700
702
|
ignore: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**'],
|
|
701
703
|
dot: false,
|
|
@@ -4,19 +4,33 @@
|
|
|
4
4
|
* tree-sitter-dart, tree-sitter-proto, and tree-sitter-swift are vendored
|
|
5
5
|
* under vendor/ and materialized into node_modules/ at postinstall. Dart
|
|
6
6
|
* and Proto are built from source with node-gyp; Swift ships platform
|
|
7
|
-
* prebuilds activated via node-gyp-build.
|
|
7
|
+
* prebuilds activated via node-gyp-build. tree-sitter-kotlin is a declared
|
|
8
|
+
* optionalDependency (not vendored). All can be skipped via
|
|
8
9
|
* GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or can silently
|
|
9
|
-
* soft-fail when the toolchain is missing (Dart/Proto)
|
|
10
|
-
* matches the host platform (Swift)
|
|
10
|
+
* soft-fail when the toolchain is missing (Dart/Proto), when no prebuild
|
|
11
|
+
* matches the host platform (Swift), or when the optional install was
|
|
12
|
+
* skipped or its native build failed (Kotlin).
|
|
11
13
|
*
|
|
12
14
|
* Either path produces the same observable: the .node binding is absent
|
|
13
15
|
* at runtime. This helper detects that condition and surfaces a single
|
|
14
|
-
* stderr line per missing grammar so users learn why .dart/.proto/.swift
|
|
16
|
+
* stderr line per missing grammar so users learn why .dart/.proto/.swift/.kt
|
|
15
17
|
* support is unavailable instead of silently getting a degraded index.
|
|
16
18
|
*/
|
|
19
|
+
/**
|
|
20
|
+
* The file extensions backed by an optional grammar — the single source for
|
|
21
|
+
* the `analyze` preflight glob (so the glob can't drift from this list).
|
|
22
|
+
*/
|
|
23
|
+
export declare function getOptionalGrammarExtensions(): string[];
|
|
17
24
|
export interface MissingGrammar {
|
|
18
25
|
name: string;
|
|
19
26
|
extensions: string[];
|
|
27
|
+
/**
|
|
28
|
+
* `missing` — the native binding could not be loaded (not installed / build
|
|
29
|
+
* soft-failed / no prebuild). `skipped` — the binding is fine but the user
|
|
30
|
+
* disabled it via `GITNEXUS_SKIP_OPTIONAL_GRAMMARS`. Drives the warning text
|
|
31
|
+
* so a deliberate opt-out is not told to reinstall.
|
|
32
|
+
*/
|
|
33
|
+
reason: 'missing' | 'skipped';
|
|
20
34
|
}
|
|
21
35
|
/**
|
|
22
36
|
* Returns the list of optional grammars whose native binding cannot be
|
|
@@ -4,24 +4,51 @@
|
|
|
4
4
|
* tree-sitter-dart, tree-sitter-proto, and tree-sitter-swift are vendored
|
|
5
5
|
* under vendor/ and materialized into node_modules/ at postinstall. Dart
|
|
6
6
|
* and Proto are built from source with node-gyp; Swift ships platform
|
|
7
|
-
* prebuilds activated via node-gyp-build.
|
|
7
|
+
* prebuilds activated via node-gyp-build. tree-sitter-kotlin is a declared
|
|
8
|
+
* optionalDependency (not vendored). All can be skipped via
|
|
8
9
|
* GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or can silently
|
|
9
|
-
* soft-fail when the toolchain is missing (Dart/Proto)
|
|
10
|
-
* matches the host platform (Swift)
|
|
10
|
+
* soft-fail when the toolchain is missing (Dart/Proto), when no prebuild
|
|
11
|
+
* matches the host platform (Swift), or when the optional install was
|
|
12
|
+
* skipped or its native build failed (Kotlin).
|
|
11
13
|
*
|
|
12
14
|
* Either path produces the same observable: the .node binding is absent
|
|
13
15
|
* at runtime. This helper detects that condition and surfaces a single
|
|
14
|
-
* stderr line per missing grammar so users learn why .dart/.proto/.swift
|
|
16
|
+
* stderr line per missing grammar so users learn why .dart/.proto/.swift/.kt
|
|
15
17
|
* support is unavailable instead of silently getting a degraded index.
|
|
16
18
|
*/
|
|
17
19
|
import { createRequire } from 'module';
|
|
20
|
+
import { SupportedLanguages } from '../_shared/index.js';
|
|
21
|
+
import { isGrammarRuntimeSkipped } from '../core/tree-sitter/parser-loader.js';
|
|
18
22
|
import { cliWarn } from './cli-message.js';
|
|
19
23
|
const _require = createRequire(import.meta.url);
|
|
20
24
|
const OPTIONAL_GRAMMARS = [
|
|
21
|
-
{
|
|
25
|
+
{
|
|
26
|
+
name: 'tree-sitter-dart',
|
|
27
|
+
pkg: 'tree-sitter-dart',
|
|
28
|
+
extensions: ['.dart'],
|
|
29
|
+
language: SupportedLanguages.Dart,
|
|
30
|
+
},
|
|
22
31
|
{ name: 'tree-sitter-proto', pkg: 'tree-sitter-proto', extensions: ['.proto'] },
|
|
23
|
-
{
|
|
32
|
+
{
|
|
33
|
+
name: 'tree-sitter-swift',
|
|
34
|
+
pkg: 'tree-sitter-swift',
|
|
35
|
+
extensions: ['.swift'],
|
|
36
|
+
language: SupportedLanguages.Swift,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'tree-sitter-kotlin',
|
|
40
|
+
pkg: 'tree-sitter-kotlin',
|
|
41
|
+
extensions: ['.kt', '.kts'],
|
|
42
|
+
language: SupportedLanguages.Kotlin,
|
|
43
|
+
},
|
|
24
44
|
];
|
|
45
|
+
/**
|
|
46
|
+
* The file extensions backed by an optional grammar — the single source for
|
|
47
|
+
* the `analyze` preflight glob (so the glob can't drift from this list).
|
|
48
|
+
*/
|
|
49
|
+
export function getOptionalGrammarExtensions() {
|
|
50
|
+
return [...new Set(OPTIONAL_GRAMMARS.flatMap((g) => g.extensions))];
|
|
51
|
+
}
|
|
25
52
|
/**
|
|
26
53
|
* Returns the list of optional grammars whose native binding cannot be
|
|
27
54
|
* loaded. Actually `require()`s the package — `require.resolve` would
|
|
@@ -41,6 +68,13 @@ const OPTIONAL_GRAMMARS = [
|
|
|
41
68
|
export function detectMissingOptionalGrammars() {
|
|
42
69
|
const missing = [];
|
|
43
70
|
for (const g of OPTIONAL_GRAMMARS) {
|
|
71
|
+
// Deliberate runtime opt-out comes first: even an installed binding is
|
|
72
|
+
// treated as unavailable, with a `skipped` reason so the warning says so
|
|
73
|
+
// instead of suggesting a reinstall (#2101 review).
|
|
74
|
+
if (g.language !== undefined && isGrammarRuntimeSkipped(g.language)) {
|
|
75
|
+
missing.push({ name: g.name, extensions: g.extensions, reason: 'skipped' });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
44
78
|
try {
|
|
45
79
|
_require(g.pkg);
|
|
46
80
|
}
|
|
@@ -59,7 +93,7 @@ export function detectMissingOptionalGrammars() {
|
|
|
59
93
|
// there for tool-data stdout output).
|
|
60
94
|
cliWarn(`GitNexus: optional grammar "${g.name}" is installed but failed to load (${msg.slice(0, 200)}). ${g.extensions.join('/')} files will not be parsed.`, { grammar: g.name, extensions: g.extensions, error: msg });
|
|
61
95
|
}
|
|
62
|
-
missing.push({ name: g.name, extensions: g.extensions });
|
|
96
|
+
missing.push({ name: g.name, extensions: g.extensions, reason: 'missing' });
|
|
63
97
|
}
|
|
64
98
|
}
|
|
65
99
|
return missing;
|
|
@@ -86,6 +120,15 @@ export function warnMissingOptionalGrammars(opts) {
|
|
|
86
120
|
if (relevantExtensions && !g.extensions.some((e) => relevantExtensions.has(e))) {
|
|
87
121
|
continue;
|
|
88
122
|
}
|
|
89
|
-
|
|
123
|
+
const exts = g.extensions.join('/');
|
|
124
|
+
const message = g.reason === 'skipped'
|
|
125
|
+
? `GitNexus${ctx}: optional grammar "${g.name}" is disabled via GITNEXUS_SKIP_OPTIONAL_GRAMMARS — ${exts} files will not be parsed. Unset the variable to re-enable.`
|
|
126
|
+
: `GitNexus${ctx}: optional grammar "${g.name}" is unavailable — ${exts} files will not be parsed. Reinstall without GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (and ensure python3, make, g++) to enable.`;
|
|
127
|
+
cliWarn(message, {
|
|
128
|
+
grammar: g.name,
|
|
129
|
+
extensions: g.extensions,
|
|
130
|
+
reason: g.reason,
|
|
131
|
+
context: opts?.context,
|
|
132
|
+
});
|
|
90
133
|
}
|
|
91
134
|
}
|
|
@@ -22,7 +22,15 @@
|
|
|
22
22
|
* - Parameter / return / receiver type bindings and arity metadata.
|
|
23
23
|
*/
|
|
24
24
|
import Parser from 'tree-sitter';
|
|
25
|
-
import
|
|
25
|
+
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
26
|
+
// `tree-sitter-dart` is an optional/vendored grammar that may be absent on a
|
|
27
|
+
// default install. Loaded lazily + guarded via parser-loader rather than
|
|
28
|
+
// statically imported: this module is pulled onto the main thread eagerly by
|
|
29
|
+
// the scope-resolution registry and the language-provider index, so a top-level
|
|
30
|
+
// `import Dart from 'tree-sitter-dart'` would throw ERR_MODULE_NOT_FOUND at
|
|
31
|
+
// module-load and crash `analyze` even for repos with no Dart files (#2091,
|
|
32
|
+
// #2093). The grammar is only ever needed inside the lazy getters below.
|
|
33
|
+
import { getLanguageGrammar } from '../../../tree-sitter/parser-loader.js';
|
|
26
34
|
const DART_SCOPE_QUERY = `
|
|
27
35
|
; ── Scopes ───────────────────────────────────────────────────────────────────
|
|
28
36
|
(program) @scope.module
|
|
@@ -130,13 +138,13 @@ let _query = null;
|
|
|
130
138
|
export function getDartParser() {
|
|
131
139
|
if (_parser === null) {
|
|
132
140
|
_parser = new Parser();
|
|
133
|
-
_parser.setLanguage(Dart);
|
|
141
|
+
_parser.setLanguage(getLanguageGrammar(SupportedLanguages.Dart));
|
|
134
142
|
}
|
|
135
143
|
return _parser;
|
|
136
144
|
}
|
|
137
145
|
export function getDartScopeQuery() {
|
|
138
146
|
if (_query === null) {
|
|
139
|
-
_query = new Parser.Query(Dart, DART_SCOPE_QUERY);
|
|
147
|
+
_query = new Parser.Query(getLanguageGrammar(SupportedLanguages.Dart), DART_SCOPE_QUERY);
|
|
140
148
|
}
|
|
141
149
|
return _query;
|
|
142
150
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import Parser from 'tree-sitter';
|
|
2
|
-
import
|
|
2
|
+
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
3
|
+
// `tree-sitter-kotlin` is an optionalDependency that may be absent on a default
|
|
4
|
+
// install (or fail its native build). Loaded lazily + guarded via parser-loader
|
|
5
|
+
// rather than statically imported: this module is pulled onto the main thread
|
|
6
|
+
// eagerly by the scope-resolution registry and the language-provider index, so
|
|
7
|
+
// a top-level `import Kotlin from 'tree-sitter-kotlin'` would throw
|
|
8
|
+
// ERR_MODULE_NOT_FOUND at module-load and crash `analyze` even for repos with no
|
|
9
|
+
// Kotlin files (#2091, #2093). The grammar is only ever needed in the getters.
|
|
10
|
+
import { getLanguageGrammar } from '../../../tree-sitter/parser-loader.js';
|
|
3
11
|
const KOTLIN_SCOPE_QUERY = `
|
|
4
12
|
;; Scopes
|
|
5
13
|
(source_file) @scope.module
|
|
@@ -176,13 +184,13 @@ let query = null;
|
|
|
176
184
|
export function getKotlinParser() {
|
|
177
185
|
if (parser === null) {
|
|
178
186
|
parser = new Parser();
|
|
179
|
-
parser.setLanguage(Kotlin);
|
|
187
|
+
parser.setLanguage(getLanguageGrammar(SupportedLanguages.Kotlin));
|
|
180
188
|
}
|
|
181
189
|
return parser;
|
|
182
190
|
}
|
|
183
191
|
export function getKotlinScopeQuery() {
|
|
184
192
|
if (query === null) {
|
|
185
|
-
query = new Parser.Query(Kotlin, KOTLIN_SCOPE_QUERY);
|
|
193
|
+
query = new Parser.Query(getLanguageGrammar(SupportedLanguages.Kotlin), KOTLIN_SCOPE_QUERY);
|
|
186
194
|
}
|
|
187
195
|
return query;
|
|
188
196
|
}
|
|
@@ -42,7 +42,15 @@
|
|
|
42
42
|
* tree-sitter init cost per file.
|
|
43
43
|
*/
|
|
44
44
|
import Parser from 'tree-sitter';
|
|
45
|
-
import
|
|
45
|
+
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
46
|
+
// `tree-sitter-swift` is an optional/vendored grammar that may be absent on a
|
|
47
|
+
// default install. It is loaded lazily + guarded via parser-loader rather than
|
|
48
|
+
// statically imported: this module is pulled onto the main thread eagerly by
|
|
49
|
+
// the scope-resolution registry and the language-provider index, so a top-level
|
|
50
|
+
// `import Swift from 'tree-sitter-swift'` would throw ERR_MODULE_NOT_FOUND at
|
|
51
|
+
// module-load and crash `analyze` even for repos with no Swift files (#2091,
|
|
52
|
+
// #2093). The grammar is only ever needed inside the lazy getters below.
|
|
53
|
+
import { getLanguageGrammar } from '../../../tree-sitter/parser-loader.js';
|
|
46
54
|
const SWIFT_SCOPE_QUERY = `
|
|
47
55
|
;; ── Scopes ──────────────────────────────────────────────────────────
|
|
48
56
|
(source_file) @scope.module
|
|
@@ -182,13 +190,13 @@ let _query = null;
|
|
|
182
190
|
export function getSwiftParser() {
|
|
183
191
|
if (_parser === null) {
|
|
184
192
|
_parser = new Parser();
|
|
185
|
-
_parser.setLanguage(Swift);
|
|
193
|
+
_parser.setLanguage(getLanguageGrammar(SupportedLanguages.Swift));
|
|
186
194
|
}
|
|
187
195
|
return _parser;
|
|
188
196
|
}
|
|
189
197
|
export function getSwiftScopeQuery() {
|
|
190
198
|
if (_query === null) {
|
|
191
|
-
_query = new Parser.Query(Swift, SWIFT_SCOPE_QUERY);
|
|
199
|
+
_query = new Parser.Query(getLanguageGrammar(SupportedLanguages.Swift), SWIFT_SCOPE_QUERY);
|
|
192
200
|
}
|
|
193
201
|
return _query;
|
|
194
202
|
}
|
|
@@ -116,6 +116,9 @@ const LABEL_BEHAVIOR = {
|
|
|
116
116
|
Section: 'inert',
|
|
117
117
|
Route: 'inert',
|
|
118
118
|
Tool: 'inert',
|
|
119
|
+
// Taint/PDG substrate (issue #2080) — a control-flow node, never a
|
|
120
|
+
// symbol-resolution target. Inert: file index only, no owner scope.
|
|
121
|
+
BasicBlock: 'inert',
|
|
119
122
|
};
|
|
120
123
|
// ---------------------------------------------------------------------------
|
|
121
124
|
// Derived runtime collections — all keyed off LABEL_BEHAVIOR
|
|
@@ -21,3 +21,4 @@ export { processesPhase, type ProcessesOutput } from './processes.js';
|
|
|
21
21
|
export { runPipeline } from './runner.js';
|
|
22
22
|
export type { PipelinePhase, PipelineContext, PhaseResult } from './types.js';
|
|
23
23
|
export { getPhaseOutput } from './types.js';
|
|
24
|
+
export { PhaseRegistry, type RegisterPhaseOptions } from './registry.js';
|
|
@@ -22,3 +22,4 @@ export { processesPhase } from './processes.js';
|
|
|
22
22
|
// ── Infrastructure ─────────────────────────────────────────────────────────
|
|
23
23
|
export { runPipeline } from './runner.js';
|
|
24
24
|
export { getPhaseOutput } from './types.js';
|
|
25
|
+
export { PhaseRegistry } from './registry.js';
|
|
@@ -20,9 +20,9 @@ import { fileContentHash, computeChunkHash, loadParseCacheChunk, persistParseCac
|
|
|
20
20
|
import { clearParsedFileStore, persistParsedFileChunk, getDurableParsedFileDir, loadDurableParsedFileIndex, restoreDurableParsedFileShard, } from '../../../storage/parsedfile-store.js';
|
|
21
21
|
import { processRoutesFromExtracted, buildExportedTypeMapFromGraph, } from '../call-processor.js';
|
|
22
22
|
import { createSemanticModel } from '../model/index.js';
|
|
23
|
-
import { getLanguageFromFilename } from '../../../_shared/index.js';
|
|
23
|
+
import { getLanguageFromFilename, } from '../../../_shared/index.js';
|
|
24
24
|
import { readFileContents } from '../filesystem-walker.js';
|
|
25
|
-
import { isLanguageAvailable } from '../../tree-sitter/parser-loader.js';
|
|
25
|
+
import { isLanguageAvailable, isGrammarRuntimeSkipped } from '../../tree-sitter/parser-loader.js';
|
|
26
26
|
import { createWorkerPool, workerPoolDisabledByEnv, resolveAutoPoolSize, WorkerPoolInitializationError, WorkerPoolDisabledError, } from '../workers/worker-pool.js';
|
|
27
27
|
import fs from 'node:fs';
|
|
28
28
|
import path from 'node:path';
|
|
@@ -167,7 +167,15 @@ export async function runChunkedParseAndResolve(graph, scannedFiles, allPaths, t
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
for (const [lang, count] of skippedByLang) {
|
|
170
|
-
|
|
170
|
+
// Distinguish a deliberate runtime opt-out from a genuinely-missing binding
|
|
171
|
+
// so we don't tell a user who set GITNEXUS_SKIP_OPTIONAL_GRAMMARS to
|
|
172
|
+
// `npm rebuild` a grammar that built fine (#2091/#2093 review).
|
|
173
|
+
if (isGrammarRuntimeSkipped(lang)) {
|
|
174
|
+
logger.warn(`Skipping ${count} ${lang} file(s) — ${lang} parsing disabled via GITNEXUS_SKIP_OPTIONAL_GRAMMARS.`);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
logger.warn(`Skipping ${count} ${lang} file(s) — ${lang} parser not available (native binding may not have built). Try: npm rebuild tree-sitter-${lang}`);
|
|
178
|
+
}
|
|
171
179
|
}
|
|
172
180
|
// Sort parseableScanned alphabetically for stable chunk membership
|
|
173
181
|
// across runs (Finding 4). Without this, filesystem-scan order can
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase registry seam (issue #2080, taint/PDG substrate M0).
|
|
3
|
+
*
|
|
4
|
+
* A small, behaviour-preserving abstraction over phase-list *assembly*. Today
|
|
5
|
+
* `buildPhaseList` is a hand-maintained array with a single ad-hoc
|
|
6
|
+
* `if (!skipGraphPhases)` guard; this registry generalises that guard into a
|
|
7
|
+
* per-phase `enabledWhen` predicate so later milestones can register opt-in
|
|
8
|
+
* phases (e.g. CFG → M1 #2081) without editing the array each time.
|
|
9
|
+
*
|
|
10
|
+
* M0 wires the seam with **no behaviour change**: `build(options)` must return
|
|
11
|
+
* a phase list identical in membership and order to the legacy array for every
|
|
12
|
+
* options combination. The registry covers only list assembly — the runner,
|
|
13
|
+
* topological sort, `PipelinePhase.execute`, and any result-extraction guards
|
|
14
|
+
* (e.g. the `skipGraphPhases` check in `runPipelineFromRepo`) are untouched.
|
|
15
|
+
*
|
|
16
|
+
* Generic over the options type so this module depends only on `PipelinePhase`
|
|
17
|
+
* (no import of `PipelineOptions`, which lives in `pipeline.ts` and would
|
|
18
|
+
* otherwise create an import cycle).
|
|
19
|
+
*/
|
|
20
|
+
import type { PipelinePhase } from './types.js';
|
|
21
|
+
/** Options accepted when registering a phase. */
|
|
22
|
+
export interface RegisterPhaseOptions<TOptions> {
|
|
23
|
+
/**
|
|
24
|
+
* Predicate deciding whether this phase is included for a given options
|
|
25
|
+
* object. Absent ⇒ the phase is always enabled. This is the generalised
|
|
26
|
+
* form of the legacy `if (!skipGraphPhases)` guard.
|
|
27
|
+
*
|
|
28
|
+
* `options` is required, not optional: callers normalize an absent options
|
|
29
|
+
* object once at `build()` (e.g. `buildPhaseList` passes `options ?? {}`), so
|
|
30
|
+
* individual predicates read `(o) => !o.skipGraphPhases` without a defensive
|
|
31
|
+
* `?.` on every phase (#2080 review S1).
|
|
32
|
+
*/
|
|
33
|
+
readonly enabledWhen?: (options: TOptions) => boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Ordered registry of pipeline phases. Not a global singleton — callers
|
|
37
|
+
* construct a fresh registry (so registration order is deterministic and there
|
|
38
|
+
* is no import-order or test-isolation hazard) and `build()` it per run.
|
|
39
|
+
*/
|
|
40
|
+
export declare class PhaseRegistry<TOptions = unknown> {
|
|
41
|
+
private readonly registrations;
|
|
42
|
+
/**
|
|
43
|
+
* Register a phase. This is the `registerPhase(phase, { enabledWhen })` seam
|
|
44
|
+
* named in issue #2080. Returns `this` for fluent chaining. Registration
|
|
45
|
+
* order is preserved by `build()`.
|
|
46
|
+
*/
|
|
47
|
+
register(phase: PipelinePhase, options?: RegisterPhaseOptions<TOptions>): this;
|
|
48
|
+
/**
|
|
49
|
+
* Build the ordered phase list for the given options. A phase is included
|
|
50
|
+
* iff it has no `enabledWhen` predicate or its predicate returns `true`.
|
|
51
|
+
* Order matches registration order. `options` is required — callers that may
|
|
52
|
+
* have no options normalize once at the call site (`options ?? {}`) so the
|
|
53
|
+
* predicates never see `undefined`.
|
|
54
|
+
*/
|
|
55
|
+
build(options: TOptions): PipelinePhase[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase registry seam (issue #2080, taint/PDG substrate M0).
|
|
3
|
+
*
|
|
4
|
+
* A small, behaviour-preserving abstraction over phase-list *assembly*. Today
|
|
5
|
+
* `buildPhaseList` is a hand-maintained array with a single ad-hoc
|
|
6
|
+
* `if (!skipGraphPhases)` guard; this registry generalises that guard into a
|
|
7
|
+
* per-phase `enabledWhen` predicate so later milestones can register opt-in
|
|
8
|
+
* phases (e.g. CFG → M1 #2081) without editing the array each time.
|
|
9
|
+
*
|
|
10
|
+
* M0 wires the seam with **no behaviour change**: `build(options)` must return
|
|
11
|
+
* a phase list identical in membership and order to the legacy array for every
|
|
12
|
+
* options combination. The registry covers only list assembly — the runner,
|
|
13
|
+
* topological sort, `PipelinePhase.execute`, and any result-extraction guards
|
|
14
|
+
* (e.g. the `skipGraphPhases` check in `runPipelineFromRepo`) are untouched.
|
|
15
|
+
*
|
|
16
|
+
* Generic over the options type so this module depends only on `PipelinePhase`
|
|
17
|
+
* (no import of `PipelineOptions`, which lives in `pipeline.ts` and would
|
|
18
|
+
* otherwise create an import cycle).
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Ordered registry of pipeline phases. Not a global singleton — callers
|
|
22
|
+
* construct a fresh registry (so registration order is deterministic and there
|
|
23
|
+
* is no import-order or test-isolation hazard) and `build()` it per run.
|
|
24
|
+
*/
|
|
25
|
+
export class PhaseRegistry {
|
|
26
|
+
registrations = [];
|
|
27
|
+
/**
|
|
28
|
+
* Register a phase. This is the `registerPhase(phase, { enabledWhen })` seam
|
|
29
|
+
* named in issue #2080. Returns `this` for fluent chaining. Registration
|
|
30
|
+
* order is preserved by `build()`.
|
|
31
|
+
*/
|
|
32
|
+
register(phase, options) {
|
|
33
|
+
this.registrations.push({ phase, enabledWhen: options?.enabledWhen });
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the ordered phase list for the given options. A phase is included
|
|
38
|
+
* iff it has no `enabledWhen` predicate or its predicate returns `true`.
|
|
39
|
+
* Order matches registration order. `options` is required — callers that may
|
|
40
|
+
* have no options normalize once at the call site (`options ?? {}`) so the
|
|
41
|
+
* predicates never see `undefined`.
|
|
42
|
+
*/
|
|
43
|
+
build(options) {
|
|
44
|
+
return this.registrations
|
|
45
|
+
.filter((r) => r.enabledWhen === undefined || r.enabledWhen(options))
|
|
46
|
+
.map((r) => r.phase);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { type PipelineProgress } from '../../_shared/index.js';
|
|
18
18
|
import { PipelineResult } from '../../types/pipeline.js';
|
|
19
|
+
import { type PipelinePhase } from './pipeline-phases/index.js';
|
|
19
20
|
export interface PipelineOptions {
|
|
20
21
|
/**
|
|
21
22
|
* Skip MRO, community detection, and process extraction for faster test runs.
|
|
@@ -104,4 +105,24 @@ export interface PipelineOptions {
|
|
|
104
105
|
*/
|
|
105
106
|
keepLocalValueSymbols?: boolean;
|
|
106
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* All pipeline phases with their dependency relationships.
|
|
110
|
+
*
|
|
111
|
+
* Phase dependency graph:
|
|
112
|
+
*
|
|
113
|
+
* scan → structure → [markdown, cobol] → parse → [routes, tools, orm]
|
|
114
|
+
* → crossFile → scopeResolution → pruneLocalSymbols
|
|
115
|
+
* → mro → communities → processes
|
|
116
|
+
*
|
|
117
|
+
* To add a new phase: create a file in pipeline-phases/, export the phase
|
|
118
|
+
* object, and `.register()` it at the appropriate position below. Opt-in
|
|
119
|
+
* phases pass an `enabledWhen` predicate (issue #2080 phase-registry seam) —
|
|
120
|
+
* the legacy `if (!skipGraphPhases)` guard is now expressed that way on the
|
|
121
|
+
* three graph phases, with no change in behaviour.
|
|
122
|
+
*
|
|
123
|
+
* Exported for the parity test (`pipeline-phase-registry.test.ts`), which
|
|
124
|
+
* asserts the produced list is byte-identical to the legacy array for every
|
|
125
|
+
* options combination.
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildPhaseList(options?: PipelineOptions): PipelinePhase[];
|
|
107
128
|
export declare const runPipelineFromRepo: (repoPath: string, onProgress: (progress: PipelineProgress) => void, options?: PipelineOptions) => Promise<PipelineResult>;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* See ARCHITECTURE.md for the full phase dependency diagram.
|
|
16
16
|
*/
|
|
17
17
|
import { createKnowledgeGraph } from '../graph/graph.js';
|
|
18
|
-
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, pruneLocalSymbolsPhase, mroPhase, communitiesPhase, processesPhase, } from './pipeline-phases/index.js';
|
|
18
|
+
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, pruneLocalSymbolsPhase, mroPhase, communitiesPhase, processesPhase, PhaseRegistry, } from './pipeline-phases/index.js';
|
|
19
19
|
// ── Phase registry ─────────────────────────────────────────────────────────
|
|
20
20
|
/**
|
|
21
21
|
* All pipeline phases with their dependency relationships.
|
|
@@ -27,26 +27,34 @@ import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase,
|
|
|
27
27
|
* → mro → communities → processes
|
|
28
28
|
*
|
|
29
29
|
* To add a new phase: create a file in pipeline-phases/, export the phase
|
|
30
|
-
* object, and
|
|
30
|
+
* object, and `.register()` it at the appropriate position below. Opt-in
|
|
31
|
+
* phases pass an `enabledWhen` predicate (issue #2080 phase-registry seam) —
|
|
32
|
+
* the legacy `if (!skipGraphPhases)` guard is now expressed that way on the
|
|
33
|
+
* three graph phases, with no change in behaviour.
|
|
34
|
+
*
|
|
35
|
+
* Exported for the parity test (`pipeline-phase-registry.test.ts`), which
|
|
36
|
+
* asserts the produced list is byte-identical to the legacy array for every
|
|
37
|
+
* options combination.
|
|
31
38
|
*/
|
|
32
|
-
function buildPhaseList(options) {
|
|
33
|
-
|
|
34
|
-
scanPhase
|
|
35
|
-
structurePhase
|
|
36
|
-
markdownPhase
|
|
37
|
-
cobolPhase
|
|
38
|
-
parsePhase
|
|
39
|
-
routesPhase
|
|
40
|
-
toolsPhase
|
|
41
|
-
ormPhase
|
|
42
|
-
crossFilePhase
|
|
43
|
-
scopeResolutionPhase
|
|
44
|
-
pruneLocalSymbolsPhase
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
export function buildPhaseList(options) {
|
|
40
|
+
return (new PhaseRegistry()
|
|
41
|
+
.register(scanPhase)
|
|
42
|
+
.register(structurePhase)
|
|
43
|
+
.register(markdownPhase)
|
|
44
|
+
.register(cobolPhase)
|
|
45
|
+
.register(parsePhase)
|
|
46
|
+
.register(routesPhase)
|
|
47
|
+
.register(toolsPhase)
|
|
48
|
+
.register(ormPhase)
|
|
49
|
+
.register(crossFilePhase)
|
|
50
|
+
.register(scopeResolutionPhase)
|
|
51
|
+
.register(pruneLocalSymbolsPhase)
|
|
52
|
+
.register(mroPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
53
|
+
.register(communitiesPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
54
|
+
.register(processesPhase, { enabledWhen: (o) => !o.skipGraphPhases })
|
|
55
|
+
// Normalize a missing options object once here so phase predicates above
|
|
56
|
+
// take a required PipelineOptions and need no `?.` guard (#2080 review S1).
|
|
57
|
+
.build(options ?? {}));
|
|
50
58
|
}
|
|
51
59
|
// ── Pipeline orchestrator ─────────────────────────────────────────────────
|
|
52
60
|
export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
|