@nodesify/astria 1.0.0 → 1.0.1

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.
Files changed (81) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +65 -65
  3. package/dist/commands/add.d.ts +7 -7
  4. package/dist/commands/add.js +33 -33
  5. package/dist/commands/affected.d.ts +5 -5
  6. package/dist/commands/affected.js +29 -29
  7. package/dist/commands/cluster.d.ts +1 -1
  8. package/dist/commands/cluster.js +50 -50
  9. package/dist/commands/diagnose.d.ts +4 -4
  10. package/dist/commands/diagnose.js +19 -19
  11. package/dist/commands/diff.d.ts +1 -1
  12. package/dist/commands/diff.js +35 -35
  13. package/dist/commands/explain.d.ts +3 -3
  14. package/dist/commands/explain.js +37 -37
  15. package/dist/commands/export.d.ts +6 -6
  16. package/dist/commands/export.js +32 -32
  17. package/dist/commands/feedback.d.ts +11 -11
  18. package/dist/commands/feedback.js +40 -40
  19. package/dist/commands/global.d.ts +6 -6
  20. package/dist/commands/global.js +60 -60
  21. package/dist/commands/history.d.ts +4 -4
  22. package/dist/commands/history.js +27 -27
  23. package/dist/commands/hook-guard.d.ts +1 -1
  24. package/dist/commands/hook-guard.js +144 -144
  25. package/dist/commands/hook.d.ts +2 -2
  26. package/dist/commands/hook.js +52 -52
  27. package/dist/commands/install.d.ts +2 -2
  28. package/dist/commands/install.js +39 -39
  29. package/dist/commands/map.d.ts +5 -5
  30. package/dist/commands/map.js +15 -15
  31. package/dist/commands/mcp.d.ts +3 -3
  32. package/dist/commands/mcp.js +14 -14
  33. package/dist/commands/merge.d.ts +1 -1
  34. package/dist/commands/merge.js +50 -50
  35. package/dist/commands/migrate.d.ts +3 -3
  36. package/dist/commands/migrate.js +74 -74
  37. package/dist/commands/path.d.ts +5 -5
  38. package/dist/commands/path.js +18 -18
  39. package/dist/commands/prs.d.ts +4 -4
  40. package/dist/commands/prs.js +132 -132
  41. package/dist/commands/query.d.ts +9 -9
  42. package/dist/commands/query.js +21 -21
  43. package/dist/commands/run.d.ts +9 -9
  44. package/dist/commands/run.js +68 -68
  45. package/dist/commands/stats.d.ts +3 -3
  46. package/dist/commands/stats.js +17 -17
  47. package/dist/commands/status.d.ts +3 -3
  48. package/dist/commands/status.js +56 -56
  49. package/dist/commands/tree.d.ts +5 -5
  50. package/dist/commands/tree.js +52 -52
  51. package/dist/commands/update.d.ts +6 -6
  52. package/dist/commands/update.js +65 -65
  53. package/dist/commands/watch.d.ts +3 -3
  54. package/dist/commands/watch.js +113 -113
  55. package/dist/commands/wiki.d.ts +6 -6
  56. package/dist/commands/wiki.js +59 -59
  57. package/dist/index.d.ts +4 -4
  58. package/dist/index.js +249 -249
  59. package/dist/install/hooks.d.ts +11 -11
  60. package/dist/install/hooks.js +306 -306
  61. package/dist/install/index.d.ts +2 -2
  62. package/dist/install/index.js +361 -361
  63. package/dist/install/markdown-inject.d.ts +6 -6
  64. package/dist/install/markdown-inject.js +177 -177
  65. package/dist/install/platforms.d.ts +12 -12
  66. package/dist/install/platforms.js +129 -129
  67. package/dist/install/settings-inject.d.ts +17 -17
  68. package/dist/install/settings-inject.js +424 -424
  69. package/dist/native.d.ts +31 -31
  70. package/dist/native.js +106 -106
  71. package/package.json +72 -72
  72. package/skills/skill-aider.md +40 -40
  73. package/skills/skill-codex.md +46 -46
  74. package/skills/skill-copilot.md +46 -46
  75. package/skills/skill-cursor.md +39 -39
  76. package/skills/skill-gemini.md +46 -46
  77. package/skills/skill-kiro.md +39 -39
  78. package/skills/skill-opencode.md +44 -44
  79. package/skills/skill-trae.md +46 -46
  80. package/skills/skill.md +266 -266
  81. package/dist/graphify.node +0 -4
