pm-github 2026.7.10 → 2026.7.13

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.
@@ -0,0 +1,445 @@
1
+ // pm-github — GitHub Projects v2 support (pure logic layer).
2
+ //
3
+ // GitHub Projects v2 is a GraphQL-only API, structurally different from the REST
4
+ // Issues API the rest of pm-github speaks. This module holds the *pure*,
5
+ // side-effect-free half of the integration — reference parsing, provenance-tag
6
+ // helpers, status mapping, and plan builders — so it can be unit-tested without
7
+ // any network I/O. The GraphQL client and command handlers live in index.ts
8
+ // where the shared request/backoff infrastructure already exists.
9
+ //
10
+ // Design invariant — NO DATA LOSS:
11
+ // * plans NEVER delete or archive project items, and NEVER delete pm items;
12
+ // * an unmapped status is SKIPPED (with a reason) rather than guessed, so we
13
+ // never overwrite a real state with a wrong one in either direction;
14
+ // * every action is idempotent via the `gh-project:owner/number#itemId` tag.
15
+ // ---------------------------------------------------------------------------
16
+ // Reference parsing
17
+ // ---------------------------------------------------------------------------
18
+ // Accept the human shorthand `owner/number` (and the tolerant `owner#number`),
19
+ // or a full Projects v2 URL:
20
+ // https://github.com/orgs/<owner>/projects/<n>
21
+ // https://github.com/users/<owner>/projects/<n>
22
+ // Returns undefined for anything unparseable so callers can fail fast.
23
+ export function parseProjectRef(input) {
24
+ if (!input)
25
+ return undefined;
26
+ const raw = input.trim();
27
+ if (!raw)
28
+ return undefined;
29
+ const urlMatch = /^https?:\/\/github\.com\/(?:orgs|users)\/([^/\s]+)\/projects\/(\d+)/i.exec(raw);
30
+ if (urlMatch) {
31
+ return { owner: urlMatch[1], number: Number(urlMatch[2]) };
32
+ }
33
+ const shortMatch = /^([^/#\s]+)[/#](\d+)$/.exec(raw);
34
+ if (shortMatch) {
35
+ const number = Number(shortMatch[2]);
36
+ if (Number.isInteger(number) && number > 0) {
37
+ return { owner: shortMatch[1], number };
38
+ }
39
+ }
40
+ return undefined;
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Provenance tags (idempotency keys)
44
+ // ---------------------------------------------------------------------------
45
+ // A ProjectV2Item node id (e.g. `PVTI_lAHOABGZtc4BdHj8zGYf8pU`) is CASE
46
+ // SENSITIVE, but pm normalizes tag values to lowercase — storing the raw id in a
47
+ // tag corrupts it, breaking idempotency (a re-sync would duplicate the item) and
48
+ // pull (a linked item would look unlinked). To survive that round-trip losslessly
49
+ // we hex-encode the id inside the tag; hex is `[0-9a-f]` so lowercasing is a
50
+ // no-op. This is the difference between "no data loss" and silent double-adds.
51
+ export function encodeItemId(id) {
52
+ return Buffer.from(id, "utf8").toString("hex");
53
+ }
54
+ // Decode a hex-encoded project item id back to its original GraphQL id;
55
+ // returns undefined for malformed (empty, odd-length, non-hex) input.
56
+ export function decodeItemId(encoded) {
57
+ if (encoded.length === 0 || encoded.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(encoded)) {
58
+ return undefined;
59
+ }
60
+ try {
61
+ return Buffer.from(encoded, "hex").toString("utf8");
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ }
67
+ // The project link rides on a machine-parseable tag, like the issue provenance
68
+ // tag (`gh:owner/repo#N`). The node id is hex-encoded (see above) so it survives
69
+ // pm's lowercasing; a re-import/re-sync then finds the existing pm item and the
70
+ // existing project item instead of duplicating either side.
71
+ export function projectItemTag(ref, itemId) {
72
+ return `gh-project:${ref.owner.toLowerCase()}/${ref.number}#${encodeItemId(itemId)}`;
73
+ }
74
+ // Parse a `gh-project:owner/number#hexItemId` provenance tag into its parts,
75
+ // rejecting non-string tags and malformed encodings. Returns undefined when the
76
+ // tag is not a project-item provenance tag.
77
+ export function parseProjectItemTag(tag) {
78
+ if (typeof tag !== "string")
79
+ return undefined;
80
+ const m = /^gh-project:([^/\s]+)\/(\d+)#([0-9a-f]+)$/i.exec(tag.trim());
81
+ if (!m)
82
+ return undefined;
83
+ const itemId = decodeItemId(m[3]);
84
+ if (!itemId)
85
+ return undefined;
86
+ return { owner: m[1].toLowerCase(), number: Number(m[2]), itemId };
87
+ }
88
+ // Reuse of the issue provenance format so a project item that wraps a real
89
+ // GitHub issue can also carry a `gh:owner/repo#N` tag (dual linkage).
90
+ export function issueProvenanceTag(repo, number) {
91
+ return `gh:${repo.toLowerCase()}#${number}`;
92
+ }
93
+ // ---------------------------------------------------------------------------
94
+ // Status mapping (pm status <-> Project "Status" single-select option)
95
+ // ---------------------------------------------------------------------------
96
+ // Canonical pm statuses we know how to place on a board, mapped to an ordered
97
+ // list of candidate Status-option names (matched case-insensitively against the
98
+ // project's ACTUAL options). First match wins; if none match we skip the write.
99
+ export const DEFAULT_STATUS_CANDIDATES = {
100
+ draft: ["Draft", "Backlog", "Todo", "To Do"],
101
+ open: ["Todo", "To Do", "Backlog", "New", "Open", "Triage", "Ready"],
102
+ in_progress: ["In Progress", "In-Progress", "Doing", "Started", "Active"],
103
+ blocked: ["Blocked", "On Hold", "Waiting"],
104
+ closed: ["Done", "Closed", "Complete", "Completed", "Shipped", "Resolved"],
105
+ canceled: ["Cancelled", "Canceled", "Won't Do", "Wont Do", "Not Planned", "Dropped"],
106
+ };
107
+ // Parse a `--status-map` option into a forward table (pm status → exact Status
108
+ // option name). Accepts `pm=OptionName` pairs, comma-separated or repeated.
109
+ // Entries without a `=` or an empty side are skipped. Returns undefined when no
110
+ // usable mapping was supplied so callers keep the default behavior.
111
+ export function parseStatusMap(raw) {
112
+ if (!raw || raw.length === 0)
113
+ return undefined;
114
+ const map = new Map();
115
+ for (const entry of raw) {
116
+ const eq = entry.indexOf("=");
117
+ if (eq <= 0)
118
+ continue;
119
+ const from = entry.slice(0, eq).trim().toLowerCase();
120
+ const to = entry.slice(eq + 1).trim();
121
+ if (!from || !to)
122
+ continue;
123
+ map.set(from, to);
124
+ }
125
+ return map.size > 0 ? map : undefined;
126
+ }
127
+ const normalizeName = (s) => s.trim().toLowerCase();
128
+ // Resolve the Status option a given pm status should be set to, against the
129
+ // project's real options. An explicit override (`--status-map`) wins; otherwise
130
+ // the default candidate list is tried in order. Returns undefined when nothing
131
+ // matches — the caller must SKIP rather than guess (no data loss).
132
+ export function resolveOptionForStatus(pmStatus, options, override) {
133
+ const status = (pmStatus || "open").toLowerCase();
134
+ const byName = new Map();
135
+ for (const o of options) {
136
+ if (o && typeof o.name === "string")
137
+ byName.set(normalizeName(o.name), o);
138
+ }
139
+ const overrideName = override?.get(status);
140
+ if (overrideName) {
141
+ const hit = byName.get(normalizeName(overrideName));
142
+ if (hit)
143
+ return hit;
144
+ // An explicit override that does not exist on the board is a hard miss:
145
+ // we do NOT silently fall through to a default guess.
146
+ return undefined;
147
+ }
148
+ const candidates = DEFAULT_STATUS_CANDIDATES[status] ?? DEFAULT_STATUS_CANDIDATES.open;
149
+ for (const cand of candidates) {
150
+ const hit = byName.get(normalizeName(cand));
151
+ if (hit)
152
+ return hit;
153
+ }
154
+ return undefined;
155
+ }
156
+ // Reverse map: a Project Status option name → a pm status. Used by pull. An
157
+ // explicit forward `--status-map` is inverted first (option name → pm status);
158
+ // otherwise a keyword heuristic is applied. Returns undefined for names we do
159
+ // not recognize so pull SKIPS them instead of forcing a wrong pm status.
160
+ export function mapOptionNameToPmStatus(optionName, override) {
161
+ if (!optionName)
162
+ return undefined;
163
+ const name = normalizeName(optionName);
164
+ if (override) {
165
+ for (const [pmStatus, optName] of override) {
166
+ if (normalizeName(optName) === name)
167
+ return pmStatus;
168
+ }
169
+ }
170
+ // Order matters: check the more specific buckets (cancel/blocked/draft) before
171
+ // the generic done/open ones so "Won't do" is canceled and "Draft" is draft,
172
+ // not open. Keeping "draft" ahead of the open/todo bucket makes the push↔pull
173
+ // roundtrip symmetric (a pm "draft" pushes to a "Draft" option and pulls back
174
+ // to "draft", not "open").
175
+ if (/(cancel|won'?t|not\s*planned|drop|abandon)/.test(name))
176
+ return "canceled";
177
+ if (/(block|on\s*hold|waiting)/.test(name))
178
+ return "blocked";
179
+ if (/draft/.test(name))
180
+ return "draft";
181
+ if (/\bnot\s+started\b|\bunstarted\b/.test(name))
182
+ return "open";
183
+ if (/(progress|doing|started|active|review)/.test(name))
184
+ return "in_progress";
185
+ if (/(done|closed|complete|shipped|resolved|merged)/.test(name))
186
+ return "closed";
187
+ if (/(todo|to\s*do|backlog|new|open|triage|ready)/.test(name))
188
+ return "open";
189
+ return undefined;
190
+ }
191
+ // ---------------------------------------------------------------------------
192
+ // Indexing helpers
193
+ // ---------------------------------------------------------------------------
194
+ // Index pm items by the project-item id they are linked to (for THIS project).
195
+ export function indexPmByProjectItem(items, ref) {
196
+ const index = new Map();
197
+ const ownerLc = ref.owner.toLowerCase();
198
+ for (const item of items) {
199
+ if (!item?.id)
200
+ continue;
201
+ for (const tag of item.tags ?? []) {
202
+ const p = parseProjectItemTag(tag);
203
+ if (p && p.owner === ownerLc && p.number === ref.number) {
204
+ index.set(p.itemId, item);
205
+ }
206
+ }
207
+ }
208
+ return index;
209
+ }
210
+ // Index pm items by `owner/repo#number` issue provenance so a push can link an
211
+ // already-imported pm item to the existing issue's project item (rather than
212
+ // adding a duplicate draft).
213
+ export function indexPmByIssue(items) {
214
+ const index = new Map();
215
+ for (const item of items) {
216
+ if (!item?.id)
217
+ continue;
218
+ for (const tag of item.tags ?? []) {
219
+ const m = /^gh:([^#\s]+)#(\d+)$/.exec(tag.trim());
220
+ if (m)
221
+ index.set(`${m[1].toLowerCase()}#${Number(m[2])}`, item);
222
+ }
223
+ }
224
+ return index;
225
+ }
226
+ // Index project items by the issue they wrap (`owner/repo#number`) so a push
227
+ // can find the project item for a pm item that is issue-linked but not yet
228
+ // project-tagged.
229
+ export function indexProjectItemsByIssue(projectItems) {
230
+ const index = new Map();
231
+ for (const pi of projectItems) {
232
+ if (!pi?.id || !pi.content)
233
+ continue;
234
+ const c = pi.content;
235
+ if (c.repo && typeof c.number === "number") {
236
+ index.set(`${c.repo.toLowerCase()}#${c.number}`, pi);
237
+ }
238
+ }
239
+ return index;
240
+ }
241
+ // Build the pm → project plan. Pure and side-effect free so it is unit-testable
242
+ // and printable verbatim in --dry-run.
243
+ export function buildProjectPushPlan(pmItems, ref, projectItems, statusField, opts = {}) {
244
+ const addMissing = opts.addMissing !== false;
245
+ const options = statusField?.options ?? [];
246
+ const byProjectItem = indexProjectItemMap(projectItems);
247
+ const byIssue = indexProjectItemsByIssue(projectItems);
248
+ const entries = [];
249
+ const statusSkipped = [];
250
+ for (const item of pmItems) {
251
+ if (!item?.id)
252
+ continue;
253
+ const title = item.title ?? "(untitled)";
254
+ const status = item.status ?? "open";
255
+ // Find the existing project item this pm item maps to: first by project
256
+ // provenance tag, then by the issue it wraps (if issue-linked).
257
+ let linked;
258
+ let linkedByProjectTag = false;
259
+ for (const tag of item.tags ?? []) {
260
+ const p = parseProjectItemTag(tag);
261
+ if (p && p.owner === ref.owner.toLowerCase() && p.number === ref.number) {
262
+ linked = byProjectItem.get(p.itemId);
263
+ linkedByProjectTag = true;
264
+ break;
265
+ }
266
+ }
267
+ let issueKey;
268
+ if (!linked) {
269
+ for (const tag of item.tags ?? []) {
270
+ const m = /^gh:([^#\s]+)#(\d+)$/.exec(tag.trim());
271
+ if (m) {
272
+ issueKey = { repo: m[1].toLowerCase(), number: Number(m[2]) };
273
+ linked = byIssue.get(`${issueKey.repo}#${issueKey.number}`);
274
+ break;
275
+ }
276
+ }
277
+ }
278
+ // Resolve the target Status option for this pm status.
279
+ const targetOption = statusField
280
+ ? resolveOptionForStatus(status, options, opts.statusMap)
281
+ : undefined;
282
+ if (statusField && !targetOption) {
283
+ statusSkipped.push({ pmId: item.id, title, status });
284
+ }
285
+ if (linked) {
286
+ // Already on the board: only (maybe) reconcile its Status.
287
+ if (!targetOption) {
288
+ entries.push({
289
+ action: "noop",
290
+ pmId: item.id,
291
+ title,
292
+ itemId: linked.id,
293
+ currentOptionName: linked.statusName,
294
+ reason: statusField ? `pm status "${status}" has no matching board option` : "project has no Status field",
295
+ });
296
+ continue;
297
+ }
298
+ if (linked.statusOptionId === targetOption.id) {
299
+ entries.push({
300
+ action: "noop",
301
+ pmId: item.id,
302
+ title,
303
+ itemId: linked.id,
304
+ currentOptionName: linked.statusName,
305
+ targetOptionName: targetOption.name,
306
+ reason: "already in sync",
307
+ });
308
+ continue;
309
+ }
310
+ entries.push({
311
+ action: "set-status",
312
+ pmId: item.id,
313
+ title,
314
+ itemId: linked.id,
315
+ currentOptionName: linked.statusName,
316
+ targetOptionId: targetOption.id,
317
+ targetOptionName: targetOption.name,
318
+ });
319
+ continue;
320
+ }
321
+ // Not on the board yet.
322
+ if (!addMissing) {
323
+ entries.push({
324
+ action: "noop",
325
+ pmId: item.id,
326
+ title,
327
+ reason: "not on board (--no-add-missing)",
328
+ });
329
+ continue;
330
+ }
331
+ if (issueKey) {
332
+ // Attach the existing issue rather than creating a duplicate draft.
333
+ entries.push({
334
+ action: "add-issue",
335
+ pmId: item.id,
336
+ title,
337
+ issueRepo: issueKey.repo,
338
+ issueNumber: issueKey.number,
339
+ targetOptionId: targetOption?.id,
340
+ targetOptionName: targetOption?.name,
341
+ });
342
+ }
343
+ else {
344
+ entries.push({
345
+ action: "add-draft",
346
+ pmId: item.id,
347
+ title,
348
+ targetOptionId: targetOption?.id,
349
+ targetOptionName: targetOption?.name,
350
+ });
351
+ }
352
+ }
353
+ return { entries, statusSkipped };
354
+ }
355
+ // Index project items by their own id for O(1) lookup during sync planning.
356
+ function indexProjectItemMap(projectItems) {
357
+ const m = new Map();
358
+ for (const pi of projectItems)
359
+ m.set(pi.id, pi);
360
+ return m;
361
+ }
362
+ // Build the project → pm plan: for each project item linked to a pm item, if the
363
+ // board's Status maps to a pm status that differs from the pm item's current
364
+ // status, propose an update. Only status changes; never touches title/body/tags.
365
+ export function buildProjectPullPlan(pmItems, ref, projectItems, statusMap) {
366
+ const pmByItemId = indexPmByProjectItem(pmItems, ref);
367
+ const pmByIssue = indexPmByIssue(pmItems);
368
+ const entries = [];
369
+ const statusSkipped = [];
370
+ for (const pi of projectItems) {
371
+ let pm = pmByItemId.get(pi.id);
372
+ if (!pm && pi.content.repo && typeof pi.content.number === "number") {
373
+ pm = pmByIssue.get(`${pi.content.repo.toLowerCase()}#${pi.content.number}`);
374
+ }
375
+ if (!pm || !pm.id)
376
+ continue; // unlinked project items are handled by import
377
+ const toStatus = mapOptionNameToPmStatus(pi.statusName, statusMap);
378
+ if (!toStatus) {
379
+ if (pi.statusName)
380
+ statusSkipped.push({ itemId: pi.id, optionName: pi.statusName });
381
+ continue;
382
+ }
383
+ const fromStatus = pm.status ?? "open";
384
+ if (fromStatus === toStatus)
385
+ continue;
386
+ entries.push({ itemId: pi.id, pmId: pm.id, title: pm.title ?? "(untitled)", fromStatus, toStatus });
387
+ }
388
+ return { entries, statusSkipped };
389
+ }
390
+ // Build the plan to import project items as pm items. Idempotent: a project item
391
+ // already linked (by project tag, or by the issue it wraps) UPDATEs the existing
392
+ // pm item; everything else CREATEs. Draft issues import as pm items too.
393
+ export function buildProjectImportPlan(projectItems, ref, pmItems, statusMap) {
394
+ const pmByItemId = indexPmByProjectItem(pmItems, ref);
395
+ const pmByIssue = indexPmByIssue(pmItems);
396
+ const plan = [];
397
+ for (const pi of projectItems) {
398
+ const c = pi.content;
399
+ if (c.typename === "Unknown")
400
+ continue; // redacted / inaccessible content
401
+ const title = (c.title || "").trim() || `(project item ${pi.id})`;
402
+ // Prefer the board's Status; fall back to the wrapped issue's own state.
403
+ // `mappedStatus` records only an EXPLICIT mapping (undefined when the board
404
+ // status is unknown) so the re-import update path can skip the status write
405
+ // instead of clobbering an existing pm state (no data loss).
406
+ const mappedStatus = mapOptionNameToPmStatus(pi.statusName, statusMap);
407
+ let status = mappedStatus;
408
+ if (!status) {
409
+ if (c.state === "closed" || c.state === "merged") {
410
+ status = c.stateReason === "not_planned" ? "canceled" : "closed";
411
+ }
412
+ else {
413
+ status = "open";
414
+ }
415
+ }
416
+ let existing = pmByItemId.get(pi.id);
417
+ if (!existing && c.repo && typeof c.number === "number") {
418
+ existing = pmByIssue.get(`${c.repo.toLowerCase()}#${c.number}`);
419
+ }
420
+ // Provenance tags this import adds, MERGED with any tags the existing pm item
421
+ // already carries (labels from a prior `pm github import`, user-added tags).
422
+ // `pm update --tags` REPLACES the tag set, so passing only the provenance
423
+ // tags would silently wipe everything else — a data-loss bug. Union, dedup,
424
+ // existing-first (preserves order); the Set collapses re-adds of a tag we
425
+ // already own.
426
+ const provenance = [projectItemTag(ref, pi.id)];
427
+ if (c.repo && typeof c.number === "number") {
428
+ provenance.push(issueProvenanceTag(c.repo, c.number));
429
+ }
430
+ const tags = [...new Set([...(existing?.tags ?? []), ...provenance])];
431
+ plan.push({
432
+ action: existing?.id ? "update" : "create",
433
+ itemId: pi.id,
434
+ title,
435
+ status,
436
+ mappedStatus,
437
+ body: c.body,
438
+ tags,
439
+ pmId: existing?.id,
440
+ content: c,
441
+ });
442
+ }
443
+ return plan;
444
+ }
445
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../projects.ts"],"names":[],"mappings":"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"}
package/manifest.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "pm-github",
3
- "version": "2026.7.10",
4
- "description": "GitHub Issues importer/exporter. Imports issues from a GitHub repo as pm items (native `pm github import`), exports pm items as a GitHub-issues payload, and declares GitHub provenance fields.",
3
+ "version": "2026.7.13",
4
+ "description": "GitHub Issues + Projects v2 integration. Imports issues as pm items (`pm github import`), exports pm items as GitHub issues, syncs issue state, and bidirectionally syncs pm items with a GitHub Projects v2 board (`pm github project import/sync/list/fields`) — mapping pm status to the board Status column with idempotent, no-data-loss provenance.",
5
5
  "author": "@unbraind",
6
6
  "entry": "./dist/index.js",
7
7
  "priority": 50,
8
+ "pm_min_version": "2026.7.10",
8
9
  "capabilities": [
9
10
  "commands",
10
11
  "importers",
11
- "exporters",
12
12
  "schema",
13
13
  "hooks",
14
14
  "preflight",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pm-github",
3
- "version": "2026.7.10",
3
+ "version": "2026.7.13",
4
4
  "description": "GitHub Issues importer extension for pm-cli",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,23 +26,23 @@
26
26
  "prepack": "npm run build",
27
27
  "typecheck": "tsc --noEmit",
28
28
  "check": "npm run typecheck",
29
- "audit:prod": "npm audit --omit=dev",
29
+ "audit:prod": "env -u npm_config_allow_scripts npm audit --omit=dev --ignore-scripts",
30
30
  "pack:dry-run": "npm pack --dry-run",
31
31
  "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-github/blob/main/.agents/pm",
32
32
  "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-github/blob/main/.agents/pm",
33
- "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-github/blob/main/.agents/pm --check",
33
+ "changelog:check": "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-github/blob/main/.agents/pm --check",
34
34
  "release:check": "npm run typecheck && npm run build && npm test && npm run audit:prod && npm run pack:dry-run && npm run changelog:check",
35
35
  "prepublishOnly": "npm run release:check",
36
36
  "release:notes": "pm-changelog --pm-root .agents/pm --stdout --since-previous-tag --until-release-tag --release-version-from-package --item-url-base https://github.com/unbraind/pm-github/blob/main/.agents/pm --pm-bin ./node_modules/.bin/pm --github-step-summary"
37
37
  },
38
38
  "peerDependencies": {
39
- "@unbrained/pm-cli": ">=2026.7.5"
39
+ "@unbrained/pm-cli": ">=2026.7.10"
40
40
  },
41
41
  "devDependencies": {
42
- "@types/node": "^25.9.2",
43
- "@unbrained/pm-cli": "^2026.7.5",
44
- "pm-changelog": "^2026.6.30",
45
- "typescript": "^6.0.3"
42
+ "@types/node": "^26.1.1",
43
+ "@unbrained/pm-cli": "^2026.7.10",
44
+ "pm-changelog": "^2026.7.10",
45
+ "typescript": "^7.0.2"
46
46
  },
47
47
  "keywords": [
48
48
  "github",