@codedrifters/configulator 0.0.404 → 0.0.406
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/lib/index.d.mts +261 -1
- package/lib/index.d.ts +262 -2
- package/lib/index.js +1055 -264
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1038 -264
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -280,6 +280,603 @@ function renderClaimVerificationSection() {
|
|
|
280
280
|
];
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
// src/agent/bundles/bundle-ownership.ts
|
|
284
|
+
var BUNDLE_OWNERSHIP = {
|
|
285
|
+
agenda: {
|
|
286
|
+
typeLabels: ["agenda"],
|
|
287
|
+
phaseLabelPrefixes: ["agenda:"],
|
|
288
|
+
scheduledTaskIds: ["worker-agenda"],
|
|
289
|
+
emitsDocs: true,
|
|
290
|
+
downstreamIssueKinds: true
|
|
291
|
+
},
|
|
292
|
+
"bcm-writer": {
|
|
293
|
+
typeLabels: ["bcm-document"],
|
|
294
|
+
phaseLabelPrefixes: ["bcm:"],
|
|
295
|
+
scheduledTaskIds: ["worker-bcm-writer"],
|
|
296
|
+
emitsDocs: true,
|
|
297
|
+
downstreamIssueKinds: true
|
|
298
|
+
},
|
|
299
|
+
"business-models": {
|
|
300
|
+
typeLabels: ["business-model"],
|
|
301
|
+
phaseLabelPrefixes: ["business-models:"],
|
|
302
|
+
scheduledTaskIds: ["worker-business-models"],
|
|
303
|
+
emitsDocs: true,
|
|
304
|
+
downstreamIssueKinds: true
|
|
305
|
+
},
|
|
306
|
+
"company-profile": {
|
|
307
|
+
typeLabels: ["company-profile"],
|
|
308
|
+
phaseLabelPrefixes: ["company:"],
|
|
309
|
+
scheduledTaskIds: ["worker-company-profile"],
|
|
310
|
+
emitsDocs: true,
|
|
311
|
+
downstreamIssueKinds: true
|
|
312
|
+
},
|
|
313
|
+
"customer-profile": {
|
|
314
|
+
typeLabels: ["customer-profile"],
|
|
315
|
+
phaseLabelPrefixes: ["customer:"],
|
|
316
|
+
scheduledTaskIds: ["worker-customer-profile"],
|
|
317
|
+
emitsDocs: true,
|
|
318
|
+
downstreamIssueKinds: true
|
|
319
|
+
},
|
|
320
|
+
"docs-sync": {
|
|
321
|
+
typeLabels: ["docs-sync"],
|
|
322
|
+
phaseLabelPrefixes: ["docs-sync:"],
|
|
323
|
+
scheduledTaskIds: ["worker-docs-sync"],
|
|
324
|
+
emitsDocs: true,
|
|
325
|
+
downstreamIssueKinds: true
|
|
326
|
+
},
|
|
327
|
+
"industry-discovery": {
|
|
328
|
+
typeLabels: ["industry-discovery"],
|
|
329
|
+
phaseLabelPrefixes: ["industry:"],
|
|
330
|
+
scheduledTaskIds: ["worker-industry-discovery"],
|
|
331
|
+
emitsDocs: true,
|
|
332
|
+
downstreamIssueKinds: true
|
|
333
|
+
},
|
|
334
|
+
"maintenance-audit": {
|
|
335
|
+
typeLabels: ["maintenance"],
|
|
336
|
+
phaseLabelPrefixes: ["maint:"],
|
|
337
|
+
scheduledTaskIds: ["worker-maintenance"],
|
|
338
|
+
emitsDocs: false,
|
|
339
|
+
downstreamIssueKinds: true
|
|
340
|
+
},
|
|
341
|
+
"meeting-analysis": {
|
|
342
|
+
typeLabels: ["meeting-processing"],
|
|
343
|
+
phaseLabelPrefixes: ["meeting:"],
|
|
344
|
+
scheduledTaskIds: ["worker-meeting-analysis"],
|
|
345
|
+
emitsDocs: true,
|
|
346
|
+
downstreamIssueKinds: true
|
|
347
|
+
},
|
|
348
|
+
orchestrator: {
|
|
349
|
+
// The orchestrator pipeline manager itself ships with the
|
|
350
|
+
// `worker-orchestrator` scheduled task. It owns no `type:*` label
|
|
351
|
+
// (it dispatches every type) and no phase-label prefix.
|
|
352
|
+
typeLabels: [],
|
|
353
|
+
phaseLabelPrefixes: [],
|
|
354
|
+
scheduledTaskIds: ["worker-orchestrator"],
|
|
355
|
+
emitsDocs: false,
|
|
356
|
+
downstreamIssueKinds: false
|
|
357
|
+
},
|
|
358
|
+
"people-profile": {
|
|
359
|
+
typeLabels: ["people-profile"],
|
|
360
|
+
phaseLabelPrefixes: ["people:"],
|
|
361
|
+
scheduledTaskIds: ["worker-people-profile"],
|
|
362
|
+
emitsDocs: true,
|
|
363
|
+
downstreamIssueKinds: true
|
|
364
|
+
},
|
|
365
|
+
"pr-review": {
|
|
366
|
+
typeLabels: ["pr-review"],
|
|
367
|
+
phaseLabelPrefixes: [],
|
|
368
|
+
scheduledTaskIds: ["worker-pr-review"],
|
|
369
|
+
emitsDocs: false,
|
|
370
|
+
downstreamIssueKinds: false
|
|
371
|
+
},
|
|
372
|
+
"regulatory-research": {
|
|
373
|
+
typeLabels: ["regulatory-research"],
|
|
374
|
+
phaseLabelPrefixes: ["regulatory:"],
|
|
375
|
+
scheduledTaskIds: ["worker-regulatory-research"],
|
|
376
|
+
emitsDocs: true,
|
|
377
|
+
downstreamIssueKinds: true
|
|
378
|
+
},
|
|
379
|
+
"requirements-analyst": {
|
|
380
|
+
typeLabels: ["requirement"],
|
|
381
|
+
phaseLabelPrefixes: ["req:"],
|
|
382
|
+
scheduledTaskIds: ["worker-requirements-analyst"],
|
|
383
|
+
emitsDocs: true,
|
|
384
|
+
downstreamIssueKinds: true
|
|
385
|
+
},
|
|
386
|
+
"requirements-reviewer": {
|
|
387
|
+
// Co-owns `type:requirement` with the analyst and writer; owns
|
|
388
|
+
// the `req:review` and `req:deprecate` phase labels exactly.
|
|
389
|
+
typeLabels: ["requirement"],
|
|
390
|
+
phaseLabelPrefixes: ["req:review", "req:deprecate"],
|
|
391
|
+
scheduledTaskIds: ["worker-requirements-reviewer"],
|
|
392
|
+
emitsDocs: true,
|
|
393
|
+
downstreamIssueKinds: true
|
|
394
|
+
},
|
|
395
|
+
"requirements-writer": {
|
|
396
|
+
// Co-owns `type:requirement` with the analyst and reviewer; owns
|
|
397
|
+
// the `req:write` phase label exactly.
|
|
398
|
+
typeLabels: ["requirement"],
|
|
399
|
+
phaseLabelPrefixes: ["req:write"],
|
|
400
|
+
scheduledTaskIds: ["worker-requirements-writer"],
|
|
401
|
+
emitsDocs: true,
|
|
402
|
+
downstreamIssueKinds: true
|
|
403
|
+
},
|
|
404
|
+
"research-pipeline": {
|
|
405
|
+
typeLabels: ["research"],
|
|
406
|
+
phaseLabelPrefixes: ["research:"],
|
|
407
|
+
scheduledTaskIds: ["worker-research"],
|
|
408
|
+
emitsDocs: true,
|
|
409
|
+
downstreamIssueKinds: true
|
|
410
|
+
},
|
|
411
|
+
"software-profile": {
|
|
412
|
+
typeLabels: ["software-profile"],
|
|
413
|
+
phaseLabelPrefixes: ["software:"],
|
|
414
|
+
scheduledTaskIds: ["worker-software-profile"],
|
|
415
|
+
emitsDocs: true,
|
|
416
|
+
downstreamIssueKinds: true
|
|
417
|
+
},
|
|
418
|
+
"standards-research": {
|
|
419
|
+
typeLabels: ["standards-research"],
|
|
420
|
+
phaseLabelPrefixes: ["standards:"],
|
|
421
|
+
scheduledTaskIds: ["worker-standards-research"],
|
|
422
|
+
emitsDocs: true,
|
|
423
|
+
downstreamIssueKinds: true
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var CONVENTIONAL_COMMIT_TYPE_LABELS = [
|
|
427
|
+
"type:chore",
|
|
428
|
+
"type:docs",
|
|
429
|
+
"type:feat",
|
|
430
|
+
"type:fix",
|
|
431
|
+
"type:hotfix",
|
|
432
|
+
"type:refactor",
|
|
433
|
+
"type:release"
|
|
434
|
+
];
|
|
435
|
+
var PHASE_LABEL_TYPE_MAP = buildPhaseLabelTypeMap();
|
|
436
|
+
function typeLabelForPhaseLabel(phaseLabel) {
|
|
437
|
+
const exact = PHASE_LABEL_TYPE_MAP[phaseLabel];
|
|
438
|
+
if (exact !== void 0 && !phaseLabel.endsWith(":")) {
|
|
439
|
+
return exact;
|
|
440
|
+
}
|
|
441
|
+
let bestMatcher;
|
|
442
|
+
for (const matcher of Object.keys(PHASE_LABEL_TYPE_MAP)) {
|
|
443
|
+
if (!matcher.endsWith(":")) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
if (!phaseLabel.startsWith(matcher)) {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (bestMatcher === void 0 || matcher.length > bestMatcher.length) {
|
|
450
|
+
bestMatcher = matcher;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return bestMatcher === void 0 ? void 0 : PHASE_LABEL_TYPE_MAP[bestMatcher];
|
|
454
|
+
}
|
|
455
|
+
function resolveTypeLabelForLabels(labels) {
|
|
456
|
+
const phaseLabels = [];
|
|
457
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
458
|
+
for (const label of labels) {
|
|
459
|
+
const typeLabel = typeLabelForPhaseLabel(label);
|
|
460
|
+
if (typeLabel === void 0) {
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
phaseLabels.push(label);
|
|
464
|
+
candidates.add(typeLabel);
|
|
465
|
+
}
|
|
466
|
+
const candidateTypeLabels = Array.from(candidates).sort();
|
|
467
|
+
if (candidateTypeLabels.length === 0) {
|
|
468
|
+
return { outcome: "none", candidateTypeLabels: [], phaseLabels: [] };
|
|
469
|
+
}
|
|
470
|
+
if (candidateTypeLabels.length === 1) {
|
|
471
|
+
return {
|
|
472
|
+
outcome: "match",
|
|
473
|
+
typeLabel: candidateTypeLabels[0],
|
|
474
|
+
candidateTypeLabels,
|
|
475
|
+
phaseLabels
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
return { outcome: "ambiguous", candidateTypeLabels, phaseLabels };
|
|
479
|
+
}
|
|
480
|
+
function renderPhaseTypeInvariantSection(excludeBundles = []) {
|
|
481
|
+
const rows = Object.keys(PHASE_LABEL_TYPE_MAP).filter(
|
|
482
|
+
(matcher) => !isPhaseLabelMatcherOwnedByExcluded(matcher, excludeBundles)
|
|
483
|
+
).sort().map((matcher) => {
|
|
484
|
+
const display = matcher.endsWith(":") ? `${matcher}*` : matcher;
|
|
485
|
+
const kind = matcher.endsWith(":") ? "prefix" : "exact";
|
|
486
|
+
return `| \`${display}\` | ${kind} | \`${PHASE_LABEL_TYPE_MAP[matcher]}\` |`;
|
|
487
|
+
});
|
|
488
|
+
return [
|
|
489
|
+
"## Phase-label \u2192 `type:<bundle>` invariant",
|
|
490
|
+
"",
|
|
491
|
+
"Every phased-pipeline bundle pairs its `<bundle>:<phase>` labels",
|
|
492
|
+
"with exactly one `type:<bundle>` label. That type label is the",
|
|
493
|
+
"**dedup + dispatch signal**: agents de-duplicate downstream work",
|
|
494
|
+
'with `gh issue list --label "type:<bundle>"`, and Phase E derives',
|
|
495
|
+
"its funnel-tier sort key from the issue's `type:*` label. An issue",
|
|
496
|
+
"that carries the phase label but a conventional-commit `type:*`",
|
|
497
|
+
"(`type:feat`, `type:docs`, \u2026, stamped from its title prefix by the",
|
|
498
|
+
"generic create-issue workflow) is invisible to that dedup query and",
|
|
499
|
+
"mis-tiers in dispatch.",
|
|
500
|
+
"",
|
|
501
|
+
"The pairing below is derived from the canonical bundle-ownership",
|
|
502
|
+
"map \u2014 the same source of truth that generates the label registry.",
|
|
503
|
+
"Matchers ending in `*` match by prefix; the rest match exactly, and",
|
|
504
|
+
"an exact match always beats a prefix match.",
|
|
505
|
+
"",
|
|
506
|
+
"| Phase label | Match | Required type label |",
|
|
507
|
+
"|-------------|-------|---------------------|",
|
|
508
|
+
...rows,
|
|
509
|
+
"",
|
|
510
|
+
"### Enforcement",
|
|
511
|
+
"",
|
|
512
|
+
"The Phase D maintenance sweep runs the invariant in auto-correct",
|
|
513
|
+
"mode and emits one summary line:",
|
|
514
|
+
"",
|
|
515
|
+
"```",
|
|
516
|
+
"LABEL_INVARIANT_DONE mode=fix checked=<N> ok=<O> violations=<V> corrected=<C> flagged=<F>",
|
|
517
|
+
"```",
|
|
518
|
+
"",
|
|
519
|
+
"A **report-only** audit is available for repos that prefer",
|
|
520
|
+
"report-then-fix over auto-correct \u2014 same sweep, no mutations:",
|
|
521
|
+
"",
|
|
522
|
+
"```bash",
|
|
523
|
+
".claude/procedures/check-blocked.sh label-invariant # report only",
|
|
524
|
+
".claude/procedures/check-blocked.sh label-invariant --fix # apply",
|
|
525
|
+
"```",
|
|
526
|
+
"",
|
|
527
|
+
"### Correction policy",
|
|
528
|
+
"",
|
|
529
|
+
"An issue must carry **exactly one** `type:*` label. Merely *adding*",
|
|
530
|
+
"the required type label to an issue that already carries a",
|
|
531
|
+
"conventional-commit one would leave two, making the funnel-tier sort",
|
|
532
|
+
"key (which reads the **first** `type:*` label) non-deterministic and",
|
|
533
|
+
"violating the label conventions. The correction therefore",
|
|
534
|
+
"**replaces**, in a single atomic `gh issue edit`, so the issue is",
|
|
535
|
+
"never observable carrying two `type:*` labels:",
|
|
536
|
+
"",
|
|
537
|
+
"| Issue state | Action |",
|
|
538
|
+
"|-------------|--------|",
|
|
539
|
+
"| Required type label present, nothing else | none \u2014 compliant, left untouched |",
|
|
540
|
+
"| No `type:*` label at all | **add** the required label |",
|
|
541
|
+
"| Only conventional-commit `type:*` label(s) | **replace** \u2014 remove them, add the required label |",
|
|
542
|
+
"| Required label present **plus** a stray conventional-commit one | **remove** the stray, leaving exactly one |",
|
|
543
|
+
"| A `type:*` label owned by a **different** bundle | **flag** `status:needs-attention` \u2014 never guessed at |",
|
|
544
|
+
"| Phase labels imply **two or more** type labels | **flag** `status:needs-attention` \u2014 never auto-corrected |",
|
|
545
|
+
"",
|
|
546
|
+
"Only a conventional-commit `type:*` label is ever removed. A",
|
|
547
|
+
"`type:*` label owned by another bundle carries real routing",
|
|
548
|
+
"information, so the sweep refuses to guess and hands the issue to a",
|
|
549
|
+
"human instead. Ambiguity is narrower than it looks: all three",
|
|
550
|
+
"requirements bundles declare `type:requirement`, so every `req:*`",
|
|
551
|
+
"phase label resolves to the same type label \u2014 genuine ambiguity",
|
|
552
|
+
"needs phase labels from two bundles with *different* type labels.",
|
|
553
|
+
"",
|
|
554
|
+
"`status:needs-attention` is applied **additively** \u2014 the base",
|
|
555
|
+
"`status:*` label always stays, per the additive-flag rule. Flagging",
|
|
556
|
+
"is idempotent: an issue already carrying the flag is reported but",
|
|
557
|
+
"not re-flagged."
|
|
558
|
+
].join("\n");
|
|
559
|
+
}
|
|
560
|
+
function isPhaseLabelMatcherOwnedByExcluded(matcher, excludeBundles) {
|
|
561
|
+
if (excludeBundles.length === 0) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
let owned = false;
|
|
565
|
+
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
566
|
+
if (!ownership.phaseLabelPrefixes.includes(matcher)) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
owned = true;
|
|
570
|
+
if (!excludeBundles.includes(bundleName)) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return owned;
|
|
575
|
+
}
|
|
576
|
+
function renderPhaseTypeInvariantShellHelpers() {
|
|
577
|
+
const matchers = Object.keys(PHASE_LABEL_TYPE_MAP);
|
|
578
|
+
const exactMatchers = matchers.filter((m) => !m.endsWith(":")).sort();
|
|
579
|
+
const prefixMatchers = matchers.filter((m) => m.endsWith(":")).sort((a, b) => b.length - a.length || a.localeCompare(b));
|
|
580
|
+
const lines = [
|
|
581
|
+
"# Resolve ONE phase label to the `type:<bundle>` label its owning",
|
|
582
|
+
"# bundle declares. Echoes the label (with the `type:` prefix) or",
|
|
583
|
+
"# nothing when no bundle owns it. Exact-match branches come first,",
|
|
584
|
+
"# so `req:write` (requirements-writer) beats the `req:` prefix",
|
|
585
|
+
"# (requirements-analyst). Generated from BUNDLE_OWNERSHIP \u2014 do not",
|
|
586
|
+
"# hand-edit.",
|
|
587
|
+
"phase_label_type_of() {",
|
|
588
|
+
' case "${1:-}" in'
|
|
589
|
+
];
|
|
590
|
+
for (const matcher of exactMatchers) {
|
|
591
|
+
lines.push(` ${matcher}) echo "${PHASE_LABEL_TYPE_MAP[matcher]}" ;;`);
|
|
592
|
+
}
|
|
593
|
+
for (const matcher of prefixMatchers) {
|
|
594
|
+
lines.push(` ${matcher}*) echo "${PHASE_LABEL_TYPE_MAP[matcher]}" ;;`);
|
|
595
|
+
}
|
|
596
|
+
lines.push(
|
|
597
|
+
" *) : ;;",
|
|
598
|
+
" esac",
|
|
599
|
+
"}",
|
|
600
|
+
"",
|
|
601
|
+
"# Return 0 when the argument is a conventional-commit `type:*`",
|
|
602
|
+
"# label \u2014 the ONLY type labels the invariant correction may remove.",
|
|
603
|
+
"# A `type:*` label owned by another bundle is never removed; the",
|
|
604
|
+
"# issue is flagged for human triage instead.",
|
|
605
|
+
"is_conventional_type_label() {",
|
|
606
|
+
` case "\${1:-}" in`,
|
|
607
|
+
` ${CONVENTIONAL_COMMIT_TYPE_LABELS.join("|")}) return 0 ;;`,
|
|
608
|
+
" *) return 1 ;;",
|
|
609
|
+
" esac",
|
|
610
|
+
"}",
|
|
611
|
+
"",
|
|
612
|
+
"# Resolve an issue's FULL label list (one label per line on stdin)",
|
|
613
|
+
"# to the type label the phase-label invariant requires. Emits",
|
|
614
|
+
"# KEY=VALUE assignments the caller parses:",
|
|
615
|
+
"# OUTCOME=none \u2014 no recognised phase label; invariant N/A",
|
|
616
|
+
"# OUTCOME=match \u2014 plus TYPE_LABEL=<type:bundle>",
|
|
617
|
+
"# OUTCOME=ambiguous \u2014 plus CANDIDATE_TYPE_LABELS=<space-separated>",
|
|
618
|
+
"# PHASE_LABELS=<space-separated recognised phase labels>",
|
|
619
|
+
"phase_type_of() {",
|
|
620
|
+
" local label resolved",
|
|
621
|
+
' local matched_types=""',
|
|
622
|
+
' local matched_phase=""',
|
|
623
|
+
" while IFS= read -r label; do",
|
|
624
|
+
' [ -z "$label" ] && continue',
|
|
625
|
+
' resolved=$(phase_label_type_of "$label")',
|
|
626
|
+
' [ -z "$resolved" ] && continue',
|
|
627
|
+
' matched_phase="${matched_phase}${label} "',
|
|
628
|
+
' case " ${matched_types} " in',
|
|
629
|
+
' *" ${resolved} "*) ;;',
|
|
630
|
+
' *) matched_types="${matched_types}${resolved} " ;;',
|
|
631
|
+
" esac",
|
|
632
|
+
" done",
|
|
633
|
+
" local count=0",
|
|
634
|
+
" for resolved in $matched_types; do",
|
|
635
|
+
" count=$((count + 1))",
|
|
636
|
+
" done",
|
|
637
|
+
' if [ "$count" -eq 0 ]; then',
|
|
638
|
+
' echo "OUTCOME=none"',
|
|
639
|
+
' elif [ "$count" -eq 1 ]; then',
|
|
640
|
+
' echo "OUTCOME=match"',
|
|
641
|
+
' echo "TYPE_LABEL=${matched_types% }"',
|
|
642
|
+
" else",
|
|
643
|
+
' echo "OUTCOME=ambiguous"',
|
|
644
|
+
' echo "CANDIDATE_TYPE_LABELS=${matched_types% }"',
|
|
645
|
+
" fi",
|
|
646
|
+
' echo "PHASE_LABELS=${matched_phase% }"',
|
|
647
|
+
"}"
|
|
648
|
+
);
|
|
649
|
+
return lines.join("\n");
|
|
650
|
+
}
|
|
651
|
+
function buildPhaseLabelTypeMap() {
|
|
652
|
+
const map = {};
|
|
653
|
+
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
654
|
+
if (ownership.phaseLabelPrefixes.length === 0) {
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
if (ownership.typeLabels.length !== 1) {
|
|
658
|
+
throw new Error(
|
|
659
|
+
`BUNDLE_OWNERSHIP["${bundleName}"] declares ${ownership.phaseLabelPrefixes.length} phase-label matcher(s) but ${ownership.typeLabels.length} type label(s); a phase label must pair with exactly one type label`
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
const typeLabel = `type:${ownership.typeLabels[0]}`;
|
|
663
|
+
for (const matcher of ownership.phaseLabelPrefixes) {
|
|
664
|
+
const existing = map[matcher];
|
|
665
|
+
if (existing !== void 0 && existing !== typeLabel) {
|
|
666
|
+
throw new Error(
|
|
667
|
+
`Phase-label matcher "${matcher}" resolves to both "${existing}" and "${typeLabel}"; a matcher must imply exactly one type label`
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
map[matcher] = typeLabel;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return map;
|
|
674
|
+
}
|
|
675
|
+
function isTypeLabelOwnedByExcluded(typeLabel, excludedBundles) {
|
|
676
|
+
if (excludedBundles.length === 0) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
for (const bundleName of excludedBundles) {
|
|
680
|
+
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
681
|
+
if (!ownership) {
|
|
682
|
+
continue;
|
|
683
|
+
}
|
|
684
|
+
if (ownership.typeLabels.includes(typeLabel)) {
|
|
685
|
+
const owners = findOwnersOfTypeLabel(typeLabel);
|
|
686
|
+
const allExcluded = owners.every(
|
|
687
|
+
(owner) => excludedBundles.includes(owner)
|
|
688
|
+
);
|
|
689
|
+
if (allExcluded) {
|
|
690
|
+
return true;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return false;
|
|
695
|
+
}
|
|
696
|
+
function isPhaseLabelOwnedByExcluded(phaseLabel, excludedBundles) {
|
|
697
|
+
if (excludedBundles.length === 0) {
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
for (const bundleName of excludedBundles) {
|
|
701
|
+
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
702
|
+
if (!ownership) {
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
for (const entry of ownership.phaseLabelPrefixes) {
|
|
706
|
+
if (entry.endsWith(":")) {
|
|
707
|
+
if (phaseLabel.startsWith(entry)) {
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
} else if (phaseLabel === entry) {
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
function isScheduledTaskOwnedByExcluded(taskId, excludedBundles) {
|
|
718
|
+
if (excludedBundles.length === 0) {
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
for (const bundleName of excludedBundles) {
|
|
722
|
+
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
723
|
+
if (!ownership) {
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
if (ownership.scheduledTaskIds.includes(taskId)) {
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
function hasAnyDocsEmittingBundle(excludedBundles) {
|
|
733
|
+
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
734
|
+
if (!ownership.emitsDocs) {
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
if (!excludedBundles.includes(bundleName)) {
|
|
738
|
+
return true;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
function hasAnyDownstreamIssueKindBundle(excludedBundles) {
|
|
744
|
+
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
745
|
+
if (!ownership.downstreamIssueKinds) {
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
if (!excludedBundles.includes(bundleName)) {
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
function findOwnersOfTypeLabel(typeLabel) {
|
|
755
|
+
const owners = [];
|
|
756
|
+
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
757
|
+
if (ownership.typeLabels.includes(typeLabel)) {
|
|
758
|
+
owners.push(bundleName);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return owners;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/agent/bundles/issue-type.ts
|
|
765
|
+
var GITHUB_ISSUE_TYPES = ["Epic", "Feature", "Bug", "Task"];
|
|
766
|
+
var DEFAULT_GITHUB_ISSUE_TYPE = "Task";
|
|
767
|
+
var NON_DEFAULT_TITLE_PREFIX_TYPES = {
|
|
768
|
+
"epic:": "Epic",
|
|
769
|
+
"feat:": "Feature",
|
|
770
|
+
"fix:": "Bug"
|
|
771
|
+
};
|
|
772
|
+
var GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX = buildTitlePrefixTypeMap();
|
|
773
|
+
function githubIssueTypeForTitle(title) {
|
|
774
|
+
const colon = title.indexOf(":");
|
|
775
|
+
if (colon === -1) {
|
|
776
|
+
return DEFAULT_GITHUB_ISSUE_TYPE;
|
|
777
|
+
}
|
|
778
|
+
const prefix2 = title.slice(0, colon + 1).trim().toLowerCase();
|
|
779
|
+
return GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX[prefix2] ?? DEFAULT_GITHUB_ISSUE_TYPE;
|
|
780
|
+
}
|
|
781
|
+
var SET_ISSUE_TYPE_HELPER_PATH = ".claude/procedures/set-issue-type.sh";
|
|
782
|
+
function renderSetIssueTypeFallbackLines() {
|
|
783
|
+
return [
|
|
784
|
+
"```bash",
|
|
785
|
+
"gh api graphql -f query='query($owner:String!,$repo:String!){repository(owner:$owner,name:$repo){issueTypes(first:50){nodes{id name}}}}' -f owner=<owner> -f repo=<repo>",
|
|
786
|
+
"gh issue view <issue-number> --json id --jq '.id'",
|
|
787
|
+
"gh api graphql -f query='mutation($issueId:ID!,$typeId:ID!){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$typeId}){issue{number issueType{name}}}}' -f issueId=<issue-node-id> -f typeId=<issue-type-node-id>",
|
|
788
|
+
"```"
|
|
789
|
+
];
|
|
790
|
+
}
|
|
791
|
+
function renderGithubIssueTypeSectionLines() {
|
|
792
|
+
const defaultPrefixes = Object.keys(GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX).filter(
|
|
793
|
+
(prefix2) => GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX[prefix2] === DEFAULT_GITHUB_ISSUE_TYPE
|
|
794
|
+
).sort().map((prefix2) => `\`${prefix2}\``).join(", ");
|
|
795
|
+
return [
|
|
796
|
+
"## GitHub Issue Type",
|
|
797
|
+
"",
|
|
798
|
+
"A GitHub **issue type** is a distinct field from the `type:*` **label**:",
|
|
799
|
+
"the label routes and dedups, the issue type drives triage and Epic",
|
|
800
|
+
"tracking. Setting one does not set the other. Derive it from the",
|
|
801
|
+
"**title prefix**:",
|
|
802
|
+
"",
|
|
803
|
+
"| Prefix | GitHub Issue Type |",
|
|
804
|
+
"|--------|------------------|",
|
|
805
|
+
"| `epic:` | Epic |",
|
|
806
|
+
"| `feat:` | Feature |",
|
|
807
|
+
"| `fix:` | Bug |",
|
|
808
|
+
`| ${defaultPrefixes} | ${DEFAULT_GITHUB_ISSUE_TYPE} |`,
|
|
809
|
+
"| any bundle-phase prefix (`company:`, `req:`, \u2026), or no prefix | Task |",
|
|
810
|
+
"",
|
|
811
|
+
"### Assigning the GitHub issue type",
|
|
812
|
+
"",
|
|
813
|
+
"`gh issue create` **cannot** set the issue type \u2014 there is no `--type`",
|
|
814
|
+
"flag \u2014 so assign it in a follow-up call immediately after creation, for",
|
|
815
|
+
"every issue an agent files (auto-enqueued downstream issues included).",
|
|
816
|
+
"An issue that skips that call stays untyped forever. The",
|
|
817
|
+
"`github-workflow` bundle ships a one-step helper:",
|
|
818
|
+
"",
|
|
819
|
+
"```bash",
|
|
820
|
+
`${SET_ISSUE_TYPE_HELPER_PATH} <issue-number> <${GITHUB_ISSUE_TYPES.join("|")}>`,
|
|
821
|
+
"```",
|
|
822
|
+
"",
|
|
823
|
+
"When that helper is absent (the bundle is excluded), run the",
|
|
824
|
+
"`updateIssueIssueType` GraphQL flow it wraps:",
|
|
825
|
+
"",
|
|
826
|
+
...renderSetIssueTypeFallbackLines()
|
|
827
|
+
];
|
|
828
|
+
}
|
|
829
|
+
function renderTitlePrefixTypeBullets(indent = " ") {
|
|
830
|
+
const nonDefault = Object.entries(NON_DEFAULT_TITLE_PREFIX_TYPES).map(
|
|
831
|
+
([prefix2, issueType]) => `${indent}- \`${prefix2}\` \u2192 ${issueType}`
|
|
832
|
+
);
|
|
833
|
+
const defaults = Object.keys(GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX).filter(
|
|
834
|
+
(prefix2) => GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX[prefix2] === DEFAULT_GITHUB_ISSUE_TYPE
|
|
835
|
+
).sort().map((prefix2) => `\`${prefix2}\``).join(", ");
|
|
836
|
+
return [
|
|
837
|
+
...nonDefault,
|
|
838
|
+
`${indent}- ${defaults} \u2192 ${DEFAULT_GITHUB_ISSUE_TYPE}`,
|
|
839
|
+
`${indent}- any bundle-phase prefix (\`company:\`, \`req:\`, \`bcm:\`, \u2026) \u2192 ${DEFAULT_GITHUB_ISSUE_TYPE}`
|
|
840
|
+
];
|
|
841
|
+
}
|
|
842
|
+
function renderGithubIssueTypeSection() {
|
|
843
|
+
return renderGithubIssueTypeSectionLines().join("\n");
|
|
844
|
+
}
|
|
845
|
+
function renderIssueTypeAssignmentStep(options = {}) {
|
|
846
|
+
const indent = options.indent ?? " ";
|
|
847
|
+
const issueType = options.issueType ?? DEFAULT_GITHUB_ISSUE_TYPE;
|
|
848
|
+
const lead = options.bullet ? `${indent}- ` : indent;
|
|
849
|
+
const cont = options.bullet ? `${indent} ` : indent;
|
|
850
|
+
return [
|
|
851
|
+
`${lead}Then assign the new issue's **GitHub issue type** (\`${issueType}\`) \u2014`,
|
|
852
|
+
`${cont}the \`type:*\` label does not set it:`,
|
|
853
|
+
`${cont}\`${SET_ISSUE_TYPE_HELPER_PATH} <issue-number> ${issueType}\`. See`,
|
|
854
|
+
`${cont}**Assigning the GitHub issue type** for the no-helper fallback.`
|
|
855
|
+
];
|
|
856
|
+
}
|
|
857
|
+
function renderIssueTypeAssignmentBlanket(indent = "", issueType = DEFAULT_GITHUB_ISSUE_TYPE) {
|
|
858
|
+
return [
|
|
859
|
+
`${indent}**Every** issue this phase files needs a **GitHub issue type**`,
|
|
860
|
+
`${indent}assigned right after creation \u2014 the \`type:*\` label does not set`,
|
|
861
|
+
`${indent}it, and \`gh issue create\` cannot:`,
|
|
862
|
+
`${indent}\`${SET_ISSUE_TYPE_HELPER_PATH} <issue-number> ${issueType}\`. See`,
|
|
863
|
+
`${indent}**Assigning the GitHub issue type** for the prefix table (nearly`,
|
|
864
|
+
`${indent}every downstream issue is a \`${issueType}\`) and the no-helper fallback.`
|
|
865
|
+
];
|
|
866
|
+
}
|
|
867
|
+
function buildTitlePrefixTypeMap() {
|
|
868
|
+
const map = {};
|
|
869
|
+
for (const label of CONVENTIONAL_COMMIT_TYPE_LABELS) {
|
|
870
|
+
map[`${label.slice("type:".length)}:`] = DEFAULT_GITHUB_ISSUE_TYPE;
|
|
871
|
+
}
|
|
872
|
+
for (const [prefix2, issueType] of Object.entries(
|
|
873
|
+
NON_DEFAULT_TITLE_PREFIX_TYPES
|
|
874
|
+
)) {
|
|
875
|
+
map[prefix2] = issueType;
|
|
876
|
+
}
|
|
877
|
+
return map;
|
|
878
|
+
}
|
|
879
|
+
|
|
283
880
|
// src/agent/bundles/project-context.ts
|
|
284
881
|
var PROJECT_CONTEXT_PATH = "docs/src/content/docs/project-context.md";
|
|
285
882
|
var SUBPROJECT_ROLE_GUIDANCE = [
|
|
@@ -872,6 +1469,9 @@ var draftAgendaSkill = {
|
|
|
872
1469
|
' - `desired_outcomes` \u2014 1\u20133 bullets describing "done"',
|
|
873
1470
|
" - `pre_reads` \u2014 relative paths to existing docs (optional)",
|
|
874
1471
|
" - `related_docs` \u2014 relative paths for context (optional)",
|
|
1472
|
+
"",
|
|
1473
|
+
...renderIssueTypeAssignmentStep(),
|
|
1474
|
+
"",
|
|
875
1475
|
"2. Execute Phase 1 (Draft) of the agenda-analyst agent.",
|
|
876
1476
|
"3. If the draft phase inline-finalizes (default path), no",
|
|
877
1477
|
" downstream issues are created.",
|
|
@@ -936,6 +1536,9 @@ var finalizeAgendaSkill = {
|
|
|
936
1536
|
" - Path to the draft agenda",
|
|
937
1537
|
" (`<meetingsRoot>/<YYYY-MM-DD>-<slug>/agenda.md`)",
|
|
938
1538
|
" - Any late-added items to incorporate",
|
|
1539
|
+
"",
|
|
1540
|
+
...renderIssueTypeAssignmentStep(),
|
|
1541
|
+
"",
|
|
939
1542
|
"2. Execute Phase 2 (Finalize) of the agenda-analyst agent.",
|
|
940
1543
|
"",
|
|
941
1544
|
"## Output",
|
|
@@ -1481,6 +2084,14 @@ function renderIssueTemplatesStarterPage(_it) {
|
|
|
1481
2084
|
"`status:*` label from the conventions documented in the",
|
|
1482
2085
|
"`issue-label-conventions` rule.",
|
|
1483
2086
|
"",
|
|
2087
|
+
"Every recipe also ends with a **GitHub issue type** assignment.",
|
|
2088
|
+
"`gh issue create` cannot set the issue type, so it takes a second",
|
|
2089
|
+
"call \u2014 an issue that skips it stays untyped forever. Derive the type",
|
|
2090
|
+
"from the title prefix (`epic:` \u2192 Epic, `feat:` \u2192 Feature, `fix:` \u2192",
|
|
2091
|
+
"Bug, everything else \u2014 including every bundle-phase prefix \u2014 \u2192",
|
|
2092
|
+
"Task); see **Assigning the GitHub issue type** in the",
|
|
2093
|
+
"`issue-conventions` rule for the command and its fallback.",
|
|
2094
|
+
"",
|
|
1484
2095
|
"Before creating any profile-style issue (people, companies,",
|
|
1485
2096
|
"software), run the duplicate check documented in the owning",
|
|
1486
2097
|
"bundle's rule \u2014 the issue-templates page is a recipe catalogue,",
|
|
@@ -1515,6 +2126,13 @@ function renderIssueTemplatesStarterPage(_it) {
|
|
|
1515
2126
|
"- [ ] <criterion 1>",
|
|
1516
2127
|
"- [ ] <criterion 2>",
|
|
1517
2128
|
'"',
|
|
2129
|
+
"```",
|
|
2130
|
+
"",
|
|
2131
|
+
"Then assign the GitHub issue type (`Task` for a phase-labelled",
|
|
2132
|
+
"title):",
|
|
2133
|
+
"",
|
|
2134
|
+
"```bash",
|
|
2135
|
+
`${SET_ISSUE_TYPE_HELPER_PATH} <issue-number> ${DEFAULT_GITHUB_ISSUE_TYPE}`,
|
|
1518
2136
|
"```"
|
|
1519
2137
|
].join("\n");
|
|
1520
2138
|
}
|
|
@@ -4619,16 +5237,7 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
4619
5237
|
"| `release:` | Release preparation, version bumps |",
|
|
4620
5238
|
"| `hotfix:` | Urgent production fixes |",
|
|
4621
5239
|
"",
|
|
4622
|
-
|
|
4623
|
-
"",
|
|
4624
|
-
"When creating issues, always assign the appropriate **GitHub issue type** based on the title prefix:",
|
|
4625
|
-
"",
|
|
4626
|
-
"| Prefix | GitHub Issue Type |",
|
|
4627
|
-
"|--------|------------------|",
|
|
4628
|
-
"| `epic:` | Epic |",
|
|
4629
|
-
"| `feat:` | Feature |",
|
|
4630
|
-
"| `fix:` | Bug |",
|
|
4631
|
-
"| `chore:`, `docs:`, `refactor:`, `release:`, `hotfix:` | Task |",
|
|
5240
|
+
...renderGithubIssueTypeSectionLines(),
|
|
4632
5241
|
"",
|
|
4633
5242
|
"## Prerequisite Issues",
|
|
4634
5243
|
"",
|
|
@@ -5318,6 +5927,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
|
|
|
5318
5927
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
5319
5928
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
5320
5929
|
"",
|
|
5930
|
+
...renderIssueTypeAssignmentStep(),
|
|
5931
|
+
"",
|
|
5321
5932
|
" **Unfamiliar company (enabling vendor, partner, competitor).**",
|
|
5322
5933
|
" Hand off to the `company-profile` bundle by creating a",
|
|
5323
5934
|
" `company:research` issue. The issue must carry:",
|
|
@@ -5327,6 +5938,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
|
|
|
5327
5938
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
5328
5939
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
5329
5940
|
"",
|
|
5941
|
+
...renderIssueTypeAssignmentStep(),
|
|
5942
|
+
"",
|
|
5330
5943
|
" **Missing research topic (value stream, market sizing, etc.).**",
|
|
5331
5944
|
" Hand off to the `research-pipeline` bundle by creating a",
|
|
5332
5945
|
" `research:scope` issue. The issue must carry:",
|
|
@@ -5336,6 +5949,8 @@ function buildBcmWriterSubAgent(paths, issueDefaults) {
|
|
|
5336
5949
|
` - \`priority:${labelsForPhase(issueDefaults, "research:scope").priority}\``,
|
|
5337
5950
|
` - \`status:${labelsForPhase(issueDefaults, "research:scope").status}\``,
|
|
5338
5951
|
"",
|
|
5952
|
+
...renderIssueTypeAssignmentStep(),
|
|
5953
|
+
"",
|
|
5339
5954
|
" This phase assumes the `people-profile`, `company-profile`, and",
|
|
5340
5955
|
" `research-pipeline` bundles are enabled in the consuming project.",
|
|
5341
5956
|
" If a bundle is not enabled, flag the connect issue with",
|
|
@@ -5458,6 +6073,8 @@ function buildWriteBcmSkill(paths, issueDefaults) {
|
|
|
5458
6073
|
` \`priority:${labelsForPhase(issueDefaults, "bcm:outline").priority}\`, and \`status:${labelsForPhase(issueDefaults, "bcm:outline").status}\`. Body must include the`,
|
|
5459
6074
|
" verbatim capability name and any overrides.",
|
|
5460
6075
|
"",
|
|
6076
|
+
"",
|
|
6077
|
+
...renderIssueTypeAssignmentStep(),
|
|
5461
6078
|
"2. Execute Phase 1 (Outline) of the bcm-writer agent.",
|
|
5462
6079
|
"",
|
|
5463
6080
|
"3. Phase 1 creates a `bcm:scaffold` issue, which Phase 2 follows with",
|
|
@@ -6744,6 +7361,8 @@ function buildScanBusinessModelsSkill(paths, issueDefaults) {
|
|
|
6744
7361
|
"1. Create a `business-models:scan` issue with `type:business-model`,",
|
|
6745
7362
|
` \`priority:${labelsForPhase(issueDefaults, "business-models:scan").priority}\`, and \`status:${labelsForPhase(issueDefaults, "business-models:scan").status}\`. The body must include the`,
|
|
6746
7363
|
" industry slug, the source plan path (if any), and any overrides.",
|
|
7364
|
+
"",
|
|
7365
|
+
...renderIssueTypeAssignmentStep(),
|
|
6747
7366
|
"2. Execute Phase 1 (Scan) of the business-models-analyst agent.",
|
|
6748
7367
|
"3. Phase 1 creates one `business-models:canvas` issue per in-scope",
|
|
6749
7368
|
" segment. Each canvas issue declares its `Depends on:`",
|
|
@@ -6818,6 +7437,8 @@ function buildCanvasBusinessModelSkill(paths, issueDefaults) {
|
|
|
6818
7437
|
` \`type:business-model\`, \`priority:${labelsForPhase(issueDefaults, "business-models:canvas").priority}\`, and \`status:${labelsForPhase(issueDefaults, "business-models:canvas").status}\`.`,
|
|
6819
7438
|
" The body must include the industry slug, segment slug, and any",
|
|
6820
7439
|
" scan-report reference.",
|
|
7440
|
+
"",
|
|
7441
|
+
...renderIssueTypeAssignmentStep(),
|
|
6821
7442
|
"2. Execute Phase 2 (Canvas) of the business-models-analyst agent.",
|
|
6822
7443
|
"3. Phase 2 writes the nine-block canvas and creates a",
|
|
6823
7444
|
" `business-models:complete` issue for the downstream Phase 3.",
|
|
@@ -6877,6 +7498,8 @@ function buildCompleteBusinessModelSkill(paths, issueDefaults) {
|
|
|
6877
7498
|
"1. Create a `business-models:complete` issue with",
|
|
6878
7499
|
` \`type:business-model\`, \`priority:${labelsForPhase(issueDefaults, "business-models:complete").priority}\`, and \`status:${labelsForPhase(issueDefaults, "business-models:complete").status}\`.`,
|
|
6879
7500
|
" Body must include the canvas document path.",
|
|
7501
|
+
"",
|
|
7502
|
+
...renderIssueTypeAssignmentStep(),
|
|
6880
7503
|
"2. Execute Phase 3 (Complete) of the business-models-analyst agent.",
|
|
6881
7504
|
"",
|
|
6882
7505
|
"## Output",
|
|
@@ -7401,6 +8024,8 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
7401
8024
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
7402
8025
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
7403
8026
|
"",
|
|
8027
|
+
...renderIssueTypeAssignmentStep(),
|
|
8028
|
+
"",
|
|
7404
8029
|
" The issue body must include:",
|
|
7405
8030
|
" - A **discovery source** line naming this company profile",
|
|
7406
8031
|
" (`Discovered while profiling: <company name>`)",
|
|
@@ -7418,6 +8043,8 @@ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
7418
8043
|
` - \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\``,
|
|
7419
8044
|
` - \`status:${labelsForPhase(issueDefaults, "software:research").status}\``,
|
|
7420
8045
|
"",
|
|
8046
|
+
...renderIssueTypeAssignmentStep(),
|
|
8047
|
+
"",
|
|
7421
8048
|
" The issue body must include:",
|
|
7422
8049
|
" - A **discovery source** line naming this company profile",
|
|
7423
8050
|
" (`Discovered while profiling: <company name>`)",
|
|
@@ -7969,6 +8596,8 @@ function buildProfileCompanySkill(paths, issueDefaults) {
|
|
|
7969
8596
|
"1. Create a `company:research` issue with `type:company-profile`,",
|
|
7970
8597
|
` \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:research").status}\`. Body must include the`,
|
|
7971
8598
|
" company name, selected type, framing, and any overrides.",
|
|
8599
|
+
"",
|
|
8600
|
+
...renderIssueTypeAssignmentStep(),
|
|
7972
8601
|
"2. Execute Phase 1 (Research) of the company-profile-analyst agent.",
|
|
7973
8602
|
"3. Phase 1 creates the `company:draft` issue. Phase 2 may create a",
|
|
7974
8603
|
" `company:followup` issue **and** a `company:match` issue. Each",
|
|
@@ -8043,6 +8672,8 @@ function buildMatchCompanySkill(paths, issueDefaults) {
|
|
|
8043
8672
|
"1. Create a `company:match` issue with `type:company-profile`,",
|
|
8044
8673
|
` \`priority:${labelsForPhase(issueDefaults, "company:match").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:match").status}\`. Body must include the`,
|
|
8045
8674
|
" profile path and any overrides.",
|
|
8675
|
+
"",
|
|
8676
|
+
...renderIssueTypeAssignmentStep(),
|
|
8046
8677
|
"2. Execute Phase 4 (Match) of the company-profile-analyst agent.",
|
|
8047
8678
|
"",
|
|
8048
8679
|
"## Output",
|
|
@@ -8116,6 +8747,8 @@ function buildRefreshCompanySkill(paths, issueDefaults) {
|
|
|
8116
8747
|
"1. Create a `company:refresh` issue with `type:company-profile`,",
|
|
8117
8748
|
` \`priority:${labelsForPhase(issueDefaults, "company:refresh").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:refresh").status}\`. Body must include the`,
|
|
8118
8749
|
" profile path and any overrides.",
|
|
8750
|
+
"",
|
|
8751
|
+
...renderIssueTypeAssignmentStep(),
|
|
8119
8752
|
"2. Execute Phase 5 (Refresh) of the company-profile-analyst agent.",
|
|
8120
8753
|
"",
|
|
8121
8754
|
"## Output",
|
|
@@ -8189,6 +8822,8 @@ function buildAnalyzeSegmentSkill(paths, issueDefaults) {
|
|
|
8189
8822
|
"1. Create a `company:analyze` issue with `type:company-profile`,",
|
|
8190
8823
|
` \`priority:${labelsForPhase(issueDefaults, "company:analyze").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:analyze").status}\`. Body must include the`,
|
|
8191
8824
|
" segment slug and any overrides.",
|
|
8825
|
+
"",
|
|
8826
|
+
...renderIssueTypeAssignmentStep(),
|
|
8192
8827
|
"2. Execute Phase 6 (Analyze) of the company-profile-analyst agent.",
|
|
8193
8828
|
"",
|
|
8194
8829
|
"## Output",
|
|
@@ -8777,6 +9412,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
8777
9412
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
8778
9413
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
8779
9414
|
"",
|
|
9415
|
+
...renderIssueTypeAssignmentStep(),
|
|
9416
|
+
"",
|
|
8780
9417
|
"9. **Create `people:research` issues** for notable contacts",
|
|
8781
9418
|
" (economic buyers, technical buyers, user champions) surfaced in",
|
|
8782
9419
|
" sources. Keep the list small \u2014 at most three individuals per",
|
|
@@ -8788,6 +9425,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
8788
9425
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
8789
9426
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
8790
9427
|
"",
|
|
9428
|
+
...renderIssueTypeAssignmentStep(),
|
|
9429
|
+
"",
|
|
8791
9430
|
"10. **Verify all handoffs were created** before committing.",
|
|
8792
9431
|
"",
|
|
8793
9432
|
"11. **Commit and push** the archetype page. Close the profile issue.",
|
|
@@ -8889,6 +9528,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
8889
9528
|
` - \`priority:${labelsForPhase(issueDefaults, "req:scan").priority}\``,
|
|
8890
9529
|
` - \`status:${labelsForPhase(issueDefaults, "req:scan").status}\``,
|
|
8891
9530
|
"",
|
|
9531
|
+
...renderIssueTypeAssignmentStep(),
|
|
9532
|
+
"",
|
|
8892
9533
|
" The body must also:",
|
|
8893
9534
|
" - Link back to the archetype page and the competitor page",
|
|
8894
9535
|
" - Cite the specific unmet-need row and the originating job",
|
|
@@ -8905,6 +9546,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
8905
9546
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
8906
9547
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
8907
9548
|
"",
|
|
9549
|
+
...renderIssueTypeAssignmentStep(),
|
|
9550
|
+
"",
|
|
8908
9551
|
"9. **Create `people:research` issues** for notable competitor",
|
|
8909
9552
|
" leadership or customer-advocacy figures surfaced in the analysis.",
|
|
8910
9553
|
" Keep this list small \u2014 at most three individuals per competitors",
|
|
@@ -8916,6 +9559,8 @@ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
8916
9559
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
8917
9560
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
8918
9561
|
"",
|
|
9562
|
+
...renderIssueTypeAssignmentStep(),
|
|
9563
|
+
"",
|
|
8919
9564
|
"10. **Commit and push** the competitor-analysis page and the",
|
|
8920
9565
|
" updated archetype page. Close the competitors issue.",
|
|
8921
9566
|
"",
|
|
@@ -9102,6 +9747,8 @@ function buildDiscoverCustomersSkill(paths, issueDefaults) {
|
|
|
9102
9747
|
"1. Create a `customer:discover` issue with `type:customer-profile`,",
|
|
9103
9748
|
` \`priority:${labelsForPhase(issueDefaults, "customer:discover").priority}\`, and \`status:${labelsForPhase(issueDefaults, "customer:discover").status}\`. The body must include the`,
|
|
9104
9749
|
" scope slug and any known archetypes to include or exclude.",
|
|
9750
|
+
"",
|
|
9751
|
+
...renderIssueTypeAssignmentStep(),
|
|
9105
9752
|
"2. Execute Phase 1 (Discover) of the customer-profile-analyst agent.",
|
|
9106
9753
|
"3. Phase 1 writes the discovery report and creates one",
|
|
9107
9754
|
" `customer:profile` issue per prioritized archetype.",
|
|
@@ -9177,6 +9824,8 @@ function buildProfileCustomerSkill(paths, issueDefaults) {
|
|
|
9177
9824
|
"1. Create a `customer:profile` issue with `type:customer-profile`,",
|
|
9178
9825
|
` \`priority:${labelsForPhase(issueDefaults, "customer:profile").priority}\`, and \`status:${labelsForPhase(issueDefaults, "customer:profile").status}\`. The body must include the`,
|
|
9179
9826
|
" archetype slug and (optionally) the segment slug.",
|
|
9827
|
+
"",
|
|
9828
|
+
...renderIssueTypeAssignmentStep(),
|
|
9180
9829
|
"2. Execute Phase 2 (Profile) of the customer-profile-analyst agent.",
|
|
9181
9830
|
" The agent runs 4\u20138 targeted web searches and populates the",
|
|
9182
9831
|
" archetype page.",
|
|
@@ -9253,6 +9902,8 @@ function buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults) {
|
|
|
9253
9902
|
` \`status:${labelsForPhase(issueDefaults, "customer:competitors").status}\` (or \`status:blocked\` when still dependent on a`,
|
|
9254
9903
|
" Phase 2 profile issue). Body must include the archetype page",
|
|
9255
9904
|
" path.",
|
|
9905
|
+
"",
|
|
9906
|
+
...renderIssueTypeAssignmentStep(),
|
|
9256
9907
|
"2. Execute Phase 3 (Competitors) of the customer-profile-analyst",
|
|
9257
9908
|
" agent. The agent reads `<MATRIX_FILE>` and runs up to 4\u20138 web",
|
|
9258
9909
|
" searches only to close competitor-coverage gaps the matrix does",
|
|
@@ -10962,10 +11613,7 @@ function buildGithubWorkflowBundle(buildPolicy = DEFAULT_BUILD_POLICY) {
|
|
|
10962
11613
|
" - If unclear, ask the user which type applies",
|
|
10963
11614
|
"2. **Compose the issue title** in the format: `<type>: <short description>`",
|
|
10964
11615
|
"3. **Determine the GitHub issue type** based on the prefix:",
|
|
10965
|
-
|
|
10966
|
-
" - `feat:` \u2192 Feature",
|
|
10967
|
-
" - `fix:` \u2192 Bug",
|
|
10968
|
-
" - `chore:`, `docs:`, `refactor:`, `release:`, `hotfix:` \u2192 Task",
|
|
11616
|
+
...renderTitlePrefixTypeBullets(),
|
|
10969
11617
|
"4. **Identify prerequisite issues** \u2014 if the user mentions dependencies or blockers, include a **Dependencies** section in the body with `Depends on: #<issue-number>`",
|
|
10970
11618
|
"5. **Determine labels** \u2014 every issue must be created with the following labels:",
|
|
10971
11619
|
" - **`type:*`** \u2014 derived from the issue title prefix:",
|
|
@@ -11451,6 +12099,7 @@ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
|
|
|
11451
12099
|
" downstream research needs to answer)",
|
|
11452
12100
|
" - Cite the evaluation row that justified advancing the vertical",
|
|
11453
12101
|
" - Reference the plan file path for traceability",
|
|
12102
|
+
...renderIssueTypeAssignmentStep({ indent: " ", bullet: true }),
|
|
11454
12103
|
"",
|
|
11455
12104
|
"5. **Cross-link** \u2014 update the plan file's `## Cleared Verticals`",
|
|
11456
12105
|
" table so each row references its newly-created `research:scope`",
|
|
@@ -11541,6 +12190,8 @@ function buildDiscoverIndustriesSkill(paths, issueDefaults) {
|
|
|
11541
12190
|
"1. Create an `industry:discover` issue with `type:industry-discovery`,",
|
|
11542
12191
|
` \`priority:${labelsForPhase(issueDefaults, "industry:discover").priority}\`, and \`status:${labelsForPhase(issueDefaults, "industry:discover").status}\`. Body must include the`,
|
|
11543
12192
|
" verbatim scope, authorized sources, and any overrides.",
|
|
12193
|
+
"",
|
|
12194
|
+
...renderIssueTypeAssignmentStep(),
|
|
11544
12195
|
"2. Execute Phase 1 (Discover) of the industry-discovery-analyst",
|
|
11545
12196
|
" agent.",
|
|
11546
12197
|
"3. Phase 1 creates an `industry:evaluate` issue, which Phase 2 follows",
|
|
@@ -11819,6 +12470,8 @@ function buildMaintenanceAuditSubAgent(paths, tier) {
|
|
|
11819
12470
|
"4. Commit, push, open a PR (if applicable), and close the issue per",
|
|
11820
12471
|
" your project's PR workflow.",
|
|
11821
12472
|
"",
|
|
12473
|
+
...renderIssueTypeAssignmentBlanket(),
|
|
12474
|
+
"",
|
|
11822
12475
|
"---",
|
|
11823
12476
|
"",
|
|
11824
12477
|
...renderClaimVerificationSection(),
|
|
@@ -12251,6 +12904,8 @@ function buildMaintenanceAuditSkill(paths, issueDefaults) {
|
|
|
12251
12904
|
" - `<AUDIT_ROOT>` \u2014 where to write the audit report",
|
|
12252
12905
|
" - `<AUDIT_SLUG>` \u2014 short identifier for this audit",
|
|
12253
12906
|
" - The audit checks to run (defaults to the full check catalog)",
|
|
12907
|
+
"",
|
|
12908
|
+
...renderIssueTypeAssignmentStep(),
|
|
12254
12909
|
"2. Execute Phase 1 (Scan) of the maintenance-audit agent.",
|
|
12255
12910
|
"3. If auto-fixable findings exist, a `maint:fix` issue is created",
|
|
12256
12911
|
" automatically.",
|
|
@@ -12315,6 +12970,8 @@ function buildMaintenanceVerifySkill(issueDefaults) {
|
|
|
12315
12970
|
" - The Phase 2 fix report path (if one exists)",
|
|
12316
12971
|
" - The `Paths Touched` list (copied from the fix report)",
|
|
12317
12972
|
" - The audit check catalog (copied from the scan issue)",
|
|
12973
|
+
"",
|
|
12974
|
+
...renderIssueTypeAssignmentStep(),
|
|
12318
12975
|
"2. Execute Phase 3 (Verify) of the maintenance-audit agent.",
|
|
12319
12976
|
"",
|
|
12320
12977
|
"## Output",
|
|
@@ -12824,6 +13481,8 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
12824
13481
|
" - Always create a `meeting:link` issue \u2014 blocked on the draft issue if one",
|
|
12825
13482
|
" was created, otherwise blocked on the notes issue",
|
|
12826
13483
|
"",
|
|
13484
|
+
...renderIssueTypeAssignmentStep(),
|
|
13485
|
+
"",
|
|
12827
13486
|
"7. **Commit the extraction content first.** Stage and commit",
|
|
12828
13487
|
" the `insights/{type}/<basename>.md` file (and any newly",
|
|
12829
13488
|
" created `insights/index.md` / `insights/{type}/index.md`",
|
|
@@ -13023,6 +13682,8 @@ function buildMeetingAnalystSubAgent(tier) {
|
|
|
13023
13682
|
"",
|
|
13024
13683
|
"### Steps",
|
|
13025
13684
|
"",
|
|
13685
|
+
...renderIssueTypeAssignmentBlanket(),
|
|
13686
|
+
"",
|
|
13026
13687
|
"1. Read the drafts from Phase 3 (if they exist) and the extraction",
|
|
13027
13688
|
" from Phase 1 at `<meetingsRoot>/insights/{type}/<basename>.md`.",
|
|
13028
13689
|
" Re-read the extraction frontmatter for `meeting_kind` and `areas`,",
|
|
@@ -13185,6 +13846,8 @@ var processMeetingSkill = {
|
|
|
13185
13846
|
" - `meeting:notes` issue (always)",
|
|
13186
13847
|
" - `meeting:draft` issue (if requirements or decisions were found)",
|
|
13187
13848
|
" - `meeting:link` issue (always)",
|
|
13849
|
+
"",
|
|
13850
|
+
...renderIssueTypeAssignmentStep(),
|
|
13188
13851
|
"5. Each downstream issue includes `Depends on:` linking to its predecessor",
|
|
13189
13852
|
"6. Commit and push the extraction file",
|
|
13190
13853
|
"",
|
|
@@ -13482,238 +14145,6 @@ function assertValidStateFilePath(stateFilePath) {
|
|
|
13482
14145
|
}
|
|
13483
14146
|
}
|
|
13484
14147
|
|
|
13485
|
-
// src/agent/bundles/bundle-ownership.ts
|
|
13486
|
-
var BUNDLE_OWNERSHIP = {
|
|
13487
|
-
agenda: {
|
|
13488
|
-
typeLabels: ["agenda"],
|
|
13489
|
-
phaseLabelPrefixes: ["agenda:"],
|
|
13490
|
-
scheduledTaskIds: ["worker-agenda"],
|
|
13491
|
-
emitsDocs: true,
|
|
13492
|
-
downstreamIssueKinds: true
|
|
13493
|
-
},
|
|
13494
|
-
"bcm-writer": {
|
|
13495
|
-
typeLabels: ["bcm-document"],
|
|
13496
|
-
phaseLabelPrefixes: ["bcm:"],
|
|
13497
|
-
scheduledTaskIds: ["worker-bcm-writer"],
|
|
13498
|
-
emitsDocs: true,
|
|
13499
|
-
downstreamIssueKinds: true
|
|
13500
|
-
},
|
|
13501
|
-
"business-models": {
|
|
13502
|
-
typeLabels: ["business-model"],
|
|
13503
|
-
phaseLabelPrefixes: ["business-models:"],
|
|
13504
|
-
scheduledTaskIds: ["worker-business-models"],
|
|
13505
|
-
emitsDocs: true,
|
|
13506
|
-
downstreamIssueKinds: true
|
|
13507
|
-
},
|
|
13508
|
-
"company-profile": {
|
|
13509
|
-
typeLabels: ["company-profile"],
|
|
13510
|
-
phaseLabelPrefixes: ["company:"],
|
|
13511
|
-
scheduledTaskIds: ["worker-company-profile"],
|
|
13512
|
-
emitsDocs: true,
|
|
13513
|
-
downstreamIssueKinds: true
|
|
13514
|
-
},
|
|
13515
|
-
"customer-profile": {
|
|
13516
|
-
typeLabels: ["customer-profile"],
|
|
13517
|
-
phaseLabelPrefixes: ["customer:"],
|
|
13518
|
-
scheduledTaskIds: ["worker-customer-profile"],
|
|
13519
|
-
emitsDocs: true,
|
|
13520
|
-
downstreamIssueKinds: true
|
|
13521
|
-
},
|
|
13522
|
-
"docs-sync": {
|
|
13523
|
-
typeLabels: ["docs-sync"],
|
|
13524
|
-
phaseLabelPrefixes: ["docs-sync:"],
|
|
13525
|
-
scheduledTaskIds: ["worker-docs-sync"],
|
|
13526
|
-
emitsDocs: true,
|
|
13527
|
-
downstreamIssueKinds: true
|
|
13528
|
-
},
|
|
13529
|
-
"industry-discovery": {
|
|
13530
|
-
typeLabels: ["industry-discovery"],
|
|
13531
|
-
phaseLabelPrefixes: ["industry:"],
|
|
13532
|
-
scheduledTaskIds: ["worker-industry-discovery"],
|
|
13533
|
-
emitsDocs: true,
|
|
13534
|
-
downstreamIssueKinds: true
|
|
13535
|
-
},
|
|
13536
|
-
"maintenance-audit": {
|
|
13537
|
-
typeLabels: ["maintenance"],
|
|
13538
|
-
phaseLabelPrefixes: ["maint:"],
|
|
13539
|
-
scheduledTaskIds: ["worker-maintenance"],
|
|
13540
|
-
emitsDocs: false,
|
|
13541
|
-
downstreamIssueKinds: true
|
|
13542
|
-
},
|
|
13543
|
-
"meeting-analysis": {
|
|
13544
|
-
typeLabels: ["meeting-processing"],
|
|
13545
|
-
phaseLabelPrefixes: ["meeting:"],
|
|
13546
|
-
scheduledTaskIds: ["worker-meeting-analysis"],
|
|
13547
|
-
emitsDocs: true,
|
|
13548
|
-
downstreamIssueKinds: true
|
|
13549
|
-
},
|
|
13550
|
-
orchestrator: {
|
|
13551
|
-
// The orchestrator pipeline manager itself ships with the
|
|
13552
|
-
// `worker-orchestrator` scheduled task. It owns no `type:*` label
|
|
13553
|
-
// (it dispatches every type) and no phase-label prefix.
|
|
13554
|
-
typeLabels: [],
|
|
13555
|
-
phaseLabelPrefixes: [],
|
|
13556
|
-
scheduledTaskIds: ["worker-orchestrator"],
|
|
13557
|
-
emitsDocs: false,
|
|
13558
|
-
downstreamIssueKinds: false
|
|
13559
|
-
},
|
|
13560
|
-
"people-profile": {
|
|
13561
|
-
typeLabels: ["people-profile"],
|
|
13562
|
-
phaseLabelPrefixes: ["people:"],
|
|
13563
|
-
scheduledTaskIds: ["worker-people-profile"],
|
|
13564
|
-
emitsDocs: true,
|
|
13565
|
-
downstreamIssueKinds: true
|
|
13566
|
-
},
|
|
13567
|
-
"pr-review": {
|
|
13568
|
-
typeLabels: ["pr-review"],
|
|
13569
|
-
phaseLabelPrefixes: [],
|
|
13570
|
-
scheduledTaskIds: ["worker-pr-review"],
|
|
13571
|
-
emitsDocs: false,
|
|
13572
|
-
downstreamIssueKinds: false
|
|
13573
|
-
},
|
|
13574
|
-
"regulatory-research": {
|
|
13575
|
-
typeLabels: ["regulatory-research"],
|
|
13576
|
-
phaseLabelPrefixes: ["regulatory:"],
|
|
13577
|
-
scheduledTaskIds: ["worker-regulatory-research"],
|
|
13578
|
-
emitsDocs: true,
|
|
13579
|
-
downstreamIssueKinds: true
|
|
13580
|
-
},
|
|
13581
|
-
"requirements-analyst": {
|
|
13582
|
-
typeLabels: ["requirement"],
|
|
13583
|
-
phaseLabelPrefixes: ["req:"],
|
|
13584
|
-
scheduledTaskIds: ["worker-requirements-analyst"],
|
|
13585
|
-
emitsDocs: true,
|
|
13586
|
-
downstreamIssueKinds: true
|
|
13587
|
-
},
|
|
13588
|
-
"requirements-reviewer": {
|
|
13589
|
-
// Co-owns `type:requirement` with the analyst and writer; owns
|
|
13590
|
-
// the `req:review` and `req:deprecate` phase labels exactly.
|
|
13591
|
-
typeLabels: ["requirement"],
|
|
13592
|
-
phaseLabelPrefixes: ["req:review", "req:deprecate"],
|
|
13593
|
-
scheduledTaskIds: ["worker-requirements-reviewer"],
|
|
13594
|
-
emitsDocs: true,
|
|
13595
|
-
downstreamIssueKinds: true
|
|
13596
|
-
},
|
|
13597
|
-
"requirements-writer": {
|
|
13598
|
-
// Co-owns `type:requirement` with the analyst and reviewer; owns
|
|
13599
|
-
// the `req:write` phase label exactly.
|
|
13600
|
-
typeLabels: ["requirement"],
|
|
13601
|
-
phaseLabelPrefixes: ["req:write"],
|
|
13602
|
-
scheduledTaskIds: ["worker-requirements-writer"],
|
|
13603
|
-
emitsDocs: true,
|
|
13604
|
-
downstreamIssueKinds: true
|
|
13605
|
-
},
|
|
13606
|
-
"research-pipeline": {
|
|
13607
|
-
typeLabels: ["research"],
|
|
13608
|
-
phaseLabelPrefixes: ["research:"],
|
|
13609
|
-
scheduledTaskIds: ["worker-research"],
|
|
13610
|
-
emitsDocs: true,
|
|
13611
|
-
downstreamIssueKinds: true
|
|
13612
|
-
},
|
|
13613
|
-
"software-profile": {
|
|
13614
|
-
typeLabels: ["software-profile"],
|
|
13615
|
-
phaseLabelPrefixes: ["software:"],
|
|
13616
|
-
scheduledTaskIds: ["worker-software-profile"],
|
|
13617
|
-
emitsDocs: true,
|
|
13618
|
-
downstreamIssueKinds: true
|
|
13619
|
-
},
|
|
13620
|
-
"standards-research": {
|
|
13621
|
-
typeLabels: ["standards-research"],
|
|
13622
|
-
phaseLabelPrefixes: ["standards:"],
|
|
13623
|
-
scheduledTaskIds: ["worker-standards-research"],
|
|
13624
|
-
emitsDocs: true,
|
|
13625
|
-
downstreamIssueKinds: true
|
|
13626
|
-
}
|
|
13627
|
-
};
|
|
13628
|
-
function isTypeLabelOwnedByExcluded(typeLabel, excludedBundles) {
|
|
13629
|
-
if (excludedBundles.length === 0) {
|
|
13630
|
-
return false;
|
|
13631
|
-
}
|
|
13632
|
-
for (const bundleName of excludedBundles) {
|
|
13633
|
-
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
13634
|
-
if (!ownership) {
|
|
13635
|
-
continue;
|
|
13636
|
-
}
|
|
13637
|
-
if (ownership.typeLabels.includes(typeLabel)) {
|
|
13638
|
-
const owners = findOwnersOfTypeLabel(typeLabel);
|
|
13639
|
-
const allExcluded = owners.every(
|
|
13640
|
-
(owner) => excludedBundles.includes(owner)
|
|
13641
|
-
);
|
|
13642
|
-
if (allExcluded) {
|
|
13643
|
-
return true;
|
|
13644
|
-
}
|
|
13645
|
-
}
|
|
13646
|
-
}
|
|
13647
|
-
return false;
|
|
13648
|
-
}
|
|
13649
|
-
function isPhaseLabelOwnedByExcluded(phaseLabel, excludedBundles) {
|
|
13650
|
-
if (excludedBundles.length === 0) {
|
|
13651
|
-
return false;
|
|
13652
|
-
}
|
|
13653
|
-
for (const bundleName of excludedBundles) {
|
|
13654
|
-
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
13655
|
-
if (!ownership) {
|
|
13656
|
-
continue;
|
|
13657
|
-
}
|
|
13658
|
-
for (const entry of ownership.phaseLabelPrefixes) {
|
|
13659
|
-
if (entry.endsWith(":")) {
|
|
13660
|
-
if (phaseLabel.startsWith(entry)) {
|
|
13661
|
-
return true;
|
|
13662
|
-
}
|
|
13663
|
-
} else if (phaseLabel === entry) {
|
|
13664
|
-
return true;
|
|
13665
|
-
}
|
|
13666
|
-
}
|
|
13667
|
-
}
|
|
13668
|
-
return false;
|
|
13669
|
-
}
|
|
13670
|
-
function isScheduledTaskOwnedByExcluded(taskId, excludedBundles) {
|
|
13671
|
-
if (excludedBundles.length === 0) {
|
|
13672
|
-
return false;
|
|
13673
|
-
}
|
|
13674
|
-
for (const bundleName of excludedBundles) {
|
|
13675
|
-
const ownership = BUNDLE_OWNERSHIP[bundleName];
|
|
13676
|
-
if (!ownership) {
|
|
13677
|
-
continue;
|
|
13678
|
-
}
|
|
13679
|
-
if (ownership.scheduledTaskIds.includes(taskId)) {
|
|
13680
|
-
return true;
|
|
13681
|
-
}
|
|
13682
|
-
}
|
|
13683
|
-
return false;
|
|
13684
|
-
}
|
|
13685
|
-
function hasAnyDocsEmittingBundle(excludedBundles) {
|
|
13686
|
-
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
13687
|
-
if (!ownership.emitsDocs) {
|
|
13688
|
-
continue;
|
|
13689
|
-
}
|
|
13690
|
-
if (!excludedBundles.includes(bundleName)) {
|
|
13691
|
-
return true;
|
|
13692
|
-
}
|
|
13693
|
-
}
|
|
13694
|
-
return false;
|
|
13695
|
-
}
|
|
13696
|
-
function hasAnyDownstreamIssueKindBundle(excludedBundles) {
|
|
13697
|
-
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
13698
|
-
if (!ownership.downstreamIssueKinds) {
|
|
13699
|
-
continue;
|
|
13700
|
-
}
|
|
13701
|
-
if (!excludedBundles.includes(bundleName)) {
|
|
13702
|
-
return true;
|
|
13703
|
-
}
|
|
13704
|
-
}
|
|
13705
|
-
return false;
|
|
13706
|
-
}
|
|
13707
|
-
function findOwnersOfTypeLabel(typeLabel) {
|
|
13708
|
-
const owners = [];
|
|
13709
|
-
for (const [bundleName, ownership] of Object.entries(BUNDLE_OWNERSHIP)) {
|
|
13710
|
-
if (ownership.typeLabels.includes(typeLabel)) {
|
|
13711
|
-
owners.push(bundleName);
|
|
13712
|
-
}
|
|
13713
|
-
}
|
|
13714
|
-
return owners;
|
|
13715
|
-
}
|
|
13716
|
-
|
|
13717
14148
|
// src/agent/bundles/scheduled-tasks.ts
|
|
13718
14149
|
var SCHEDULED_TASK_MODEL_VALUES = ["opus", "sonnet", "haiku"];
|
|
13719
14150
|
var SCHEDULED_TASK_KIND_VALUES = ["issue-worker", "pipeline"];
|
|
@@ -15669,6 +16100,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15669
16100
|
"# .claude/procedures/check-blocked.sh maintenance",
|
|
15670
16101
|
"# .claude/procedures/check-blocked.sh prs",
|
|
15671
16102
|
"# .claude/procedures/check-blocked.sh scope <issue-number>",
|
|
16103
|
+
"# .claude/procedures/check-blocked.sh label-invariant [--fix]",
|
|
15672
16104
|
"",
|
|
15673
16105
|
"set -uo pipefail",
|
|
15674
16106
|
"",
|
|
@@ -15718,6 +16150,8 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
15718
16150
|
"",
|
|
15719
16151
|
scopeHelperIndented,
|
|
15720
16152
|
"",
|
|
16153
|
+
renderPhaseTypeInvariantShellHelpers(),
|
|
16154
|
+
"",
|
|
15721
16155
|
...renderDelegationActiveSignalsHelper(),
|
|
15722
16156
|
"",
|
|
15723
16157
|
"# \u2500\u2500 subcommands \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
@@ -16353,16 +16787,43 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
16353
16787
|
" esac",
|
|
16354
16788
|
' done <<< "$lease_output"',
|
|
16355
16789
|
"",
|
|
16790
|
+
" # \u2500\u2500 phase-label \u2192 type:<bundle> invariant (MUTATING) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
16791
|
+
" # Run the label-invariant sweep in --fix mode and surface its",
|
|
16792
|
+
" # per-issue lines for log visibility. cmd_label_invariant applies",
|
|
16793
|
+
" # the label edits itself (a single atomic remove+add per issue, so",
|
|
16794
|
+
" # an issue is never observable carrying two type:* labels) and",
|
|
16795
|
+
" # flags the cases it must not guess at. Its terminal",
|
|
16796
|
+
" # LABEL_INVARIANT_DONE line is captured and re-emitted alongside",
|
|
16797
|
+
" # MAINTENANCE_DONE so the orchestrator reads every summary from",
|
|
16798
|
+
" # one maintenance invocation.",
|
|
16799
|
+
" local label_output",
|
|
16800
|
+
" label_output=$(cmd_label_invariant --fix)",
|
|
16801
|
+
' local label_summary="LABEL_INVARIANT_DONE mode=fix checked=0 ok=0 violations=0 corrected=0 flagged=0"',
|
|
16802
|
+
"",
|
|
16803
|
+
" while IFS= read -r line; do",
|
|
16804
|
+
' [[ -z "$line" ]] && continue',
|
|
16805
|
+
' case "$line" in',
|
|
16806
|
+
" 'LABEL_INVARIANT_DONE '*)",
|
|
16807
|
+
' label_summary="$line"',
|
|
16808
|
+
" ;;",
|
|
16809
|
+
" *)",
|
|
16810
|
+
' echo "$line"',
|
|
16811
|
+
" ;;",
|
|
16812
|
+
" esac",
|
|
16813
|
+
' done <<< "$label_output"',
|
|
16814
|
+
"",
|
|
16356
16815
|
" # \u2500\u2500 needs-attention total \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
16357
16816
|
" local needs_attention_total",
|
|
16358
16817
|
' needs_attention_total=$(gh issue list --label "status:needs-attention" --state open \\',
|
|
16359
16818
|
" --json number --limit 100 2>/dev/null | jq 'length' 2>/dev/null || echo 0)",
|
|
16360
16819
|
" needs_attention_total=${needs_attention_total:-0}",
|
|
16361
16820
|
"",
|
|
16362
|
-
" #
|
|
16363
|
-
" # MAINTENANCE_DONE line
|
|
16821
|
+
" # Three summary lines consumed by the orchestrator: the",
|
|
16822
|
+
" # issue/orphan MAINTENANCE_DONE line, the PR-lease LEASE_RECONCILE",
|
|
16823
|
+
" # line, and the LABEL_INVARIANT_DONE line.",
|
|
16364
16824
|
' echo "MAINTENANCE_DONE flagged_stale=${flagged_stale_count} flagged_blocked=${flagged_blocked_count} orphan_branches=${orphan_branches_count} orphan_prs=${orphan_prs_count} needs_attention_total=${needs_attention_total}"',
|
|
16365
16825
|
' echo "$lease_summary"',
|
|
16826
|
+
' echo "$label_summary"',
|
|
16366
16827
|
"}",
|
|
16367
16828
|
"",
|
|
16368
16829
|
"cmd_prs() {",
|
|
@@ -16428,6 +16889,196 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
16428
16889
|
' done <<< "$eligible"',
|
|
16429
16890
|
"}",
|
|
16430
16891
|
"",
|
|
16892
|
+
"cmd_label_invariant() {",
|
|
16893
|
+
" # Phase-label \u2192 type:<bundle> invariant sweep.",
|
|
16894
|
+
" #",
|
|
16895
|
+
" # Every phased-pipeline bundle pairs its <bundle>:<phase> labels",
|
|
16896
|
+
" # with exactly one type:<bundle> label. An agent that reconstructs",
|
|
16897
|
+
" # a gh issue create call from prose can stamp a conventional-commit",
|
|
16898
|
+
" # type label derived from the title prefix instead, producing an",
|
|
16899
|
+
" # issue that carries the phase label but the WRONG type label \u2014",
|
|
16900
|
+
" # invisible to the --label type:<bundle> duplicate-check idiom and",
|
|
16901
|
+
" # mis-tiered by the funnel-tier sort in cmd_eligible.",
|
|
16902
|
+
" #",
|
|
16903
|
+
" # Default mode is REPORT-ONLY (the consumer-runnable audit); pass",
|
|
16904
|
+
" # --fix to apply corrections. cmd_maintenance runs the --fix mode",
|
|
16905
|
+
" # as part of the Phase D sweep.",
|
|
16906
|
+
" #",
|
|
16907
|
+
" # CORRECTION POLICY. An issue must carry EXACTLY ONE type:* label",
|
|
16908
|
+
" # (cmd_eligible derives its funnel-tier sort key from the FIRST",
|
|
16909
|
+
" # one, and the label conventions mandate exactly one), so the",
|
|
16910
|
+
" # correction REPLACES rather than merely adds:",
|
|
16911
|
+
" #",
|
|
16912
|
+
" # no type:* at all \u2192 add the implied type label",
|
|
16913
|
+
" # only conventional-commit \u2192 remove them, add the implied",
|
|
16914
|
+
" # type labels present label (single atomic edit)",
|
|
16915
|
+
" # implied label already there \u2192 remove the stray conventional",
|
|
16916
|
+
" # alongside a conventional one label, leaving exactly one",
|
|
16917
|
+
" # a type:* owned by ANOTHER \u2192 FLAG status:needs-attention;",
|
|
16918
|
+
" # bundle never guess which to drop",
|
|
16919
|
+
" # phase labels imply 2+ types \u2192 FLAG status:needs-attention",
|
|
16920
|
+
" #",
|
|
16921
|
+
" # Only a conventional-commit type label is ever removed \u2014 the set",
|
|
16922
|
+
" # is_conventional_type_label() recognises. A type:* label owned by",
|
|
16923
|
+
" # a different bundle is a genuine conflict a human must resolve.",
|
|
16924
|
+
" # status:needs-attention is applied ADDITIVELY; the base status:*",
|
|
16925
|
+
" # label always stays (see the additive-flag rule).",
|
|
16926
|
+
" local apply=0",
|
|
16927
|
+
' if [[ "${1:-}" == "--fix" ]]; then',
|
|
16928
|
+
" apply=1",
|
|
16929
|
+
" fi",
|
|
16930
|
+
' local mode="report"',
|
|
16931
|
+
' [[ "$apply" -eq 1 ]] && mode="fix"',
|
|
16932
|
+
"",
|
|
16933
|
+
" local issues",
|
|
16934
|
+
" issues=$(gh issue list --state open --json number,labels \\",
|
|
16935
|
+
' --limit 1000 2>/dev/null || echo "[]")',
|
|
16936
|
+
"",
|
|
16937
|
+
" # Filter jq-side and emit a TWO-field record. The label list is",
|
|
16938
|
+
" # last AND guaranteed non-empty by the select, so no field can",
|
|
16939
|
+
" # collapse under IFS=tab and shift the record left (#884). The",
|
|
16940
|
+
" # title is deliberately not threaded through \u2014 every output line",
|
|
16941
|
+
" # keys off the issue number.",
|
|
16942
|
+
" local issue_data",
|
|
16943
|
+
` issue_data=$(echo "$issues" | jq -r '`,
|
|
16944
|
+
" .[] |",
|
|
16945
|
+
" (.labels | map(.name)) as $names |",
|
|
16946
|
+
" select($names | length > 0) |",
|
|
16947
|
+
' "\\(.number)\\t\\($names | join(","))"',
|
|
16948
|
+
" ' 2>/dev/null)",
|
|
16949
|
+
"",
|
|
16950
|
+
" local checked_count=0",
|
|
16951
|
+
" local ok_count=0",
|
|
16952
|
+
" local corrected_count=0",
|
|
16953
|
+
" local flagged_count=0",
|
|
16954
|
+
"",
|
|
16955
|
+
" while IFS=$'\\t' read -r num labels_csv; do",
|
|
16956
|
+
' [[ -z "$num" ]] && continue',
|
|
16957
|
+
"",
|
|
16958
|
+
" local labels_nl",
|
|
16959
|
+
` labels_nl=$(printf '%s' "$labels_csv" | tr ',' '\\n')`,
|
|
16960
|
+
"",
|
|
16961
|
+
" local resolution assignment",
|
|
16962
|
+
" local outcome='' type_label='' phase_labels='' candidates=''",
|
|
16963
|
+
` resolution=$(printf '%s\\n' "$labels_nl" | phase_type_of)`,
|
|
16964
|
+
" while IFS= read -r assignment; do",
|
|
16965
|
+
' case "$assignment" in',
|
|
16966
|
+
" OUTCOME=*) outcome=${assignment#OUTCOME=} ;;",
|
|
16967
|
+
" TYPE_LABEL=*) type_label=${assignment#TYPE_LABEL=} ;;",
|
|
16968
|
+
" CANDIDATE_TYPE_LABELS=*) candidates=${assignment#CANDIDATE_TYPE_LABELS=} ;;",
|
|
16969
|
+
" PHASE_LABELS=*) phase_labels=${assignment#PHASE_LABELS=} ;;",
|
|
16970
|
+
" esac",
|
|
16971
|
+
' done <<< "$resolution"',
|
|
16972
|
+
"",
|
|
16973
|
+
" # No recognised phase label \u2014 the invariant does not apply.",
|
|
16974
|
+
" # Consumer-specific `foo:bar` labels are deliberately not policed.",
|
|
16975
|
+
' [[ "$outcome" == "none" ]] && continue',
|
|
16976
|
+
" checked_count=$((checked_count + 1))",
|
|
16977
|
+
"",
|
|
16978
|
+
" # Idempotent flagging: read the existing flag off the labels we",
|
|
16979
|
+
" # already fetched rather than spending another API call.",
|
|
16980
|
+
" local already_flagged=0",
|
|
16981
|
+
' case ",${labels_csv}," in',
|
|
16982
|
+
' *",status:needs-attention,"*) already_flagged=1 ;;',
|
|
16983
|
+
" esac",
|
|
16984
|
+
"",
|
|
16985
|
+
' if [[ "$outcome" == "ambiguous" ]]; then',
|
|
16986
|
+
' echo "LABEL_AMBIGUOUS #${num} phase=\\"${phase_labels}\\" candidates=\\"${candidates}\\""',
|
|
16987
|
+
" flagged_count=$((flagged_count + 1))",
|
|
16988
|
+
' if [[ "$apply" -eq 1 && "$already_flagged" -eq 0 ]]; then',
|
|
16989
|
+
' if gh issue edit "$num" --add-label "status:needs-attention" >/dev/null 2>&1; then',
|
|
16990
|
+
' gh issue comment "$num" \\',
|
|
16991
|
+
' --body "Label invariant: phase label(s) ${phase_labels} imply more than one bundle type label (${candidates}). Flagged for human triage \u2014 an ambiguous pairing is never auto-corrected." >/dev/null 2>&1 || true',
|
|
16992
|
+
' echo "LABEL_FLAGGED #${num} \u2014 added status:needs-attention (ambiguous)"',
|
|
16993
|
+
" else",
|
|
16994
|
+
' echo "LABEL_FLAG_FAILED #${num} \u2014 could not add status:needs-attention (ambiguous)"',
|
|
16995
|
+
" fi",
|
|
16996
|
+
" fi",
|
|
16997
|
+
" continue",
|
|
16998
|
+
" fi",
|
|
16999
|
+
"",
|
|
17000
|
+
" # Partition the issue's existing type:* labels against the",
|
|
17001
|
+
" # implied one.",
|
|
17002
|
+
" local label",
|
|
17003
|
+
" local has_expected=0",
|
|
17004
|
+
" local conv_types=''",
|
|
17005
|
+
" local foreign_types=''",
|
|
17006
|
+
" while IFS= read -r label; do",
|
|
17007
|
+
' [ -z "$label" ] && continue',
|
|
17008
|
+
' case "$label" in',
|
|
17009
|
+
" type:*) ;;",
|
|
17010
|
+
" *) continue ;;",
|
|
17011
|
+
" esac",
|
|
17012
|
+
' if [ "$label" = "$type_label" ]; then',
|
|
17013
|
+
" has_expected=1",
|
|
17014
|
+
" continue",
|
|
17015
|
+
" fi",
|
|
17016
|
+
' if is_conventional_type_label "$label"; then',
|
|
17017
|
+
' conv_types="${conv_types}${label} "',
|
|
17018
|
+
" else",
|
|
17019
|
+
' foreign_types="${foreign_types}${label} "',
|
|
17020
|
+
" fi",
|
|
17021
|
+
' done <<< "$labels_nl"',
|
|
17022
|
+
"",
|
|
17023
|
+
' if [[ "$has_expected" -eq 1 && -z "${conv_types}${foreign_types}" ]]; then',
|
|
17024
|
+
' echo "LABEL_OK #${num} type=${type_label}"',
|
|
17025
|
+
" ok_count=$((ok_count + 1))",
|
|
17026
|
+
" continue",
|
|
17027
|
+
" fi",
|
|
17028
|
+
"",
|
|
17029
|
+
" # A type:* label owned by a DIFFERENT bundle is a conflict the",
|
|
17030
|
+
" # sweep must not guess at: removing it would destroy routing",
|
|
17031
|
+
" # information, and adding alongside it would leave two bundle",
|
|
17032
|
+
" # type labels and a non-deterministic funnel tier.",
|
|
17033
|
+
' if [[ -n "$foreign_types" ]]; then',
|
|
17034
|
+
' echo "LABEL_CONFLICT #${num} phase=\\"${phase_labels}\\" expected=${type_label} foreign=\\"${foreign_types% }\\""',
|
|
17035
|
+
" flagged_count=$((flagged_count + 1))",
|
|
17036
|
+
' if [[ "$apply" -eq 1 && "$already_flagged" -eq 0 ]]; then',
|
|
17037
|
+
' if gh issue edit "$num" --add-label "status:needs-attention" >/dev/null 2>&1; then',
|
|
17038
|
+
' gh issue comment "$num" \\',
|
|
17039
|
+
' --body "Label invariant: phase label(s) ${phase_labels} require ${type_label}, but this issue carries ${foreign_types% }, which is owned by another bundle. Flagged for human triage \u2014 the sweep only removes conventional-commit type labels." >/dev/null 2>&1 || true',
|
|
17040
|
+
' echo "LABEL_FLAGGED #${num} \u2014 added status:needs-attention (conflicting bundle type)"',
|
|
17041
|
+
" else",
|
|
17042
|
+
' echo "LABEL_FLAG_FAILED #${num} \u2014 could not add status:needs-attention (conflict)"',
|
|
17043
|
+
" fi",
|
|
17044
|
+
" fi",
|
|
17045
|
+
" continue",
|
|
17046
|
+
" fi",
|
|
17047
|
+
"",
|
|
17048
|
+
" # Correctable: add the implied label and/or drop the",
|
|
17049
|
+
" # conventional-commit label(s) shadowing it, in ONE edit so the",
|
|
17050
|
+
" # issue is never observable carrying two type:* labels.",
|
|
17051
|
+
' local removing="${conv_types% }"',
|
|
17052
|
+
" local adding=''",
|
|
17053
|
+
' [[ "$has_expected" -eq 0 ]] && adding="$type_label"',
|
|
17054
|
+
' echo "LABEL_VIOLATION #${num} phase=\\"${phase_labels}\\" expected=${type_label} add=\\"${adding}\\" remove=\\"${removing}\\""',
|
|
17055
|
+
' if [[ "$apply" -eq 0 ]]; then',
|
|
17056
|
+
" continue",
|
|
17057
|
+
" fi",
|
|
17058
|
+
"",
|
|
17059
|
+
" local -a edit_args=()",
|
|
17060
|
+
" local stray",
|
|
17061
|
+
" for stray in $removing; do",
|
|
17062
|
+
' edit_args+=(--remove-label "$stray")',
|
|
17063
|
+
" done",
|
|
17064
|
+
' [[ -n "$adding" ]] && edit_args+=(--add-label "$adding")',
|
|
17065
|
+
' if [[ "${#edit_args[@]}" -eq 0 ]]; then',
|
|
17066
|
+
" continue",
|
|
17067
|
+
" fi",
|
|
17068
|
+
' if gh issue edit "$num" "${edit_args[@]}" >/dev/null 2>&1; then',
|
|
17069
|
+
' gh issue comment "$num" \\',
|
|
17070
|
+
' --body "Label invariant: phase label(s) ${phase_labels} require ${type_label}. Corrected \u2014 added: ${adding:-(none)}; removed: ${removing:-(none)}." >/dev/null 2>&1 || true',
|
|
17071
|
+
' echo "LABEL_CORRECTED #${num} added=\\"${adding}\\" removed=\\"${removing}\\""',
|
|
17072
|
+
" corrected_count=$((corrected_count + 1))",
|
|
17073
|
+
" else",
|
|
17074
|
+
' echo "LABEL_CORRECT_FAILED #${num} \u2014 label edit failed"',
|
|
17075
|
+
" fi",
|
|
17076
|
+
' done <<< "$issue_data"',
|
|
17077
|
+
"",
|
|
17078
|
+
" local violations_count=$((checked_count - ok_count))",
|
|
17079
|
+
' echo "LABEL_INVARIANT_DONE mode=${mode} checked=${checked_count} ok=${ok_count} violations=${violations_count} corrected=${corrected_count} flagged=${flagged_count}"',
|
|
17080
|
+
"}",
|
|
17081
|
+
"",
|
|
16431
17082
|
"cmd_scope() {",
|
|
16432
17083
|
' local issue_num="${1:-}"',
|
|
16433
17084
|
' if [[ -z "$issue_num" ]]; then',
|
|
@@ -16514,8 +17165,9 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
16514
17165
|
' maintenance) shift; cmd_maintenance "$@" ;;',
|
|
16515
17166
|
' prs) shift; cmd_prs "$@" ;;',
|
|
16516
17167
|
' scope) shift; cmd_scope "$@" ;;',
|
|
17168
|
+
' label-invariant) shift; cmd_label_invariant "$@" ;;',
|
|
16517
17169
|
" help|*)",
|
|
16518
|
-
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|lease-reconcile|maintenance|prs|scope>"',
|
|
17170
|
+
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|lease-reconcile|maintenance|prs|scope|label-invariant>"',
|
|
16519
17171
|
" exit 1",
|
|
16520
17172
|
" ;;",
|
|
16521
17173
|
"esac"
|
|
@@ -16524,7 +17176,7 @@ function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
|
16524
17176
|
function buildCheckBlockedProcedure(tiers, scopeGate = resolveScopeGate(), runRatio = resolveRunRatio()) {
|
|
16525
17177
|
return {
|
|
16526
17178
|
name: "check-blocked.sh",
|
|
16527
|
-
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, lease-reconcile, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc, excluding issues carrying `status:needs-attention` or `status:deferred`; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, skips human-parked `status:deferred` candidates with a `SKIP_DEFERRED` line, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M deferred_skipped=K` summary line; the lease-reconcile subcommand auto-reconciles stuck `review:fixing` PR leases \u2014 re-applying `review:needs-worker` on an orphaned lease (fix-list stale, no worker report) so the Phase B1 drain retries, and removing `review:needs-worker` on a consumed-but-uncleared wedge (branch HEAD advanced past the fix-list, marker still set, no worker report) so the reviewer confirm pass can merge, always posting an audit-trail note comment and emitting a single `LEASE_RECONCILE orphaned=N consumed_uncleared=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, folds in the lease-reconcile sweep, and emits a `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line followed by the `LEASE_RECONCILE` line.",
|
|
17179
|
+
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, lease-reconcile, maintenance, prs, scope, label-invariant. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc, excluding issues carrying `status:needs-attention` or `status:deferred`; the scope subcommand classifies a single issue against the scope-gate thresholds; the unblock subcommand applies the `status:blocked` \u2192 `status:ready` label flip itself, posts the canned unblock comment, skips human-parked `status:deferred` candidates with a `SKIP_DEFERRED` line, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M deferred_skipped=K` summary line; the lease-reconcile subcommand auto-reconciles stuck `review:fixing` PR leases \u2014 re-applying `review:needs-worker` on an orphaned lease (fix-list stale, no worker report) so the Phase B1 drain retries, and removing `review:needs-worker` on a consumed-but-uncleared wedge (branch HEAD advanced past the fix-list, marker still set, no worker report) so the reviewer confirm pass can merge, always posting an audit-trail note comment and emitting a single `LEASE_RECONCILE orphaned=N consumed_uncleared=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, folds in the lease-reconcile sweep and the label-invariant auto-correction, and emits a `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line followed by the `LEASE_RECONCILE` and `LABEL_INVARIANT_DONE` lines; the label-invariant subcommand enforces the phase-label \u2192 `type:<bundle>` pairing derived from the canonical `BUNDLE_OWNERSHIP` map \u2014 report-only by default, auto-correcting with `--fix` (replacing a shadowing conventional-commit `type:*` rather than merely adding, so the issue keeps exactly one `type:*`) and flagging `status:needs-attention` when the pairing is ambiguous or collides with another bundle's type label, emitting a single `LABEL_INVARIANT_DONE mode=M checked=N ok=O violations=V corrected=C flagged=F` summary line.",
|
|
16528
17180
|
content: buildCheckBlockedScript(tiers, scopeGate, runRatio)
|
|
16529
17181
|
};
|
|
16530
17182
|
}
|
|
@@ -17240,32 +17892,36 @@ var orchestratorSubAgent = {
|
|
|
17240
17892
|
"## Phase D: Maintenance",
|
|
17241
17893
|
"",
|
|
17242
17894
|
"Run the bundled `check-blocked.sh maintenance` procedure and read",
|
|
17243
|
-
"**only** the
|
|
17244
|
-
"`LEASE_RECONCILE`. The procedure folds
|
|
17245
|
-
"orphan-detection, needs-attention summary,
|
|
17246
|
-
"auto-reconcile
|
|
17247
|
-
"into a single sweep \u2014
|
|
17248
|
-
"
|
|
17249
|
-
"
|
|
17250
|
-
"
|
|
17251
|
-
"
|
|
17895
|
+
"**only** the three summary lines it emits \u2014 `MAINTENANCE_DONE`,",
|
|
17896
|
+
"`LEASE_RECONCILE`, and `LABEL_INVARIANT_DONE`. The procedure folds",
|
|
17897
|
+
"the stale-detection, orphan-detection, needs-attention summary,",
|
|
17898
|
+
"PR-lease auto-reconcile, and phase-label invariant sweep that",
|
|
17899
|
+
"earlier revisions split across D1, D2, and D3 into a single sweep \u2014",
|
|
17900
|
+
"applying the `status:needs-attention` label and posting the canned",
|
|
17901
|
+
"flag comment for each stale / stale-blocked issue itself,",
|
|
17902
|
+
"reconciling stuck `review:fixing` PR leases itself, and correcting",
|
|
17903
|
+
"mislabeled pipeline issues itself, mirroring the discipline of",
|
|
17904
|
+
"Phase B (`pr-sweep.sh`) and Phase C (`check-blocked.sh unblock`).",
|
|
17252
17905
|
"",
|
|
17253
17906
|
"```bash",
|
|
17254
17907
|
".claude/procedures/check-blocked.sh maintenance",
|
|
17255
17908
|
"```",
|
|
17256
17909
|
"",
|
|
17257
|
-
"The script emits
|
|
17910
|
+
"The script emits three summary lines in this shape:",
|
|
17258
17911
|
"",
|
|
17259
17912
|
"```",
|
|
17260
17913
|
"MAINTENANCE_DONE flagged_stale=<N> flagged_blocked=<M> orphan_branches=<A> orphan_prs=<B> needs_attention_total=<T>",
|
|
17261
17914
|
"LEASE_RECONCILE orphaned=<N> consumed_uncleared=<M>",
|
|
17915
|
+
"LABEL_INVARIANT_DONE mode=fix checked=<N> ok=<O> violations=<V> corrected=<C> flagged=<F>",
|
|
17262
17916
|
"```",
|
|
17263
17917
|
"",
|
|
17264
17918
|
"Per-issue / per-orphan / per-PR informational lines (`FLAGGED_STALE",
|
|
17265
17919
|
"#N`, `FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
17266
17920
|
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026`,",
|
|
17267
17921
|
"`LEASE_ORPHANED PR #N \u2014 \u2026`, `LEASE_CONSUMED_UNCLEARED PR #N \u2014 \u2026`,",
|
|
17268
|
-
"`LEASE_RECONCILE_FAILED PR #N \u2014 \u2026`
|
|
17922
|
+
"`LEASE_RECONCILE_FAILED PR #N \u2014 \u2026`, `LABEL_VIOLATION #N \u2014 \u2026`,",
|
|
17923
|
+
"`LABEL_CORRECTED #N \u2014 \u2026`, `LABEL_AMBIGUOUS #N \u2014 \u2026`,",
|
|
17924
|
+
"`LABEL_CONFLICT #N \u2014 \u2026`) are emitted for log visibility",
|
|
17269
17925
|
"but are **not** load-bearing for the orchestrator \u2014 partial failures",
|
|
17270
17926
|
"(one bad `gh` call) do not abort the sweep, they are simply omitted",
|
|
17271
17927
|
"from the counters.",
|
|
@@ -17305,9 +17961,24 @@ var orchestratorSubAgent = {
|
|
|
17305
17961
|
"is never silently force-released. The `review:fixing` lease itself",
|
|
17306
17962
|
"is always left for the reviewer confirm pass to release.",
|
|
17307
17963
|
"",
|
|
17308
|
-
"
|
|
17309
|
-
"
|
|
17310
|
-
"
|
|
17964
|
+
"**Phase-label invariant (`LABEL_INVARIANT_DONE`).** The sweep also",
|
|
17965
|
+
"enforces the phase-label \u2192 `type:<bundle>` pairing on every open",
|
|
17966
|
+
"issue, so a pipeline issue filed with a conventional-commit",
|
|
17967
|
+
"`type:*` (derived from its title prefix) cannot stay invisible to",
|
|
17968
|
+
'the `--label "type:<bundle>"` duplicate-check idiom or mis-tier in',
|
|
17969
|
+
"Phase E's funnel-tier sort. The script mutates the labels itself \u2014",
|
|
17970
|
+
"the orchestrator only reads the summary line. See the **Phase-label",
|
|
17971
|
+
"\u2192 `type:<bundle>` invariant** section in `CLAUDE.md` for the full",
|
|
17972
|
+
"correction policy; in short, a shadowing conventional-commit type",
|
|
17973
|
+
"label is **replaced** (never merely supplemented, so the issue",
|
|
17974
|
+
"keeps exactly one `type:*`), and an ambiguous or cross-bundle",
|
|
17975
|
+
"collision is **flagged** `status:needs-attention` rather than",
|
|
17976
|
+
"guessed at.",
|
|
17977
|
+
"",
|
|
17978
|
+
"Log all three summary lines and continue to Phase E regardless of",
|
|
17979
|
+
"outcomes \u2014 a non-zero `flagged_*`, `orphan_*`, `orphaned`,",
|
|
17980
|
+
"`consumed_uncleared`, `corrected`, or `flagged` count is",
|
|
17981
|
+
"informational, not a failure.",
|
|
17311
17982
|
"",
|
|
17312
17983
|
"## Phase E: Queue Scan",
|
|
17313
17984
|
"",
|
|
@@ -18309,6 +18980,7 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
|
|
|
18309
18980
|
"- Stale thresholds: 72h for in-progress, 168h for blocked",
|
|
18310
18981
|
"- Flagged issues get `status:needs-attention` \u2014 they are not auto-reset",
|
|
18311
18982
|
"- **Phase D auto-reconciles stuck PR leases.** The maintenance sweep's `check-blocked.sh maintenance` invocation folds in a PR-lease reconcile that unwedges `review:fixing` PRs the Phase B1 drain and the worker hand-off left stuck, emitting a `LEASE_RECONCILE orphaned=<N> consumed_uncleared=<M>` line alongside `MAINTENANCE_DONE`. An **orphaned lease** (`review:fixing` without `review:needs-worker`, fix-list older than the 72h stale threshold, no worker-report newer than the fix-list) is **re-armed** \u2014 the sweep re-applies `review:needs-worker` so the Phase B1 drain retries the delegation, leaving the lease untouched. A **consumed-but-uncleared wedge** (both labels present, branch HEAD newer than the fix-list, no worker-report \u2014 the worker pushed but skipped the hand-off) is **auto-reconciled** \u2014 the sweep removes `review:needs-worker` so the reviewer confirm pass can merge. Both paths post an audit-trail note comment; a lease is never silently force-released, and the `review:fixing` lease itself is always left for the reviewer confirm pass to release.",
|
|
18983
|
+
"- **Phase D enforces the phase-label \u2192 `type:<bundle>` invariant.** The same maintenance sweep folds in a label-invariant pass that auto-corrects open issues carrying a pipeline phase label without the matching `type:<bundle>` label, emitting a `LABEL_INVARIANT_DONE mode=fix checked=<N> ok=<O> violations=<V> corrected=<C> flagged=<F>` line alongside `MAINTENANCE_DONE`. The correction **replaces** a shadowing conventional-commit `type:*` rather than merely adding the bundle type, so the issue keeps exactly one `type:*` and Phase E's funnel-tier sort key stays deterministic. Ambiguous pairings and collisions with another bundle's `type:*` label are **flagged** `status:needs-attention` (additively) instead of guessed at. See the **Phase-label \u2192 `type:<bundle>` invariant** section below for the matcher table and the full correction policy.",
|
|
18312
18984
|
"",
|
|
18313
18985
|
"## Depth-0 invocation requirement",
|
|
18314
18986
|
"",
|
|
@@ -18324,6 +18996,8 @@ function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate
|
|
|
18324
18996
|
"",
|
|
18325
18997
|
renderScopeGateSection(scopeGate, excludeBundles),
|
|
18326
18998
|
"",
|
|
18999
|
+
renderPhaseTypeInvariantSection(excludeBundles),
|
|
19000
|
+
"",
|
|
18327
19001
|
renderScheduledTasksSection(scheduledTasks),
|
|
18328
19002
|
"",
|
|
18329
19003
|
renderUnblockDependentsSection(unblockDependents)
|
|
@@ -18924,6 +19598,8 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
18924
19598
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
18925
19599
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
18926
19600
|
"",
|
|
19601
|
+
...renderIssueTypeAssignmentStep(),
|
|
19602
|
+
"",
|
|
18927
19603
|
" The issue body must include:",
|
|
18928
19604
|
" - A **discovery source** line naming this person profile",
|
|
18929
19605
|
" (`Discovered while profiling: <person name>`)",
|
|
@@ -18944,6 +19620,8 @@ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
18944
19620
|
` - \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\``,
|
|
18945
19621
|
` - \`status:${labelsForPhase(issueDefaults, "software:research").status}\``,
|
|
18946
19622
|
"",
|
|
19623
|
+
...renderIssueTypeAssignmentStep(),
|
|
19624
|
+
"",
|
|
18947
19625
|
" The issue body must include:",
|
|
18948
19626
|
" - A **discovery source** line naming this person profile",
|
|
18949
19627
|
" (`Discovered while profiling: <person name>`)",
|
|
@@ -19226,6 +19904,8 @@ function buildProfilePersonSkill(paths, issueDefaults) {
|
|
|
19226
19904
|
` \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "people:research").status}\`. Body must include the`,
|
|
19227
19905
|
" person's name, selected role, primary company, framing, and any",
|
|
19228
19906
|
" overrides.",
|
|
19907
|
+
"",
|
|
19908
|
+
...renderIssueTypeAssignmentStep(),
|
|
19229
19909
|
"2. Execute Phase 1 (Research) of the people-profile-analyst agent.",
|
|
19230
19910
|
"3. Phase 1 creates the `people:draft` issue. Phase 2 may create a",
|
|
19231
19911
|
" `people:followup` issue. Each downstream issue declares its",
|
|
@@ -19317,6 +19997,8 @@ function buildRefreshPersonSkill(paths, issueDefaults) {
|
|
|
19317
19997
|
"1. Create a `people:refresh` issue with `type:people-profile`,",
|
|
19318
19998
|
` \`priority:${labelsForPhase(issueDefaults, "people:refresh").priority}\`, and \`status:${labelsForPhase(issueDefaults, "people:refresh").status}\`. Body must include the`,
|
|
19319
19999
|
" profile path and any overrides.",
|
|
20000
|
+
"",
|
|
20001
|
+
...renderIssueTypeAssignmentStep(),
|
|
19320
20002
|
"2. Execute Phase 4 (Refresh) of the people-profile-analyst agent.",
|
|
19321
20003
|
"",
|
|
19322
20004
|
"## Output",
|
|
@@ -23013,6 +23695,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
23013
23695
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
23014
23696
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
23015
23697
|
"",
|
|
23698
|
+
...renderIssueTypeAssignmentStep(),
|
|
23699
|
+
"",
|
|
23016
23700
|
"9. **Verify all handoffs were created** before committing.",
|
|
23017
23701
|
"",
|
|
23018
23702
|
"10. **Commit and push** the regulation page. Close the research",
|
|
@@ -23123,6 +23807,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
23123
23807
|
` - \`priority:${labelsForPhase(issueDefaults, "req:scan").priority}\``,
|
|
23124
23808
|
` - \`status:${labelsForPhase(issueDefaults, "req:scan").status}\``,
|
|
23125
23809
|
"",
|
|
23810
|
+
...renderIssueTypeAssignmentStep(),
|
|
23811
|
+
"",
|
|
23126
23812
|
" The body must also:",
|
|
23127
23813
|
" - Identify the target category as **SEC** (security & compliance)",
|
|
23128
23814
|
" in the body so the downstream writer phase picks up the right",
|
|
@@ -23142,6 +23828,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
23142
23828
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
23143
23829
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
23144
23830
|
"",
|
|
23831
|
+
...renderIssueTypeAssignmentStep(),
|
|
23832
|
+
"",
|
|
23145
23833
|
"6. **Create `people:research` issues** for notable regulatory",
|
|
23146
23834
|
" leaders (commissioners, agency directors, lead policy authors)",
|
|
23147
23835
|
" mentioned on the regulation page. Keep this list small \u2014 at most",
|
|
@@ -23153,6 +23841,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
23153
23841
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
23154
23842
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
23155
23843
|
"",
|
|
23844
|
+
...renderIssueTypeAssignmentStep(),
|
|
23845
|
+
"",
|
|
23156
23846
|
"7. **Commit and push** the updated regulation page. Close the",
|
|
23157
23847
|
" impact issue.",
|
|
23158
23848
|
"",
|
|
@@ -23320,6 +24010,8 @@ function buildScanRegulatoryLandscapeSkill(paths, issueDefaults) {
|
|
|
23320
24010
|
` \`priority:${labelsForPhase(issueDefaults, "regulatory:scan").priority}\`, and \`status:${labelsForPhase(issueDefaults, "regulatory:scan").status}\`. The body must include the`,
|
|
23321
24011
|
" scope slug, the scope type, and any known regulations to include",
|
|
23322
24012
|
" or exclude.",
|
|
24013
|
+
"",
|
|
24014
|
+
...renderIssueTypeAssignmentStep(),
|
|
23323
24015
|
"2. Execute Phase 1 (Scan) of the regulatory-research-analyst agent.",
|
|
23324
24016
|
"3. Phase 1 writes the scan report and creates one",
|
|
23325
24017
|
" `regulatory:research` issue per prioritized regulation.",
|
|
@@ -23396,6 +24088,8 @@ function buildResearchRegulationSkill(paths, issueDefaults) {
|
|
|
23396
24088
|
` \`type:regulatory-research\`, \`priority:${labelsForPhase(issueDefaults, "regulatory:research").priority}\`, and`,
|
|
23397
24089
|
` \`status:${labelsForPhase(issueDefaults, "regulatory:research").status}\`. The body must include the scope slug and the`,
|
|
23398
24090
|
" regulation slug.",
|
|
24091
|
+
"",
|
|
24092
|
+
...renderIssueTypeAssignmentStep(),
|
|
23399
24093
|
"2. Execute Phase 2 (Research) of the regulatory-research-analyst",
|
|
23400
24094
|
" agent. The agent runs 6\u201312 targeted web searches and populates",
|
|
23401
24095
|
" the regulation page.",
|
|
@@ -23463,6 +24157,8 @@ function buildImpactRegulationSkill(paths, issueDefaults) {
|
|
|
23463
24157
|
` \`status:${labelsForPhase(issueDefaults, "regulatory:impact").status}\` (or \`status:blocked\` when still dependent on a`,
|
|
23464
24158
|
" Phase 2 research issue). Body must include the regulation page",
|
|
23465
24159
|
" path.",
|
|
24160
|
+
"",
|
|
24161
|
+
...renderIssueTypeAssignmentStep(),
|
|
23466
24162
|
"2. Execute Phase 3 (Impact) of the regulatory-research-analyst",
|
|
23467
24163
|
" agent. No web searches \u2014 pure synthesis from the regulation",
|
|
23468
24164
|
" page and project context.",
|
|
@@ -26298,6 +26994,8 @@ function buildWriteRequirementSkill(paths, issueDefaults) {
|
|
|
26298
26994
|
" Body must include the category, tier, output path, and a pointer",
|
|
26299
26995
|
" to the upstream proposal (or a direct user description if no",
|
|
26300
26996
|
" proposals file exists).",
|
|
26997
|
+
"",
|
|
26998
|
+
...renderIssueTypeAssignmentStep(),
|
|
26301
26999
|
"2. Execute the write phase of the requirements-writer agent.",
|
|
26302
27000
|
"3. The agent writes one requirement document, updates the category",
|
|
26303
27001
|
" index, opens a PR, and closes the issue.",
|
|
@@ -26887,6 +27585,8 @@ function buildRequirementsAnalystSubAgent(paths, issueDefaults) {
|
|
|
26887
27585
|
` \`--label "tier:<tier-slug>"\`, \`--label "status:${labelsForPhase(issueDefaults, "req:write").status}"\`, and`,
|
|
26888
27586
|
` \`--label "priority:${labelsForPhase(issueDefaults, "req:write").priority}"\`.`,
|
|
26889
27587
|
"",
|
|
27588
|
+
...renderIssueTypeAssignmentStep(),
|
|
27589
|
+
"",
|
|
26890
27590
|
" The body must carry the three writer-required fields in an",
|
|
26891
27591
|
" `## Objective` block, written as bold-prefixed lines so the",
|
|
26892
27592
|
" writer's intake parser can pull them out, plus the reserved-ID",
|
|
@@ -27033,6 +27733,8 @@ function buildScanRequirementsSkill(issueDefaults) {
|
|
|
27033
27733
|
"",
|
|
27034
27734
|
`1. Create a \`req:scan\` issue with \`type:requirement\`, \`priority:${labelsForPhase(issueDefaults, "req:scan").priority}\`,`,
|
|
27035
27735
|
` and \`status:${labelsForPhase(issueDefaults, "req:scan").status}\`. Body must list the files to read and the scan scope.`,
|
|
27736
|
+
"",
|
|
27737
|
+
...renderIssueTypeAssignmentStep(),
|
|
27036
27738
|
"2. Execute Phase 1 (Scan) of the requirements-analyst agent.",
|
|
27037
27739
|
"3. If gaps are found, a `req:draft-trace` issue is created automatically.",
|
|
27038
27740
|
"",
|
|
@@ -28081,6 +28783,7 @@ function buildRequirementsReviewerSubAgent(paths, issueDefaults) {
|
|
|
28081
28783
|
"- Labels: `type:requirement`, `req:write`, the matching",
|
|
28082
28784
|
" `tier:*` label derived from the referencing document's Tier,",
|
|
28083
28785
|
` \`priority:${labelsForPhase(issueDefaults, "req:write").priority}\`, \`status:${labelsForPhase(issueDefaults, "req:write").status}\`.`,
|
|
28786
|
+
...renderIssueTypeAssignmentStep({ indent: "", bullet: true }),
|
|
28084
28787
|
"- If any of Category / Tier / Output Path cannot be derived from",
|
|
28085
28788
|
" the referencing document, open the follow-up with",
|
|
28086
28789
|
" `status:needs-attention` and a `Missing:` line, per the same",
|
|
@@ -28236,6 +28939,8 @@ function buildReviewRequirementsSkill(paths, issueDefaults) {
|
|
|
28236
28939
|
` \`priority:${labelsForPhase(issueDefaults, "req:review").priority}\`, and \`status:${labelsForPhase(issueDefaults, "req:review").status}\`. Body must include the`,
|
|
28237
28940
|
" scope, the requirements root (or accept the default), and the",
|
|
28238
28941
|
" output path.",
|
|
28942
|
+
"",
|
|
28943
|
+
...renderIssueTypeAssignmentStep(),
|
|
28239
28944
|
"2. Execute the review phase of the requirements-reviewer agent.",
|
|
28240
28945
|
"3. The agent runs the 12-check audit, writes a structured report",
|
|
28241
28946
|
" grouped by Critical / Warning / Info (plus a separate",
|
|
@@ -28338,6 +29043,8 @@ function buildDeprecateRequirementSkill(_paths, issueDefaults) {
|
|
|
28338
29043
|
` \`priority:${labelsForPhase(issueDefaults, "req:deprecate").priority}\`, and \`status:${labelsForPhase(issueDefaults, "req:deprecate").status}\`. Body must include the`,
|
|
28339
29044
|
" Targets, Transition, and Reason sections above (optionally",
|
|
28340
29045
|
" `Pre-approved: yes`).",
|
|
29046
|
+
"",
|
|
29047
|
+
...renderIssueTypeAssignmentStep(),
|
|
28341
29048
|
"2. Execute the deprecation phase of the requirements-reviewer",
|
|
28342
29049
|
" agent.",
|
|
28343
29050
|
"3. The agent verifies inputs, pauses for human confirmation (or",
|
|
@@ -28912,6 +29619,8 @@ function buildResearchSkill(paths, issueDefaults) {
|
|
|
28912
29619
|
"1. Create a `research:scope` issue with `type:research`,",
|
|
28913
29620
|
` \`priority:${labelsForPhase(issueDefaults, "research:scope").priority}\`, and \`status:${labelsForPhase(issueDefaults, "research:scope").status}\`. Body must include the`,
|
|
28914
29621
|
" verbatim question, authorized sources, and any overrides.",
|
|
29622
|
+
"",
|
|
29623
|
+
...renderIssueTypeAssignmentStep(),
|
|
28915
29624
|
"2. Execute Phase 1 (Scope) of the research-analyst agent.",
|
|
28916
29625
|
"3. Phase 1 creates `research:slice` issues (one per slice) and a",
|
|
28917
29626
|
" single `research:verify` issue. Each downstream issue declares",
|
|
@@ -29727,6 +30436,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
29727
30436
|
` - \`priority:${labelsForPhase(issueDefaults, "bcm:outline").priority}\``,
|
|
29728
30437
|
` - \`status:${labelsForPhase(issueDefaults, "bcm:outline").status}\``,
|
|
29729
30438
|
"",
|
|
30439
|
+
...renderIssueTypeAssignmentStep(),
|
|
30440
|
+
"",
|
|
29730
30441
|
" The issue body must include:",
|
|
29731
30442
|
" - A **discovery source** line naming this software profile",
|
|
29732
30443
|
" (`Discovered while mapping: <product name>`)",
|
|
@@ -29795,6 +30506,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
29795
30506
|
" `software:research` phase with `type:software-profile`,",
|
|
29796
30507
|
` \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:research").status}\`.`,
|
|
29797
30508
|
"",
|
|
30509
|
+
...renderIssueTypeAssignmentStep(),
|
|
30510
|
+
"",
|
|
29798
30511
|
"3. **Enqueue a `company:research` issue for the vendor company** if",
|
|
29799
30512
|
" no matching profile already exists under `<COMPANY_PROFILES_DIR>/`.",
|
|
29800
30513
|
" The vendor (the company that builds or maintains the product)",
|
|
@@ -29807,6 +30520,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
29807
30520
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
29808
30521
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
29809
30522
|
"",
|
|
30523
|
+
...renderIssueTypeAssignmentStep(),
|
|
30524
|
+
"",
|
|
29810
30525
|
" The issue body must include:",
|
|
29811
30526
|
" - A **discovery source** line naming this software profile",
|
|
29812
30527
|
" (`Discovered while profiling: <product name>`)",
|
|
@@ -29826,6 +30541,8 @@ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
|
29826
30541
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
29827
30542
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
29828
30543
|
"",
|
|
30544
|
+
...renderIssueTypeAssignmentStep(),
|
|
30545
|
+
"",
|
|
29829
30546
|
" The issue body must include:",
|
|
29830
30547
|
" - A **discovery source** line naming this software profile",
|
|
29831
30548
|
" (`Discovered while profiling: <product name>`)",
|
|
@@ -30016,6 +30733,8 @@ function buildProfileSoftwareSkill(paths, issueDefaults) {
|
|
|
30016
30733
|
"1. Create a `software:research` issue with `type:software-profile`,",
|
|
30017
30734
|
` \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:research").status}\`. Body must include the`,
|
|
30018
30735
|
" product name, selected type, framing, and any overrides.",
|
|
30736
|
+
"",
|
|
30737
|
+
...renderIssueTypeAssignmentStep(),
|
|
30019
30738
|
"2. Execute Phase 1 (Research) of the software-profile-analyst",
|
|
30020
30739
|
" agent.",
|
|
30021
30740
|
"3. Phase 1 creates the `software:profile` issue. Phase 2 creates",
|
|
@@ -30104,6 +30823,8 @@ function buildMapSoftwareSkill(paths, issueDefaults) {
|
|
|
30104
30823
|
"1. Create a `software:map` issue with `type:software-profile`,",
|
|
30105
30824
|
` \`priority:${labelsForPhase(issueDefaults, "software:map").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:map").status}\`. Body must include the`,
|
|
30106
30825
|
" profile path and any overrides.",
|
|
30826
|
+
"",
|
|
30827
|
+
...renderIssueTypeAssignmentStep(),
|
|
30107
30828
|
"2. Execute Phase 4 (Map) of the software-profile-analyst agent.",
|
|
30108
30829
|
"3. Phase 4 writes the `## Capability Mapping` section, enqueues",
|
|
30109
30830
|
" `bcm:outline` issues for unmapped features above the threshold,",
|
|
@@ -30716,6 +31437,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
30716
31437
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
30717
31438
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
30718
31439
|
"",
|
|
31440
|
+
...renderIssueTypeAssignmentStep(),
|
|
31441
|
+
"",
|
|
30719
31442
|
"6. **Create `people:research` issues** for every entry in *People of",
|
|
30720
31443
|
" Interest* that does not already have a canonical person profile",
|
|
30721
31444
|
" or an open `people:research` issue. The `people-profile` bundle",
|
|
@@ -30727,6 +31450,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
30727
31450
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
30728
31451
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
30729
31452
|
"",
|
|
31453
|
+
...renderIssueTypeAssignmentStep(),
|
|
31454
|
+
"",
|
|
30730
31455
|
"7. **Verify all handoffs were created** before committing. For each",
|
|
30731
31456
|
" entity in both tables, confirm an existing profile or a fresh",
|
|
30732
31457
|
" handoff issue exists. Do not commit with missing handoffs.",
|
|
@@ -31020,6 +31745,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
31020
31745
|
` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
|
|
31021
31746
|
` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
|
|
31022
31747
|
"",
|
|
31748
|
+
...renderIssueTypeAssignmentStep(),
|
|
31749
|
+
"",
|
|
31023
31750
|
"6. **Hand off canonical people profiles** by creating one",
|
|
31024
31751
|
" `people:research` issue per leadership entry that does not",
|
|
31025
31752
|
" already have a canonical profile or an open `people:research`",
|
|
@@ -31031,6 +31758,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
|
|
|
31031
31758
|
` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
|
|
31032
31759
|
` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
|
|
31033
31760
|
"",
|
|
31761
|
+
...renderIssueTypeAssignmentStep(),
|
|
31762
|
+
"",
|
|
31034
31763
|
"7. **Commit and push** the organization page. Close the",
|
|
31035
31764
|
" organizations issue.",
|
|
31036
31765
|
"",
|
|
@@ -31205,6 +31934,8 @@ function buildScopeStandardsResearchSkill(paths, issueDefaults) {
|
|
|
31205
31934
|
` \`priority:${labelsForPhase(issueDefaults, "standards:scope").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:scope").status}\`. The body must include the`,
|
|
31206
31935
|
" standard slug, the list of target versions (or a request to",
|
|
31207
31936
|
" enumerate), and any known governance bodies.",
|
|
31937
|
+
"",
|
|
31938
|
+
...renderIssueTypeAssignmentStep(),
|
|
31208
31939
|
"2. Execute Phase 1 (Scope) of the standards-research-analyst agent.",
|
|
31209
31940
|
"3. Phase 1 writes the query plan and creates one `standards:research`",
|
|
31210
31941
|
" issue per target version, one `standards:compare` issue (blocked",
|
|
@@ -31269,6 +32000,8 @@ function buildResearchStandardSkill(paths, issueDefaults) {
|
|
|
31269
32000
|
"1. Create a `standards:research` issue with",
|
|
31270
32001
|
` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:research").status}\`.`,
|
|
31271
32002
|
" The body must include the standard slug and the version slug.",
|
|
32003
|
+
"",
|
|
32004
|
+
...renderIssueTypeAssignmentStep(),
|
|
31272
32005
|
"2. Execute Phase 2 (Research) of the standards-research-analyst",
|
|
31273
32006
|
" agent. The agent runs 6\u201310 targeted web searches and populates",
|
|
31274
32007
|
" the version page.",
|
|
@@ -31342,6 +32075,8 @@ function buildCompareStandardsSkill(paths, issueDefaults) {
|
|
|
31342
32075
|
` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:compare").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:compare").status}\`.`,
|
|
31343
32076
|
" Body must include the standard slug and the list of version",
|
|
31344
32077
|
" pages under comparison.",
|
|
32078
|
+
"",
|
|
32079
|
+
...renderIssueTypeAssignmentStep(),
|
|
31345
32080
|
"2. Execute Phase 3 (Compare) of the standards-research-analyst",
|
|
31346
32081
|
" agent. No web searches \u2014 pure synthesis from the version pages.",
|
|
31347
32082
|
"",
|
|
@@ -31410,6 +32145,8 @@ function buildExtensionStandardSkill(paths, issueDefaults) {
|
|
|
31410
32145
|
" The body must include the standard slug, the entity slug, the",
|
|
31411
32146
|
" closest resource, and a link to the source BCM or canvas",
|
|
31412
32147
|
" document.",
|
|
32148
|
+
"",
|
|
32149
|
+
...renderIssueTypeAssignmentStep(),
|
|
31413
32150
|
"2. Execute Phase 4 (Extension) of the standards-research-analyst",
|
|
31414
32151
|
" agent. The agent runs 4\u20138 targeted web searches against",
|
|
31415
32152
|
" community registries, implementation guides, and working-group",
|
|
@@ -31475,6 +32212,8 @@ function buildOrganizationsStandardSkill(paths, issueDefaults) {
|
|
|
31475
32212
|
` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:organizations").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:organizations").status}\`.`,
|
|
31476
32213
|
" Body must include the standard slug, the organization slug, and",
|
|
31477
32214
|
" the organization's governance role.",
|
|
32215
|
+
"",
|
|
32216
|
+
...renderIssueTypeAssignmentStep(),
|
|
31478
32217
|
"2. Execute Phase 5 (Organizations) of the",
|
|
31479
32218
|
" standards-research-analyst agent. The agent runs 4\u20138 targeted",
|
|
31480
32219
|
" web searches.",
|
|
@@ -31784,6 +32523,14 @@ var UPSTREAM_CONFIGULATOR_DOCS_SUMMARY = [
|
|
|
31784
32523
|
"",
|
|
31785
32524
|
"Pick the `type:*` and matching prefix that describes the work (`feat:`, `fix:`, `chore:`, `docs:`, `refactor:`). Set `priority:*` from the urgency and use `status:blocked` instead of `status:ready` if the issue depends on another open issue.",
|
|
31786
32525
|
"",
|
|
32526
|
+
"Then set the new issue's **GitHub issue type** \u2014 a separate field from the `type:*` label, which `gh issue create` cannot set. Derive it from the title prefix (`epic:` \u2192 Epic, `feat:` \u2192 Feature, `fix:` \u2192 Bug, everything else \u2192 Task). The local `.claude/procedures/set-issue-type.sh` helper resolves owner/repo from the **current** checkout, so a cross-repo filing needs the `updateIssueIssueType` GraphQL flow with an explicit owner/repo:",
|
|
32527
|
+
"",
|
|
32528
|
+
"```sh",
|
|
32529
|
+
"gh api graphql -f query='query($owner:String!,$repo:String!){repository(owner:$owner,name:$repo){issueTypes(first:50){nodes{id name}}}}' -f owner=codedrifters -f repo=packages",
|
|
32530
|
+
"gh issue view <issue-number> --repo codedrifters/packages --json id --jq '.id'",
|
|
32531
|
+
"gh api graphql -f query='mutation($issueId:ID!,$typeId:ID!){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$typeId}){issue{number issueType{name}}}}' -f issueId=<issue-node-id> -f typeId=<issue-type-node-id>",
|
|
32532
|
+
"```",
|
|
32533
|
+
"",
|
|
31787
32534
|
"See `.claude/rules/upstream-configulator-docs-detail.md` for the full reference \u2014 extended `gh` recipes, common pitfalls (rate limits, base64 decoding, search vs. browse), and a complete issue-creation walkthrough."
|
|
31788
32535
|
].join("\n");
|
|
31789
32536
|
var UPSTREAM_CONFIGULATOR_DOCS_DETAIL = [
|
|
@@ -31892,6 +32639,16 @@ var UPSTREAM_CONFIGULATOR_DOCS_DETAIL = [
|
|
|
31892
32639
|
"- `priority:*` \u2014 pick exactly one of `priority:critical`, `priority:high`, `priority:medium`, `priority:low`, `priority:trivial`. Default to `priority:medium` when nothing in the request signals urgency. Use `priority:high` for blockers and `priority:critical` only for outages or release-blocking work.",
|
|
31893
32640
|
"- `status:*` \u2014 `status:ready` for self-contained issues, `status:blocked` when the issue declares `Depends on: #<n>` against another open issue.",
|
|
31894
32641
|
"",
|
|
32642
|
+
"### GitHub issue type",
|
|
32643
|
+
"",
|
|
32644
|
+
"The GitHub **issue type** (Epic / Feature / Bug / Task) is a separate field from the `type:*` label, and `gh issue create` cannot set it. Derive it from the title prefix \u2014 `epic:` \u2192 Epic, `feat:` \u2192 Feature, `fix:` \u2192 Bug, everything else \u2192 Task \u2014 and apply it in a follow-up call. The bundled `.claude/procedures/set-issue-type.sh` helper resolves owner/repo from the **current** checkout, so a cross-repo filing against `codedrifters/packages` uses the `updateIssueIssueType` GraphQL flow with an explicit owner/repo instead:",
|
|
32645
|
+
"",
|
|
32646
|
+
"```sh",
|
|
32647
|
+
"gh api graphql -f query='query($owner:String!,$repo:String!){repository(owner:$owner,name:$repo){issueTypes(first:50){nodes{id name}}}}' -f owner=codedrifters -f repo=packages",
|
|
32648
|
+
"gh issue view <issue-number> --repo codedrifters/packages --json id --jq '.id'",
|
|
32649
|
+
"gh api graphql -f query='mutation($issueId:ID!,$typeId:ID!){updateIssueIssueType(input:{issueId:$issueId,issueTypeId:$typeId}){issue{number issueType{name}}}}' -f issueId=<issue-node-id> -f typeId=<issue-type-node-id>",
|
|
32650
|
+
"```",
|
|
32651
|
+
"",
|
|
31895
32652
|
"### Worked example",
|
|
31896
32653
|
"",
|
|
31897
32654
|
"Suppose configulator's `software-profile-analyst` agent prompt is missing a step you need. Instead of forking the prompt locally:",
|
|
@@ -40688,6 +41445,7 @@ export {
|
|
|
40688
41445
|
CDK_WATCH_DEFAULTS_BY_STAGE,
|
|
40689
41446
|
CLAUDE_RULE_TARGET,
|
|
40690
41447
|
COMPLETE_JOB_ID,
|
|
41448
|
+
CONVENTIONAL_COMMIT_TYPE_LABELS,
|
|
40691
41449
|
CdkCli,
|
|
40692
41450
|
DEFAULT_AC_THRESHOLDS,
|
|
40693
41451
|
DEFAULT_AGENT_PATHS,
|
|
@@ -40702,6 +41460,7 @@ export {
|
|
|
40702
41460
|
DEFAULT_DECOMPOSITION_TEMPLATE,
|
|
40703
41461
|
DEFAULT_DISPATCH_MODEL,
|
|
40704
41462
|
DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO,
|
|
41463
|
+
DEFAULT_GITHUB_ISSUE_TYPE,
|
|
40705
41464
|
DEFAULT_HOUSEKEEPING_MODEL,
|
|
40706
41465
|
DEFAULT_ISSUE_PRIORITY,
|
|
40707
41466
|
DEFAULT_ISSUE_STATUS,
|
|
@@ -40748,6 +41507,8 @@ export {
|
|
|
40748
41507
|
DEFAULT_UNBLOCK_DEPENDENTS_ENABLED,
|
|
40749
41508
|
DEFAULT_UPSTREAM_CONFIGULATOR_ENABLED,
|
|
40750
41509
|
DOCS_SYNC_AUDIT_SCHEMA_VERSION,
|
|
41510
|
+
GITHUB_ISSUE_TYPES,
|
|
41511
|
+
GITHUB_ISSUE_TYPE_BY_TITLE_PREFIX,
|
|
40751
41512
|
JsiiFaker,
|
|
40752
41513
|
LAYOUT_ENFORCEMENT,
|
|
40753
41514
|
LAYOUT_ROOT_BY_PROJECT_TYPE,
|
|
@@ -40759,6 +41520,7 @@ export {
|
|
|
40759
41520
|
MONOREPO_LAYOUT,
|
|
40760
41521
|
MonorepoProject,
|
|
40761
41522
|
Nvmrc,
|
|
41523
|
+
PHASE_LABEL_TYPE_MAP,
|
|
40762
41524
|
PROD_DEPLOY_NAME,
|
|
40763
41525
|
PROGRESS_FILES_FORMAT_VALUES,
|
|
40764
41526
|
PnpmWorkspace,
|
|
@@ -40771,6 +41533,7 @@ export {
|
|
|
40771
41533
|
ResetTask,
|
|
40772
41534
|
SCHEDULED_TASK_MODEL_VALUES,
|
|
40773
41535
|
SCOPE_CLASS_VALUES,
|
|
41536
|
+
SET_ISSUE_TYPE_HELPER_PATH,
|
|
40774
41537
|
SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
|
|
40775
41538
|
STARLIGHT_ROLE,
|
|
40776
41539
|
SUPPRESSED_WORKFLOW_RULE_NAMES,
|
|
@@ -40856,6 +41619,7 @@ export {
|
|
|
40856
41619
|
formatLayoutViolation,
|
|
40857
41620
|
formatStarlightSingletonViolation,
|
|
40858
41621
|
getLatestEligibleVersion,
|
|
41622
|
+
githubIssueTypeForTitle,
|
|
40859
41623
|
githubWorkflowBundle,
|
|
40860
41624
|
hasAnyDocsEmittingBundle,
|
|
40861
41625
|
hasAnyDownstreamIssueKindBundle,
|
|
@@ -40913,12 +41677,18 @@ export {
|
|
|
40913
41677
|
renderCustomDocSections,
|
|
40914
41678
|
renderExtractApiProcedure,
|
|
40915
41679
|
renderFocusSection,
|
|
41680
|
+
renderGithubIssueTypeSection,
|
|
41681
|
+
renderGithubIssueTypeSectionLines,
|
|
40916
41682
|
renderIssueTemplatesBundleHook,
|
|
40917
41683
|
renderIssueTemplatesCheckerScript,
|
|
40918
41684
|
renderIssueTemplatesRuleContent,
|
|
40919
41685
|
renderIssueTemplatesStarterPage,
|
|
41686
|
+
renderIssueTypeAssignmentBlanket,
|
|
41687
|
+
renderIssueTypeAssignmentStep,
|
|
40920
41688
|
renderMeetingTypesSection,
|
|
40921
41689
|
renderNextRequirementIdProcedure,
|
|
41690
|
+
renderPhaseTypeInvariantSection,
|
|
41691
|
+
renderPhaseTypeInvariantShellHelpers,
|
|
40922
41692
|
renderPriorityRulesSection,
|
|
40923
41693
|
renderProgressFileName,
|
|
40924
41694
|
renderProgressFilePath,
|
|
@@ -40931,6 +41701,7 @@ export {
|
|
|
40931
41701
|
renderScheduledTasksSection,
|
|
40932
41702
|
renderScopeGateSection,
|
|
40933
41703
|
renderScopeGateShellHelpers,
|
|
41704
|
+
renderSetIssueTypeFallbackLines,
|
|
40934
41705
|
renderSharedEditingBundleHook,
|
|
40935
41706
|
renderSharedEditingHelperScript,
|
|
40936
41707
|
renderSharedEditingRuleContent,
|
|
@@ -40941,6 +41712,7 @@ export {
|
|
|
40941
41712
|
renderStripToolArtifactTagsProcedure,
|
|
40942
41713
|
renderTemporalFramingCheckerScript,
|
|
40943
41714
|
renderTemporalFramingRuleContent,
|
|
41715
|
+
renderTitlePrefixTypeBullets,
|
|
40944
41716
|
renderUnblockDependentsScript,
|
|
40945
41717
|
renderUnblockDependentsSection,
|
|
40946
41718
|
requirementsAnalystBundle,
|
|
@@ -40970,6 +41742,7 @@ export {
|
|
|
40970
41742
|
resolveSkillEvals,
|
|
40971
41743
|
resolveTemplateVariables,
|
|
40972
41744
|
resolveTemporalFraming,
|
|
41745
|
+
resolveTypeLabelForLabels,
|
|
40973
41746
|
resolveTypeScriptProjectOutdir,
|
|
40974
41747
|
resolveUnblockDependents,
|
|
40975
41748
|
runScan,
|
|
@@ -40979,6 +41752,7 @@ export {
|
|
|
40979
41752
|
stripToolArtifactTagsProcedure,
|
|
40980
41753
|
tsdocRecordToFindings,
|
|
40981
41754
|
turborepoBundle,
|
|
41755
|
+
typeLabelForPhaseLabel,
|
|
40982
41756
|
typescriptBundle,
|
|
40983
41757
|
upstreamConfigulatorDocsBundle,
|
|
40984
41758
|
validateAgentTierConfig,
|