@codedrifters/configulator 0.0.297 → 0.0.299
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 +335 -26
- package/lib/index.d.ts +336 -27
- package/lib/index.js +1516 -593
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1507 -593
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -175,6 +175,45 @@ var require_lib = __commonJS({
|
|
|
175
175
|
// src/agent/agent-config.ts
|
|
176
176
|
import { Component as Component8, SampleFile, TextFile as TextFile4 } from "projen";
|
|
177
177
|
|
|
178
|
+
// src/agent/types.ts
|
|
179
|
+
var AGENT_RULE_SCOPE = {
|
|
180
|
+
ALWAYS: "always",
|
|
181
|
+
FILE_PATTERN: "file-pattern"
|
|
182
|
+
};
|
|
183
|
+
var AGENT_PLATFORM = {
|
|
184
|
+
CURSOR: "cursor",
|
|
185
|
+
CLAUDE: "claude",
|
|
186
|
+
CODEX: "codex",
|
|
187
|
+
COPILOT: "copilot"
|
|
188
|
+
};
|
|
189
|
+
var CLAUDE_RULE_TARGET = {
|
|
190
|
+
SCOPED_FILE: "scoped-file",
|
|
191
|
+
AGENTS_MD: "agents-md",
|
|
192
|
+
CLAUDE_MD: "claude-md"
|
|
193
|
+
};
|
|
194
|
+
var AGENT_MODEL = {
|
|
195
|
+
INHERIT: "inherit",
|
|
196
|
+
FAST: "fast",
|
|
197
|
+
BALANCED: "balanced",
|
|
198
|
+
POWERFUL: "powerful"
|
|
199
|
+
};
|
|
200
|
+
function resolveModelAlias(model) {
|
|
201
|
+
if (!model || model === AGENT_MODEL.INHERIT) {
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
const mapping = {
|
|
205
|
+
[AGENT_MODEL.POWERFUL]: "opus",
|
|
206
|
+
[AGENT_MODEL.BALANCED]: "sonnet",
|
|
207
|
+
[AGENT_MODEL.FAST]: "haiku"
|
|
208
|
+
};
|
|
209
|
+
return mapping[model] ?? model;
|
|
210
|
+
}
|
|
211
|
+
var MCP_TRANSPORT = {
|
|
212
|
+
STDIO: "stdio",
|
|
213
|
+
HTTP: "http",
|
|
214
|
+
SSE: "sse"
|
|
215
|
+
};
|
|
216
|
+
|
|
178
217
|
// src/agent/bundles/project-context.ts
|
|
179
218
|
var PROJECT_CONTEXT_PATH = "docs/src/content/docs/project-context.md";
|
|
180
219
|
var SUBPROJECT_ROLE_GUIDANCE = [
|
|
@@ -302,45 +341,6 @@ var MONOREPO_LAYOUT_SEED_BLOCK = [
|
|
|
302
341
|
""
|
|
303
342
|
].join("\n");
|
|
304
343
|
|
|
305
|
-
// src/agent/types.ts
|
|
306
|
-
var AGENT_RULE_SCOPE = {
|
|
307
|
-
ALWAYS: "always",
|
|
308
|
-
FILE_PATTERN: "file-pattern"
|
|
309
|
-
};
|
|
310
|
-
var AGENT_PLATFORM = {
|
|
311
|
-
CURSOR: "cursor",
|
|
312
|
-
CLAUDE: "claude",
|
|
313
|
-
CODEX: "codex",
|
|
314
|
-
COPILOT: "copilot"
|
|
315
|
-
};
|
|
316
|
-
var CLAUDE_RULE_TARGET = {
|
|
317
|
-
SCOPED_FILE: "scoped-file",
|
|
318
|
-
AGENTS_MD: "agents-md",
|
|
319
|
-
CLAUDE_MD: "claude-md"
|
|
320
|
-
};
|
|
321
|
-
var AGENT_MODEL = {
|
|
322
|
-
INHERIT: "inherit",
|
|
323
|
-
FAST: "fast",
|
|
324
|
-
BALANCED: "balanced",
|
|
325
|
-
POWERFUL: "powerful"
|
|
326
|
-
};
|
|
327
|
-
function resolveModelAlias(model) {
|
|
328
|
-
if (!model || model === AGENT_MODEL.INHERIT) {
|
|
329
|
-
return void 0;
|
|
330
|
-
}
|
|
331
|
-
const mapping = {
|
|
332
|
-
[AGENT_MODEL.POWERFUL]: "opus",
|
|
333
|
-
[AGENT_MODEL.BALANCED]: "sonnet",
|
|
334
|
-
[AGENT_MODEL.FAST]: "haiku"
|
|
335
|
-
};
|
|
336
|
-
return mapping[model] ?? model;
|
|
337
|
-
}
|
|
338
|
-
var MCP_TRANSPORT = {
|
|
339
|
-
STDIO: "stdio",
|
|
340
|
-
HTTP: "http",
|
|
341
|
-
SSE: "sse"
|
|
342
|
-
};
|
|
343
|
-
|
|
344
344
|
// src/agent/bundles/agenda.ts
|
|
345
345
|
var agendaAnalystSubAgent = {
|
|
346
346
|
name: "agenda-analyst",
|
|
@@ -1080,6 +1080,47 @@ var awsCdkBundle = {
|
|
|
1080
1080
|
"- When adding a `NodejsFunction` with a bundled handler, ensure the `entry` path is explicitly configured",
|
|
1081
1081
|
"- Verify the entry is included in the build tool config (e.g., tsup entry list) so the runtime can find the handler",
|
|
1082
1082
|
"",
|
|
1083
|
+
"## Lambda Construct Encapsulation",
|
|
1084
|
+
"",
|
|
1085
|
+
"When a Lambda construct is event-driven, it should own:",
|
|
1086
|
+
"",
|
|
1087
|
+
"- The EventBridge Rule (or other trigger) that routes events to itself.",
|
|
1088
|
+
"- The IAM permissions it needs on resources passed in via props.",
|
|
1089
|
+
"",
|
|
1090
|
+
"Pass the resources (event bus, table, queue, etc.) into the Lambda",
|
|
1091
|
+
"construct's props rather than defining triggers and grants in the",
|
|
1092
|
+
"enclosing workflow or service. The Lambda construct then becomes",
|
|
1093
|
+
'self-describing \u2014 "what triggers me, what I write to" lives in one',
|
|
1094
|
+
"file \u2014 and reverting or refactoring a single Lambda doesn't ripple",
|
|
1095
|
+
"through unrelated constructs.",
|
|
1096
|
+
"",
|
|
1097
|
+
"```typescript",
|
|
1098
|
+
"export interface MyLambdaProps {",
|
|
1099
|
+
" readonly eventBus: IEventBus;",
|
|
1100
|
+
" readonly dataStoreTable: ITable;",
|
|
1101
|
+
"}",
|
|
1102
|
+
"",
|
|
1103
|
+
"export class MyLambda extends Construct {",
|
|
1104
|
+
" public readonly lambda: NodejsFunction;",
|
|
1105
|
+
" public readonly rule: Rule;",
|
|
1106
|
+
"",
|
|
1107
|
+
" constructor(scope: Construct, props: MyLambdaProps) {",
|
|
1108
|
+
' super(scope, "my-lambda");',
|
|
1109
|
+
"",
|
|
1110
|
+
' this.lambda = new NodejsFunction(this, "handler", { /* ... */ });',
|
|
1111
|
+
" props.dataStoreTable.grantReadWriteData(this.lambda);",
|
|
1112
|
+
' this.rule = new Rule(this, "rule", {',
|
|
1113
|
+
" eventBus: props.eventBus,",
|
|
1114
|
+
" eventPattern: { /* ... */ },",
|
|
1115
|
+
" targets: [new LambdaFunction(this.lambda)],",
|
|
1116
|
+
" });",
|
|
1117
|
+
" }",
|
|
1118
|
+
"}",
|
|
1119
|
+
"```",
|
|
1120
|
+
"",
|
|
1121
|
+
"A workflow or service construct then composes these Lambda constructs",
|
|
1122
|
+
"without owning their triggers or grants directly.",
|
|
1123
|
+
"",
|
|
1083
1124
|
"## CDK Testing",
|
|
1084
1125
|
"",
|
|
1085
1126
|
"- Mock `Code.fromAsset` in any test file that synthesizes CDK stacks",
|
|
@@ -3361,6 +3402,7 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
3361
3402
|
"- **After modifying Projen configuration**, run the three-step regen sequence: `pnpm i`, then `pnpm exec projen`, then `pnpm i` again. The leading `pnpm i` syncs `node_modules` with the lockfile so synth runs against the right configulator/projen/plugin versions; the trailing `pnpm i` refreshes the lockfile to match anything projen rewrote in `package.json`.",
|
|
3362
3403
|
"- **Configure dependencies through Projen** \u2014 never use `npm install`, `pnpm add`, or `yarn add`. Add them to `deps` or `devDeps` in Projen config.",
|
|
3363
3404
|
"- **Export from index.ts** to maintain clean public APIs",
|
|
3405
|
+
'- **`defaultMode: "dontAsk"` is configulator\'s hardcoded default** for the rendered Claude Code `settings.json`. Scheduled-task workers (issue-worker, orchestrator, pr-reviewer, and the analyst/writer family) run autonomously and would deadlock on confirmation prompts, so the synthesised default suppresses them. Override only after revisiting the autonomous-worker contract end-to-end; the override path is `claudeSettings.defaultMode` on `AgentConfigOptions`.',
|
|
3364
3406
|
"",
|
|
3365
3407
|
"## Repository Layout",
|
|
3366
3408
|
"",
|
|
@@ -5836,11 +5878,11 @@ function buildBusinessModelsBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
|
|
|
5836
5878
|
var businessModelsBundle = buildBusinessModelsBundle();
|
|
5837
5879
|
|
|
5838
5880
|
// src/agent/bundles/company-profile.ts
|
|
5839
|
-
function buildCompanyProfileAnalystSubAgent(paths, issueDefaults) {
|
|
5881
|
+
function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
5840
5882
|
return {
|
|
5841
5883
|
name: "company-profile-analyst",
|
|
5842
5884
|
description: "Researches an external company (competitor, vendor, partner, customer, etc.) from public sources and produces a structured markdown profile, then enqueues downstream `people:research` and `software:research` issues for notable people and software products surfaced during profiling. Also handles profile enrichment against business-model canvases (`company:match`), maintenance refreshes on a configurable staleness cadence (`company:refresh`), and cross-profile competitive synthesis for a segment (`company:analyze`). One company or segment per session, tracked by company:* GitHub issue labels.",
|
|
5843
|
-
model:
|
|
5885
|
+
model: tier,
|
|
5844
5886
|
maxTurns: 80,
|
|
5845
5887
|
platforms: { cursor: { exclude: true } },
|
|
5846
5888
|
prompt: [
|
|
@@ -7027,7 +7069,7 @@ function buildAnalyzeSegmentSkill(paths, issueDefaults) {
|
|
|
7027
7069
|
].join("\n")
|
|
7028
7070
|
};
|
|
7029
7071
|
}
|
|
7030
|
-
function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
7072
|
+
function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
|
|
7031
7073
|
return {
|
|
7032
7074
|
name: "company-profile",
|
|
7033
7075
|
description: "Company research and profiling pipeline: research, draft profile, followup, match, refresh, analyze. Enabled by default; domain-neutral; filesystem-durable between phases. Phase 3 (Followup) hands surfaced people and software products off to the `people-profile` and `software-profile` bundles via `people:research` and `software:research` issues. Phase 4 (Match) enriches profiles against business-model canvases. Phase 5 (Refresh) re-verifies profiles on a configurable staleness cadence. Phase 6 (Analyze) synthesizes profiles in a segment into a competitive-analysis document.",
|
|
@@ -7085,7 +7127,7 @@ function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
|
|
|
7085
7127
|
buildRefreshCompanySkill(paths, issueDefaults),
|
|
7086
7128
|
buildAnalyzeSegmentSkill(paths, issueDefaults)
|
|
7087
7129
|
],
|
|
7088
|
-
subAgents: [buildCompanyProfileAnalystSubAgent(paths, issueDefaults)],
|
|
7130
|
+
subAgents: [buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier)],
|
|
7089
7131
|
labels: [
|
|
7090
7132
|
{
|
|
7091
7133
|
name: "type:company-profile",
|
|
@@ -7265,11 +7307,11 @@ var CUSTOMER_PROFILE_REFERENCE_FILES = [
|
|
|
7265
7307
|
content: TEMPLATE_CUSTOMER_PROFILE
|
|
7266
7308
|
}
|
|
7267
7309
|
];
|
|
7268
|
-
function buildCustomerProfileAnalystSubAgent(paths, issueDefaults) {
|
|
7310
|
+
function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
7269
7311
|
return {
|
|
7270
7312
|
name: "customer-profile-analyst",
|
|
7271
7313
|
description: "Authors customer-archetype research through a 3-phase pipeline (discover \u2192 profile \u2192 competitors). Segments customer archetypes, profiles each archetype's goals, jobs-to-be-done, constraints, and buying process, then maps competitor features (from the shared software-profile feature matrix) to each archetype's needs and hands off unmet-need gaps to the requirements-analyst as req:scan seeds. One phase per session, tracked by customer:* GitHub issue labels with filesystem-based durability between phases.",
|
|
7272
|
-
model:
|
|
7314
|
+
model: tier,
|
|
7273
7315
|
maxTurns: 80,
|
|
7274
7316
|
platforms: { cursor: { exclude: true } },
|
|
7275
7317
|
prompt: [
|
|
@@ -8094,7 +8136,7 @@ function buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults) {
|
|
|
8094
8136
|
].join("\n")
|
|
8095
8137
|
};
|
|
8096
8138
|
}
|
|
8097
|
-
function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
8139
|
+
function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
|
|
8098
8140
|
return {
|
|
8099
8141
|
name: "customer-profile",
|
|
8100
8142
|
description: "Customer-archetype research pipeline: discover, profile, competitors. 3 phases with customer:* phase labels. Segments customer archetypes, profiles each archetype's goals, jobs-to-be-done, constraints, and buying process, then maps competitor features (from the shared software-profile feature matrix) to each archetype's needs and hands off unmet-need gaps to the requirements-analyst bundle as req:scan seeds. Enabled by default; domain-neutral; customer-centric (distinct from company-profile); filesystem-durable between phases.",
|
|
@@ -8169,7 +8211,9 @@ function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
|
|
|
8169
8211
|
buildProfileCustomerSkill(paths, issueDefaults),
|
|
8170
8212
|
buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults)
|
|
8171
8213
|
],
|
|
8172
|
-
subAgents: [
|
|
8214
|
+
subAgents: [
|
|
8215
|
+
buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier)
|
|
8216
|
+
],
|
|
8173
8217
|
labels: [
|
|
8174
8218
|
{
|
|
8175
8219
|
name: "type:customer-profile",
|
|
@@ -9952,11 +9996,11 @@ var jestBundle = {
|
|
|
9952
9996
|
};
|
|
9953
9997
|
|
|
9954
9998
|
// src/agent/bundles/maintenance-audit.ts
|
|
9955
|
-
function buildMaintenanceAuditSubAgent(paths) {
|
|
9999
|
+
function buildMaintenanceAuditSubAgent(paths, tier) {
|
|
9956
10000
|
return {
|
|
9957
10001
|
name: "maintenance-audit",
|
|
9958
10002
|
description: "Audits documentation registries and cross-references for integrity (broken links, registry drift, stale indexes), applies idempotent fixes, then re-runs the checks to confirm the fixes cleared the reported findings. One phase per session, tracked by maint:* GitHub issue labels with filesystem-based durability between phases.",
|
|
9959
|
-
model:
|
|
10003
|
+
model: tier,
|
|
9960
10004
|
maxTurns: 80,
|
|
9961
10005
|
platforms: { cursor: { exclude: true } },
|
|
9962
10006
|
prompt: [
|
|
@@ -10590,7 +10634,7 @@ function buildMaintenanceVerifySkill(issueDefaults) {
|
|
|
10590
10634
|
].join("\n")
|
|
10591
10635
|
};
|
|
10592
10636
|
}
|
|
10593
|
-
function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
10637
|
+
function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
|
|
10594
10638
|
return {
|
|
10595
10639
|
name: "maintenance-audit",
|
|
10596
10640
|
description: "Documentation-maintenance agent bundle. 3-phase pipeline (scan, fix, verify) with maint:* phase labels for auditing registries and cross-references, applying idempotent fixes, and confirming the fixes cleared the originally-flagged findings. Enabled by default.",
|
|
@@ -10637,7 +10681,7 @@ function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults
|
|
|
10637
10681
|
buildMaintenanceAuditSkill(paths, issueDefaults),
|
|
10638
10682
|
buildMaintenanceVerifySkill(issueDefaults)
|
|
10639
10683
|
],
|
|
10640
|
-
subAgents: [buildMaintenanceAuditSubAgent(paths)],
|
|
10684
|
+
subAgents: [buildMaintenanceAuditSubAgent(paths, tier)],
|
|
10641
10685
|
labels: [
|
|
10642
10686
|
{
|
|
10643
10687
|
name: "type:maintenance",
|
|
@@ -10665,351 +10709,353 @@ function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults
|
|
|
10665
10709
|
var maintenanceAuditBundle = buildMaintenanceAuditBundle();
|
|
10666
10710
|
|
|
10667
10711
|
// src/agent/bundles/meeting-analysis.ts
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10675
|
-
|
|
10676
|
-
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
|
|
10680
|
-
|
|
10681
|
-
|
|
10682
|
-
|
|
10683
|
-
|
|
10684
|
-
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10810
|
-
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10832
|
-
|
|
10833
|
-
|
|
10834
|
-
|
|
10835
|
-
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10840
|
-
|
|
10841
|
-
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10845
|
-
|
|
10846
|
-
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
|
|
10872
|
-
|
|
10873
|
-
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
|
|
10884
|
-
|
|
10885
|
-
|
|
10886
|
-
|
|
10887
|
-
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
10891
|
-
|
|
10892
|
-
|
|
10893
|
-
|
|
10894
|
-
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
|
|
10898
|
-
|
|
10899
|
-
|
|
10900
|
-
|
|
10901
|
-
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
|
|
11005
|
-
|
|
11006
|
-
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
10712
|
+
function buildMeetingAnalystSubAgent(tier) {
|
|
10713
|
+
return {
|
|
10714
|
+
name: "meeting-analyst",
|
|
10715
|
+
description: "Processes meeting transcripts through a 4-phase pipeline: extract, notes, draft, and link",
|
|
10716
|
+
model: tier,
|
|
10717
|
+
maxTurns: 80,
|
|
10718
|
+
platforms: { cursor: { exclude: true } },
|
|
10719
|
+
prompt: [
|
|
10720
|
+
"# Meeting Analyst Agent",
|
|
10721
|
+
"",
|
|
10722
|
+
"You process meeting transcripts through a structured 4-phase pipeline.",
|
|
10723
|
+
"Each phase runs as a **separate agent session**, triggered by its own",
|
|
10724
|
+
"GitHub issue with a `meeting:*` phase label. You handle exactly **one",
|
|
10725
|
+
"phase per session** \u2014 read the issue to determine which phase to execute.",
|
|
10726
|
+
"",
|
|
10727
|
+
"## Execution Model",
|
|
10728
|
+
"",
|
|
10729
|
+
"1. Each meeting produces up to 4 GitHub issues (one per phase)",
|
|
10730
|
+
"2. Each issue carries a `meeting:*` label identifying the phase",
|
|
10731
|
+
"3. You pick up one issue, execute that phase, commit/push, then close the issue",
|
|
10732
|
+
"4. Phase 1 (Extract) creates the downstream phase issues for phases 2-4",
|
|
10733
|
+
"5. Each downstream issue includes `Depends on: #N` linking to its predecessor",
|
|
10734
|
+
"",
|
|
10735
|
+
"## Design Principles",
|
|
10736
|
+
"",
|
|
10737
|
+
"1. **Extract, don't interpret.** Capture what was said and decided. Flag",
|
|
10738
|
+
" ambiguity as open items rather than resolving it.",
|
|
10739
|
+
"2. **Route to the right category.** Meeting content maps to requirements,",
|
|
10740
|
+
" ADRs, product docs, and business strategy. Each output goes to the",
|
|
10741
|
+
" correct location per the project's taxonomy.",
|
|
10742
|
+
"3. **Preserve provenance.** Every extracted item links back to the meeting",
|
|
10743
|
+
" source so reviewers can check context.",
|
|
10744
|
+
"4. **Create issues, not documents.** For requirements and ADRs, create",
|
|
10745
|
+
" GitHub issues that other agents or humans will pick up. Do not write",
|
|
10746
|
+
" final requirement documents yourself.",
|
|
10747
|
+
"5. **Bi-directional traceability.** Every document and issue created by",
|
|
10748
|
+
" this pipeline must link back to the meeting source, and the meeting",
|
|
10749
|
+
" source documents must link forward to everything created from them.",
|
|
10750
|
+
"6. **Respect meeting type and areas.** Read the `meeting_type` and",
|
|
10751
|
+
" `areas` values from the meeting frontmatter before starting Phase 1.",
|
|
10752
|
+
" Apply the type-specific rules from the **Meeting type handling**",
|
|
10753
|
+
" table (phases 1\u20132) and the area-filtered routing rules from the",
|
|
10754
|
+
" **Areas filtering** table (phase 4).",
|
|
10755
|
+
"",
|
|
10756
|
+
"---",
|
|
10757
|
+
"",
|
|
10758
|
+
"## Meeting type handling",
|
|
10759
|
+
"",
|
|
10760
|
+
"Meeting frontmatter is expected to carry a `meeting_type` field whose",
|
|
10761
|
+
"value is one of the project's concrete meeting-type `id`s (declared",
|
|
10762
|
+
"via `AgentConfigOptions.meetings.meetingTypes`). Each concrete `id`",
|
|
10763
|
+
"maps to one of six generic **meeting kinds** that drive type-specific",
|
|
10764
|
+
"extraction rules:",
|
|
10765
|
+
"",
|
|
10766
|
+
"| Kind | Primary outputs | Phase-1/2 rules |",
|
|
10767
|
+
"|------|-----------------|-----------------|",
|
|
10768
|
+
"| `planning` | Sprint/plan updates, task issues, requirement drafts | Extract every task assignment. Phase 4 updates the active sprint-plan doc directly and creates one issue per assigned task. |",
|
|
10769
|
+
"| `review` | Retro notes, follow-up issues, status updates, requirement revisions | Mark completed tasks in the active sprint-plan doc. Capture retrospective learnings inside the meeting notes \u2014 do not spawn a separate retro document. |",
|
|
10770
|
+
"| `brainstorm` | Future-feature candidates, research topics, very few Firm decisions | Lower the bar for Open Questions. Do **not** create requirement or ADR issues from brainstorm output unless the item is explicitly marked **Firm**. Prefer research/discovery issues for promising ideas. |",
|
|
10771
|
+
"| `standup` | Action items, blockers, status updates | Do not produce requirement, ADR, or BDR drafts. Phase 3 (Draft) is almost always skipped. Focus on action-item issues and sprint-plan status updates. |",
|
|
10772
|
+
"| `external` | Customer/competitive intel, people/company profiles, lead capture | Default every attendee outside the team into **People of Interest**. Default every organization mentioned into **Companies of Interest** (signal threshold still applies). Capture stated customer pain points as candidate **BR** (business requirements), not FR. |",
|
|
10773
|
+
"| `other` | General meeting extraction | Apply the default workflow with no type-specific overrides. |",
|
|
10774
|
+
"",
|
|
10775
|
+
"**How to resolve the kind:**",
|
|
10776
|
+
"",
|
|
10777
|
+
"1. Read `meeting_type` from the frontmatter.",
|
|
10778
|
+
"2. Look up the matching `id` in the project's **Recognized meeting",
|
|
10779
|
+
" types** table (rendered below when `meetingTypes` is declared).",
|
|
10780
|
+
"3. Use the `Kind` column value. If the table is absent, the `id` is",
|
|
10781
|
+
" unknown, or the `Kind` column is `\u2014`, fall back to `other`.",
|
|
10782
|
+
"4. Apply the rules in the row above **in addition to** the normal",
|
|
10783
|
+
" phase workflow \u2014 never as a replacement.",
|
|
10784
|
+
"",
|
|
10785
|
+
"If `meeting_type` is missing, invalid, or the declared `id` is not in",
|
|
10786
|
+
"the project's table, note it in the extraction's Open Questions and",
|
|
10787
|
+
"proceed with the default workflow (treat as `other`).",
|
|
10788
|
+
"",
|
|
10789
|
+
"## Areas filtering",
|
|
10790
|
+
"",
|
|
10791
|
+
"Meeting frontmatter may carry an `areas: [...]` list whose values",
|
|
10792
|
+
"match `id`s from the project's **Area \u2192 doc-root mapping** table",
|
|
10793
|
+
"(declared via `AgentConfigOptions.meetings.meetingAreas`). The list",
|
|
10794
|
+
"scopes phase-4 direct edits and cross-references to the doc-root",
|
|
10795
|
+
"sub-folders registered for those areas. A given area's effective",
|
|
10796
|
+
"path resolves as `<docsRoot>/<docRoot>` \u2014 `docsRoot` comes from",
|
|
10797
|
+
"`AgentPathsConfig.docsRoot`; `docRoot` is the sub-folder shown in",
|
|
10798
|
+
"the **Area \u2192 doc-root mapping** table.",
|
|
10799
|
+
"",
|
|
10800
|
+
"**Gating contract (phase 4 only):**",
|
|
10801
|
+
"",
|
|
10802
|
+
"- **Scoped in:** direct edits and cross-reference stubs under the",
|
|
10803
|
+
" `docRoot` of every `id` present in the meeting's `areas` list.",
|
|
10804
|
+
"- **Scoped out:** direct edits to any doc-root sub-folder that is",
|
|
10805
|
+
" declared in the project's area map but whose `id` is **not** in",
|
|
10806
|
+
" the meeting's `areas`. For those out-of-scope areas, create",
|
|
10807
|
+
" follow-up issues instead of editing the doc directly.",
|
|
10808
|
+
"- **Not gated:** issue creation (requirements, ADRs, profiles,",
|
|
10809
|
+
" research) is always in scope regardless of areas.",
|
|
10810
|
+
"",
|
|
10811
|
+
"**Resolution rules:**",
|
|
10812
|
+
"",
|
|
10813
|
+
"1. If the meeting's `areas` frontmatter is missing or empty **and**",
|
|
10814
|
+
" the project has declared a non-empty `meetingAreas` map, no",
|
|
10815
|
+
" doc-root sub-folder is gated in: direct edits to any declared",
|
|
10816
|
+
" `docRoot` sub-folder are out-of-scope and become follow-up issues",
|
|
10817
|
+
" per step 6. Only the default meetings root (`meetingsRoot`)",
|
|
10818
|
+
" remains editable.",
|
|
10819
|
+
"2. If `areas` lists an `id` that is not in the project's area map,",
|
|
10820
|
+
" note it in the extraction's Open Questions and treat the unknown",
|
|
10821
|
+
" `id` as absent. Do **not** invent a doc-root path for it.",
|
|
10822
|
+
"3. Out-of-scope direct edits become `type:docs` follow-up issues on",
|
|
10823
|
+
" phase 4 step 6, with the area noted in the issue body.",
|
|
10824
|
+
"",
|
|
10825
|
+
"When the project has **not** declared any `meetingAreas` at all,",
|
|
10826
|
+
"this section applies degenerately \u2014 no areas are gated, no",
|
|
10827
|
+
"follow-up issues are synthesized for missing areas, and phase-4",
|
|
10828
|
+
"direct edits follow the default workflow (step 6 edits any doc",
|
|
10829
|
+
"flagged as Firm, unrestricted by `docRoot`).",
|
|
10830
|
+
"",
|
|
10831
|
+
"---",
|
|
10832
|
+
"",
|
|
10833
|
+
...PROJECT_CONTEXT_MAINTAINER_SECTION,
|
|
10834
|
+
"## Traceability",
|
|
10835
|
+
"",
|
|
10836
|
+
"All outputs must be bi-directionally linked so any artifact can be traced",
|
|
10837
|
+
"back to the meeting that produced it and forward to everything it spawned.",
|
|
10838
|
+
"",
|
|
10839
|
+
"### Backward links (created artifact \u2192 meeting source)",
|
|
10840
|
+
"",
|
|
10841
|
+
"Every GitHub issue and document created by this pipeline must include a",
|
|
10842
|
+
"`## Traceability` section with:",
|
|
10843
|
+
"",
|
|
10844
|
+
"```markdown",
|
|
10845
|
+
"## Traceability",
|
|
10846
|
+
"",
|
|
10847
|
+
"- **Source meeting:** <path to transcript or meeting notes>",
|
|
10848
|
+
"- **Extraction:** <path to extraction file>",
|
|
10849
|
+
"- **Phase issue:** #<N> (the phase issue that created this artifact)",
|
|
10850
|
+
"```",
|
|
10851
|
+
"",
|
|
10852
|
+
"### Forward links (meeting source \u2192 created artifacts)",
|
|
10853
|
+
"",
|
|
10854
|
+
"After Phase 4 (Link) creates all follow-up issues and documents:",
|
|
10855
|
+
"",
|
|
10856
|
+
"1. **Update the extraction file** with a `## Downstream Artifacts` section",
|
|
10857
|
+
" listing every issue and document created from this meeting:",
|
|
10858
|
+
"",
|
|
10859
|
+
" ```markdown",
|
|
10860
|
+
" ## Downstream Artifacts",
|
|
10861
|
+
"",
|
|
10862
|
+
" | Artifact | Type | Issue/Path |",
|
|
10863
|
+
" |----------|------|------------|",
|
|
10864
|
+
" | <title> | requirement / ADR / action-item / profile | #<N> or <path> |",
|
|
10865
|
+
" ```",
|
|
10866
|
+
"",
|
|
10867
|
+
"2. **Update the meeting notes** with a similar `## Related Issues` section",
|
|
10868
|
+
" listing all issues created from this meeting.",
|
|
10869
|
+
"",
|
|
10870
|
+
"3. **Comment on the extract issue** with a summary linking to all created",
|
|
10871
|
+
" artifacts.",
|
|
10872
|
+
"",
|
|
10873
|
+
"### Within-pipeline links",
|
|
10874
|
+
"",
|
|
10875
|
+
"- Phase issues link to predecessors via `Depends on: #N`",
|
|
10876
|
+
"- Phase issues reference the extraction file path in their body",
|
|
10877
|
+
"- Draft documents reference both the extraction and the meeting notes",
|
|
10878
|
+
"",
|
|
10879
|
+
"---",
|
|
10880
|
+
"",
|
|
10881
|
+
"## Phase 1: Extract (`meeting:extract`)",
|
|
10882
|
+
"",
|
|
10883
|
+
"**Goal:** Read the meeting transcript and categorize all substantive content.",
|
|
10884
|
+
"",
|
|
10885
|
+
"### Steps",
|
|
10886
|
+
"",
|
|
10887
|
+
"1. Read the transcript file specified in the issue body. Parse the",
|
|
10888
|
+
" meeting-note frontmatter first, capturing `meeting_type` and",
|
|
10889
|
+
" `areas`. Resolve `meeting_type` to a kind using the **Meeting type",
|
|
10890
|
+
" handling** table; note the resolved kind in the extraction",
|
|
10891
|
+
" frontmatter. If `meeting_type` is missing or not in the project's",
|
|
10892
|
+
" Recognized meeting types table, treat it as `other` and flag it",
|
|
10893
|
+
" in Open Questions.",
|
|
10894
|
+
"2. Identify and categorize content into these buckets:",
|
|
10895
|
+
"",
|
|
10896
|
+
" | Bucket | What to look for |",
|
|
10897
|
+
" |--------|-----------------|",
|
|
10898
|
+
` | **Decisions** | "We decided...", "Let's go with...", explicit choices |`,
|
|
10899
|
+
' | **Requirements** | Feature descriptions, acceptance criteria, "it should..." |',
|
|
10900
|
+
" | **Technology discussions** | Platform comparisons, architecture options, tool evaluations |",
|
|
10901
|
+
' | **Action items** | "[Person] will...", "Next step is...", assigned tasks |',
|
|
10902
|
+
' | **Open questions** | "We need to figure out...", unresolved debates |',
|
|
10903
|
+
" | **People of interest** | Industry contacts, domain experts mentioned |",
|
|
10904
|
+
" | **Companies of interest** | Competitors, vendors, partners discussed |",
|
|
10905
|
+
" | **Strategic direction** | Business model changes, market positioning |",
|
|
10906
|
+
" | **Product direction** | Roadmap changes, feature prioritization |",
|
|
10907
|
+
"",
|
|
10908
|
+
"3. Write the extraction to a markdown file with structured sections:",
|
|
10909
|
+
" - Attendees",
|
|
10910
|
+
" - Decisions Made (with category and confidence: Firm / Tentative / Needs confirmation)",
|
|
10911
|
+
" - Requirements Identified (with category and priority estimate)",
|
|
10912
|
+
" - Technology Discussions (with status: Decided / Leaning toward / Open)",
|
|
10913
|
+
" - Action Items (with assignee and due date if stated)",
|
|
10914
|
+
" - Open Questions",
|
|
10915
|
+
" - People of Interest (with context and whether a profile exists)",
|
|
10916
|
+
" - Companies of Interest (with type and context)",
|
|
10917
|
+
" - Strategic / Product Direction",
|
|
10918
|
+
"",
|
|
10919
|
+
" Carry `meeting_type`, the resolved `meeting_kind`, and `areas`",
|
|
10920
|
+
" into the extraction frontmatter so downstream phases can gate",
|
|
10921
|
+
" behaviour without re-parsing the meeting note.",
|
|
10922
|
+
"",
|
|
10923
|
+
"4. **Apply type-specific rules.** Consult the **Meeting type handling**",
|
|
10924
|
+
" table for the resolved kind and apply its phase-1 rules in",
|
|
10925
|
+
" addition to the default extraction above. Examples:",
|
|
10926
|
+
" - `standup`: skip requirement, ADR, and BDR extraction; focus on",
|
|
10927
|
+
" action items and status.",
|
|
10928
|
+
" - `brainstorm`: emphasize Open Questions and Future Features.",
|
|
10929
|
+
" Only mark decisions as Firm when the transcript is unambiguous.",
|
|
10930
|
+
" - `external`: default attendees outside the team into People of",
|
|
10931
|
+
" Interest; default organizations mentioned into Companies of",
|
|
10932
|
+
" Interest (signal threshold still applies); capture customer",
|
|
10933
|
+
" pain points as candidate BR (not FR).",
|
|
10934
|
+
"",
|
|
10935
|
+
"5. **Create downstream phase issues** using `gh issue create`:",
|
|
10936
|
+
" - Always create a `meeting:notes` issue (blocked on this extract issue)",
|
|
10937
|
+
" - If requirements OR decisions/ADRs identified, create a `meeting:draft` issue",
|
|
10938
|
+
" (blocked on the notes issue). For kind `standup`, skip the",
|
|
10939
|
+
" `meeting:draft` issue \u2014 standup meetings almost never produce",
|
|
10940
|
+
" formal drafts.",
|
|
10941
|
+
" - Always create a `meeting:link` issue \u2014 blocked on the draft issue if one",
|
|
10942
|
+
" was created, otherwise blocked on the notes issue",
|
|
10943
|
+
"",
|
|
10944
|
+
"6. Commit, push, and close the extract issue.",
|
|
10945
|
+
"",
|
|
10946
|
+
"---",
|
|
10947
|
+
"",
|
|
10948
|
+
"## Phase 2: Notes (`meeting:notes`)",
|
|
10949
|
+
"",
|
|
10950
|
+
"**Goal:** Transform the extraction into structured meeting notes.",
|
|
10951
|
+
"",
|
|
10952
|
+
"### Steps",
|
|
10953
|
+
"",
|
|
10954
|
+
"1. Read the extraction file referenced in the issue body (output of Phase 1).",
|
|
10955
|
+
"2. Write structured meeting notes with these sections:",
|
|
10956
|
+
" - Meeting metadata (title, date, attendees)",
|
|
10957
|
+
" - Agenda / topics covered",
|
|
10958
|
+
" - Key Discussion Points (organized by topic)",
|
|
10959
|
+
" - Decisions (numbered, with rationale)",
|
|
10960
|
+
" - Action Items (table: who, what, when)",
|
|
10961
|
+
" - Open Questions",
|
|
10962
|
+
" - Follow-up items",
|
|
10963
|
+
"3. Commit, push, and close the notes issue.",
|
|
10964
|
+
"",
|
|
10965
|
+
"---",
|
|
10966
|
+
"",
|
|
10967
|
+
"## Phase 3: Draft (`meeting:draft`)",
|
|
10968
|
+
"",
|
|
10969
|
+
"**Goal:** Draft proposals for requirements, ADRs, and product/strategy updates.",
|
|
10970
|
+
"",
|
|
10971
|
+
"This phase only exists if the extraction identified requirements, architectural",
|
|
10972
|
+
"decisions, or strategy changes. If this issue exists, execute it.",
|
|
10973
|
+
"",
|
|
10974
|
+
"### Steps",
|
|
10975
|
+
"",
|
|
10976
|
+
"1. Read the extraction file from Phase 1.",
|
|
10977
|
+
"2. Check existing requirement registries and ADR registries for duplicates.",
|
|
10978
|
+
"3. Draft requirement proposals with:",
|
|
10979
|
+
" - Category (FR, BR, NFR, etc.)",
|
|
10980
|
+
" - Summary (2-3 sentences)",
|
|
10981
|
+
" - Draft acceptance criteria",
|
|
10982
|
+
" - Related existing requirements",
|
|
10983
|
+
"4. Draft ADR proposals for technology decisions with:",
|
|
10984
|
+
" - Context and problem statement",
|
|
10985
|
+
" - Options discussed",
|
|
10986
|
+
" - Stated preferences or decisions",
|
|
10987
|
+
" - Status: Proposed or Decided",
|
|
10988
|
+
"5. Summarize product/strategy document updates needed.",
|
|
10989
|
+
"6. Commit, push, and close the draft issue.",
|
|
10990
|
+
"",
|
|
10991
|
+
"---",
|
|
10992
|
+
"",
|
|
10993
|
+
"## Phase 4: Link (`meeting:link`)",
|
|
10994
|
+
"",
|
|
10995
|
+
"**Goal:** Create GitHub issues for follow-up work, cross-reference the",
|
|
10996
|
+
"meeting into existing documentation, and complete bi-directional traceability.",
|
|
10997
|
+
"",
|
|
10998
|
+
"### Steps",
|
|
10999
|
+
"",
|
|
11000
|
+
"1. Read the drafts from Phase 3 (if they exist) and the extraction from Phase 1.",
|
|
11001
|
+
" Re-read the extraction frontmatter for `meeting_kind` and `areas`,",
|
|
11002
|
+
" then build the area-gate: the set of `docRoot` sub-folders that",
|
|
11003
|
+
" are in scope for direct edits on this meeting. Apply the rules in",
|
|
11004
|
+
" the **Areas filtering** section above.",
|
|
11005
|
+
"2. Create requirement issues using `gh issue create` with appropriate labels.",
|
|
11006
|
+
" Include a `## Traceability` section in each issue body linking back to",
|
|
11007
|
+
" the source meeting and extraction file. Issue creation is **not**",
|
|
11008
|
+
" gated by areas.",
|
|
11009
|
+
"3. Create ADR issues if technology decisions need formal records.",
|
|
11010
|
+
" Include a `## Traceability` section in each. Not gated by areas.",
|
|
11011
|
+
"4. Create action item issues for tasks that are not document-related.",
|
|
11012
|
+
" Include a `## Traceability` section in each. Not gated by areas.",
|
|
11013
|
+
"5. Cross-reference the meeting in any existing documents that were",
|
|
11014
|
+
" discussed **and that live under an in-scope `docRoot`**. For",
|
|
11015
|
+
" discussed documents under an out-of-scope `docRoot`, open a",
|
|
11016
|
+
" follow-up `type:docs` issue instead of editing the doc directly.",
|
|
11017
|
+
"6. Apply direct product/strategy doc updates for items flagged as",
|
|
11018
|
+
" **Firm** confidence. When the project declares `meetingAreas`,",
|
|
11019
|
+
" gate these edits: only apply them when the target path lies",
|
|
11020
|
+
" under an in-scope `docRoot`, and for Firm items targeting an",
|
|
11021
|
+
" out-of-scope `docRoot` open a follow-up `type:docs` issue",
|
|
11022
|
+
" noting the area and the target path. When the project has not",
|
|
11023
|
+
" declared any `meetingAreas`, apply Firm updates unrestricted",
|
|
11024
|
+
" (the degenerate case above). For the kind `planning`, also",
|
|
11025
|
+
" update the active sprint-plan doc directly (when the",
|
|
11026
|
+
" sprint-plan doc's area is in-scope, or always when no",
|
|
11027
|
+
" `meetingAreas` are declared); for the kind `review`, mark",
|
|
11028
|
+
" completed tasks in that same doc.",
|
|
11029
|
+
"7. **Update the extraction file** with a `## Downstream Artifacts` section",
|
|
11030
|
+
" listing every issue and document created from this meeting. Note",
|
|
11031
|
+
" any items that were deferred to follow-up issues because of the",
|
|
11032
|
+
" area gate.",
|
|
11033
|
+
"8. **Update the meeting notes** with a `## Related Issues` section listing",
|
|
11034
|
+
" all issues created from this meeting.",
|
|
11035
|
+
"9. Comment on the parent extract issue with a summary linking to all",
|
|
11036
|
+
" created artifacts.",
|
|
11037
|
+
"10. Commit and push (if any file changes were made), then close the link issue.",
|
|
11038
|
+
"",
|
|
11039
|
+
"---",
|
|
11040
|
+
"",
|
|
11041
|
+
"## GitHub Integration",
|
|
11042
|
+
"",
|
|
11043
|
+
"- Use `gh` CLI for all GitHub operations",
|
|
11044
|
+
"- Apply the appropriate `meeting:*` phase label to each phase issue",
|
|
11045
|
+
"- Use `type:docs` for documentation-producing issues, `type:chore` for",
|
|
11046
|
+
" maintenance/organizational tasks",
|
|
11047
|
+
"- Use `status:` labels to track progress (`status:ready`, `status:in-progress`, `status:done`)",
|
|
11048
|
+
"- Reference the source meeting transcript in all created issues",
|
|
11049
|
+
"- Link phase issues with `Depends on: #N` to enforce ordering",
|
|
11050
|
+
"",
|
|
11051
|
+
"## When to Shorten the Pipeline",
|
|
11052
|
+
"",
|
|
11053
|
+
"- **Short meetings** (<30 min, <2000 words): combine extract + notes into one session",
|
|
11054
|
+
"- **No requirements or decisions**: Phase 1 skips creating the `meeting:draft` issue",
|
|
11055
|
+
"- **Only action items**: extract + notes + link (3 phase issues)"
|
|
11056
|
+
].join("\n")
|
|
11057
|
+
};
|
|
11058
|
+
}
|
|
11013
11059
|
var processMeetingSkill = {
|
|
11014
11060
|
name: "process-meeting",
|
|
11015
11061
|
description: "Process a meeting transcript through the 4-phase meeting analysis pipeline",
|
|
@@ -11053,64 +11099,67 @@ var processMeetingSkill = {
|
|
|
11053
11099
|
" to pick up (notes, draft, link)"
|
|
11054
11100
|
].join("\n")
|
|
11055
11101
|
};
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11102
|
+
function buildMeetingAnalysisBundle(tier = AGENT_MODEL.BALANCED) {
|
|
11103
|
+
return {
|
|
11104
|
+
name: "meeting-analysis",
|
|
11105
|
+
description: "Meeting transcript processing workflow with 4-phase pipeline (extract, notes, draft, link)",
|
|
11106
|
+
appliesWhen: () => true,
|
|
11107
|
+
rules: [
|
|
11108
|
+
{
|
|
11109
|
+
name: "meeting-processing-workflow",
|
|
11110
|
+
description: "Describes the 4-phase meeting processing pipeline, extraction taxonomy, and labeling conventions",
|
|
11111
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
11112
|
+
content: [
|
|
11113
|
+
"# Meeting Processing Workflow",
|
|
11114
|
+
"",
|
|
11115
|
+
"Use `/process-meeting <path>` to process a meeting transcript through a",
|
|
11116
|
+
"4-phase pipeline (extract \u2192 notes \u2192 draft \u2192 link). Each phase runs as a",
|
|
11117
|
+
"separate agent session tracked by a GitHub issue with a `meeting:*` label.",
|
|
11118
|
+
"See the `meeting-analyst` agent definition for full workflow details.",
|
|
11119
|
+
"",
|
|
11120
|
+
"Meeting notes may declare a `meeting_type` (one of the project's",
|
|
11121
|
+
"recognized types) and an `areas: [...]` list. The `meeting_type`",
|
|
11122
|
+
"resolves to a generic kind \u2014 `planning` / `review` / `brainstorm` /",
|
|
11123
|
+
"`standup` / `external` / `other` \u2014 that drives type-specific",
|
|
11124
|
+
"extraction rules in phases 1\u20132. The `areas` list scopes phase-4",
|
|
11125
|
+
"direct edits to the doc-root sub-folders declared in the project's",
|
|
11126
|
+
"**Area \u2192 doc-root mapping** table. When both fields are absent",
|
|
11127
|
+
"the pipeline falls back to the default workflow (kind `other`,",
|
|
11128
|
+
"no area gating)."
|
|
11129
|
+
].join("\n"),
|
|
11130
|
+
platforms: {
|
|
11131
|
+
cursor: { exclude: true }
|
|
11132
|
+
},
|
|
11133
|
+
tags: ["workflow"]
|
|
11134
|
+
}
|
|
11135
|
+
],
|
|
11136
|
+
skills: [processMeetingSkill],
|
|
11137
|
+
subAgents: [buildMeetingAnalystSubAgent(tier)],
|
|
11138
|
+
labels: [
|
|
11139
|
+
{
|
|
11140
|
+
name: "meeting:extract",
|
|
11141
|
+
color: "C5DEF5",
|
|
11142
|
+
description: "Phase 1: raw extraction from a meeting transcript"
|
|
11085
11143
|
},
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
description: "Phase 3: draft follow-up issues proposed from notes"
|
|
11106
|
-
},
|
|
11107
|
-
{
|
|
11108
|
-
name: "meeting:link",
|
|
11109
|
-
color: "FEF2C0",
|
|
11110
|
-
description: "Phase 4: linking/reconciling drafted issues with existing work"
|
|
11111
|
-
}
|
|
11112
|
-
]
|
|
11113
|
-
};
|
|
11144
|
+
{
|
|
11145
|
+
name: "meeting:notes",
|
|
11146
|
+
color: "BFDADC",
|
|
11147
|
+
description: "Phase 2: curated notes derived from an extraction"
|
|
11148
|
+
},
|
|
11149
|
+
{
|
|
11150
|
+
name: "meeting:draft",
|
|
11151
|
+
color: "D4C5F9",
|
|
11152
|
+
description: "Phase 3: draft follow-up issues proposed from notes"
|
|
11153
|
+
},
|
|
11154
|
+
{
|
|
11155
|
+
name: "meeting:link",
|
|
11156
|
+
color: "FEF2C0",
|
|
11157
|
+
description: "Phase 4: linking/reconciling drafted issues with existing work"
|
|
11158
|
+
}
|
|
11159
|
+
]
|
|
11160
|
+
};
|
|
11161
|
+
}
|
|
11162
|
+
var meetingAnalysisBundle = buildMeetingAnalysisBundle();
|
|
11114
11163
|
|
|
11115
11164
|
// src/agent/bundles/run-ratio.ts
|
|
11116
11165
|
var DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO = 4;
|
|
@@ -13185,11 +13234,10 @@ function shellSingleQuote(value) {
|
|
|
13185
13234
|
}
|
|
13186
13235
|
|
|
13187
13236
|
// src/agent/bundles/orchestrator.ts
|
|
13188
|
-
function buildCheckBlockedScript(tiers, scopeGate,
|
|
13237
|
+
function buildCheckBlockedScript(tiers, scopeGate, _runRatio) {
|
|
13189
13238
|
const tierCase = renderAgentTierCaseStatement(tiers);
|
|
13190
13239
|
const scopeHelper = renderScopeGateShellHelpers(scopeGate);
|
|
13191
13240
|
const scopeHelperIndented = scopeHelper.split("\n").map((line) => line.length > 0 ? line : "").join("\n");
|
|
13192
|
-
const runRatioHelper = renderRunRatioShellHelpers(runRatio);
|
|
13193
13241
|
return [
|
|
13194
13242
|
"#!/usr/bin/env bash",
|
|
13195
13243
|
"# check-blocked.sh \u2014 Token-efficient issue triage for agent loops.",
|
|
@@ -13201,9 +13249,9 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13201
13249
|
"# .claude/procedures/check-blocked.sh eligible",
|
|
13202
13250
|
"# .claude/procedures/check-blocked.sh stale",
|
|
13203
13251
|
"# .claude/procedures/check-blocked.sh orphaned",
|
|
13252
|
+
"# .claude/procedures/check-blocked.sh maintenance",
|
|
13204
13253
|
"# .claude/procedures/check-blocked.sh prs",
|
|
13205
13254
|
"# .claude/procedures/check-blocked.sh scope <issue-number>",
|
|
13206
|
-
"# .claude/procedures/check-blocked.sh tick",
|
|
13207
13255
|
"",
|
|
13208
13256
|
"set -uo pipefail",
|
|
13209
13257
|
"",
|
|
@@ -13217,9 +13265,6 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13217
13265
|
`SCOPE_AC_MEDIUM_MAX=${scopeGate.acceptanceCriteria.mediumMax}`,
|
|
13218
13266
|
`SCOPE_SOURCES_SMALL_MAX=${scopeGate.sources.smallMax}`,
|
|
13219
13267
|
`SCOPE_SOURCES_MEDIUM_MAX=${scopeGate.sources.mediumMax}`,
|
|
13220
|
-
`RUN_RATIO_ENABLED=${runRatio.enabled ? "1" : "0"}`,
|
|
13221
|
-
`RUN_RATIO_DISPATCH_PER_HOUSEKEEPING=${runRatio.ratio}`,
|
|
13222
|
-
`ORCHESTRATOR_STATE_FILE="${runRatio.stateFilePath}"`,
|
|
13223
13268
|
"",
|
|
13224
13269
|
"# \u2500\u2500 helpers \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\u2500\u2500\u2500\u2500",
|
|
13225
13270
|
"",
|
|
@@ -13250,8 +13295,6 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13250
13295
|
"",
|
|
13251
13296
|
scopeHelperIndented,
|
|
13252
13297
|
"",
|
|
13253
|
-
runRatioHelper,
|
|
13254
|
-
"",
|
|
13255
13298
|
"# \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",
|
|
13256
13299
|
"",
|
|
13257
13300
|
"cmd_unblock() {",
|
|
@@ -13262,7 +13305,7 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13262
13305
|
" local count",
|
|
13263
13306
|
` count=$(echo "$issues" | jq 'length')`,
|
|
13264
13307
|
' if [[ "$count" -eq 0 ]]; then',
|
|
13265
|
-
' echo "
|
|
13308
|
+
' echo "TRIAGE_DONE unblocked=0 still_blocked=0"',
|
|
13266
13309
|
" return 0",
|
|
13267
13310
|
" fi",
|
|
13268
13311
|
"",
|
|
@@ -13273,18 +13316,36 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13273
13316
|
' "\\(.number)\\t\\($dep_line)"',
|
|
13274
13317
|
" ')",
|
|
13275
13318
|
"",
|
|
13319
|
+
" # Counters for the summary line. The orchestrator reads only",
|
|
13320
|
+
" # TRIAGE_DONE; the per-issue lines below are for log visibility,",
|
|
13321
|
+
" # mirroring unblock-dependents.sh.",
|
|
13322
|
+
" local unblocked_count=0",
|
|
13323
|
+
" local still_blocked_count=0",
|
|
13324
|
+
"",
|
|
13276
13325
|
" while IFS=$'\\t' read -r num dep_line; do",
|
|
13277
13326
|
' [[ -z "$num" ]] && continue',
|
|
13278
13327
|
"",
|
|
13279
13328
|
' if [[ -z "$dep_line" ]]; then',
|
|
13280
13329
|
' echo "BLOCKED #${num} \u2014 no Depends on field found"',
|
|
13330
|
+
" still_blocked_count=$((still_blocked_count + 1))",
|
|
13281
13331
|
" continue",
|
|
13282
13332
|
" fi",
|
|
13283
13333
|
"",
|
|
13284
13334
|
" local deps",
|
|
13285
13335
|
' deps=$(parse_deps "$dep_line")',
|
|
13286
13336
|
' if [[ -z "${deps// /}" ]]; then',
|
|
13287
|
-
|
|
13337
|
+
" # Empty dependency list \u2014 treat as eligible for unblocking.",
|
|
13338
|
+
' if gh issue edit "$num" \\',
|
|
13339
|
+
' --remove-label "status:blocked" \\',
|
|
13340
|
+
' --add-label "status:ready" >/dev/null 2>&1; then',
|
|
13341
|
+
' gh issue comment "$num" \\',
|
|
13342
|
+
' --body "Dependencies resolved \u2014 unblocking." >/dev/null 2>&1 || true',
|
|
13343
|
+
' echo "UNBLOCKED #${num} \u2014 no dependencies"',
|
|
13344
|
+
" unblocked_count=$((unblocked_count + 1))",
|
|
13345
|
+
" else",
|
|
13346
|
+
' echo "UNBLOCK_FAILED #${num} \u2014 label flip failed (no dependencies)"',
|
|
13347
|
+
" still_blocked_count=$((still_blocked_count + 1))",
|
|
13348
|
+
" fi",
|
|
13288
13349
|
" continue",
|
|
13289
13350
|
" fi",
|
|
13290
13351
|
"",
|
|
@@ -13301,11 +13362,30 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13301
13362
|
" done",
|
|
13302
13363
|
"",
|
|
13303
13364
|
" if $all_closed; then",
|
|
13304
|
-
|
|
13365
|
+
" # The label flip is the load-bearing edit; if it fails we must",
|
|
13366
|
+
" # report the failure so the orchestrator does not double-count.",
|
|
13367
|
+
" # The comment is best-effort (its absence is recoverable on the",
|
|
13368
|
+
" # next sweep), so a failed `gh issue comment` does not block the",
|
|
13369
|
+
" # unblock from being recorded as successful.",
|
|
13370
|
+
' if gh issue edit "$num" \\',
|
|
13371
|
+
' --remove-label "status:blocked" \\',
|
|
13372
|
+
' --add-label "status:ready" >/dev/null 2>&1; then',
|
|
13373
|
+
' gh issue comment "$num" \\',
|
|
13374
|
+
' --body "Dependencies resolved \u2014 unblocking." >/dev/null 2>&1 || true',
|
|
13375
|
+
' echo "UNBLOCKED #${num} \u2014 all deps closed (${closed_deps% })"',
|
|
13376
|
+
" unblocked_count=$((unblocked_count + 1))",
|
|
13377
|
+
" else",
|
|
13378
|
+
' echo "UNBLOCK_FAILED #${num} \u2014 label flip failed (all deps closed: ${closed_deps% })"',
|
|
13379
|
+
" still_blocked_count=$((still_blocked_count + 1))",
|
|
13380
|
+
" fi",
|
|
13305
13381
|
" else",
|
|
13306
|
-
' echo "
|
|
13382
|
+
' echo "STILL_BLOCKED #${num} \u2014 waiting on ${open_deps% }"',
|
|
13383
|
+
" still_blocked_count=$((still_blocked_count + 1))",
|
|
13307
13384
|
" fi",
|
|
13308
13385
|
' done <<< "$issue_data"',
|
|
13386
|
+
"",
|
|
13387
|
+
" # Single summary line consumed by the orchestrator.",
|
|
13388
|
+
' echo "TRIAGE_DONE unblocked=${unblocked_count} still_blocked=${still_blocked_count}"',
|
|
13309
13389
|
"}",
|
|
13310
13390
|
"",
|
|
13311
13391
|
"cmd_eligible() {",
|
|
@@ -13497,6 +13577,101 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13497
13577
|
" fi",
|
|
13498
13578
|
"}",
|
|
13499
13579
|
"",
|
|
13580
|
+
"cmd_maintenance() {",
|
|
13581
|
+
" # Phase D maintenance sweep: flag stale issues with",
|
|
13582
|
+
" # `status:needs-attention`, count orphan branches/PRs (no",
|
|
13583
|
+
" # auto-deletion), and emit a single MAINTENANCE_DONE summary",
|
|
13584
|
+
" # line so the orchestrator never iterates raw stale/orphan",
|
|
13585
|
+
" # output. Mirrors the discipline of cmd_unblock \u2014 per-issue",
|
|
13586
|
+
" # informational lines (FLAGGED #N, ORPHAN_BRANCH \u2026) survive",
|
|
13587
|
+
" # for log visibility but are not load-bearing for the",
|
|
13588
|
+
" # orchestrator.",
|
|
13589
|
+
" #",
|
|
13590
|
+
" # SAFETY: this subcommand NEVER auto-resets stale issues to",
|
|
13591
|
+
" # `status:ready`. It only adds `status:needs-attention`; the",
|
|
13592
|
+
" # existing `status:in-progress` or `status:blocked` label",
|
|
13593
|
+
" # stays in place so partial implementation work on a branch",
|
|
13594
|
+
" # remains visible to humans.",
|
|
13595
|
+
"",
|
|
13596
|
+
" local flagged_stale_count=0",
|
|
13597
|
+
" local flagged_blocked_count=0",
|
|
13598
|
+
" local orphan_branches_count=0",
|
|
13599
|
+
" local orphan_prs_count=0",
|
|
13600
|
+
"",
|
|
13601
|
+
" # \u2500\u2500 stale detection + flagging \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",
|
|
13602
|
+
" local stale_output",
|
|
13603
|
+
" stale_output=$(cmd_stale)",
|
|
13604
|
+
"",
|
|
13605
|
+
" while IFS= read -r line; do",
|
|
13606
|
+
' [[ -z "$line" ]] && continue',
|
|
13607
|
+
' case "$line" in',
|
|
13608
|
+
" 'STALE #'*)",
|
|
13609
|
+
" # Extract the issue number after the '#' and before the ' '.",
|
|
13610
|
+
" local num=${line#STALE #}",
|
|
13611
|
+
" num=${num%% *}",
|
|
13612
|
+
' if gh issue edit "$num" --add-label "status:needs-attention" >/dev/null 2>&1; then',
|
|
13613
|
+
' gh issue comment "$num" \\',
|
|
13614
|
+
' --body "Flagged: in-progress for >3 days with no activity." >/dev/null 2>&1 || true',
|
|
13615
|
+
' echo "FLAGGED_STALE #${num} \u2014 added status:needs-attention"',
|
|
13616
|
+
" flagged_stale_count=$((flagged_stale_count + 1))",
|
|
13617
|
+
" else",
|
|
13618
|
+
' echo "FLAG_FAILED #${num} \u2014 could not add status:needs-attention (stale)"',
|
|
13619
|
+
" fi",
|
|
13620
|
+
" # Surface the original informational line for log visibility.",
|
|
13621
|
+
' echo "$line"',
|
|
13622
|
+
" ;;",
|
|
13623
|
+
" 'STALE_BLOCKED #'*)",
|
|
13624
|
+
" local num=${line#STALE_BLOCKED #}",
|
|
13625
|
+
" num=${num%% *}",
|
|
13626
|
+
' if gh issue edit "$num" --add-label "status:needs-attention" >/dev/null 2>&1; then',
|
|
13627
|
+
' gh issue comment "$num" \\',
|
|
13628
|
+
' --body "Flagged: blocked for >7 days \u2014 may need human intervention." >/dev/null 2>&1 || true',
|
|
13629
|
+
' echo "FLAGGED_BLOCKED #${num} \u2014 added status:needs-attention"',
|
|
13630
|
+
" flagged_blocked_count=$((flagged_blocked_count + 1))",
|
|
13631
|
+
" else",
|
|
13632
|
+
' echo "FLAG_FAILED #${num} \u2014 could not add status:needs-attention (blocked)"',
|
|
13633
|
+
" fi",
|
|
13634
|
+
' echo "$line"',
|
|
13635
|
+
" ;;",
|
|
13636
|
+
" 'NO_STALE_ISSUES')",
|
|
13637
|
+
" # Surface the no-op marker for log visibility; counters",
|
|
13638
|
+
" # stay at zero.",
|
|
13639
|
+
' echo "$line"',
|
|
13640
|
+
" ;;",
|
|
13641
|
+
" esac",
|
|
13642
|
+
' done <<< "$stale_output"',
|
|
13643
|
+
"",
|
|
13644
|
+
" # \u2500\u2500 orphan detection (count only \u2014 no auto-deletion) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
13645
|
+
" local orphan_output",
|
|
13646
|
+
" orphan_output=$(cmd_orphaned)",
|
|
13647
|
+
"",
|
|
13648
|
+
" while IFS= read -r line; do",
|
|
13649
|
+
' [[ -z "$line" ]] && continue',
|
|
13650
|
+
' case "$line" in',
|
|
13651
|
+
" 'ORPHAN_BRANCH '*)",
|
|
13652
|
+
" orphan_branches_count=$((orphan_branches_count + 1))",
|
|
13653
|
+
' echo "$line"',
|
|
13654
|
+
" ;;",
|
|
13655
|
+
" 'ORPHAN_PR '*)",
|
|
13656
|
+
" orphan_prs_count=$((orphan_prs_count + 1))",
|
|
13657
|
+
' echo "$line"',
|
|
13658
|
+
" ;;",
|
|
13659
|
+
" 'NO_ORPHANED_RESOURCES')",
|
|
13660
|
+
' echo "$line"',
|
|
13661
|
+
" ;;",
|
|
13662
|
+
" esac",
|
|
13663
|
+
' done <<< "$orphan_output"',
|
|
13664
|
+
"",
|
|
13665
|
+
" # \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",
|
|
13666
|
+
" local needs_attention_total",
|
|
13667
|
+
' needs_attention_total=$(gh issue list --label "status:needs-attention" --state open \\',
|
|
13668
|
+
" --json number --limit 100 2>/dev/null | jq 'length' 2>/dev/null || echo 0)",
|
|
13669
|
+
" needs_attention_total=${needs_attention_total:-0}",
|
|
13670
|
+
"",
|
|
13671
|
+
" # Single summary line consumed by the orchestrator.",
|
|
13672
|
+
' 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}"',
|
|
13673
|
+
"}",
|
|
13674
|
+
"",
|
|
13500
13675
|
"cmd_prs() {",
|
|
13501
13676
|
" local prs",
|
|
13502
13677
|
" prs=$(gh pr list --state open --json number,title,isDraft,headRefName,labels,body \\",
|
|
@@ -13635,31 +13810,18 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13635
13810
|
" fi",
|
|
13636
13811
|
"}",
|
|
13637
13812
|
"",
|
|
13638
|
-
"cmd_tick() {",
|
|
13639
|
-
" # DEPRECATED: the orchestrator no longer maintains a dispatch /",
|
|
13640
|
-
" # housekeeping run-counter \u2014 every invocation runs the full",
|
|
13641
|
-
" # end-to-end cycle. This subcommand is retained as a no-op for one",
|
|
13642
|
-
" # release so any consumer mid-flight does not error out, then will",
|
|
13643
|
-
" # be removed entirely. Existing state files at",
|
|
13644
|
-
' # "$ORCHESTRATOR_STATE_FILE" can be left alone (they will become',
|
|
13645
|
-
" # orphaned).",
|
|
13646
|
-
' echo "tick: deprecated no-op (orchestrator runs a single linear cycle every invocation)" >&2',
|
|
13647
|
-
' echo "run=0 type=dispatch (deprecated)"',
|
|
13648
|
-
" return 0",
|
|
13649
|
-
"}",
|
|
13650
|
-
"",
|
|
13651
13813
|
"# \u2500\u2500 main \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
13652
13814
|
"",
|
|
13653
13815
|
'case "${1:-help}" in',
|
|
13654
|
-
' unblock)
|
|
13655
|
-
' eligible)
|
|
13656
|
-
' stale)
|
|
13657
|
-
' orphaned)
|
|
13658
|
-
'
|
|
13659
|
-
'
|
|
13660
|
-
'
|
|
13816
|
+
' unblock) shift; cmd_unblock "$@" ;;',
|
|
13817
|
+
' eligible) shift; cmd_eligible "$@" ;;',
|
|
13818
|
+
' stale) shift; cmd_stale "$@" ;;',
|
|
13819
|
+
' orphaned) shift; cmd_orphaned "$@" ;;',
|
|
13820
|
+
' maintenance) shift; cmd_maintenance "$@" ;;',
|
|
13821
|
+
' prs) shift; cmd_prs "$@" ;;',
|
|
13822
|
+
' scope) shift; cmd_scope "$@" ;;',
|
|
13661
13823
|
" help|*)",
|
|
13662
|
-
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|prs|scope
|
|
13824
|
+
' echo "Usage: check-blocked.sh <unblock|eligible|stale|orphaned|maintenance|prs|scope>"',
|
|
13663
13825
|
" exit 1",
|
|
13664
13826
|
" ;;",
|
|
13665
13827
|
"esac"
|
|
@@ -13668,7 +13830,7 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13668
13830
|
function buildCheckBlockedProcedure(tiers, scopeGate = resolveScopeGate(), runRatio = resolveRunRatio()) {
|
|
13669
13831
|
return {
|
|
13670
13832
|
name: "check-blocked.sh",
|
|
13671
|
-
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, prs, scope
|
|
13833
|
+
description: "Token-efficient issue triage script with subcommands: eligible, unblock, stale, orphaned, maintenance, prs, scope. Sorts eligible issues by priority desc \u2192 funnel tier asc \u2192 issue number asc; 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, and emits a single `TRIAGE_DONE unblocked=N still_blocked=M` summary line; the maintenance subcommand flags stale issues with `status:needs-attention` (never auto-resets to `status:ready`), counts orphan branches/PRs, and emits a single `MAINTENANCE_DONE flagged_stale=N flagged_blocked=M orphan_branches=A orphan_prs=B needs_attention_total=T` summary line.",
|
|
13672
13834
|
content: buildCheckBlockedScript(tiers, scopeGate, runRatio)
|
|
13673
13835
|
};
|
|
13674
13836
|
}
|
|
@@ -13687,6 +13849,59 @@ function buildUnblockDependentsProcedure(unblockDependents = resolveUnblockDepen
|
|
|
13687
13849
|
var unblockDependentsProcedure = buildUnblockDependentsProcedure(
|
|
13688
13850
|
resolveUnblockDependents()
|
|
13689
13851
|
);
|
|
13852
|
+
function buildPrSweepScript() {
|
|
13853
|
+
return [
|
|
13854
|
+
"#!/usr/bin/env bash",
|
|
13855
|
+
"# pr-sweep.sh \u2014 Token-efficient PR-eligibility filter for the",
|
|
13856
|
+
"# orchestrator's Phase B PR review sweep. Emits one summary line",
|
|
13857
|
+
"# per open PR; the orchestrator reads only the PR numbers and",
|
|
13858
|
+
"# dispatches `pr-reviewer` per eligible PR.",
|
|
13859
|
+
"#",
|
|
13860
|
+
"# Skip rules:",
|
|
13861
|
+
"# - isDraft = true \u2192 reason=draft",
|
|
13862
|
+
"# - review:human-required label \u2192 reason=human-required",
|
|
13863
|
+
"# - review:awaiting-human label \u2192 reason=awaiting-human",
|
|
13864
|
+
"#",
|
|
13865
|
+
"# Usage:",
|
|
13866
|
+
"# .claude/procedures/pr-sweep.sh",
|
|
13867
|
+
"",
|
|
13868
|
+
"set -uo pipefail",
|
|
13869
|
+
"",
|
|
13870
|
+
"prs=$(gh pr list --state open --json number,isDraft,labels \\",
|
|
13871
|
+
' --limit 50 2>/dev/null || echo "[]")',
|
|
13872
|
+
"",
|
|
13873
|
+
`count=$(echo "$prs" | jq 'length')`,
|
|
13874
|
+
'if [[ "$count" -eq 0 ]]; then',
|
|
13875
|
+
' echo "NO_OPEN_PRS"',
|
|
13876
|
+
" exit 0",
|
|
13877
|
+
"fi",
|
|
13878
|
+
"",
|
|
13879
|
+
"# Emit one PR_ELIGIBLE / PR_SKIP line per open PR, sorted by PR",
|
|
13880
|
+
"# number ascending so the order is deterministic across runs.",
|
|
13881
|
+
`echo "$prs" | jq -r '`,
|
|
13882
|
+
" sort_by(.number) |",
|
|
13883
|
+
" .[] |",
|
|
13884
|
+
" (.labels | map(.name)) as $labels |",
|
|
13885
|
+
" if .isDraft then",
|
|
13886
|
+
' "PR_SKIP #\\(.number) reason=draft"',
|
|
13887
|
+
' elif ($labels | index("review:human-required")) then',
|
|
13888
|
+
' "PR_SKIP #\\(.number) reason=human-required"',
|
|
13889
|
+
' elif ($labels | index("review:awaiting-human")) then',
|
|
13890
|
+
' "PR_SKIP #\\(.number) reason=awaiting-human"',
|
|
13891
|
+
" else",
|
|
13892
|
+
' "PR_ELIGIBLE #\\(.number)"',
|
|
13893
|
+
" end",
|
|
13894
|
+
"'"
|
|
13895
|
+
].join("\n");
|
|
13896
|
+
}
|
|
13897
|
+
function buildPrSweepProcedure() {
|
|
13898
|
+
return {
|
|
13899
|
+
name: "pr-sweep.sh",
|
|
13900
|
+
description: "Token-efficient PR-eligibility filter for the orchestrator's Phase B PR review sweep. Emits one `PR_ELIGIBLE #<n>` or `PR_SKIP #<n> reason=<draft|human-required|awaiting-human>` line per open PR; the orchestrator reads only the eligible numbers and dispatches `pr-reviewer` per eligible PR.",
|
|
13901
|
+
content: buildPrSweepScript()
|
|
13902
|
+
};
|
|
13903
|
+
}
|
|
13904
|
+
var prSweepProcedure = buildPrSweepProcedure();
|
|
13690
13905
|
var orchestratorSubAgent = {
|
|
13691
13906
|
name: "orchestrator",
|
|
13692
13907
|
description: "End-to-end pipeline manager that runs one full cycle every invocation: triage \u2192 maintenance \u2192 queue scan \u2192 delegate the picked issue to the issue-worker \u2192 cleanup",
|
|
@@ -13697,13 +13912,16 @@ var orchestratorSubAgent = {
|
|
|
13697
13912
|
"# Orchestrator Agent",
|
|
13698
13913
|
"",
|
|
13699
13914
|
"You are the pipeline orchestrator for the **{{repository.owner}}/{{repository.name}}** repository.",
|
|
13700
|
-
"Each invocation runs **one full end-to-end cycle**. The cycle
|
|
13701
|
-
"
|
|
13702
|
-
"
|
|
13703
|
-
"
|
|
13704
|
-
"
|
|
13705
|
-
"
|
|
13706
|
-
"
|
|
13915
|
+
"Each invocation runs **one full end-to-end cycle**. The cycle pulls",
|
|
13916
|
+
"the default branch, sweeps eligible open PRs through the `pr-reviewer`",
|
|
13917
|
+
"sub-agent, triages blocked issues, runs maintenance scans, picks the",
|
|
13918
|
+
"next ready issue, and **delegates implementation to the `issue-worker`**",
|
|
13919
|
+
"sub-agent in scheduled mode. The orchestrator itself never implements",
|
|
13920
|
+
"code, creates branches, pushes commits, or merges PRs \u2014 it routes",
|
|
13921
|
+
"work to other agents. The merge decision is still owned by the",
|
|
13922
|
+
"`pr-reviewer` sub-agent; the orchestrator only chooses which PRs the",
|
|
13923
|
+
"reviewer should look at and dispatches one reviewer session per",
|
|
13924
|
+
"eligible PR.",
|
|
13707
13925
|
"",
|
|
13708
13926
|
"Run the phases below in order on every invocation. There is no",
|
|
13709
13927
|
"dispatch/housekeeping fork \u2014 every phase runs every time.",
|
|
@@ -13711,16 +13929,20 @@ var orchestratorSubAgent = {
|
|
|
13711
13929
|
"Phase ordering (each runs exactly once per invocation):",
|
|
13712
13930
|
"",
|
|
13713
13931
|
"1. **Phase A \u2014 Startup.** Pull the default branch.",
|
|
13714
|
-
"2. **Phase
|
|
13932
|
+
"2. **Phase B \u2014 PR Review Sweep.** Read the procedure-script's",
|
|
13933
|
+
" eligibility summary and dispatch the `pr-reviewer` sub-agent",
|
|
13934
|
+
" in scheduled mode against each eligible open PR. Failures on",
|
|
13935
|
+
" one PR never stop the sweep.",
|
|
13936
|
+
"3. **Phase C \u2014 Triage / Unblock.** Flip dependents that have all",
|
|
13715
13937
|
" their dependencies closed back to `status:ready`.",
|
|
13716
|
-
"
|
|
13938
|
+
"4. **Phase D \u2014 Maintenance.** Stale-issue and orphaned-resource scan",
|
|
13717
13939
|
" plus a needs-attention summary.",
|
|
13718
|
-
"
|
|
13940
|
+
"5. **Phase E \u2014 Queue Scan.** Pick the highest-priority `PICK` line",
|
|
13719
13941
|
" and run the scope gate. If the result is `large`, flag and stop.",
|
|
13720
|
-
"
|
|
13942
|
+
"6. **Phase G \u2014 Delegate Implementation.** Hand the picked issue off",
|
|
13721
13943
|
" to the `issue-worker` sub-agent in scheduled mode. The worker",
|
|
13722
13944
|
" handles claim \u2192 branch \u2192 implement \u2192 commit \u2192 PR autonomously.",
|
|
13723
|
-
"
|
|
13945
|
+
"7. **Phase F \u2014 Cleanup.** Return to the default branch and log the",
|
|
13724
13946
|
" run summary.",
|
|
13725
13947
|
"",
|
|
13726
13948
|
"Phase letters are stable identifiers \u2014 letters skipped in the list",
|
|
@@ -13739,76 +13961,160 @@ var orchestratorSubAgent = {
|
|
|
13739
13961
|
"git checkout main && git pull origin main",
|
|
13740
13962
|
"```",
|
|
13741
13963
|
"",
|
|
13742
|
-
"## Phase
|
|
13964
|
+
"## Phase B: PR Review Sweep",
|
|
13965
|
+
"",
|
|
13966
|
+
"Sweep every open PR through the `pr-reviewer` sub-agent before the",
|
|
13967
|
+
"queue scan so a single `/orchestrate` invocation merges ready PRs",
|
|
13968
|
+
"and dispatches new issue work in one pass.",
|
|
13743
13969
|
"",
|
|
13744
|
-
"
|
|
13970
|
+
"### Step 1 \u2014 read the eligibility summary",
|
|
13971
|
+
"",
|
|
13972
|
+
"Run the bundled `pr-sweep.sh` procedure and read **only** the",
|
|
13973
|
+
"summary lines it emits. Do **not** iterate raw `gh pr list` JSON",
|
|
13974
|
+
"yourself \u2014 the procedure is the single source of PR-eligibility",
|
|
13975
|
+
"metadata, mirroring the discipline of Phase E's bucketed queue scan.",
|
|
13745
13976
|
"",
|
|
13746
13977
|
"```bash",
|
|
13747
|
-
".claude/procedures/
|
|
13978
|
+
".claude/procedures/pr-sweep.sh",
|
|
13748
13979
|
"```",
|
|
13749
13980
|
"",
|
|
13750
|
-
"
|
|
13751
|
-
"unblocking. Every agent that applies `status:done` already runs",
|
|
13752
|
-
"`.claude/procedures/unblock-dependents.sh <n>` as part of that",
|
|
13753
|
-
"transition, so in steady state Phase C should usually report",
|
|
13754
|
-
"`NO_BLOCKED_ISSUES` or leave dependents untouched. Phase C still",
|
|
13755
|
-
"runs on every cycle so issues that slipped through \u2014 human",
|
|
13756
|
-
"closures, manual `status:done` edits, or crashes mid-sweep \u2014 get",
|
|
13757
|
-
"picked up within one cycle. See the **Agent-driven",
|
|
13758
|
-
"unblocking** section in `CLAUDE.md` for the per-agent contract.",
|
|
13981
|
+
"Each line follows one of these shapes:",
|
|
13759
13982
|
"",
|
|
13760
|
-
"
|
|
13761
|
-
"
|
|
13762
|
-
|
|
13763
|
-
|
|
13983
|
+
"```",
|
|
13984
|
+
"PR_ELIGIBLE #<n>",
|
|
13985
|
+
"PR_SKIP #<n> reason=draft",
|
|
13986
|
+
"PR_SKIP #<n> reason=human-required",
|
|
13987
|
+
"PR_SKIP #<n> reason=awaiting-human",
|
|
13764
13988
|
"```",
|
|
13765
13989
|
"",
|
|
13766
|
-
"
|
|
13767
|
-
"catch it if it's been blocked too long).",
|
|
13990
|
+
"Skip rules (PRs that never reach the reviewer in this sweep):",
|
|
13768
13991
|
"",
|
|
13769
|
-
"
|
|
13992
|
+
"- `isDraft: true` \u2192 `reason=draft` (the author has not yet asked for review)",
|
|
13993
|
+
"- Carries the `review:human-required` label \u2192 `reason=human-required`",
|
|
13994
|
+
" (operator override \u2014 the reviewer's auto-merge path is forbidden)",
|
|
13995
|
+
"- Carries the `review:awaiting-human` label \u2192 `reason=awaiting-human`",
|
|
13996
|
+
" (the reviewer already handed off; a human is the next actor)",
|
|
13770
13997
|
"",
|
|
13771
|
-
"
|
|
13998
|
+
"If the script emits `NO_OPEN_PRS`, log the empty result and skip",
|
|
13999
|
+
"directly to Phase C.",
|
|
13772
14000
|
"",
|
|
13773
|
-
"###
|
|
14001
|
+
"### Step 2 \u2014 dispatch the reviewer per eligible PR",
|
|
13774
14002
|
"",
|
|
13775
|
-
"
|
|
13776
|
-
"
|
|
13777
|
-
"
|
|
14003
|
+
"For each `PR_ELIGIBLE #<n>` line in the order the procedure",
|
|
14004
|
+
"emitted them, invoke the `pr-reviewer` sub-agent **in scheduled",
|
|
14005
|
+
"mode** with the brief below. Substitute `<n>` with the PR number",
|
|
14006
|
+
"from the line.",
|
|
14007
|
+
"",
|
|
14008
|
+
"> `scheduled mode`: review PR #<n>. Run the full review pipeline",
|
|
14009
|
+
"> (eligibility, AC checklist, CI status, policy decision, sticky",
|
|
14010
|
+
"> reviewer-notes update) and either enable squash auto-merge or",
|
|
14011
|
+
"> apply `review:awaiting-human`. Do not pause for approval.",
|
|
14012
|
+
"> Return a one-line summary as the final line of your response in",
|
|
14013
|
+
"> the form `REVIEWER_DONE pr:#<n> outcome:<merged|awaiting-human|commented>`",
|
|
14014
|
+
"> on success or `REVIEWER_FAILED pr:#<n> reason:<short>` on failure.",
|
|
14015
|
+
"",
|
|
14016
|
+
"The orchestrator does **not** call `gh pr merge`, apply review",
|
|
14017
|
+
"labels, or post review comments directly \u2014 the reviewer's existing",
|
|
14018
|
+
"logic owns merge dispatch, AC verification, and the sticky",
|
|
14019
|
+
"`## Reviewer notes` comment. Phase B is a thin invoker, not an",
|
|
14020
|
+
"absorber.",
|
|
14021
|
+
"",
|
|
14022
|
+
"### Step 3 \u2014 failure semantics",
|
|
14023
|
+
"",
|
|
14024
|
+
"A single PR's reviewer failure (missing or malformed",
|
|
14025
|
+
"`REVIEWER_*` final line, sub-agent error, CI flake) **never stops",
|
|
14026
|
+
"the sweep**. Log the failure as",
|
|
14027
|
+
"`REVIEWER_FAILED pr:#<n> reason:<observed>` and continue to the",
|
|
14028
|
+
"next eligible PR. The next orchestrator invocation re-scans the",
|
|
14029
|
+
"PR list and re-dispatches the reviewer if the PR is still",
|
|
14030
|
+
"eligible.",
|
|
14031
|
+
"",
|
|
14032
|
+
"After every eligible PR has been processed (or zero eligible PRs",
|
|
14033
|
+
"were emitted), continue to Phase C regardless of outcomes.",
|
|
14034
|
+
"",
|
|
14035
|
+
"## Phase C: Triage \u2014 Unblock",
|
|
14036
|
+
"",
|
|
14037
|
+
"Run the bundled `check-blocked.sh unblock` procedure and read",
|
|
14038
|
+
"**only** the final `TRIAGE_DONE` summary line it emits. The",
|
|
14039
|
+
"procedure applies the label flips (`status:blocked` \u2192",
|
|
14040
|
+
"`status:ready`) and posts the canned",
|
|
14041
|
+
"`Dependencies resolved \u2014 unblocking.` comment itself, mirroring",
|
|
14042
|
+
"the discipline of Phase B (`pr-sweep.sh`) and Phase E",
|
|
14043
|
+
"(`check-blocked.sh eligible`) \u2014 the orchestrator never iterates",
|
|
14044
|
+
"raw `gh` responses, only the procedure's summary lines.",
|
|
13778
14045
|
"",
|
|
13779
|
-
"For each `STALE #N` line (in-progress >72h without activity):",
|
|
13780
14046
|
"```bash",
|
|
13781
|
-
|
|
13782
|
-
'gh issue comment N --body "Flagged: in-progress for >3 days with no activity."',
|
|
14047
|
+
".claude/procedures/check-blocked.sh unblock",
|
|
13783
14048
|
"```",
|
|
13784
14049
|
"",
|
|
13785
|
-
"
|
|
13786
|
-
"
|
|
13787
|
-
|
|
13788
|
-
|
|
14050
|
+
"The script emits one summary line in this shape:",
|
|
14051
|
+
"",
|
|
14052
|
+
"```",
|
|
14053
|
+
"TRIAGE_DONE unblocked=<N> still_blocked=<M>",
|
|
13789
14054
|
"```",
|
|
13790
14055
|
"",
|
|
13791
|
-
"
|
|
13792
|
-
"
|
|
14056
|
+
"Per-issue informational lines (`UNBLOCKED #N`, `UNBLOCK_FAILED #N`,",
|
|
14057
|
+
"`STILL_BLOCKED #N`, `BLOCKED #N \u2014 no Depends on field found`) are",
|
|
14058
|
+
"emitted for log visibility but are **not** load-bearing for the",
|
|
14059
|
+
"orchestrator \u2014 partial failures (one bad `gh` call) do not abort",
|
|
14060
|
+
"the sweep, they are simply counted toward `still_blocked`.",
|
|
14061
|
+
"",
|
|
14062
|
+
"This phase is the **fallback safety net** for agent-driven",
|
|
14063
|
+
"unblocking. Every agent that applies `status:done` already runs",
|
|
14064
|
+
"`.claude/procedures/unblock-dependents.sh <n>` as part of that",
|
|
14065
|
+
"transition, so in steady state Phase C should usually report",
|
|
14066
|
+
"`TRIAGE_DONE unblocked=0 still_blocked=0` or leave dependents",
|
|
14067
|
+
"untouched. Phase C still runs on every cycle so issues that",
|
|
14068
|
+
"slipped through \u2014 human closures, manual `status:done` edits, or",
|
|
14069
|
+
"crashes mid-sweep \u2014 get picked up within one cycle. See the",
|
|
14070
|
+
"**Agent-driven unblocking** section in `CLAUDE.md` for the",
|
|
14071
|
+
"per-agent contract.",
|
|
14072
|
+
"",
|
|
14073
|
+
"Log the summary line and continue to Phase D regardless of",
|
|
14074
|
+
"outcomes \u2014 a non-zero `still_blocked` count is normal (issues",
|
|
14075
|
+
"with open dependencies stay blocked) and Phase D will surface",
|
|
14076
|
+
"any that have been blocked too long.",
|
|
13793
14077
|
"",
|
|
13794
|
-
"
|
|
14078
|
+
"## Phase D: Maintenance",
|
|
14079
|
+
"",
|
|
14080
|
+
"Run the bundled `check-blocked.sh maintenance` procedure and read",
|
|
14081
|
+
"**only** the final `MAINTENANCE_DONE` summary line it emits. The",
|
|
14082
|
+
"procedure folds the stale-detection, orphan-detection, and",
|
|
14083
|
+
"needs-attention summary that earlier revisions split across D1,",
|
|
14084
|
+
"D2, and D3 into a single sweep \u2014 applying the",
|
|
14085
|
+
"`status:needs-attention` label and posting the canned flag comment",
|
|
14086
|
+
"for each stale / stale-blocked issue itself, mirroring the",
|
|
14087
|
+
"discipline of Phase B (`pr-sweep.sh`) and Phase C",
|
|
14088
|
+
"(`check-blocked.sh unblock`).",
|
|
13795
14089
|
"",
|
|
13796
14090
|
"```bash",
|
|
13797
|
-
".claude/procedures/check-blocked.sh
|
|
14091
|
+
".claude/procedures/check-blocked.sh maintenance",
|
|
13798
14092
|
"```",
|
|
13799
14093
|
"",
|
|
13800
|
-
"
|
|
13801
|
-
"or PRs whose linked issues are closed or missing. Log them for visibility",
|
|
13802
|
-
"but do not delete branches automatically.",
|
|
13803
|
-
"",
|
|
13804
|
-
"### D3: Needs-Attention Summary",
|
|
14094
|
+
"The script emits one summary line in this shape:",
|
|
13805
14095
|
"",
|
|
13806
|
-
"
|
|
13807
|
-
"
|
|
13808
|
-
'gh issue list --label "status:needs-attention" --state open --json number,title',
|
|
14096
|
+
"```",
|
|
14097
|
+
"MAINTENANCE_DONE flagged_stale=<N> flagged_blocked=<M> orphan_branches=<A> orphan_prs=<B> needs_attention_total=<T>",
|
|
13809
14098
|
"```",
|
|
13810
14099
|
"",
|
|
13811
|
-
"
|
|
14100
|
+
"Per-issue / per-orphan informational lines (`FLAGGED_STALE #N`,",
|
|
14101
|
+
"`FLAGGED_BLOCKED #N`, `STALE #N \u2014 \u2026`, `STALE_BLOCKED #N \u2014 \u2026`,",
|
|
14102
|
+
"`ORPHAN_BRANCH \u2026`, `ORPHAN_PR #N \u2014 \u2026`, `FLAG_FAILED #N \u2014 \u2026`) are",
|
|
14103
|
+
"emitted for log visibility but are **not** load-bearing for the",
|
|
14104
|
+
"orchestrator \u2014 partial failures (one bad `gh` call) do not abort",
|
|
14105
|
+
"the sweep, they are simply omitted from the `flagged_*` counters.",
|
|
14106
|
+
"",
|
|
14107
|
+
"**Important:** the script never auto-resets stale issues to",
|
|
14108
|
+
"`status:ready`. It only adds `status:needs-attention`; the",
|
|
14109
|
+
"existing `status:in-progress` or `status:blocked` label stays in",
|
|
14110
|
+
"place so partial implementation work on a branch remains visible",
|
|
14111
|
+
"to humans. Orphan branches and PRs are surfaced in the counters",
|
|
14112
|
+
"but are never deleted by the orchestrator \u2014 a human reviews the",
|
|
14113
|
+
"log lines and prunes orphans manually.",
|
|
14114
|
+
"",
|
|
14115
|
+
"Log the summary line and continue to Phase E regardless of",
|
|
14116
|
+
"outcomes \u2014 a non-zero `flagged_*` or `orphan_*` count is",
|
|
14117
|
+
"informational, not a failure.",
|
|
13812
14118
|
"",
|
|
13813
14119
|
"## Phase E: Queue Scan",
|
|
13814
14120
|
"",
|
|
@@ -13968,27 +14274,30 @@ var orchestratorSubAgent = {
|
|
|
13968
14274
|
"",
|
|
13969
14275
|
"1. **Never implement code.** You triage, scan, and delegate \u2014 you do not code.",
|
|
13970
14276
|
"2. **Never claim issues.** Do not add `status:in-progress` or create branches for issues. Phase G's `issue-worker` delegation is the only path that flips an issue's claim labels.",
|
|
13971
|
-
"3. **
|
|
13972
|
-
"4. **
|
|
13973
|
-
"5. **
|
|
13974
|
-
"6. **
|
|
13975
|
-
"7. **Never dispatch a `large` issue.** Always run the scope check",
|
|
14277
|
+
"3. **Always use procedure scripts.** Issue triage queries go through `.claude/procedures/check-blocked.sh`; PR-eligibility filtering goes through `.claude/procedures/pr-sweep.sh`. Never iterate raw `gh issue list` / `gh pr list` JSON in-context.",
|
|
14278
|
+
"4. **Follow CLAUDE.md conventions** for all git and gh operations.",
|
|
14279
|
+
"5. **Priority order:** critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number.",
|
|
14280
|
+
"6. **Never dispatch a `large` issue.** Always run the scope check",
|
|
13976
14281
|
" on the top `PICK` line before reporting `NEXT_WORK_ITEM`. A",
|
|
13977
14282
|
" `large` issue must be flagged with `status:needs-attention` and",
|
|
13978
14283
|
" handed a decomposition proposal \u2014 never claimed, never branched,",
|
|
13979
14284
|
" never delegated to the `issue-worker`.",
|
|
13980
|
-
"
|
|
14285
|
+
"7. **Sweep dependents whenever you apply `status:done`.** Every",
|
|
13981
14286
|
" `status:done` transition must be immediately followed by",
|
|
13982
14287
|
" `.claude/procedures/unblock-dependents.sh <n>` so downstream",
|
|
13983
14288
|
" `Depends on: #<n>` issues flip to `status:ready` without",
|
|
13984
14289
|
" waiting for the next cycle. See the **Agent-driven unblocking**",
|
|
13985
14290
|
" section in `CLAUDE.md` for the contract.",
|
|
13986
|
-
"
|
|
13987
|
-
"
|
|
13988
|
-
"
|
|
13989
|
-
"
|
|
13990
|
-
" the phrase the
|
|
13991
|
-
" delegation stalls."
|
|
14291
|
+
"8. **Always invoke child sub-agents in scheduled mode.** Phase B's",
|
|
14292
|
+
" `pr-reviewer` dispatch and Phase G's `issue-worker` delegation",
|
|
14293
|
+
" prompts must each contain the literal phrase `scheduled mode`",
|
|
14294
|
+
" so the child sub-agent skips its interactive approval pause and",
|
|
14295
|
+
" runs autonomously. Without the phrase the child pauses for",
|
|
14296
|
+
" human approval and the delegation stalls.",
|
|
14297
|
+
"9. **A failed reviewer never stops the sweep.** Phase B continues",
|
|
14298
|
+
" to the next eligible PR after a `REVIEWER_FAILED` line and",
|
|
14299
|
+
" proceeds to Phase C regardless of how many PRs failed. Do not",
|
|
14300
|
+
" abort the cycle on a single PR's reviewer failure."
|
|
13992
14301
|
].join("\n")
|
|
13993
14302
|
};
|
|
13994
14303
|
var issueWorkerSubAgent = {
|
|
@@ -14463,9 +14772,9 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
|
|
|
14463
14772
|
"",
|
|
14464
14773
|
"When running the orchestrator agent (`.claude/agents/orchestrator.md`):",
|
|
14465
14774
|
"",
|
|
14466
|
-
"- The orchestrator runs **one full end-to-end cycle every invocation**: triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate to `issue-worker` \u2192 cleanup",
|
|
14467
|
-
"- The orchestrator **never** implements code, creates branches, pushes commits
|
|
14468
|
-
"- All triage queries use `.claude/procedures/check-blocked.sh` for token efficiency",
|
|
14775
|
+
"- The orchestrator runs **one full end-to-end cycle every invocation**: startup \u2192 PR review sweep \u2192 triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate to `issue-worker` \u2192 cleanup",
|
|
14776
|
+
"- The orchestrator **never** implements code, creates branches, or pushes commits \u2014 it routes work to other sub-agents. The merge decision is still owned by the `pr-reviewer` sub-agent; Phase B only chooses which open PRs the reviewer should look at and dispatches one reviewer session per eligible PR (skipping drafts and any PR carrying `review:human-required` or `review:awaiting-human`).",
|
|
14777
|
+
"- All triage queries use `.claude/procedures/check-blocked.sh` for token efficiency. PR-eligibility filtering for Phase B uses `.claude/procedures/pr-sweep.sh`, which emits `PR_ELIGIBLE` / `PR_SKIP` lines so the orchestrator never iterates raw `gh pr list` JSON.",
|
|
14469
14778
|
"- The queue scan reads only `priority:*` and `status:*` labels \u2014 type-routing (which typed agent handles a given `type:*` label) is the `issue-worker`'s concern, not the orchestrator's. The orchestrator's funnel-tier sort is a tie-breaker on `priority:*`, not a routing decision.",
|
|
14470
14779
|
"- Priority order: critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number. Phase E's queue scan walks each priority bucket in turn (one `gh issue list` call per bucket, **capped at 50 issues per bucket**) and short-circuits on the first bucket whose survivors clear the `Depends on:` filter, so every higher-priority issue is visible even when the global ready backlog is much larger than 50.",
|
|
14471
14780
|
"- Stale thresholds: 72h for in-progress, 168h for blocked",
|
|
@@ -14473,11 +14782,11 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
|
|
|
14473
14782
|
"",
|
|
14474
14783
|
"## Depth-0 invocation requirement",
|
|
14475
14784
|
"",
|
|
14476
|
-
'The orchestrator agent **must run as the top-level (depth-0) session**
|
|
14785
|
+
'The orchestrator agent **must run as the top-level (depth-0) session** because both Phase B (PR review sweep) and Phase G (issue delegation) need to spawn child sub-agents. Phase B dispatches the `pr-reviewer` sub-agent once per eligible open PR; Phase G dispatches the `issue-worker` sub-agent against the picked issue. The Claude Code harness forbids nested sub-agent spawning \u2014 *"Subagents cannot spawn other subagents. If your workflow requires nested delegation, use Skills or chain subagents from the main conversation."* (see <https://code.claude.com/docs/en/sub-agents>). If the orchestrator itself were spawned as a depth-1 sub-agent (e.g. via `Agent(subagent_type: "orchestrator")` from another session), the `Agent` tool needed to reach `pr-reviewer` and `issue-worker` at depth-2 would not be available and both Phase B and Phase G would silently abort.',
|
|
14477
14786
|
"",
|
|
14478
|
-
'Practical implication for scheduled-task wiring: the `worker-orchestrator` scheduled task\'s `SKILL.md` instructs the **scheduled-task session itself** to read `.claude/agents/orchestrator.md` and execute its phase pipeline in-session, then use the `Agent` tool to delegate
|
|
14787
|
+
'Practical implication for scheduled-task wiring: the `worker-orchestrator` scheduled task\'s `SKILL.md` instructs the **scheduled-task session itself** to read `.claude/agents/orchestrator.md` and execute its phase pipeline in-session, then use the `Agent` tool to delegate to `pr-reviewer` (Phase B) and `issue-worker` (Phase G) at depth-1. The scheduled task does **not** call `Agent(subagent_type: "orchestrator")` \u2014 that would put the orchestrator at depth-1 and break both delegation chains.'
|
|
14479
14788
|
].join("\n");
|
|
14480
|
-
function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate(),
|
|
14789
|
+
function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate(), _runRatio = resolveRunRatio(), scheduledTasks = resolveScheduledTasks(), unblockDependents = resolveUnblockDependents(), excludeBundles = []) {
|
|
14481
14790
|
return [
|
|
14482
14791
|
ORCHESTRATOR_CONVENTIONS_PREAMBLE,
|
|
14483
14792
|
"",
|
|
@@ -14485,8 +14794,6 @@ function buildOrchestratorConventionsContent(tiers, scopeGate = resolveScopeGate
|
|
|
14485
14794
|
"",
|
|
14486
14795
|
renderScopeGateSection(scopeGate, excludeBundles),
|
|
14487
14796
|
"",
|
|
14488
|
-
renderRunRatioSection(runRatio),
|
|
14489
|
-
"",
|
|
14490
14797
|
renderScheduledTasksSection(scheduledTasks),
|
|
14491
14798
|
"",
|
|
14492
14799
|
renderUnblockDependentsSection(unblockDependents)
|
|
@@ -14523,6 +14830,74 @@ function resolveOrchestratorAssets(tierConfig, scopeGateConfig, runRatioConfig,
|
|
|
14523
14830
|
)
|
|
14524
14831
|
};
|
|
14525
14832
|
}
|
|
14833
|
+
var orchestrateCommand = {
|
|
14834
|
+
name: "orchestrate",
|
|
14835
|
+
description: "Run one full orchestrator cycle: triage, queue scan, delegate to issue-worker.",
|
|
14836
|
+
content: [
|
|
14837
|
+
"# Orchestrate",
|
|
14838
|
+
"",
|
|
14839
|
+
"Invoke the `orchestrator` sub-agent and run **one full end-to-end",
|
|
14840
|
+
"cycle**: triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate the",
|
|
14841
|
+
"picked issue to the `issue-worker` sub-agent \u2192 cleanup.",
|
|
14842
|
+
"",
|
|
14843
|
+
"Follow the contract in `.claude/agents/orchestrator.md`. Do **not**",
|
|
14844
|
+
"implement code, create branches, push commits, or merge PRs \u2014 those",
|
|
14845
|
+
"are the worker's and `pr-reviewer`'s jobs respectively.",
|
|
14846
|
+
"",
|
|
14847
|
+
"Run as a depth-0 (top-level) session so the orchestrator can spawn",
|
|
14848
|
+
"the `issue-worker` sub-agent at depth-1 \u2014 Claude Code forbids nested",
|
|
14849
|
+
"sub-agent dispatch.",
|
|
14850
|
+
""
|
|
14851
|
+
].join("\n")
|
|
14852
|
+
};
|
|
14853
|
+
var checkBlockedCommand = {
|
|
14854
|
+
name: "check-blocked",
|
|
14855
|
+
description: "Run .claude/procedures/check-blocked.sh and summarise the unblock candidates.",
|
|
14856
|
+
content: [
|
|
14857
|
+
"# Check Blocked",
|
|
14858
|
+
"",
|
|
14859
|
+
"Run the bundled triage helper and report what it found:",
|
|
14860
|
+
"",
|
|
14861
|
+
"```bash",
|
|
14862
|
+
'bash .claude/procedures/check-blocked.sh "$@"',
|
|
14863
|
+
"```",
|
|
14864
|
+
"",
|
|
14865
|
+
"Pass any extra arguments through verbatim. The `unblock` subcommand",
|
|
14866
|
+
"walks every `status:blocked` issue, re-checks each `Depends on:`",
|
|
14867
|
+
"reference, applies the `status:blocked` \u2192 `status:ready` label flip",
|
|
14868
|
+
"itself, posts the canned `Dependencies resolved \u2014 unblocking.`",
|
|
14869
|
+
"comment, and emits a single",
|
|
14870
|
+
"`TRIAGE_DONE unblocked=<N> still_blocked=<M>` summary line. Per-issue",
|
|
14871
|
+
"informational lines (`UNBLOCKED`, `UNBLOCK_FAILED`, `STILL_BLOCKED`)",
|
|
14872
|
+
"are also emitted for log visibility.",
|
|
14873
|
+
"",
|
|
14874
|
+
"Summarise the output (the `TRIAGE_DONE` counts and the first few",
|
|
14875
|
+
"per-issue lines) \u2014 do **not** apply additional label flips yourself;",
|
|
14876
|
+
"the script already transitioned every eligible issue.",
|
|
14877
|
+
""
|
|
14878
|
+
].join("\n")
|
|
14879
|
+
};
|
|
14880
|
+
var scanCommand = {
|
|
14881
|
+
name: "scan",
|
|
14882
|
+
description: "Run the orchestrator queue scan only and report the next ready issue without dispatching.",
|
|
14883
|
+
content: [
|
|
14884
|
+
"# Scan",
|
|
14885
|
+
"",
|
|
14886
|
+
"Run the orchestrator's **queue scan only** (Phase E of the contract",
|
|
14887
|
+
"in `.claude/agents/orchestrator.md`) and print the next ready issue,",
|
|
14888
|
+
"the funnel-tier sort that put it on top, and the scope-gate result.",
|
|
14889
|
+
"",
|
|
14890
|
+
"Do **not** claim the issue, create a branch, or delegate to",
|
|
14891
|
+
"`issue-worker`. This command exists for proactive review of what",
|
|
14892
|
+
"the next `/orchestrate` invocation would pick up.",
|
|
14893
|
+
"",
|
|
14894
|
+
"Walk each `priority:*` bucket in turn (capped at 50 per bucket),",
|
|
14895
|
+
"filter `Depends on:` references, and short-circuit on the first",
|
|
14896
|
+
"bucket whose survivors clear the filter. Report the top candidate",
|
|
14897
|
+
"and the number of survivors per bucket.",
|
|
14898
|
+
""
|
|
14899
|
+
].join("\n")
|
|
14900
|
+
};
|
|
14526
14901
|
var orchestratorBundle = {
|
|
14527
14902
|
name: "orchestrator",
|
|
14528
14903
|
description: "Pipeline orchestrator agent for issue triage, PR review, and queue management",
|
|
@@ -14548,7 +14923,12 @@ var orchestratorBundle = {
|
|
|
14548
14923
|
}
|
|
14549
14924
|
],
|
|
14550
14925
|
subAgents: [orchestratorSubAgent, issueWorkerSubAgent],
|
|
14551
|
-
procedures: [
|
|
14926
|
+
procedures: [
|
|
14927
|
+
checkBlockedProcedure,
|
|
14928
|
+
unblockDependentsProcedure,
|
|
14929
|
+
prSweepProcedure
|
|
14930
|
+
],
|
|
14931
|
+
commands: [orchestrateCommand, checkBlockedCommand, scanCommand],
|
|
14552
14932
|
claudePermissions: {
|
|
14553
14933
|
allow: [
|
|
14554
14934
|
// Allow executing the check-blocked.sh procedure
|
|
@@ -14558,11 +14938,11 @@ var orchestratorBundle = {
|
|
|
14558
14938
|
};
|
|
14559
14939
|
|
|
14560
14940
|
// src/agent/bundles/people-profile.ts
|
|
14561
|
-
function buildPeopleProfileAnalystSubAgent(paths, issueDefaults) {
|
|
14941
|
+
function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
14562
14942
|
return {
|
|
14563
14943
|
name: "people-profile-analyst",
|
|
14564
14944
|
description: "Researches an individual person (colleague, customer contact, vendor contact, partner contact, industry expert, or connector) from public sources and produces a structured markdown profile cross-linked to companies, software, and meeting notes, then enqueues downstream `company:research` and `software:research` issues for unprofiled companies and software products surfaced during profiling. Also handles maintenance refreshes on a configurable staleness cadence (`people:refresh`). One person per session, tracked by people:* GitHub issue labels.",
|
|
14565
|
-
model:
|
|
14945
|
+
model: tier,
|
|
14566
14946
|
maxTurns: 80,
|
|
14567
14947
|
platforms: { cursor: { exclude: true } },
|
|
14568
14948
|
prompt: [
|
|
@@ -15392,7 +15772,7 @@ function buildRefreshPersonSkill(paths, issueDefaults) {
|
|
|
15392
15772
|
].join("\n")
|
|
15393
15773
|
};
|
|
15394
15774
|
}
|
|
15395
|
-
function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
15775
|
+
function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
|
|
15396
15776
|
return {
|
|
15397
15777
|
name: "people-profile",
|
|
15398
15778
|
description: "People research and profiling pipeline: research, draft profile, followup, refresh. Enabled by default; domain-neutral; filesystem-durable between phases. Cross-references existing companies, software, and meeting notes, and Phase 3 (Followup) hands unprofiled, genuinely-relevant companies and software products off to the `company-profile` and `software-profile` bundles via `company:research` and `software:research` issues. Phase 4 (Refresh) re-verifies profiles on a configurable staleness cadence.",
|
|
@@ -15440,7 +15820,7 @@ function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = D
|
|
|
15440
15820
|
buildProfilePersonSkill(paths, issueDefaults),
|
|
15441
15821
|
buildRefreshPersonSkill(paths, issueDefaults)
|
|
15442
15822
|
],
|
|
15443
|
-
subAgents: [buildPeopleProfileAnalystSubAgent(paths, issueDefaults)],
|
|
15823
|
+
subAgents: [buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier)],
|
|
15444
15824
|
labels: [
|
|
15445
15825
|
{
|
|
15446
15826
|
name: "type:people-profile",
|
|
@@ -17015,7 +17395,19 @@ var prReviewBundle = {
|
|
|
17015
17395
|
"to a PR's branch \u2014 it only reviews, decides, and orchestrates merge",
|
|
17016
17396
|
"or comment. In loop mode, a failed review for one PR never stops",
|
|
17017
17397
|
"the loop; the reviewer comments and moves on. See the `pr-reviewer`",
|
|
17018
|
-
"agent definition for the full phase-by-phase contract."
|
|
17398
|
+
"agent definition for the full phase-by-phase contract."
|
|
17399
|
+
].join("\n"),
|
|
17400
|
+
platforms: {
|
|
17401
|
+
cursor: { exclude: true }
|
|
17402
|
+
},
|
|
17403
|
+
tags: ["workflow"]
|
|
17404
|
+
},
|
|
17405
|
+
{
|
|
17406
|
+
name: "pr-review-feedback-protocol",
|
|
17407
|
+
description: "Documents the human-in-the-loop feedback loop on PR review: reaction state machine, pushback resolution, fix-list comment format, sticky reviewer-notes comment, label glossary, and human-author opt-in flag.",
|
|
17408
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
17409
|
+
content: [
|
|
17410
|
+
"# PR Review Feedback Protocol",
|
|
17019
17411
|
"",
|
|
17020
17412
|
"## Human-in-the-Loop Feedback Protocol",
|
|
17021
17413
|
"",
|
|
@@ -23799,11 +24191,11 @@ var slackBundle = {
|
|
|
23799
24191
|
};
|
|
23800
24192
|
|
|
23801
24193
|
// src/agent/bundles/software-profile.ts
|
|
23802
|
-
function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults) {
|
|
24194
|
+
function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
|
|
23803
24195
|
return {
|
|
23804
24196
|
name: "software-profile-analyst",
|
|
23805
24197
|
description: "Researches a software product (competitor, adjacent, incumbent, enabler, infrastructure, or ecosystem-tool) from public sources, produces a structured markdown profile, contributes rows to a shared feature matrix ranked against configurable segment-importance weights, maps features back to the BCM capability model and flags unmapped features, then enqueues downstream `bcm:outline`, `company:research`, and `people:research` issues for new sub-capabilities, the vendor company, and primary-attribution founders/leaders surfaced during profiling. One product per session, tracked by software:* GitHub issue labels.",
|
|
23806
|
-
model:
|
|
24198
|
+
model: tier,
|
|
23807
24199
|
maxTurns: 80,
|
|
23808
24200
|
platforms: { cursor: { exclude: true } },
|
|
23809
24201
|
prompt: [
|
|
@@ -24738,7 +25130,7 @@ function buildMapSoftwareSkill(paths, issueDefaults) {
|
|
|
24738
25130
|
].join("\n")
|
|
24739
25131
|
};
|
|
24740
25132
|
}
|
|
24741
|
-
function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
25133
|
+
function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
|
|
24742
25134
|
return {
|
|
24743
25135
|
name: "software-profile",
|
|
24744
25136
|
description: "Software research, profiling, feature-matrix, and capability-mapping pipeline: research, profile, matrix, map, followup. Enabled by default; domain-neutral; filesystem-durable between phases; ranks features against configurable segment-importance weights and maps features back to the BCM capability model. Phase 4 (Map) hands unmapped features off to the `bcm-writer` bundle via `bcm:outline` issues. Phase 5 (Followup) hands the vendor company and primary-attribution founders/leaders off to the `company-profile` and `people-profile` bundles via `company:research` and `people:research` issues.",
|
|
@@ -24795,7 +25187,9 @@ function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
|
|
|
24795
25187
|
buildProfileSoftwareSkill(paths, issueDefaults),
|
|
24796
25188
|
buildMapSoftwareSkill(paths, issueDefaults)
|
|
24797
25189
|
],
|
|
24798
|
-
subAgents: [
|
|
25190
|
+
subAgents: [
|
|
25191
|
+
buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier)
|
|
25192
|
+
],
|
|
24799
25193
|
labels: [
|
|
24800
25194
|
{
|
|
24801
25195
|
name: "type:software-profile",
|
|
@@ -27029,6 +27423,211 @@ var vitestBundle = {
|
|
|
27029
27423
|
}
|
|
27030
27424
|
};
|
|
27031
27425
|
|
|
27426
|
+
// src/agent/bundles/agent-registry.ts
|
|
27427
|
+
var AGENT_REGISTRY_ENTRIES = [
|
|
27428
|
+
{
|
|
27429
|
+
bundle: "agenda",
|
|
27430
|
+
skill: "/draft-agenda",
|
|
27431
|
+
agent: "agenda-analyst",
|
|
27432
|
+
resolveOutputPath: (p) => `${p.meetingsRoot}/`,
|
|
27433
|
+
purpose: "Pre-meeting agenda authoring (2-phase: draft, finalize). Reuses the project's meeting-type taxonomy.",
|
|
27434
|
+
workflowRuleName: "meeting-agenda-workflow"
|
|
27435
|
+
},
|
|
27436
|
+
{
|
|
27437
|
+
bundle: "bcm-writer",
|
|
27438
|
+
skill: "/write-bcm",
|
|
27439
|
+
agent: "bcm-writer",
|
|
27440
|
+
resolveOutputPath: (p) => `${p.bcmRoot}/`,
|
|
27441
|
+
purpose: "BCM capability-model documents (4-phase: outline, scaffold, context, connect). BIZBOK-aligned.",
|
|
27442
|
+
workflowRuleName: "bcm-writer-workflow"
|
|
27443
|
+
},
|
|
27444
|
+
{
|
|
27445
|
+
bundle: "business-models",
|
|
27446
|
+
skill: "/scan-business-models",
|
|
27447
|
+
agent: "business-models-analyst",
|
|
27448
|
+
resolveOutputPath: (p) => `${p.docsRoot}/industry-research/`,
|
|
27449
|
+
purpose: "Osterwalder business-model canvases per industry segment (3-phase: scan, canvas, complete).",
|
|
27450
|
+
workflowRuleName: "business-models-workflow"
|
|
27451
|
+
},
|
|
27452
|
+
{
|
|
27453
|
+
bundle: "company-profile",
|
|
27454
|
+
skill: "/profile-company",
|
|
27455
|
+
agent: "company-profile-analyst",
|
|
27456
|
+
resolveOutputPath: (p) => `${p.companiesRoot}/`,
|
|
27457
|
+
purpose: "Company profiles, notes, and segment competitive analyses (up to 6 phases incl. refresh).",
|
|
27458
|
+
workflowRuleName: "company-profile-workflow"
|
|
27459
|
+
},
|
|
27460
|
+
{
|
|
27461
|
+
bundle: "customer-profile",
|
|
27462
|
+
skill: "/discover-customers",
|
|
27463
|
+
agent: "customer-profile-analyst",
|
|
27464
|
+
resolveOutputPath: (p) => `${p.profilesRoot}/customers/`,
|
|
27465
|
+
purpose: "Customer-archetype discovery, profiles, and competitor feature-mapping (3-phase).",
|
|
27466
|
+
workflowRuleName: "customer-profile-workflow"
|
|
27467
|
+
},
|
|
27468
|
+
{
|
|
27469
|
+
bundle: "docs-sync",
|
|
27470
|
+
skill: "/docs-sync-pr",
|
|
27471
|
+
agent: "docs-sync",
|
|
27472
|
+
resolveOutputPath: (p) => `${p.docsRoot}/`,
|
|
27473
|
+
purpose: "Pre-PR drift detection and mechanical doc fixes (2-phase: scan, fix). Skeleton release.",
|
|
27474
|
+
workflowRuleName: "docs-sync-workflow"
|
|
27475
|
+
},
|
|
27476
|
+
{
|
|
27477
|
+
bundle: "industry-discovery",
|
|
27478
|
+
skill: "/discover-industries",
|
|
27479
|
+
agent: "industry-discovery-analyst",
|
|
27480
|
+
resolveOutputPath: (p) => `${p.industriesRoot}/`,
|
|
27481
|
+
purpose: "Industry-vertical discovery, fit-evaluation, and research planning (3-phase).",
|
|
27482
|
+
workflowRuleName: "industry-discovery-workflow"
|
|
27483
|
+
},
|
|
27484
|
+
{
|
|
27485
|
+
bundle: "maintenance-audit",
|
|
27486
|
+
skill: "/audit-docs",
|
|
27487
|
+
agent: "maintenance-audit",
|
|
27488
|
+
resolveOutputPath: (p) => `${p.docsRoot}/`,
|
|
27489
|
+
purpose: "Doc-registry audits with idempotent fixes (3-phase: scan, fix, verify). No new content.",
|
|
27490
|
+
workflowRuleName: "maintenance-audit-workflow"
|
|
27491
|
+
},
|
|
27492
|
+
{
|
|
27493
|
+
bundle: "meeting-analysis",
|
|
27494
|
+
skill: "/process-meeting",
|
|
27495
|
+
agent: "meeting-analyst",
|
|
27496
|
+
resolveOutputPath: (p) => `${p.meetingsRoot}/`,
|
|
27497
|
+
purpose: "Post-meeting transcript processing (4-phase: extract, notes, draft, link).",
|
|
27498
|
+
workflowRuleName: "meeting-processing-workflow"
|
|
27499
|
+
},
|
|
27500
|
+
{
|
|
27501
|
+
bundle: "people-profile",
|
|
27502
|
+
skill: "/profile-person",
|
|
27503
|
+
agent: "people-profile-analyst",
|
|
27504
|
+
resolveOutputPath: (p) => `${p.peopleRoot}/`,
|
|
27505
|
+
purpose: "Person profiles only (up to 4 phases incl. refresh). Hands off to company/software bundles.",
|
|
27506
|
+
workflowRuleName: "people-profile-workflow"
|
|
27507
|
+
},
|
|
27508
|
+
{
|
|
27509
|
+
bundle: "pr-review",
|
|
27510
|
+
skill: "/review-pr",
|
|
27511
|
+
agent: "pr-reviewer",
|
|
27512
|
+
resolveOutputPath: () => "",
|
|
27513
|
+
purpose: "PR review, auto-merge gating, and human-in-the-loop feedback orchestration.",
|
|
27514
|
+
workflowRuleName: "pr-review-workflow"
|
|
27515
|
+
},
|
|
27516
|
+
{
|
|
27517
|
+
bundle: "regulatory-research",
|
|
27518
|
+
skill: "/scan-regulatory-landscape",
|
|
27519
|
+
agent: "regulatory-research-analyst",
|
|
27520
|
+
resolveOutputPath: (p) => `${p.docsRoot}/regulations/`,
|
|
27521
|
+
purpose: "Regulation research, version pages, and impact analysis (3-phase). Documents, never interprets.",
|
|
27522
|
+
workflowRuleName: "regulatory-research-workflow"
|
|
27523
|
+
},
|
|
27524
|
+
{
|
|
27525
|
+
bundle: "requirements-analyst",
|
|
27526
|
+
skill: "/scan-requirements",
|
|
27527
|
+
agent: "requirements-analyst",
|
|
27528
|
+
resolveOutputPath: (p) => `${p.researchRequirementsRoot}/`,
|
|
27529
|
+
purpose: "Requirements gap discovery + draft proposals (2-phase: scan, draft-trace). Hands off to writer.",
|
|
27530
|
+
workflowRuleName: "requirements-analyst-workflow"
|
|
27531
|
+
},
|
|
27532
|
+
{
|
|
27533
|
+
bundle: "requirements-reviewer",
|
|
27534
|
+
skill: "/review-requirements",
|
|
27535
|
+
agent: "requirements-reviewer",
|
|
27536
|
+
resolveOutputPath: (p) => `${p.requirementsRoot}/`,
|
|
27537
|
+
purpose: "Requirements audit (12 checks) and narrow-edit deprecation. Never authors new requirement docs.",
|
|
27538
|
+
workflowRuleName: "requirements-reviewer-workflow"
|
|
27539
|
+
},
|
|
27540
|
+
{
|
|
27541
|
+
bundle: "requirements-writer",
|
|
27542
|
+
skill: "/write-requirement",
|
|
27543
|
+
agent: "requirements-writer",
|
|
27544
|
+
resolveOutputPath: (p) => `${p.requirementsRoot}/`,
|
|
27545
|
+
purpose: "Formal requirement document authoring across the 11-category taxonomy + four-tier classification.",
|
|
27546
|
+
workflowRuleName: "requirements-writer-workflow"
|
|
27547
|
+
},
|
|
27548
|
+
{
|
|
27549
|
+
bundle: "research-pipeline",
|
|
27550
|
+
skill: "/research",
|
|
27551
|
+
agent: "research-analyst",
|
|
27552
|
+
resolveOutputPath: (p) => `${p.researchRoot}/`,
|
|
27553
|
+
purpose: "Generic research micro-tasks (3-phase: scope, slice, verify). Notes-only output.",
|
|
27554
|
+
workflowRuleName: "research-pipeline-workflow"
|
|
27555
|
+
},
|
|
27556
|
+
{
|
|
27557
|
+
bundle: "software-profile",
|
|
27558
|
+
skill: "/profile-software",
|
|
27559
|
+
agent: "software-profile-analyst",
|
|
27560
|
+
resolveOutputPath: (p) => `${p.softwareRoot}/`,
|
|
27561
|
+
purpose: "Software profiles, shared feature matrix, and BCM-tree capability mapping (up to 5 phases).",
|
|
27562
|
+
workflowRuleName: "software-profile-workflow"
|
|
27563
|
+
},
|
|
27564
|
+
{
|
|
27565
|
+
bundle: "standards-research",
|
|
27566
|
+
skill: "/scope-standards-research",
|
|
27567
|
+
agent: "standards-research-analyst",
|
|
27568
|
+
resolveOutputPath: (p) => `${p.docsRoot}/standards/`,
|
|
27569
|
+
purpose: "Interoperability standards research (5-phase: scope, research, compare, extension, organizations).",
|
|
27570
|
+
workflowRuleName: "standards-research-workflow"
|
|
27571
|
+
}
|
|
27572
|
+
];
|
|
27573
|
+
var SUPPRESSED_WORKFLOW_RULE_NAMES = AGENT_REGISTRY_ENTRIES.map((e) => e.workflowRuleName);
|
|
27574
|
+
function isSuppressedWorkflowRule(name) {
|
|
27575
|
+
return SUPPRESSED_WORKFLOW_RULE_NAMES.includes(name);
|
|
27576
|
+
}
|
|
27577
|
+
function bundleNameForWorkflowRule(ruleName) {
|
|
27578
|
+
const entry = AGENT_REGISTRY_ENTRIES.find(
|
|
27579
|
+
(e) => e.workflowRuleName === ruleName
|
|
27580
|
+
);
|
|
27581
|
+
return entry?.bundle;
|
|
27582
|
+
}
|
|
27583
|
+
function buildAgentRegistryRule(bundles, paths) {
|
|
27584
|
+
const activeNames = new Set(bundles.map((b) => b.name));
|
|
27585
|
+
const rows = AGENT_REGISTRY_ENTRIES.filter(
|
|
27586
|
+
(e) => activeNames.has(e.bundle)
|
|
27587
|
+
).slice();
|
|
27588
|
+
if (rows.length === 0) {
|
|
27589
|
+
return void 0;
|
|
27590
|
+
}
|
|
27591
|
+
rows.sort((a, b) => a.bundle.localeCompare(b.bundle));
|
|
27592
|
+
const lines = [
|
|
27593
|
+
"# Agent Registry",
|
|
27594
|
+
"",
|
|
27595
|
+
"Each row below is the routing summary for one phased-agent",
|
|
27596
|
+
"bundle: the user-invocable skill, the sub-agent that handles",
|
|
27597
|
+
"the work, the output path the agent writes to, and a one-line",
|
|
27598
|
+
"purpose. Use the table to answer *which agent handles X* \u2014",
|
|
27599
|
+
"full agent prompts live in `.claude/agents/<name>.md` and only",
|
|
27600
|
+
"load on delegation, so the table is the always-on routing",
|
|
27601
|
+
"signal.",
|
|
27602
|
+
"",
|
|
27603
|
+
"Cross-cutting policies that apply to every agent below \u2014",
|
|
27604
|
+
"Progress File Convention, Shared-Editing Safety, Issue",
|
|
27605
|
+
"Templates, Skill Evals \u2014 are documented as their own top-level",
|
|
27606
|
+
"sections elsewhere in this file. The registry only captures",
|
|
27607
|
+
"routing; it does not duplicate convention prose.",
|
|
27608
|
+
"",
|
|
27609
|
+
"| Skill | Agent | Bundle | Output path | Purpose |",
|
|
27610
|
+
"| --- | --- | --- | --- | --- |"
|
|
27611
|
+
];
|
|
27612
|
+
for (const row of rows) {
|
|
27613
|
+
const outputPath = row.resolveOutputPath(paths);
|
|
27614
|
+
const pathCell = outputPath.length > 0 ? `\`${outputPath}\`` : "\u2014";
|
|
27615
|
+
lines.push(
|
|
27616
|
+
`| \`${row.skill}\` | \`${row.agent}\` | \`${row.bundle}\` | ${pathCell} | ${row.purpose} |`
|
|
27617
|
+
);
|
|
27618
|
+
}
|
|
27619
|
+
return {
|
|
27620
|
+
name: "agent-registry",
|
|
27621
|
+
description: "Routing table mapping each phased-agent bundle to its primary skill, sub-agent, output path, and one-line purpose. Replaces the per-bundle workflow rules whose prose summaries duplicated the routing signal.",
|
|
27622
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
27623
|
+
content: lines.join("\n"),
|
|
27624
|
+
platforms: {
|
|
27625
|
+
cursor: { exclude: true }
|
|
27626
|
+
},
|
|
27627
|
+
tags: ["workflow"]
|
|
27628
|
+
};
|
|
27629
|
+
}
|
|
27630
|
+
|
|
27032
27631
|
// src/agent/bundles/features.ts
|
|
27033
27632
|
var SOURCE_TIER_HEADINGS = [
|
|
27034
27633
|
{ key: "t1", heading: "### T1 \u2014 Primary Living" },
|
|
@@ -27396,7 +27995,8 @@ function renderPriorityRulesSection(rules) {
|
|
|
27396
27995
|
}
|
|
27397
27996
|
|
|
27398
27997
|
// src/agent/bundles/index.ts
|
|
27399
|
-
function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
|
|
27998
|
+
function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, defaultAgentTier = AGENT_MODEL.BALANCED, bundleAgentTiers = /* @__PURE__ */ new Map()) {
|
|
27999
|
+
const tierFor = (bundle) => bundleAgentTiers.get(bundle) ?? defaultAgentTier;
|
|
27400
28000
|
return [
|
|
27401
28001
|
buildBaseBundle(paths),
|
|
27402
28002
|
upstreamConfigulatorDocsBundle,
|
|
@@ -27409,7 +28009,7 @@ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAUL
|
|
|
27409
28009
|
projenBundle,
|
|
27410
28010
|
githubWorkflowBundle,
|
|
27411
28011
|
slackBundle,
|
|
27412
|
-
|
|
28012
|
+
buildMeetingAnalysisBundle(tierFor("meeting-analysis")),
|
|
27413
28013
|
agendaBundle,
|
|
27414
28014
|
orchestratorBundle,
|
|
27415
28015
|
prReviewBundle,
|
|
@@ -27417,16 +28017,28 @@ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAUL
|
|
|
27417
28017
|
buildRequirementsWriterBundle(paths, issueDefaults),
|
|
27418
28018
|
buildRequirementsReviewerBundle(paths, issueDefaults),
|
|
27419
28019
|
buildResearchPipelineBundle(paths, issueDefaults),
|
|
27420
|
-
buildCompanyProfileBundle(paths, issueDefaults),
|
|
27421
|
-
buildCustomerProfileBundle(
|
|
27422
|
-
|
|
27423
|
-
|
|
28020
|
+
buildCompanyProfileBundle(paths, issueDefaults, tierFor("company-profile")),
|
|
28021
|
+
buildCustomerProfileBundle(
|
|
28022
|
+
paths,
|
|
28023
|
+
issueDefaults,
|
|
28024
|
+
tierFor("customer-profile")
|
|
28025
|
+
),
|
|
28026
|
+
buildPeopleProfileBundle(paths, issueDefaults, tierFor("people-profile")),
|
|
28027
|
+
buildSoftwareProfileBundle(
|
|
28028
|
+
paths,
|
|
28029
|
+
issueDefaults,
|
|
28030
|
+
tierFor("software-profile")
|
|
28031
|
+
),
|
|
27424
28032
|
buildIndustryDiscoveryBundle(paths, issueDefaults),
|
|
27425
28033
|
buildBusinessModelsBundle(paths, issueDefaults),
|
|
27426
28034
|
buildBcmWriterBundle(paths, issueDefaults),
|
|
27427
28035
|
buildStandardsResearchBundle(paths, issueDefaults),
|
|
27428
28036
|
buildRegulatoryResearchBundle(paths, issueDefaults),
|
|
27429
|
-
buildMaintenanceAuditBundle(
|
|
28037
|
+
buildMaintenanceAuditBundle(
|
|
28038
|
+
paths,
|
|
28039
|
+
issueDefaults,
|
|
28040
|
+
tierFor("maintenance-audit")
|
|
28041
|
+
),
|
|
27430
28042
|
buildDocsSyncBundle(paths)
|
|
27431
28043
|
];
|
|
27432
28044
|
}
|
|
@@ -27672,7 +28284,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
|
|
|
27672
28284
|
/**
|
|
27673
28285
|
* Render all Claude Code configuration files.
|
|
27674
28286
|
*/
|
|
27675
|
-
static render(component, rules, skills, subAgents, mcpServers, settings, procedures) {
|
|
28287
|
+
static render(component, rules, skills, subAgents, mcpServers, settings, procedures, commands) {
|
|
27676
28288
|
_ClaudeRenderer.renderClaudeMd(component, rules);
|
|
27677
28289
|
_ClaudeRenderer.renderScopedRules(component, rules);
|
|
27678
28290
|
_ClaudeRenderer.renderSettings(component, mcpServers, settings);
|
|
@@ -27681,6 +28293,9 @@ var ClaudeRenderer = class _ClaudeRenderer {
|
|
|
27681
28293
|
if (procedures && procedures.length > 0) {
|
|
27682
28294
|
_ClaudeRenderer.renderProcedures(component, procedures);
|
|
27683
28295
|
}
|
|
28296
|
+
if (commands && commands.length > 0) {
|
|
28297
|
+
_ClaudeRenderer.renderCommands(component, commands);
|
|
28298
|
+
}
|
|
27684
28299
|
}
|
|
27685
28300
|
static renderClaudeMd(component, rules) {
|
|
27686
28301
|
const claudeMdRules = rules.filter((r) => {
|
|
@@ -28012,6 +28627,30 @@ var ClaudeRenderer = class _ClaudeRenderer {
|
|
|
28012
28627
|
});
|
|
28013
28628
|
}
|
|
28014
28629
|
}
|
|
28630
|
+
/**
|
|
28631
|
+
* Renders user-invokable slash commands to `.claude/commands/<name>.md`.
|
|
28632
|
+
*
|
|
28633
|
+
* Each command file carries a YAML frontmatter block with the
|
|
28634
|
+
* `description` (always present) and an optional `model` alias. The
|
|
28635
|
+
* body is the {@link AgentCommand.content} written verbatim.
|
|
28636
|
+
*
|
|
28637
|
+
* @see https://docs.claude.com/en/docs/claude-code/slash-commands
|
|
28638
|
+
*/
|
|
28639
|
+
static renderCommands(component, commands) {
|
|
28640
|
+
for (const command of commands) {
|
|
28641
|
+
const lines = [];
|
|
28642
|
+
lines.push("---");
|
|
28643
|
+
lines.push(`description: ${command.description}`);
|
|
28644
|
+
const resolvedModel = resolveModelAlias(command.model);
|
|
28645
|
+
if (resolvedModel) {
|
|
28646
|
+
lines.push(`model: ${resolvedModel}`);
|
|
28647
|
+
}
|
|
28648
|
+
lines.push("---");
|
|
28649
|
+
lines.push("");
|
|
28650
|
+
lines.push(...command.content.split("\n"));
|
|
28651
|
+
new TextFile3(component, `.claude/commands/${command.name}.md`, { lines });
|
|
28652
|
+
}
|
|
28653
|
+
}
|
|
28015
28654
|
/**
|
|
28016
28655
|
* Determine the default Claude rule target based on rule scope.
|
|
28017
28656
|
* ALWAYS-scoped rules default to CLAUDE_MD; FILE_PATTERN rules default to SCOPED_FILE.
|
|
@@ -28034,6 +28673,45 @@ var CopilotRenderer = class {
|
|
|
28034
28673
|
};
|
|
28035
28674
|
|
|
28036
28675
|
// src/agent/agent-config.ts
|
|
28676
|
+
function mapAgentTier(value) {
|
|
28677
|
+
switch (value) {
|
|
28678
|
+
case "powerful":
|
|
28679
|
+
return AGENT_MODEL.POWERFUL;
|
|
28680
|
+
case "fast":
|
|
28681
|
+
return AGENT_MODEL.FAST;
|
|
28682
|
+
case "balanced":
|
|
28683
|
+
default:
|
|
28684
|
+
return AGENT_MODEL.BALANCED;
|
|
28685
|
+
}
|
|
28686
|
+
}
|
|
28687
|
+
function resolveDefaultAgentTier(options) {
|
|
28688
|
+
return mapAgentTier(options?.defaultAgentTier);
|
|
28689
|
+
}
|
|
28690
|
+
var TIER_AWARE_BUNDLE_NAMES = [
|
|
28691
|
+
"company-profile",
|
|
28692
|
+
"customer-profile",
|
|
28693
|
+
"maintenance-audit",
|
|
28694
|
+
"meeting-analysis",
|
|
28695
|
+
"people-profile",
|
|
28696
|
+
"software-profile"
|
|
28697
|
+
];
|
|
28698
|
+
function resolveBundleAgentTiers(options) {
|
|
28699
|
+
const overrides = options?.bundleAgentTiers;
|
|
28700
|
+
if (!overrides) {
|
|
28701
|
+
return /* @__PURE__ */ new Map();
|
|
28702
|
+
}
|
|
28703
|
+
const validNames = new Set(TIER_AWARE_BUNDLE_NAMES);
|
|
28704
|
+
const out = /* @__PURE__ */ new Map();
|
|
28705
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
28706
|
+
if (!validNames.has(name)) {
|
|
28707
|
+
throw new Error(
|
|
28708
|
+
`bundleAgentTiers contains unknown bundle name "${name}". Valid names are: ${TIER_AWARE_BUNDLE_NAMES.join(", ")}.`
|
|
28709
|
+
);
|
|
28710
|
+
}
|
|
28711
|
+
out.set(name, mapAgentTier(value));
|
|
28712
|
+
}
|
|
28713
|
+
return out;
|
|
28714
|
+
}
|
|
28037
28715
|
var DEFAULT_CLAUDE_ALLOW = [
|
|
28038
28716
|
// ── Git ──────────────────────────────────────────────────────────────
|
|
28039
28717
|
"Bash(git add *)",
|
|
@@ -28138,6 +28816,45 @@ var DEFAULT_CLAUDE_DENY = [
|
|
|
28138
28816
|
"Bash(export *)",
|
|
28139
28817
|
"Bash(env *)"
|
|
28140
28818
|
];
|
|
28819
|
+
var DEFAULT_CLAUDE_PATH_DENY = [
|
|
28820
|
+
"Read(./node_modules/**)",
|
|
28821
|
+
"Read(./dist/**)",
|
|
28822
|
+
"Read(./lib/**)",
|
|
28823
|
+
"Read(./.astro/**)",
|
|
28824
|
+
"Read(./.env)",
|
|
28825
|
+
"Read(./.env.*)",
|
|
28826
|
+
"Read(./*.lock)",
|
|
28827
|
+
"Read(./pnpm-lock.yaml)",
|
|
28828
|
+
"Read(./package-lock.json)"
|
|
28829
|
+
];
|
|
28830
|
+
var DEFAULT_USAGE_LOG_PATH = ".claude/usage.log";
|
|
28831
|
+
var DEFAULT_CLAUDE_ENV = {
|
|
28832
|
+
ENABLE_TOOL_SEARCH: "1"
|
|
28833
|
+
};
|
|
28834
|
+
var DEFAULT_CLAUDE_HOOKS = {
|
|
28835
|
+
Stop: [
|
|
28836
|
+
{
|
|
28837
|
+
matcher: "*",
|
|
28838
|
+
hooks: [
|
|
28839
|
+
{
|
|
28840
|
+
type: "command",
|
|
28841
|
+
command: `echo "$(date -u +%FT%TZ),\${CLAUDE_SESSION_ID:-unknown},\${CLAUDE_INPUT_TOKENS:-0},\${CLAUDE_OUTPUT_TOKENS:-0}" >> ${DEFAULT_USAGE_LOG_PATH}`
|
|
28842
|
+
}
|
|
28843
|
+
]
|
|
28844
|
+
}
|
|
28845
|
+
],
|
|
28846
|
+
PostToolUse: [
|
|
28847
|
+
{
|
|
28848
|
+
matcher: "Edit|Write",
|
|
28849
|
+
hooks: [
|
|
28850
|
+
{
|
|
28851
|
+
type: "command",
|
|
28852
|
+
command: 'case "${CLAUDE_TOOL_INPUT_path:-}" in *docs/src/content/docs/*) if [ -x .claude/procedures/check-links.sh ]; then bash .claude/procedures/check-links.sh "$CLAUDE_TOOL_INPUT_path" 2>&1 | head -20; fi ;; esac'
|
|
28853
|
+
}
|
|
28854
|
+
]
|
|
28855
|
+
}
|
|
28856
|
+
]
|
|
28857
|
+
};
|
|
28141
28858
|
var PROGRESS_FILE_BUNDLE_HOOKS = [
|
|
28142
28859
|
["bcm-writer-workflow", "bcm-writer"],
|
|
28143
28860
|
["business-models-workflow", "business-models"],
|
|
@@ -28212,10 +28929,30 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28212
28929
|
return (examples.t1?.length ?? 0) > 0 || (examples.t2?.length ?? 0) > 0 || (examples.t3?.length ?? 0) > 0 || (examples.t4?.length ?? 0) > 0;
|
|
28213
28930
|
}
|
|
28214
28931
|
/**
|
|
28215
|
-
* Merges default Claude permissions with bundle and
|
|
28932
|
+
* Merges default Claude permissions and hooks with bundle and
|
|
28933
|
+
* user-supplied settings.
|
|
28216
28934
|
*
|
|
28217
|
-
*
|
|
28218
|
-
* `
|
|
28935
|
+
* Permission merge order: defaults → bundle permissions → user-supplied
|
|
28936
|
+
* entries. Both `allow` and `deny` are deduped via
|
|
28937
|
+
* `Array.from(new Set(...))`; V8 `Set` iteration preserves insertion
|
|
28938
|
+
* order, so the final ordering is defaults first, then bundle, then
|
|
28939
|
+
* user, with duplicates removed (first-occurrence wins). `defaultMode`
|
|
28940
|
+
* defaults to `"dontAsk"` unless overridden — see the inline comment
|
|
28941
|
+
* on the literal below for the autonomous-worker rationale.
|
|
28942
|
+
*
|
|
28943
|
+
* Hooks merge: consumer-supplied entries first, then default entries
|
|
28944
|
+
* (Stop, PostToolUse), deduped by `(matcher, JSON-serialized hooks)`.
|
|
28945
|
+
* Defaults are skipped entirely when `disableAllHooks: true` is set —
|
|
28946
|
+
* the `disableAllHooks` flag passes through to the rendered file so
|
|
28947
|
+
* Claude Code suppresses every project-level hook at runtime, and the
|
|
28948
|
+
* defaults are dropped at synth time so the rendered file does not
|
|
28949
|
+
* carry orphan entries that would re-fire if the operator later flipped
|
|
28950
|
+
* the flag back off.
|
|
28951
|
+
*
|
|
28952
|
+
* Env merge: defaults from `DEFAULT_CLAUDE_ENV` (e.g.
|
|
28953
|
+
* `ENABLE_TOOL_SEARCH=1`) layer first, then consumer-supplied
|
|
28954
|
+
* `claudeSettings.env` entries override on key collision. Sibling keys
|
|
28955
|
+
* from both sources land in the rendered file.
|
|
28219
28956
|
*/
|
|
28220
28957
|
static mergeClaudeDefaults(userSettings, bundlePermissions) {
|
|
28221
28958
|
const bundleAllow = bundlePermissions?.allow ?? [];
|
|
@@ -28224,14 +28961,80 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28224
28961
|
const userDeny = userSettings?.permissions?.deny ?? [];
|
|
28225
28962
|
return {
|
|
28226
28963
|
...userSettings,
|
|
28964
|
+
// `defaultMode: "dontAsk"` is configulator's hardcoded default
|
|
28965
|
+
// because scheduled-task workers (issue-worker, orchestrator,
|
|
28966
|
+
// pr-reviewer, and the analyst/writer family) run autonomously
|
|
28967
|
+
// and would deadlock on confirmation prompts. Any other value
|
|
28968
|
+
// breaks the autonomous-worker contract — override only after
|
|
28969
|
+
// revisiting that contract end-to-end. The override path for
|
|
28970
|
+
// consumers is `claudeSettings.defaultMode` on
|
|
28971
|
+
// `AgentConfigOptions`.
|
|
28227
28972
|
defaultMode: userSettings?.defaultMode ?? "dontAsk",
|
|
28228
28973
|
permissions: {
|
|
28229
28974
|
...userSettings?.permissions,
|
|
28230
|
-
allow:
|
|
28231
|
-
|
|
28232
|
-
|
|
28975
|
+
allow: Array.from(
|
|
28976
|
+
/* @__PURE__ */ new Set([...DEFAULT_CLAUDE_ALLOW, ...bundleAllow, ...userAllow])
|
|
28977
|
+
),
|
|
28978
|
+
deny: Array.from(
|
|
28979
|
+
/* @__PURE__ */ new Set([
|
|
28980
|
+
...DEFAULT_CLAUDE_DENY,
|
|
28981
|
+
...DEFAULT_CLAUDE_PATH_DENY,
|
|
28982
|
+
...bundleDeny,
|
|
28983
|
+
...userDeny
|
|
28984
|
+
])
|
|
28985
|
+
)
|
|
28986
|
+
},
|
|
28987
|
+
hooks: _AgentConfig.mergeClaudeHooks(userSettings),
|
|
28988
|
+
env: { ...DEFAULT_CLAUDE_ENV, ...userSettings?.env ?? {} }
|
|
28233
28989
|
};
|
|
28234
28990
|
}
|
|
28991
|
+
/**
|
|
28992
|
+
* Merge default lifecycle hooks (Stop, PostToolUse) with consumer-
|
|
28993
|
+
* supplied entries on `claudeSettings.hooks`. Consumer entries appear
|
|
28994
|
+
* first so a downstream override that wires a faster lint/format hook
|
|
28995
|
+
* runs ahead of the defaults; defaults are appended after.
|
|
28996
|
+
*
|
|
28997
|
+
* Returns `undefined` when neither defaults nor consumer entries
|
|
28998
|
+
* remain — the renderer skips the `hooks` key entirely in that case
|
|
28999
|
+
* so opt-out repos do not ship an empty `"hooks": {}` object.
|
|
29000
|
+
*
|
|
29001
|
+
* Defaults are gated on `disableAllHooks !== true`. When the flag is
|
|
29002
|
+
* set we still pass through any consumer-supplied entries (the
|
|
29003
|
+
* runtime-level `disableAllHooks: true` is what suppresses execution),
|
|
29004
|
+
* but we never inject the bundle defaults. That keeps the disable-all
|
|
29005
|
+
* escape hatch idempotent: flipping the flag drops the bundle's
|
|
29006
|
+
* default surface area instead of leaving the entries on disk for a
|
|
29007
|
+
* future re-enable.
|
|
29008
|
+
*/
|
|
29009
|
+
static mergeClaudeHooks(userSettings) {
|
|
29010
|
+
const userHooks = userSettings?.hooks;
|
|
29011
|
+
const includeDefaults = userSettings?.disableAllHooks !== true;
|
|
29012
|
+
const defaults = includeDefaults ? DEFAULT_CLAUDE_HOOKS : {};
|
|
29013
|
+
const allEvents = /* @__PURE__ */ new Set([
|
|
29014
|
+
...Object.keys(userHooks ?? {}),
|
|
29015
|
+
...Object.keys(defaults)
|
|
29016
|
+
]);
|
|
29017
|
+
const merged = {};
|
|
29018
|
+
for (const event of allEvents) {
|
|
29019
|
+
const userEntries = (userHooks ?? {})[event] ?? [];
|
|
29020
|
+
const defaultEntries = defaults[event] ?? [];
|
|
29021
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29022
|
+
const combined = [];
|
|
29023
|
+
for (const entry of [...userEntries, ...defaultEntries]) {
|
|
29024
|
+
const key = JSON.stringify({
|
|
29025
|
+
matcher: entry.matcher,
|
|
29026
|
+
hooks: entry.hooks
|
|
29027
|
+
});
|
|
29028
|
+
if (seen.has(key)) continue;
|
|
29029
|
+
seen.add(key);
|
|
29030
|
+
combined.push(entry);
|
|
29031
|
+
}
|
|
29032
|
+
if (combined.length > 0) {
|
|
29033
|
+
merged[event] = combined;
|
|
29034
|
+
}
|
|
29035
|
+
}
|
|
29036
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
29037
|
+
}
|
|
28235
29038
|
constructor(project, options = {}) {
|
|
28236
29039
|
super(project);
|
|
28237
29040
|
this.options = options;
|
|
@@ -28260,7 +29063,9 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28260
29063
|
if (!this.cachedBundles) {
|
|
28261
29064
|
this.cachedBundles = buildBuiltInBundles(
|
|
28262
29065
|
this.resolvedPaths,
|
|
28263
|
-
resolveIssueDefaults(this.options.issueDefaults)
|
|
29066
|
+
resolveIssueDefaults(this.options.issueDefaults),
|
|
29067
|
+
resolveDefaultAgentTier(this.options),
|
|
29068
|
+
resolveBundleAgentTiers(this.options)
|
|
28264
29069
|
);
|
|
28265
29070
|
}
|
|
28266
29071
|
return this.cachedBundles;
|
|
@@ -28306,6 +29111,9 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28306
29111
|
if (resolvedRunRatio.enabled) {
|
|
28307
29112
|
this.project.gitignore.addPatterns(`/${resolvedRunRatio.stateFilePath}`);
|
|
28308
29113
|
}
|
|
29114
|
+
if (this.options.claudeSettings?.disableAllHooks !== true) {
|
|
29115
|
+
this.project.gitignore.addPatterns(`/${DEFAULT_USAGE_LOG_PATH}`);
|
|
29116
|
+
}
|
|
28309
29117
|
validateUnblockDependentsConfig(this.options.unblockDependents);
|
|
28310
29118
|
validateIssueDefaultsConfig(this.options.issueDefaults);
|
|
28311
29119
|
const resolvedProgressFiles = validateProgressFilesConfig(
|
|
@@ -28370,6 +29178,7 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28370
29178
|
const skills = this.resolveSkills();
|
|
28371
29179
|
const subAgents = this.resolveSubAgents();
|
|
28372
29180
|
const procedures = this.resolveProcedures();
|
|
29181
|
+
const commands = this.resolveCommands();
|
|
28373
29182
|
const mcpServers = this.options.mcpServers ?? {};
|
|
28374
29183
|
const projectMetadata = ProjectMetadata.of(this.project);
|
|
28375
29184
|
const metadata = projectMetadata?.metadata;
|
|
@@ -28405,7 +29214,8 @@ var AgentConfig = class _AgentConfig extends Component8 {
|
|
|
28405
29214
|
this.options.claudeSettings,
|
|
28406
29215
|
bundlePermissions
|
|
28407
29216
|
),
|
|
28408
|
-
resolvedProcedures
|
|
29217
|
+
resolvedProcedures,
|
|
29218
|
+
commands
|
|
28409
29219
|
);
|
|
28410
29220
|
}
|
|
28411
29221
|
if (platforms.includes(AGENT_PLATFORM.CODEX)) {
|
|
@@ -28544,6 +29354,7 @@ ${section}`
|
|
|
28544
29354
|
}
|
|
28545
29355
|
}
|
|
28546
29356
|
}
|
|
29357
|
+
const injectBundleHooks = this.options.claudeMd?.injectBundleHooks ?? true;
|
|
28547
29358
|
const resolvedProgressFiles = resolveProgressFiles(
|
|
28548
29359
|
this.options.progressFiles
|
|
28549
29360
|
);
|
|
@@ -28561,7 +29372,7 @@ ${section}`
|
|
|
28561
29372
|
}
|
|
28562
29373
|
}
|
|
28563
29374
|
}
|
|
28564
|
-
if (resolvedProgressFiles.enabled) {
|
|
29375
|
+
if (injectBundleHooks && resolvedProgressFiles.enabled) {
|
|
28565
29376
|
for (const [ruleName, label] of PROGRESS_FILE_BUNDLE_HOOKS) {
|
|
28566
29377
|
const existing = ruleMap.get(ruleName);
|
|
28567
29378
|
if (!existing) {
|
|
@@ -28601,7 +29412,7 @@ ${hook}`
|
|
|
28601
29412
|
}
|
|
28602
29413
|
}
|
|
28603
29414
|
}
|
|
28604
|
-
if (resolvedSharedEditingForRules.enabled) {
|
|
29415
|
+
if (injectBundleHooks && resolvedSharedEditingForRules.enabled) {
|
|
28605
29416
|
for (const [ruleName, label] of SHARED_EDITING_BUNDLE_HOOKS) {
|
|
28606
29417
|
const existing = ruleMap.get(ruleName);
|
|
28607
29418
|
if (!existing) {
|
|
@@ -28641,7 +29452,7 @@ ${hook}`
|
|
|
28641
29452
|
}
|
|
28642
29453
|
}
|
|
28643
29454
|
}
|
|
28644
|
-
if (resolvedSkillEvalsForRules.enabled) {
|
|
29455
|
+
if (injectBundleHooks && resolvedSkillEvalsForRules.enabled) {
|
|
28645
29456
|
for (const [ruleName, label] of SKILL_EVALS_BUNDLE_HOOKS) {
|
|
28646
29457
|
const existing = ruleMap.get(ruleName);
|
|
28647
29458
|
if (!existing) {
|
|
@@ -28686,7 +29497,7 @@ ${hook}`
|
|
|
28686
29497
|
if (!hasAnyDocsEmittingBundle(excludedBundleNames)) {
|
|
28687
29498
|
ruleMap.delete("stub-index-convention");
|
|
28688
29499
|
}
|
|
28689
|
-
if (resolvedIssueTemplatesForRules.enabled && hasDownstreamBundles) {
|
|
29500
|
+
if (injectBundleHooks && resolvedIssueTemplatesForRules.enabled && hasDownstreamBundles) {
|
|
28690
29501
|
for (const [ruleName, label] of ISSUE_TEMPLATES_BUNDLE_HOOKS) {
|
|
28691
29502
|
const existing = ruleMap.get(ruleName);
|
|
28692
29503
|
if (!existing) {
|
|
@@ -28734,6 +29545,57 @@ ${hook}`
|
|
|
28734
29545
|
}
|
|
28735
29546
|
}
|
|
28736
29547
|
}
|
|
29548
|
+
const registryRule = buildAgentRegistryRule(
|
|
29549
|
+
this.activeBundles,
|
|
29550
|
+
this.resolvedPaths
|
|
29551
|
+
);
|
|
29552
|
+
if (registryRule) {
|
|
29553
|
+
let registryContent = registryRule.content;
|
|
29554
|
+
const meetingAnalysisActive = this.activeBundles.some(
|
|
29555
|
+
(b) => b.name === "meeting-analysis"
|
|
29556
|
+
);
|
|
29557
|
+
if (this.options.meetings && meetingAnalysisActive) {
|
|
29558
|
+
const meetingsSection = renderMeetingTypesSection(
|
|
29559
|
+
this.options.meetings
|
|
29560
|
+
);
|
|
29561
|
+
if (meetingsSection.length > 0) {
|
|
29562
|
+
registryContent = `${registryContent}
|
|
29563
|
+
|
|
29564
|
+
---
|
|
29565
|
+
|
|
29566
|
+
${meetingsSection}`;
|
|
29567
|
+
}
|
|
29568
|
+
}
|
|
29569
|
+
ruleMap.set(registryRule.name, {
|
|
29570
|
+
...registryRule,
|
|
29571
|
+
content: registryContent
|
|
29572
|
+
});
|
|
29573
|
+
const customSectionBundles = new Set(
|
|
29574
|
+
(this.options.features?.customDocSections ?? []).map(
|
|
29575
|
+
(s) => s.bundleName
|
|
29576
|
+
)
|
|
29577
|
+
);
|
|
29578
|
+
for (const [ruleName, rule] of ruleMap) {
|
|
29579
|
+
if (!isSuppressedWorkflowRule(ruleName)) {
|
|
29580
|
+
continue;
|
|
29581
|
+
}
|
|
29582
|
+
const owningBundleName = bundleNameForWorkflowRule(ruleName);
|
|
29583
|
+
if (owningBundleName !== void 0 && customSectionBundles.has(owningBundleName)) {
|
|
29584
|
+
continue;
|
|
29585
|
+
}
|
|
29586
|
+
const existingClaude = rule.platforms?.claude ?? {};
|
|
29587
|
+
if (existingClaude.exclude === true) {
|
|
29588
|
+
continue;
|
|
29589
|
+
}
|
|
29590
|
+
ruleMap.set(ruleName, {
|
|
29591
|
+
...rule,
|
|
29592
|
+
platforms: {
|
|
29593
|
+
...rule.platforms,
|
|
29594
|
+
claude: { ...existingClaude, exclude: true }
|
|
29595
|
+
}
|
|
29596
|
+
});
|
|
29597
|
+
}
|
|
29598
|
+
}
|
|
28737
29599
|
return [...ruleMap.values()].sort((a, b) => {
|
|
28738
29600
|
if (a.name === "project-overview") return -1;
|
|
28739
29601
|
if (b.name === "project-overview") return 1;
|
|
@@ -28882,6 +29744,49 @@ ${hook}`
|
|
|
28882
29744
|
}
|
|
28883
29745
|
return [...procMap.values()];
|
|
28884
29746
|
}
|
|
29747
|
+
/**
|
|
29748
|
+
* Resolves the final list of slash commands by merging bundle-shipped
|
|
29749
|
+
* defaults with consumer-supplied entries. Mirrors {@link resolveSkills}
|
|
29750
|
+
* and {@link resolveSubAgents}: auto-detected bundles contribute first,
|
|
29751
|
+
* force-included bundles overlay, and consumer commands override on
|
|
29752
|
+
* name collision. Names listed in `excludeCommands` are dropped after
|
|
29753
|
+
* the merge so consumers can opt out of a single default without
|
|
29754
|
+
* disabling the whole bundle.
|
|
29755
|
+
*/
|
|
29756
|
+
resolveCommands() {
|
|
29757
|
+
const commandMap = /* @__PURE__ */ new Map();
|
|
29758
|
+
if (this.options.autoDetectBundles !== false) {
|
|
29759
|
+
for (const bundle of this.pathAwareBundles) {
|
|
29760
|
+
if (this.options.excludeBundles?.includes(bundle.name)) continue;
|
|
29761
|
+
if (bundle.appliesWhen(this.project) && bundle.commands) {
|
|
29762
|
+
for (const command of bundle.commands) {
|
|
29763
|
+
commandMap.set(command.name, command);
|
|
29764
|
+
}
|
|
29765
|
+
}
|
|
29766
|
+
}
|
|
29767
|
+
}
|
|
29768
|
+
if (this.options.includeBundles) {
|
|
29769
|
+
for (const bundleName of this.options.includeBundles) {
|
|
29770
|
+
const bundle = this.pathAwareBundles.find((b) => b.name === bundleName);
|
|
29771
|
+
if (bundle?.commands) {
|
|
29772
|
+
for (const command of bundle.commands) {
|
|
29773
|
+
commandMap.set(command.name, command);
|
|
29774
|
+
}
|
|
29775
|
+
}
|
|
29776
|
+
}
|
|
29777
|
+
}
|
|
29778
|
+
if (this.options.commands) {
|
|
29779
|
+
for (const command of this.options.commands) {
|
|
29780
|
+
commandMap.set(command.name, command);
|
|
29781
|
+
}
|
|
29782
|
+
}
|
|
29783
|
+
if (this.options.excludeCommands) {
|
|
29784
|
+
for (const name of this.options.excludeCommands) {
|
|
29785
|
+
commandMap.delete(name);
|
|
29786
|
+
}
|
|
29787
|
+
}
|
|
29788
|
+
return [...commandMap.values()];
|
|
29789
|
+
}
|
|
28885
29790
|
/**
|
|
28886
29791
|
* Resolves template variables in rule content using project metadata.
|
|
28887
29792
|
* Emits synthesis warnings for rules with unresolved variables.
|
|
@@ -33326,6 +34231,7 @@ var TypeScriptConfig = class extends Component20 {
|
|
|
33326
34231
|
export {
|
|
33327
34232
|
AGENT_MODEL,
|
|
33328
34233
|
AGENT_PLATFORM,
|
|
34234
|
+
AGENT_REGISTRY_ENTRIES,
|
|
33329
34235
|
AGENT_RULE_SCOPE,
|
|
33330
34236
|
AGENT_TIER_ROLES,
|
|
33331
34237
|
AGENT_TIER_VALUES,
|
|
@@ -33422,8 +34328,10 @@ export {
|
|
|
33422
34328
|
SCOPE_CLASS_VALUES,
|
|
33423
34329
|
SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
|
|
33424
34330
|
STARLIGHT_ROLE,
|
|
34331
|
+
SUPPRESSED_WORKFLOW_RULE_NAMES,
|
|
33425
34332
|
SampleLang,
|
|
33426
34333
|
StarlightProject,
|
|
34334
|
+
TIER_AWARE_BUNDLE_NAMES,
|
|
33427
34335
|
TestRunner,
|
|
33428
34336
|
TsDocCoverageKind,
|
|
33429
34337
|
TurboRepo,
|
|
@@ -33447,6 +34355,7 @@ export {
|
|
|
33447
34355
|
awsCdkBundle,
|
|
33448
34356
|
baseBundle,
|
|
33449
34357
|
bcmWriterBundle,
|
|
34358
|
+
buildAgentRegistryRule,
|
|
33450
34359
|
buildBaseBundle,
|
|
33451
34360
|
buildBcmWriterBundle,
|
|
33452
34361
|
buildBuiltInBundles,
|
|
@@ -33457,6 +34366,7 @@ export {
|
|
|
33457
34366
|
buildDocsSyncBundle,
|
|
33458
34367
|
buildIndustryDiscoveryBundle,
|
|
33459
34368
|
buildMaintenanceAuditBundle,
|
|
34369
|
+
buildMeetingAnalysisBundle,
|
|
33460
34370
|
buildOrchestratorConventionsContent,
|
|
33461
34371
|
buildPeopleProfileBundle,
|
|
33462
34372
|
buildRegulatoryResearchBundle,
|
|
@@ -33468,6 +34378,7 @@ export {
|
|
|
33468
34378
|
buildSoftwareProfileBundle,
|
|
33469
34379
|
buildStandardsResearchBundle,
|
|
33470
34380
|
buildUnblockDependentsProcedure,
|
|
34381
|
+
bundleNameForWorkflowRule,
|
|
33471
34382
|
businessModelsBundle,
|
|
33472
34383
|
checkDocSamplesProcedure,
|
|
33473
34384
|
checkLinksProcedure,
|
|
@@ -33494,6 +34405,7 @@ export {
|
|
|
33494
34405
|
industryDiscoveryBundle,
|
|
33495
34406
|
isPhaseLabelOwnedByExcluded,
|
|
33496
34407
|
isScheduledTaskOwnedByExcluded,
|
|
34408
|
+
isSuppressedWorkflowRule,
|
|
33497
34409
|
isTypeLabelOwnedByExcluded,
|
|
33498
34410
|
jestBundle,
|
|
33499
34411
|
labelsForPhase,
|
|
@@ -33552,6 +34464,8 @@ export {
|
|
|
33552
34464
|
resolveAgentTiers,
|
|
33553
34465
|
resolveAstroProjectOutdir,
|
|
33554
34466
|
resolveAwsCdkProjectOutdir,
|
|
34467
|
+
resolveBundleAgentTiers,
|
|
34468
|
+
resolveDefaultAgentTier,
|
|
33555
34469
|
resolveIssueDefaults,
|
|
33556
34470
|
resolveIssueTemplates,
|
|
33557
34471
|
resolveModelAlias,
|