ghagga 3.1.0 → 3.3.0
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/commands/index-cmd.d.ts +49 -0
- package/dist/commands/index-cmd.d.ts.map +1 -0
- package/dist/commands/index-cmd.js +367 -0
- package/dist/commands/index-cmd.js.map +1 -0
- package/dist/commands/index-cmd.test.d.ts +17 -0
- package/dist/commands/index-cmd.test.d.ts.map +1 -0
- package/dist/commands/index-cmd.test.js +541 -0
- package/dist/commands/index-cmd.test.js.map +1 -0
- package/dist/commands/indexer-registry.d.ts +93 -0
- package/dist/commands/indexer-registry.d.ts.map +1 -0
- package/dist/commands/indexer-registry.js +342 -0
- package/dist/commands/indexer-registry.js.map +1 -0
- package/dist/commands/indexer-registry.test.d.ts +10 -0
- package/dist/commands/indexer-registry.test.d.ts.map +1 -0
- package/dist/commands/indexer-registry.test.js +538 -0
- package/dist/commands/indexer-registry.test.js.map +1 -0
- package/dist/commands/memory/backfill.d.ts +13 -0
- package/dist/commands/memory/backfill.d.ts.map +1 -0
- package/dist/commands/memory/backfill.js +47 -0
- package/dist/commands/memory/backfill.js.map +1 -0
- package/dist/commands/memory/backfill.test.d.ts +11 -0
- package/dist/commands/memory/backfill.test.d.ts.map +1 -0
- package/dist/commands/memory/backfill.test.js +127 -0
- package/dist/commands/memory/backfill.test.js.map +1 -0
- package/dist/commands/memory/clear.test.js +9 -0
- package/dist/commands/memory/clear.test.js.map +1 -1
- package/dist/commands/memory/delete.test.js +9 -0
- package/dist/commands/memory/delete.test.js.map +1 -1
- package/dist/commands/memory/index.d.ts +3 -3
- package/dist/commands/memory/index.d.ts.map +1 -1
- package/dist/commands/memory/index.js +5 -3
- package/dist/commands/memory/index.js.map +1 -1
- package/dist/commands/memory/list.test.js +9 -0
- package/dist/commands/memory/list.test.js.map +1 -1
- package/dist/commands/memory/search.test.js +9 -0
- package/dist/commands/memory/search.test.js.map +1 -1
- package/dist/commands/memory/show.test.js +9 -0
- package/dist/commands/memory/show.test.js.map +1 -1
- package/dist/commands/memory/stats.test.js +9 -0
- package/dist/commands/memory/stats.test.js.map +1 -1
- package/dist/commands/memory/utils.d.ts.map +1 -1
- package/dist/commands/memory/utils.js +14 -1
- package/dist/commands/memory/utils.js.map +1 -1
- package/dist/commands/review-blast-radius.test.d.ts +13 -0
- package/dist/commands/review-blast-radius.test.d.ts.map +1 -0
- package/dist/commands/review-blast-radius.test.js +179 -0
- package/dist/commands/review-blast-radius.test.js.map +1 -0
- package/dist/commands/review-output.test.js +9 -0
- package/dist/commands/review-output.test.js.map +1 -1
- package/dist/commands/review.d.ts +112 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +278 -4
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/review.test.js +299 -0
- package/dist/commands/review.test.js.map +1 -1
- package/dist/commands/triage.d.ts +14 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +153 -0
- package/dist/commands/triage.js.map +1 -0
- package/dist/commands/triage.test.d.ts +8 -0
- package/dist/commands/triage.test.d.ts.map +1 -0
- package/dist/commands/triage.test.js +184 -0
- package/dist/commands/triage.test.js.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/cli-gitlab-client-port.test.js +38 -24
- package/dist/lib/cli-gitlab-client-port.test.js.map +1 -1
- package/dist/lib/config.d.ts +11 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/embedding.d.ts +23 -0
- package/dist/lib/embedding.d.ts.map +1 -0
- package/dist/lib/embedding.js +39 -0
- package/dist/lib/embedding.js.map +1 -0
- package/dist/lib/embedding.test.d.ts +8 -0
- package/dist/lib/embedding.test.d.ts.map +1 -0
- package/dist/lib/embedding.test.js +101 -0
- package/dist/lib/embedding.test.js.map +1 -0
- package/dist/lib/gitlab-e2e.manual.test.d.ts +38 -5
- package/dist/lib/gitlab-e2e.manual.test.d.ts.map +1 -1
- package/dist/lib/gitlab-e2e.manual.test.js +93 -15
- package/dist/lib/gitlab-e2e.manual.test.js.map +1 -1
- package/dist/lib/pr-postback.test.js +40 -24
- package/dist/lib/pr-postback.test.js.map +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index command — builds the dependency graph consumed by blast-radius/review.
|
|
3
|
+
*
|
|
4
|
+
* Registry dispatcher (D1, nested-marker-detection D3): walks the repo for
|
|
5
|
+
* marker directories at any depth (`detectMarkerDirectories`), checks
|
|
6
|
+
* per-entry toolchain availability ONCE (dir-independent), runs each
|
|
7
|
+
* available indexer once per `{entry, dir}` pair to a centralized,
|
|
8
|
+
* per-dir-disambiguated `.scip` output (D3), merges the results with each
|
|
9
|
+
* document's path prefixed by its source marker directory (D4), and builds
|
|
10
|
+
* ONE graph. Per-pair failures degrade gracefully (D6) — a missing
|
|
11
|
+
* toolchain skips ALL of that entry's dirs (one warning); a runtime crash
|
|
12
|
+
* in one marker directory warns and skips only THAT pair, never aborting
|
|
13
|
+
* the whole run. A run-count cap (D5) bounds pathological monorepos. The
|
|
14
|
+
* regex-based indexer remains available as an explicit opt-in fallback
|
|
15
|
+
* (`--fallback-regex`) for when NO detected language could be indexed via
|
|
16
|
+
* SCIP.
|
|
17
|
+
*/
|
|
18
|
+
export interface IndexCommandOptions {
|
|
19
|
+
/** Output path for graph.json, relative to the target repo. */
|
|
20
|
+
out?: string;
|
|
21
|
+
/** Fall back to the regex-based indexer when no language could be SCIP-indexed. */
|
|
22
|
+
fallbackRegex?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Raw `--marker-depth` CLI value (string — commander does not coerce it).
|
|
25
|
+
* Maximum depth (repo root = 0) the nested-marker walk descends to.
|
|
26
|
+
* Must be a positive integer; validated and parsed in `indexCommand`.
|
|
27
|
+
* Undefined → `detectMarkerDirectories`'s own default (`DEFAULT_MARKER_DEPTH`, 4).
|
|
28
|
+
*/
|
|
29
|
+
markerDepth?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run-count guard default (D5): biogas-scale monorepos have ~5 marker
|
|
33
|
+
* dirs; 25 gives headroom while bounding pathological monorepans ×
|
|
34
|
+
* `heavy`/`experimental` wall-clock. Overridable via `opts.maxRuns`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const DEFAULT_MAX_NESTED_RUNS = 25;
|
|
37
|
+
/**
|
|
38
|
+
* Sanitize a relative path into a filesystem-safe, collision-free slug.
|
|
39
|
+
*
|
|
40
|
+
* The human-readable sanitized prefix alone is NOT collision-stable: e.g.
|
|
41
|
+
* `apps/a_b` and `apps_a/b` both sanitize to `apps_a_b`, which would
|
|
42
|
+
* silently clobber one indexer run's `.scip` output with another's. A
|
|
43
|
+
* deterministic hash of the RAW `relPath` is appended as a suffix so two
|
|
44
|
+
* distinct relPaths can never produce the same slug, while keeping the
|
|
45
|
+
* sanitized prefix for debuggability.
|
|
46
|
+
*/
|
|
47
|
+
export declare function slugifyRelPath(relPath: string): string;
|
|
48
|
+
export declare function indexCommand(targetPath: string, options: IndexCommandOptions): Promise<void>;
|
|
49
|
+
//# sourceMappingURL=index-cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/index-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA2BH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsHD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AA0B1C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOtD;AAsKD,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA+Ff"}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index command — builds the dependency graph consumed by blast-radius/review.
|
|
3
|
+
*
|
|
4
|
+
* Registry dispatcher (D1, nested-marker-detection D3): walks the repo for
|
|
5
|
+
* marker directories at any depth (`detectMarkerDirectories`), checks
|
|
6
|
+
* per-entry toolchain availability ONCE (dir-independent), runs each
|
|
7
|
+
* available indexer once per `{entry, dir}` pair to a centralized,
|
|
8
|
+
* per-dir-disambiguated `.scip` output (D3), merges the results with each
|
|
9
|
+
* document's path prefixed by its source marker directory (D4), and builds
|
|
10
|
+
* ONE graph. Per-pair failures degrade gracefully (D6) — a missing
|
|
11
|
+
* toolchain skips ALL of that entry's dirs (one warning); a runtime crash
|
|
12
|
+
* in one marker directory warns and skips only THAT pair, never aborting
|
|
13
|
+
* the whole run. A run-count cap (D5) bounds pathological monorepos. The
|
|
14
|
+
* regex-based indexer remains available as an explicit opt-in fallback
|
|
15
|
+
* (`--fallback-regex`) for when NO detected language could be indexed via
|
|
16
|
+
* SCIP.
|
|
17
|
+
*/
|
|
18
|
+
import { execFileSync } from 'node:child_process';
|
|
19
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
21
|
+
import { buildGraph, buildGraphFromScip, EXCLUDED_DIRS, GRAPH_VERSION, mergeScipIndexes, parseScipIndex, } from 'ghagga-core';
|
|
22
|
+
import * as tui from '../ui/tui.js';
|
|
23
|
+
import { detectMarkerDirectories, scipOutputPath, } from './indexer-registry.js';
|
|
24
|
+
// ─── Constants ──────────────────────────────────────────────────
|
|
25
|
+
const DEFAULT_OUT = '.ghagga/graph.json';
|
|
26
|
+
// ─── Regex Fallback: File Collection ────────────────────────────
|
|
27
|
+
/** Recursively collect readable text files under rootDir, skipping excluded dirs. */
|
|
28
|
+
function collectFiles(rootDir) {
|
|
29
|
+
const files = new Map();
|
|
30
|
+
function walk(dir) {
|
|
31
|
+
let entries;
|
|
32
|
+
try {
|
|
33
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const full = join(dir, entry.name);
|
|
40
|
+
if (entry.isDirectory()) {
|
|
41
|
+
if (EXCLUDED_DIRS.has(entry.name))
|
|
42
|
+
continue;
|
|
43
|
+
walk(full);
|
|
44
|
+
}
|
|
45
|
+
else if (entry.isFile()) {
|
|
46
|
+
try {
|
|
47
|
+
const content = readFileSync(full, 'utf-8');
|
|
48
|
+
files.set(relative(rootDir, full), content);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Skip unreadable/binary files
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
walk(rootDir);
|
|
57
|
+
return files;
|
|
58
|
+
}
|
|
59
|
+
// ─── Output ─────────────────────────────────────────────────────
|
|
60
|
+
function writeGraph(outPath, graph) {
|
|
61
|
+
const dir = dirname(outPath);
|
|
62
|
+
if (!existsSync(dir)) {
|
|
63
|
+
mkdirSync(dir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
writeFileSync(outPath, JSON.stringify(graph, null, 2));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve the current git HEAD SHA for `repoPath`. Returns `''` on any
|
|
69
|
+
* failure (not a git repo, detached-without-HEAD edge cases, git not on
|
|
70
|
+
* PATH) — non-git repos degrade gracefully rather than aborting `ghagga
|
|
71
|
+
* index` (design v2 D1).
|
|
72
|
+
*/
|
|
73
|
+
function resolveGitHead(repoPath) {
|
|
74
|
+
try {
|
|
75
|
+
return execFileSync('git', ['rev-parse', 'HEAD'], {
|
|
76
|
+
cwd: repoPath,
|
|
77
|
+
encoding: 'utf-8',
|
|
78
|
+
}).trim();
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Write `.ghagga/metadata.json` ALONGSIDE `.ghagga/graph.json` (design v2
|
|
86
|
+
* D1). MUST be called AFTER `writeGraph` (B-003 write ordering) — a crash
|
|
87
|
+
* between the two writes leaves graph-without-metadata, which
|
|
88
|
+
* `checkGraphStaleness` reports as a distinct "cannot verify staleness"
|
|
89
|
+
* warning, never metadata newer than (or inconsistent with) the graph.
|
|
90
|
+
*
|
|
91
|
+
* `languages` is DERIVED FROM THE GRAPH'S ACTUAL NODE CONTENTS (CRITICAL-1)
|
|
92
|
+
* — NOT dispatch's `indexedLanguages` — because the regex-fallback path sets
|
|
93
|
+
* `indexedLanguages: []` while every node still has a real `language`.
|
|
94
|
+
* `skippedLanguages` is informational only (languages detected but not
|
|
95
|
+
* indexed) and is never used to drive a warning.
|
|
96
|
+
*/
|
|
97
|
+
function writeMetadata(graphOutPath, graph, opts) {
|
|
98
|
+
const metadataPath = join(dirname(graphOutPath), 'metadata.json');
|
|
99
|
+
const languages = [...new Set(Object.values(graph.nodes).map((node) => node.language))];
|
|
100
|
+
const metadata = {
|
|
101
|
+
lastIndexedCommit: resolveGitHead(opts.repoPath),
|
|
102
|
+
lastIndexedAt: new Date().toISOString(),
|
|
103
|
+
schemaVersion: GRAPH_VERSION,
|
|
104
|
+
fileCount: Object.keys(graph.nodes).length,
|
|
105
|
+
languages,
|
|
106
|
+
indexDurationMs: opts.indexDurationMs,
|
|
107
|
+
skippedLanguages: opts.skippedLanguages,
|
|
108
|
+
graphVersion: graph.version,
|
|
109
|
+
builtVia: opts.builtVia,
|
|
110
|
+
};
|
|
111
|
+
writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Run-count guard default (D5): biogas-scale monorepos have ~5 marker
|
|
115
|
+
* dirs; 25 gives headroom while bounding pathological monorepans ×
|
|
116
|
+
* `heavy`/`experimental` wall-clock. Overridable via `opts.maxRuns`.
|
|
117
|
+
*/
|
|
118
|
+
export const DEFAULT_MAX_NESTED_RUNS = 25;
|
|
119
|
+
const MATURITY_ORDER = { stable: 0, heavy: 1, experimental: 2 };
|
|
120
|
+
/** Depth of `dir` relative to `repoPath` (repo root = 0). */
|
|
121
|
+
function pairDepth(repoPath, dir) {
|
|
122
|
+
const rel = relative(repoPath, dir);
|
|
123
|
+
if (!rel || rel === '.')
|
|
124
|
+
return 0;
|
|
125
|
+
return rel.split(/[\\/]/).filter(Boolean).length;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Deterministic string hash (FNV-1a, 32-bit → 8 lowercase hex chars). Pure
|
|
129
|
+
* and reproducible run-to-run for the same input — NOT `Math.random`/`Date`
|
|
130
|
+
* — so the same marker directory always maps to the same `.scip` output
|
|
131
|
+
* path across runs.
|
|
132
|
+
*/
|
|
133
|
+
function hash8(input) {
|
|
134
|
+
let hash = 0x811c9dc5; // FNV offset basis
|
|
135
|
+
for (let i = 0; i < input.length; i++) {
|
|
136
|
+
hash ^= input.charCodeAt(i);
|
|
137
|
+
hash = Math.imul(hash, 0x01000193); // FNV prime
|
|
138
|
+
}
|
|
139
|
+
return (hash >>> 0).toString(16).padStart(8, '0');
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Sanitize a relative path into a filesystem-safe, collision-free slug.
|
|
143
|
+
*
|
|
144
|
+
* The human-readable sanitized prefix alone is NOT collision-stable: e.g.
|
|
145
|
+
* `apps/a_b` and `apps_a/b` both sanitize to `apps_a_b`, which would
|
|
146
|
+
* silently clobber one indexer run's `.scip` output with another's. A
|
|
147
|
+
* deterministic hash of the RAW `relPath` is appended as a suffix so two
|
|
148
|
+
* distinct relPaths can never produce the same slug, while keeping the
|
|
149
|
+
* sanitized prefix for debuggability.
|
|
150
|
+
*/
|
|
151
|
+
export function slugifyRelPath(relPath) {
|
|
152
|
+
const sanitized = relPath
|
|
153
|
+
.split(/[\\/]/)
|
|
154
|
+
.filter(Boolean)
|
|
155
|
+
.join('_')
|
|
156
|
+
.replace(/[^a-zA-Z0-9_.-]/g, '-');
|
|
157
|
+
return `${sanitized}__${hash8(relPath)}`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Sort pairs (maturity stable→heavy→experimental, then depth ascending =
|
|
161
|
+
* root-first) BEFORE capping (D5) — cheap high-value indexers run before
|
|
162
|
+
* expensive ones get dropped, deterministically, root-first.
|
|
163
|
+
*
|
|
164
|
+
* Root-level pairs (depth 0) are EXEMPT from the cap and ALWAYS run — before
|
|
165
|
+
* nested-marker-detection, `ghagga index` unconditionally indexed every
|
|
166
|
+
* root-level language, so a root marker silently vanishing under the cap
|
|
167
|
+
* would be a regression. The cap (`maxRuns`) applies only to NESTED pairs,
|
|
168
|
+
* using the existing maturity→depth sort; if root pairs alone exceed
|
|
169
|
+
* `maxRuns`, they STILL all run (never dropped), matching pre-cap behavior.
|
|
170
|
+
*/
|
|
171
|
+
function sortAndCapPairs(repoPath, pairs, maxRuns) {
|
|
172
|
+
const rootPairs = pairs.filter((p) => pairDepth(repoPath, p.dir) === 0);
|
|
173
|
+
const nestedPairs = pairs.filter((p) => pairDepth(repoPath, p.dir) !== 0);
|
|
174
|
+
const sortedNested = [...nestedPairs].sort((a, b) => {
|
|
175
|
+
const maturityDiff = MATURITY_ORDER[a.entry.maturity] - MATURITY_ORDER[b.entry.maturity];
|
|
176
|
+
if (maturityDiff !== 0)
|
|
177
|
+
return maturityDiff;
|
|
178
|
+
return pairDepth(repoPath, a.dir) - pairDepth(repoPath, b.dir);
|
|
179
|
+
});
|
|
180
|
+
const nestedBudget = Math.max(0, maxRuns - rootPairs.length);
|
|
181
|
+
return {
|
|
182
|
+
toRun: [...rootPairs, ...sortedNested.slice(0, nestedBudget)],
|
|
183
|
+
dropped: sortedNested.slice(nestedBudget),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Run every {entry, dir} pair whose entry's toolchain is available,
|
|
188
|
+
* collecting parsed SCIP indexes + their source marker directory (for
|
|
189
|
+
* merge path-prefixing). Missing toolchains warn ONCE per entry and skip
|
|
190
|
+
* ALL its dirs; runtime failures warn and skip only THAT pair (D6) — this
|
|
191
|
+
* function never throws for a single pair's failure. The output path per
|
|
192
|
+
* pair is CENTRALIZED here (not computed by the entry — D3): repo root
|
|
193
|
+
* pairs use the bare bin name, nested pairs get a `__<dir-slug>` suffix so
|
|
194
|
+
* two marker dirs of the SAME bin (e.g. two `scip-python` dirs) never
|
|
195
|
+
* collide on the same `.scip` output file.
|
|
196
|
+
*/
|
|
197
|
+
async function dispatchIndexers(repoPath, pairs, opts = {}) {
|
|
198
|
+
const maxRuns = opts.maxRuns ?? DEFAULT_MAX_NESTED_RUNS;
|
|
199
|
+
const { toRun, dropped } = sortAndCapPairs(repoPath, pairs, maxRuns);
|
|
200
|
+
if (dropped.length > 0) {
|
|
201
|
+
const names = dropped
|
|
202
|
+
.map((p) => `${p.entry.languages.join('/')} @ ${relative(repoPath, p.dir) || '.'}`)
|
|
203
|
+
.join(', ');
|
|
204
|
+
tui.log.warn(`⚠️ Run-count cap (${maxRuns}) reached — skipped ${dropped.length} ` +
|
|
205
|
+
`marker director${dropped.length === 1 ? 'y' : 'ies'}: ${names}`);
|
|
206
|
+
}
|
|
207
|
+
const indexes = [];
|
|
208
|
+
const indexedLanguages = new Set();
|
|
209
|
+
const skipped = [];
|
|
210
|
+
const toolchainAvailable = new Map();
|
|
211
|
+
for (const { entry, dir } of toRun) {
|
|
212
|
+
const languageLabel = entry.languages.join('/');
|
|
213
|
+
const dirLabel = relative(repoPath, dir) || '.';
|
|
214
|
+
let available = toolchainAvailable.get(entry);
|
|
215
|
+
if (available === undefined) {
|
|
216
|
+
available = entry.toolchainCheck();
|
|
217
|
+
toolchainAvailable.set(entry, available);
|
|
218
|
+
if (!available) {
|
|
219
|
+
tui.log.warn(`⚠️ ${languageLabel}: toolchain not found (${entry.bin}) — skipping.\n ${entry.installHint}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (!available) {
|
|
223
|
+
skipped.push({ entry, dir, reason: `toolchain not found (${entry.bin})` });
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const relPath = relative(repoPath, dir);
|
|
227
|
+
const outName = dir === repoPath ? entry.bin : `${entry.bin}__${slugifyRelPath(relPath)}`;
|
|
228
|
+
const outPath = scipOutputPath(repoPath, outName);
|
|
229
|
+
try {
|
|
230
|
+
const scipPath = await entry.run(dir, outPath);
|
|
231
|
+
const bytes = readFileSync(scipPath);
|
|
232
|
+
const index = parseScipIndex(new Uint8Array(bytes));
|
|
233
|
+
indexes.push({ index, pathPrefix: dir === repoPath ? '' : relPath });
|
|
234
|
+
for (const lang of entry.languages)
|
|
235
|
+
indexedLanguages.add(lang);
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
239
|
+
tui.log.warn(`⚠️ ${languageLabel} @ ${dirLabel}: ${entry.bin} failed at runtime — skipping.\n ${message}`);
|
|
240
|
+
skipped.push({ entry, dir, reason: message });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return { indexes, indexedLanguages: [...indexedLanguages], skipped };
|
|
244
|
+
}
|
|
245
|
+
// ─── scip-typescript Root-Umbrella Collapse (D6, empirical spike) ───
|
|
246
|
+
/**
|
|
247
|
+
* RESOLVED (2026-07-15, empirical spike against a synthetic 2-package
|
|
248
|
+
* TypeScript project-references fixture — apps/web + packages/utils, with
|
|
249
|
+
* apps/web importing from packages/utils via `tsconfig.json` `paths`):
|
|
250
|
+
* `scip-typescript index --cwd <repoPath> --infer-tsconfig` run FROM REPO
|
|
251
|
+
* ROOT already recursively discovers and indexes EVERY nested TS/JS
|
|
252
|
+
* package — this held even with NO tsconfig.json/package.json at repo
|
|
253
|
+
* root at all. The root run produced clean repo-relative paths for BOTH
|
|
254
|
+
* packages (`apps/web/src/main.ts`, `packages/utils/src/index.ts`) and
|
|
255
|
+
* correctly resolved the cross-package symbol reference (`main.ts`'s
|
|
256
|
+
* `greet()` call resolved to `packages/utils/src/index.ts`'s definition,
|
|
257
|
+
* not left dangling as an external/unresolved symbol).
|
|
258
|
+
*
|
|
259
|
+
* By contrast, running scip-typescript with `cwd` set to a SUBPACKAGE
|
|
260
|
+
* directory (the per-subroot approach every other indexer needs) still
|
|
261
|
+
* auto-discovered the referenced sibling project, but emitted its path as
|
|
262
|
+
* `../../packages/utils/src/index.ts` — a `..`-escaping relative path
|
|
263
|
+
* outside the run's own cwd tree, which is fragile to prefix-join
|
|
264
|
+
* correctly for arbitrary nesting depths (unlike every other indexer,
|
|
265
|
+
* which never emits paths outside the directory it was pointed at).
|
|
266
|
+
*
|
|
267
|
+
* Conclusion: unlike go/rust/java/dotnet/php (which cannot self-discover
|
|
268
|
+
* nested modules from an ancestor cwd — per-subroot dispatch is mandatory
|
|
269
|
+
* for them, per D1), scip-typescript's own project-reference/tsconfig
|
|
270
|
+
* auto-discovery makes per-subroot dispatch actively WORSE (double-indexes
|
|
271
|
+
* + `..`-escaping paths). So: collapse every TS/JS marker-dir pair to
|
|
272
|
+
* exactly ONE root-cwd run, regardless of how many TS/JS marker
|
|
273
|
+
* directories `detectMarkerDirectories` found.
|
|
274
|
+
*/
|
|
275
|
+
const TS_ROOT_UMBRELLA = true;
|
|
276
|
+
/**
|
|
277
|
+
* Collapse all `scip-typescript` pairs down to a single root-cwd run (D6).
|
|
278
|
+
* No-op for every other entry. If TS/JS was detected ANYWHERE (root or
|
|
279
|
+
* nested), the collapsed pair always runs with `dir = repoPath` — the
|
|
280
|
+
* indexer's own `--infer-tsconfig` walk covers nested tsconfigs from
|
|
281
|
+
* there, so the specific nested `dir` that triggered detection doesn't
|
|
282
|
+
* matter once collapsed.
|
|
283
|
+
*/
|
|
284
|
+
function collapseTypescriptPairs(repoPath, pairs) {
|
|
285
|
+
if (!TS_ROOT_UMBRELLA)
|
|
286
|
+
return pairs;
|
|
287
|
+
const tsPairs = pairs.filter((p) => p.entry.bin === 'scip-typescript');
|
|
288
|
+
if (tsPairs.length === 0)
|
|
289
|
+
return pairs;
|
|
290
|
+
const nonTsPairs = pairs.filter((p) => p.entry.bin !== 'scip-typescript');
|
|
291
|
+
const firstTs = tsPairs[0];
|
|
292
|
+
if (!firstTs)
|
|
293
|
+
return pairs;
|
|
294
|
+
return [...nonTsPairs, { entry: firstTs.entry, dir: repoPath }];
|
|
295
|
+
}
|
|
296
|
+
// ─── Main Command ───────────────────────────────────────────────
|
|
297
|
+
export async function indexCommand(targetPath, options) {
|
|
298
|
+
const repoPath = resolve(targetPath || '.');
|
|
299
|
+
const outPath = resolve(repoPath, options.out ?? DEFAULT_OUT);
|
|
300
|
+
const startedAt = Date.now();
|
|
301
|
+
let markerDepth;
|
|
302
|
+
if (options.markerDepth != null) {
|
|
303
|
+
const parsed = Number.parseInt(options.markerDepth, 10);
|
|
304
|
+
if (Number.isNaN(parsed) || parsed <= 0 || String(parsed) !== options.markerDepth.trim()) {
|
|
305
|
+
tui.log.error(`❌ Invalid --marker-depth "${options.markerDepth}". Provide a positive integer.`);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
markerDepth = parsed;
|
|
310
|
+
}
|
|
311
|
+
const rawPairs = detectMarkerDirectories(repoPath, { maxDepth: markerDepth });
|
|
312
|
+
const pairs = collapseTypescriptPairs(repoPath, rawPairs);
|
|
313
|
+
const { indexes, indexedLanguages, skipped } = await dispatchIndexers(repoPath, pairs);
|
|
314
|
+
const skippedLanguages = [...new Set(skipped.flatMap((s) => s.entry.languages))];
|
|
315
|
+
if (indexes.length === 0) {
|
|
316
|
+
if (!options.fallbackRegex) {
|
|
317
|
+
const triedLines = pairs.length === 0
|
|
318
|
+
? ' No supported language markers were detected in this repo.'
|
|
319
|
+
: skipped
|
|
320
|
+
.map((s) => ` - ${s.entry.languages.join('/')} @ ${relative(repoPath, s.dir) || '.'} (${s.entry.bin}): ${s.reason}`)
|
|
321
|
+
.join('\n');
|
|
322
|
+
tui.log.error('❌ No language could be indexed via SCIP.\n' +
|
|
323
|
+
`${triedLines}\n` +
|
|
324
|
+
' Pass --fallback-regex to use the regex-based indexer instead\n' +
|
|
325
|
+
' (note: it cannot resolve non-relative/module-path imports).');
|
|
326
|
+
process.exit(1);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
tui.log.warn('⚠️ No language could be indexed via SCIP — falling back to regex-based indexing.');
|
|
330
|
+
const files = collectFiles(repoPath);
|
|
331
|
+
const graph = buildGraph(repoPath, files);
|
|
332
|
+
// Write ORDER (B-003): graph.json FIRST, THEN metadata.json — a crash
|
|
333
|
+
// between the two leaves graph-without-metadata, never the reverse.
|
|
334
|
+
writeGraph(outPath, graph);
|
|
335
|
+
writeMetadata(outPath, graph, {
|
|
336
|
+
repoPath,
|
|
337
|
+
skippedLanguages,
|
|
338
|
+
indexDurationMs: Date.now() - startedAt,
|
|
339
|
+
builtVia: 'regex',
|
|
340
|
+
});
|
|
341
|
+
tui.log.success(`✅ Wrote ${Object.keys(graph.nodes).length} node(s) to ${outPath} (regex fallback).`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const { index: mergedIndex, duplicatePaths, escapedPaths } = mergeScipIndexes(indexes);
|
|
345
|
+
for (const duplicatePath of duplicatePaths) {
|
|
346
|
+
tui.log.warn(`⚠️ Duplicate SCIP document path across indexers: ${duplicatePath} — last indexer wins.`);
|
|
347
|
+
}
|
|
348
|
+
for (const escapedPath of escapedPaths) {
|
|
349
|
+
tui.log.warn(`⚠️ SCIP document path escaped the repo-relative root: ${escapedPath} — dropped from graph.`);
|
|
350
|
+
}
|
|
351
|
+
const graph = buildGraphFromScip(mergedIndex, {
|
|
352
|
+
onUnmappedDoc: (relativePath, language) => {
|
|
353
|
+
tui.log.warn(`⚠️ Unmapped SCIP document ${relativePath} (language: ${language}) — dropped from graph.`);
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
// Write ORDER (B-003): graph.json FIRST, THEN metadata.json.
|
|
357
|
+
writeGraph(outPath, graph);
|
|
358
|
+
writeMetadata(outPath, graph, {
|
|
359
|
+
repoPath,
|
|
360
|
+
skippedLanguages,
|
|
361
|
+
indexDurationMs: Date.now() - startedAt,
|
|
362
|
+
builtVia: 'scip',
|
|
363
|
+
});
|
|
364
|
+
tui.log.success(`✅ Wrote ${Object.keys(graph.nodes).length} node(s) to ${outPath} ` +
|
|
365
|
+
`(SCIP: ${indexedLanguages.join(', ')}).`);
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=index-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.js","sourceRoot":"","sources":["../../src/commands/index-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `ghagga index` — registry-dispatcher dependency graph indexing.
|
|
3
|
+
*
|
|
4
|
+
* Mocked: `detectMarkerDirectories` (from `./indexer-registry.js`) — the
|
|
5
|
+
* dispatcher tests only exercise detect/availability/degrade/zero-index/
|
|
6
|
+
* merge/output-isolation/cap wiring, mirroring the mocking style of the
|
|
7
|
+
* previous Go-only tests (mocked `toolchainCheck`/`run`, not real
|
|
8
|
+
* toolchains). Per-language mapping correctness is covered separately by
|
|
9
|
+
* `packages/core`'s SCIP mapper fixture tests.
|
|
10
|
+
*
|
|
11
|
+
* Nested marker detection: `detectMarkerDirectories` returns
|
|
12
|
+
* `Array<{entry, dir}>` pairs (not a flat entry list) — the dispatcher runs
|
|
13
|
+
* each pair independently and merges with `pathPrefix = relative(repoPath,
|
|
14
|
+
* dir)`, so tests here exercise per-pair (not just per-language) dispatch.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=index-cmd.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cmd.test.d.ts","sourceRoot":"","sources":["../../src/commands/index-cmd.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|