pumuki 6.3.44 → 6.3.46

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.
@@ -11,6 +11,18 @@ const SDD_STATUS_SECTION = {
11
11
  end: '<!-- PUMUKI:END SDD_STATUS -->',
12
12
  } as const;
13
13
 
14
+ const TRACKING_HUB_SECTION = {
15
+ id: 'pumuki-sdd-sync',
16
+ begin: '<!-- PUMUKI:BEGIN SDD_SYNC_STATUS -->',
17
+ end: '<!-- PUMUKI:END SDD_SYNC_STATUS -->',
18
+ } as const;
19
+
20
+ const OPERATIONAL_SUMMARY_SECTION = {
21
+ id: 'pumuki-sdd-sync',
22
+ begin: '<!-- PUMUKI:BEGIN SDD_SYNC_STATUS -->',
23
+ end: '<!-- PUMUKI:END SDD_SYNC_STATUS -->',
24
+ } as const;
25
+
14
26
  type ManagedSectionSyncResult = {
15
27
  sectionId: string;
16
28
  updated: boolean;
@@ -24,11 +36,15 @@ export type SddSyncDocsManagedSection = {
24
36
  beginMarker: string;
25
37
  endMarker: string;
26
38
  renderBody: (repoRoot: string) => string;
39
+ createIfMissing?: boolean;
27
40
  };
28
41
 
29
42
  export type SddSyncDocsTarget = {
30
43
  path: string;
31
- sections: ReadonlyArray<SddSyncDocsManagedSection>;
44
+ sections?: ReadonlyArray<SddSyncDocsManagedSection>;
45
+ renderWholeFile?: (repoRoot: string, currentSource: string) => string;
46
+ optional?: boolean;
47
+ bootstrapIfMissing?: string | ((repoRoot: string) => string);
32
48
  };
33
49
 
34
50
  export type SddSyncDocsFileResult = {
@@ -182,7 +198,51 @@ const formatSddStatusManagedBody = (repoRoot: string): string => {
182
198
  ].join('\n');
183
199
  };
184
200
 
185
- const DEFAULT_SYNC_DOCS_TARGETS: ReadonlyArray<SddSyncDocsTarget> = [
201
+ const formatTrackingManagedBody = (repoRoot: string): string => {
202
+ const status = readSddStatus(repoRoot);
203
+ return [
204
+ `- source: pumuki sdd sync-docs`,
205
+ `- repo_root: ${status.repoRoot}`,
206
+ `- openspec_installed: ${status.openspec.installed ? 'yes' : 'no'}`,
207
+ `- openspec_version: ${status.openspec.version ?? 'unknown'}`,
208
+ `- sdd_session_active: ${status.session.active ? 'yes' : 'no'}`,
209
+ `- sdd_session_valid: ${status.session.valid ? 'yes' : 'no'}`,
210
+ `- sdd_session_change: ${status.session.changeId ?? 'none'}`,
211
+ ].join('\n');
212
+ };
213
+
214
+ const renderLastRunJson = (repoRoot: string, currentSource: string): string => {
215
+ let parsed: unknown;
216
+ try {
217
+ parsed = JSON.parse(currentSource);
218
+ } catch {
219
+ throw new Error('[pumuki][sdd] sync-docs invalid JSON in docs/validation/refactor/last-run.json');
220
+ }
221
+ if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
222
+ throw new Error('[pumuki][sdd] sync-docs expected object JSON in docs/validation/refactor/last-run.json');
223
+ }
224
+
225
+ const status = readSddStatus(repoRoot);
226
+ const payload = parsed as Record<string, unknown>;
227
+ const next = {
228
+ ...payload,
229
+ pumuki_sdd_status: {
230
+ source: 'pumuki sdd sync-docs',
231
+ repo_root: status.repoRoot,
232
+ openspec_installed: status.openspec.installed,
233
+ openspec_version: status.openspec.version ?? null,
234
+ openspec_project_initialized: status.openspec.projectInitialized,
235
+ openspec_compatible: status.openspec.compatible,
236
+ session_active: status.session.active,
237
+ session_valid: status.session.valid,
238
+ session_change: status.session.changeId ?? null,
239
+ },
240
+ };
241
+
242
+ return `${JSON.stringify(next, null, 2)}\n`;
243
+ };
244
+
245
+ const PRIMARY_SYNC_DOCS_TARGETS: ReadonlyArray<SddSyncDocsTarget> = [
186
246
  {
187
247
  path: 'docs/technical/08-validation/refactor/pumuki-integration-feedback.md',
188
248
  sections: [
@@ -196,10 +256,151 @@ const DEFAULT_SYNC_DOCS_TARGETS: ReadonlyArray<SddSyncDocsTarget> = [
196
256
  },
197
257
  ];
198
258
 
259
+ const OPTIONAL_SYNC_DOCS_TARGETS: ReadonlyArray<SddSyncDocsTarget> = [
260
+ {
261
+ path: 'docs/strategy/ruralgo-tracking-hub.md',
262
+ optional: true,
263
+ sections: [
264
+ {
265
+ id: TRACKING_HUB_SECTION.id,
266
+ beginMarker: TRACKING_HUB_SECTION.begin,
267
+ endMarker: TRACKING_HUB_SECTION.end,
268
+ renderBody: formatTrackingManagedBody,
269
+ createIfMissing: true,
270
+ },
271
+ ],
272
+ },
273
+ {
274
+ path: 'docs/technical/08-validation/refactor/operational-summary.md',
275
+ optional: true,
276
+ sections: [
277
+ {
278
+ id: OPERATIONAL_SUMMARY_SECTION.id,
279
+ beginMarker: OPERATIONAL_SUMMARY_SECTION.begin,
280
+ endMarker: OPERATIONAL_SUMMARY_SECTION.end,
281
+ renderBody: formatTrackingManagedBody,
282
+ createIfMissing: true,
283
+ },
284
+ ],
285
+ },
286
+ {
287
+ path: 'docs/validation/refactor/last-run.json',
288
+ optional: true,
289
+ renderWholeFile: renderLastRunJson,
290
+ },
291
+ ];
292
+
293
+ const DEFAULT_SYNC_DOCS_TARGETS: ReadonlyArray<SddSyncDocsTarget> = [
294
+ ...PRIMARY_SYNC_DOCS_TARGETS,
295
+ ...OPTIONAL_SYNC_DOCS_TARGETS,
296
+ ];
297
+
199
298
  export const SDD_SYNC_DOCS_CANONICAL_FILES = DEFAULT_SYNC_DOCS_TARGETS.map(
200
299
  (target) => target.path
201
300
  );
202
301
 
302
+ const resolveSyncDocsTargets = (
303
+ repoRoot: string,
304
+ targets?: ReadonlyArray<SddSyncDocsTarget>
305
+ ): ReadonlyArray<SddSyncDocsTarget> => {
306
+ if (targets) {
307
+ return targets;
308
+ }
309
+ return DEFAULT_SYNC_DOCS_TARGETS.filter((target) => {
310
+ if (!target.optional) {
311
+ return true;
312
+ }
313
+ return existsSync(resolve(repoRoot, target.path));
314
+ });
315
+ };
316
+
317
+ const OPENSPEC_AUTO_SYNC_SECTION = {
318
+ id: 'pumuki-auto-sync',
319
+ begin: '<!-- PUMUKI:BEGIN AUTO_SYNC_STATUS -->',
320
+ end: '<!-- PUMUKI:END AUTO_SYNC_STATUS -->',
321
+ } as const;
322
+
323
+ const formatOpenSpecAutoSyncBody = (params: {
324
+ change: string;
325
+ stage: SddStage | null;
326
+ task: string | null;
327
+ now: () => Date;
328
+ }): string =>
329
+ [
330
+ `- source: pumuki sdd auto-sync`,
331
+ `- change: ${params.change}`,
332
+ `- stage: ${params.stage ?? 'none'}`,
333
+ `- task: ${params.task ?? 'none'}`,
334
+ `- updated_at: ${params.now().toISOString()}`,
335
+ ].join('\n');
336
+
337
+ const buildOpenSpecAutoSyncTargets = (params: {
338
+ change: string;
339
+ stage: SddStage | null;
340
+ task: string | null;
341
+ now: () => Date;
342
+ }): ReadonlyArray<SddSyncDocsTarget> => {
343
+ const buildDoc = (title: string): string =>
344
+ [
345
+ `# ${title}`,
346
+ '',
347
+ OPENSPEC_AUTO_SYNC_SECTION.begin,
348
+ '- source: bootstrap',
349
+ OPENSPEC_AUTO_SYNC_SECTION.end,
350
+ '',
351
+ ].join('\n');
352
+
353
+ const renderBody = () =>
354
+ formatOpenSpecAutoSyncBody({
355
+ change: params.change,
356
+ stage: params.stage,
357
+ task: params.task,
358
+ now: params.now,
359
+ });
360
+
361
+ return [
362
+ {
363
+ path: `openspec/changes/${params.change}/tasks.md`,
364
+ sections: [
365
+ {
366
+ id: OPENSPEC_AUTO_SYNC_SECTION.id,
367
+ beginMarker: OPENSPEC_AUTO_SYNC_SECTION.begin,
368
+ endMarker: OPENSPEC_AUTO_SYNC_SECTION.end,
369
+ renderBody,
370
+ createIfMissing: true,
371
+ },
372
+ ],
373
+ bootstrapIfMissing: buildDoc('Tasks'),
374
+ },
375
+ {
376
+ path: `openspec/changes/${params.change}/design.md`,
377
+ sections: [
378
+ {
379
+ id: OPENSPEC_AUTO_SYNC_SECTION.id,
380
+ beginMarker: OPENSPEC_AUTO_SYNC_SECTION.begin,
381
+ endMarker: OPENSPEC_AUTO_SYNC_SECTION.end,
382
+ renderBody,
383
+ createIfMissing: true,
384
+ },
385
+ ],
386
+ bootstrapIfMissing: buildDoc('Design'),
387
+ },
388
+ {
389
+ path: `openspec/changes/${params.change}/retrospective.md`,
390
+ sections: [
391
+ {
392
+ id: OPENSPEC_AUTO_SYNC_SECTION.id,
393
+ beginMarker: OPENSPEC_AUTO_SYNC_SECTION.begin,
394
+ endMarker: OPENSPEC_AUTO_SYNC_SECTION.end,
395
+ renderBody,
396
+ createIfMissing: true,
397
+ },
398
+ ],
399
+ bootstrapIfMissing: buildDoc('Retrospective'),
400
+ },
401
+ ];
402
+ };
403
+
203
404
  const applyManagedSection = (params: {
204
405
  filePath: string;
205
406
  source: string;
@@ -207,14 +408,46 @@ const applyManagedSection = (params: {
207
408
  endMarker: string;
208
409
  renderedBody: string;
209
410
  sectionId: string;
411
+ createIfMissing?: boolean;
210
412
  }): {
211
413
  nextSource: string;
212
414
  result: ManagedSectionSyncResult;
213
415
  } => {
214
416
  const beginIndex = params.source.indexOf(params.beginMarker);
215
417
  const endIndex = params.source.indexOf(params.endMarker);
216
-
217
- if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) {
418
+ const missingBegin = beginIndex === -1;
419
+ const missingEnd = endIndex === -1;
420
+
421
+ if (missingBegin || missingEnd) {
422
+ if (params.createIfMissing === true && missingBegin && missingEnd) {
423
+ const beforeBody = '';
424
+ const afterBody = normalizeSectionBody(params.renderedBody);
425
+ const block = `${params.beginMarker}\n${params.renderedBody}\n${params.endMarker}`;
426
+ const sourceTrimmedEnd = params.source.replace(/\s*$/, '');
427
+ const nextSource =
428
+ sourceTrimmedEnd.length === 0
429
+ ? `${block}\n`
430
+ : `${sourceTrimmedEnd}\n\n${block}\n`;
431
+ return {
432
+ nextSource,
433
+ result: {
434
+ sectionId: params.sectionId,
435
+ updated: true,
436
+ before: beforeBody,
437
+ after: afterBody,
438
+ diffMarkdown: buildSectionDiffMarkdown({
439
+ sectionId: params.sectionId,
440
+ before: beforeBody,
441
+ after: afterBody,
442
+ }),
443
+ },
444
+ };
445
+ }
446
+ throw new Error(
447
+ `[pumuki][sdd] sync-docs conflict in ${params.filePath}: expected managed markers ${params.beginMarker} ... ${params.endMarker}`
448
+ );
449
+ }
450
+ if (endIndex < beginIndex) {
218
451
  throw new Error(
219
452
  `[pumuki][sdd] sync-docs conflict in ${params.filePath}: expected managed markers ${params.beginMarker} ... ${params.endMarker}`
220
453
  );
@@ -369,7 +602,7 @@ export const runSddSyncDocs = (params?: {
369
602
  flagName: '--from-evidence',
370
603
  })
371
604
  : null;
372
- const targets = params?.targets ?? DEFAULT_SYNC_DOCS_TARGETS;
605
+ const targets = resolveSyncDocsTargets(repoRoot, params?.targets);
373
606
  const now = params?.now ?? (() => new Date());
374
607
  const evidenceReader =
375
608
  params?.evidenceReader ??
@@ -381,45 +614,88 @@ export const runSddSyncDocs = (params?: {
381
614
  : undefined
382
615
  ));
383
616
 
384
- const updates = targets.map((target) => {
617
+ const updates: Array<{
618
+ relativePath: string;
619
+ absolutePath: string;
620
+ currentSource: string;
621
+ nextSource: string;
622
+ sections: ManagedSectionSyncResult[];
623
+ }> = [];
624
+
625
+ for (const target of targets) {
385
626
  const absolutePath = resolve(repoRoot, target.path);
386
- if (!existsSync(absolutePath)) {
387
- throw new Error(
388
- `[pumuki][sdd] sync-docs missing canonical file: ${target.path}`
389
- );
627
+ const exists = existsSync(absolutePath);
628
+ let currentSource = '';
629
+
630
+ if (!exists) {
631
+ if (target.bootstrapIfMissing !== undefined) {
632
+ currentSource =
633
+ typeof target.bootstrapIfMissing === 'function'
634
+ ? target.bootstrapIfMissing(repoRoot)
635
+ : target.bootstrapIfMissing;
636
+ } else if (target.optional) {
637
+ continue;
638
+ } else {
639
+ throw new Error(
640
+ `[pumuki][sdd] sync-docs missing canonical file: ${target.path}`
641
+ );
642
+ }
643
+ } else {
644
+ currentSource = readFileSync(absolutePath, 'utf8');
390
645
  }
391
646
 
392
- const currentSource = readFileSync(absolutePath, 'utf8');
393
647
  let nextSource = currentSource;
394
648
  const sectionUpdates: ManagedSectionSyncResult[] = [];
395
649
 
396
- for (const section of target.sections) {
397
- const update = applyManagedSection({
398
- filePath: target.path,
399
- source: nextSource,
400
- beginMarker: section.beginMarker,
401
- endMarker: section.endMarker,
402
- renderedBody: section.renderBody(repoRoot),
403
- sectionId: section.id,
650
+ if (target.renderWholeFile) {
651
+ nextSource = target.renderWholeFile(repoRoot, nextSource);
652
+ sectionUpdates.push({
653
+ sectionId: 'file-content',
654
+ updated: normalizeSectionBody(currentSource) !== normalizeSectionBody(nextSource),
655
+ before: normalizeSectionBody(currentSource),
656
+ after: normalizeSectionBody(nextSource),
657
+ diffMarkdown: buildSectionDiffMarkdown({
658
+ sectionId: 'file-content',
659
+ before: normalizeSectionBody(currentSource),
660
+ after: normalizeSectionBody(nextSource),
661
+ }),
404
662
  });
405
- nextSource = update.nextSource;
406
- sectionUpdates.push(update.result);
663
+ } else {
664
+ if (!target.sections || target.sections.length === 0) {
665
+ throw new Error(
666
+ `[pumuki][sdd] sync-docs invalid target configuration for ${target.path}: expected sections or renderWholeFile`
667
+ );
668
+ }
669
+ for (const section of target.sections) {
670
+ const update = applyManagedSection({
671
+ filePath: target.path,
672
+ source: nextSource,
673
+ beginMarker: section.beginMarker,
674
+ endMarker: section.endMarker,
675
+ renderedBody: section.renderBody(repoRoot),
676
+ sectionId: section.id,
677
+ createIfMissing: section.createIfMissing,
678
+ });
679
+ nextSource = update.nextSource;
680
+ sectionUpdates.push(update.result);
681
+ }
407
682
  }
408
683
 
409
- return {
684
+ updates.push({
410
685
  relativePath: target.path,
411
686
  absolutePath,
412
687
  currentSource,
413
688
  nextSource,
414
689
  sections: sectionUpdates,
415
- };
416
- });
690
+ });
691
+ }
417
692
 
418
693
  if (!dryRun) {
419
694
  for (const update of updates) {
420
- if (update.currentSource === update.nextSource) {
695
+ if (update.currentSource === update.nextSource && existsSync(update.absolutePath)) {
421
696
  continue;
422
697
  }
698
+ mkdirSync(dirname(update.absolutePath), { recursive: true });
423
699
  writeFileSync(update.absolutePath, update.nextSource, 'utf8');
424
700
  }
425
701
  }
@@ -557,17 +833,30 @@ export const runSddAutoSync = (params?: {
557
833
  if (!change) {
558
834
  throw new Error('[pumuki][sdd] auto-sync requires --change=<change-id>.');
559
835
  }
836
+ const repoRoot = resolve(params?.repoRoot ?? process.cwd());
837
+ const now = params?.now ?? (() => new Date());
838
+ const targets =
839
+ params?.targets ??
840
+ [
841
+ ...resolveSyncDocsTargets(repoRoot),
842
+ ...buildOpenSpecAutoSyncTargets({
843
+ change,
844
+ stage: params?.stage ?? null,
845
+ task: params?.task?.trim() ? params.task.trim() : null,
846
+ now,
847
+ }),
848
+ ];
560
849
 
561
850
  const syncResult = runSddSyncDocs({
562
- repoRoot: params?.repoRoot,
851
+ repoRoot,
563
852
  dryRun: params?.dryRun,
564
853
  change,
565
854
  stage: params?.stage,
566
855
  task: params?.task,
567
856
  fromEvidencePath: params?.fromEvidencePath,
568
- now: params?.now,
857
+ now,
569
858
  evidenceReader: params?.evidenceReader,
570
- targets: params?.targets,
859
+ targets,
571
860
  });
572
861
 
573
862
  if (!syncResult.learning) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.44",
3
+ "version": "6.3.46",
4
4
  "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -49,7 +49,7 @@
49
49
  "test:heuristics": "npx --yes tsx@4.21.0 --test core/facts/__tests__/extractHeuristicFacts.test.ts",
50
50
  "test:evidence": "npx --yes tsx@4.21.0 --test integrations/evidence/__tests__/buildEvidence.test.ts integrations/evidence/__tests__/humanIntent.test.ts",
51
51
  "test:mcp": "npx --yes tsx@4.21.0 --test integrations/mcp/__tests__/*.test.ts",
52
- "test:backlog-tooling": "npx --yes tsx@4.21.0 --test scripts/__tests__/backlog-action-reasons-lib.test.ts scripts/__tests__/backlog-json-contract-lib.test.ts scripts/__tests__/backlog-cli-help-exit-code.test.ts scripts/__tests__/backlog-id-issue-map-lib.test.ts scripts/__tests__/reconcile-consumer-backlog-issues.test.ts scripts/__tests__/watch-consumer-backlog.test.ts",
52
+ "test:backlog-tooling": "npx --yes tsx@4.21.0 --test scripts/__tests__/backlog-action-reasons-lib.test.ts scripts/__tests__/backlog-json-contract-lib.test.ts scripts/__tests__/backlog-cli-help-exit-code.test.ts scripts/__tests__/backlog-id-issue-map-lib.test.ts scripts/__tests__/reconcile-consumer-backlog-issues.test.ts scripts/__tests__/watch-consumer-backlog.test.ts scripts/__tests__/watch-consumer-backlog-fleet.test.ts scripts/__tests__/watch-consumer-backlog-fleet-tick.test.ts",
53
53
  "test:saas-ingestion": "npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/saasIngestionContract.test.ts integrations/lifecycle/__tests__/saasIngestionBuilder.test.ts integrations/lifecycle/__tests__/saasIngestionTransport.test.ts integrations/lifecycle/__tests__/saasIngestionIdempotency.test.ts integrations/lifecycle/__tests__/saasIngestionAuth.test.ts integrations/lifecycle/__tests__/saasIngestionAudit.test.ts integrations/lifecycle/__tests__/saasIngestionMetrics.test.ts integrations/lifecycle/__tests__/saasIngestionGovernance.test.ts integrations/lifecycle/__tests__/saasFederation.test.ts integrations/lifecycle/__tests__/saasEnterpriseAnalytics.test.ts integrations/lifecycle/__tests__/cli.test.ts",
54
54
  "test:operational-memory": "npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/operationalMemoryContract.test.ts integrations/lifecycle/__tests__/operationalMemorySignals.test.ts integrations/lifecycle/__tests__/operationalMemorySnapshot.test.ts integrations/git/__tests__/runPlatformGate.test.ts integrations/git/__tests__/runPlatformGateEvidence.test.ts integrations/evidence/__tests__/buildEvidence.test.ts integrations/evidence/writeEvidence.test.ts integrations/evidence/generateEvidence.test.ts",
55
55
  "test:stage-gates": "npx --yes tsx@4.21.0 --test integrations/config/__tests__/*.test.ts integrations/gate/__tests__/*.test.ts integrations/git/__tests__/*.test.ts integrations/lifecycle/__tests__/*.test.ts integrations/sdd/__tests__/*.test.ts scripts/__tests__/*.test.ts",
@@ -101,6 +101,9 @@
101
101
  "validation:tracking-single-active": "bash scripts/check-tracking-single-active.sh",
102
102
  "validation:backlog-reconcile": "node --import tsx scripts/reconcile-consumer-backlog-issues.ts",
103
103
  "validation:backlog-watch": "node --import tsx scripts/watch-consumer-backlog.ts",
104
+ "validation:backlog-watch:fleet": "node --import tsx scripts/watch-consumer-backlog-fleet.ts",
105
+ "validation:backlog-watch:tick": "node --import tsx scripts/watch-consumer-backlog-fleet-tick.ts --json --no-fail",
106
+ "validation:backlog-watch:gate": "node --import tsx scripts/watch-consumer-backlog-fleet-tick.ts --json",
104
107
  "validation:phase5-escalation:ready-to-submit": "bash scripts/check-phase5-escalation-ready-to-submit.sh",
105
108
  "validation:phase5-escalation:prepare": "bash scripts/prepare-phase5-escalation-submission.sh",
106
109
  "validation:phase5-escalation:close-submission": "bash scripts/close-phase5-escalation-submission.sh",
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
3
 
4
- export const BACKLOG_ID_PATTERN = /^(PUMUKI-(?:M)?\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)$/;
4
+ export const BACKLOG_ID_PATTERN = /^(PUMUKI-(?:M)?\d+|PUM-\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)$/;
5
5
 
6
6
  export type BacklogIdIssueMapRecord = Readonly<Record<string, number>>;
7
7
 
@@ -75,10 +75,10 @@ export type BacklogReconcileResult = {
75
75
 
76
76
  const STATUS_EMOJI_PATTERN = /(✅|🚧|⏳|⛔)/;
77
77
  const ISSUE_REF_PATTERN = /#(\d+)/;
78
- const BACKLOG_ID_PATTERN = /^(PUMUKI-(?:M)?\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)$/;
78
+ const BACKLOG_ID_PATTERN = /^(PUMUKI-(?:M)?\d+|PUM-\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)$/;
79
79
  const PENDING_REFERENCE_PATTERN = /\|\s*Pendiente(?:\s*\(rel\.\s*#\d+\))?\s*\|/;
80
80
  const BACKLOG_SECTION_HEADING_PATTERN =
81
- /^(\s*###\s*)(✅|🚧|⏳|⛔)(\s+)(PUMUKI-(?:M)?\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)\b/;
81
+ /^(\s*###\s*)(✅|🚧|⏳|⛔)(\s+)(PUMUKI-(?:M)?\d+|PUM-\d+|PUMUKI-INC-\d+|FP-\d+|AST-GAP-\d+)\b/;
82
82
 
83
83
  export type BacklogIssueNumberResolver = (
84
84
  backlogId: string,