@@ -1,51 +1,51 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.mergeCommand = mergeCommand;
37
- const path = __importStar(require("path"));
38
- const native_1 = require("../native");
39
- async function mergeCommand(pathA, pathB, outPath) {
40
- try {
41
- console.log(`Merging graphs: ${pathA} + ${pathB} -> ${outPath}`);
42
- const result = (0, native_1.mergeGraphs)(pathA, pathB, outPath);
43
- console.log(`Nodes: ${result.nodesAdded}, Edges: ${result.edgesAdded}, Communities: ${result.communities}`);
44
- console.log(`Merged graph written to: ${path.join(outPath, '.astria')}`);
45
- }
46
- catch (e) {
47
- console.error(`Error: ${e.message || e}`);
48
- process.exitCode = 1;
49
- }
50
- }
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.mergeCommand = mergeCommand;
37
+ const path = __importStar(require("path"));
38
+ const native_1 = require("../native");
39
+ async function mergeCommand(pathA, pathB, outPath) {
40
+ try {
41
+ console.log(`Merging graphs: ${pathA} + ${pathB} -> ${outPath}`);
42
+ const result = (0, native_1.mergeGraphs)(pathA, pathB, outPath);
43
+ console.log(`Nodes: ${result.nodesAdded}, Edges: ${result.edgesAdded}, Communities: ${result.communities}`);
44
+ console.log(`Merged graph written to: ${path.join(outPath, '.astria')}`);
45
+ }
46
+ catch (e) {
47
+ console.error(`Error: ${e.message || e}`);
48
+ process.exitCode = 1;
49
+ }
50
+ }
51
51
  //# sourceMappingURL=merge.js.map
@@ -1,4 +1,4 @@
1
- export declare function migrateCommand(opts: {
2
- graph: string;
3
- }): void;
1
+ export declare function migrateCommand(opts: {
2
+ graph: string;
3
+ }): void;
4
4
  //# sourceMappingURL=migrate.d.ts.map
