@opencodehub/cli 0.1.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/LICENSE +202 -0
- package/README.md +85 -0
- package/dist/agent-context.d.ts +54 -0
- package/dist/agent-context.d.ts.map +1 -0
- package/dist/agent-context.js +122 -0
- package/dist/agent-context.js.map +1 -0
- package/dist/cobol-proleap-setup.d.ts +77 -0
- package/dist/cobol-proleap-setup.d.ts.map +1 -0
- package/dist/cobol-proleap-setup.js +289 -0
- package/dist/cobol-proleap-setup.js.map +1 -0
- package/dist/commands/analyze.d.ts +234 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +1096 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/augment.d.ts +48 -0
- package/dist/commands/augment.d.ts.map +1 -0
- package/dist/commands/augment.js +249 -0
- package/dist/commands/augment.js.map +1 -0
- package/dist/commands/baseline.d.ts +68 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +110 -0
- package/dist/commands/baseline.js.map +1 -0
- package/dist/commands/bench.d.ts +54 -0
- package/dist/commands/bench.d.ts.map +1 -0
- package/dist/commands/bench.js +283 -0
- package/dist/commands/bench.js.map +1 -0
- package/dist/commands/ci-init.d.ts +37 -0
- package/dist/commands/ci-init.d.ts.map +1 -0
- package/dist/commands/ci-init.js +115 -0
- package/dist/commands/ci-init.js.map +1 -0
- package/dist/commands/clean.d.ts +13 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +38 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/code-pack.d.ts +105 -0
- package/dist/commands/code-pack.d.ts.map +1 -0
- package/dist/commands/code-pack.js +187 -0
- package/dist/commands/code-pack.js.map +1 -0
- package/dist/commands/context.d.ts +30 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +237 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/detect-changes.d.ts +26 -0
- package/dist/commands/detect-changes.d.ts.map +1 -0
- package/dist/commands/detect-changes.js +73 -0
- package/dist/commands/detect-changes.js.map +1 -0
- package/dist/commands/doctor.d.ts +52 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +472 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/find-enclosing-symbol.d.ts +67 -0
- package/dist/commands/find-enclosing-symbol.d.ts.map +1 -0
- package/dist/commands/find-enclosing-symbol.js +106 -0
- package/dist/commands/find-enclosing-symbol.js.map +1 -0
- package/dist/commands/group.d.ts +123 -0
- package/dist/commands/group.d.ts.map +1 -0
- package/dist/commands/group.js +448 -0
- package/dist/commands/group.js.map +1 -0
- package/dist/commands/impact.d.ts +23 -0
- package/dist/commands/impact.d.ts.map +1 -0
- package/dist/commands/impact.js +91 -0
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/index-repo.d.ts +39 -0
- package/dist/commands/index-repo.d.ts.map +1 -0
- package/dist/commands/index-repo.js +148 -0
- package/dist/commands/index-repo.js.map +1 -0
- package/dist/commands/ingest-sarif.d.ts +64 -0
- package/dist/commands/ingest-sarif.d.ts.map +1 -0
- package/dist/commands/ingest-sarif.js +381 -0
- package/dist/commands/ingest-sarif.js.map +1 -0
- package/dist/commands/init.d.ts +75 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +315 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +17 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +79 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/mcp.d.ts +8 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +28 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/open-store.d.ts +25 -0
- package/dist/commands/open-store.d.ts.map +1 -0
- package/dist/commands/open-store.js +47 -0
- package/dist/commands/open-store.js.map +1 -0
- package/dist/commands/pack.d.ts +35 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/commands/pack.js +83 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/query.d.ts +85 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +309 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/scan.d.ts +81 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +407 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/setup.d.ts +178 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +370 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/sql.d.ts +19 -0
- package/dist/commands/sql.d.ts.map +1 -0
- package/dist/commands/sql.js +51 -0
- package/dist/commands/sql.js.map +1 -0
- package/dist/commands/status.d.ts +13 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +66 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/verdict-render.d.ts +33 -0
- package/dist/commands/verdict-render.d.ts.map +1 -0
- package/dist/commands/verdict-render.js +123 -0
- package/dist/commands/verdict-render.js.map +1 -0
- package/dist/commands/verdict.d.ts +61 -0
- package/dist/commands/verdict.d.ts.map +1 -0
- package/dist/commands/verdict.js +146 -0
- package/dist/commands/verdict.js.map +1 -0
- package/dist/commands/wiki.d.ts +26 -0
- package/dist/commands/wiki.d.ts.map +1 -0
- package/dist/commands/wiki.js +74 -0
- package/dist/commands/wiki.js.map +1 -0
- package/dist/editors/claude-code.d.ts +23 -0
- package/dist/editors/claude-code.d.ts.map +1 -0
- package/dist/editors/claude-code.js +58 -0
- package/dist/editors/claude-code.js.map +1 -0
- package/dist/editors/codex.d.ts +22 -0
- package/dist/editors/codex.d.ts.map +1 -0
- package/dist/editors/codex.js +59 -0
- package/dist/editors/codex.js.map +1 -0
- package/dist/editors/cursor.d.ts +13 -0
- package/dist/editors/cursor.d.ts.map +1 -0
- package/dist/editors/cursor.js +21 -0
- package/dist/editors/cursor.js.map +1 -0
- package/dist/editors/index.d.ts +12 -0
- package/dist/editors/index.d.ts.map +1 -0
- package/dist/editors/index.js +11 -0
- package/dist/editors/index.js.map +1 -0
- package/dist/editors/opencode.d.ts +23 -0
- package/dist/editors/opencode.d.ts.map +1 -0
- package/dist/editors/opencode.js +61 -0
- package/dist/editors/opencode.js.map +1 -0
- package/dist/editors/types.d.ts +33 -0
- package/dist/editors/types.d.ts.map +1 -0
- package/dist/editors/types.js +19 -0
- package/dist/editors/types.js.map +1 -0
- package/dist/editors/windows-wrap.d.ts +19 -0
- package/dist/editors/windows-wrap.d.ts.map +1 -0
- package/dist/editors/windows-wrap.js +28 -0
- package/dist/editors/windows-wrap.js.map +1 -0
- package/dist/editors/windsurf.d.ts +12 -0
- package/dist/editors/windsurf.d.ts.map +1 -0
- package/dist/editors/windsurf.js +21 -0
- package/dist/editors/windsurf.js.map +1 -0
- package/dist/embedder-downloader.d.ts +87 -0
- package/dist/embedder-downloader.d.ts.map +1 -0
- package/dist/embedder-downloader.js +261 -0
- package/dist/embedder-downloader.js.map +1 -0
- package/dist/fs-atomic.d.ts +22 -0
- package/dist/fs-atomic.d.ts.map +1 -0
- package/dist/fs-atomic.js +28 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/groups.d.ts +64 -0
- package/dist/groups.d.ts.map +1 -0
- package/dist/groups.js +172 -0
- package/dist/groups.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +703 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/is-indexed.d.ts +20 -0
- package/dist/lib/is-indexed.d.ts.map +1 -0
- package/dist/lib/is-indexed.js +35 -0
- package/dist/lib/is-indexed.js.map +1 -0
- package/dist/registry.d.ts +64 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +145 -0
- package/dist/registry.js.map +1 -0
- package/dist/scip-downloader.d.ts +138 -0
- package/dist/scip-downloader.d.ts.map +1 -0
- package/dist/scip-downloader.js +372 -0
- package/dist/scip-downloader.js.map +1 -0
- package/dist/scip-pins.d.ts +99 -0
- package/dist/scip-pins.d.ts.map +1 -0
- package/dist/scip-pins.js +195 -0
- package/dist/scip-pins.js.map +1 -0
- package/dist/skills-gen.d.ts +47 -0
- package/dist/skills-gen.d.ts.map +1 -0
- package/dist/skills-gen.js +292 -0
- package/dist/skills-gen.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codehub impact <symbol>` — dependent graph traversal for blast-radius.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to `@opencodehub/analysis`'s `runImpact()` which owns the
|
|
5
|
+
* risk-tier scoring and PROCESS_STEP fan-out logic. The CLI layer only
|
|
6
|
+
* maps the user-facing `--direction` flag into the analysis query shape
|
|
7
|
+
* and formats the result.
|
|
8
|
+
*/
|
|
9
|
+
import { runImpact as runImpactAnalysis } from "@opencodehub/analysis";
|
|
10
|
+
import { openStoreForCommand } from "./open-store.js";
|
|
11
|
+
function mapDirection(dir) {
|
|
12
|
+
if (dir === "up")
|
|
13
|
+
return "upstream";
|
|
14
|
+
if (dir === "down")
|
|
15
|
+
return "downstream";
|
|
16
|
+
return "both";
|
|
17
|
+
}
|
|
18
|
+
export async function runImpact(symbol, opts = {}) {
|
|
19
|
+
const depth = opts.depth ?? 3;
|
|
20
|
+
const direction = opts.direction ?? "both";
|
|
21
|
+
const { store, repoPath } = await openStoreForCommand(opts);
|
|
22
|
+
try {
|
|
23
|
+
const query = {
|
|
24
|
+
target: symbol,
|
|
25
|
+
direction: mapDirection(direction),
|
|
26
|
+
maxDepth: depth,
|
|
27
|
+
};
|
|
28
|
+
if (opts.targetUid !== undefined && opts.targetUid.length > 0) {
|
|
29
|
+
query.targetUid = opts.targetUid;
|
|
30
|
+
}
|
|
31
|
+
if (opts.filePath !== undefined && opts.filePath.length > 0) {
|
|
32
|
+
query.filePath = opts.filePath;
|
|
33
|
+
}
|
|
34
|
+
if (opts.kind !== undefined && opts.kind.length > 0)
|
|
35
|
+
query.kind = opts.kind;
|
|
36
|
+
const result = await runImpactAnalysis(store.graph, query);
|
|
37
|
+
if (result.ambiguous) {
|
|
38
|
+
if (opts.json) {
|
|
39
|
+
console.log(JSON.stringify(result, null, 2));
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const candidates = result.targetCandidates.slice(0, 10);
|
|
44
|
+
console.warn(`impact: "${symbol}" matched ${result.targetCandidates.length} symbols in ${repoPath}. Re-call with --target-uid, --file-path, or --kind.`);
|
|
45
|
+
for (let i = 0; i < candidates.length; i += 1) {
|
|
46
|
+
const c = candidates[i];
|
|
47
|
+
if (!c)
|
|
48
|
+
continue;
|
|
49
|
+
console.warn(` ${i + 1}. [${c.kind}] ${c.name} — ${c.filePath} (${c.id})`);
|
|
50
|
+
}
|
|
51
|
+
if (result.targetCandidates.length > candidates.length) {
|
|
52
|
+
console.warn(` … ${result.targetCandidates.length - candidates.length} more`);
|
|
53
|
+
}
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!result.chosenTarget) {
|
|
58
|
+
console.warn(`impact: no symbol matching "${symbol}" in ${repoPath}`);
|
|
59
|
+
if (opts.json) {
|
|
60
|
+
console.log(JSON.stringify(result, null, 2));
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (opts.json) {
|
|
65
|
+
console.log(JSON.stringify(result, null, 2));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.warn(`impact: ${result.chosenTarget.name} — risk=${result.risk}, ${result.totalAffected} reachable nodes at depth ≤ ${depth} (${direction}), ${result.affectedProcesses.length} affected process(es)`);
|
|
69
|
+
const header = ["DEPTH", "NODE", "VIA"];
|
|
70
|
+
const widths = header.map((h) => h.length);
|
|
71
|
+
const rows = [];
|
|
72
|
+
for (const bucket of result.byDepth) {
|
|
73
|
+
for (const node of bucket.nodes) {
|
|
74
|
+
rows.push([String(bucket.depth), node.id, node.viaRelation]);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
for (const row of rows) {
|
|
78
|
+
widths[0] = Math.max(widths[0] ?? 0, (row[0] ?? "").length);
|
|
79
|
+
widths[1] = Math.max(widths[1] ?? 0, (row[1] ?? "").length);
|
|
80
|
+
widths[2] = Math.max(widths[2] ?? 0, (row[2] ?? "").length);
|
|
81
|
+
}
|
|
82
|
+
const line = (cols) => cols.map((c, i) => c.padEnd(widths[i] ?? 0)).join(" ");
|
|
83
|
+
console.log(line(header));
|
|
84
|
+
for (const row of rows)
|
|
85
|
+
console.log(line(row));
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await store.close();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.js","sourceRoot":"","sources":["../../src/commands/impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codehub index [path...]` — register an existing `.codehub/` folder.
|
|
3
|
+
*
|
|
4
|
+
* Unlike `codehub analyze`, this command performs no ingestion. It reads
|
|
5
|
+
* `<path>/.codehub/meta.json` and upserts a registry entry keyed by the repo
|
|
6
|
+
* basename. Useful when a pre-built `.codehub/` directory is already present
|
|
7
|
+
* (shared team index, restore from backup, CI artifact download, etc.).
|
|
8
|
+
*
|
|
9
|
+
* Flag semantics:
|
|
10
|
+
* --force If `.codehub/meta.json` is missing but the path looks
|
|
11
|
+
* indexable, stamp a minimal meta sidecar using
|
|
12
|
+
* `git rev-parse HEAD` (when available) and register
|
|
13
|
+
* with zero node/edge counts. Without `--force`, a
|
|
14
|
+
* missing meta.json is a hard failure for that path.
|
|
15
|
+
* --allow-non-git Skip the `.git/` presence check so folders that carry
|
|
16
|
+
* only a `.codehub/` (e.g. synthetic fixtures) can still
|
|
17
|
+
* be registered.
|
|
18
|
+
*
|
|
19
|
+
* Multi-path behavior:
|
|
20
|
+
* Every path is processed independently. A failure on one path sets
|
|
21
|
+
* `process.exitCode = 1` but does not abort the remaining paths; all
|
|
22
|
+
* successful paths are still upserted into the registry.
|
|
23
|
+
*/
|
|
24
|
+
import { type RepoEntry } from "../registry.js";
|
|
25
|
+
export interface IndexRepoOptions {
|
|
26
|
+
readonly force?: boolean;
|
|
27
|
+
readonly allowNonGit?: boolean;
|
|
28
|
+
/** Test hook: override the home dir used for the registry. */
|
|
29
|
+
readonly home?: string;
|
|
30
|
+
/** Test hook: override the git HEAD reader (pure, no spawn). */
|
|
31
|
+
readonly readGitHead?: (repoPath: string) => Promise<string | undefined>;
|
|
32
|
+
}
|
|
33
|
+
export interface IndexRepoResult {
|
|
34
|
+
readonly successCount: number;
|
|
35
|
+
readonly failureCount: number;
|
|
36
|
+
readonly entries: readonly RepoEntry[];
|
|
37
|
+
}
|
|
38
|
+
export declare function runIndexRepo(paths: readonly string[], opts?: IndexRepoOptions): Promise<IndexRepoResult>;
|
|
39
|
+
//# sourceMappingURL=index-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-repo.d.ts","sourceRoot":"","sources":["../../src/commands/index-repo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,gBAAgB,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;CACxC;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,eAAe,CAAC,CA2B1B"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codehub index [path...]` — register an existing `.codehub/` folder.
|
|
3
|
+
*
|
|
4
|
+
* Unlike `codehub analyze`, this command performs no ingestion. It reads
|
|
5
|
+
* `<path>/.codehub/meta.json` and upserts a registry entry keyed by the repo
|
|
6
|
+
* basename. Useful when a pre-built `.codehub/` directory is already present
|
|
7
|
+
* (shared team index, restore from backup, CI artifact download, etc.).
|
|
8
|
+
*
|
|
9
|
+
* Flag semantics:
|
|
10
|
+
* --force If `.codehub/meta.json` is missing but the path looks
|
|
11
|
+
* indexable, stamp a minimal meta sidecar using
|
|
12
|
+
* `git rev-parse HEAD` (when available) and register
|
|
13
|
+
* with zero node/edge counts. Without `--force`, a
|
|
14
|
+
* missing meta.json is a hard failure for that path.
|
|
15
|
+
* --allow-non-git Skip the `.git/` presence check so folders that carry
|
|
16
|
+
* only a `.codehub/` (e.g. synthetic fixtures) can still
|
|
17
|
+
* be registered.
|
|
18
|
+
*
|
|
19
|
+
* Multi-path behavior:
|
|
20
|
+
* Every path is processed independently. A failure on one path sets
|
|
21
|
+
* `process.exitCode = 1` but does not abort the remaining paths; all
|
|
22
|
+
* successful paths are still upserted into the registry.
|
|
23
|
+
*/
|
|
24
|
+
import { access, mkdir, stat } from "node:fs/promises";
|
|
25
|
+
import { basename, resolve } from "node:path";
|
|
26
|
+
import { SCHEMA_VERSION } from "@opencodehub/core-types";
|
|
27
|
+
import { readStoreMeta, resolveRepoMetaDir, writeStoreMeta } from "@opencodehub/storage";
|
|
28
|
+
import { upsertRegistry } from "../registry.js";
|
|
29
|
+
export async function runIndexRepo(paths, opts = {}) {
|
|
30
|
+
const targets = paths.length === 0 ? [process.cwd()] : paths;
|
|
31
|
+
const entries = [];
|
|
32
|
+
let successCount = 0;
|
|
33
|
+
let failureCount = 0;
|
|
34
|
+
for (const rawPath of targets) {
|
|
35
|
+
try {
|
|
36
|
+
const entry = await indexOne(rawPath, opts);
|
|
37
|
+
entries.push(entry);
|
|
38
|
+
successCount += 1;
|
|
39
|
+
console.warn(`codehub index: registered ${entry.name} at ${entry.path} ` +
|
|
40
|
+
`(${entry.nodeCount} nodes, ${entry.edgeCount} edges)`);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
failureCount += 1;
|
|
44
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
45
|
+
console.warn(`codehub index: ${resolve(rawPath)}: ${message}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (failureCount > 0) {
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
}
|
|
51
|
+
return { successCount, failureCount, entries };
|
|
52
|
+
}
|
|
53
|
+
async function indexOne(rawPath, opts) {
|
|
54
|
+
const repoPath = resolve(rawPath);
|
|
55
|
+
// Path must exist and be a directory.
|
|
56
|
+
let st;
|
|
57
|
+
try {
|
|
58
|
+
st = await stat(repoPath);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new Error("path does not exist");
|
|
62
|
+
}
|
|
63
|
+
if (!st.isDirectory()) {
|
|
64
|
+
throw new Error("path is not a directory");
|
|
65
|
+
}
|
|
66
|
+
// `.git/` gate, unless explicitly bypassed.
|
|
67
|
+
if (opts.allowNonGit !== true) {
|
|
68
|
+
const gitDir = resolve(repoPath, ".git");
|
|
69
|
+
try {
|
|
70
|
+
await access(gitDir);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
throw new Error("not a git repository (use --allow-non-git to override)");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const metaDir = resolveRepoMetaDir(repoPath);
|
|
77
|
+
let meta = await readStoreMeta(repoPath);
|
|
78
|
+
if (meta === undefined) {
|
|
79
|
+
if (opts.force !== true) {
|
|
80
|
+
throw new Error(".codehub/meta.json not found (use --force to stamp a minimal stub, " +
|
|
81
|
+
"or run `codehub analyze` to build the index)");
|
|
82
|
+
}
|
|
83
|
+
// --force: stamp a minimal meta sidecar so the registry entry is coherent.
|
|
84
|
+
// Node/edge counts are zero because we genuinely don't know them; consumers
|
|
85
|
+
// (`codehub status`, MCP resources) treat that as "not yet analyzed".
|
|
86
|
+
await mkdir(metaDir, { recursive: true });
|
|
87
|
+
const readHead = opts.readGitHead ?? readGitHeadViaSpawn;
|
|
88
|
+
const head = opts.allowNonGit === true ? undefined : await readHead(repoPath);
|
|
89
|
+
meta = {
|
|
90
|
+
schemaVersion: SCHEMA_VERSION,
|
|
91
|
+
indexedAt: new Date().toISOString(),
|
|
92
|
+
nodeCount: 0,
|
|
93
|
+
edgeCount: 0,
|
|
94
|
+
...(head !== undefined ? { lastCommit: head } : {}),
|
|
95
|
+
};
|
|
96
|
+
await writeStoreMeta(repoPath, meta);
|
|
97
|
+
}
|
|
98
|
+
const entry = {
|
|
99
|
+
name: basename(repoPath),
|
|
100
|
+
path: repoPath,
|
|
101
|
+
indexedAt: meta.indexedAt,
|
|
102
|
+
nodeCount: meta.nodeCount,
|
|
103
|
+
edgeCount: meta.edgeCount,
|
|
104
|
+
...(meta.lastCommit !== undefined ? { lastCommit: meta.lastCommit } : {}),
|
|
105
|
+
};
|
|
106
|
+
const registryOpts = opts.home !== undefined ? { home: opts.home } : {};
|
|
107
|
+
await upsertRegistry(entry, registryOpts);
|
|
108
|
+
return entry;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Default git HEAD reader. Returns `undefined` when git is unavailable,
|
|
112
|
+
* the directory is not a git repo, or HEAD cannot be resolved (detached
|
|
113
|
+
* work trees on a fresh init with zero commits). Never throws.
|
|
114
|
+
*/
|
|
115
|
+
async function readGitHeadViaSpawn(repoPath) {
|
|
116
|
+
const { spawn } = await import("node:child_process");
|
|
117
|
+
return new Promise((resolveP) => {
|
|
118
|
+
let stdout = "";
|
|
119
|
+
let settled = false;
|
|
120
|
+
const child = spawn("git", ["rev-parse", "HEAD"], {
|
|
121
|
+
cwd: repoPath,
|
|
122
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
123
|
+
});
|
|
124
|
+
child.stdout.setEncoding("utf8");
|
|
125
|
+
child.stdout.on("data", (chunk) => {
|
|
126
|
+
stdout += chunk;
|
|
127
|
+
});
|
|
128
|
+
child.on("error", () => {
|
|
129
|
+
if (!settled) {
|
|
130
|
+
settled = true;
|
|
131
|
+
resolveP(undefined);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
child.on("close", (code) => {
|
|
135
|
+
if (settled)
|
|
136
|
+
return;
|
|
137
|
+
settled = true;
|
|
138
|
+
if (code === 0) {
|
|
139
|
+
const trimmed = stdout.trim();
|
|
140
|
+
resolveP(trimmed.length > 0 ? trimmed : undefined);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
resolveP(undefined);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=index-repo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-repo.js","sourceRoot":"","sources":["../../src/commands/index-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codehub ingest-sarif <sarif-file>` — import a SARIF v2.1.0 log into
|
|
3
|
+
* the code graph as `Finding` nodes + `FOUND_IN` edges.
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* 1. Read + parse + validate the SARIF file via `@opencodehub/sarif`.
|
|
7
|
+
* 2. Resolve the target repo (either `--repo <name>` or CWD).
|
|
8
|
+
* 3. Open the DuckDB store and pull a per-file, line-sorted symbol
|
|
9
|
+
* index over the SARIF's referenced URIs (used to resolve Finding
|
|
10
|
+
* → Symbol edges).
|
|
11
|
+
* 4. For every Result across every Run, build a Finding node keyed by
|
|
12
|
+
* `Finding:<scannerId>:<ruleId>:<uri>:<startLine>`. Emit FOUND_IN
|
|
13
|
+
* edges to the target File node (matched by `artifactLocation.uri`
|
|
14
|
+
* against `file_path`) plus a second FOUND_IN edge to the tightest
|
|
15
|
+
* enclosing symbol at `(uri, startLine)` when the graph contains
|
|
16
|
+
* one. A scanner-provided `opencodehub.symbolId` hint wins over the
|
|
17
|
+
* enclosing lookup when set.
|
|
18
|
+
* 5. UPSERT into DuckDB via `store.bulkLoad({ mode: "upsert" })`.
|
|
19
|
+
*
|
|
20
|
+
* The command is idempotent — re-running with the same SARIF produces
|
|
21
|
+
* the same nodes and edges. Results without a parsable location (no
|
|
22
|
+
* physicalLocation.artifactLocation.uri) are skipped with a warning.
|
|
23
|
+
*/
|
|
24
|
+
import { KnowledgeGraph } from "@opencodehub/core-types";
|
|
25
|
+
import { type SarifRun } from "@opencodehub/sarif";
|
|
26
|
+
import { type NodesByFile } from "./find-enclosing-symbol.js";
|
|
27
|
+
export interface IngestSarifOptions {
|
|
28
|
+
/** `--repo <name>`: look up a registered repo instead of using CWD. */
|
|
29
|
+
readonly repo?: string;
|
|
30
|
+
/** Test hook: override the registry home. */
|
|
31
|
+
readonly home?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface IngestSarifSummary {
|
|
34
|
+
readonly sarifFile: string;
|
|
35
|
+
readonly repoPath: string;
|
|
36
|
+
readonly findingsEmitted: number;
|
|
37
|
+
readonly edgesEmitted: number;
|
|
38
|
+
readonly resultsSkipped: number;
|
|
39
|
+
readonly warnings: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
export declare function runIngestSarif(sarifFile: string, opts?: IngestSarifOptions): Promise<IngestSarifSummary>;
|
|
42
|
+
interface BuildSummary {
|
|
43
|
+
readonly findingsEmitted: number;
|
|
44
|
+
readonly edgesEmitted: number;
|
|
45
|
+
readonly resultsSkipped: number;
|
|
46
|
+
readonly warnings: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Pure builder over SARIF runs. Exposed for unit tests so we can exercise
|
|
50
|
+
* the node/edge emission logic without touching DuckDB.
|
|
51
|
+
*
|
|
52
|
+
* `nodesByFile` is the per-file, line-sorted symbol index (produced by
|
|
53
|
+
* {@link indexNodesByFile}) used to resolve each SARIF result back to the
|
|
54
|
+
* tightest-enclosing code symbol when the scanner did not populate
|
|
55
|
+
* `result.properties["opencodehub.symbolId"]` itself. Callers that only
|
|
56
|
+
* want the File-level edge (e.g. unit tests) can omit it — an empty map
|
|
57
|
+
* means every symbol lookup misses and only the File edge is emitted.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildFindingsGraph(runs: readonly SarifRun[], nodesByFile?: NodesByFile): {
|
|
60
|
+
graph: KnowledgeGraph;
|
|
61
|
+
summary: BuildSummary;
|
|
62
|
+
};
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=ingest-sarif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-sarif.d.ts","sourceRoot":"","sources":["../../src/commands/ingest-sarif.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAAoB,cAAc,EAA2B,MAAM,yBAAyB,CAAC;AACpG,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CA8D7B;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,WAAW,GAAE,WAAuB,GACnC;IACD,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;CACvB,CAgEA"}
|