pm-graph 0.1.4

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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.4 - 2026-05-26
4
+
5
+ ### Other
6
+
7
+ - Release readiness hardening for pm-graph ([pm-graph-fnu1](https://github.com/unbraind/pm-graph/blob/main/.agents/pm/tasks/pm-graph-fnu1.toon))
package/README.md ADDED
@@ -0,0 +1,273 @@
1
+ # pm-graph
2
+
3
+ Knowledge graph and dependency graph extension for [pm CLI](https://github.com/unbraind/pm-cli) workspaces, with optional Neo4j sync.
4
+
5
+ The extension reads the current workspace through `pm list-all --json` and `pm deps <id> --json`, then turns items, parent links, `blocked_by` metadata, dependency metadata, tags, statuses, types, assignees, sprints, and releases into graph nodes and relationships.
6
+
7
+ ## Quick Start
8
+
9
+ **Step 1 — Install the extension:**
10
+
11
+ ```bash
12
+ pm install github.com/unbraind/pm-graph
13
+ pm pm-graph ping
14
+ ```
15
+
16
+ **Step 2 — Configure Neo4j environment variables** (only needed for `sync`, `status`, `query`, `neighbors`):
17
+
18
+ ```bash
19
+ export NEO4J_URI=bolt://localhost:7687
20
+ export NEO4J_USER=neo4j
21
+ export NEO4J_PASSWORD=change-me
22
+ ```
23
+
24
+ **Step 3 — Sync your workspace to Neo4j:**
25
+
26
+ ```bash
27
+ pm pm-graph sync --json
28
+ ```
29
+
30
+ That's it. Open Neo4j Browser at `http://localhost:7474` to explore your graph.
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pm install github.com/unbraind/pm-graph
36
+ pm pm-graph ping
37
+ ```
38
+
39
+ To reinstall or update:
40
+
41
+ ```bash
42
+ pm install github.com/unbraind/pm-graph --force
43
+ ```
44
+
45
+ ## Environment Variables
46
+
47
+ | Variable | Required | Description |
48
+ |---|---|---|
49
+ | `NEO4J_URI` | Yes (for Neo4j commands) | Bolt URI, e.g. `bolt://localhost:7687` |
50
+ | `NEO4J_USER` | Yes (for Neo4j commands) | Neo4j username, e.g. `neo4j` |
51
+ | `NEO4J_PASSWORD` | Yes (for Neo4j commands) | Neo4j password |
52
+ | `NEO4J_DATABASE` | No | Target database (defaults to server default) |
53
+ | `PM_GRAPH_PROJECT_KEY` | No | Override the project key (defaults to workspace directory name) |
54
+
55
+ The commands `export` and `cypher` do not require Neo4j at all.
56
+
57
+ ## Commands
58
+
59
+ ### `pm pm-graph ping`
60
+
61
+ Verify that the extension is active. Returns the extension version and whether Neo4j is configured.
62
+
63
+ ```bash
64
+ pm pm-graph ping --json
65
+ ```
66
+
67
+ Example output:
68
+
69
+ ```json
70
+ {
71
+ "ok": true,
72
+ "source": "pm-graph",
73
+ "neo4jConfigured": true,
74
+ "version": "0.1.4"
75
+ }
76
+ ```
77
+
78
+ ### `pm pm-graph export`
79
+
80
+ Export the current workspace as a dependency and knowledge graph in JSON format. Returns `nodes`, `relationships`, and a `projectKey`. **Does not require Neo4j.**
81
+
82
+ ```bash
83
+ pm pm-graph export --json
84
+ ```
85
+
86
+ Example output (abbreviated):
87
+
88
+ ```json
89
+ {
90
+ "ok": true,
91
+ "graph": {
92
+ "generatedAt": "2026-05-14T10:00:00.000Z",
93
+ "workspace": "/path/to/workspace",
94
+ "projectKey": "my-project",
95
+ "nodes": [
96
+ { "id": "TASK-1", "labels": ["PmItem", "task"], "properties": { "title": "Build API", "status": "in_progress" } }
97
+ ],
98
+ "relationships": [
99
+ { "from": "TASK-2", "to": "TASK-1", "type": "BLOCKED_BY", "properties": {} }
100
+ ]
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### `pm pm-graph cypher`
106
+
107
+ Render parameterized Cypher statements for importing the current workspace graph into Neo4j. Returns the statements without executing them. **Does not require Neo4j.**
108
+
109
+ ```bash
110
+ pm pm-graph cypher --json
111
+ ```
112
+
113
+ Example output (abbreviated):
114
+
115
+ ```json
116
+ {
117
+ "ok": true,
118
+ "graph": { "nodes": 12, "relationships": 8 },
119
+ "statements": [
120
+ {
121
+ "statement": "MATCH (n:PmGraphNode {projectKey: $projectKey}) DETACH DELETE n",
122
+ "parameters": { "projectKey": "my-project" }
123
+ }
124
+ ]
125
+ }
126
+ ```
127
+
128
+ ### `pm pm-graph sync`
129
+
130
+ Sync the current workspace graph into Neo4j using the `NEO4J_*` environment variables.
131
+
132
+ - **Default (incremental):** Upserts all nodes and relationships, then deletes stale nodes that are no longer present in the workspace.
133
+ - **`--full`:** Performs a complete wipe-and-resync — deletes all `PmGraphNode` entries for the project before re-importing.
134
+
135
+ After every sync, a `lastSyncedAt` timestamp is stored in a `PmGraphSync` metadata node in Neo4j.
136
+
137
+ ```bash
138
+ pm pm-graph sync --json # incremental
139
+ pm pm-graph sync --full --json # complete resync
140
+ ```
141
+
142
+ Example output:
143
+
144
+ ```json
145
+ {
146
+ "ok": true,
147
+ "projectKey": "my-project",
148
+ "syncedNodes": 18,
149
+ "syncedRelationships": 11,
150
+ "deletedStaleNodes": 0,
151
+ "fullSync": false
152
+ }
153
+ ```
154
+
155
+ ### `pm pm-graph status`
156
+
157
+ Show Neo4j configuration status, node and relationship counts for the current project, local pm item count, the last sync timestamp, and the extension version.
158
+
159
+ ```bash
160
+ pm pm-graph status --json
161
+ ```
162
+
163
+ Example output (Neo4j connected):
164
+
165
+ ```json
166
+ {
167
+ "ok": true,
168
+ "neo4jConfigured": true,
169
+ "projectKey": "my-project",
170
+ "workspace": "/path/to/workspace",
171
+ "localItemCount": 15,
172
+ "nodeCount": 18,
173
+ "relationshipCount": 11,
174
+ "lastSyncedAt": "2026-05-14T10:00:00.000Z",
175
+ "syncVersion": "0.1.4",
176
+ "version": "0.1.4"
177
+ }
178
+ ```
179
+
180
+ Example output (Neo4j not configured):
181
+
182
+ ```json
183
+ {
184
+ "ok": true,
185
+ "neo4jConfigured": false,
186
+ "message": "Neo4j is not configured. Set NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD before using this command.",
187
+ "projectKey": "my-project",
188
+ "workspace": "/path/to/workspace",
189
+ "localItemCount": 15,
190
+ "version": "0.1.4"
191
+ }
192
+ ```
193
+
194
+ ### `pm pm-graph query`
195
+
196
+ Run a **read-only** Cypher query against Neo4j and return JSON results. Destructive Cypher keywords (`CREATE`, `MERGE`, `DELETE`, `DETACH`, `DROP`, `REMOVE`, `SET`) are blocked to prevent accidental data modification.
197
+
198
+ ```bash
199
+ pm pm-graph query "MATCH (n:PmGraphNode {projectKey: 'my-project'}) RETURN n.id, n.title LIMIT 10" --json
200
+ ```
201
+
202
+ Example output:
203
+
204
+ ```json
205
+ {
206
+ "ok": true,
207
+ "count": 2,
208
+ "records": [
209
+ { "n.id": "TASK-1", "n.title": "Build API" },
210
+ { "n.id": "TASK-2", "n.title": "Write tests" }
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ### `pm pm-graph neighbors`
216
+
217
+ Return all 1-hop neighbors with relationships for a given node ID. Each neighbor includes the relationship type, direction (`outgoing` or `incoming`), and properties.
218
+
219
+ ```bash
220
+ pm pm-graph neighbors TASK-42 --json
221
+ ```
222
+
223
+ Example output:
224
+
225
+ ```json
226
+ {
227
+ "ok": true,
228
+ "center": { "id": "TASK-42", "title": "Deploy service", "_labels": ["PmItem", "task"] },
229
+ "neighbors": [
230
+ {
231
+ "node": { "id": "TASK-10", "title": "Build service" },
232
+ "relationship": { "type": "BLOCKED_BY", "direction": "outgoing", "properties": {} }
233
+ }
234
+ ]
235
+ }
236
+ ```
237
+
238
+ ## Graph Model
239
+
240
+ - **`PmItem`** nodes for real pm items, labelled with item type (e.g. `task`, `bug`).
241
+ - **`ExternalPmItem`** nodes for dependency targets referenced but not present in the current workspace.
242
+ - **`PmFacet`** nodes for metadata: type, status, assignee, sprint, release, and tags.
243
+ - **`PmGraphSync`** metadata node storing the last sync timestamp and extension version per project.
244
+
245
+ Relationships: `CHILD_OF`, `BLOCKED_BY`, dependency relationship types from `pm deps`, `HAS_TYPE`, `HAS_STATUS`, `ASSIGNED_TO`, `IN_SPRINT`, `IN_RELEASE`, `TAGGED_WITH`.
246
+
247
+ All nodes in Neo4j carry the label `PmGraphNode` in addition to their semantic labels, making it easy to scope queries to a project:
248
+
249
+ ```cypher
250
+ MATCH (n:PmGraphNode {projectKey: 'my-project'}) RETURN n LIMIT 25
251
+ ```
252
+
253
+ ## Error Handling
254
+
255
+ - Missing environment variables produce clear messages listing exactly which variables are unset.
256
+ - Neo4j connection failures (unreachable host, wrong credentials) produce actionable error messages rather than raw driver errors.
257
+ - The `query` command blocks destructive Cypher keywords to protect data integrity.
258
+ - The Neo4j driver is created with `connectionAcquisitionTimeout: 10s` and `maxConnectionLifetime: 5min`.
259
+ - Driver sessions are always closed in `finally` blocks to prevent connection leaks.
260
+
261
+ ## Development
262
+
263
+ ```bash
264
+ cd /path/to/pm-graph
265
+ npm install
266
+ npm run build
267
+ pm install --project .
268
+ pm pm-graph ping
269
+ ```
270
+
271
+ ## Release Automation
272
+
273
+ This package is release-ready for GitHub, npm, and Bun-compatible installs. CI runs type checking, build, production dependency audit, package packing, Bun install verification, and pm-changelog validation. The daily release workflow publishes only when commits exist after the latest release tag and uses pm-changelog to generate CHANGELOG.md and GitHub release notes.
@@ -0,0 +1,19 @@
1
+ type CommandContext = {
2
+ command?: string;
3
+ args?: string[];
4
+ cwd?: string;
5
+ workspaceRoot?: string;
6
+ };
7
+ type RegisterCommand = {
8
+ name: string;
9
+ description: string;
10
+ run: (context: CommandContext) => Promise<unknown>;
11
+ };
12
+ type ExtensionApi = {
13
+ registerCommand(command: RegisterCommand): void;
14
+ };
15
+ export declare function activate(api: ExtensionApi): void;
16
+ declare const _default: {
17
+ activate: typeof activate;
18
+ };
19
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,799 @@
1
+ import { execFile, spawnSync } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const execFileAsync = promisify(execFile);
6
+ const EXTENSION_VERSION = "0.1.4";
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ const packageRoot = path.resolve(__dirname, "..");
9
+ let neo4jApi = null;
10
+ // ---------------------------------------------------------------------------
11
+ // Helpers
12
+ // ---------------------------------------------------------------------------
13
+ function getWorkspace(context) {
14
+ return context.workspaceRoot ?? context.cwd ?? process.cwd();
15
+ }
16
+ function projectKeyForWorkspace(workspace) {
17
+ if (process.env.PM_GRAPH_PROJECT_KEY)
18
+ return process.env.PM_GRAPH_PROJECT_KEY;
19
+ // Derive from the workspace directory name for a concise, stable key
20
+ return path.basename(workspace);
21
+ }
22
+ function neo4jConfigured() {
23
+ return Boolean(process.env.NEO4J_URI &&
24
+ (process.env.NEO4J_USER ?? process.env.NEO4J_USERNAME) &&
25
+ process.env.NEO4J_PASSWORD);
26
+ }
27
+ function neo4jMissingMessage() {
28
+ const missing = [];
29
+ if (!process.env.NEO4J_URI)
30
+ missing.push("NEO4J_URI");
31
+ if (!process.env.NEO4J_USER && !process.env.NEO4J_USERNAME)
32
+ missing.push("NEO4J_USER");
33
+ if (!process.env.NEO4J_PASSWORD)
34
+ missing.push("NEO4J_PASSWORD");
35
+ return `Neo4j is not configured. Set ${missing.join(", ")} before using this command.`;
36
+ }
37
+ async function loadNeo4j() {
38
+ if (neo4jApi)
39
+ return neo4jApi;
40
+ try {
41
+ const mod = await import("neo4j-driver");
42
+ neo4jApi = (mod.default ?? mod);
43
+ return neo4jApi;
44
+ }
45
+ catch (err) {
46
+ console.error("Installing pm-graph Neo4j runtime dependency...");
47
+ const install = spawnSync("npm", ["install", "--omit=dev"], {
48
+ cwd: packageRoot,
49
+ stdio: "inherit",
50
+ env: { ...process.env, NODE_ENV: "production" },
51
+ });
52
+ if (install.error)
53
+ throw install.error;
54
+ if (install.status !== 0) {
55
+ const msg = err instanceof Error ? err.message : String(err);
56
+ throw new Error(`Neo4j driver is not installed and npm install --omit=dev failed with exit code ${install.status ?? "unknown"}. (${msg})`);
57
+ }
58
+ const mod = await import("neo4j-driver");
59
+ neo4jApi = (mod.default ?? mod);
60
+ return neo4jApi;
61
+ }
62
+ }
63
+ /**
64
+ * Produce a user-friendly error message for Neo4j connection failures.
65
+ * The neo4j-driver throws errors with codes like ServiceUnavailable or
66
+ * AuthorizationExpired that are not helpful on their own.
67
+ */
68
+ function neo4jFriendlyError(err) {
69
+ if (!(err instanceof Error))
70
+ return new Error(String(err));
71
+ const msg = err.message ?? "";
72
+ const code = err.code ?? "";
73
+ if (code === "ServiceUnavailable" ||
74
+ msg.includes("Could not perform discovery") ||
75
+ msg.includes("ECONNREFUSED") ||
76
+ msg.includes("connect ETIMEDOUT") ||
77
+ msg.includes("Failed to connect")) {
78
+ const uri = process.env.NEO4J_URI ?? "bolt://localhost:7687";
79
+ return new Error(`Neo4j is not reachable at ${uri}. Check that Neo4j is running and NEO4J_URI is correct.`);
80
+ }
81
+ if (code === "Neo.ClientError.Security.Unauthorized" ||
82
+ msg.includes("authentication failure") ||
83
+ msg.includes("Unauthorized")) {
84
+ return new Error("Neo4j authentication failed. Check NEO4J_USER and NEO4J_PASSWORD.");
85
+ }
86
+ return err;
87
+ }
88
+ async function createDriver() {
89
+ const uri = process.env.NEO4J_URI;
90
+ const user = process.env.NEO4J_USER ?? process.env.NEO4J_USERNAME;
91
+ const password = process.env.NEO4J_PASSWORD;
92
+ if (!uri || !user || !password) {
93
+ throw new Error(neo4jMissingMessage());
94
+ }
95
+ const neo4j = await loadNeo4j();
96
+ return neo4j.driver(uri, neo4j.auth.basic(user, password), {
97
+ // Close idle connections after 5 minutes
98
+ maxConnectionLifetime: 5 * 60 * 1000,
99
+ // Give up acquiring a connection within 10 seconds
100
+ connectionAcquisitionTimeout: 10_000,
101
+ // Allow at most 10 concurrent connections per pool
102
+ maxConnectionPoolSize: 10,
103
+ });
104
+ }
105
+ /**
106
+ * Convert a Neo4j driver value (Integer, Node, Relationship, Path, …)
107
+ * into a plain JSON-safe value.
108
+ */
109
+ function toPlain(value) {
110
+ if (value === null || value === undefined)
111
+ return null;
112
+ if (typeof value !== "object")
113
+ return value;
114
+ // Neo4j Integer
115
+ if ("toNumber" in value && typeof value.toNumber === "function") {
116
+ return value.toNumber();
117
+ }
118
+ // Neo4j Node
119
+ if ("labels" in value &&
120
+ Array.isArray(value.labels) &&
121
+ "properties" in value &&
122
+ typeof value.properties === "object") {
123
+ const node = value;
124
+ return {
125
+ _labels: node.labels,
126
+ _elementId: node.elementId,
127
+ ...node.properties,
128
+ };
129
+ }
130
+ // Neo4j Relationship
131
+ if ("type" in value &&
132
+ "properties" in value &&
133
+ typeof value.properties === "object" &&
134
+ ("startNodeElementId" in value || "endNodeElementId" in value)) {
135
+ const relationship = value;
136
+ return {
137
+ _type: relationship.type,
138
+ _elementId: relationship.elementId,
139
+ _startNodeElementId: relationship.startNodeElementId,
140
+ _endNodeElementId: relationship.endNodeElementId,
141
+ ...relationship.properties,
142
+ };
143
+ }
144
+ // Neo4j Path
145
+ if ("segments" in value &&
146
+ Array.isArray(value.segments) &&
147
+ "start" in value &&
148
+ "end" in value) {
149
+ const pathValue = value;
150
+ return {
151
+ start: toPlain(pathValue.start),
152
+ end: toPlain(pathValue.end),
153
+ segments: pathValue.segments.map((s) => ({
154
+ start: toPlain(s.start),
155
+ relationship: toPlain(s.relationship),
156
+ end: toPlain(s.end),
157
+ })),
158
+ length: pathValue.length,
159
+ };
160
+ }
161
+ if (Array.isArray(value))
162
+ return value.map(toPlain);
163
+ if (typeof value === "object") {
164
+ const obj = {};
165
+ for (const [k, v] of Object.entries(value)) {
166
+ obj[k] = toPlain(v);
167
+ }
168
+ return obj;
169
+ }
170
+ return value;
171
+ }
172
+ function toNumber(value) {
173
+ if (typeof value === "number")
174
+ return value;
175
+ if (value && typeof value === "object" && "toNumber" in value && typeof value.toNumber === "function") {
176
+ return value.toNumber();
177
+ }
178
+ return 0;
179
+ }
180
+ // ---------------------------------------------------------------------------
181
+ // PM CLI interaction
182
+ // ---------------------------------------------------------------------------
183
+ async function runPmJson(context, args) {
184
+ const cliEntry = process.argv[1];
185
+ const command = cliEntry ? process.execPath : "pm";
186
+ const commandArgs = cliEntry ? [cliEntry, ...args, "--json"] : [...args, "--json"];
187
+ try {
188
+ const { stdout } = await execFileAsync(command, commandArgs, {
189
+ cwd: getWorkspace(context),
190
+ timeout: 30_000,
191
+ maxBuffer: 20 * 1024 * 1024,
192
+ });
193
+ return JSON.parse(stdout);
194
+ }
195
+ catch (err) {
196
+ const msg = err instanceof Error ? err.message : String(err);
197
+ throw new Error(`Failed to run pm ${args.join(" ")}: ${msg}`);
198
+ }
199
+ }
200
+ // ---------------------------------------------------------------------------
201
+ // Graph construction
202
+ // ---------------------------------------------------------------------------
203
+ function relationshipType(rawType) {
204
+ const text = typeof rawType === "string" && rawType.length > 0 ? rawType : "relates_to";
205
+ return text.toUpperCase().replace(/[^A-Z0-9]+/g, "_");
206
+ }
207
+ function relationshipTarget(dep) {
208
+ for (const key of ["id", "target", "target_id", "targetId", "item", "item_id", "itemId"]) {
209
+ const value = dep[key];
210
+ if (typeof value === "string" && value.length > 0)
211
+ return value;
212
+ }
213
+ return null;
214
+ }
215
+ function dependencyRows(raw) {
216
+ if (Array.isArray(raw)) {
217
+ return raw.filter((entry) => Boolean(entry) && typeof entry === "object");
218
+ }
219
+ if (!raw || typeof raw !== "object")
220
+ return [];
221
+ const data = raw;
222
+ for (const key of ["deps", "dependencies", "items", "relationships"]) {
223
+ const value = data[key];
224
+ if (Array.isArray(value)) {
225
+ return value.filter((entry) => Boolean(entry) && typeof entry === "object");
226
+ }
227
+ }
228
+ return [];
229
+ }
230
+ function facetNodeId(kind, value) {
231
+ return `${kind}:${value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-")}`;
232
+ }
233
+ function graphFromItems(items, workspace, depsByItem) {
234
+ const nodesById = new Map();
235
+ const relationships = [];
236
+ const addNode = (node) => {
237
+ if (!nodesById.has(node.id))
238
+ nodesById.set(node.id, node);
239
+ };
240
+ const addRelationship = (from, to, type, properties) => {
241
+ if (!nodesById.has(to) && !items.some((item) => item.id === to)) {
242
+ addNode({
243
+ id: to,
244
+ labels: ["ExternalPmItem"],
245
+ properties: { id: to, title: to, type: "ExternalPmItem" },
246
+ });
247
+ }
248
+ relationships.push({ from, to, type, properties });
249
+ };
250
+ for (const item of items) {
251
+ addNode({
252
+ id: item.id,
253
+ labels: ["PmItem", item.type ?? "Item"].filter(Boolean),
254
+ properties: {
255
+ id: item.id,
256
+ title: item.title ?? "",
257
+ type: item.type ?? "Item",
258
+ status: item.status ?? "unknown",
259
+ priority: item.priority ?? null,
260
+ tags: item.tags ?? [],
261
+ assignee: item.assignee ?? null,
262
+ sprint: item.sprint ?? null,
263
+ release: item.release ?? null,
264
+ deadline: item.deadline ?? null,
265
+ created_at: item.created_at ?? null,
266
+ updated_at: item.updated_at ?? null,
267
+ },
268
+ });
269
+ if (item.parent) {
270
+ addRelationship(item.id, item.parent, "CHILD_OF", { source: "parent" });
271
+ }
272
+ const blockedBy = item.blocked_by ?? item.blockedBy;
273
+ if (typeof blockedBy === "string" && blockedBy.trim().length > 0) {
274
+ addRelationship(item.id, blockedBy.trim(), "BLOCKED_BY", {
275
+ source: "blocked_by",
276
+ reason: item.blocked_reason ?? item.blockedReason ?? null,
277
+ });
278
+ }
279
+ const deps = [
280
+ ...(item.deps ?? []),
281
+ ...(item.dependencies ?? []),
282
+ ...(depsByItem.get(item.id) ?? []),
283
+ ];
284
+ const seenDeps = new Set();
285
+ for (const dep of deps) {
286
+ const target = relationshipTarget(dep);
287
+ if (!target)
288
+ continue;
289
+ const type = relationshipType(dep.type ?? dep.kind ?? dep.relation ?? dep.rel ?? dep.relationship);
290
+ const key = `${item.id}->${target}:${type}`;
291
+ if (seenDeps.has(key))
292
+ continue;
293
+ seenDeps.add(key);
294
+ addRelationship(item.id, target, type, { ...dep });
295
+ }
296
+ const facets = [
297
+ { kind: "type", value: item.type, label: "ItemType", rel: "HAS_TYPE" },
298
+ { kind: "status", value: item.status, label: "Status", rel: "HAS_STATUS" },
299
+ { kind: "assignee", value: item.assignee, label: "Person", rel: "ASSIGNED_TO" },
300
+ { kind: "sprint", value: item.sprint, label: "Sprint", rel: "IN_SPRINT" },
301
+ { kind: "release", value: item.release, label: "Release", rel: "IN_RELEASE" },
302
+ ];
303
+ for (const facet of facets) {
304
+ if (typeof facet.value !== "string" || facet.value.trim().length === 0)
305
+ continue;
306
+ const id = facetNodeId(facet.kind, facet.value);
307
+ addNode({
308
+ id,
309
+ labels: ["PmFacet", facet.label],
310
+ properties: { id, title: facet.value, kind: facet.kind, value: facet.value },
311
+ });
312
+ addRelationship(item.id, id, facet.rel, { source: facet.kind });
313
+ }
314
+ for (const tag of item.tags ?? []) {
315
+ if (!tag.trim())
316
+ continue;
317
+ const id = facetNodeId("tag", tag);
318
+ addNode({
319
+ id,
320
+ labels: ["PmFacet", "Tag"],
321
+ properties: { id, title: tag, kind: "tag", value: tag },
322
+ });
323
+ addRelationship(item.id, id, "TAGGED_WITH", { source: "tags" });
324
+ }
325
+ }
326
+ return {
327
+ generatedAt: new Date().toISOString(),
328
+ workspace,
329
+ projectKey: projectKeyForWorkspace(workspace),
330
+ nodes: Array.from(nodesById.values()),
331
+ relationships: relationships.filter((relationship, index, all) => all.findIndex((candidate) => candidate.from === relationship.from &&
332
+ candidate.to === relationship.to &&
333
+ candidate.type === relationship.type) === index),
334
+ };
335
+ }
336
+ async function loadGraph(context) {
337
+ const result = await runPmJson(context, ["list-all"]);
338
+ const items = result.items ?? [];
339
+ const depsByItem = new Map();
340
+ await Promise.all(items.map(async (item) => {
341
+ try {
342
+ const deps = await runPmJson(context, ["deps", item.id]);
343
+ depsByItem.set(item.id, dependencyRows(deps));
344
+ }
345
+ catch {
346
+ depsByItem.set(item.id, []);
347
+ }
348
+ }));
349
+ return graphFromItems(items, getWorkspace(context), depsByItem);
350
+ }
351
+ // ---------------------------------------------------------------------------
352
+ // Cypher generation (for export)
353
+ // ---------------------------------------------------------------------------
354
+ function cypherStatements(graph) {
355
+ const statements = [
356
+ {
357
+ statement: "MATCH (n:PmGraphNode {projectKey: $projectKey}) DETACH DELETE n",
358
+ parameters: { projectKey: graph.projectKey },
359
+ },
360
+ ];
361
+ statements.push(...graph.nodes.map((node) => ({
362
+ statement: "MERGE (n:PmGraphNode {projectKey: $projectKey, id: $id}) SET n += $properties, n.labels = $labels RETURN n.id",
363
+ parameters: {
364
+ projectKey: graph.projectKey,
365
+ id: node.id,
366
+ labels: node.labels,
367
+ properties: { ...node.properties, projectKey: graph.projectKey },
368
+ },
369
+ })));
370
+ for (const relationship of graph.relationships) {
371
+ statements.push({
372
+ statement: `MATCH (from:PmGraphNode {projectKey: $projectKey, id: $from}), (to:PmGraphNode {projectKey: $projectKey, id: $to}) MERGE (from)-[r:${relationship.type}]->(to) SET r += $properties RETURN type(r)`,
373
+ parameters: {
374
+ projectKey: graph.projectKey,
375
+ from: relationship.from,
376
+ to: relationship.to,
377
+ properties: relationship.properties,
378
+ },
379
+ });
380
+ }
381
+ return statements;
382
+ }
383
+ async function syncNeo4j(graph, options) {
384
+ const driver = await createDriver();
385
+ const session = driver.session({ database: process.env.NEO4J_DATABASE });
386
+ const projectKey = graph.projectKey;
387
+ const currentIds = new Set(graph.nodes.map((n) => n.id));
388
+ try {
389
+ if (options.fullSync) {
390
+ // Full resync: wipe all graph nodes for this project first
391
+ await session.executeWrite((tx) => tx.run("MATCH (n:PmGraphNode {projectKey: $projectKey}) DETACH DELETE n", { projectKey }));
392
+ }
393
+ // Upsert nodes with progress-friendly batching
394
+ for (let i = 0; i < graph.nodes.length; i++) {
395
+ const node = graph.nodes[i];
396
+ await session.executeWrite((tx) => tx.run("MERGE (n:PmGraphNode {projectKey: $projectKey, id: $id}) SET n += $properties, n.labels = $labels RETURN n.id", {
397
+ projectKey,
398
+ id: node.id,
399
+ labels: node.labels,
400
+ properties: { ...node.properties, projectKey },
401
+ }));
402
+ }
403
+ // Upsert relationships
404
+ for (const relationship of graph.relationships) {
405
+ await session.executeWrite((tx) => tx.run(`MATCH (from:PmGraphNode {projectKey: $projectKey, id: $from}), (to:PmGraphNode {projectKey: $projectKey, id: $to}) MERGE (from)-[r:${relationship.type}]->(to) SET r += $properties RETURN type(r)`, {
406
+ projectKey,
407
+ from: relationship.from,
408
+ to: relationship.to,
409
+ properties: relationship.properties,
410
+ }));
411
+ }
412
+ // Incremental mode: delete stale nodes that were not in this sync
413
+ let deletedStaleNodes = 0;
414
+ if (!options.fullSync && currentIds.size > 0) {
415
+ const deleteResult = await session.executeWrite((tx) => tx.run("MATCH (n:PmGraphNode {projectKey: $projectKey}) WHERE NOT n.id IN $currentIds DETACH DELETE n RETURN count(n) AS deleted", { projectKey, currentIds: [...currentIds] }));
416
+ deletedStaleNodes = toNumber(deleteResult.records[0]?.get("deleted"));
417
+ }
418
+ // Store last sync timestamp
419
+ await session.executeWrite((tx) => tx.run("MERGE (m:PmGraphSync {projectKey: $projectKey}) SET m.lastSyncedAt = $timestamp, m.syncVersion = $version", { projectKey, timestamp: new Date().toISOString(), version: EXTENSION_VERSION }));
420
+ return {
421
+ syncedNodes: graph.nodes.length,
422
+ syncedRelationships: graph.relationships.length,
423
+ deletedStaleNodes,
424
+ };
425
+ }
426
+ catch (err) {
427
+ throw neo4jFriendlyError(err);
428
+ }
429
+ finally {
430
+ await session.close();
431
+ await driver.close();
432
+ }
433
+ }
434
+ // ---------------------------------------------------------------------------
435
+ // Cypher query sanitisation
436
+ // ---------------------------------------------------------------------------
437
+ const DESTRUCTIVE_KEYWORDS = [
438
+ /\bCREATE\b/,
439
+ /\bMERGE\b/,
440
+ /\bDELETE\b/,
441
+ /\bDETACH\b/,
442
+ /\bDROP\b/,
443
+ /\bREMOVE\b/,
444
+ /\bSET\b(?!\s*\bSESSION\b)/,
445
+ ];
446
+ const DESTRUCTIVE_NAMES = [
447
+ "CREATE",
448
+ "MERGE",
449
+ "DELETE",
450
+ "DETACH",
451
+ "DROP",
452
+ "REMOVE",
453
+ "SET",
454
+ ];
455
+ function findDestructiveKeyword(query) {
456
+ const upper = query.toUpperCase();
457
+ for (let i = 0; i < DESTRUCTIVE_KEYWORDS.length; i++) {
458
+ if (DESTRUCTIVE_KEYWORDS[i].test(upper))
459
+ return DESTRUCTIVE_NAMES[i];
460
+ }
461
+ return null;
462
+ }
463
+ // ---------------------------------------------------------------------------
464
+ // Help text helpers
465
+ // ---------------------------------------------------------------------------
466
+ function hasHelpFlag(context) {
467
+ const args = context.args ?? [];
468
+ return args.includes("--help") || args.includes("-h");
469
+ }
470
+ // ---------------------------------------------------------------------------
471
+ // Command registrations
472
+ // ---------------------------------------------------------------------------
473
+ export function activate(api) {
474
+ // --- pm-graph ping -------------------------------------------------------
475
+ api.registerCommand({
476
+ name: "pm-graph ping",
477
+ description: "Verify that the pm-graph extension is active.",
478
+ run: async (context) => {
479
+ if (hasHelpFlag(context)) {
480
+ return {
481
+ usage: "pm pm-graph ping [--json]",
482
+ description: "Verify that the pm-graph extension is active. Returns extension version and whether Neo4j is configured.",
483
+ flags: {
484
+ "--json": "Output as JSON",
485
+ },
486
+ };
487
+ }
488
+ return {
489
+ ok: true,
490
+ source: "pm-graph",
491
+ command: context.command,
492
+ neo4jConfigured: neo4jConfigured(),
493
+ version: EXTENSION_VERSION,
494
+ };
495
+ },
496
+ });
497
+ // --- pm-graph export -----------------------------------------------------
498
+ api.registerCommand({
499
+ name: "pm-graph export",
500
+ description: "Export the current workspace as dependency and knowledge graph JSON.",
501
+ run: async (context) => {
502
+ if (hasHelpFlag(context)) {
503
+ return {
504
+ usage: "pm pm-graph export [--json]",
505
+ description: "Export the current workspace as a dependency and knowledge graph. Does not require Neo4j.",
506
+ flags: {
507
+ "--json": "Output as JSON",
508
+ },
509
+ output: {
510
+ graph: "Object containing nodes[], relationships[], projectKey, workspace, generatedAt",
511
+ },
512
+ };
513
+ }
514
+ try {
515
+ return {
516
+ ok: true,
517
+ graph: await loadGraph(context),
518
+ };
519
+ }
520
+ catch (err) {
521
+ const msg = err instanceof Error ? err.message : String(err);
522
+ throw new Error(`Export failed: ${msg}`);
523
+ }
524
+ },
525
+ });
526
+ // --- pm-graph cypher -----------------------------------------------------
527
+ api.registerCommand({
528
+ name: "pm-graph cypher",
529
+ description: "Render Cypher statements for importing the current workspace graph into Neo4j.",
530
+ run: async (context) => {
531
+ if (hasHelpFlag(context)) {
532
+ return {
533
+ usage: "pm pm-graph cypher [--json]",
534
+ description: "Render parameterized Cypher statements for importing the current workspace graph into Neo4j. Does not execute them.",
535
+ flags: {
536
+ "--json": "Output as JSON",
537
+ },
538
+ output: {
539
+ statements: "Array of { statement, parameters } objects ready to execute against Neo4j",
540
+ },
541
+ };
542
+ }
543
+ try {
544
+ const graph = await loadGraph(context);
545
+ return {
546
+ ok: true,
547
+ graph: {
548
+ nodes: graph.nodes.length,
549
+ relationships: graph.relationships.length,
550
+ },
551
+ statements: cypherStatements(graph),
552
+ };
553
+ }
554
+ catch (err) {
555
+ const msg = err instanceof Error ? err.message : String(err);
556
+ throw new Error(`Cypher generation failed: ${msg}`);
557
+ }
558
+ },
559
+ });
560
+ // --- pm-graph sync -------------------------------------------------------
561
+ api.registerCommand({
562
+ name: "pm-graph sync",
563
+ description: "Sync the current workspace graph into Neo4j. Add --full for a complete wipe-and-resync.",
564
+ run: async (context) => {
565
+ const args = context.args ?? [];
566
+ if (hasHelpFlag(context)) {
567
+ return {
568
+ usage: "pm pm-graph sync [--full] [--json]",
569
+ description: "Sync the current workspace graph into Neo4j. Requires NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD.",
570
+ flags: {
571
+ "--full": "Full wipe-and-resync: deletes all existing PmGraphNode entries for this project before re-importing",
572
+ "--json": "Output as JSON",
573
+ },
574
+ output: {
575
+ syncedNodes: "Number of nodes upserted",
576
+ syncedRelationships: "Number of relationships upserted",
577
+ deletedStaleNodes: "Number of stale nodes removed (incremental mode only)",
578
+ fullSync: "Whether --full was used",
579
+ },
580
+ };
581
+ }
582
+ const fullSync = args.includes("--full");
583
+ if (!neo4jConfigured()) {
584
+ throw new Error(neo4jMissingMessage());
585
+ }
586
+ let graph;
587
+ try {
588
+ graph = await loadGraph(context);
589
+ }
590
+ catch (err) {
591
+ const msg = err instanceof Error ? err.message : String(err);
592
+ throw new Error(`Failed to load workspace graph: ${msg}`);
593
+ }
594
+ const result = await syncNeo4j(graph, { fullSync });
595
+ return {
596
+ ok: true,
597
+ projectKey: graph.projectKey,
598
+ syncedNodes: result.syncedNodes,
599
+ syncedRelationships: result.syncedRelationships,
600
+ deletedStaleNodes: result.deletedStaleNodes,
601
+ fullSync,
602
+ };
603
+ },
604
+ });
605
+ // --- pm-graph status -----------------------------------------------------
606
+ api.registerCommand({
607
+ name: "pm-graph status",
608
+ description: "Show Neo4j configuration status, node/relationship counts, last sync timestamp, and extension version.",
609
+ run: async (context) => {
610
+ if (hasHelpFlag(context)) {
611
+ return {
612
+ usage: "pm pm-graph status [--json]",
613
+ description: "Show Neo4j configuration status, node/relationship counts for the current project, local pm item count, and extension version.",
614
+ flags: {
615
+ "--json": "Output as JSON",
616
+ },
617
+ output: {
618
+ neo4jConfigured: "Whether NEO4J_URI/NEO4J_USER/NEO4J_PASSWORD are all set",
619
+ projectKey: "Derived project key (from PM_GRAPH_PROJECT_KEY or directory name)",
620
+ workspace: "Current workspace path",
621
+ localItemCount: "Number of pm items found locally",
622
+ nodeCount: "Number of PmGraphNode entries in Neo4j (if connected)",
623
+ relationshipCount: "Number of relationships between PmGraphNode entries (if connected)",
624
+ lastSyncedAt: "Timestamp of the most recent sync (or null)",
625
+ version: "Extension version",
626
+ },
627
+ };
628
+ }
629
+ const workspace = getWorkspace(context);
630
+ const projectKey = projectKeyForWorkspace(workspace);
631
+ const configured = neo4jConfigured();
632
+ // Always fetch local item count regardless of Neo4j availability
633
+ let localItemCount = 0;
634
+ try {
635
+ const result = await runPmJson(context, ["list-all"]);
636
+ localItemCount = result.items?.length ?? 0;
637
+ }
638
+ catch {
639
+ // Non-fatal: workspace may not be initialised
640
+ }
641
+ if (!configured) {
642
+ return {
643
+ ok: true,
644
+ neo4jConfigured: false,
645
+ message: neo4jMissingMessage(),
646
+ projectKey,
647
+ workspace,
648
+ localItemCount,
649
+ version: EXTENSION_VERSION,
650
+ };
651
+ }
652
+ const driver = await createDriver();
653
+ const session = driver.session({ database: process.env.NEO4J_DATABASE });
654
+ try {
655
+ const nodeResult = await session.executeRead((tx) => tx.run("MATCH (n:PmGraphNode {projectKey: $projectKey}) RETURN count(n) AS count", { projectKey }));
656
+ const nodeCount = toNumber(nodeResult.records[0]?.get("count"));
657
+ const relResult = await session.executeRead((tx) => tx.run("MATCH (:PmGraphNode {projectKey: $projectKey})-[r]->(:PmGraphNode {projectKey: $projectKey}) RETURN count(r) AS count", { projectKey }));
658
+ const relCount = toNumber(relResult.records[0]?.get("count"));
659
+ const syncResult = await session.executeRead((tx) => tx.run("MATCH (m:PmGraphSync {projectKey: $projectKey}) RETURN m.lastSyncedAt AS lastSyncedAt, m.syncVersion AS syncVersion", { projectKey }));
660
+ const lastSyncedAt = syncResult.records[0]?.get("lastSyncedAt") ?? null;
661
+ const syncVersion = syncResult.records[0]?.get("syncVersion") ?? null;
662
+ return {
663
+ ok: true,
664
+ neo4jConfigured: true,
665
+ projectKey,
666
+ workspace,
667
+ localItemCount,
668
+ nodeCount,
669
+ relationshipCount: relCount,
670
+ lastSyncedAt,
671
+ syncVersion,
672
+ version: EXTENSION_VERSION,
673
+ };
674
+ }
675
+ catch (err) {
676
+ throw neo4jFriendlyError(err);
677
+ }
678
+ finally {
679
+ await session.close();
680
+ await driver.close();
681
+ }
682
+ },
683
+ });
684
+ // --- pm-graph query ------------------------------------------------------
685
+ api.registerCommand({
686
+ name: "pm-graph query",
687
+ description: "Run a read-only Cypher query against Neo4j and return JSON results. Destructive keywords are blocked.",
688
+ run: async (context) => {
689
+ if (hasHelpFlag(context)) {
690
+ return {
691
+ usage: 'pm pm-graph query "<cypher-query>" [--json]',
692
+ description: "Run a read-only Cypher query against Neo4j. Destructive keywords (CREATE, MERGE, DELETE, DETACH, DROP, REMOVE, SET) are blocked.",
693
+ flags: {
694
+ "--json": "Output as JSON",
695
+ },
696
+ example: "pm pm-graph query \"MATCH (n:PmGraphNode {projectKey: 'my-project'}) RETURN n.id, n.title LIMIT 10\" --json",
697
+ output: {
698
+ count: "Number of records returned",
699
+ records: "Array of result objects with all Neo4j types converted to plain JSON",
700
+ },
701
+ };
702
+ }
703
+ const query = (context.args ?? []).join(" ").trim();
704
+ if (!query) {
705
+ throw new Error('Usage: pm pm-graph query "<cypher-query>"\nExample: pm pm-graph query "MATCH (n:PmGraphNode) RETURN n.id LIMIT 5"');
706
+ }
707
+ const destructive = findDestructiveKeyword(query);
708
+ if (destructive) {
709
+ throw new Error(`Blocked destructive Cypher keyword "${destructive}". Only read-only queries (MATCH / RETURN / WITH / ORDER BY / LIMIT / SKIP / WHERE) are allowed.`);
710
+ }
711
+ if (!neo4jConfigured()) {
712
+ throw new Error(neo4jMissingMessage());
713
+ }
714
+ const driver = await createDriver();
715
+ const session = driver.session({ database: process.env.NEO4J_DATABASE });
716
+ try {
717
+ const result = await session.executeRead((tx) => tx.run(query));
718
+ const records = result.records.map((record) => {
719
+ const obj = {};
720
+ for (const key of record.keys) {
721
+ obj[key] = toPlain(record.get(key));
722
+ }
723
+ return obj;
724
+ });
725
+ return { ok: true, count: records.length, records };
726
+ }
727
+ catch (err) {
728
+ throw neo4jFriendlyError(err);
729
+ }
730
+ finally {
731
+ await session.close();
732
+ await driver.close();
733
+ }
734
+ },
735
+ });
736
+ // --- pm-graph neighbors --------------------------------------------------
737
+ api.registerCommand({
738
+ name: "pm-graph neighbors",
739
+ description: "Return all 1-hop neighbors with relationships for a given node ID.",
740
+ run: async (context) => {
741
+ if (hasHelpFlag(context)) {
742
+ return {
743
+ usage: "pm pm-graph neighbors <node-id> [--json]",
744
+ description: "Return all 1-hop neighbors and their relationships for a given node ID in Neo4j.",
745
+ flags: {
746
+ "--json": "Output as JSON",
747
+ },
748
+ example: "pm pm-graph neighbors TASK-42 --json",
749
+ output: {
750
+ center: "The queried node (or null if not found)",
751
+ neighbors: "Array of { node, relationship: { type, direction, properties } }",
752
+ },
753
+ };
754
+ }
755
+ const nodeId = (context.args ?? [])[0];
756
+ if (!nodeId) {
757
+ throw new Error("Usage: pm pm-graph neighbors <node-id>\nExample: pm pm-graph neighbors TASK-42");
758
+ }
759
+ if (!neo4jConfigured()) {
760
+ throw new Error(neo4jMissingMessage());
761
+ }
762
+ const projectKey = projectKeyForWorkspace(getWorkspace(context));
763
+ const driver = await createDriver();
764
+ const session = driver.session({ database: process.env.NEO4J_DATABASE });
765
+ try {
766
+ const result = await session.executeRead((tx) => tx.run(`MATCH (center:PmGraphNode {projectKey: $projectKey, id: $nodeId})-[r]-(neighbor:PmGraphNode {projectKey: $projectKey})
767
+ RETURN center, r, neighbor, type(r) AS relType,
768
+ CASE WHEN startNode(r) = center THEN 'outgoing' ELSE 'incoming' END AS direction`, { projectKey, nodeId }));
769
+ if (result.records.length === 0) {
770
+ return {
771
+ ok: true,
772
+ center: null,
773
+ neighbors: [],
774
+ message: `No node found with id "${nodeId}" for project "${projectKey}".`,
775
+ };
776
+ }
777
+ const center = toPlain(result.records[0].get("center"));
778
+ const neighbors = result.records.map((record) => ({
779
+ node: toPlain(record.get("neighbor")),
780
+ relationship: {
781
+ type: record.get("relType"),
782
+ direction: record.get("direction"),
783
+ properties: toPlain(record.get("r")),
784
+ },
785
+ }));
786
+ return { ok: true, center, neighbors };
787
+ }
788
+ catch (err) {
789
+ throw neo4jFriendlyError(err);
790
+ }
791
+ finally {
792
+ await session.close();
793
+ await driver.close();
794
+ }
795
+ },
796
+ });
797
+ }
798
+ export default { activate };
799
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/manifest.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "pm-graph",
3
+ "version": "0.1.4",
4
+ "description": "Knowledge graph and dependency graph extension for pm CLI workspaces, with optional Neo4j sync.",
5
+ "entry": "./dist/index.js",
6
+ "capabilities": [
7
+ "commands"
8
+ ],
9
+ "pm": {
10
+ "compatibility": "v2"
11
+ },
12
+ "author": "@unbraind",
13
+ "priority": 50
14
+ }
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "pm-graph",
3
+ "version": "0.1.4",
4
+ "description": "Knowledge graph and dependency graph extension for pm CLI workspaces, with optional Neo4j sync.",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "tsc",
8
+ "typecheck": "tsc --noEmit",
9
+ "prepare": "npm run build",
10
+ "check": "npm run typecheck",
11
+ "audit:prod": "npm audit --omit=dev",
12
+ "pack:dry-run": "npm pack --dry-run",
13
+ "changelog": "pm-changelog --pm-root .agents/pm --mode prepend --output CHANGELOG.md --release-version-from-package --since-previous-tag --until-release-tag --item-url-base https://github.com/unbraind/pm-graph/blob/main/.agents/pm",
14
+ "changelog:full": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-graph/blob/main/.agents/pm",
15
+ "changelog:check": "pm-changelog --pm-root .agents/pm --mode replace --output CHANGELOG.md --all-release-tags --release-version-from-package --item-url-base https://github.com/unbraind/pm-graph/blob/main/.agents/pm --check",
16
+ "release:check": "npm run typecheck && npm run build && npm run audit:prod && npm run pack:dry-run && npm run changelog:check",
17
+ "prepack": "npm run build"
18
+ },
19
+ "dependencies": {
20
+ "neo4j-driver": "^5.28.1"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.9.1",
24
+ "typescript": "^6.0.3",
25
+ "@unbrained/pm-cli": "^2026.5.24",
26
+ "pm-changelog": "^2026.5.25"
27
+ },
28
+ "files": [
29
+ "dist/",
30
+ "manifest.json",
31
+ "README.md",
32
+ "CHANGELOG.md"
33
+ ],
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/unbraind/pm-graph.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/unbraind/pm-graph/issues"
40
+ },
41
+ "homepage": "https://github.com/unbraind/pm-graph#readme",
42
+ "main": "dist/index.js",
43
+ "types": "dist/index.d.ts",
44
+ "peerDependencies": {
45
+ "@unbrained/pm-cli": ">=2026.5.24"
46
+ },
47
+ "engines": {
48
+ "node": ">=20.0.0"
49
+ },
50
+ "author": "@unbraind",
51
+ "license": "MIT",
52
+ "keywords": [
53
+ "graph",
54
+ "pm-cli",
55
+ "pm-extension",
56
+ "pm-package"
57
+ ],
58
+ "pm": {
59
+ "aliases": [
60
+ "graph"
61
+ ],
62
+ "extensions": [
63
+ "."
64
+ ],
65
+ "catalog": {
66
+ "display_name": "Knowledge Graph",
67
+ "category": "visualization",
68
+ "summary": "Knowledge graph and dependency graph extension for pm CLI workspaces, with optional Neo4j sync.",
69
+ "tags": [
70
+ "graph",
71
+ "neo4j",
72
+ "dependencies",
73
+ "knowledge"
74
+ ],
75
+ "links": {
76
+ "docs": "https://github.com/unbraind/pm-graph#readme",
77
+ "npm": "https://www.npmjs.com/package/pm-graph",
78
+ "repository": "https://github.com/unbraind/pm-graph",
79
+ "report": "https://github.com/unbraind/pm-graph/issues"
80
+ }
81
+ },
82
+ "docs": [
83
+ "README.md",
84
+ "CHANGELOG.md"
85
+ ],
86
+ "examples": [
87
+ "README.md"
88
+ ]
89
+ }
90
+ }