@@ -1,75 +1,75 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.migrateCommand = migrateCommand;
4
- const fs_1 = require("fs");
5
- const path_1 = require("path");
6
- function homeDir() {
7
- return process.env.USERPROFILE || process.env.HOME || '.';
8
- }
9
- function moveOrReport(from, to, label) {
10
- if (!(0, fs_1.existsSync)(from))
11
- return 'absent';
12
- if ((0, fs_1.existsSync)(to)) {
13
- console.log(`[migrate] ${label}: ${to} already exists — left ${from} untouched. Remove it manually once verified.`);
14
- return 'target-exists';
15
- }
16
- try {
17
- (0, fs_1.renameSync)(from, to);
18
- }
19
- catch (err) {
20
- if (err && (err.code === 'EPERM' || err.code === 'EBUSY' || err.code === 'ENOTEMPTY')) {
21
- console.error(`[migrate] ${label}: ${from} is locked by another process (editor MCP server, watcher, or a running query).\n` +
22
- `Close it and re-run \`astria migrate\`.`);
23
- return 'locked';
24
- }
25
- throw err;
26
- }
27
- console.log(`[migrate] ${label}: ${from} -> ${to}`);
28
- return 'moved';
29
- }
30
- /// One-time migration from the pre-1.0 nodesify-graphify layout. 1.0 reads
31
- /// only `.astria/`, so this is the escape hatch for existing graphs: the
32
- /// data folder, ignore file, and home-dir global store are renamed in place.
33
- function migrateCommand(opts) {
34
- const root = opts.graph;
35
- if (!(0, fs_1.existsSync)(root)) {
36
- throw new Error(`path not found: ${root}`);
37
- }
38
- let moved = 0;
39
- let locked = 0;
40
- const results = [
41
- moveOrReport((0, path_1.join)(root, '.graphify'), (0, path_1.join)(root, '.astria'), 'data folder'),
42
- moveOrReport((0, path_1.join)(root, '.graphifyignore'), (0, path_1.join)(root, '.astriaignore'), 'ignore file'),
43
- ];
44
- for (const r of results) {
45
- if (r === 'moved')
46
- moved += 1;
47
- if (r === 'locked')
48
- locked += 1;
49
- }
50
- const globalFrom = (0, path_1.join)(homeDir(), '.nodesify-graphify', 'global.db');
51
- const globalTo = (0, path_1.join)(homeDir(), '.astria', 'global.db');
52
- if ((0, fs_1.existsSync)(globalFrom)) {
53
- if ((0, fs_1.existsSync)(globalTo)) {
54
- console.log(`[migrate] global store: ${globalTo} already exists — left ${globalFrom} untouched.`);
55
- }
56
- else {
57
- const r = moveOrReport(globalFrom, globalTo, 'global store');
58
- if (r === 'moved')
59
- moved += 1;
60
- if (r === 'locked')
61
- locked += 1;
62
- }
63
- }
64
- if (locked > 0) {
65
- console.log(`[migrate] ${locked} item(s) still locked — close the locking process and re-run \`astria migrate\`.`);
66
- process.exitCode = 1;
67
- }
68
- else if (moved === 0) {
69
- console.log('[migrate] nothing to migrate (no pre-1.0 layout found).');
70
- }
71
- else {
72
- console.log(`[migrate] done — ${moved} item(s) moved. Run \`astria update ${root}\` to refresh.`);
73
- }
74
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrateCommand = migrateCommand;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ function homeDir() {
7
+ return process.env.USERPROFILE || process.env.HOME || '.';
8
+ }
9
+ function moveOrReport(from, to, label) {
10
+ if (!(0, fs_1.existsSync)(from))
11
+ return 'absent';
12
+ if ((0, fs_1.existsSync)(to)) {
13
+ console.log(`[migrate] ${label}: ${to} already exists — left ${from} untouched. Remove it manually once verified.`);
14
+ return 'target-exists';
15
+ }
16
+ try {
17
+ (0, fs_1.renameSync)(from, to);
18
+ }
19
+ catch (err) {
20
+ if (err && (err.code === 'EPERM' || err.code === 'EBUSY' || err.code === 'ENOTEMPTY')) {
21
+ console.error(`[migrate] ${label}: ${from} is locked by another process (editor MCP server, watcher, or a running query).\n` +
22
+ `Close it and re-run \`astria migrate\`.`);
23
+ return 'locked';
24
+ }
25
+ throw err;
26
+ }
27
+ console.log(`[migrate] ${label}: ${from} -> ${to}`);
28
+ return 'moved';
29
+ }
30
+ /// One-time migration from the pre-1.0 nodesify-graphify layout. 1.0 reads
31
+ /// only `.astria/`, so this is the escape hatch for existing graphs: the
32
+ /// data folder, ignore file, and home-dir global store are renamed in place.
33
+ function migrateCommand(opts) {
34
+ const root = opts.graph;
35
+ if (!(0, fs_1.existsSync)(root)) {
36
+ throw new Error(`path not found: ${root}`);
37
+ }
38
+ let moved = 0;
39
+ let locked = 0;
40
+ const results = [
41
+ moveOrReport((0, path_1.join)(root, '.graphify'), (0, path_1.join)(root, '.astria'), 'data folder'),
42
+ moveOrReport((0, path_1.join)(root, '.graphifyignore'), (0, path_1.join)(root, '.astriaignore'), 'ignore file'),
43
+ ];
44
+ for (const r of results) {
45
+ if (r === 'moved')
46
+ moved += 1;
47
+ if (r === 'locked')
48
+ locked += 1;
49
+ }
50
+ const globalFrom = (0, path_1.join)(homeDir(), '.nodesify-graphify', 'global.db');
51
+ const globalTo = (0, path_1.join)(homeDir(), '.astria', 'global.db');
52
+ if ((0, fs_1.existsSync)(globalFrom)) {
53
+ if ((0, fs_1.existsSync)(globalTo)) {
54
+ console.log(`[migrate] global store: ${globalTo} already exists — left ${globalFrom} untouched.`);
55
+ }
56
+ else {
57
+ const r = moveOrReport(globalFrom, globalTo, 'global store');
58
+ if (r === 'moved')
59
+ moved += 1;
60
+ if (r === 'locked')
61
+ locked += 1;
62
+ }
63
+ }
64
+ if (locked > 0) {
65
+ console.log(`[migrate] ${locked} item(s) still locked — close the locking process and re-run \`astria migrate\`.`);
66
+ process.exitCode = 1;
67
+ }
68
+ else if (moved === 0) {
69
+ console.log('[migrate] nothing to migrate (no pre-1.0 layout found).');
70
+ }
71
+ else {
72
+ console.log(`[migrate] done — ${moved} item(s) moved. Run \`astria update ${root}\` to refresh.`);
73
+ }
74
+ }
75
75
  //# sourceMappingURL=migrate.js.map
@@ -1,6 +1,6 @@
1
- export declare function pathCommand(source: string, target: string, opts: {
2
- graph: string;
3
- directed?: boolean;
4
- detail?: string;
5
- }): Promise<void>;
1
+ export declare function pathCommand(source: string, target: string, opts: {
2
+ graph: string;
3
+ directed?: boolean;
4
+ detail?: string;
5
+ }): Promise<void>;
6
6
  //# sourceMappingURL=path.d.ts.map
@@ -1,19 +1,19 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pathCommand = pathCommand;
4
- const native_1 = require("../native");
5
- async function pathCommand(source, target, opts) {
6
- try {
7
- const result = (0, native_1.findPath)(opts.graph, source, target, opts.directed ?? false, opts.detail);
8
- if (!result.found) {
9
- console.log(result.text);
10
- return;
11
- }
12
- console.log(result.text);
13
- }
14
- catch (e) {
15
- console.error(`Error: ${e.message || e}`);
16
- process.exitCode = 1;
17
- }
18
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pathCommand = pathCommand;
4
+ const native_1 = require("../native");
5
+ async function pathCommand(source, target, opts) {
6
+ try {
7
+ const result = (0, native_1.findPath)(opts.graph, source, target, opts.directed ?? false, opts.detail);
8
+ if (!result.found) {
9
+ console.log(result.text);
10
+ return;
11
+ }
12
+ console.log(result.text);
13
+ }
14
+ catch (e) {
15
+ console.error(`Error: ${e.message || e}`);
16
+ process.exitCode = 1;
17
+ }
18
+ }
19
19
  //# sourceMappingURL=path.js.map
@@ -1,5 +1,5 @@
1
- export declare function prsCommand(count: string, opts: {
2
- graph: string;
3
- conflicts: boolean;
4
- }): Promise<void>;
1
+ export declare function prsCommand(count: string, opts: {
2
+ graph: string;
3
+ conflicts: boolean;
4
+ }): Promise<void>;
5
5
  //# sourceMappingURL=prs.d.ts.map
@@ -1,133 +1,133 @@
1
- "use strict";
2
- // PR impact dashboard: maps open PRs' changed files onto the knowledge graph
3
- // (communities touched, node blast radius) and flags merge-order risk.
4
- // Ported from upstream graphify v8 prs.py. Requires the `gh` CLI (read-only).
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.prsCommand = prsCommand;
7
- const child_process_1 = require("child_process");
8
- const fs_1 = require("fs");
9
- const path_1 = require("path");
10
- const DIM = '\x1b[2m';
11
- const BOLD = '\x1b[1m';
12
- const YELLOW = '\x1b[33m';
13
- const CYAN = '\x1b[36m';
14
- const RESET = '\x1b[0m';
15
- function ghAvailable() {
16
- try {
17
- (0, child_process_1.execFileSync)('gh', ['--version'], { stdio: 'pipe' });
18
- return true;
19
- }
20
- catch {
21
- return false;
22
- }
23
- }
24
- function listOpenPrs(limit) {
25
- const out = (0, child_process_1.execFileSync)('gh', ['pr', 'list', '--limit', String(limit), '--json', 'number,title,headRefName,baseRefName,isDraft'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
26
- return JSON.parse(out);
27
- }
28
- function prFiles(number) {
29
- if (!Number.isInteger(number) || number <= 0)
30
- return [];
31
- try {
32
- const out = (0, child_process_1.execFileSync)('gh', ['pr', 'view', String(number), '--json', 'files'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
33
- const parsed = JSON.parse(out);
34
- return (parsed.files || []).map((f) => f.path);
35
- }
36
- catch {
37
- return [];
38
- }
39
- }
40
- function loadGraphNodes(graphRoot) {
41
- const graphJson = (0, path_1.join)(graphRoot, '.astria', 'graph.json');
42
- if (!(0, fs_1.existsSync)(graphJson)) {
43
- throw new Error(`no graph found at ${graphJson} — run 'astria run ${graphRoot}' first`);
44
- }
45
- const graph = JSON.parse((0, fs_1.readFileSync)(graphJson, 'utf-8'));
46
- return (graph.nodes || []).map((n) => ({
47
- source_file: String(n.source_file || '').replace(/\\/g, '/'),
48
- community: n.community ?? null,
49
- }));
50
- }
51
- function computeImpact(pr, files, nodes) {
52
- const normalized = files.map((f) => f.replace(/\\/g, '/'));
53
- const impact = {
54
- number: pr.number,
55
- title: pr.title,
56
- draft: pr.isDraft,
57
- files,
58
- nodes: new Set(),
59
- communities: new Map(),
60
- };
61
- for (const node of nodes) {
62
- if (!node.source_file)
63
- continue;
64
- const hit = normalized.some((f) => node.source_file === f || node.source_file.endsWith('/' + f));
65
- if (hit) {
66
- impact.nodes.add(node.source_file);
67
- if (node.community !== null) {
68
- impact.communities.set(node.community, (impact.communities.get(node.community) || 0) + 1);
69
- }
70
- }
71
- }
72
- return impact;
73
- }
74
- function printTable(impacts) {
75
- console.log(`${BOLD}Open pull requests mapped onto the knowledge graph${RESET}\n`);
76
- const numW = String(Math.max(...impacts.map((i) => i.number), 0)).length;
77
- for (const pr of impacts) {
78
- const draft = pr.draft ? `${DIM}[draft]${RESET} ` : '';
79
- const top = [...pr.communities.entries()].sort((a, b) => b[1] - a[1]).slice(0, 4);
80
- const commStr = top.map(([c, n]) => `${CYAN}${c}${RESET}:${n}`).join(' ') || '—';
81
- const symbols = [...pr.communities.values()].reduce((a, b) => a + b, 0);
82
- console.log(`${DIM}#${String(pr.number).padStart(numW)}${RESET} ${draft}${pr.title}`);
83
- console.log(` ${DIM}${pr.files.length} file(s) · ${symbols} graph symbols · communities: ${commStr}${RESET}`);
84
- }
85
- }
86
- function printConflicts(impacts) {
87
- console.log(`\n${BOLD}Merge-order risk (shared communities)${RESET}\n`);
88
- let found = false;
89
- for (let i = 0; i < impacts.length; i++) {
90
- for (let j = i + 1; j < impacts.length; j++) {
91
- const shared = [...impacts[i].communities.keys()].filter((c) => impacts[j].communities.has(c));
92
- if (shared.length > 0) {
93
- found = true;
94
- console.log(`${YELLOW}#${impacts[i].number} ↔ #${impacts[j].number}${RESET} share ${shared.length} communit${shared.length === 1 ? 'y' : 'ies'}: ${shared.slice(0, 8).join(', ')}${shared.length > 8 ? ' …' : ''}`);
95
- }
96
- }
97
- }
98
- if (!found)
99
- console.log('No shared communities between open PRs.');
100
- }
101
- async function prsCommand(count, opts) {
102
- const limit = parseInt(count, 10) || 20;
103
- try {
104
- if (!ghAvailable()) {
105
- console.error('Error: the GitHub CLI (gh) is required for this command — https://cli.github.com');
106
- process.exitCode = 1;
107
- return;
108
- }
109
- let prs;
110
- try {
111
- prs = listOpenPrs(limit);
112
- }
113
- catch (e) {
114
- console.error(`Error: gh could not list PRs (not a git repo / not authenticated?): ${e.message || e}`);
115
- process.exitCode = 1;
116
- return;
117
- }
118
- if (prs.length === 0) {
119
- console.log('No open pull requests.');
120
- return;
121
- }
122
- const nodes = loadGraphNodes(opts.graph);
123
- const impacts = prs.map((pr) => computeImpact(pr, prFiles(pr.number), nodes));
124
- printTable(impacts);
125
- if (opts.conflicts)
126
- printConflicts(impacts);
127
- }
128
- catch (e) {
129
- console.error(`Error: ${e.message || e}`);
130
- process.exitCode = 1;
131
- }
132
- }
1
+ "use strict";
2
+ // PR impact dashboard: maps open PRs' changed files onto the knowledge graph
3
+ // (communities touched, node blast radius) and flags merge-order risk.
4
+ // Ported from upstream graphify v8 prs.py. Requires the `gh` CLI (read-only).
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.prsCommand = prsCommand;
7
+ const child_process_1 = require("child_process");
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ const DIM = '\x1b[2m';
11
+ const BOLD = '\x1b[1m';
12
+ const YELLOW = '\x1b[33m';
13
+ const CYAN = '\x1b[36m';
14
+ const RESET = '\x1b[0m';
15
+ function ghAvailable() {
16
+ try {
17
+ (0, child_process_1.execFileSync)('gh', ['--version'], { stdio: 'pipe' });
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function listOpenPrs(limit) {
25
+ const out = (0, child_process_1.execFileSync)('gh', ['pr', 'list', '--limit', String(limit), '--json', 'number,title,headRefName,baseRefName,isDraft'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
26
+ return JSON.parse(out);
27
+ }
28
+ function prFiles(number) {
29
+ if (!Number.isInteger(number) || number <= 0)
30
+ return [];
31
+ try {
32
+ const out = (0, child_process_1.execFileSync)('gh', ['pr', 'view', String(number), '--json', 'files'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
33
+ const parsed = JSON.parse(out);
34
+ return (parsed.files || []).map((f) => f.path);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ function loadGraphNodes(graphRoot) {
41
+ const graphJson = (0, path_1.join)(graphRoot, '.astria', 'graph.json');
42
+ if (!(0, fs_1.existsSync)(graphJson)) {
43
+ throw new Error(`no graph found at ${graphJson} — run 'astria run ${graphRoot}' first`);
44
+ }
45
+ const graph = JSON.parse((0, fs_1.readFileSync)(graphJson, 'utf-8'));
46
+ return (graph.nodes || []).map((n) => ({
47
+ source_file: String(n.source_file || '').replace(/\\/g, '/'),
48
+ community: n.community ?? null,
49
+ }));
50
+ }
51
+ function computeImpact(pr, files, nodes) {
52
+ const normalized = files.map((f) => f.replace(/\\/g, '/'));
53
+ const impact = {
54
+ number: pr.number,
55
+ title: pr.title,
56
+ draft: pr.isDraft,
57
+ files,
58
+ nodes: new Set(),
59
+ communities: new Map(),
60
+ };
61
+ for (const node of nodes) {
62
+ if (!node.source_file)
63
+ continue;
64
+ const hit = normalized.some((f) => node.source_file === f || node.source_file.endsWith('/' + f));
65
+ if (hit) {
66
+ impact.nodes.add(node.source_file);
67
+ if (node.community !== null) {
68
+ impact.communities.set(node.community, (impact.communities.get(node.community) || 0) + 1);
69
+ }
70
+ }
71
+ }
72
+ return impact;
73
+ }
74
+ function printTable(impacts) {
75
+ console.log(`${BOLD}Open pull requests mapped onto the knowledge graph${RESET}\n`);
76
+ const numW = String(Math.max(...impacts.map((i) => i.number), 0)).length;
77
+ for (const pr of impacts) {
78
+ const draft = pr.draft ? `${DIM}[draft]${RESET} ` : '';
79
+ const top = [...pr.communities.entries()].sort((a, b) => b[1] - a[1]).slice(0, 4);
80
+ const commStr = top.map(([c, n]) => `${CYAN}${c}${RESET}:${n}`).join(' ') || '—';
81
+ const symbols = [...pr.communities.values()].reduce((a, b) => a + b, 0);
82
+ console.log(`${DIM}#${String(pr.number).padStart(numW)}${RESET} ${draft}${pr.title}`);
83
+ console.log(` ${DIM}${pr.files.length} file(s) · ${symbols} graph symbols · communities: ${commStr}${RESET}`);
84
+ }
85
+ }
86
+ function printConflicts(impacts) {
87
+ console.log(`\n${BOLD}Merge-order risk (shared communities)${RESET}\n`);
88
+ let found = false;
89
+ for (let i = 0; i < impacts.length; i++) {
90
+ for (let j = i + 1; j < impacts.length; j++) {
91
+ const shared = [...impacts[i].communities.keys()].filter((c) => impacts[j].communities.has(c));
92
+ if (shared.length > 0) {
93
+ found = true;
94
+ console.log(`${YELLOW}#${impacts[i].number} ↔ #${impacts[j].number}${RESET} share ${shared.length} communit${shared.length === 1 ? 'y' : 'ies'}: ${shared.slice(0, 8).join(', ')}${shared.length > 8 ? ' …' : ''}`);
95
+ }
96
+ }
97
+ }
98
+ if (!found)
99
+ console.log('No shared communities between open PRs.');
100
+ }
101
+ async function prsCommand(count, opts) {
102
+ const limit = parseInt(count, 10) || 20;
103
+ try {
104
+ if (!ghAvailable()) {
105
+ console.error('Error: the GitHub CLI (gh) is required for this command — https://cli.github.com');
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+ let prs;
110
+ try {
111
+ prs = listOpenPrs(limit);
112
+ }
113
+ catch (e) {
114
+ console.error(`Error: gh could not list PRs (not a git repo / not authenticated?): ${e.message || e}`);
115
+ process.exitCode = 1;
116
+ return;
117
+ }
118
+ if (prs.length === 0) {
119
+ console.log('No open pull requests.');
120
+ return;
121
+ }
122
+ const nodes = loadGraphNodes(opts.graph);
123
+ const impacts = prs.map((pr) => computeImpact(pr, prFiles(pr.number), nodes));
124
+ printTable(impacts);
125
+ if (opts.conflicts)
126
+ printConflicts(impacts);
127
+ }
128
+ catch (e) {
129
+ console.error(`Error: ${e.message || e}`);
130
+ process.exitCode = 1;
131
+ }
132
+ }
133
133
  //# sourceMappingURL=prs.js.map
@@ -1,10 +1,10 @@
1
- export declare function queryCommand(question: string, opts: {
2
- graph: string;
3
- dfs: boolean;
4
- depth: string;
5
- budget: string;
6
- directed?: boolean;
7
- detail?: string;
8
- cursor?: string;
9
- }): Promise<void>;
1
+ export declare function queryCommand(question: string, opts: {
2
+ graph: string;
3
+ dfs: boolean;
4
+ depth: string;
5
+ budget: string;
6
+ directed?: boolean;
7
+ detail?: string;
8
+ cursor?: string;
9
+ }): Promise<void>;
10
10
  //# sourceMappingURL=query.d.ts.map
@@ -1,22 +1,22 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.queryCommand = queryCommand;
4
- const native_1 = require("../native");
5
- async function queryCommand(question, opts) {
6
- try {
7
- const mode = opts.dfs ? 'dfs' : 'bfs';
8
- const depth = parseInt(opts.depth || '2', 10);
9
- const budget = parseInt(opts.budget || '2000', 10);
10
- const cursor = parseInt(opts.cursor || '0', 10) || 0;
11
- const result = (0, native_1.queryGraph)(opts.graph, question, mode, depth, budget, opts.directed ?? false, opts.detail, cursor);
12
- console.log(result.text);
13
- if (result.graphBuiltAt) {
14
- console.log(`# graph built at ${result.graphBuiltAt}`);
15
- }
16
- }
17
- catch (e) {
18
- console.error(`Error: ${e.message || e}`);
19
- process.exitCode = 1;
20
- }
21
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryCommand = queryCommand;
4
+ const native_1 = require("../native");
5
+ async function queryCommand(question, opts) {
6
+ try {
7
+ const mode = opts.dfs ? 'dfs' : 'bfs';
8
+ const depth = parseInt(opts.depth || '2', 10);
9
+ const budget = parseInt(opts.budget || '2000', 10);
10
+ const cursor = parseInt(opts.cursor || '0', 10) || 0;
11
+ const result = (0, native_1.queryGraph)(opts.graph, question, mode, depth, budget, opts.directed ?? false, opts.detail, cursor);
12
+ console.log(result.text);
13
+ if (result.graphBuiltAt) {
14
+ console.log(`# graph built at ${result.graphBuiltAt}`);
15
+ }
16
+ }
17
+ catch (e) {
18
+ console.error(`Error: ${e.message || e}`);
19
+ process.exitCode = 1;
20
+ }
21
+ }
22
22
  //# sourceMappingURL=query.js.map