@codedrifters/configulator 0.0.296 → 0.0.298

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.js CHANGED
@@ -177,6 +177,7 @@ var index_exports = {};
177
177
  __export(index_exports, {
178
178
  AGENT_MODEL: () => AGENT_MODEL,
179
179
  AGENT_PLATFORM: () => AGENT_PLATFORM,
180
+ AGENT_REGISTRY_ENTRIES: () => AGENT_REGISTRY_ENTRIES,
180
181
  AGENT_RULE_SCOPE: () => AGENT_RULE_SCOPE,
181
182
  AGENT_TIER_ROLES: () => AGENT_TIER_ROLES,
182
183
  AGENT_TIER_VALUES: () => AGENT_TIER_VALUES,
@@ -260,6 +261,7 @@ __export(index_exports, {
260
261
  MINIMUM_RELEASE_AGE: () => MINIMUM_RELEASE_AGE,
261
262
  MONOREPO_LAYOUT: () => MONOREPO_LAYOUT,
262
263
  MonorepoProject: () => MonorepoProject,
264
+ Nvmrc: () => Nvmrc,
263
265
  PROD_DEPLOY_NAME: () => PROD_DEPLOY_NAME,
264
266
  PROGRESS_FILES_FORMAT_VALUES: () => PROGRESS_FILES_FORMAT_VALUES,
265
267
  PnpmWorkspace: () => PnpmWorkspace,
@@ -272,6 +274,7 @@ __export(index_exports, {
272
274
  SCOPE_CLASS_VALUES: () => SCOPE_CLASS_VALUES,
273
275
  SHARED_EDITING_CONFLICT_STRATEGY_VALUES: () => SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
274
276
  STARLIGHT_ROLE: () => STARLIGHT_ROLE,
277
+ SUPPRESSED_WORKFLOW_RULE_NAMES: () => SUPPRESSED_WORKFLOW_RULE_NAMES,
275
278
  SampleLang: () => SampleLang,
276
279
  StarlightProject: () => StarlightProject,
277
280
  TestRunner: () => TestRunner,
@@ -297,6 +300,7 @@ __export(index_exports, {
297
300
  awsCdkBundle: () => awsCdkBundle,
298
301
  baseBundle: () => baseBundle,
299
302
  bcmWriterBundle: () => bcmWriterBundle,
303
+ buildAgentRegistryRule: () => buildAgentRegistryRule,
300
304
  buildBaseBundle: () => buildBaseBundle,
301
305
  buildBcmWriterBundle: () => buildBcmWriterBundle,
302
306
  buildBuiltInBundles: () => buildBuiltInBundles,
@@ -307,6 +311,7 @@ __export(index_exports, {
307
311
  buildDocsSyncBundle: () => buildDocsSyncBundle,
308
312
  buildIndustryDiscoveryBundle: () => buildIndustryDiscoveryBundle,
309
313
  buildMaintenanceAuditBundle: () => buildMaintenanceAuditBundle,
314
+ buildMeetingAnalysisBundle: () => buildMeetingAnalysisBundle,
310
315
  buildOrchestratorConventionsContent: () => buildOrchestratorConventionsContent,
311
316
  buildPeopleProfileBundle: () => buildPeopleProfileBundle,
312
317
  buildRegulatoryResearchBundle: () => buildRegulatoryResearchBundle,
@@ -318,6 +323,7 @@ __export(index_exports, {
318
323
  buildSoftwareProfileBundle: () => buildSoftwareProfileBundle,
319
324
  buildStandardsResearchBundle: () => buildStandardsResearchBundle,
320
325
  buildUnblockDependentsProcedure: () => buildUnblockDependentsProcedure,
326
+ bundleNameForWorkflowRule: () => bundleNameForWorkflowRule,
321
327
  businessModelsBundle: () => businessModelsBundle,
322
328
  checkDocSamplesProcedure: () => checkDocSamplesProcedure,
323
329
  checkLinksProcedure: () => checkLinksProcedure,
@@ -344,6 +350,7 @@ __export(index_exports, {
344
350
  industryDiscoveryBundle: () => industryDiscoveryBundle,
345
351
  isPhaseLabelOwnedByExcluded: () => isPhaseLabelOwnedByExcluded,
346
352
  isScheduledTaskOwnedByExcluded: () => isScheduledTaskOwnedByExcluded,
353
+ isSuppressedWorkflowRule: () => isSuppressedWorkflowRule,
347
354
  isTypeLabelOwnedByExcluded: () => isTypeLabelOwnedByExcluded,
348
355
  jestBundle: () => jestBundle,
349
356
  labelsForPhase: () => labelsForPhase,
@@ -353,6 +360,8 @@ __export(index_exports, {
353
360
  parseApiRollup: () => parseApiRollup,
354
361
  peopleProfileBundle: () => peopleProfileBundle,
355
362
  persistAuditReport: () => persistAuditReport,
363
+ pinPnpmActionSetup: () => pinPnpmActionSetup,
364
+ pinSetupNodeVersion: () => pinSetupNodeVersion,
356
365
  pnpmBundle: () => pnpmBundle,
357
366
  prReviewBundle: () => prReviewBundle,
358
367
  projenBundle: () => projenBundle,
@@ -400,6 +409,7 @@ __export(index_exports, {
400
409
  resolveAgentTiers: () => resolveAgentTiers,
401
410
  resolveAstroProjectOutdir: () => resolveAstroProjectOutdir,
402
411
  resolveAwsCdkProjectOutdir: () => resolveAwsCdkProjectOutdir,
412
+ resolveDefaultAgentTier: () => resolveDefaultAgentTier,
403
413
  resolveIssueDefaults: () => resolveIssueDefaults,
404
414
  resolveIssueTemplates: () => resolveIssueTemplates,
405
415
  resolveModelAlias: () => resolveModelAlias,
@@ -442,6 +452,45 @@ module.exports = __toCommonJS(index_exports);
442
452
  // src/agent/agent-config.ts
443
453
  var import_projen8 = require("projen");
444
454
 
455
+ // src/agent/types.ts
456
+ var AGENT_RULE_SCOPE = {
457
+ ALWAYS: "always",
458
+ FILE_PATTERN: "file-pattern"
459
+ };
460
+ var AGENT_PLATFORM = {
461
+ CURSOR: "cursor",
462
+ CLAUDE: "claude",
463
+ CODEX: "codex",
464
+ COPILOT: "copilot"
465
+ };
466
+ var CLAUDE_RULE_TARGET = {
467
+ SCOPED_FILE: "scoped-file",
468
+ AGENTS_MD: "agents-md",
469
+ CLAUDE_MD: "claude-md"
470
+ };
471
+ var AGENT_MODEL = {
472
+ INHERIT: "inherit",
473
+ FAST: "fast",
474
+ BALANCED: "balanced",
475
+ POWERFUL: "powerful"
476
+ };
477
+ function resolveModelAlias(model) {
478
+ if (!model || model === AGENT_MODEL.INHERIT) {
479
+ return void 0;
480
+ }
481
+ const mapping = {
482
+ [AGENT_MODEL.POWERFUL]: "opus",
483
+ [AGENT_MODEL.BALANCED]: "sonnet",
484
+ [AGENT_MODEL.FAST]: "haiku"
485
+ };
486
+ return mapping[model] ?? model;
487
+ }
488
+ var MCP_TRANSPORT = {
489
+ STDIO: "stdio",
490
+ HTTP: "http",
491
+ SSE: "sse"
492
+ };
493
+
445
494
  // src/agent/bundles/project-context.ts
446
495
  var PROJECT_CONTEXT_PATH = "docs/src/content/docs/project-context.md";
447
496
  var SUBPROJECT_ROLE_GUIDANCE = [
@@ -569,45 +618,6 @@ var MONOREPO_LAYOUT_SEED_BLOCK = [
569
618
  ""
570
619
  ].join("\n");
571
620
 
572
- // src/agent/types.ts
573
- var AGENT_RULE_SCOPE = {
574
- ALWAYS: "always",
575
- FILE_PATTERN: "file-pattern"
576
- };
577
- var AGENT_PLATFORM = {
578
- CURSOR: "cursor",
579
- CLAUDE: "claude",
580
- CODEX: "codex",
581
- COPILOT: "copilot"
582
- };
583
- var CLAUDE_RULE_TARGET = {
584
- SCOPED_FILE: "scoped-file",
585
- AGENTS_MD: "agents-md",
586
- CLAUDE_MD: "claude-md"
587
- };
588
- var AGENT_MODEL = {
589
- INHERIT: "inherit",
590
- FAST: "fast",
591
- BALANCED: "balanced",
592
- POWERFUL: "powerful"
593
- };
594
- function resolveModelAlias(model) {
595
- if (!model || model === AGENT_MODEL.INHERIT) {
596
- return void 0;
597
- }
598
- const mapping = {
599
- [AGENT_MODEL.POWERFUL]: "opus",
600
- [AGENT_MODEL.BALANCED]: "sonnet",
601
- [AGENT_MODEL.FAST]: "haiku"
602
- };
603
- return mapping[model] ?? model;
604
- }
605
- var MCP_TRANSPORT = {
606
- STDIO: "stdio",
607
- HTTP: "http",
608
- SSE: "sse"
609
- };
610
-
611
621
  // src/agent/bundles/agenda.ts
612
622
  var agendaAnalystSubAgent = {
613
623
  name: "agenda-analyst",
@@ -3628,6 +3638,7 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
3628
3638
  "- **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`.",
3629
3639
  "- **Configure dependencies through Projen** \u2014 never use `npm install`, `pnpm add`, or `yarn add`. Add them to `deps` or `devDeps` in Projen config.",
3630
3640
  "- **Export from index.ts** to maintain clean public APIs",
3641
+ '- **`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`.',
3631
3642
  "",
3632
3643
  "## Repository Layout",
3633
3644
  "",
@@ -6103,11 +6114,11 @@ function buildBusinessModelsBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
6103
6114
  var businessModelsBundle = buildBusinessModelsBundle();
6104
6115
 
6105
6116
  // src/agent/bundles/company-profile.ts
6106
- function buildCompanyProfileAnalystSubAgent(paths, issueDefaults) {
6117
+ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier) {
6107
6118
  return {
6108
6119
  name: "company-profile-analyst",
6109
6120
  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.",
6110
- model: AGENT_MODEL.POWERFUL,
6121
+ model: tier,
6111
6122
  maxTurns: 80,
6112
6123
  platforms: { cursor: { exclude: true } },
6113
6124
  prompt: [
@@ -7294,7 +7305,7 @@ function buildAnalyzeSegmentSkill(paths, issueDefaults) {
7294
7305
  ].join("\n")
7295
7306
  };
7296
7307
  }
7297
- function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
7308
+ function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
7298
7309
  return {
7299
7310
  name: "company-profile",
7300
7311
  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.",
@@ -7352,7 +7363,7 @@ function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
7352
7363
  buildRefreshCompanySkill(paths, issueDefaults),
7353
7364
  buildAnalyzeSegmentSkill(paths, issueDefaults)
7354
7365
  ],
7355
- subAgents: [buildCompanyProfileAnalystSubAgent(paths, issueDefaults)],
7366
+ subAgents: [buildCompanyProfileAnalystSubAgent(paths, issueDefaults, tier)],
7356
7367
  labels: [
7357
7368
  {
7358
7369
  name: "type:company-profile",
@@ -7532,11 +7543,11 @@ var CUSTOMER_PROFILE_REFERENCE_FILES = [
7532
7543
  content: TEMPLATE_CUSTOMER_PROFILE
7533
7544
  }
7534
7545
  ];
7535
- function buildCustomerProfileAnalystSubAgent(paths, issueDefaults) {
7546
+ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier) {
7536
7547
  return {
7537
7548
  name: "customer-profile-analyst",
7538
7549
  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.",
7539
- model: AGENT_MODEL.POWERFUL,
7550
+ model: tier,
7540
7551
  maxTurns: 80,
7541
7552
  platforms: { cursor: { exclude: true } },
7542
7553
  prompt: [
@@ -8361,7 +8372,7 @@ function buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults) {
8361
8372
  ].join("\n")
8362
8373
  };
8363
8374
  }
8364
- function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
8375
+ function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
8365
8376
  return {
8366
8377
  name: "customer-profile",
8367
8378
  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.",
@@ -8436,7 +8447,9 @@ function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
8436
8447
  buildProfileCustomerSkill(paths, issueDefaults),
8437
8448
  buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults)
8438
8449
  ],
8439
- subAgents: [buildCustomerProfileAnalystSubAgent(paths, issueDefaults)],
8450
+ subAgents: [
8451
+ buildCustomerProfileAnalystSubAgent(paths, issueDefaults, tier)
8452
+ ],
8440
8453
  labels: [
8441
8454
  {
8442
8455
  name: "type:customer-profile",
@@ -10219,11 +10232,11 @@ var jestBundle = {
10219
10232
  };
10220
10233
 
10221
10234
  // src/agent/bundles/maintenance-audit.ts
10222
- function buildMaintenanceAuditSubAgent(paths) {
10235
+ function buildMaintenanceAuditSubAgent(paths, tier) {
10223
10236
  return {
10224
10237
  name: "maintenance-audit",
10225
10238
  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.",
10226
- model: AGENT_MODEL.POWERFUL,
10239
+ model: tier,
10227
10240
  maxTurns: 80,
10228
10241
  platforms: { cursor: { exclude: true } },
10229
10242
  prompt: [
@@ -10857,7 +10870,7 @@ function buildMaintenanceVerifySkill(issueDefaults) {
10857
10870
  ].join("\n")
10858
10871
  };
10859
10872
  }
10860
- function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
10873
+ function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
10861
10874
  return {
10862
10875
  name: "maintenance-audit",
10863
10876
  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.",
@@ -10904,7 +10917,7 @@ function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults
10904
10917
  buildMaintenanceAuditSkill(paths, issueDefaults),
10905
10918
  buildMaintenanceVerifySkill(issueDefaults)
10906
10919
  ],
10907
- subAgents: [buildMaintenanceAuditSubAgent(paths)],
10920
+ subAgents: [buildMaintenanceAuditSubAgent(paths, tier)],
10908
10921
  labels: [
10909
10922
  {
10910
10923
  name: "type:maintenance",
@@ -10932,351 +10945,353 @@ function buildMaintenanceAuditBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults
10932
10945
  var maintenanceAuditBundle = buildMaintenanceAuditBundle();
10933
10946
 
10934
10947
  // src/agent/bundles/meeting-analysis.ts
10935
- var meetingAnalystSubAgent = {
10936
- name: "meeting-analyst",
10937
- description: "Processes meeting transcripts through a 4-phase pipeline: extract, notes, draft, and link",
10938
- model: AGENT_MODEL.POWERFUL,
10939
- maxTurns: 80,
10940
- platforms: { cursor: { exclude: true } },
10941
- prompt: [
10942
- "# Meeting Analyst Agent",
10943
- "",
10944
- "You process meeting transcripts through a structured 4-phase pipeline.",
10945
- "Each phase runs as a **separate agent session**, triggered by its own",
10946
- "GitHub issue with a `meeting:*` phase label. You handle exactly **one",
10947
- "phase per session** \u2014 read the issue to determine which phase to execute.",
10948
- "",
10949
- "## Execution Model",
10950
- "",
10951
- "1. Each meeting produces up to 4 GitHub issues (one per phase)",
10952
- "2. Each issue carries a `meeting:*` label identifying the phase",
10953
- "3. You pick up one issue, execute that phase, commit/push, then close the issue",
10954
- "4. Phase 1 (Extract) creates the downstream phase issues for phases 2-4",
10955
- "5. Each downstream issue includes `Depends on: #N` linking to its predecessor",
10956
- "",
10957
- "## Design Principles",
10958
- "",
10959
- "1. **Extract, don't interpret.** Capture what was said and decided. Flag",
10960
- " ambiguity as open items rather than resolving it.",
10961
- "2. **Route to the right category.** Meeting content maps to requirements,",
10962
- " ADRs, product docs, and business strategy. Each output goes to the",
10963
- " correct location per the project's taxonomy.",
10964
- "3. **Preserve provenance.** Every extracted item links back to the meeting",
10965
- " source so reviewers can check context.",
10966
- "4. **Create issues, not documents.** For requirements and ADRs, create",
10967
- " GitHub issues that other agents or humans will pick up. Do not write",
10968
- " final requirement documents yourself.",
10969
- "5. **Bi-directional traceability.** Every document and issue created by",
10970
- " this pipeline must link back to the meeting source, and the meeting",
10971
- " source documents must link forward to everything created from them.",
10972
- "6. **Respect meeting type and areas.** Read the `meeting_type` and",
10973
- " `areas` values from the meeting frontmatter before starting Phase 1.",
10974
- " Apply the type-specific rules from the **Meeting type handling**",
10975
- " table (phases 1\u20132) and the area-filtered routing rules from the",
10976
- " **Areas filtering** table (phase 4).",
10977
- "",
10978
- "---",
10979
- "",
10980
- "## Meeting type handling",
10981
- "",
10982
- "Meeting frontmatter is expected to carry a `meeting_type` field whose",
10983
- "value is one of the project's concrete meeting-type `id`s (declared",
10984
- "via `AgentConfigOptions.meetings.meetingTypes`). Each concrete `id`",
10985
- "maps to one of six generic **meeting kinds** that drive type-specific",
10986
- "extraction rules:",
10987
- "",
10988
- "| Kind | Primary outputs | Phase-1/2 rules |",
10989
- "|------|-----------------|-----------------|",
10990
- "| `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. |",
10991
- "| `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. |",
10992
- "| `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. |",
10993
- "| `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. |",
10994
- "| `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. |",
10995
- "| `other` | General meeting extraction | Apply the default workflow with no type-specific overrides. |",
10996
- "",
10997
- "**How to resolve the kind:**",
10998
- "",
10999
- "1. Read `meeting_type` from the frontmatter.",
11000
- "2. Look up the matching `id` in the project's **Recognized meeting",
11001
- " types** table (rendered below when `meetingTypes` is declared).",
11002
- "3. Use the `Kind` column value. If the table is absent, the `id` is",
11003
- " unknown, or the `Kind` column is `\u2014`, fall back to `other`.",
11004
- "4. Apply the rules in the row above **in addition to** the normal",
11005
- " phase workflow \u2014 never as a replacement.",
11006
- "",
11007
- "If `meeting_type` is missing, invalid, or the declared `id` is not in",
11008
- "the project's table, note it in the extraction's Open Questions and",
11009
- "proceed with the default workflow (treat as `other`).",
11010
- "",
11011
- "## Areas filtering",
11012
- "",
11013
- "Meeting frontmatter may carry an `areas: [...]` list whose values",
11014
- "match `id`s from the project's **Area \u2192 doc-root mapping** table",
11015
- "(declared via `AgentConfigOptions.meetings.meetingAreas`). The list",
11016
- "scopes phase-4 direct edits and cross-references to the doc-root",
11017
- "sub-folders registered for those areas. A given area's effective",
11018
- "path resolves as `<docsRoot>/<docRoot>` \u2014 `docsRoot` comes from",
11019
- "`AgentPathsConfig.docsRoot`; `docRoot` is the sub-folder shown in",
11020
- "the **Area \u2192 doc-root mapping** table.",
11021
- "",
11022
- "**Gating contract (phase 4 only):**",
11023
- "",
11024
- "- **Scoped in:** direct edits and cross-reference stubs under the",
11025
- " `docRoot` of every `id` present in the meeting's `areas` list.",
11026
- "- **Scoped out:** direct edits to any doc-root sub-folder that is",
11027
- " declared in the project's area map but whose `id` is **not** in",
11028
- " the meeting's `areas`. For those out-of-scope areas, create",
11029
- " follow-up issues instead of editing the doc directly.",
11030
- "- **Not gated:** issue creation (requirements, ADRs, profiles,",
11031
- " research) is always in scope regardless of areas.",
11032
- "",
11033
- "**Resolution rules:**",
11034
- "",
11035
- "1. If the meeting's `areas` frontmatter is missing or empty **and**",
11036
- " the project has declared a non-empty `meetingAreas` map, no",
11037
- " doc-root sub-folder is gated in: direct edits to any declared",
11038
- " `docRoot` sub-folder are out-of-scope and become follow-up issues",
11039
- " per step 6. Only the default meetings root (`meetingsRoot`)",
11040
- " remains editable.",
11041
- "2. If `areas` lists an `id` that is not in the project's area map,",
11042
- " note it in the extraction's Open Questions and treat the unknown",
11043
- " `id` as absent. Do **not** invent a doc-root path for it.",
11044
- "3. Out-of-scope direct edits become `type:docs` follow-up issues on",
11045
- " phase 4 step 6, with the area noted in the issue body.",
11046
- "",
11047
- "When the project has **not** declared any `meetingAreas` at all,",
11048
- "this section applies degenerately \u2014 no areas are gated, no",
11049
- "follow-up issues are synthesized for missing areas, and phase-4",
11050
- "direct edits follow the default workflow (step 6 edits any doc",
11051
- "flagged as Firm, unrestricted by `docRoot`).",
11052
- "",
11053
- "---",
11054
- "",
11055
- ...PROJECT_CONTEXT_MAINTAINER_SECTION,
11056
- "## Traceability",
11057
- "",
11058
- "All outputs must be bi-directionally linked so any artifact can be traced",
11059
- "back to the meeting that produced it and forward to everything it spawned.",
11060
- "",
11061
- "### Backward links (created artifact \u2192 meeting source)",
11062
- "",
11063
- "Every GitHub issue and document created by this pipeline must include a",
11064
- "`## Traceability` section with:",
11065
- "",
11066
- "```markdown",
11067
- "## Traceability",
11068
- "",
11069
- "- **Source meeting:** <path to transcript or meeting notes>",
11070
- "- **Extraction:** <path to extraction file>",
11071
- "- **Phase issue:** #<N> (the phase issue that created this artifact)",
11072
- "```",
11073
- "",
11074
- "### Forward links (meeting source \u2192 created artifacts)",
11075
- "",
11076
- "After Phase 4 (Link) creates all follow-up issues and documents:",
11077
- "",
11078
- "1. **Update the extraction file** with a `## Downstream Artifacts` section",
11079
- " listing every issue and document created from this meeting:",
11080
- "",
11081
- " ```markdown",
11082
- " ## Downstream Artifacts",
11083
- "",
11084
- " | Artifact | Type | Issue/Path |",
11085
- " |----------|------|------------|",
11086
- " | <title> | requirement / ADR / action-item / profile | #<N> or <path> |",
11087
- " ```",
11088
- "",
11089
- "2. **Update the meeting notes** with a similar `## Related Issues` section",
11090
- " listing all issues created from this meeting.",
11091
- "",
11092
- "3. **Comment on the extract issue** with a summary linking to all created",
11093
- " artifacts.",
11094
- "",
11095
- "### Within-pipeline links",
11096
- "",
11097
- "- Phase issues link to predecessors via `Depends on: #N`",
11098
- "- Phase issues reference the extraction file path in their body",
11099
- "- Draft documents reference both the extraction and the meeting notes",
11100
- "",
11101
- "---",
11102
- "",
11103
- "## Phase 1: Extract (`meeting:extract`)",
11104
- "",
11105
- "**Goal:** Read the meeting transcript and categorize all substantive content.",
11106
- "",
11107
- "### Steps",
11108
- "",
11109
- "1. Read the transcript file specified in the issue body. Parse the",
11110
- " meeting-note frontmatter first, capturing `meeting_type` and",
11111
- " `areas`. Resolve `meeting_type` to a kind using the **Meeting type",
11112
- " handling** table; note the resolved kind in the extraction",
11113
- " frontmatter. If `meeting_type` is missing or not in the project's",
11114
- " Recognized meeting types table, treat it as `other` and flag it",
11115
- " in Open Questions.",
11116
- "2. Identify and categorize content into these buckets:",
11117
- "",
11118
- " | Bucket | What to look for |",
11119
- " |--------|-----------------|",
11120
- ` | **Decisions** | "We decided...", "Let's go with...", explicit choices |`,
11121
- ' | **Requirements** | Feature descriptions, acceptance criteria, "it should..." |',
11122
- " | **Technology discussions** | Platform comparisons, architecture options, tool evaluations |",
11123
- ' | **Action items** | "[Person] will...", "Next step is...", assigned tasks |',
11124
- ' | **Open questions** | "We need to figure out...", unresolved debates |',
11125
- " | **People of interest** | Industry contacts, domain experts mentioned |",
11126
- " | **Companies of interest** | Competitors, vendors, partners discussed |",
11127
- " | **Strategic direction** | Business model changes, market positioning |",
11128
- " | **Product direction** | Roadmap changes, feature prioritization |",
11129
- "",
11130
- "3. Write the extraction to a markdown file with structured sections:",
11131
- " - Attendees",
11132
- " - Decisions Made (with category and confidence: Firm / Tentative / Needs confirmation)",
11133
- " - Requirements Identified (with category and priority estimate)",
11134
- " - Technology Discussions (with status: Decided / Leaning toward / Open)",
11135
- " - Action Items (with assignee and due date if stated)",
11136
- " - Open Questions",
11137
- " - People of Interest (with context and whether a profile exists)",
11138
- " - Companies of Interest (with type and context)",
11139
- " - Strategic / Product Direction",
11140
- "",
11141
- " Carry `meeting_type`, the resolved `meeting_kind`, and `areas`",
11142
- " into the extraction frontmatter so downstream phases can gate",
11143
- " behaviour without re-parsing the meeting note.",
11144
- "",
11145
- "4. **Apply type-specific rules.** Consult the **Meeting type handling**",
11146
- " table for the resolved kind and apply its phase-1 rules in",
11147
- " addition to the default extraction above. Examples:",
11148
- " - `standup`: skip requirement, ADR, and BDR extraction; focus on",
11149
- " action items and status.",
11150
- " - `brainstorm`: emphasize Open Questions and Future Features.",
11151
- " Only mark decisions as Firm when the transcript is unambiguous.",
11152
- " - `external`: default attendees outside the team into People of",
11153
- " Interest; default organizations mentioned into Companies of",
11154
- " Interest (signal threshold still applies); capture customer",
11155
- " pain points as candidate BR (not FR).",
11156
- "",
11157
- "5. **Create downstream phase issues** using `gh issue create`:",
11158
- " - Always create a `meeting:notes` issue (blocked on this extract issue)",
11159
- " - If requirements OR decisions/ADRs identified, create a `meeting:draft` issue",
11160
- " (blocked on the notes issue). For kind `standup`, skip the",
11161
- " `meeting:draft` issue \u2014 standup meetings almost never produce",
11162
- " formal drafts.",
11163
- " - Always create a `meeting:link` issue \u2014 blocked on the draft issue if one",
11164
- " was created, otherwise blocked on the notes issue",
11165
- "",
11166
- "6. Commit, push, and close the extract issue.",
11167
- "",
11168
- "---",
11169
- "",
11170
- "## Phase 2: Notes (`meeting:notes`)",
11171
- "",
11172
- "**Goal:** Transform the extraction into structured meeting notes.",
11173
- "",
11174
- "### Steps",
11175
- "",
11176
- "1. Read the extraction file referenced in the issue body (output of Phase 1).",
11177
- "2. Write structured meeting notes with these sections:",
11178
- " - Meeting metadata (title, date, attendees)",
11179
- " - Agenda / topics covered",
11180
- " - Key Discussion Points (organized by topic)",
11181
- " - Decisions (numbered, with rationale)",
11182
- " - Action Items (table: who, what, when)",
11183
- " - Open Questions",
11184
- " - Follow-up items",
11185
- "3. Commit, push, and close the notes issue.",
11186
- "",
11187
- "---",
11188
- "",
11189
- "## Phase 3: Draft (`meeting:draft`)",
11190
- "",
11191
- "**Goal:** Draft proposals for requirements, ADRs, and product/strategy updates.",
11192
- "",
11193
- "This phase only exists if the extraction identified requirements, architectural",
11194
- "decisions, or strategy changes. If this issue exists, execute it.",
11195
- "",
11196
- "### Steps",
11197
- "",
11198
- "1. Read the extraction file from Phase 1.",
11199
- "2. Check existing requirement registries and ADR registries for duplicates.",
11200
- "3. Draft requirement proposals with:",
11201
- " - Category (FR, BR, NFR, etc.)",
11202
- " - Summary (2-3 sentences)",
11203
- " - Draft acceptance criteria",
11204
- " - Related existing requirements",
11205
- "4. Draft ADR proposals for technology decisions with:",
11206
- " - Context and problem statement",
11207
- " - Options discussed",
11208
- " - Stated preferences or decisions",
11209
- " - Status: Proposed or Decided",
11210
- "5. Summarize product/strategy document updates needed.",
11211
- "6. Commit, push, and close the draft issue.",
11212
- "",
11213
- "---",
11214
- "",
11215
- "## Phase 4: Link (`meeting:link`)",
11216
- "",
11217
- "**Goal:** Create GitHub issues for follow-up work, cross-reference the",
11218
- "meeting into existing documentation, and complete bi-directional traceability.",
11219
- "",
11220
- "### Steps",
11221
- "",
11222
- "1. Read the drafts from Phase 3 (if they exist) and the extraction from Phase 1.",
11223
- " Re-read the extraction frontmatter for `meeting_kind` and `areas`,",
11224
- " then build the area-gate: the set of `docRoot` sub-folders that",
11225
- " are in scope for direct edits on this meeting. Apply the rules in",
11226
- " the **Areas filtering** section above.",
11227
- "2. Create requirement issues using `gh issue create` with appropriate labels.",
11228
- " Include a `## Traceability` section in each issue body linking back to",
11229
- " the source meeting and extraction file. Issue creation is **not**",
11230
- " gated by areas.",
11231
- "3. Create ADR issues if technology decisions need formal records.",
11232
- " Include a `## Traceability` section in each. Not gated by areas.",
11233
- "4. Create action item issues for tasks that are not document-related.",
11234
- " Include a `## Traceability` section in each. Not gated by areas.",
11235
- "5. Cross-reference the meeting in any existing documents that were",
11236
- " discussed **and that live under an in-scope `docRoot`**. For",
11237
- " discussed documents under an out-of-scope `docRoot`, open a",
11238
- " follow-up `type:docs` issue instead of editing the doc directly.",
11239
- "6. Apply direct product/strategy doc updates for items flagged as",
11240
- " **Firm** confidence. When the project declares `meetingAreas`,",
11241
- " gate these edits: only apply them when the target path lies",
11242
- " under an in-scope `docRoot`, and for Firm items targeting an",
11243
- " out-of-scope `docRoot` open a follow-up `type:docs` issue",
11244
- " noting the area and the target path. When the project has not",
11245
- " declared any `meetingAreas`, apply Firm updates unrestricted",
11246
- " (the degenerate case above). For the kind `planning`, also",
11247
- " update the active sprint-plan doc directly (when the",
11248
- " sprint-plan doc's area is in-scope, or always when no",
11249
- " `meetingAreas` are declared); for the kind `review`, mark",
11250
- " completed tasks in that same doc.",
11251
- "7. **Update the extraction file** with a `## Downstream Artifacts` section",
11252
- " listing every issue and document created from this meeting. Note",
11253
- " any items that were deferred to follow-up issues because of the",
11254
- " area gate.",
11255
- "8. **Update the meeting notes** with a `## Related Issues` section listing",
11256
- " all issues created from this meeting.",
11257
- "9. Comment on the parent extract issue with a summary linking to all",
11258
- " created artifacts.",
11259
- "10. Commit and push (if any file changes were made), then close the link issue.",
11260
- "",
11261
- "---",
11262
- "",
11263
- "## GitHub Integration",
11264
- "",
11265
- "- Use `gh` CLI for all GitHub operations",
11266
- "- Apply the appropriate `meeting:*` phase label to each phase issue",
11267
- "- Use `type:docs` for documentation-producing issues, `type:chore` for",
11268
- " maintenance/organizational tasks",
11269
- "- Use `status:` labels to track progress (`status:ready`, `status:in-progress`, `status:done`)",
11270
- "- Reference the source meeting transcript in all created issues",
11271
- "- Link phase issues with `Depends on: #N` to enforce ordering",
11272
- "",
11273
- "## When to Shorten the Pipeline",
11274
- "",
11275
- "- **Short meetings** (<30 min, <2000 words): combine extract + notes into one session",
11276
- "- **No requirements or decisions**: Phase 1 skips creating the `meeting:draft` issue",
11277
- "- **Only action items**: extract + notes + link (3 phase issues)"
11278
- ].join("\n")
11279
- };
10948
+ function buildMeetingAnalystSubAgent(tier) {
10949
+ return {
10950
+ name: "meeting-analyst",
10951
+ description: "Processes meeting transcripts through a 4-phase pipeline: extract, notes, draft, and link",
10952
+ model: tier,
10953
+ maxTurns: 80,
10954
+ platforms: { cursor: { exclude: true } },
10955
+ prompt: [
10956
+ "# Meeting Analyst Agent",
10957
+ "",
10958
+ "You process meeting transcripts through a structured 4-phase pipeline.",
10959
+ "Each phase runs as a **separate agent session**, triggered by its own",
10960
+ "GitHub issue with a `meeting:*` phase label. You handle exactly **one",
10961
+ "phase per session** \u2014 read the issue to determine which phase to execute.",
10962
+ "",
10963
+ "## Execution Model",
10964
+ "",
10965
+ "1. Each meeting produces up to 4 GitHub issues (one per phase)",
10966
+ "2. Each issue carries a `meeting:*` label identifying the phase",
10967
+ "3. You pick up one issue, execute that phase, commit/push, then close the issue",
10968
+ "4. Phase 1 (Extract) creates the downstream phase issues for phases 2-4",
10969
+ "5. Each downstream issue includes `Depends on: #N` linking to its predecessor",
10970
+ "",
10971
+ "## Design Principles",
10972
+ "",
10973
+ "1. **Extract, don't interpret.** Capture what was said and decided. Flag",
10974
+ " ambiguity as open items rather than resolving it.",
10975
+ "2. **Route to the right category.** Meeting content maps to requirements,",
10976
+ " ADRs, product docs, and business strategy. Each output goes to the",
10977
+ " correct location per the project's taxonomy.",
10978
+ "3. **Preserve provenance.** Every extracted item links back to the meeting",
10979
+ " source so reviewers can check context.",
10980
+ "4. **Create issues, not documents.** For requirements and ADRs, create",
10981
+ " GitHub issues that other agents or humans will pick up. Do not write",
10982
+ " final requirement documents yourself.",
10983
+ "5. **Bi-directional traceability.** Every document and issue created by",
10984
+ " this pipeline must link back to the meeting source, and the meeting",
10985
+ " source documents must link forward to everything created from them.",
10986
+ "6. **Respect meeting type and areas.** Read the `meeting_type` and",
10987
+ " `areas` values from the meeting frontmatter before starting Phase 1.",
10988
+ " Apply the type-specific rules from the **Meeting type handling**",
10989
+ " table (phases 1\u20132) and the area-filtered routing rules from the",
10990
+ " **Areas filtering** table (phase 4).",
10991
+ "",
10992
+ "---",
10993
+ "",
10994
+ "## Meeting type handling",
10995
+ "",
10996
+ "Meeting frontmatter is expected to carry a `meeting_type` field whose",
10997
+ "value is one of the project's concrete meeting-type `id`s (declared",
10998
+ "via `AgentConfigOptions.meetings.meetingTypes`). Each concrete `id`",
10999
+ "maps to one of six generic **meeting kinds** that drive type-specific",
11000
+ "extraction rules:",
11001
+ "",
11002
+ "| Kind | Primary outputs | Phase-1/2 rules |",
11003
+ "|------|-----------------|-----------------|",
11004
+ "| `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. |",
11005
+ "| `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. |",
11006
+ "| `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. |",
11007
+ "| `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. |",
11008
+ "| `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. |",
11009
+ "| `other` | General meeting extraction | Apply the default workflow with no type-specific overrides. |",
11010
+ "",
11011
+ "**How to resolve the kind:**",
11012
+ "",
11013
+ "1. Read `meeting_type` from the frontmatter.",
11014
+ "2. Look up the matching `id` in the project's **Recognized meeting",
11015
+ " types** table (rendered below when `meetingTypes` is declared).",
11016
+ "3. Use the `Kind` column value. If the table is absent, the `id` is",
11017
+ " unknown, or the `Kind` column is `\u2014`, fall back to `other`.",
11018
+ "4. Apply the rules in the row above **in addition to** the normal",
11019
+ " phase workflow \u2014 never as a replacement.",
11020
+ "",
11021
+ "If `meeting_type` is missing, invalid, or the declared `id` is not in",
11022
+ "the project's table, note it in the extraction's Open Questions and",
11023
+ "proceed with the default workflow (treat as `other`).",
11024
+ "",
11025
+ "## Areas filtering",
11026
+ "",
11027
+ "Meeting frontmatter may carry an `areas: [...]` list whose values",
11028
+ "match `id`s from the project's **Area \u2192 doc-root mapping** table",
11029
+ "(declared via `AgentConfigOptions.meetings.meetingAreas`). The list",
11030
+ "scopes phase-4 direct edits and cross-references to the doc-root",
11031
+ "sub-folders registered for those areas. A given area's effective",
11032
+ "path resolves as `<docsRoot>/<docRoot>` \u2014 `docsRoot` comes from",
11033
+ "`AgentPathsConfig.docsRoot`; `docRoot` is the sub-folder shown in",
11034
+ "the **Area \u2192 doc-root mapping** table.",
11035
+ "",
11036
+ "**Gating contract (phase 4 only):**",
11037
+ "",
11038
+ "- **Scoped in:** direct edits and cross-reference stubs under the",
11039
+ " `docRoot` of every `id` present in the meeting's `areas` list.",
11040
+ "- **Scoped out:** direct edits to any doc-root sub-folder that is",
11041
+ " declared in the project's area map but whose `id` is **not** in",
11042
+ " the meeting's `areas`. For those out-of-scope areas, create",
11043
+ " follow-up issues instead of editing the doc directly.",
11044
+ "- **Not gated:** issue creation (requirements, ADRs, profiles,",
11045
+ " research) is always in scope regardless of areas.",
11046
+ "",
11047
+ "**Resolution rules:**",
11048
+ "",
11049
+ "1. If the meeting's `areas` frontmatter is missing or empty **and**",
11050
+ " the project has declared a non-empty `meetingAreas` map, no",
11051
+ " doc-root sub-folder is gated in: direct edits to any declared",
11052
+ " `docRoot` sub-folder are out-of-scope and become follow-up issues",
11053
+ " per step 6. Only the default meetings root (`meetingsRoot`)",
11054
+ " remains editable.",
11055
+ "2. If `areas` lists an `id` that is not in the project's area map,",
11056
+ " note it in the extraction's Open Questions and treat the unknown",
11057
+ " `id` as absent. Do **not** invent a doc-root path for it.",
11058
+ "3. Out-of-scope direct edits become `type:docs` follow-up issues on",
11059
+ " phase 4 step 6, with the area noted in the issue body.",
11060
+ "",
11061
+ "When the project has **not** declared any `meetingAreas` at all,",
11062
+ "this section applies degenerately \u2014 no areas are gated, no",
11063
+ "follow-up issues are synthesized for missing areas, and phase-4",
11064
+ "direct edits follow the default workflow (step 6 edits any doc",
11065
+ "flagged as Firm, unrestricted by `docRoot`).",
11066
+ "",
11067
+ "---",
11068
+ "",
11069
+ ...PROJECT_CONTEXT_MAINTAINER_SECTION,
11070
+ "## Traceability",
11071
+ "",
11072
+ "All outputs must be bi-directionally linked so any artifact can be traced",
11073
+ "back to the meeting that produced it and forward to everything it spawned.",
11074
+ "",
11075
+ "### Backward links (created artifact \u2192 meeting source)",
11076
+ "",
11077
+ "Every GitHub issue and document created by this pipeline must include a",
11078
+ "`## Traceability` section with:",
11079
+ "",
11080
+ "```markdown",
11081
+ "## Traceability",
11082
+ "",
11083
+ "- **Source meeting:** <path to transcript or meeting notes>",
11084
+ "- **Extraction:** <path to extraction file>",
11085
+ "- **Phase issue:** #<N> (the phase issue that created this artifact)",
11086
+ "```",
11087
+ "",
11088
+ "### Forward links (meeting source \u2192 created artifacts)",
11089
+ "",
11090
+ "After Phase 4 (Link) creates all follow-up issues and documents:",
11091
+ "",
11092
+ "1. **Update the extraction file** with a `## Downstream Artifacts` section",
11093
+ " listing every issue and document created from this meeting:",
11094
+ "",
11095
+ " ```markdown",
11096
+ " ## Downstream Artifacts",
11097
+ "",
11098
+ " | Artifact | Type | Issue/Path |",
11099
+ " |----------|------|------------|",
11100
+ " | <title> | requirement / ADR / action-item / profile | #<N> or <path> |",
11101
+ " ```",
11102
+ "",
11103
+ "2. **Update the meeting notes** with a similar `## Related Issues` section",
11104
+ " listing all issues created from this meeting.",
11105
+ "",
11106
+ "3. **Comment on the extract issue** with a summary linking to all created",
11107
+ " artifacts.",
11108
+ "",
11109
+ "### Within-pipeline links",
11110
+ "",
11111
+ "- Phase issues link to predecessors via `Depends on: #N`",
11112
+ "- Phase issues reference the extraction file path in their body",
11113
+ "- Draft documents reference both the extraction and the meeting notes",
11114
+ "",
11115
+ "---",
11116
+ "",
11117
+ "## Phase 1: Extract (`meeting:extract`)",
11118
+ "",
11119
+ "**Goal:** Read the meeting transcript and categorize all substantive content.",
11120
+ "",
11121
+ "### Steps",
11122
+ "",
11123
+ "1. Read the transcript file specified in the issue body. Parse the",
11124
+ " meeting-note frontmatter first, capturing `meeting_type` and",
11125
+ " `areas`. Resolve `meeting_type` to a kind using the **Meeting type",
11126
+ " handling** table; note the resolved kind in the extraction",
11127
+ " frontmatter. If `meeting_type` is missing or not in the project's",
11128
+ " Recognized meeting types table, treat it as `other` and flag it",
11129
+ " in Open Questions.",
11130
+ "2. Identify and categorize content into these buckets:",
11131
+ "",
11132
+ " | Bucket | What to look for |",
11133
+ " |--------|-----------------|",
11134
+ ` | **Decisions** | "We decided...", "Let's go with...", explicit choices |`,
11135
+ ' | **Requirements** | Feature descriptions, acceptance criteria, "it should..." |',
11136
+ " | **Technology discussions** | Platform comparisons, architecture options, tool evaluations |",
11137
+ ' | **Action items** | "[Person] will...", "Next step is...", assigned tasks |',
11138
+ ' | **Open questions** | "We need to figure out...", unresolved debates |',
11139
+ " | **People of interest** | Industry contacts, domain experts mentioned |",
11140
+ " | **Companies of interest** | Competitors, vendors, partners discussed |",
11141
+ " | **Strategic direction** | Business model changes, market positioning |",
11142
+ " | **Product direction** | Roadmap changes, feature prioritization |",
11143
+ "",
11144
+ "3. Write the extraction to a markdown file with structured sections:",
11145
+ " - Attendees",
11146
+ " - Decisions Made (with category and confidence: Firm / Tentative / Needs confirmation)",
11147
+ " - Requirements Identified (with category and priority estimate)",
11148
+ " - Technology Discussions (with status: Decided / Leaning toward / Open)",
11149
+ " - Action Items (with assignee and due date if stated)",
11150
+ " - Open Questions",
11151
+ " - People of Interest (with context and whether a profile exists)",
11152
+ " - Companies of Interest (with type and context)",
11153
+ " - Strategic / Product Direction",
11154
+ "",
11155
+ " Carry `meeting_type`, the resolved `meeting_kind`, and `areas`",
11156
+ " into the extraction frontmatter so downstream phases can gate",
11157
+ " behaviour without re-parsing the meeting note.",
11158
+ "",
11159
+ "4. **Apply type-specific rules.** Consult the **Meeting type handling**",
11160
+ " table for the resolved kind and apply its phase-1 rules in",
11161
+ " addition to the default extraction above. Examples:",
11162
+ " - `standup`: skip requirement, ADR, and BDR extraction; focus on",
11163
+ " action items and status.",
11164
+ " - `brainstorm`: emphasize Open Questions and Future Features.",
11165
+ " Only mark decisions as Firm when the transcript is unambiguous.",
11166
+ " - `external`: default attendees outside the team into People of",
11167
+ " Interest; default organizations mentioned into Companies of",
11168
+ " Interest (signal threshold still applies); capture customer",
11169
+ " pain points as candidate BR (not FR).",
11170
+ "",
11171
+ "5. **Create downstream phase issues** using `gh issue create`:",
11172
+ " - Always create a `meeting:notes` issue (blocked on this extract issue)",
11173
+ " - If requirements OR decisions/ADRs identified, create a `meeting:draft` issue",
11174
+ " (blocked on the notes issue). For kind `standup`, skip the",
11175
+ " `meeting:draft` issue \u2014 standup meetings almost never produce",
11176
+ " formal drafts.",
11177
+ " - Always create a `meeting:link` issue \u2014 blocked on the draft issue if one",
11178
+ " was created, otherwise blocked on the notes issue",
11179
+ "",
11180
+ "6. Commit, push, and close the extract issue.",
11181
+ "",
11182
+ "---",
11183
+ "",
11184
+ "## Phase 2: Notes (`meeting:notes`)",
11185
+ "",
11186
+ "**Goal:** Transform the extraction into structured meeting notes.",
11187
+ "",
11188
+ "### Steps",
11189
+ "",
11190
+ "1. Read the extraction file referenced in the issue body (output of Phase 1).",
11191
+ "2. Write structured meeting notes with these sections:",
11192
+ " - Meeting metadata (title, date, attendees)",
11193
+ " - Agenda / topics covered",
11194
+ " - Key Discussion Points (organized by topic)",
11195
+ " - Decisions (numbered, with rationale)",
11196
+ " - Action Items (table: who, what, when)",
11197
+ " - Open Questions",
11198
+ " - Follow-up items",
11199
+ "3. Commit, push, and close the notes issue.",
11200
+ "",
11201
+ "---",
11202
+ "",
11203
+ "## Phase 3: Draft (`meeting:draft`)",
11204
+ "",
11205
+ "**Goal:** Draft proposals for requirements, ADRs, and product/strategy updates.",
11206
+ "",
11207
+ "This phase only exists if the extraction identified requirements, architectural",
11208
+ "decisions, or strategy changes. If this issue exists, execute it.",
11209
+ "",
11210
+ "### Steps",
11211
+ "",
11212
+ "1. Read the extraction file from Phase 1.",
11213
+ "2. Check existing requirement registries and ADR registries for duplicates.",
11214
+ "3. Draft requirement proposals with:",
11215
+ " - Category (FR, BR, NFR, etc.)",
11216
+ " - Summary (2-3 sentences)",
11217
+ " - Draft acceptance criteria",
11218
+ " - Related existing requirements",
11219
+ "4. Draft ADR proposals for technology decisions with:",
11220
+ " - Context and problem statement",
11221
+ " - Options discussed",
11222
+ " - Stated preferences or decisions",
11223
+ " - Status: Proposed or Decided",
11224
+ "5. Summarize product/strategy document updates needed.",
11225
+ "6. Commit, push, and close the draft issue.",
11226
+ "",
11227
+ "---",
11228
+ "",
11229
+ "## Phase 4: Link (`meeting:link`)",
11230
+ "",
11231
+ "**Goal:** Create GitHub issues for follow-up work, cross-reference the",
11232
+ "meeting into existing documentation, and complete bi-directional traceability.",
11233
+ "",
11234
+ "### Steps",
11235
+ "",
11236
+ "1. Read the drafts from Phase 3 (if they exist) and the extraction from Phase 1.",
11237
+ " Re-read the extraction frontmatter for `meeting_kind` and `areas`,",
11238
+ " then build the area-gate: the set of `docRoot` sub-folders that",
11239
+ " are in scope for direct edits on this meeting. Apply the rules in",
11240
+ " the **Areas filtering** section above.",
11241
+ "2. Create requirement issues using `gh issue create` with appropriate labels.",
11242
+ " Include a `## Traceability` section in each issue body linking back to",
11243
+ " the source meeting and extraction file. Issue creation is **not**",
11244
+ " gated by areas.",
11245
+ "3. Create ADR issues if technology decisions need formal records.",
11246
+ " Include a `## Traceability` section in each. Not gated by areas.",
11247
+ "4. Create action item issues for tasks that are not document-related.",
11248
+ " Include a `## Traceability` section in each. Not gated by areas.",
11249
+ "5. Cross-reference the meeting in any existing documents that were",
11250
+ " discussed **and that live under an in-scope `docRoot`**. For",
11251
+ " discussed documents under an out-of-scope `docRoot`, open a",
11252
+ " follow-up `type:docs` issue instead of editing the doc directly.",
11253
+ "6. Apply direct product/strategy doc updates for items flagged as",
11254
+ " **Firm** confidence. When the project declares `meetingAreas`,",
11255
+ " gate these edits: only apply them when the target path lies",
11256
+ " under an in-scope `docRoot`, and for Firm items targeting an",
11257
+ " out-of-scope `docRoot` open a follow-up `type:docs` issue",
11258
+ " noting the area and the target path. When the project has not",
11259
+ " declared any `meetingAreas`, apply Firm updates unrestricted",
11260
+ " (the degenerate case above). For the kind `planning`, also",
11261
+ " update the active sprint-plan doc directly (when the",
11262
+ " sprint-plan doc's area is in-scope, or always when no",
11263
+ " `meetingAreas` are declared); for the kind `review`, mark",
11264
+ " completed tasks in that same doc.",
11265
+ "7. **Update the extraction file** with a `## Downstream Artifacts` section",
11266
+ " listing every issue and document created from this meeting. Note",
11267
+ " any items that were deferred to follow-up issues because of the",
11268
+ " area gate.",
11269
+ "8. **Update the meeting notes** with a `## Related Issues` section listing",
11270
+ " all issues created from this meeting.",
11271
+ "9. Comment on the parent extract issue with a summary linking to all",
11272
+ " created artifacts.",
11273
+ "10. Commit and push (if any file changes were made), then close the link issue.",
11274
+ "",
11275
+ "---",
11276
+ "",
11277
+ "## GitHub Integration",
11278
+ "",
11279
+ "- Use `gh` CLI for all GitHub operations",
11280
+ "- Apply the appropriate `meeting:*` phase label to each phase issue",
11281
+ "- Use `type:docs` for documentation-producing issues, `type:chore` for",
11282
+ " maintenance/organizational tasks",
11283
+ "- Use `status:` labels to track progress (`status:ready`, `status:in-progress`, `status:done`)",
11284
+ "- Reference the source meeting transcript in all created issues",
11285
+ "- Link phase issues with `Depends on: #N` to enforce ordering",
11286
+ "",
11287
+ "## When to Shorten the Pipeline",
11288
+ "",
11289
+ "- **Short meetings** (<30 min, <2000 words): combine extract + notes into one session",
11290
+ "- **No requirements or decisions**: Phase 1 skips creating the `meeting:draft` issue",
11291
+ "- **Only action items**: extract + notes + link (3 phase issues)"
11292
+ ].join("\n")
11293
+ };
11294
+ }
11280
11295
  var processMeetingSkill = {
11281
11296
  name: "process-meeting",
11282
11297
  description: "Process a meeting transcript through the 4-phase meeting analysis pipeline",
@@ -11320,64 +11335,67 @@ var processMeetingSkill = {
11320
11335
  " to pick up (notes, draft, link)"
11321
11336
  ].join("\n")
11322
11337
  };
11323
- var meetingAnalysisBundle = {
11324
- name: "meeting-analysis",
11325
- description: "Meeting transcript processing workflow with 4-phase pipeline (extract, notes, draft, link)",
11326
- appliesWhen: () => true,
11327
- rules: [
11328
- {
11329
- name: "meeting-processing-workflow",
11330
- description: "Describes the 4-phase meeting processing pipeline, extraction taxonomy, and labeling conventions",
11331
- scope: AGENT_RULE_SCOPE.ALWAYS,
11332
- content: [
11333
- "# Meeting Processing Workflow",
11334
- "",
11335
- "Use `/process-meeting <path>` to process a meeting transcript through a",
11336
- "4-phase pipeline (extract \u2192 notes \u2192 draft \u2192 link). Each phase runs as a",
11337
- "separate agent session tracked by a GitHub issue with a `meeting:*` label.",
11338
- "See the `meeting-analyst` agent definition for full workflow details.",
11339
- "",
11340
- "Meeting notes may declare a `meeting_type` (one of the project's",
11341
- "recognized types) and an `areas: [...]` list. The `meeting_type`",
11342
- "resolves to a generic kind \u2014 `planning` / `review` / `brainstorm` /",
11343
- "`standup` / `external` / `other` \u2014 that drives type-specific",
11344
- "extraction rules in phases 1\u20132. The `areas` list scopes phase-4",
11345
- "direct edits to the doc-root sub-folders declared in the project's",
11346
- "**Area \u2192 doc-root mapping** table. When both fields are absent",
11347
- "the pipeline falls back to the default workflow (kind `other`,",
11348
- "no area gating)."
11349
- ].join("\n"),
11350
- platforms: {
11351
- cursor: { exclude: true }
11338
+ function buildMeetingAnalysisBundle(tier = AGENT_MODEL.BALANCED) {
11339
+ return {
11340
+ name: "meeting-analysis",
11341
+ description: "Meeting transcript processing workflow with 4-phase pipeline (extract, notes, draft, link)",
11342
+ appliesWhen: () => true,
11343
+ rules: [
11344
+ {
11345
+ name: "meeting-processing-workflow",
11346
+ description: "Describes the 4-phase meeting processing pipeline, extraction taxonomy, and labeling conventions",
11347
+ scope: AGENT_RULE_SCOPE.ALWAYS,
11348
+ content: [
11349
+ "# Meeting Processing Workflow",
11350
+ "",
11351
+ "Use `/process-meeting <path>` to process a meeting transcript through a",
11352
+ "4-phase pipeline (extract \u2192 notes \u2192 draft \u2192 link). Each phase runs as a",
11353
+ "separate agent session tracked by a GitHub issue with a `meeting:*` label.",
11354
+ "See the `meeting-analyst` agent definition for full workflow details.",
11355
+ "",
11356
+ "Meeting notes may declare a `meeting_type` (one of the project's",
11357
+ "recognized types) and an `areas: [...]` list. The `meeting_type`",
11358
+ "resolves to a generic kind \u2014 `planning` / `review` / `brainstorm` /",
11359
+ "`standup` / `external` / `other` \u2014 that drives type-specific",
11360
+ "extraction rules in phases 1\u20132. The `areas` list scopes phase-4",
11361
+ "direct edits to the doc-root sub-folders declared in the project's",
11362
+ "**Area \u2192 doc-root mapping** table. When both fields are absent",
11363
+ "the pipeline falls back to the default workflow (kind `other`,",
11364
+ "no area gating)."
11365
+ ].join("\n"),
11366
+ platforms: {
11367
+ cursor: { exclude: true }
11368
+ },
11369
+ tags: ["workflow"]
11370
+ }
11371
+ ],
11372
+ skills: [processMeetingSkill],
11373
+ subAgents: [buildMeetingAnalystSubAgent(tier)],
11374
+ labels: [
11375
+ {
11376
+ name: "meeting:extract",
11377
+ color: "C5DEF5",
11378
+ description: "Phase 1: raw extraction from a meeting transcript"
11352
11379
  },
11353
- tags: ["workflow"]
11354
- }
11355
- ],
11356
- skills: [processMeetingSkill],
11357
- subAgents: [meetingAnalystSubAgent],
11358
- labels: [
11359
- {
11360
- name: "meeting:extract",
11361
- color: "C5DEF5",
11362
- description: "Phase 1: raw extraction from a meeting transcript"
11363
- },
11364
- {
11365
- name: "meeting:notes",
11366
- color: "BFDADC",
11367
- description: "Phase 2: curated notes derived from an extraction"
11368
- },
11369
- {
11370
- name: "meeting:draft",
11371
- color: "D4C5F9",
11372
- description: "Phase 3: draft follow-up issues proposed from notes"
11373
- },
11374
- {
11375
- name: "meeting:link",
11376
- color: "FEF2C0",
11377
- description: "Phase 4: linking/reconciling drafted issues with existing work"
11378
- }
11379
- ]
11380
- };
11380
+ {
11381
+ name: "meeting:notes",
11382
+ color: "BFDADC",
11383
+ description: "Phase 2: curated notes derived from an extraction"
11384
+ },
11385
+ {
11386
+ name: "meeting:draft",
11387
+ color: "D4C5F9",
11388
+ description: "Phase 3: draft follow-up issues proposed from notes"
11389
+ },
11390
+ {
11391
+ name: "meeting:link",
11392
+ color: "FEF2C0",
11393
+ description: "Phase 4: linking/reconciling drafted issues with existing work"
11394
+ }
11395
+ ]
11396
+ };
11397
+ }
11398
+ var meetingAnalysisBundle = buildMeetingAnalysisBundle();
11381
11399
 
11382
11400
  // src/agent/bundles/run-ratio.ts
11383
11401
  var DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO = 4;
@@ -14790,6 +14808,69 @@ function resolveOrchestratorAssets(tierConfig, scopeGateConfig, runRatioConfig,
14790
14808
  )
14791
14809
  };
14792
14810
  }
14811
+ var orchestrateCommand = {
14812
+ name: "orchestrate",
14813
+ description: "Run one full orchestrator cycle: triage, queue scan, delegate to issue-worker.",
14814
+ content: [
14815
+ "# Orchestrate",
14816
+ "",
14817
+ "Invoke the `orchestrator` sub-agent and run **one full end-to-end",
14818
+ "cycle**: triage / unblock \u2192 maintenance \u2192 queue scan \u2192 delegate the",
14819
+ "picked issue to the `issue-worker` sub-agent \u2192 cleanup.",
14820
+ "",
14821
+ "Follow the contract in `.claude/agents/orchestrator.md`. Do **not**",
14822
+ "implement code, create branches, push commits, or merge PRs \u2014 those",
14823
+ "are the worker's and `pr-reviewer`'s jobs respectively.",
14824
+ "",
14825
+ "Run as a depth-0 (top-level) session so the orchestrator can spawn",
14826
+ "the `issue-worker` sub-agent at depth-1 \u2014 Claude Code forbids nested",
14827
+ "sub-agent dispatch.",
14828
+ ""
14829
+ ].join("\n")
14830
+ };
14831
+ var checkBlockedCommand = {
14832
+ name: "check-blocked",
14833
+ description: "Run .claude/procedures/check-blocked.sh and summarise the unblock candidates.",
14834
+ content: [
14835
+ "# Check Blocked",
14836
+ "",
14837
+ "Run the bundled triage helper and report what it found:",
14838
+ "",
14839
+ "```bash",
14840
+ 'bash .claude/procedures/check-blocked.sh "$@"',
14841
+ "```",
14842
+ "",
14843
+ "Pass any extra arguments through verbatim. The script walks every",
14844
+ "`status:blocked` issue, re-checks each `Depends on:` reference, and",
14845
+ "prints `UNBLOCKED` / `STILL_BLOCKED` lines for issues that should",
14846
+ "transition to `status:ready`.",
14847
+ "",
14848
+ "Summarise the output (counts, the first few candidates) \u2014 do **not**",
14849
+ "transition labels yourself; that is the orchestrator's responsibility.",
14850
+ ""
14851
+ ].join("\n")
14852
+ };
14853
+ var scanCommand = {
14854
+ name: "scan",
14855
+ description: "Run the orchestrator queue scan only and report the next ready issue without dispatching.",
14856
+ content: [
14857
+ "# Scan",
14858
+ "",
14859
+ "Run the orchestrator's **queue scan only** (Phase E of the contract",
14860
+ "in `.claude/agents/orchestrator.md`) and print the next ready issue,",
14861
+ "the funnel-tier sort that put it on top, and the scope-gate result.",
14862
+ "",
14863
+ "Do **not** claim the issue, create a branch, or delegate to",
14864
+ "`issue-worker`. This command exists for proactive review of what",
14865
+ "the next `/orchestrate` invocation would pick up.",
14866
+ "",
14867
+ "Walk each `priority:*` bucket in turn (capped at 50 per bucket),",
14868
+ "filter `Depends on:` references, and short-circuit on the first",
14869
+ "bucket whose survivors clear the filter. Report the top candidate",
14870
+ "and the number of survivors per bucket.",
14871
+ ""
14872
+ ].join("\n")
14873
+ };
14793
14874
  var orchestratorBundle = {
14794
14875
  name: "orchestrator",
14795
14876
  description: "Pipeline orchestrator agent for issue triage, PR review, and queue management",
@@ -14816,6 +14897,7 @@ var orchestratorBundle = {
14816
14897
  ],
14817
14898
  subAgents: [orchestratorSubAgent, issueWorkerSubAgent],
14818
14899
  procedures: [checkBlockedProcedure, unblockDependentsProcedure],
14900
+ commands: [orchestrateCommand, checkBlockedCommand, scanCommand],
14819
14901
  claudePermissions: {
14820
14902
  allow: [
14821
14903
  // Allow executing the check-blocked.sh procedure
@@ -14825,11 +14907,11 @@ var orchestratorBundle = {
14825
14907
  };
14826
14908
 
14827
14909
  // src/agent/bundles/people-profile.ts
14828
- function buildPeopleProfileAnalystSubAgent(paths, issueDefaults) {
14910
+ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier) {
14829
14911
  return {
14830
14912
  name: "people-profile-analyst",
14831
14913
  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.",
14832
- model: AGENT_MODEL.POWERFUL,
14914
+ model: tier,
14833
14915
  maxTurns: 80,
14834
14916
  platforms: { cursor: { exclude: true } },
14835
14917
  prompt: [
@@ -15659,7 +15741,7 @@ function buildRefreshPersonSkill(paths, issueDefaults) {
15659
15741
  ].join("\n")
15660
15742
  };
15661
15743
  }
15662
- function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
15744
+ function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
15663
15745
  return {
15664
15746
  name: "people-profile",
15665
15747
  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.",
@@ -15707,7 +15789,7 @@ function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = D
15707
15789
  buildProfilePersonSkill(paths, issueDefaults),
15708
15790
  buildRefreshPersonSkill(paths, issueDefaults)
15709
15791
  ],
15710
- subAgents: [buildPeopleProfileAnalystSubAgent(paths, issueDefaults)],
15792
+ subAgents: [buildPeopleProfileAnalystSubAgent(paths, issueDefaults, tier)],
15711
15793
  labels: [
15712
15794
  {
15713
15795
  name: "type:people-profile",
@@ -15775,6 +15857,7 @@ var PnpmWorkspace = class _PnpmWorkspace extends import_projen.Component {
15775
15857
  this.minimumReleaseAgeExclude = options.minimumReleaseAgeExclude ? ["@codedrifters/*", ...options.minimumReleaseAgeExclude] : ["@codedrifters/*"];
15776
15858
  this.onlyBuiltDependencies = options.onlyBuiltDependencies ? options.onlyBuiltDependencies : [];
15777
15859
  this.ignoredBuiltDependencies = options.ignoredBuiltDependencies ? options.ignoredBuiltDependencies : [];
15860
+ this.allowBuilds = options.allowBuilds ?? {};
15778
15861
  this.subprojects = options.subprojects ?? [];
15779
15862
  this.defaultCatalog = options.defaultCatalog;
15780
15863
  this.namedCatalogs = options.namedCatalogs;
@@ -15798,11 +15881,35 @@ var PnpmWorkspace = class _PnpmWorkspace extends import_projen.Component {
15798
15881
  if (this.minimumReleaseAgeExclude.length > 0) {
15799
15882
  pnpmConfig.minimumReleaseAgeExclude = this.minimumReleaseAgeExclude;
15800
15883
  }
15801
- if (this.onlyBuiltDependencies.length > 0) {
15802
- pnpmConfig.onlyBuiltDependencies = this.onlyBuiltDependencies;
15884
+ const mergedAllowBuilds = {};
15885
+ for (const pkg of this.onlyBuiltDependencies) {
15886
+ mergedAllowBuilds[pkg] = true;
15887
+ }
15888
+ for (const pkg of this.ignoredBuiltDependencies) {
15889
+ mergedAllowBuilds[pkg] = false;
15890
+ }
15891
+ for (const [pkg, allowed] of Object.entries(this.allowBuilds)) {
15892
+ mergedAllowBuilds[pkg] = allowed;
15893
+ }
15894
+ const allowList = [];
15895
+ const denyList = [];
15896
+ for (const [pkg, allowed] of Object.entries(mergedAllowBuilds)) {
15897
+ if (allowed) {
15898
+ allowList.push(pkg);
15899
+ } else {
15900
+ denyList.push(pkg);
15901
+ }
15902
+ }
15903
+ allowList.sort();
15904
+ denyList.sort();
15905
+ if (allowList.length > 0) {
15906
+ pnpmConfig.onlyBuiltDependencies = allowList;
15907
+ }
15908
+ if (denyList.length > 0) {
15909
+ pnpmConfig.ignoredBuiltDependencies = denyList;
15803
15910
  }
15804
- if (this.ignoredBuiltDependencies.length > 0) {
15805
- pnpmConfig.ignoreBuiltDependencies = this.ignoredBuiltDependencies;
15911
+ if (Object.keys(mergedAllowBuilds).length > 0) {
15912
+ pnpmConfig.allowBuilds = mergedAllowBuilds;
15806
15913
  }
15807
15914
  if (this.defaultCatalog && Object.keys(this.defaultCatalog).length > 0) {
15808
15915
  pnpmConfig.catalog = this.defaultCatalog;
@@ -17257,7 +17364,19 @@ var prReviewBundle = {
17257
17364
  "to a PR's branch \u2014 it only reviews, decides, and orchestrates merge",
17258
17365
  "or comment. In loop mode, a failed review for one PR never stops",
17259
17366
  "the loop; the reviewer comments and moves on. See the `pr-reviewer`",
17260
- "agent definition for the full phase-by-phase contract.",
17367
+ "agent definition for the full phase-by-phase contract."
17368
+ ].join("\n"),
17369
+ platforms: {
17370
+ cursor: { exclude: true }
17371
+ },
17372
+ tags: ["workflow"]
17373
+ },
17374
+ {
17375
+ name: "pr-review-feedback-protocol",
17376
+ 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.",
17377
+ scope: AGENT_RULE_SCOPE.ALWAYS,
17378
+ content: [
17379
+ "# PR Review Feedback Protocol",
17261
17380
  "",
17262
17381
  "## Human-in-the-Loop Feedback Protocol",
17263
17382
  "",
@@ -24041,11 +24160,11 @@ var slackBundle = {
24041
24160
  };
24042
24161
 
24043
24162
  // src/agent/bundles/software-profile.ts
24044
- function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults) {
24163
+ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier) {
24045
24164
  return {
24046
24165
  name: "software-profile-analyst",
24047
24166
  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.",
24048
- model: AGENT_MODEL.POWERFUL,
24167
+ model: tier,
24049
24168
  maxTurns: 80,
24050
24169
  platforms: { cursor: { exclude: true } },
24051
24170
  prompt: [
@@ -24980,7 +25099,7 @@ function buildMapSoftwareSkill(paths, issueDefaults) {
24980
25099
  ].join("\n")
24981
25100
  };
24982
25101
  }
24983
- function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
25102
+ function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, tier = AGENT_MODEL.BALANCED) {
24984
25103
  return {
24985
25104
  name: "software-profile",
24986
25105
  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.",
@@ -25037,7 +25156,9 @@ function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults =
25037
25156
  buildProfileSoftwareSkill(paths, issueDefaults),
25038
25157
  buildMapSoftwareSkill(paths, issueDefaults)
25039
25158
  ],
25040
- subAgents: [buildSoftwareProfileAnalystSubAgent(paths, issueDefaults)],
25159
+ subAgents: [
25160
+ buildSoftwareProfileAnalystSubAgent(paths, issueDefaults, tier)
25161
+ ],
25041
25162
  labels: [
25042
25163
  {
25043
25164
  name: "type:software-profile",
@@ -27083,11 +27204,11 @@ var VERSION = {
27083
27204
  * Version of `pnpm/action-setup` to use in GitHub workflows.
27084
27205
  * Tracks the version projen currently emits (see node_modules/projen/lib/javascript/node-project.js).
27085
27206
  */
27086
- PNPM_ACTION_SETUP_VERSION: "v5",
27207
+ PNPM_ACTION_SETUP_VERSION: "v6.0.5",
27087
27208
  /**
27088
27209
  * Version of PNPM to use in workflows at github actions.
27089
27210
  */
27090
- PNPM_VERSION: "10.33.3",
27211
+ PNPM_VERSION: "11.0.8",
27091
27212
  /**
27092
27213
  * Version of Projen to use.
27093
27214
  */
@@ -27271,6 +27392,211 @@ var vitestBundle = {
27271
27392
  }
27272
27393
  };
27273
27394
 
27395
+ // src/agent/bundles/agent-registry.ts
27396
+ var AGENT_REGISTRY_ENTRIES = [
27397
+ {
27398
+ bundle: "agenda",
27399
+ skill: "/draft-agenda",
27400
+ agent: "agenda-analyst",
27401
+ resolveOutputPath: (p) => `${p.meetingsRoot}/`,
27402
+ purpose: "Pre-meeting agenda authoring (2-phase: draft, finalize). Reuses the project's meeting-type taxonomy.",
27403
+ workflowRuleName: "meeting-agenda-workflow"
27404
+ },
27405
+ {
27406
+ bundle: "bcm-writer",
27407
+ skill: "/write-bcm",
27408
+ agent: "bcm-writer",
27409
+ resolveOutputPath: (p) => `${p.bcmRoot}/`,
27410
+ purpose: "BCM capability-model documents (4-phase: outline, scaffold, context, connect). BIZBOK-aligned.",
27411
+ workflowRuleName: "bcm-writer-workflow"
27412
+ },
27413
+ {
27414
+ bundle: "business-models",
27415
+ skill: "/scan-business-models",
27416
+ agent: "business-models-analyst",
27417
+ resolveOutputPath: (p) => `${p.docsRoot}/industry-research/`,
27418
+ purpose: "Osterwalder business-model canvases per industry segment (3-phase: scan, canvas, complete).",
27419
+ workflowRuleName: "business-models-workflow"
27420
+ },
27421
+ {
27422
+ bundle: "company-profile",
27423
+ skill: "/profile-company",
27424
+ agent: "company-profile-analyst",
27425
+ resolveOutputPath: (p) => `${p.companiesRoot}/`,
27426
+ purpose: "Company profiles, notes, and segment competitive analyses (up to 6 phases incl. refresh).",
27427
+ workflowRuleName: "company-profile-workflow"
27428
+ },
27429
+ {
27430
+ bundle: "customer-profile",
27431
+ skill: "/discover-customers",
27432
+ agent: "customer-profile-analyst",
27433
+ resolveOutputPath: (p) => `${p.profilesRoot}/customers/`,
27434
+ purpose: "Customer-archetype discovery, profiles, and competitor feature-mapping (3-phase).",
27435
+ workflowRuleName: "customer-profile-workflow"
27436
+ },
27437
+ {
27438
+ bundle: "docs-sync",
27439
+ skill: "/docs-sync-pr",
27440
+ agent: "docs-sync",
27441
+ resolveOutputPath: (p) => `${p.docsRoot}/`,
27442
+ purpose: "Pre-PR drift detection and mechanical doc fixes (2-phase: scan, fix). Skeleton release.",
27443
+ workflowRuleName: "docs-sync-workflow"
27444
+ },
27445
+ {
27446
+ bundle: "industry-discovery",
27447
+ skill: "/discover-industries",
27448
+ agent: "industry-discovery-analyst",
27449
+ resolveOutputPath: (p) => `${p.industriesRoot}/`,
27450
+ purpose: "Industry-vertical discovery, fit-evaluation, and research planning (3-phase).",
27451
+ workflowRuleName: "industry-discovery-workflow"
27452
+ },
27453
+ {
27454
+ bundle: "maintenance-audit",
27455
+ skill: "/audit-docs",
27456
+ agent: "maintenance-audit",
27457
+ resolveOutputPath: (p) => `${p.docsRoot}/`,
27458
+ purpose: "Doc-registry audits with idempotent fixes (3-phase: scan, fix, verify). No new content.",
27459
+ workflowRuleName: "maintenance-audit-workflow"
27460
+ },
27461
+ {
27462
+ bundle: "meeting-analysis",
27463
+ skill: "/process-meeting",
27464
+ agent: "meeting-analyst",
27465
+ resolveOutputPath: (p) => `${p.meetingsRoot}/`,
27466
+ purpose: "Post-meeting transcript processing (4-phase: extract, notes, draft, link).",
27467
+ workflowRuleName: "meeting-processing-workflow"
27468
+ },
27469
+ {
27470
+ bundle: "people-profile",
27471
+ skill: "/profile-person",
27472
+ agent: "people-profile-analyst",
27473
+ resolveOutputPath: (p) => `${p.peopleRoot}/`,
27474
+ purpose: "Person profiles only (up to 4 phases incl. refresh). Hands off to company/software bundles.",
27475
+ workflowRuleName: "people-profile-workflow"
27476
+ },
27477
+ {
27478
+ bundle: "pr-review",
27479
+ skill: "/review-pr",
27480
+ agent: "pr-reviewer",
27481
+ resolveOutputPath: () => "",
27482
+ purpose: "PR review, auto-merge gating, and human-in-the-loop feedback orchestration.",
27483
+ workflowRuleName: "pr-review-workflow"
27484
+ },
27485
+ {
27486
+ bundle: "regulatory-research",
27487
+ skill: "/scan-regulatory-landscape",
27488
+ agent: "regulatory-research-analyst",
27489
+ resolveOutputPath: (p) => `${p.docsRoot}/regulations/`,
27490
+ purpose: "Regulation research, version pages, and impact analysis (3-phase). Documents, never interprets.",
27491
+ workflowRuleName: "regulatory-research-workflow"
27492
+ },
27493
+ {
27494
+ bundle: "requirements-analyst",
27495
+ skill: "/scan-requirements",
27496
+ agent: "requirements-analyst",
27497
+ resolveOutputPath: (p) => `${p.researchRequirementsRoot}/`,
27498
+ purpose: "Requirements gap discovery + draft proposals (2-phase: scan, draft-trace). Hands off to writer.",
27499
+ workflowRuleName: "requirements-analyst-workflow"
27500
+ },
27501
+ {
27502
+ bundle: "requirements-reviewer",
27503
+ skill: "/review-requirements",
27504
+ agent: "requirements-reviewer",
27505
+ resolveOutputPath: (p) => `${p.requirementsRoot}/`,
27506
+ purpose: "Requirements audit (12 checks) and narrow-edit deprecation. Never authors new requirement docs.",
27507
+ workflowRuleName: "requirements-reviewer-workflow"
27508
+ },
27509
+ {
27510
+ bundle: "requirements-writer",
27511
+ skill: "/write-requirement",
27512
+ agent: "requirements-writer",
27513
+ resolveOutputPath: (p) => `${p.requirementsRoot}/`,
27514
+ purpose: "Formal requirement document authoring across the 11-category taxonomy + four-tier classification.",
27515
+ workflowRuleName: "requirements-writer-workflow"
27516
+ },
27517
+ {
27518
+ bundle: "research-pipeline",
27519
+ skill: "/research",
27520
+ agent: "research-analyst",
27521
+ resolveOutputPath: (p) => `${p.researchRoot}/`,
27522
+ purpose: "Generic research micro-tasks (3-phase: scope, slice, verify). Notes-only output.",
27523
+ workflowRuleName: "research-pipeline-workflow"
27524
+ },
27525
+ {
27526
+ bundle: "software-profile",
27527
+ skill: "/profile-software",
27528
+ agent: "software-profile-analyst",
27529
+ resolveOutputPath: (p) => `${p.softwareRoot}/`,
27530
+ purpose: "Software profiles, shared feature matrix, and BCM-tree capability mapping (up to 5 phases).",
27531
+ workflowRuleName: "software-profile-workflow"
27532
+ },
27533
+ {
27534
+ bundle: "standards-research",
27535
+ skill: "/scope-standards-research",
27536
+ agent: "standards-research-analyst",
27537
+ resolveOutputPath: (p) => `${p.docsRoot}/standards/`,
27538
+ purpose: "Interoperability standards research (5-phase: scope, research, compare, extension, organizations).",
27539
+ workflowRuleName: "standards-research-workflow"
27540
+ }
27541
+ ];
27542
+ var SUPPRESSED_WORKFLOW_RULE_NAMES = AGENT_REGISTRY_ENTRIES.map((e) => e.workflowRuleName);
27543
+ function isSuppressedWorkflowRule(name) {
27544
+ return SUPPRESSED_WORKFLOW_RULE_NAMES.includes(name);
27545
+ }
27546
+ function bundleNameForWorkflowRule(ruleName) {
27547
+ const entry = AGENT_REGISTRY_ENTRIES.find(
27548
+ (e) => e.workflowRuleName === ruleName
27549
+ );
27550
+ return entry?.bundle;
27551
+ }
27552
+ function buildAgentRegistryRule(bundles, paths) {
27553
+ const activeNames = new Set(bundles.map((b) => b.name));
27554
+ const rows = AGENT_REGISTRY_ENTRIES.filter(
27555
+ (e) => activeNames.has(e.bundle)
27556
+ ).slice();
27557
+ if (rows.length === 0) {
27558
+ return void 0;
27559
+ }
27560
+ rows.sort((a, b) => a.bundle.localeCompare(b.bundle));
27561
+ const lines = [
27562
+ "# Agent Registry",
27563
+ "",
27564
+ "Each row below is the routing summary for one phased-agent",
27565
+ "bundle: the user-invocable skill, the sub-agent that handles",
27566
+ "the work, the output path the agent writes to, and a one-line",
27567
+ "purpose. Use the table to answer *which agent handles X* \u2014",
27568
+ "full agent prompts live in `.claude/agents/<name>.md` and only",
27569
+ "load on delegation, so the table is the always-on routing",
27570
+ "signal.",
27571
+ "",
27572
+ "Cross-cutting policies that apply to every agent below \u2014",
27573
+ "Progress File Convention, Shared-Editing Safety, Issue",
27574
+ "Templates, Skill Evals \u2014 are documented as their own top-level",
27575
+ "sections elsewhere in this file. The registry only captures",
27576
+ "routing; it does not duplicate convention prose.",
27577
+ "",
27578
+ "| Skill | Agent | Bundle | Output path | Purpose |",
27579
+ "| --- | --- | --- | --- | --- |"
27580
+ ];
27581
+ for (const row of rows) {
27582
+ const outputPath = row.resolveOutputPath(paths);
27583
+ const pathCell = outputPath.length > 0 ? `\`${outputPath}\`` : "\u2014";
27584
+ lines.push(
27585
+ `| \`${row.skill}\` | \`${row.agent}\` | \`${row.bundle}\` | ${pathCell} | ${row.purpose} |`
27586
+ );
27587
+ }
27588
+ return {
27589
+ name: "agent-registry",
27590
+ 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.",
27591
+ scope: AGENT_RULE_SCOPE.ALWAYS,
27592
+ content: lines.join("\n"),
27593
+ platforms: {
27594
+ cursor: { exclude: true }
27595
+ },
27596
+ tags: ["workflow"]
27597
+ };
27598
+ }
27599
+
27274
27600
  // src/agent/bundles/features.ts
27275
27601
  var SOURCE_TIER_HEADINGS = [
27276
27602
  { key: "t1", heading: "### T1 \u2014 Primary Living" },
@@ -27638,7 +27964,7 @@ function renderPriorityRulesSection(rules) {
27638
27964
  }
27639
27965
 
27640
27966
  // src/agent/bundles/index.ts
27641
- function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
27967
+ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS, defaultAgentTier = AGENT_MODEL.BALANCED) {
27642
27968
  return [
27643
27969
  buildBaseBundle(paths),
27644
27970
  upstreamConfigulatorDocsBundle,
@@ -27651,7 +27977,7 @@ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAUL
27651
27977
  projenBundle,
27652
27978
  githubWorkflowBundle,
27653
27979
  slackBundle,
27654
- meetingAnalysisBundle,
27980
+ buildMeetingAnalysisBundle(defaultAgentTier),
27655
27981
  agendaBundle,
27656
27982
  orchestratorBundle,
27657
27983
  prReviewBundle,
@@ -27659,16 +27985,16 @@ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAUL
27659
27985
  buildRequirementsWriterBundle(paths, issueDefaults),
27660
27986
  buildRequirementsReviewerBundle(paths, issueDefaults),
27661
27987
  buildResearchPipelineBundle(paths, issueDefaults),
27662
- buildCompanyProfileBundle(paths, issueDefaults),
27663
- buildCustomerProfileBundle(paths, issueDefaults),
27664
- buildPeopleProfileBundle(paths, issueDefaults),
27665
- buildSoftwareProfileBundle(paths, issueDefaults),
27988
+ buildCompanyProfileBundle(paths, issueDefaults, defaultAgentTier),
27989
+ buildCustomerProfileBundle(paths, issueDefaults, defaultAgentTier),
27990
+ buildPeopleProfileBundle(paths, issueDefaults, defaultAgentTier),
27991
+ buildSoftwareProfileBundle(paths, issueDefaults, defaultAgentTier),
27666
27992
  buildIndustryDiscoveryBundle(paths, issueDefaults),
27667
27993
  buildBusinessModelsBundle(paths, issueDefaults),
27668
27994
  buildBcmWriterBundle(paths, issueDefaults),
27669
27995
  buildStandardsResearchBundle(paths, issueDefaults),
27670
27996
  buildRegulatoryResearchBundle(paths, issueDefaults),
27671
- buildMaintenanceAuditBundle(paths, issueDefaults),
27997
+ buildMaintenanceAuditBundle(paths, issueDefaults, defaultAgentTier),
27672
27998
  buildDocsSyncBundle(paths)
27673
27999
  ];
27674
28000
  }
@@ -27914,7 +28240,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
27914
28240
  /**
27915
28241
  * Render all Claude Code configuration files.
27916
28242
  */
27917
- static render(component, rules, skills, subAgents, mcpServers, settings, procedures) {
28243
+ static render(component, rules, skills, subAgents, mcpServers, settings, procedures, commands) {
27918
28244
  _ClaudeRenderer.renderClaudeMd(component, rules);
27919
28245
  _ClaudeRenderer.renderScopedRules(component, rules);
27920
28246
  _ClaudeRenderer.renderSettings(component, mcpServers, settings);
@@ -27923,6 +28249,9 @@ var ClaudeRenderer = class _ClaudeRenderer {
27923
28249
  if (procedures && procedures.length > 0) {
27924
28250
  _ClaudeRenderer.renderProcedures(component, procedures);
27925
28251
  }
28252
+ if (commands && commands.length > 0) {
28253
+ _ClaudeRenderer.renderCommands(component, commands);
28254
+ }
27926
28255
  }
27927
28256
  static renderClaudeMd(component, rules) {
27928
28257
  const claudeMdRules = rules.filter((r) => {
@@ -28254,6 +28583,30 @@ var ClaudeRenderer = class _ClaudeRenderer {
28254
28583
  });
28255
28584
  }
28256
28585
  }
28586
+ /**
28587
+ * Renders user-invokable slash commands to `.claude/commands/<name>.md`.
28588
+ *
28589
+ * Each command file carries a YAML frontmatter block with the
28590
+ * `description` (always present) and an optional `model` alias. The
28591
+ * body is the {@link AgentCommand.content} written verbatim.
28592
+ *
28593
+ * @see https://docs.claude.com/en/docs/claude-code/slash-commands
28594
+ */
28595
+ static renderCommands(component, commands) {
28596
+ for (const command of commands) {
28597
+ const lines = [];
28598
+ lines.push("---");
28599
+ lines.push(`description: ${command.description}`);
28600
+ const resolvedModel = resolveModelAlias(command.model);
28601
+ if (resolvedModel) {
28602
+ lines.push(`model: ${resolvedModel}`);
28603
+ }
28604
+ lines.push("---");
28605
+ lines.push("");
28606
+ lines.push(...command.content.split("\n"));
28607
+ new import_textfile3.TextFile(component, `.claude/commands/${command.name}.md`, { lines });
28608
+ }
28609
+ }
28257
28610
  /**
28258
28611
  * Determine the default Claude rule target based on rule scope.
28259
28612
  * ALWAYS-scoped rules default to CLAUDE_MD; FILE_PATTERN rules default to SCOPED_FILE.
@@ -28276,6 +28629,17 @@ var CopilotRenderer = class {
28276
28629
  };
28277
28630
 
28278
28631
  // src/agent/agent-config.ts
28632
+ function resolveDefaultAgentTier(options) {
28633
+ switch (options?.defaultAgentTier) {
28634
+ case "powerful":
28635
+ return AGENT_MODEL.POWERFUL;
28636
+ case "fast":
28637
+ return AGENT_MODEL.FAST;
28638
+ case "balanced":
28639
+ default:
28640
+ return AGENT_MODEL.BALANCED;
28641
+ }
28642
+ }
28279
28643
  var DEFAULT_CLAUDE_ALLOW = [
28280
28644
  // ── Git ──────────────────────────────────────────────────────────────
28281
28645
  "Bash(git add *)",
@@ -28380,6 +28744,45 @@ var DEFAULT_CLAUDE_DENY = [
28380
28744
  "Bash(export *)",
28381
28745
  "Bash(env *)"
28382
28746
  ];
28747
+ var DEFAULT_CLAUDE_PATH_DENY = [
28748
+ "Read(./node_modules/**)",
28749
+ "Read(./dist/**)",
28750
+ "Read(./lib/**)",
28751
+ "Read(./.astro/**)",
28752
+ "Read(./.env)",
28753
+ "Read(./.env.*)",
28754
+ "Read(./*.lock)",
28755
+ "Read(./pnpm-lock.yaml)",
28756
+ "Read(./package-lock.json)"
28757
+ ];
28758
+ var DEFAULT_USAGE_LOG_PATH = ".claude/usage.log";
28759
+ var DEFAULT_CLAUDE_ENV = {
28760
+ ENABLE_TOOL_SEARCH: "1"
28761
+ };
28762
+ var DEFAULT_CLAUDE_HOOKS = {
28763
+ Stop: [
28764
+ {
28765
+ matcher: "*",
28766
+ hooks: [
28767
+ {
28768
+ type: "command",
28769
+ command: `echo "$(date -u +%FT%TZ),\${CLAUDE_SESSION_ID:-unknown},\${CLAUDE_INPUT_TOKENS:-0},\${CLAUDE_OUTPUT_TOKENS:-0}" >> ${DEFAULT_USAGE_LOG_PATH}`
28770
+ }
28771
+ ]
28772
+ }
28773
+ ],
28774
+ PostToolUse: [
28775
+ {
28776
+ matcher: "Edit|Write",
28777
+ hooks: [
28778
+ {
28779
+ type: "command",
28780
+ 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'
28781
+ }
28782
+ ]
28783
+ }
28784
+ ]
28785
+ };
28383
28786
  var PROGRESS_FILE_BUNDLE_HOOKS = [
28384
28787
  ["bcm-writer-workflow", "bcm-writer"],
28385
28788
  ["business-models-workflow", "business-models"],
@@ -28454,10 +28857,30 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28454
28857
  return (examples.t1?.length ?? 0) > 0 || (examples.t2?.length ?? 0) > 0 || (examples.t3?.length ?? 0) > 0 || (examples.t4?.length ?? 0) > 0;
28455
28858
  }
28456
28859
  /**
28457
- * Merges default Claude permissions with bundle and user-supplied settings.
28860
+ * Merges default Claude permissions and hooks with bundle and
28861
+ * user-supplied settings.
28862
+ *
28863
+ * Permission merge order: defaults → bundle permissions → user-supplied
28864
+ * entries. Both `allow` and `deny` are deduped via
28865
+ * `Array.from(new Set(...))`; V8 `Set` iteration preserves insertion
28866
+ * order, so the final ordering is defaults first, then bundle, then
28867
+ * user, with duplicates removed (first-occurrence wins). `defaultMode`
28868
+ * defaults to `"dontAsk"` unless overridden — see the inline comment
28869
+ * on the literal below for the autonomous-worker rationale.
28870
+ *
28871
+ * Hooks merge: consumer-supplied entries first, then default entries
28872
+ * (Stop, PostToolUse), deduped by `(matcher, JSON-serialized hooks)`.
28873
+ * Defaults are skipped entirely when `disableAllHooks: true` is set —
28874
+ * the `disableAllHooks` flag passes through to the rendered file so
28875
+ * Claude Code suppresses every project-level hook at runtime, and the
28876
+ * defaults are dropped at synth time so the rendered file does not
28877
+ * carry orphan entries that would re-fire if the operator later flipped
28878
+ * the flag back off.
28458
28879
  *
28459
- * Merge order: defaults bundle permissions → user-supplied entries.
28460
- * `defaultMode` defaults to `"dontAsk"` unless overridden.
28880
+ * Env merge: defaults from `DEFAULT_CLAUDE_ENV` (e.g.
28881
+ * `ENABLE_TOOL_SEARCH=1`) layer first, then consumer-supplied
28882
+ * `claudeSettings.env` entries override on key collision. Sibling keys
28883
+ * from both sources land in the rendered file.
28461
28884
  */
28462
28885
  static mergeClaudeDefaults(userSettings, bundlePermissions) {
28463
28886
  const bundleAllow = bundlePermissions?.allow ?? [];
@@ -28466,14 +28889,80 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28466
28889
  const userDeny = userSettings?.permissions?.deny ?? [];
28467
28890
  return {
28468
28891
  ...userSettings,
28892
+ // `defaultMode: "dontAsk"` is configulator's hardcoded default
28893
+ // because scheduled-task workers (issue-worker, orchestrator,
28894
+ // pr-reviewer, and the analyst/writer family) run autonomously
28895
+ // and would deadlock on confirmation prompts. Any other value
28896
+ // breaks the autonomous-worker contract — override only after
28897
+ // revisiting that contract end-to-end. The override path for
28898
+ // consumers is `claudeSettings.defaultMode` on
28899
+ // `AgentConfigOptions`.
28469
28900
  defaultMode: userSettings?.defaultMode ?? "dontAsk",
28470
28901
  permissions: {
28471
28902
  ...userSettings?.permissions,
28472
- allow: [...DEFAULT_CLAUDE_ALLOW, ...bundleAllow, ...userAllow],
28473
- deny: [...DEFAULT_CLAUDE_DENY, ...bundleDeny, ...userDeny]
28474
- }
28903
+ allow: Array.from(
28904
+ /* @__PURE__ */ new Set([...DEFAULT_CLAUDE_ALLOW, ...bundleAllow, ...userAllow])
28905
+ ),
28906
+ deny: Array.from(
28907
+ /* @__PURE__ */ new Set([
28908
+ ...DEFAULT_CLAUDE_DENY,
28909
+ ...DEFAULT_CLAUDE_PATH_DENY,
28910
+ ...bundleDeny,
28911
+ ...userDeny
28912
+ ])
28913
+ )
28914
+ },
28915
+ hooks: _AgentConfig.mergeClaudeHooks(userSettings),
28916
+ env: { ...DEFAULT_CLAUDE_ENV, ...userSettings?.env ?? {} }
28475
28917
  };
28476
28918
  }
28919
+ /**
28920
+ * Merge default lifecycle hooks (Stop, PostToolUse) with consumer-
28921
+ * supplied entries on `claudeSettings.hooks`. Consumer entries appear
28922
+ * first so a downstream override that wires a faster lint/format hook
28923
+ * runs ahead of the defaults; defaults are appended after.
28924
+ *
28925
+ * Returns `undefined` when neither defaults nor consumer entries
28926
+ * remain — the renderer skips the `hooks` key entirely in that case
28927
+ * so opt-out repos do not ship an empty `"hooks": {}` object.
28928
+ *
28929
+ * Defaults are gated on `disableAllHooks !== true`. When the flag is
28930
+ * set we still pass through any consumer-supplied entries (the
28931
+ * runtime-level `disableAllHooks: true` is what suppresses execution),
28932
+ * but we never inject the bundle defaults. That keeps the disable-all
28933
+ * escape hatch idempotent: flipping the flag drops the bundle's
28934
+ * default surface area instead of leaving the entries on disk for a
28935
+ * future re-enable.
28936
+ */
28937
+ static mergeClaudeHooks(userSettings) {
28938
+ const userHooks = userSettings?.hooks;
28939
+ const includeDefaults = userSettings?.disableAllHooks !== true;
28940
+ const defaults = includeDefaults ? DEFAULT_CLAUDE_HOOKS : {};
28941
+ const allEvents = /* @__PURE__ */ new Set([
28942
+ ...Object.keys(userHooks ?? {}),
28943
+ ...Object.keys(defaults)
28944
+ ]);
28945
+ const merged = {};
28946
+ for (const event of allEvents) {
28947
+ const userEntries = (userHooks ?? {})[event] ?? [];
28948
+ const defaultEntries = defaults[event] ?? [];
28949
+ const seen = /* @__PURE__ */ new Set();
28950
+ const combined = [];
28951
+ for (const entry of [...userEntries, ...defaultEntries]) {
28952
+ const key = JSON.stringify({
28953
+ matcher: entry.matcher,
28954
+ hooks: entry.hooks
28955
+ });
28956
+ if (seen.has(key)) continue;
28957
+ seen.add(key);
28958
+ combined.push(entry);
28959
+ }
28960
+ if (combined.length > 0) {
28961
+ merged[event] = combined;
28962
+ }
28963
+ }
28964
+ return Object.keys(merged).length > 0 ? merged : void 0;
28965
+ }
28477
28966
  constructor(project, options = {}) {
28478
28967
  super(project);
28479
28968
  this.options = options;
@@ -28502,7 +28991,8 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28502
28991
  if (!this.cachedBundles) {
28503
28992
  this.cachedBundles = buildBuiltInBundles(
28504
28993
  this.resolvedPaths,
28505
- resolveIssueDefaults(this.options.issueDefaults)
28994
+ resolveIssueDefaults(this.options.issueDefaults),
28995
+ resolveDefaultAgentTier(this.options)
28506
28996
  );
28507
28997
  }
28508
28998
  return this.cachedBundles;
@@ -28548,6 +29038,9 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28548
29038
  if (resolvedRunRatio.enabled) {
28549
29039
  this.project.gitignore.addPatterns(`/${resolvedRunRatio.stateFilePath}`);
28550
29040
  }
29041
+ if (this.options.claudeSettings?.disableAllHooks !== true) {
29042
+ this.project.gitignore.addPatterns(`/${DEFAULT_USAGE_LOG_PATH}`);
29043
+ }
28551
29044
  validateUnblockDependentsConfig(this.options.unblockDependents);
28552
29045
  validateIssueDefaultsConfig(this.options.issueDefaults);
28553
29046
  const resolvedProgressFiles = validateProgressFilesConfig(
@@ -28612,6 +29105,7 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28612
29105
  const skills = this.resolveSkills();
28613
29106
  const subAgents = this.resolveSubAgents();
28614
29107
  const procedures = this.resolveProcedures();
29108
+ const commands = this.resolveCommands();
28615
29109
  const mcpServers = this.options.mcpServers ?? {};
28616
29110
  const projectMetadata = ProjectMetadata.of(this.project);
28617
29111
  const metadata = projectMetadata?.metadata;
@@ -28647,7 +29141,8 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28647
29141
  this.options.claudeSettings,
28648
29142
  bundlePermissions
28649
29143
  ),
28650
- resolvedProcedures
29144
+ resolvedProcedures,
29145
+ commands
28651
29146
  );
28652
29147
  }
28653
29148
  if (platforms.includes(AGENT_PLATFORM.CODEX)) {
@@ -28786,6 +29281,7 @@ ${section}`
28786
29281
  }
28787
29282
  }
28788
29283
  }
29284
+ const injectBundleHooks = this.options.claudeMd?.injectBundleHooks ?? true;
28789
29285
  const resolvedProgressFiles = resolveProgressFiles(
28790
29286
  this.options.progressFiles
28791
29287
  );
@@ -28803,7 +29299,7 @@ ${section}`
28803
29299
  }
28804
29300
  }
28805
29301
  }
28806
- if (resolvedProgressFiles.enabled) {
29302
+ if (injectBundleHooks && resolvedProgressFiles.enabled) {
28807
29303
  for (const [ruleName, label] of PROGRESS_FILE_BUNDLE_HOOKS) {
28808
29304
  const existing = ruleMap.get(ruleName);
28809
29305
  if (!existing) {
@@ -28843,7 +29339,7 @@ ${hook}`
28843
29339
  }
28844
29340
  }
28845
29341
  }
28846
- if (resolvedSharedEditingForRules.enabled) {
29342
+ if (injectBundleHooks && resolvedSharedEditingForRules.enabled) {
28847
29343
  for (const [ruleName, label] of SHARED_EDITING_BUNDLE_HOOKS) {
28848
29344
  const existing = ruleMap.get(ruleName);
28849
29345
  if (!existing) {
@@ -28883,7 +29379,7 @@ ${hook}`
28883
29379
  }
28884
29380
  }
28885
29381
  }
28886
- if (resolvedSkillEvalsForRules.enabled) {
29382
+ if (injectBundleHooks && resolvedSkillEvalsForRules.enabled) {
28887
29383
  for (const [ruleName, label] of SKILL_EVALS_BUNDLE_HOOKS) {
28888
29384
  const existing = ruleMap.get(ruleName);
28889
29385
  if (!existing) {
@@ -28928,7 +29424,7 @@ ${hook}`
28928
29424
  if (!hasAnyDocsEmittingBundle(excludedBundleNames)) {
28929
29425
  ruleMap.delete("stub-index-convention");
28930
29426
  }
28931
- if (resolvedIssueTemplatesForRules.enabled && hasDownstreamBundles) {
29427
+ if (injectBundleHooks && resolvedIssueTemplatesForRules.enabled && hasDownstreamBundles) {
28932
29428
  for (const [ruleName, label] of ISSUE_TEMPLATES_BUNDLE_HOOKS) {
28933
29429
  const existing = ruleMap.get(ruleName);
28934
29430
  if (!existing) {
@@ -28976,6 +29472,57 @@ ${hook}`
28976
29472
  }
28977
29473
  }
28978
29474
  }
29475
+ const registryRule = buildAgentRegistryRule(
29476
+ this.activeBundles,
29477
+ this.resolvedPaths
29478
+ );
29479
+ if (registryRule) {
29480
+ let registryContent = registryRule.content;
29481
+ const meetingAnalysisActive = this.activeBundles.some(
29482
+ (b) => b.name === "meeting-analysis"
29483
+ );
29484
+ if (this.options.meetings && meetingAnalysisActive) {
29485
+ const meetingsSection = renderMeetingTypesSection(
29486
+ this.options.meetings
29487
+ );
29488
+ if (meetingsSection.length > 0) {
29489
+ registryContent = `${registryContent}
29490
+
29491
+ ---
29492
+
29493
+ ${meetingsSection}`;
29494
+ }
29495
+ }
29496
+ ruleMap.set(registryRule.name, {
29497
+ ...registryRule,
29498
+ content: registryContent
29499
+ });
29500
+ const customSectionBundles = new Set(
29501
+ (this.options.features?.customDocSections ?? []).map(
29502
+ (s) => s.bundleName
29503
+ )
29504
+ );
29505
+ for (const [ruleName, rule] of ruleMap) {
29506
+ if (!isSuppressedWorkflowRule(ruleName)) {
29507
+ continue;
29508
+ }
29509
+ const owningBundleName = bundleNameForWorkflowRule(ruleName);
29510
+ if (owningBundleName !== void 0 && customSectionBundles.has(owningBundleName)) {
29511
+ continue;
29512
+ }
29513
+ const existingClaude = rule.platforms?.claude ?? {};
29514
+ if (existingClaude.exclude === true) {
29515
+ continue;
29516
+ }
29517
+ ruleMap.set(ruleName, {
29518
+ ...rule,
29519
+ platforms: {
29520
+ ...rule.platforms,
29521
+ claude: { ...existingClaude, exclude: true }
29522
+ }
29523
+ });
29524
+ }
29525
+ }
28979
29526
  return [...ruleMap.values()].sort((a, b) => {
28980
29527
  if (a.name === "project-overview") return -1;
28981
29528
  if (b.name === "project-overview") return 1;
@@ -29124,6 +29671,49 @@ ${hook}`
29124
29671
  }
29125
29672
  return [...procMap.values()];
29126
29673
  }
29674
+ /**
29675
+ * Resolves the final list of slash commands by merging bundle-shipped
29676
+ * defaults with consumer-supplied entries. Mirrors {@link resolveSkills}
29677
+ * and {@link resolveSubAgents}: auto-detected bundles contribute first,
29678
+ * force-included bundles overlay, and consumer commands override on
29679
+ * name collision. Names listed in `excludeCommands` are dropped after
29680
+ * the merge so consumers can opt out of a single default without
29681
+ * disabling the whole bundle.
29682
+ */
29683
+ resolveCommands() {
29684
+ const commandMap = /* @__PURE__ */ new Map();
29685
+ if (this.options.autoDetectBundles !== false) {
29686
+ for (const bundle of this.pathAwareBundles) {
29687
+ if (this.options.excludeBundles?.includes(bundle.name)) continue;
29688
+ if (bundle.appliesWhen(this.project) && bundle.commands) {
29689
+ for (const command of bundle.commands) {
29690
+ commandMap.set(command.name, command);
29691
+ }
29692
+ }
29693
+ }
29694
+ }
29695
+ if (this.options.includeBundles) {
29696
+ for (const bundleName of this.options.includeBundles) {
29697
+ const bundle = this.pathAwareBundles.find((b) => b.name === bundleName);
29698
+ if (bundle?.commands) {
29699
+ for (const command of bundle.commands) {
29700
+ commandMap.set(command.name, command);
29701
+ }
29702
+ }
29703
+ }
29704
+ }
29705
+ if (this.options.commands) {
29706
+ for (const command of this.options.commands) {
29707
+ commandMap.set(command.name, command);
29708
+ }
29709
+ }
29710
+ if (this.options.excludeCommands) {
29711
+ for (const name of this.options.excludeCommands) {
29712
+ commandMap.delete(name);
29713
+ }
29714
+ }
29715
+ return [...commandMap.values()];
29716
+ }
29127
29717
  /**
29128
29718
  * Resolves template variables in rule content using project metadata.
29129
29719
  * Emits synthesis warnings for rules with unresolved variables.
@@ -31281,7 +31871,7 @@ var JsiiFaker = class _JsiiFaker extends import_projen13.Component {
31281
31871
  };
31282
31872
 
31283
31873
  // src/projects/astro-project.ts
31284
- var import_projen18 = require("projen");
31874
+ var import_projen19 = require("projen");
31285
31875
  var import_ts_deepmerge3 = require("ts-deepmerge");
31286
31876
 
31287
31877
  // src/projects/monorepo-layout.ts
@@ -31425,20 +32015,35 @@ function resolveAstroProjectOutdir(packageName) {
31425
32015
  }
31426
32016
 
31427
32017
  // src/projects/typescript-project.ts
31428
- var import_projen17 = require("projen");
32018
+ var import_projen18 = require("projen");
31429
32019
  var import_javascript4 = require("projen/lib/javascript");
31430
32020
  var import_release = require("projen/lib/release");
31431
32021
  var import_ts_deepmerge2 = require("ts-deepmerge");
31432
32022
 
31433
32023
  // src/projects/monorepo-project.ts
31434
- var import_github2 = require("projen/lib/github");
32024
+ var import_github4 = require("projen/lib/github");
31435
32025
  var import_javascript3 = require("projen/lib/javascript");
31436
32026
  var import_typescript3 = require("projen/lib/typescript");
31437
32027
  var import_ts_deepmerge = require("ts-deepmerge");
31438
32028
 
31439
- // src/tasks/reset-task.ts
32029
+ // src/projects/nvmrc.ts
31440
32030
  var import_projen14 = require("projen");
31441
- var ResetTask = class _ResetTask extends import_projen14.Component {
32031
+ var import_textfile5 = require("projen/lib/textfile");
32032
+ var Nvmrc = class extends import_projen14.Component {
32033
+ constructor(project) {
32034
+ super(project);
32035
+ new import_textfile5.TextFile(project, ".nvmrc", {
32036
+ // `lines` is joined with `\n` — adding an empty trailing entry
32037
+ // produces a POSIX-friendly trailing newline (`24\n`).
32038
+ lines: [VERSION.NODE_WORKFLOWS, ""],
32039
+ readonly: true
32040
+ });
32041
+ }
32042
+ };
32043
+
32044
+ // src/tasks/reset-task.ts
32045
+ var import_projen15 = require("projen");
32046
+ var ResetTask = class _ResetTask extends import_projen15.Component {
31442
32047
  constructor(project, options = {}) {
31443
32048
  super(project);
31444
32049
  this.project = project;
@@ -31511,12 +32116,12 @@ var ResetTask = class _ResetTask extends import_projen14.Component {
31511
32116
  };
31512
32117
 
31513
32118
  // src/vscode/vscode.ts
31514
- var import_projen15 = require("projen");
31515
- var VSCodeConfig = class extends import_projen15.Component {
32119
+ var import_projen16 = require("projen");
32120
+ var VSCodeConfig = class extends import_projen16.Component {
31516
32121
  constructor(project) {
31517
32122
  super(project);
31518
- const vsConfig = new import_projen15.vscode.VsCode(project);
31519
- const vsSettings = new import_projen15.vscode.VsCodeSettings(vsConfig);
32123
+ const vsConfig = new import_projen16.vscode.VsCode(project);
32124
+ const vsSettings = new import_projen16.vscode.VsCodeSettings(vsConfig);
31520
32125
  vsSettings.addSetting("editor.tabSize", 2);
31521
32126
  vsSettings.addSetting("editor.detectIndentation", false);
31522
32127
  vsSettings.addSetting("editor.bracketPairColorization.enabled", true);
@@ -31657,8 +32262,146 @@ function addBuildCompleteJob(buildWorkflow) {
31657
32262
  });
31658
32263
  }
31659
32264
 
32265
+ // src/workflows/pin-pnpm-action-setup.ts
32266
+ var import_github2 = require("projen/lib/github");
32267
+ var PNPM_ACTION_SETUP_PREFIX = "pnpm/action-setup@";
32268
+ var STEP_ARRAY_FIELDS = ["preBuildSteps", "postBuildSteps"];
32269
+ function pinPnpmActionSetup(project) {
32270
+ const pinned = `${PNPM_ACTION_SETUP_PREFIX}${VERSION.PNPM_ACTION_SETUP_VERSION}`;
32271
+ patchComponentStepArrays(project, pinned);
32272
+ for (const sub of project.subprojects) {
32273
+ patchComponentStepArrays(sub, pinned);
32274
+ }
32275
+ const github = import_github2.GitHub.of(project);
32276
+ if (!github) {
32277
+ return;
32278
+ }
32279
+ for (const workflow of github.workflows) {
32280
+ for (const job of Object.values(workflow.jobs)) {
32281
+ patchStepArray(getEagerSteps(job), pinned);
32282
+ }
32283
+ }
32284
+ }
32285
+ function patchComponentStepArrays(project, pinned) {
32286
+ for (const component of project.components) {
32287
+ for (const field of STEP_ARRAY_FIELDS) {
32288
+ const steps = readStepArray(component, field);
32289
+ if (steps !== void 0) {
32290
+ patchStepArray(steps, pinned);
32291
+ }
32292
+ }
32293
+ }
32294
+ }
32295
+ function readStepArray(component, field) {
32296
+ const value = component[field];
32297
+ return Array.isArray(value) ? value : void 0;
32298
+ }
32299
+ function getEagerSteps(job) {
32300
+ if (typeof job !== "object" || job === null) {
32301
+ return void 0;
32302
+ }
32303
+ const steps = job.steps;
32304
+ return Array.isArray(steps) ? steps : void 0;
32305
+ }
32306
+ function patchStepArray(steps, pinned) {
32307
+ if (!steps) {
32308
+ return;
32309
+ }
32310
+ for (const step of steps) {
32311
+ if (typeof step.uses === "string" && step.uses.startsWith(PNPM_ACTION_SETUP_PREFIX)) {
32312
+ step.uses = pinned;
32313
+ }
32314
+ }
32315
+ }
32316
+
32317
+ // src/workflows/pin-setup-node-version.ts
32318
+ var import_github3 = require("projen/lib/github");
32319
+ var SETUP_NODE_PREFIX = "actions/setup-node@";
32320
+ var STEP_ARRAY_FIELDS2 = ["preBuildSteps", "postBuildSteps"];
32321
+ var NODE_VERSION_FIELDS = ["workflowNodeVersion"];
32322
+ function pinSetupNodeVersion(project) {
32323
+ const pinned = VERSION.NODE_WORKFLOWS;
32324
+ patchComponentNodeVersionFields(project, pinned);
32325
+ patchComponentStepArrays2(project, pinned);
32326
+ for (const sub of project.subprojects) {
32327
+ patchComponentNodeVersionFields(sub, pinned);
32328
+ patchComponentStepArrays2(sub, pinned);
32329
+ }
32330
+ const github = import_github3.GitHub.of(project);
32331
+ if (!github) {
32332
+ return;
32333
+ }
32334
+ for (const workflow of github.workflows) {
32335
+ for (const job of Object.values(workflow.jobs)) {
32336
+ patchJobToolsNode(job, pinned);
32337
+ patchStepArray2(getEagerSteps2(job), pinned);
32338
+ }
32339
+ }
32340
+ }
32341
+ function patchComponentNodeVersionFields(project, pinned) {
32342
+ for (const component of project.components) {
32343
+ for (const field of NODE_VERSION_FIELDS) {
32344
+ const record = component;
32345
+ const value = record[field];
32346
+ if (typeof value === "string") {
32347
+ record[field] = pinned;
32348
+ }
32349
+ }
32350
+ }
32351
+ }
32352
+ function patchComponentStepArrays2(project, pinned) {
32353
+ for (const component of project.components) {
32354
+ for (const field of STEP_ARRAY_FIELDS2) {
32355
+ const steps = readStepArray2(component, field);
32356
+ if (steps !== void 0) {
32357
+ patchStepArray2(steps, pinned);
32358
+ }
32359
+ }
32360
+ }
32361
+ }
32362
+ function readStepArray2(component, field) {
32363
+ const value = component[field];
32364
+ return Array.isArray(value) ? value : void 0;
32365
+ }
32366
+ function getEagerSteps2(job) {
32367
+ if (typeof job !== "object" || job === null) {
32368
+ return void 0;
32369
+ }
32370
+ const steps = job.steps;
32371
+ return Array.isArray(steps) ? steps : void 0;
32372
+ }
32373
+ function patchJobToolsNode(job, pinned) {
32374
+ if (typeof job !== "object" || job === null) {
32375
+ return;
32376
+ }
32377
+ const tools = job.tools;
32378
+ if (typeof tools !== "object" || tools === null) {
32379
+ return;
32380
+ }
32381
+ const node = tools.node;
32382
+ if (typeof node !== "object" || node === null) {
32383
+ return;
32384
+ }
32385
+ if (typeof node.version === "string") {
32386
+ node.version = pinned;
32387
+ }
32388
+ }
32389
+ function patchStepArray2(steps, pinned) {
32390
+ if (!steps) {
32391
+ return;
32392
+ }
32393
+ for (const step of steps) {
32394
+ if (typeof step.uses === "string" && step.uses.startsWith(SETUP_NODE_PREFIX)) {
32395
+ if (!step.with || typeof step.with !== "object") {
32396
+ step.with = {};
32397
+ }
32398
+ step.with["node-version"] = pinned;
32399
+ }
32400
+ }
32401
+ }
32402
+
31660
32403
  // src/workflows/sync-labels.ts
31661
- var import_projen16 = require("projen");
32404
+ var import_projen17 = require("projen");
31662
32405
  var import_workflows_model4 = require("projen/lib/github/workflows-model");
31663
32406
  var DEFAULT_STATUS_LABELS = [
31664
32407
  {
@@ -31866,10 +32609,10 @@ ${offenders}`
31866
32609
  }
31867
32610
  });
31868
32611
  }
31869
- var LabelsFile = class extends import_projen16.Component {
32612
+ var LabelsFile = class extends import_projen17.Component {
31870
32613
  constructor(project, labels) {
31871
32614
  super(project);
31872
- new import_projen16.YamlFile(project, LABELS_CONFIG_PATH, {
32615
+ new import_projen17.YamlFile(project, LABELS_CONFIG_PATH, {
31873
32616
  obj: labels.map((l) => ({
31874
32617
  name: l.name,
31875
32618
  color: l.color,
@@ -32087,6 +32830,7 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
32087
32830
  this.configulatorRegistryConsumer = options.configulatorRegistryConsumer ?? true;
32088
32831
  this.layoutEnforcement = options.layoutEnforcement ?? LAYOUT_ENFORCEMENT.WARN;
32089
32832
  new VSCodeConfig(this);
32833
+ new Nvmrc(this);
32090
32834
  new PnpmWorkspace(this, options.pnpmOptions?.pnpmWorkspaceOptions);
32091
32835
  if (options.turbo) {
32092
32836
  new TurboRepo(this, options.turboOptions);
@@ -32095,7 +32839,7 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
32095
32839
  name: "Build Sub Projects",
32096
32840
  run: `pnpm exec projen ${ROOT_CI_TASK_NAME}`
32097
32841
  },
32098
- import_github2.WorkflowSteps.uploadArtifact({
32842
+ import_github4.WorkflowSteps.uploadArtifact({
32099
32843
  name: "Upload Turbo runs",
32100
32844
  if: "always()",
32101
32845
  continueOnError: true,
@@ -32205,6 +32949,8 @@ var MonorepoProject = class extends import_typescript3.TypeScriptAppProject {
32205
32949
  */
32206
32950
  preSynthesize() {
32207
32951
  super.preSynthesize();
32952
+ pinPnpmActionSetup(this);
32953
+ pinSetupNodeVersion(this);
32208
32954
  if (this.layoutEnforcement === LAYOUT_ENFORCEMENT.OFF) {
32209
32955
  return;
32210
32956
  }
@@ -32259,7 +33005,7 @@ var TestRunner = {
32259
33005
  JEST: "jest",
32260
33006
  VITEST: "vitest"
32261
33007
  };
32262
- var TypeScriptProject = class extends import_projen17.typescript.TypeScriptProject {
33008
+ var TypeScriptProject = class extends import_projen18.typescript.TypeScriptProject {
32263
33009
  constructor(userOptions) {
32264
33010
  if (!(userOptions.parent instanceof MonorepoProject)) {
32265
33011
  throw new Error(
@@ -32569,10 +33315,10 @@ var AstroProject = class extends TypeScriptProject {
32569
33315
  adapter: options.adapter
32570
33316
  });
32571
33317
  if (options.sampleCode === true) {
32572
- new import_projen18.SampleFile(this, "src/pages/index.astro", {
33318
+ new import_projen19.SampleFile(this, "src/pages/index.astro", {
32573
33319
  contents: DEFAULT_INDEX_ASTRO
32574
33320
  });
32575
- new import_projen18.SampleFile(this, "public/favicon.svg", {
33321
+ new import_projen19.SampleFile(this, "public/favicon.svg", {
32576
33322
  contents: DEFAULT_FAVICON_SVG
32577
33323
  });
32578
33324
  }
@@ -32597,19 +33343,19 @@ var DEFAULT_FAVICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
32597
33343
  `;
32598
33344
 
32599
33345
  // src/projects/aws-cdk-project.ts
32600
- var import_projen21 = require("projen");
33346
+ var import_projen22 = require("projen");
32601
33347
  var import_javascript5 = require("projen/lib/javascript");
32602
33348
  var import_release2 = require("projen/lib/release");
32603
33349
  var import_ts_deepmerge4 = require("ts-deepmerge");
32604
33350
 
32605
33351
  // src/workflows/aws-deploy-workflow.ts
32606
33352
  var import_utils11 = __toESM(require_lib());
32607
- var import_projen19 = require("projen");
33353
+ var import_projen20 = require("projen");
32608
33354
  var import_build = require("projen/lib/build");
32609
- var import_github3 = require("projen/lib/github");
33355
+ var import_github5 = require("projen/lib/github");
32610
33356
  var import_workflows_model5 = require("projen/lib/github/workflows-model");
32611
33357
  var PROD_DEPLOY_NAME = "prod-deploy";
32612
- var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen19.Component {
33358
+ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen20.Component {
32613
33359
  constructor(project, options = {}) {
32614
33360
  super(project);
32615
33361
  this.project = project;
@@ -32722,7 +33468,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen19.Compone
32722
33468
  );
32723
33469
  }
32724
33470
  this.rootProject = project.root;
32725
- const github = import_github3.GitHub.of(this.rootProject);
33471
+ const github = import_github5.GitHub.of(this.rootProject);
32726
33472
  if (!github) {
32727
33473
  throw new Error(
32728
33474
  "AwsDeployWorkflow requires a GitHub component in the root project"
@@ -32857,7 +33603,7 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen19.Compone
32857
33603
  name: "Build Sub Projects",
32858
33604
  run: `pnpm exec projen ${ROOT_CI_TASK_NAME}`
32859
33605
  },
32860
- import_github3.WorkflowSteps.uploadArtifact({
33606
+ import_github5.WorkflowSteps.uploadArtifact({
32861
33607
  name: "Upload Turbo runs",
32862
33608
  if: "always()",
32863
33609
  continueOnError: true,
@@ -32873,8 +33619,8 @@ var AwsDeployWorkflow = class _AwsDeployWorkflow extends import_projen19.Compone
32873
33619
  };
32874
33620
 
32875
33621
  // src/workflows/aws-teardown-workflow.ts
32876
- var import_projen20 = require("projen");
32877
- var import_github4 = require("projen/lib/github");
33622
+ var import_projen21 = require("projen");
33623
+ var import_github6 = require("projen/lib/github");
32878
33624
  var import_workflows_model6 = require("projen/lib/github/workflows-model");
32879
33625
  var DEFAULT_TEARDOWN_BRANCH_PATTERNS = [
32880
33626
  "feat/*",
@@ -32895,7 +33641,7 @@ var resolveBranchPatterns = (explicit, targets) => {
32895
33641
  }
32896
33642
  return [...DEFAULT_TEARDOWN_BRANCH_PATTERNS];
32897
33643
  };
32898
- var AwsTeardownWorkflow = class extends import_projen20.Component {
33644
+ var AwsTeardownWorkflow = class extends import_projen21.Component {
32899
33645
  constructor(rootProject, options) {
32900
33646
  super(rootProject);
32901
33647
  this.rootProject = rootProject;
@@ -32924,7 +33670,7 @@ var AwsTeardownWorkflow = class extends import_projen20.Component {
32924
33670
  "AwsTeardownWorkflow requires the root project to be a MonorepoProject"
32925
33671
  );
32926
33672
  }
32927
- const github = import_github4.GitHub.of(this.rootProject);
33673
+ const github = import_github6.GitHub.of(this.rootProject);
32928
33674
  if (!github) {
32929
33675
  throw new Error(
32930
33676
  "AwsTeardownWorkflow requires a GitHub component in the root project"
@@ -32934,7 +33680,7 @@ var AwsTeardownWorkflow = class extends import_projen20.Component {
32934
33680
  deleteBranchPatterns,
32935
33681
  awsDestructionTargets
32936
33682
  );
32937
- const workflow = new import_github4.GithubWorkflow(github, "teardown-dev");
33683
+ const workflow = new import_github6.GithubWorkflow(github, "teardown-dev");
32938
33684
  workflow.on({
32939
33685
  workflowDispatch: {},
32940
33686
  schedule: [
@@ -33077,7 +33823,7 @@ var AwsTeardownWorkflow = class extends import_projen20.Component {
33077
33823
  };
33078
33824
 
33079
33825
  // src/projects/aws-cdk-project.ts
33080
- var AwsCdkProject = class extends import_projen21.awscdk.AwsCdkTypeScriptApp {
33826
+ var AwsCdkProject = class extends import_projen22.awscdk.AwsCdkTypeScriptApp {
33081
33827
  constructor(userOptions) {
33082
33828
  if (!(userOptions.parent instanceof MonorepoProject)) {
33083
33829
  throw new Error(
@@ -33274,7 +34020,7 @@ var AwsCdkProject = class extends import_projen21.awscdk.AwsCdkTypeScriptApp {
33274
34020
  };
33275
34021
 
33276
34022
  // src/projects/starlight-project.ts
33277
- var import_projen22 = require("projen");
34023
+ var import_projen23 = require("projen");
33278
34024
  var STARLIGHT_ROLE = {
33279
34025
  DOCS: "docs",
33280
34026
  SITE: "site"
@@ -33316,10 +34062,10 @@ var StarlightProject = class extends AstroProject {
33316
34062
  turbo.compileTask.inputs.push("src/content/**");
33317
34063
  }
33318
34064
  if (userOptions.sampleContent === true) {
33319
- new import_projen22.SampleFile(this, "src/content/docs/index.mdx", {
34065
+ new import_projen23.SampleFile(this, "src/content/docs/index.mdx", {
33320
34066
  contents: DEFAULT_INDEX_MDX
33321
34067
  });
33322
- new import_projen22.SampleFile(this, "src/content.config.ts", {
34068
+ new import_projen23.SampleFile(this, "src/content.config.ts", {
33323
34069
  contents: DEFAULT_CONTENT_CONFIG_TS
33324
34070
  });
33325
34071
  }
@@ -33369,9 +34115,9 @@ export const collections = {
33369
34115
 
33370
34116
  // src/typescript/typescript-config.ts
33371
34117
  var import_node_path2 = require("path");
33372
- var import_projen23 = require("projen");
34118
+ var import_projen24 = require("projen");
33373
34119
  var import_path2 = require("projen/lib/util/path");
33374
- var TypeScriptConfig = class extends import_projen23.Component {
34120
+ var TypeScriptConfig = class extends import_projen24.Component {
33375
34121
  constructor(project) {
33376
34122
  super(project);
33377
34123
  let tsPaths = {};
@@ -33400,6 +34146,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33400
34146
  0 && (module.exports = {
33401
34147
  AGENT_MODEL,
33402
34148
  AGENT_PLATFORM,
34149
+ AGENT_REGISTRY_ENTRIES,
33403
34150
  AGENT_RULE_SCOPE,
33404
34151
  AGENT_TIER_ROLES,
33405
34152
  AGENT_TIER_VALUES,
@@ -33483,6 +34230,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33483
34230
  MINIMUM_RELEASE_AGE,
33484
34231
  MONOREPO_LAYOUT,
33485
34232
  MonorepoProject,
34233
+ Nvmrc,
33486
34234
  PROD_DEPLOY_NAME,
33487
34235
  PROGRESS_FILES_FORMAT_VALUES,
33488
34236
  PnpmWorkspace,
@@ -33495,6 +34243,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33495
34243
  SCOPE_CLASS_VALUES,
33496
34244
  SHARED_EDITING_CONFLICT_STRATEGY_VALUES,
33497
34245
  STARLIGHT_ROLE,
34246
+ SUPPRESSED_WORKFLOW_RULE_NAMES,
33498
34247
  SampleLang,
33499
34248
  StarlightProject,
33500
34249
  TestRunner,
@@ -33520,6 +34269,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33520
34269
  awsCdkBundle,
33521
34270
  baseBundle,
33522
34271
  bcmWriterBundle,
34272
+ buildAgentRegistryRule,
33523
34273
  buildBaseBundle,
33524
34274
  buildBcmWriterBundle,
33525
34275
  buildBuiltInBundles,
@@ -33530,6 +34280,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33530
34280
  buildDocsSyncBundle,
33531
34281
  buildIndustryDiscoveryBundle,
33532
34282
  buildMaintenanceAuditBundle,
34283
+ buildMeetingAnalysisBundle,
33533
34284
  buildOrchestratorConventionsContent,
33534
34285
  buildPeopleProfileBundle,
33535
34286
  buildRegulatoryResearchBundle,
@@ -33541,6 +34292,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33541
34292
  buildSoftwareProfileBundle,
33542
34293
  buildStandardsResearchBundle,
33543
34294
  buildUnblockDependentsProcedure,
34295
+ bundleNameForWorkflowRule,
33544
34296
  businessModelsBundle,
33545
34297
  checkDocSamplesProcedure,
33546
34298
  checkLinksProcedure,
@@ -33567,6 +34319,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33567
34319
  industryDiscoveryBundle,
33568
34320
  isPhaseLabelOwnedByExcluded,
33569
34321
  isScheduledTaskOwnedByExcluded,
34322
+ isSuppressedWorkflowRule,
33570
34323
  isTypeLabelOwnedByExcluded,
33571
34324
  jestBundle,
33572
34325
  labelsForPhase,
@@ -33576,6 +34329,8 @@ var TypeScriptConfig = class extends import_projen23.Component {
33576
34329
  parseApiRollup,
33577
34330
  peopleProfileBundle,
33578
34331
  persistAuditReport,
34332
+ pinPnpmActionSetup,
34333
+ pinSetupNodeVersion,
33579
34334
  pnpmBundle,
33580
34335
  prReviewBundle,
33581
34336
  projenBundle,
@@ -33623,6 +34378,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33623
34378
  resolveAgentTiers,
33624
34379
  resolveAstroProjectOutdir,
33625
34380
  resolveAwsCdkProjectOutdir,
34381
+ resolveDefaultAgentTier,
33626
34382
  resolveIssueDefaults,
33627
34383
  resolveIssueTemplates,
33628
34384
  resolveModelAlias,