@codedrifters/configulator 0.0.290 → 0.0.292

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
@@ -210,6 +210,8 @@ __export(index_exports, {
210
210
  DEFAULT_DISPATCH_MODEL: () => DEFAULT_DISPATCH_MODEL,
211
211
  DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO: () => DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO,
212
212
  DEFAULT_HOUSEKEEPING_MODEL: () => DEFAULT_HOUSEKEEPING_MODEL,
213
+ DEFAULT_ISSUE_PRIORITY: () => DEFAULT_ISSUE_PRIORITY,
214
+ DEFAULT_ISSUE_STATUS: () => DEFAULT_ISSUE_STATUS,
213
215
  DEFAULT_ISSUE_TEMPLATES_BUNDLE_PATH_PATTERNS: () => DEFAULT_ISSUE_TEMPLATES_BUNDLE_PATH_PATTERNS,
214
216
  DEFAULT_ISSUE_TEMPLATES_EMIT_CHECKER: () => DEFAULT_ISSUE_TEMPLATES_EMIT_CHECKER,
215
217
  DEFAULT_ISSUE_TEMPLATES_EMIT_STARTER: () => DEFAULT_ISSUE_TEMPLATES_EMIT_STARTER,
@@ -226,6 +228,7 @@ __export(index_exports, {
226
228
  DEFAULT_PROGRESS_FILES_STALE_AFTER_HOURS: () => DEFAULT_PROGRESS_FILES_STALE_AFTER_HOURS,
227
229
  DEFAULT_PROGRESS_FILES_STATE_DIR: () => DEFAULT_PROGRESS_FILES_STATE_DIR,
228
230
  DEFAULT_REQUIRE_PRODUCT_CONTEXT: () => DEFAULT_REQUIRE_PRODUCT_CONTEXT,
231
+ DEFAULT_RESOLVED_ISSUE_DEFAULTS: () => DEFAULT_RESOLVED_ISSUE_DEFAULTS,
229
232
  DEFAULT_SAMPLE_COMPILER_OPTIONS: () => DEFAULT_SAMPLE_COMPILER_OPTIONS,
230
233
  DEFAULT_SCHEDULED_TASKS_ROOT: () => DEFAULT_SCHEDULED_TASKS_ROOT,
231
234
  DEFAULT_SCHEDULED_TASK_ENTRIES: () => DEFAULT_SCHEDULED_TASK_ENTRIES,
@@ -277,6 +280,8 @@ __export(index_exports, {
277
280
  TypeScriptConfig: () => TypeScriptConfig,
278
281
  TypeScriptProject: () => TypeScriptProject,
279
282
  UNKNOWN_TYPE_FALLBACK_TIER: () => UNKNOWN_TYPE_FALLBACK_TIER,
283
+ VALID_PRIORITY_VALUES: () => VALID_PRIORITY_VALUES,
284
+ VALID_STATUS_VALUES: () => VALID_STATUS_VALUES,
280
285
  VERSION: () => VERSION,
281
286
  VERSION_KEYS_SKIP: () => VERSION_KEYS_SKIP,
282
287
  VERSION_NPM_PACKAGES: () => VERSION_NPM_PACKAGES,
@@ -335,6 +340,7 @@ __export(index_exports, {
335
340
  githubWorkflowBundle: () => githubWorkflowBundle,
336
341
  industryDiscoveryBundle: () => industryDiscoveryBundle,
337
342
  jestBundle: () => jestBundle,
343
+ labelsForPhase: () => labelsForPhase,
338
344
  maintenanceAuditBundle: () => maintenanceAuditBundle,
339
345
  meetingAnalysisBundle: () => meetingAnalysisBundle,
340
346
  orchestratorBundle: () => orchestratorBundle,
@@ -377,6 +383,7 @@ __export(index_exports, {
377
383
  renderSkillEvalsRuleContent: () => renderSkillEvalsRuleContent,
378
384
  renderSkillEvalsRunnerScript: () => renderSkillEvalsRunnerScript,
379
385
  renderSourceTierExamples: () => renderSourceTierExamples,
386
+ renderStubIndexConventionRuleContent: () => renderStubIndexConventionRuleContent,
380
387
  renderUnblockDependentsScript: () => renderUnblockDependentsScript,
381
388
  renderUnblockDependentsSection: () => renderUnblockDependentsSection,
382
389
  requirementsAnalystBundle: () => requirementsAnalystBundle,
@@ -387,6 +394,7 @@ __export(index_exports, {
387
394
  resolveAgentTiers: () => resolveAgentTiers,
388
395
  resolveAstroProjectOutdir: () => resolveAstroProjectOutdir,
389
396
  resolveAwsCdkProjectOutdir: () => resolveAwsCdkProjectOutdir,
397
+ resolveIssueDefaults: () => resolveIssueDefaults,
390
398
  resolveIssueTemplates: () => resolveIssueTemplates,
391
399
  resolveModelAlias: () => resolveModelAlias,
392
400
  resolveOrchestratorAssets: () => resolveOrchestratorAssets,
@@ -410,6 +418,7 @@ __export(index_exports, {
410
418
  typescriptBundle: () => typescriptBundle,
411
419
  upstreamConfigulatorDocsBundle: () => upstreamConfigulatorDocsBundle,
412
420
  validateAgentTierConfig: () => validateAgentTierConfig,
421
+ validateIssueDefaultsConfig: () => validateIssueDefaultsConfig,
413
422
  validateIssueTemplatesConfig: () => validateIssueTemplatesConfig,
414
423
  validateMonorepoLayout: () => validateMonorepoLayout,
415
424
  validateProgressFilesConfig: () => validateProgressFilesConfig,
@@ -837,13 +846,16 @@ var agendaAnalystSubAgent = {
837
846
  " `duration_min` \xB1 5 minutes. If it doesn't, adjust section times",
838
847
  " or cut content \u2014 do not ship a math-broken agenda.",
839
848
  "",
840
- "7. **Create the folder `index.md` if missing.** Populate it with:",
849
+ "7. **Create the folder `index.md` if missing.** Populate it",
850
+ " following the `stub-index-convention` rule:",
841
851
  " - Frontmatter `title` (short sidebar label) and `description`",
842
852
  " (one line).",
843
853
  " - A 2\u20134 sentence summary of the meeting's objective and desired",
844
854
  " outcomes pulled from the agenda.",
845
855
  " - A `## Documents` section linking to `./agenda.md` (and",
846
856
  " `./notes.md` once the meeting-analyst produces it).",
857
+ " - No body `# Heading` \u2014 the frontmatter `title:` already",
858
+ " renders as the page H1.",
847
859
  "",
848
860
  " Do NOT set `sidebar.hidden: true` on `index.md` \u2014 it is the page",
849
861
  " that should appear in the sidebar.",
@@ -1607,8 +1619,6 @@ function renderIssueTemplatesStarterPage(_it) {
1607
1619
  "description: Canonical gh issue create recipes \u2014 one per downstream phase label.",
1608
1620
  "---",
1609
1621
  "",
1610
- "# Issue Templates",
1611
- "",
1612
1622
  "This page lists the canonical `gh issue create` recipe for every",
1613
1623
  "downstream issue kind dispatched by an agent in this monorepo.",
1614
1624
  "Bundles and agent prompts cite the matching section below instead",
@@ -3043,6 +3053,71 @@ function assertValidProductContextPath(value) {
3043
3053
  }
3044
3054
  }
3045
3055
 
3056
+ // src/agent/bundles/stub-index-convention.ts
3057
+ function renderStubIndexConventionRuleContent() {
3058
+ return [
3059
+ "# Section Index Pages",
3060
+ "",
3061
+ "When any agent creates or updates an `index.md` (or `README.md`)",
3062
+ "in a docs subdirectory under a Starlight content root, the file's",
3063
+ "body must include:",
3064
+ "",
3065
+ "1. **A 1\u20132 paragraph summary** of the section's purpose and how",
3066
+ " it fits into the larger research, requirements, or capability",
3067
+ " area. Readers landing on the page should understand what's in",
3068
+ " the section without falling back to the sidebar.",
3069
+ "",
3070
+ "2. **A grouped, linked listing of the directory's children**",
3071
+ " (table or bullet list). When a natural taxonomy exists (e.g.",
3072
+ " organizations grouped by sub-segment, regulations grouped by",
3073
+ " jurisdiction, capabilities grouped by tier), use it. Otherwise",
3074
+ " sort alphabetically by title. Every listing entry must link",
3075
+ " to the child page.",
3076
+ "",
3077
+ "3. **No body `# Heading`.** Starlight renders the frontmatter",
3078
+ " `title:` as the page H1 automatically \u2014 a body H1 produces a",
3079
+ " duplicate. The same no-body-H1 contract that applies to skill",
3080
+ " templates and inline agent templates also applies to every",
3081
+ " index page emitted by an agent.",
3082
+ "",
3083
+ "## When this applies",
3084
+ "",
3085
+ "The convention applies to every `index.md` / `README.md` file",
3086
+ "covered by the shared-index path globs documented in the",
3087
+ "`shared-editing-safety` rule:",
3088
+ "",
3089
+ "- `docs/src/content/docs/**/index.md`",
3090
+ "- `docs/src/content/docs/**/README.md`",
3091
+ "",
3092
+ "Any agent that scaffolds a new directory under a Starlight",
3093
+ "content root MUST populate the directory's index page following",
3094
+ "this contract \u2014 a one-sentence stub is not acceptable.",
3095
+ "",
3096
+ "## Reference shapes",
3097
+ "",
3098
+ "Existing rich indexes are the canonical reference shape. Examples:",
3099
+ "",
3100
+ "- A `<MEETINGS_ROOT>/<YYYY-MM-DD>-<slug>/index.md` populated by",
3101
+ " the `agenda-analyst` bundle: frontmatter `title` /",
3102
+ " `description`, a 2\u20134 sentence summary, and a `## Documents`",
3103
+ " section listing every page in the folder.",
3104
+ "- A regulations scope index that opens with two paragraphs of",
3105
+ " context and groups every linked regulation under a",
3106
+ " `## Regulations` table by jurisdiction.",
3107
+ "- A standards-organizations index that groups every linked",
3108
+ " organization under a `## Organizations` heading by role",
3109
+ " (governance, working group, implementer).",
3110
+ "",
3111
+ "## Out of scope",
3112
+ "",
3113
+ "- Auto-generated child listings via Astro/Starlight components.",
3114
+ " Agents emit hand-curated tables or bullet lists; the rule",
3115
+ " defines the shape, not the rendering technology.",
3116
+ "- Backfilling pre-existing stub indexes is a downstream-consumer",
3117
+ " cleanup task, not a configulator change."
3118
+ ].join("\n");
3119
+ }
3120
+
3046
3121
  // src/agent/bundles/base.ts
3047
3122
  var createPackageSkill = {
3048
3123
  name: "create-package",
@@ -3834,8 +3909,21 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
3834
3909
  "| `status:in-progress` | A worker has claimed the issue and a branch exists. Set when the worker starts; cleared only when the worker opens a PR or the issue fails. |",
3835
3910
  "| `status:ready-for-review` | A PR has been opened for this issue and is awaiting review and merge. Replaces `status:in-progress` at the moment the PR opens. |",
3836
3911
  "| `status:needs-attention` | Automated triage has flagged the issue for human review (stale, failed worker, or ambiguous state). Humans reset this label manually. |",
3912
+ "| `status:deferred` | Captured for provenance only; should not be auto-dispatched. Used by consumers that want a low-priority backlog (e.g. people-profile follow-ups in research-heavy planning repos) to stay out of the orchestrator's queue until a human or a consumer-configured scheduled task promotes it. |",
3837
3913
  "| `status:done` | The change has shipped. Set when the PR merges and the issue closes. |",
3838
3914
  "",
3915
+ "### Configurable filing-site defaults",
3916
+ "",
3917
+ "The bundle-shipped `gh issue create` recipes default to",
3918
+ "`status:ready` + `priority:medium`. Consumers can override the",
3919
+ "defaults per-phase-label via",
3920
+ "`AgentConfigOptions.issueDefaults` \u2014 e.g. flip every",
3921
+ "`people:research` filing to `status:deferred` + `priority:low`",
3922
+ "without touching the bundle source. See the **`issueDefaults`**",
3923
+ "section in the configulator agent-config docs for the full",
3924
+ "schema and consumer example. `status:deferred` is a valid",
3925
+ "override value reserved for this exact use case.",
3926
+ "",
3839
3927
  "### Blocking Rules",
3840
3928
  "",
3841
3929
  "Two rules force `status:blocked` \u2014 both are non-negotiable:",
@@ -4128,6 +4216,16 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4128
4216
  },
4129
4217
  tags: ["workflow"]
4130
4218
  },
4219
+ {
4220
+ name: "stub-index-convention",
4221
+ description: "Section-index convention: every agent-emitted `index.md` / `README.md` under a Starlight docs root carries a contextual summary plus a grouped, linked listing of the directory's children \u2014 and no body `# Heading` (Starlight renders the frontmatter `title:` as the page H1).",
4222
+ scope: AGENT_RULE_SCOPE.ALWAYS,
4223
+ content: renderStubIndexConventionRuleContent(),
4224
+ platforms: {
4225
+ cursor: { exclude: true }
4226
+ },
4227
+ tags: ["workflow"]
4228
+ },
4131
4229
  {
4132
4230
  name: "skill-evals",
4133
4231
  description: "Skill eval harness contract: declarative prompt/expected-output regression suites per skill at `<skillsRoot>/<skill-name>/evals/evals.json`, parameterised by a shared product-context fixture so the same eval shape works across every configulator-consuming project without forking fixtures.",
@@ -4403,8 +4501,6 @@ function buildBcmWriterSubAgent(paths) {
4403
4501
  " tier: L1 | L2 | L3",
4404
4502
  " ---",
4405
4503
  "",
4406
- " # BCM Outline: <Capability Name>",
4407
- "",
4408
4504
  " ## Capability Name",
4409
4505
  " <noun or noun phrase \u2014 never a verb>",
4410
4506
  "",
@@ -4484,8 +4580,6 @@ function buildBcmWriterSubAgent(paths) {
4484
4580
  " date: YYYY-MM-DD",
4485
4581
  " ---",
4486
4582
  "",
4487
- " # <Capability Name>",
4488
- "",
4489
4583
  " ## Capability Definitions",
4490
4584
  " <1\u20132 sentences from the outline's Proposed Definition, refined>",
4491
4585
  "",
@@ -4895,8 +4989,6 @@ title: "Business Model: <Segment Name>"
4895
4989
  description: "Business Model Canvas analysis for the <segment name> segment of the <industry> industry."
4896
4990
  ---
4897
4991
 
4898
- # Business Model: <Segment Name>
4899
-
4900
4992
  | Field | Value |
4901
4993
  |-------|-------|
4902
4994
  | **Industry** | <industry name> |
@@ -5280,8 +5372,6 @@ function buildBusinessModelsAnalystSubAgent(paths) {
5280
5372
  " status: complete",
5281
5373
  " ---",
5282
5374
  "",
5283
- " # Business Model Scan: <Industry Name>",
5284
- "",
5285
5375
  " ## Source Inputs",
5286
5376
  " - Industry plan: <relative path>",
5287
5377
  " - Prior research: <relative path> (optional)",
@@ -5369,8 +5459,12 @@ function buildBusinessModelsAnalystSubAgent(paths) {
5369
5459
  "",
5370
5460
  "7. **Create the segment index** at",
5371
5461
  " `<BUSINESS_MODELS_ROOT>/<industry>/segments/<SEGMENT_SLUG>/index.md`",
5372
- " if it does not already exist. The index should carry a short",
5373
- " description and link to `./business-model.md`.",
5462
+ " if it does not already exist. Follow the",
5463
+ " `stub-index-convention` rule: a 1\u20132 paragraph summary of the",
5464
+ " segment plus a linked listing of every page in the folder",
5465
+ " (`./business-model.md` and any value-stream / capability pages",
5466
+ " that land later). No body `# Heading` \u2014 the frontmatter",
5467
+ " `title:` already renders as the page H1.",
5374
5468
  "",
5375
5469
  "8. **Create one `business-models:complete` issue** with",
5376
5470
  " `Depends on: #<canvas-issue>`. Its body references the path to",
@@ -5899,8 +5993,92 @@ function buildBusinessModelsBundle(paths = DEFAULT_AGENT_PATHS) {
5899
5993
  }
5900
5994
  var businessModelsBundle = buildBusinessModelsBundle();
5901
5995
 
5996
+ // src/agent/bundles/issue-defaults.ts
5997
+ var VALID_STATUS_VALUES = [
5998
+ "ready",
5999
+ "blocked",
6000
+ "in-progress",
6001
+ "ready-for-review",
6002
+ "needs-attention",
6003
+ "done",
6004
+ "deferred"
6005
+ ];
6006
+ var VALID_PRIORITY_VALUES = [
6007
+ "critical",
6008
+ "high",
6009
+ "medium",
6010
+ "low",
6011
+ "trivial"
6012
+ ];
6013
+ var DEFAULT_ISSUE_STATUS = "ready";
6014
+ var DEFAULT_ISSUE_PRIORITY = "medium";
6015
+ var DEFAULT_RESOLVED_ISSUE_DEFAULTS = {
6016
+ defaults: {
6017
+ status: DEFAULT_ISSUE_STATUS,
6018
+ priority: DEFAULT_ISSUE_PRIORITY
6019
+ },
6020
+ overrides: {}
6021
+ };
6022
+ function resolveIssueDefaults(config) {
6023
+ if (config === void 0) {
6024
+ return DEFAULT_RESOLVED_ISSUE_DEFAULTS;
6025
+ }
6026
+ const overrides = {};
6027
+ for (const [phaseLabel, override] of Object.entries(config)) {
6028
+ assertValidPhaseLabel(phaseLabel);
6029
+ assertValidOverride(phaseLabel, override);
6030
+ overrides[phaseLabel] = {
6031
+ status: override.status ?? DEFAULT_ISSUE_STATUS,
6032
+ priority: override.priority ?? DEFAULT_ISSUE_PRIORITY
6033
+ };
6034
+ }
6035
+ return {
6036
+ defaults: {
6037
+ status: DEFAULT_ISSUE_STATUS,
6038
+ priority: DEFAULT_ISSUE_PRIORITY
6039
+ },
6040
+ overrides
6041
+ };
6042
+ }
6043
+ function validateIssueDefaultsConfig(config) {
6044
+ return resolveIssueDefaults(config);
6045
+ }
6046
+ function labelsForPhase(resolved, phaseLabel) {
6047
+ return resolved.overrides[phaseLabel] ?? resolved.defaults;
6048
+ }
6049
+ function assertValidPhaseLabel(phaseLabel) {
6050
+ if (typeof phaseLabel !== "string" || phaseLabel.trim() === "") {
6051
+ throw new Error(
6052
+ "AgentConfigOptions.issueDefaults: phase-label keys must be non-empty strings (e.g. `people:research`)."
6053
+ );
6054
+ }
6055
+ }
6056
+ function assertValidOverride(phaseLabel, override) {
6057
+ if (override === null || typeof override !== "object" || Array.isArray(override)) {
6058
+ throw new Error(
6059
+ `AgentConfigOptions.issueDefaults["${phaseLabel}"] must be an object with optional \`status\` and \`priority\` fields.`
6060
+ );
6061
+ }
6062
+ const { status, priority } = override;
6063
+ if (status === void 0 && priority === void 0) {
6064
+ throw new Error(
6065
+ `AgentConfigOptions.issueDefaults["${phaseLabel}"] must declare at least one of \`status\` or \`priority\`. Empty entries are rejected because they are almost always a typo on the field name.`
6066
+ );
6067
+ }
6068
+ if (status !== void 0 && !VALID_STATUS_VALUES.includes(status)) {
6069
+ throw new Error(
6070
+ `AgentConfigOptions.issueDefaults["${phaseLabel}"].status="${status}" is not a recognised status value. Allowed values: ${VALID_STATUS_VALUES.join(", ")}.`
6071
+ );
6072
+ }
6073
+ if (priority !== void 0 && !VALID_PRIORITY_VALUES.includes(priority)) {
6074
+ throw new Error(
6075
+ `AgentConfigOptions.issueDefaults["${phaseLabel}"].priority="${priority}" is not a recognised priority value. Allowed values: ${VALID_PRIORITY_VALUES.join(", ")}.`
6076
+ );
6077
+ }
6078
+ }
6079
+
5902
6080
  // src/agent/bundles/company-profile.ts
5903
- function buildCompanyProfileAnalystSubAgent(paths) {
6081
+ function buildCompanyProfileAnalystSubAgent(paths, issueDefaults) {
5904
6082
  return {
5905
6083
  name: "company-profile-analyst",
5906
6084
  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.",
@@ -6161,8 +6339,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6161
6339
  " parent_issue: <N>",
6162
6340
  " ---",
6163
6341
  "",
6164
- " # Research Notes: <company name>",
6165
- "",
6166
6342
  " ## Framing",
6167
6343
  " <why this company was requested and what to learn>",
6168
6344
  "",
@@ -6224,8 +6400,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6224
6400
  " referencedIn: []",
6225
6401
  " ---",
6226
6402
  "",
6227
- " # <company name>",
6228
- "",
6229
6403
  " ## Summary",
6230
6404
  " <2\u20134 sentence elevator description: what they do, who they sell to>",
6231
6405
  "",
@@ -6314,8 +6488,8 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6314
6488
  "",
6315
6489
  " - `type:people-profile`",
6316
6490
  " - `people:research`",
6317
- " - `priority:medium`",
6318
- " - `status:ready`",
6491
+ ` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
6492
+ ` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
6319
6493
  "",
6320
6494
  " The issue body must include:",
6321
6495
  " - A **discovery source** line naming this company profile",
@@ -6331,8 +6505,8 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6331
6505
  "",
6332
6506
  " - `type:software-profile`",
6333
6507
  " - `software:research`",
6334
- " - `priority:medium`",
6335
- " - `status:ready`",
6508
+ ` - \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\``,
6509
+ ` - \`status:${labelsForPhase(issueDefaults, "software:research").status}\``,
6336
6510
  "",
6337
6511
  " The issue body must include:",
6338
6512
  " - A **discovery source** line naming this company profile",
@@ -6636,8 +6810,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6636
6810
  " - <relative path to profile 2>",
6637
6811
  " ---",
6638
6812
  "",
6639
- " # <segment name> Competitive Analysis",
6640
- "",
6641
6813
  " ## Market Overview",
6642
6814
  " <landscape summary \u2014 total players, market structure, trends",
6643
6815
  " visible from the profiles>",
@@ -6775,47 +6947,52 @@ function buildCompanyProfileAnalystSubAgent(paths) {
6775
6947
  ].join("\n")
6776
6948
  };
6777
6949
  }
6778
- var PROFILE_COMPANY_EVALS_JSON = JSON.stringify(
6779
- {
6780
- skill_name: "profile-company",
6781
- evals: [
6782
- {
6783
- id: 1,
6784
- prompt: "/profile-company Acme Registration \u2014 they're a mid-market B2B event platform we ran into at a trade show last month. framing: competitive analysis for our self-service registration feature.",
6785
- expected_output: "A `company:research` issue is created with `type:company-profile`, `priority:medium`, and `status:ready`. The issue body carries the company name, an inferred or stated type (likely `competitor` given the framing), the framing text, and any supplied overrides. Phase 1 produces a research-notes file under the project's notes directory with sources annotated by tier (T1/T2/T3/T4) and date. Phase 2 opens a `company:draft` issue and may additionally open `people:research` issues for notable leaders surfaced and `software:research` issues for adjacent product mentions. The skill does not author person profiles, software profiles, or comparative analyses itself.",
6786
- files: [],
6787
- product_context_refs: [
6788
- "Mission",
6789
- "Domain Vocabulary",
6790
- "In-Scope Capabilities"
6791
- ]
6792
- },
6793
- {
6794
- id: 2,
6795
- prompt: "Profile a startup called Lumen Events. Their current company page lists a 150-person team but a TechCrunch article from six months ago said they were at 80 people. Handle the conflict.",
6796
- expected_output: "The `company:research` issue body captures the conflict up-front under a dedicated conflict-resolution note. The research notes file annotates the live company page as a T1 living source and the TechCrunch article as a T3 secondary source. Conflict resolution follows the documented hierarchy: T1 wins on headcount (a fast-decay claim), so the current-state profile records 150 employees. The profile adds an inline note flagging that the T3 source is six months old and may simply be stale. Sources section lists each citation with tier, access date or publish date, and URL.",
6797
- files: [],
6798
- product_context_refs: ["Domain Vocabulary"]
6799
- },
6800
- {
6801
- id: 3,
6802
- prompt: "/profile-company Acme Registration \u2014 we already have a profile for them but it's nine months old. Refresh it.",
6803
- expected_output: "The pipeline routes through the refresh phase (not a fresh profile). It reads the existing profile slug and refuses to create a second profile under a new slug. When the existing profile is younger than the configured staleness threshold and `force: true` is not set, the refresh phase exits early and appends a revision-history row noting the review. When the profile is past cadence (nine months qualifies for most fast-decay fields), the refresh updates fast-decay claims in place (headcount, leadership, pricing, product features) while preserving stable history, and appends a revision-history row citing what changed and which sources were re-checked. No new profile file is created.",
6804
- files: [],
6805
- product_context_refs: ["Domain Vocabulary"]
6806
- }
6807
- ]
6808
- },
6809
- null,
6810
- 2
6811
- );
6812
- var PROFILE_COMPANY_REFERENCE_FILES = [
6813
- {
6814
- path: "evals/evals.json",
6815
- content: PROFILE_COMPANY_EVALS_JSON
6816
- }
6817
- ];
6818
- function buildProfileCompanySkill(paths) {
6950
+ function buildProfileCompanyEvalsJson(issueDefaults) {
6951
+ const research = labelsForPhase(issueDefaults, "company:research");
6952
+ return JSON.stringify(
6953
+ {
6954
+ skill_name: "profile-company",
6955
+ evals: [
6956
+ {
6957
+ id: 1,
6958
+ prompt: "/profile-company Acme Registration \u2014 they're a mid-market B2B event platform we ran into at a trade show last month. framing: competitive analysis for our self-service registration feature.",
6959
+ expected_output: `A \`company:research\` issue is created with \`type:company-profile\`, \`priority:${research.priority}\`, and \`status:${research.status}\`. The issue body carries the company name, an inferred or stated type (likely \`competitor\` given the framing), the framing text, and any supplied overrides. Phase 1 produces a research-notes file under the project's notes directory with sources annotated by tier (T1/T2/T3/T4) and date. Phase 2 opens a \`company:draft\` issue and may additionally open \`people:research\` issues for notable leaders surfaced and \`software:research\` issues for adjacent product mentions. The skill does not author person profiles, software profiles, or comparative analyses itself.`,
6960
+ files: [],
6961
+ product_context_refs: [
6962
+ "Mission",
6963
+ "Domain Vocabulary",
6964
+ "In-Scope Capabilities"
6965
+ ]
6966
+ },
6967
+ {
6968
+ id: 2,
6969
+ prompt: "Profile a startup called Lumen Events. Their current company page lists a 150-person team but a TechCrunch article from six months ago said they were at 80 people. Handle the conflict.",
6970
+ expected_output: "The `company:research` issue body captures the conflict up-front under a dedicated conflict-resolution note. The research notes file annotates the live company page as a T1 living source and the TechCrunch article as a T3 secondary source. Conflict resolution follows the documented hierarchy: T1 wins on headcount (a fast-decay claim), so the current-state profile records 150 employees. The profile adds an inline note flagging that the T3 source is six months old and may simply be stale. Sources section lists each citation with tier, access date or publish date, and URL.",
6971
+ files: [],
6972
+ product_context_refs: ["Domain Vocabulary"]
6973
+ },
6974
+ {
6975
+ id: 3,
6976
+ prompt: "/profile-company Acme Registration \u2014 we already have a profile for them but it's nine months old. Refresh it.",
6977
+ expected_output: "The pipeline routes through the refresh phase (not a fresh profile). It reads the existing profile slug and refuses to create a second profile under a new slug. When the existing profile is younger than the configured staleness threshold and `force: true` is not set, the refresh phase exits early and appends a revision-history row noting the review. When the profile is past cadence (nine months qualifies for most fast-decay fields), the refresh updates fast-decay claims in place (headcount, leadership, pricing, product features) while preserving stable history, and appends a revision-history row citing what changed and which sources were re-checked. No new profile file is created.",
6978
+ files: [],
6979
+ product_context_refs: ["Domain Vocabulary"]
6980
+ }
6981
+ ]
6982
+ },
6983
+ null,
6984
+ 2
6985
+ );
6986
+ }
6987
+ function buildProfileCompanyReferenceFiles(issueDefaults) {
6988
+ return [
6989
+ {
6990
+ path: "evals/evals.json",
6991
+ content: buildProfileCompanyEvalsJson(issueDefaults)
6992
+ }
6993
+ ];
6994
+ }
6995
+ function buildProfileCompanySkill(paths, issueDefaults) {
6819
6996
  return {
6820
6997
  name: "profile-company",
6821
6998
  description: "Kick off a company-profile pipeline. Creates a company:research issue for the given company and dispatches Phase 1 (Research) in the company-profile-analyst agent.",
@@ -6824,7 +7001,7 @@ function buildProfileCompanySkill(paths) {
6824
7001
  context: "fork",
6825
7002
  agent: "company-profile-analyst",
6826
7003
  platforms: { cursor: { exclude: true } },
6827
- referenceFiles: PROFILE_COMPANY_REFERENCE_FILES,
7004
+ referenceFiles: buildProfileCompanyReferenceFiles(issueDefaults),
6828
7005
  instructions: [
6829
7006
  "# Profile Company",
6830
7007
  "",
@@ -6855,7 +7032,7 @@ function buildProfileCompanySkill(paths) {
6855
7032
  "## Steps",
6856
7033
  "",
6857
7034
  "1. Create a `company:research` issue with `type:company-profile`,",
6858
- " `priority:medium`, and `status:ready`. Body must include the",
7035
+ ` \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:research").status}\`. Body must include the`,
6859
7036
  " company name, selected type, framing, and any overrides.",
6860
7037
  "2. Execute Phase 1 (Research) of the company-profile-analyst agent.",
6861
7038
  "3. Phase 1 creates the `company:draft` issue. Phase 2 may create a",
@@ -6879,7 +7056,7 @@ function buildProfileCompanySkill(paths) {
6879
7056
  ].join("\n")
6880
7057
  };
6881
7058
  }
6882
- function buildMatchCompanySkill(paths) {
7059
+ function buildMatchCompanySkill(paths, issueDefaults) {
6883
7060
  return {
6884
7061
  name: "match-company",
6885
7062
  description: "Kick off a company-profile match (enrichment) cycle. Creates a company:match issue for an existing profile and dispatches Phase 4 (Match) in the company-profile-analyst agent. Match enriches the profile with business-model, segment, and size context from existing docs \u2014 no web searches.",
@@ -6929,7 +7106,7 @@ function buildMatchCompanySkill(paths) {
6929
7106
  "## Steps",
6930
7107
  "",
6931
7108
  "1. Create a `company:match` issue with `type:company-profile`,",
6932
- " `priority:medium`, and `status:ready`. Body must include the",
7109
+ ` \`priority:${labelsForPhase(issueDefaults, "company:match").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:match").status}\`. Body must include the`,
6933
7110
  " profile path and any overrides.",
6934
7111
  "2. Execute Phase 4 (Match) of the company-profile-analyst agent.",
6935
7112
  "",
@@ -6944,7 +7121,7 @@ function buildMatchCompanySkill(paths) {
6944
7121
  ].join("\n")
6945
7122
  };
6946
7123
  }
6947
- function buildRefreshCompanySkill(paths) {
7124
+ function buildRefreshCompanySkill(paths, issueDefaults) {
6948
7125
  return {
6949
7126
  name: "refresh-company",
6950
7127
  description: "Kick off a company-profile refresh cycle. Creates a company:refresh issue for an existing profile and dispatches Phase 5 (Refresh) in the company-profile-analyst agent. Refresh re-verifies the profile with 4\u20136 targeted web searches and updates it in place. Respects a configurable staleness threshold so profiles younger than the threshold exit early.",
@@ -7002,7 +7179,7 @@ function buildRefreshCompanySkill(paths) {
7002
7179
  "## Steps",
7003
7180
  "",
7004
7181
  "1. Create a `company:refresh` issue with `type:company-profile`,",
7005
- " `priority:medium`, and `status:ready`. Body must include the",
7182
+ ` \`priority:${labelsForPhase(issueDefaults, "company:refresh").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:refresh").status}\`. Body must include the`,
7006
7183
  " profile path and any overrides.",
7007
7184
  "2. Execute Phase 5 (Refresh) of the company-profile-analyst agent.",
7008
7185
  "",
@@ -7018,7 +7195,7 @@ function buildRefreshCompanySkill(paths) {
7018
7195
  ].join("\n")
7019
7196
  };
7020
7197
  }
7021
- function buildAnalyzeSegmentSkill(paths) {
7198
+ function buildAnalyzeSegmentSkill(paths, issueDefaults) {
7022
7199
  return {
7023
7200
  name: "analyze-segment",
7024
7201
  description: "Kick off a segment-level competitive-analysis cycle. Creates a company:analyze issue for the target segment and dispatches Phase 6 (Analyze) in the company-profile-analyst agent. Analyze synthesizes every profile in the segment into one competitive-analysis document. Blocks on open company:draft issues for the segment.",
@@ -7075,7 +7252,7 @@ function buildAnalyzeSegmentSkill(paths) {
7075
7252
  "## Steps",
7076
7253
  "",
7077
7254
  "1. Create a `company:analyze` issue with `type:company-profile`,",
7078
- " `priority:medium`, and `status:ready`. Body must include the",
7255
+ ` \`priority:${labelsForPhase(issueDefaults, "company:analyze").priority}\`, and \`status:${labelsForPhase(issueDefaults, "company:analyze").status}\`. Body must include the`,
7079
7256
  " segment slug and any overrides.",
7080
7257
  "2. Execute Phase 6 (Analyze) of the company-profile-analyst agent.",
7081
7258
  "",
@@ -7092,7 +7269,7 @@ function buildAnalyzeSegmentSkill(paths) {
7092
7269
  ].join("\n")
7093
7270
  };
7094
7271
  }
7095
- function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS) {
7272
+ function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
7096
7273
  return {
7097
7274
  name: "company-profile",
7098
7275
  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.",
@@ -7145,12 +7322,12 @@ function buildCompanyProfileBundle(paths = DEFAULT_AGENT_PATHS) {
7145
7322
  }
7146
7323
  ],
7147
7324
  skills: [
7148
- buildProfileCompanySkill(paths),
7149
- buildMatchCompanySkill(paths),
7150
- buildRefreshCompanySkill(paths),
7151
- buildAnalyzeSegmentSkill(paths)
7325
+ buildProfileCompanySkill(paths, issueDefaults),
7326
+ buildMatchCompanySkill(paths, issueDefaults),
7327
+ buildRefreshCompanySkill(paths, issueDefaults),
7328
+ buildAnalyzeSegmentSkill(paths, issueDefaults)
7152
7329
  ],
7153
- subAgents: [buildCompanyProfileAnalystSubAgent(paths)],
7330
+ subAgents: [buildCompanyProfileAnalystSubAgent(paths, issueDefaults)],
7154
7331
  labels: [
7155
7332
  {
7156
7333
  name: "type:company-profile",
@@ -7200,8 +7377,6 @@ archetype: <ARCHETYPE_SLUG>
7200
7377
  segment: <SEGMENT_SLUG>
7201
7378
  ---
7202
7379
 
7203
- # <Customer Archetype Name>
7204
-
7205
7380
  | Field | Value |
7206
7381
  |-------|-------|
7207
7382
  | **Archetype** | <short noun phrase identifying the archetype> |
@@ -7332,7 +7507,8 @@ var CUSTOMER_PROFILE_REFERENCE_FILES = [
7332
7507
  content: TEMPLATE_CUSTOMER_PROFILE
7333
7508
  }
7334
7509
  ];
7335
- function buildCustomerProfileAnalystSubAgent(paths) {
7510
+ function buildCustomerProfileAnalystSubAgent(paths, issueDefaults) {
7511
+ void issueDefaults;
7336
7512
  return {
7337
7513
  name: "customer-profile-analyst",
7338
7514
  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.",
@@ -7567,8 +7743,6 @@ function buildCustomerProfileAnalystSubAgent(paths) {
7567
7743
  " scope: <SCOPE_SLUG>",
7568
7744
  " ---",
7569
7745
  "",
7570
- " # Customer Discovery: <Scope>",
7571
- "",
7572
7746
  " ## Scope Context",
7573
7747
  " - **Scope:** <SCOPE_SLUG>",
7574
7748
  " - **Sources scanned:** <counts by source type>",
@@ -7714,8 +7888,6 @@ function buildCustomerProfileAnalystSubAgent(paths) {
7714
7888
  " archetype: <ARCHETYPE_SLUG>",
7715
7889
  " ---",
7716
7890
  "",
7717
- " # Competitors: <Archetype Name>",
7718
- "",
7719
7891
  " ## Market Overview",
7720
7892
  " <Brief overview of the competitive landscape this archetype",
7721
7893
  " evaluates.>",
@@ -7919,7 +8091,7 @@ function buildCustomerProfileAnalystSubAgent(paths) {
7919
8091
  ].join("\n")
7920
8092
  };
7921
8093
  }
7922
- function buildDiscoverCustomersSkill(paths) {
8094
+ function buildDiscoverCustomersSkill(paths, issueDefaults) {
7923
8095
  return {
7924
8096
  name: "discover-customers",
7925
8097
  description: "Kick off the discover phase of a customer-research campaign. Creates a customer:discover issue for the supplied scope (industry, segment, or the consuming project as a whole) and dispatches Phase 1 of the customer-profile-analyst, which scans existing documentation for archetype candidates, writes a discovery report, and creates downstream customer:profile issues.",
@@ -7961,7 +8133,7 @@ function buildDiscoverCustomersSkill(paths) {
7961
8133
  "## Steps",
7962
8134
  "",
7963
8135
  "1. Create a `customer:discover` issue with `type:customer-profile`,",
7964
- " `priority:medium`, and `status:ready`. The body must include the",
8136
+ ` \`priority:${labelsForPhase(issueDefaults, "customer:discover").priority}\`, and \`status:${labelsForPhase(issueDefaults, "customer:discover").status}\`. The body must include the`,
7965
8137
  " scope slug and any known archetypes to include or exclude.",
7966
8138
  "2. Execute Phase 1 (Discover) of the customer-profile-analyst agent.",
7967
8139
  "3. Phase 1 writes the discovery report and creates one",
@@ -7976,7 +8148,7 @@ function buildDiscoverCustomersSkill(paths) {
7976
8148
  ].join("\n")
7977
8149
  };
7978
8150
  }
7979
- function buildProfileCustomerSkill(paths) {
8151
+ function buildProfileCustomerSkill(paths, issueDefaults) {
7980
8152
  return {
7981
8153
  name: "profile-customer",
7982
8154
  description: "Kick off the profile phase for one customer archetype. Creates a customer:profile issue for the supplied archetype and dispatches Phase 2 of the customer-profile-analyst, which populates the archetype page with segment, goals, jobs-to-be-done, constraints, buying process, technology landscape, and regulatory applicability using the ship-with customer-profile-page template.",
@@ -8036,7 +8208,7 @@ function buildProfileCustomerSkill(paths) {
8036
8208
  "## Steps",
8037
8209
  "",
8038
8210
  "1. Create a `customer:profile` issue with `type:customer-profile`,",
8039
- " `priority:medium`, and `status:ready`. The body must include the",
8211
+ ` \`priority:${labelsForPhase(issueDefaults, "customer:profile").priority}\`, and \`status:${labelsForPhase(issueDefaults, "customer:profile").status}\`. The body must include the`,
8040
8212
  " archetype slug and (optionally) the segment slug.",
8041
8213
  "2. Execute Phase 2 (Profile) of the customer-profile-analyst agent.",
8042
8214
  " The agent runs 4\u20138 targeted web searches and populates the",
@@ -8056,7 +8228,7 @@ function buildProfileCustomerSkill(paths) {
8056
8228
  ].join("\n")
8057
8229
  };
8058
8230
  }
8059
- function buildAnalyzeCustomerCompetitorsSkill(paths) {
8231
+ function buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults) {
8060
8232
  return {
8061
8233
  name: "analyze-customer-competitors",
8062
8234
  description: "Kick off the competitors phase for one customer archetype. Creates a customer:competitors issue for the supplied archetype and dispatches Phase 3 of the customer-profile-analyst, which maps rows from the shared software-profile feature matrix to the archetype's needs, identifies unmet needs, and hands off each unmet need as a req:scan seed to the requirements-analyst bundle.",
@@ -8110,8 +8282,8 @@ function buildAnalyzeCustomerCompetitorsSkill(paths) {
8110
8282
  "## Steps",
8111
8283
  "",
8112
8284
  "1. Create a `customer:competitors` issue with",
8113
- " `type:customer-profile`, `priority:medium`, and",
8114
- " `status:ready` (or `status:blocked` when still dependent on a",
8285
+ ` \`type:customer-profile\`, \`priority:${labelsForPhase(issueDefaults, "customer:competitors").priority}\`, and`,
8286
+ ` \`status:${labelsForPhase(issueDefaults, "customer:competitors").status}\` (or \`status:blocked\` when still dependent on a`,
8115
8287
  " Phase 2 profile issue). Body must include the archetype page",
8116
8288
  " path.",
8117
8289
  "2. Execute Phase 3 (Competitors) of the customer-profile-analyst",
@@ -8136,7 +8308,7 @@ function buildAnalyzeCustomerCompetitorsSkill(paths) {
8136
8308
  ].join("\n")
8137
8309
  };
8138
8310
  }
8139
- function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS) {
8311
+ function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
8140
8312
  return {
8141
8313
  name: "customer-profile",
8142
8314
  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.",
@@ -8207,11 +8379,11 @@ function buildCustomerProfileBundle(paths = DEFAULT_AGENT_PATHS) {
8207
8379
  }
8208
8380
  ],
8209
8381
  skills: [
8210
- buildDiscoverCustomersSkill(paths),
8211
- buildProfileCustomerSkill(paths),
8212
- buildAnalyzeCustomerCompetitorsSkill(paths)
8382
+ buildDiscoverCustomersSkill(paths, issueDefaults),
8383
+ buildProfileCustomerSkill(paths, issueDefaults),
8384
+ buildAnalyzeCustomerCompetitorsSkill(paths, issueDefaults)
8213
8385
  ],
8214
- subAgents: [buildCustomerProfileAnalystSubAgent(paths)],
8386
+ subAgents: [buildCustomerProfileAnalystSubAgent(paths, issueDefaults)],
8215
8387
  labels: [
8216
8388
  {
8217
8389
  name: "type:customer-profile",
@@ -9417,7 +9589,7 @@ var githubWorkflowBundle = {
9417
9589
  };
9418
9590
 
9419
9591
  // src/agent/bundles/industry-discovery.ts
9420
- function buildIndustryDiscoveryAnalystSubAgent(paths) {
9592
+ function buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults) {
9421
9593
  return {
9422
9594
  name: "industry-discovery-analyst",
9423
9595
  description: "Discovers candidate industry verticals, scores each against a configurable capability/fit rubric, and creates planning issues for verticals that clear the threshold. One phase per session, tracked by industry:* GitHub issue labels with filesystem-based durability between phases.",
@@ -9622,8 +9794,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
9622
9794
  " candidate_count: <N>",
9623
9795
  " ---",
9624
9796
  "",
9625
- " # Industry Candidates: <scope>",
9626
- "",
9627
9797
  " ## Scope",
9628
9798
  " <verbatim scope statement from the issue>",
9629
9799
  "",
@@ -9684,8 +9854,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
9684
9854
  " threshold: <0.0\u20131.0>",
9685
9855
  " ---",
9686
9856
  "",
9687
- " # Industry Evaluation: <scope>",
9688
- "",
9689
9857
  " ## Fit Rubric",
9690
9858
  " <verbatim rubric table, including weights and threshold>",
9691
9859
  "",
@@ -9742,8 +9910,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
9742
9910
  " evaluation_source: <EVALUATIONS_DIR>/<DISCOVERY_SLUG>.evaluation.md",
9743
9911
  " ---",
9744
9912
  "",
9745
- " # Industry Plan: <scope>",
9746
- "",
9747
9913
  " ## Cleared Verticals",
9748
9914
  " | Vertical | Score | Downstream Issue |",
9749
9915
  " |----------|-------|------------------|",
@@ -9761,8 +9927,8 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
9761
9927
  "4. **Create one `research:scope` issue per cleared vertical.** This",
9762
9928
  " assumes the `research-pipeline` bundle is enabled in the consuming",
9763
9929
  " project. Each downstream issue should:",
9764
- " - Carry `type:research`, `research:scope`, `priority:medium`, and",
9765
- " `status:ready` labels",
9930
+ ` - Carry \`type:research\`, \`research:scope\`, \`priority:${labelsForPhase(issueDefaults, "research:scope").priority}\`, and`,
9931
+ ` \`status:${labelsForPhase(issueDefaults, "research:scope").status}\` labels`,
9766
9932
  " - Include the research question framed for the vertical (what the",
9767
9933
  " downstream research needs to answer)",
9768
9934
  " - Cite the evaluation row that justified advancing the vertical",
@@ -9813,7 +9979,7 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
9813
9979
  ].join("\n")
9814
9980
  };
9815
9981
  }
9816
- function buildDiscoverIndustriesSkill(paths) {
9982
+ function buildDiscoverIndustriesSkill(paths, issueDefaults) {
9817
9983
  return {
9818
9984
  name: "discover-industries",
9819
9985
  description: "Kick off an industry-discovery pipeline. Creates an industry:discover issue carrying the discovery scope and dispatches Phase 1 (Discover) in the industry-discovery-analyst agent.",
@@ -9855,7 +10021,7 @@ function buildDiscoverIndustriesSkill(paths) {
9855
10021
  "## Steps",
9856
10022
  "",
9857
10023
  "1. Create an `industry:discover` issue with `type:industry-discovery`,",
9858
- " `priority:medium`, and `status:ready`. Body must include the",
10024
+ ` \`priority:${labelsForPhase(issueDefaults, "industry:discover").priority}\`, and \`status:${labelsForPhase(issueDefaults, "industry:discover").status}\`. Body must include the`,
9859
10025
  " verbatim scope, authorized sources, and any overrides.",
9860
10026
  "2. Execute Phase 1 (Discover) of the industry-discovery-analyst",
9861
10027
  " agent.",
@@ -9876,7 +10042,7 @@ function buildDiscoverIndustriesSkill(paths) {
9876
10042
  ].join("\n")
9877
10043
  };
9878
10044
  }
9879
- function buildIndustryDiscoveryBundle(paths = DEFAULT_AGENT_PATHS) {
10045
+ function buildIndustryDiscoveryBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
9880
10046
  return {
9881
10047
  name: "industry-discovery",
9882
10048
  description: "Industry-vertical discovery pipeline: discover candidates, evaluate against a fit rubric, plan downstream research. Enabled by default; domain-neutral; filesystem-durable between phases.",
@@ -9910,8 +10076,8 @@ function buildIndustryDiscoveryBundle(paths = DEFAULT_AGENT_PATHS) {
9910
10076
  tags: ["workflow"]
9911
10077
  }
9912
10078
  ],
9913
- skills: [buildDiscoverIndustriesSkill(paths)],
9914
- subAgents: [buildIndustryDiscoveryAnalystSubAgent(paths)],
10079
+ skills: [buildDiscoverIndustriesSkill(paths, issueDefaults)],
10080
+ subAgents: [buildIndustryDiscoveryAnalystSubAgent(paths, issueDefaults)],
9915
10081
  labels: [
9916
10082
  {
9917
10083
  name: "type:industry-discovery",
@@ -10196,8 +10362,6 @@ function buildMaintenanceAuditSubAgent(paths) {
10196
10362
  " status: complete",
10197
10363
  " ---",
10198
10364
  "",
10199
- " # Maintenance Audit: <AUDIT_SLUG>",
10200
- "",
10201
10365
  " ## Scope",
10202
10366
  " - **Docs root:** `<DOCS_ROOT>`",
10203
10367
  " - **Checks run:** <list of check categories>",
@@ -10319,8 +10483,6 @@ function buildMaintenanceAuditSubAgent(paths) {
10319
10483
  " status: complete",
10320
10484
  " ---",
10321
10485
  "",
10322
- " # Maintenance Fix: <AUDIT_SLUG>",
10323
- "",
10324
10486
  " ## Source Audit Report",
10325
10487
  " <link to the Phase 1 audit report>",
10326
10488
  "",
@@ -10421,8 +10583,6 @@ function buildMaintenanceAuditSubAgent(paths) {
10421
10583
  " status: complete",
10422
10584
  " ---",
10423
10585
  "",
10424
- " # Maintenance Verify: <AUDIT_SLUG>",
10425
- "",
10426
10586
  " ## Source Reports",
10427
10587
  " - Scan report: <link>",
10428
10588
  " - Fix report: <link>",
@@ -13096,80 +13256,81 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
13096
13256
  "}",
13097
13257
  "",
13098
13258
  "cmd_eligible() {",
13099
- " local issues",
13100
- ' issues=$(gh issue list --label "status:ready" --state open \\',
13101
- ' --search "sort:created-asc" \\',
13102
- ' --json number,title,body,labels --limit 50 2>/dev/null || echo "[]")',
13103
- "",
13104
- " local count",
13105
- ` count=$(echo "$issues" | jq 'length')`,
13106
- ' if [[ "$count" -eq 0 ]]; then',
13107
- ' echo "NO_READY_ISSUES"',
13108
- " return 0",
13109
- " fi",
13259
+ " # Bucketed scan: walk priority levels critical \u2192 high \u2192 medium \u2192 low \u2192",
13260
+ " # trivial, fetching one bucket at a time. The first bucket with at",
13261
+ " # least one survivor (after the Depends-on filter) short-circuits the",
13262
+ " # loop \u2014 lower-priority buckets are never queried in the common case.",
13263
+ " # This guarantees that every higher-priority issue is visible even",
13264
+ " # when the global ready backlog exceeds 50, at the cost of up to one",
13265
+ " # extra `gh issue list` call per empty bucket above the first hit.",
13266
+ " local level",
13267
+ " for level in critical high medium low trivial; do",
13268
+ " local issues",
13269
+ ' issues=$(gh issue list --label "status:ready" --label "priority:${level}" --state open \\',
13270
+ ' --search "sort:created-asc" \\',
13271
+ ' --json number,title,body,labels --limit 50 2>/dev/null || echo "[]")',
13272
+ "",
13273
+ " local count",
13274
+ ` count=$(echo "$issues" | jq 'length')`,
13275
+ ' if [[ "$count" -eq 0 ]]; then',
13276
+ " continue",
13277
+ " fi",
13110
13278
  "",
13111
- " local issue_data",
13112
- ` issue_data=$(echo "$issues" | jq -r '`,
13113
- " .[] |",
13114
- ' (.body | split("\\n") | map(select(test("Depends on:"; "i"))) | .[0] // "") as $dep_line |',
13115
- ' (.labels | map(.name) | join(",")) as $label_str |',
13116
- ' (.labels | map(.name) | map(select(startswith("type:"))) | .[0] // "") as $type_label |',
13117
- ' "\\(.number)\\t\\(.title)\\t\\($dep_line)\\t\\($label_str)\\t\\($type_label)"',
13118
- " ')",
13279
+ " local issue_data",
13280
+ ` issue_data=$(echo "$issues" | jq -r '`,
13281
+ " .[] |",
13282
+ ' (.body | split("\\n") | map(select(test("Depends on:"; "i"))) | .[0] // "") as $dep_line |',
13283
+ ' (.labels | map(.name) | map(select(startswith("type:"))) | .[0] // "") as $type_label |',
13284
+ ' "\\(.number)\\t\\(.title)\\t\\($dep_line)\\t\\($type_label)"',
13285
+ " ')",
13119
13286
  "",
13120
- ' local results=""',
13121
- " while IFS=$'\\t' read -r num title dep_line labels_str type_label; do",
13122
- ' [[ -z "$num" ]] && continue',
13287
+ ' local results=""',
13288
+ " while IFS=$'\\t' read -r num title dep_line type_label; do",
13289
+ ' [[ -z "$num" ]] && continue',
13123
13290
  "",
13124
- ' local deps=""',
13125
- ' if [[ -n "$dep_line" ]]; then',
13126
- ' deps=$(parse_deps "$dep_line")',
13127
- " fi",
13291
+ ' local deps=""',
13292
+ ' if [[ -n "$dep_line" ]]; then',
13293
+ ' deps=$(parse_deps "$dep_line")',
13294
+ " fi",
13128
13295
  "",
13129
- " # Check if any dep is still open.",
13130
- " local has_open_dep=false",
13131
- ' local open_deps=""',
13132
- ' if [[ -n "${deps// /}" ]]; then',
13133
- " for dep in $deps; do",
13134
- ' if ! is_closed "$dep"; then',
13135
- " has_open_dep=true",
13136
- ' open_deps="${open_deps}#${dep} "',
13137
- " fi",
13138
- " done",
13139
- " fi",
13296
+ " # Check if any dep is still open.",
13297
+ " local has_open_dep=false",
13298
+ ' local open_deps=""',
13299
+ ' if [[ -n "${deps// /}" ]]; then',
13300
+ " for dep in $deps; do",
13301
+ ' if ! is_closed "$dep"; then',
13302
+ " has_open_dep=true",
13303
+ ' open_deps="${open_deps}#${dep} "',
13304
+ " fi",
13305
+ " done",
13306
+ " fi",
13140
13307
  "",
13141
- " if $has_open_dep; then",
13142
- ' echo "SKIP #${num} \u2014 dep ${open_deps% } still open"',
13143
- " continue",
13144
- " fi",
13308
+ " if $has_open_dep; then",
13309
+ ' echo "SKIP #${num} \u2014 dep ${open_deps% } still open"',
13310
+ " continue",
13311
+ " fi",
13145
13312
  "",
13146
- " # 5-level priority sort key.",
13147
- " local priority_key=2",
13148
- ' local priority="medium"',
13149
- ' case "$labels_str" in',
13150
- ' *priority:critical*) priority_key=0; priority="critical" ;;',
13151
- ' *priority:high*) priority_key=1; priority="high" ;;',
13152
- ' *priority:medium*) priority_key=2; priority="medium" ;;',
13153
- ' *priority:low*) priority_key=3; priority="low" ;;',
13154
- ' *priority:trivial*) priority_key=4; priority="trivial" ;;',
13155
- " esac",
13313
+ " # Funnel-tier sort key (0-4; 0 dispatches first within a bucket).",
13314
+ ' local type_value="${type_label#type:}"',
13315
+ " local tier_key",
13316
+ ' tier_key=$(tier_of "$type_value")',
13156
13317
  "",
13157
- " # Funnel-tier sort key (0-4; 0 dispatches first on priority tie).",
13158
- ' local type_value="${type_label#type:}"',
13159
- " local tier_key",
13160
- ' tier_key=$(tier_of "$type_value")',
13318
+ ' local label_info=""',
13319
+ ' [[ -n "$type_label" ]] && label_info=" ${type_label}"',
13161
13320
  "",
13162
- ' local label_info=""',
13163
- ' [[ -n "$type_label" ]] && label_info=" ${type_label}"',
13321
+ ' results="${results}${tier_key}\\t${num}\\tPICK #${num} priority:${level} tier:${tier_key}${label_info} \\"${title}\\"\\n"',
13322
+ ' done <<< "$issue_data"',
13164
13323
  "",
13165
- ' results="${results}${priority_key}\\t${tier_key}\\t${num}\\tPICK #${num} priority:${priority} tier:${tier_key}${label_info} \\"${title}\\"\\n"',
13166
- ' done <<< "$issue_data"',
13324
+ " # Within this bucket: sort by funnel tier asc \u2192 issue number asc",
13325
+ " # (FIFO). If any PICK lines survived the Depends-on filter, emit",
13326
+ " # them and short-circuit before querying lower-priority buckets.",
13327
+ ' if [[ -n "$results" ]]; then',
13328
+ ` printf '%b' "$results" | sort -t$'\\t' -k1,1n -k2,2n | cut -f3`,
13329
+ " return 0",
13330
+ " fi",
13331
+ " done",
13167
13332
  "",
13168
- " # Sort by priority (asc, lower priority_key wins), then funnel tier",
13169
- " # (asc, lower tier wins on priority tie), then issue number (FIFO).",
13170
- ' if [[ -n "$results" ]]; then',
13171
- ` printf '%b' "$results" | sort -t$'\\t' -k1,1n -k2,2n -k3,3n | cut -f4`,
13172
- " fi",
13333
+ ' echo "NO_READY_ISSUES"',
13173
13334
  "}",
13174
13335
  "",
13175
13336
  "cmd_stale() {",
@@ -13604,9 +13765,25 @@ var orchestratorSubAgent = {
13604
13765
  ".claude/procedures/check-blocked.sh eligible",
13605
13766
  "```",
13606
13767
  "",
13768
+ "The script walks the priority buckets **critical \u2192 high \u2192 medium \u2192 low",
13769
+ "\u2192 trivial** in order, querying one bucket at a time and short-circuiting",
13770
+ "on the first non-empty bucket whose survivors clear the `Depends on:`",
13771
+ "filter. Each bucket is fetched with",
13772
+ '`gh issue list --label "status:ready" --label "priority:<level>" --limit 50`,',
13773
+ "so every higher-priority issue is visible even when the global ready",
13774
+ "backlog exceeds 50 \u2014 a `priority:critical` filing can never be hidden",
13775
+ "behind 50 older medium/low issues. The cost in the common case (the",
13776
+ "first bucket the script queries is non-empty) is **one `gh issue list`",
13777
+ "call**, identical to the previous single-fetch implementation; the",
13778
+ "worst case is five calls when every higher-priority bucket is empty",
13779
+ "or fully dep-blocked. Per-priority bucket size is still capped at 50",
13780
+ "issues \u2014 see the **Orchestrator Conventions** section in `CLAUDE.md`.",
13781
+ "",
13607
13782
  "The script emits `PICK` lines sorted by **priority desc \u2192 funnel tier asc",
13608
- "\u2192 issue number asc**. Each line carries both `priority:<level>` and",
13609
- "`tier:<n>` so the sort is legible at a glance:",
13783
+ "\u2192 issue number asc** (priority order is enforced by the bucket walk;",
13784
+ "the in-bucket sort handles funnel tier and FIFO). Each line carries",
13785
+ "both `priority:<level>` and `tier:<n>` so the sort is legible at a",
13786
+ "glance:",
13610
13787
  "",
13611
13788
  "```",
13612
13789
  'PICK #42 priority:high tier:1 type:research "FHIR extension analysis"',
@@ -14237,7 +14414,7 @@ var ORCHESTRATOR_CONVENTIONS_PREAMBLE = [
14237
14414
  "- The orchestrator **never** implements code, creates branches, pushes commits, **or merges PRs** \u2014 it triages issues, picks the next work item, and delegates implementation to other sub-agents. Approved-PR merging is owned by the `pr-reviewer` sub-agent (invoked via `/review-pr` / `/review-prs`).",
14238
14415
  "- All triage queries use `.claude/procedures/check-blocked.sh` for token efficiency",
14239
14416
  "- The queue scan reads only `priority:*` and `status:*` labels \u2014 type-routing (which typed agent handles a given `type:*` label) is the `issue-worker`'s concern, not the orchestrator's. The orchestrator's funnel-tier sort is a tie-breaker on `priority:*`, not a routing decision.",
14240
- "- Priority order: critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number",
14417
+ "- Priority order: critical > high > medium > low > trivial, then **funnel tier asc** (lower tier wins ties), then FIFO by issue number. Phase E's queue scan walks each priority bucket in turn (one `gh issue list` call per bucket, **capped at 50 issues per bucket**) and short-circuits on the first bucket whose survivors clear the `Depends on:` filter, so every higher-priority issue is visible even when the global ready backlog is much larger than 50.",
14241
14418
  "- Stale thresholds: 72h for in-progress, 168h for blocked",
14242
14419
  "- Flagged issues get `status:needs-attention` \u2014 they are not auto-reset",
14243
14420
  "",
@@ -14324,7 +14501,7 @@ var orchestratorBundle = {
14324
14501
  };
14325
14502
 
14326
14503
  // src/agent/bundles/people-profile.ts
14327
- function buildPeopleProfileAnalystSubAgent(paths) {
14504
+ function buildPeopleProfileAnalystSubAgent(paths, issueDefaults) {
14328
14505
  return {
14329
14506
  name: "people-profile-analyst",
14330
14507
  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.",
@@ -14589,8 +14766,6 @@ function buildPeopleProfileAnalystSubAgent(paths) {
14589
14766
  " parent_issue: <N>",
14590
14767
  " ---",
14591
14768
  "",
14592
- " # Research Notes: <person name>",
14593
- "",
14594
14769
  " ## Framing",
14595
14770
  " <why this person was requested and what to learn>",
14596
14771
  "",
@@ -14652,8 +14827,6 @@ function buildPeopleProfileAnalystSubAgent(paths) {
14652
14827
  " notes: <NOTES_DIR>/<PERSON_SLUG>.notes.md",
14653
14828
  " ---",
14654
14829
  "",
14655
- " # <person name>",
14656
- "",
14657
14830
  " ## Summary",
14658
14831
  " <2\u20134 sentence elevator description: who they are, what they do,",
14659
14832
  " why they matter to this project>",
@@ -14765,8 +14938,8 @@ function buildPeopleProfileAnalystSubAgent(paths) {
14765
14938
  "",
14766
14939
  " - `type:company-profile`",
14767
14940
  " - `company:research`",
14768
- " - `priority:medium`",
14769
- " - `status:ready`",
14941
+ ` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
14942
+ ` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
14770
14943
  "",
14771
14944
  " The issue body must include:",
14772
14945
  " - A **discovery source** line naming this person profile",
@@ -14785,8 +14958,8 @@ function buildPeopleProfileAnalystSubAgent(paths) {
14785
14958
  "",
14786
14959
  " - `type:software-profile`",
14787
14960
  " - `software:research`",
14788
- " - `priority:medium`",
14789
- " - `status:ready`",
14961
+ ` - \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\``,
14962
+ ` - \`status:${labelsForPhase(issueDefaults, "software:research").status}\``,
14790
14963
  "",
14791
14964
  " The issue body must include:",
14792
14965
  " - A **discovery source** line naming this person profile",
@@ -15005,7 +15178,7 @@ function buildPeopleProfileAnalystSubAgent(paths) {
15005
15178
  ].join("\n")
15006
15179
  };
15007
15180
  }
15008
- function buildProfilePersonSkill(paths) {
15181
+ function buildProfilePersonSkill(paths, issueDefaults) {
15009
15182
  return {
15010
15183
  name: "profile-person",
15011
15184
  description: "Kick off a people-profile pipeline. Creates a people:research issue for the given person and dispatches Phase 1 (Research) in the people-profile-analyst agent. Phase 3 (Followup) enqueues downstream `company:research` and `software:research` issues for unprofiled, genuinely-relevant entities surfaced in the profile.",
@@ -15056,7 +15229,7 @@ function buildProfilePersonSkill(paths) {
15056
15229
  "## Steps",
15057
15230
  "",
15058
15231
  "1. Create a `people:research` issue with `type:people-profile`,",
15059
- " `priority:medium`, and `status:ready`. Body must include the",
15232
+ ` \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "people:research").status}\`. Body must include the`,
15060
15233
  " person's name, selected role, primary company, framing, and any",
15061
15234
  " overrides.",
15062
15235
  "2. Execute Phase 1 (Research) of the people-profile-analyst agent.",
@@ -15081,7 +15254,7 @@ function buildProfilePersonSkill(paths) {
15081
15254
  ].join("\n")
15082
15255
  };
15083
15256
  }
15084
- function buildRefreshPersonSkill(paths) {
15257
+ function buildRefreshPersonSkill(paths, issueDefaults) {
15085
15258
  return {
15086
15259
  name: "refresh-person",
15087
15260
  description: "Kick off a people-profile refresh cycle. Creates a people:refresh issue for an existing profile and dispatches Phase 4 (Refresh) in the people-profile-analyst agent. Refresh re-verifies the profile's narrow delta set (role, employer, primary public channel) with 3\u20135 targeted web searches and updates it in place. Respects a configurable staleness threshold so profiles younger than the threshold exit early.",
@@ -15148,7 +15321,7 @@ function buildRefreshPersonSkill(paths) {
15148
15321
  "## Steps",
15149
15322
  "",
15150
15323
  "1. Create a `people:refresh` issue with `type:people-profile`,",
15151
- " `priority:medium`, and `status:ready`. Body must include the",
15324
+ ` \`priority:${labelsForPhase(issueDefaults, "people:refresh").priority}\`, and \`status:${labelsForPhase(issueDefaults, "people:refresh").status}\`. Body must include the`,
15152
15325
  " profile path and any overrides.",
15153
15326
  "2. Execute Phase 4 (Refresh) of the people-profile-analyst agent.",
15154
15327
  "",
@@ -15162,7 +15335,7 @@ function buildRefreshPersonSkill(paths) {
15162
15335
  ].join("\n")
15163
15336
  };
15164
15337
  }
15165
- function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS) {
15338
+ function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
15166
15339
  return {
15167
15340
  name: "people-profile",
15168
15341
  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.",
@@ -15206,8 +15379,11 @@ function buildPeopleProfileBundle(paths = DEFAULT_AGENT_PATHS) {
15206
15379
  tags: ["workflow"]
15207
15380
  }
15208
15381
  ],
15209
- skills: [buildProfilePersonSkill(paths), buildRefreshPersonSkill(paths)],
15210
- subAgents: [buildPeopleProfileAnalystSubAgent(paths)],
15382
+ skills: [
15383
+ buildProfilePersonSkill(paths, issueDefaults),
15384
+ buildRefreshPersonSkill(paths, issueDefaults)
15385
+ ],
15386
+ subAgents: [buildPeopleProfileAnalystSubAgent(paths, issueDefaults)],
15211
15387
  labels: [
15212
15388
  {
15213
15389
  name: "type:people-profile",
@@ -17237,8 +17413,6 @@ jurisdiction: <federal | state | provincial | international | local>
17237
17413
  industry: <industry-slug or 'platform'>
17238
17414
  ---
17239
17415
 
17240
- # <Regulation Name>
17241
-
17242
17416
  | Field | Value |
17243
17417
  |-------|-------|
17244
17418
  | **Official name** | <full legal name> |
@@ -17374,7 +17548,8 @@ var REGULATORY_RESEARCH_REFERENCE_FILES = [
17374
17548
  content: TEMPLATE_REGULATION
17375
17549
  }
17376
17550
  ];
17377
- function buildRegulatoryResearchAnalystSubAgent(paths) {
17551
+ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
17552
+ void issueDefaults;
17378
17553
  return {
17379
17554
  name: "regulatory-research-analyst",
17380
17555
  description: "Authors jurisdictional compliance research through a 3-phase pipeline (scan \u2192 research \u2192 impact). Enumerates applicable regulations by jurisdiction and business activity, researches each in depth, and produces an impact analysis that hands off actionable obligations to the requirements-analyst as req:scan seeds in the SEC category. One phase per session, tracked by regulatory:* GitHub issue labels with filesystem-based durability between phases.",
@@ -17609,8 +17784,6 @@ function buildRegulatoryResearchAnalystSubAgent(paths) {
17609
17784
  " scope: <SCOPE_SLUG>",
17610
17785
  " ---",
17611
17786
  "",
17612
- " # Regulatory Scan: <Scope>",
17613
- "",
17614
17787
  " ## Scope Context",
17615
17788
  " - **Scope type:** <industry / jurisdiction / platform>",
17616
17789
  " - **Scope identifier:** <SCOPE_SLUG>",
@@ -17661,7 +17834,12 @@ function buildRegulatoryResearchAnalystSubAgent(paths) {
17661
17834
  "",
17662
17835
  "7. **Create or update the scope index page** at",
17663
17836
  " `<SCOPE_INDEX_PAGE>` so downstream regulations link back to a",
17664
- " coherent landing page for the scope.",
17837
+ " coherent landing page for the scope. Follow the",
17838
+ " `stub-index-convention` rule: the body must carry a 1\u20132",
17839
+ " paragraph contextual summary plus a grouped, linked listing of",
17840
+ " every regulation in the scope (e.g. by jurisdiction). No body",
17841
+ " `# Heading` \u2014 the frontmatter `title:` already renders as the",
17842
+ " page H1.",
17665
17843
  "",
17666
17844
  "8. **Commit and push** the scan report and the scope index page.",
17667
17845
  " Close the scan issue.",
@@ -17931,7 +18109,7 @@ function buildRegulatoryResearchAnalystSubAgent(paths) {
17931
18109
  ].join("\n")
17932
18110
  };
17933
18111
  }
17934
- function buildScanRegulatoryLandscapeSkill(paths) {
18112
+ function buildScanRegulatoryLandscapeSkill(paths, issueDefaults) {
17935
18113
  return {
17936
18114
  name: "scan-regulatory-landscape",
17937
18115
  description: "Kick off the scan phase of a regulatory-research campaign. Creates a regulatory:scan issue for the supplied scope (industry, jurisdiction, or platform) and dispatches Phase 1 of the regulatory-research-analyst, which writes a scan report and creates downstream regulatory:research issues.",
@@ -17978,7 +18156,7 @@ function buildScanRegulatoryLandscapeSkill(paths) {
17978
18156
  "## Steps",
17979
18157
  "",
17980
18158
  "1. Create a `regulatory:scan` issue with `type:regulatory-research`,",
17981
- " `priority:medium`, and `status:ready`. The body must include the",
18159
+ ` \`priority:${labelsForPhase(issueDefaults, "regulatory:scan").priority}\`, and \`status:${labelsForPhase(issueDefaults, "regulatory:scan").status}\`. The body must include the`,
17982
18160
  " scope slug, the scope type, and any known regulations to include",
17983
18161
  " or exclude.",
17984
18162
  "2. Execute Phase 1 (Scan) of the regulatory-research-analyst agent.",
@@ -17995,7 +18173,7 @@ function buildScanRegulatoryLandscapeSkill(paths) {
17995
18173
  ].join("\n")
17996
18174
  };
17997
18175
  }
17998
- function buildResearchRegulationSkill(paths) {
18176
+ function buildResearchRegulationSkill(paths, issueDefaults) {
17999
18177
  return {
18000
18178
  name: "research-regulation",
18001
18179
  description: "Kick off the research phase for one regulation. Creates a regulatory:research issue for the supplied scope and regulation and dispatches Phase 2 of the regulatory-research-analyst, which populates the regulation page with scope, triggers, key requirements, jurisdiction variations, enforcement, and penalties using the ship-with regulation-page template.",
@@ -18054,8 +18232,8 @@ function buildResearchRegulationSkill(paths) {
18054
18232
  "## Steps",
18055
18233
  "",
18056
18234
  "1. Create a `regulatory:research` issue with",
18057
- " `type:regulatory-research`, `priority:medium`, and",
18058
- " `status:ready`. The body must include the scope slug and the",
18235
+ ` \`type:regulatory-research\`, \`priority:${labelsForPhase(issueDefaults, "regulatory:research").priority}\`, and`,
18236
+ ` \`status:${labelsForPhase(issueDefaults, "regulatory:research").status}\`. The body must include the scope slug and the`,
18059
18237
  " regulation slug.",
18060
18238
  "2. Execute Phase 2 (Research) of the regulatory-research-analyst",
18061
18239
  " agent. The agent runs 6\u201312 targeted web searches and populates",
@@ -18073,7 +18251,7 @@ function buildResearchRegulationSkill(paths) {
18073
18251
  ].join("\n")
18074
18252
  };
18075
18253
  }
18076
- function buildImpactRegulationSkill(paths) {
18254
+ function buildImpactRegulationSkill(paths, issueDefaults) {
18077
18255
  return {
18078
18256
  name: "impact-regulation",
18079
18257
  description: "Kick off the impact phase for one regulation. Creates a regulatory:impact issue for the supplied regulation and dispatches Phase 3 of the regulatory-research-analyst, which assesses product impact, documents capability gaps, and hands off each actionable obligation as a req:scan seed in the SEC (security & compliance) category for the requirements-analyst bundle to consume.",
@@ -18120,8 +18298,8 @@ function buildImpactRegulationSkill(paths) {
18120
18298
  "## Steps",
18121
18299
  "",
18122
18300
  "1. Create a `regulatory:impact` issue with",
18123
- " `type:regulatory-research`, `priority:medium`, and",
18124
- " `status:ready` (or `status:blocked` when still dependent on a",
18301
+ ` \`type:regulatory-research\`, \`priority:${labelsForPhase(issueDefaults, "regulatory:impact").priority}\`, and`,
18302
+ ` \`status:${labelsForPhase(issueDefaults, "regulatory:impact").status}\` (or \`status:blocked\` when still dependent on a`,
18125
18303
  " Phase 2 research issue). Body must include the regulation page",
18126
18304
  " path.",
18127
18305
  "2. Execute Phase 3 (Impact) of the regulatory-research-analyst",
@@ -18142,7 +18320,7 @@ function buildImpactRegulationSkill(paths) {
18142
18320
  ].join("\n")
18143
18321
  };
18144
18322
  }
18145
- function buildRegulatoryResearchBundle(paths = DEFAULT_AGENT_PATHS) {
18323
+ function buildRegulatoryResearchBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
18146
18324
  return {
18147
18325
  name: "regulatory-research",
18148
18326
  description: "Regulatory compliance research pipeline: scan, research, impact. 3 phases with regulatory:* phase labels. Enumerates jurisdictional regulations by industry and activity, researches each in depth with specific section citations, and hands off actionable obligations to the requirements-analyst bundle as req:scan seeds that become SEC (security & compliance) requirements. Enabled by default; domain-neutral; documents obligations without interpreting them; filesystem-durable between phases.",
@@ -18209,11 +18387,11 @@ function buildRegulatoryResearchBundle(paths = DEFAULT_AGENT_PATHS) {
18209
18387
  }
18210
18388
  ],
18211
18389
  skills: [
18212
- buildScanRegulatoryLandscapeSkill(paths),
18213
- buildResearchRegulationSkill(paths),
18214
- buildImpactRegulationSkill(paths)
18390
+ buildScanRegulatoryLandscapeSkill(paths, issueDefaults),
18391
+ buildResearchRegulationSkill(paths, issueDefaults),
18392
+ buildImpactRegulationSkill(paths, issueDefaults)
18215
18393
  ],
18216
- subAgents: [buildRegulatoryResearchAnalystSubAgent(paths)],
18394
+ subAgents: [buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults)],
18217
18395
  labels: [
18218
18396
  {
18219
18397
  name: "type:regulatory-research",
@@ -18519,8 +18697,6 @@ function buildRequirementsAnalystSubAgent(paths) {
18519
18697
  " status: complete",
18520
18698
  " ---",
18521
18699
  "",
18522
- " # Requirements Scan: <scope>",
18523
- "",
18524
18700
  " ## Source Documents Reviewed",
18525
18701
  " - <path> \u2014 <brief description>",
18526
18702
  "",
@@ -18656,42 +18832,32 @@ function buildRequirementsAnalystSubAgent(paths) {
18656
18832
  " directory under `<REQUIREMENTS_ROOT>/<category>/` to find the next",
18657
18833
  " available `NNN` for each proposed requirement.",
18658
18834
  "",
18659
- "5. **Create requirement issues.** For each proposal:",
18835
+ "5. **Create requirement issues.** For each proposal, file a",
18836
+ " `req:write` issue using the canonical recipe documented in",
18837
+ " `## Template: req:write` of",
18838
+ " `docs/src/content/docs/agents/issue-templates.md`.",
18660
18839
  "",
18661
18840
  " All `type:requirement` issues default to `priority:medium` (override",
18662
18841
  " only if the proposal's priority was explicitly High or Low). Each",
18663
18842
  " issue must also carry the `req:write` phase label plus the matching",
18664
18843
  " `tier:*` label so the downstream `requirements-writer` bundle picks",
18665
- " it up with the correct tier.",
18844
+ " it up with the correct tier. Concretely, the label list includes",
18845
+ ' `--label "type:requirement"`, `--label "req:write"`,',
18846
+ ' `--label "tier:<tier-slug>"`, `--label "status:ready"`, and',
18847
+ ' `--label "priority:medium"`.',
18666
18848
  "",
18667
- " ```bash",
18668
- " gh issue create \\",
18669
- ' --title "docs(<category>): <PREFIX>-<NNN> \u2014 <title>" \\',
18670
- ' --label "type:requirement" --label "req:write" --label "tier:<tier-slug>" --label "status:ready" --label "priority:medium" \\',
18671
- ' --body "## Objective',
18672
- " Write <PREFIX>-<NNN> \u2014 <title>.",
18849
+ " The body must carry the three writer-required fields in an",
18850
+ " `## Objective` block, written as bold-prefixed lines so the",
18851
+ " writer's intake parser can pull them out:",
18673
18852
  "",
18674
- " **Category:** <BR/FR/NFR/TR/ADR/SEC/DR/INT/OPS/UX/MT>",
18675
- " **Tier:** <platform/industry/customer-workflow/consumer-app>",
18676
- " **Output Path:** <REQUIREMENTS_ROOT>/<category-dir>/<PREFIX>-<NNN>-<slug>.md",
18853
+ " - `**Category:** <BR/FR/NFR/TR/ADR/SEC/DR/INT/OPS/UX/MT>`",
18854
+ " - `**Tier:** <platform/industry/customer-workflow/consumer-app>`",
18855
+ " - `**Output Path:** <REQUIREMENTS_ROOT>/<category-dir>/<PREFIX>-<NNN>-<slug>.md`",
18677
18856
  "",
18678
- " ## Context",
18679
- " - **Gap identified by:** requirements scan of <source>",
18680
- " - **Proposals file:** <RESEARCH_REQUIREMENTS_ROOT>/req-proposals-<scope>-<date>.md",
18681
- "",
18682
- " ## Inputs / Read",
18683
- " - **Depends on:** (none)",
18684
- " - **Read:** <RESEARCH_REQUIREMENTS_ROOT>/req-proposals-<scope>-<date>.md, <source docs>",
18685
- "",
18686
- " ## Acceptance Criteria",
18687
- " - [ ] Requirement document follows <category> template",
18688
- " - [ ] Traceability links to source BCM/competitive/product doc",
18689
- " - [ ] Registry index updated",
18690
- " - [ ] Decision authority rules followed (direct write vs. proposed)",
18691
- "",
18692
- " ## Scope Size",
18693
- ' small"',
18694
- " ```",
18857
+ " Then under `## Inputs / Read`, list the proposals file",
18858
+ " (`<RESEARCH_REQUIREMENTS_ROOT>/req-proposals-<scope>-<date>.md`)",
18859
+ " and any source documents the writer should consult (BCM model",
18860
+ " docs, competitive analyses, product docs).",
18695
18861
  "",
18696
18862
  " When one of Category / Tier / Output Path could not be derived",
18697
18863
  " from the proposal (for example, the proposal omitted the Tier",
@@ -18867,8 +19033,6 @@ var TEMPLATE_BR = `---
18867
19033
  title: "BR-NNN: [Business Requirement Title]"
18868
19034
  ---
18869
19035
 
18870
- # BR-NNN: [Business Requirement Title]
18871
-
18872
19036
  ## Metadata
18873
19037
 
18874
19038
  | Field | Value |
@@ -18976,8 +19140,6 @@ var TEMPLATE_FR = `---
18976
19140
  title: "FR-NNN: [Functional Requirement Title]"
18977
19141
  ---
18978
19142
 
18979
- # FR-NNN: [Functional Requirement Title]
18980
-
18981
19143
  ## Metadata
18982
19144
 
18983
19145
  | Field | Value |
@@ -19117,8 +19279,6 @@ var TEMPLATE_NFR = `---
19117
19279
  title: "NFR-NNN: [Non-Functional Requirement Title]"
19118
19280
  ---
19119
19281
 
19120
- # NFR-NNN: [Non-Functional Requirement Title]
19121
-
19122
19282
  ## Metadata
19123
19283
 
19124
19284
  | Field | Value |
@@ -19219,8 +19379,6 @@ var TEMPLATE_TR = `---
19219
19379
  title: "TR-NNN: [Technical Requirement Title]"
19220
19380
  ---
19221
19381
 
19222
- # TR-NNN: [Technical Requirement Title]
19223
-
19224
19382
  ## Metadata
19225
19383
 
19226
19384
  | Field | Value |
@@ -19372,8 +19530,6 @@ var TEMPLATE_ADR = `---
19372
19530
  title: "ADR-NNN: [Decision Title]"
19373
19531
  ---
19374
19532
 
19375
- # ADR-NNN: [Decision Title]
19376
-
19377
19533
  ## Metadata
19378
19534
 
19379
19535
  | Field | Value |
@@ -19502,8 +19658,6 @@ var TEMPLATE_SEC = `---
19502
19658
  title: "SEC-NNN: [Security Requirement Title]"
19503
19659
  ---
19504
19660
 
19505
- # SEC-NNN: [Security Requirement Title]
19506
-
19507
19661
  ## Metadata
19508
19662
 
19509
19663
  | Field | Value |
@@ -19615,8 +19769,6 @@ var TEMPLATE_DR = `---
19615
19769
  title: "DR-NNN: [Data Requirement Title]"
19616
19770
  ---
19617
19771
 
19618
- # DR-NNN: [Data Requirement Title]
19619
-
19620
19772
  ## Metadata
19621
19773
 
19622
19774
  | Field | Value |
@@ -19731,8 +19883,6 @@ var TEMPLATE_INT = `---
19731
19883
  title: "INT-NNN: [Integration Requirement Title]"
19732
19884
  ---
19733
19885
 
19734
- # INT-NNN: [Integration Requirement Title]
19735
-
19736
19886
  ## Metadata
19737
19887
 
19738
19888
  | Field | Value |
@@ -19864,8 +20014,6 @@ var TEMPLATE_OPS = `---
19864
20014
  title: "OPS-NNN: [Operational Requirement Title]"
19865
20015
  ---
19866
20016
 
19867
- # OPS-NNN: [Operational Requirement Title]
19868
-
19869
20017
  ## Metadata
19870
20018
 
19871
20019
  | Field | Value |
@@ -19980,8 +20128,6 @@ var TEMPLATE_UX = `---
19980
20128
  title: "UX-NNN: [UX Requirement Title]"
19981
20129
  ---
19982
20130
 
19983
- # UX-NNN: [UX Requirement Title]
19984
-
19985
20131
  ## Metadata
19986
20132
 
19987
20133
  | Field | Value |
@@ -20098,8 +20244,6 @@ var TEMPLATE_MT = `---
20098
20244
  title: "MT-NNN: [Multi-Tenancy Requirement Title]"
20099
20245
  ---
20100
20246
 
20101
- # MT-NNN: [Multi-Tenancy Requirement Title]
20102
-
20103
20247
  ## Metadata
20104
20248
 
20105
20249
  | Field | Value |
@@ -20252,8 +20396,6 @@ var TEMPLATE_REQUIREMENTS_README = `---
20252
20396
  title: "[Project Name] \u2014 Requirements Documentation"
20253
20397
  ---
20254
20398
 
20255
- # [Project Name] \u2014 Requirements Documentation
20256
-
20257
20399
  This directory contains the structured requirements taxonomy for [Project Name]. It covers the full lifecycle from business intent through operational concerns, providing traceability between strategic goals and implementation work.
20258
20400
 
20259
20401
  ## Taxonomy Overview
@@ -21010,12 +21152,9 @@ function buildRequirementsWriterSubAgent(paths) {
21010
21152
  "tier: platform",
21011
21153
  "---",
21012
21154
  "",
21013
- "# FR-001: User Registration",
21014
- "",
21015
21155
  "...",
21016
21156
  "```",
21017
21157
  "",
21018
- "The `title` value must match the document's `# Heading` line.",
21019
21158
  "Titles containing colons must be wrapped in double quotes. The",
21020
21159
  "`tier` field must be one of `platform`, `industry`,",
21021
21160
  "`customer-workflow`, or `consumer-app` (use whatever tier slugs the",
@@ -23079,8 +23218,6 @@ function buildResearchAnalystSubAgent(paths) {
23079
23218
  " slice_count: <N>",
23080
23219
  " ---",
23081
23220
  "",
23082
- " # Research Scope: <question>",
23083
- "",
23084
23221
  " ## Question",
23085
23222
  " <verbatim question from the issue>",
23086
23223
  "",
@@ -23150,8 +23287,6 @@ function buildResearchAnalystSubAgent(paths) {
23150
23287
  " parent_issue: <N>",
23151
23288
  " ---",
23152
23289
  "",
23153
- " # Slice NN: <title>",
23154
- "",
23155
23290
  " ## Question",
23156
23291
  " <the slice-level question>",
23157
23292
  "",
@@ -23216,8 +23351,6 @@ function buildResearchAnalystSubAgent(paths) {
23216
23351
  " slices_read: <count>",
23217
23352
  " ---",
23218
23353
  "",
23219
- " # Verification Report: <question>",
23220
- "",
23221
23354
  " ## Acceptance Criteria Coverage",
23222
23355
  " - [x] <criterion> \u2014 covered by slice(s) <NN, NN>",
23223
23356
  " - [ ] <criterion> \u2014 **not covered**; gap noted in deliverable",
@@ -23560,7 +23693,7 @@ var slackBundle = {
23560
23693
  };
23561
23694
 
23562
23695
  // src/agent/bundles/software-profile.ts
23563
- function buildSoftwareProfileAnalystSubAgent(paths) {
23696
+ function buildSoftwareProfileAnalystSubAgent(paths, issueDefaults) {
23564
23697
  return {
23565
23698
  name: "software-profile-analyst",
23566
23699
  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.",
@@ -23825,8 +23958,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
23825
23958
  " parent_issue: <N>",
23826
23959
  " ---",
23827
23960
  "",
23828
- " # Research Notes: <product name>",
23829
- "",
23830
23961
  " ## Framing",
23831
23962
  " <why this product was requested and what to learn>",
23832
23963
  "",
@@ -23887,8 +24018,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
23887
24018
  " notes: <NOTES_DIR>/<PRODUCT_SLUG>.notes.md",
23888
24019
  " ---",
23889
24020
  "",
23890
- " # <product name>",
23891
- "",
23892
24021
  " ## Summary",
23893
24022
  " <2\u20134 sentence elevator description: what it does, who it's for>",
23894
24023
  "",
@@ -23973,8 +24102,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
23973
24102
  "updated: YYYY-MM-DD",
23974
24103
  "---",
23975
24104
  "",
23976
- "# Software Feature Matrix",
23977
- "",
23978
24105
  "| product | feature | <segment-1> | <segment-2> | ... | score | source |",
23979
24106
  "|---------|---------|-------------|-------------|-----|-------|--------|",
23980
24107
  "| <slug> | <feature-name> | 0\u20131 | 0\u20131 | ... | <weighted-sum> | <profile-path> |",
@@ -24105,8 +24232,8 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
24105
24232
  "",
24106
24233
  " - `type:bcm-document`",
24107
24234
  " - `bcm:outline`",
24108
- " - `priority:medium`",
24109
- " - `status:ready`",
24235
+ ` - \`priority:${labelsForPhase(issueDefaults, "bcm:outline").priority}\``,
24236
+ ` - \`status:${labelsForPhase(issueDefaults, "bcm:outline").status}\``,
24110
24237
  "",
24111
24238
  " The issue body must include:",
24112
24239
  " - A **discovery source** line naming this software profile",
@@ -24174,7 +24301,7 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
24174
24301
  " `Follow-up Candidates > Adjacent products to evaluate`. Each new",
24175
24302
  " issue follows the same 4-phase pipeline \u2014 start it in the",
24176
24303
  " `software:research` phase with `type:software-profile`,",
24177
- " `priority:medium`, and `status:ready`.",
24304
+ ` \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:research").status}\`.`,
24178
24305
  "",
24179
24306
  "3. **Enqueue a `company:research` issue for the vendor company** if",
24180
24307
  " no matching profile already exists under `<COMPANY_PROFILES_DIR>/`.",
@@ -24185,8 +24312,8 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
24185
24312
  "",
24186
24313
  " - `type:company-profile`",
24187
24314
  " - `company:research`",
24188
- " - `priority:medium`",
24189
- " - `status:ready`",
24315
+ ` - \`priority:${labelsForPhase(issueDefaults, "company:research").priority}\``,
24316
+ ` - \`status:${labelsForPhase(issueDefaults, "company:research").status}\``,
24190
24317
  "",
24191
24318
  " The issue body must include:",
24192
24319
  " - A **discovery source** line naming this software profile",
@@ -24204,8 +24331,8 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
24204
24331
  "",
24205
24332
  " - `type:people-profile`",
24206
24333
  " - `people:research`",
24207
- " - `priority:medium`",
24208
- " - `status:ready`",
24334
+ ` - \`priority:${labelsForPhase(issueDefaults, "people:research").priority}\``,
24335
+ ` - \`status:${labelsForPhase(issueDefaults, "people:research").status}\``,
24209
24336
  "",
24210
24337
  " The issue body must include:",
24211
24338
  " - A **discovery source** line naming this software profile",
@@ -24348,7 +24475,7 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
24348
24475
  ].join("\n")
24349
24476
  };
24350
24477
  }
24351
- function buildProfileSoftwareSkill(paths) {
24478
+ function buildProfileSoftwareSkill(paths, issueDefaults) {
24352
24479
  return {
24353
24480
  name: "profile-software",
24354
24481
  description: "Kick off a software-profile pipeline. Creates a software:research issue for the given product and dispatches Phase 1 (Research) in the software-profile-analyst agent. Phase 4 (Map) writes a BCM capability mapping onto the profile and enqueues `bcm:outline` issues for unmapped features. Phase 5 (Followup) enqueues downstream `company:research` and `people:research` issues for the vendor company and primary-attribution founders/leaders surfaced in the profile.",
@@ -24395,7 +24522,7 @@ function buildProfileSoftwareSkill(paths) {
24395
24522
  "## Steps",
24396
24523
  "",
24397
24524
  "1. Create a `software:research` issue with `type:software-profile`,",
24398
- " `priority:medium`, and `status:ready`. Body must include the",
24525
+ ` \`priority:${labelsForPhase(issueDefaults, "software:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:research").status}\`. Body must include the`,
24399
24526
  " product name, selected type, framing, and any overrides.",
24400
24527
  "2. Execute Phase 1 (Research) of the software-profile-analyst",
24401
24528
  " agent.",
@@ -24428,7 +24555,7 @@ function buildProfileSoftwareSkill(paths) {
24428
24555
  ].join("\n")
24429
24556
  };
24430
24557
  }
24431
- function buildMapSoftwareSkill(paths) {
24558
+ function buildMapSoftwareSkill(paths, issueDefaults) {
24432
24559
  return {
24433
24560
  name: "map-software",
24434
24561
  description: "Kick off a standalone software-capability mapping session. Creates a software:map issue for an already-profiled product and dispatches Phase 4 (Map) in the software-profile-analyst agent. Produces the `## Capability Mapping` section on the profile and enqueues `bcm:outline` issues for unmapped features above the configured threshold.",
@@ -24483,7 +24610,7 @@ function buildMapSoftwareSkill(paths) {
24483
24610
  "## Steps",
24484
24611
  "",
24485
24612
  "1. Create a `software:map` issue with `type:software-profile`,",
24486
- " `priority:medium`, and `status:ready`. Body must include the",
24613
+ ` \`priority:${labelsForPhase(issueDefaults, "software:map").priority}\`, and \`status:${labelsForPhase(issueDefaults, "software:map").status}\`. Body must include the`,
24487
24614
  " profile path and any overrides.",
24488
24615
  "2. Execute Phase 4 (Map) of the software-profile-analyst agent.",
24489
24616
  "3. Phase 4 writes the `## Capability Mapping` section, enqueues",
@@ -24505,7 +24632,7 @@ function buildMapSoftwareSkill(paths) {
24505
24632
  ].join("\n")
24506
24633
  };
24507
24634
  }
24508
- function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS) {
24635
+ function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
24509
24636
  return {
24510
24637
  name: "software-profile",
24511
24638
  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.",
@@ -24558,8 +24685,11 @@ function buildSoftwareProfileBundle(paths = DEFAULT_AGENT_PATHS) {
24558
24685
  tags: ["workflow"]
24559
24686
  }
24560
24687
  ],
24561
- skills: [buildProfileSoftwareSkill(paths), buildMapSoftwareSkill(paths)],
24562
- subAgents: [buildSoftwareProfileAnalystSubAgent(paths)],
24688
+ skills: [
24689
+ buildProfileSoftwareSkill(paths, issueDefaults),
24690
+ buildMapSoftwareSkill(paths, issueDefaults)
24691
+ ],
24692
+ subAgents: [buildSoftwareProfileAnalystSubAgent(paths, issueDefaults)],
24563
24693
  labels: [
24564
24694
  {
24565
24695
  name: "type:software-profile",
@@ -24602,8 +24732,6 @@ title: "<Standard Name>"
24602
24732
  description: "Overview and cross-version comparison of <Standard Name>."
24603
24733
  ---
24604
24734
 
24605
- # <Standard Name>
24606
-
24607
24735
  | Field | Value |
24608
24736
  |-------|-------|
24609
24737
  | **Standard** | <standard name> |
@@ -24719,7 +24847,8 @@ var STANDARDS_COMPARE_REFERENCE_FILES = [
24719
24847
  content: TEMPLATE_COMPARISON_GRID
24720
24848
  }
24721
24849
  ];
24722
- function buildStandardsResearchAnalystSubAgent(paths) {
24850
+ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
24851
+ void issueDefaults;
24723
24852
  return {
24724
24853
  name: "standards-research-analyst",
24725
24854
  description: "Authors version-aware interoperability standards research through a 5-phase pipeline (scope \u2192 research \u2192 compare \u2192 extension \u2192 organizations). Researches one standard version per session, synthesizes cross-version comparisons, profiles extensions/profiles/implementation guides, and profiles standards-body organizations. Hands off canonical company and people profiles to the company-profile and people-profile bundles via company:research and people:research issues. One phase per session, tracked by standards:* GitHub issue labels with filesystem-based durability between phases.",
@@ -24921,8 +25050,6 @@ function buildStandardsResearchAnalystSubAgent(paths) {
24921
25050
  " standard: <STANDARD_SLUG>",
24922
25051
  " ---",
24923
25052
  "",
24924
- " # Query Plan: <Standard Name>",
24925
- "",
24926
25053
  " ## Context",
24927
25054
  " <1\u20132 paragraphs on why this standard matters to the consuming",
24928
25055
  " project and what gaps this research campaign fills.>",
@@ -25124,7 +25251,14 @@ function buildStandardsResearchAnalystSubAgent(paths) {
25124
25251
  " the overview page, then populate each section from the version",
25125
25252
  " pages.",
25126
25253
  "",
25127
- "4. **Write the overview page** at `<OVERVIEW_PAGE>`. Fill:",
25254
+ "4. **Write the overview page** at `<OVERVIEW_PAGE>`. Follow",
25255
+ " the `stub-index-convention` rule: the body opens with a",
25256
+ " 1\u20132 paragraph contextual summary of the standard and its",
25257
+ " versions, and the version pages, modules, and extensions",
25258
+ " sections below double as the grouped, linked listing of",
25259
+ " every child page in the standard's folder. No body",
25260
+ " `# Heading` \u2014 the frontmatter `title:` already renders as",
25261
+ " the page H1. Required sections to fill:",
25128
25262
  " - **Version Timeline** \u2014 publication dates, status, milestones",
25129
25263
  " - **Module / Resource Maturity Progression** \u2014 matrix with",
25130
25264
  " modules as rows and versions as columns, using the standard's",
@@ -25501,7 +25635,7 @@ function buildStandardsResearchAnalystSubAgent(paths) {
25501
25635
  ].join("\n")
25502
25636
  };
25503
25637
  }
25504
- function buildScopeStandardsResearchSkill(paths) {
25638
+ function buildScopeStandardsResearchSkill(paths, issueDefaults) {
25505
25639
  return {
25506
25640
  name: "scope-standards-research",
25507
25641
  description: "Kick off the scope phase of an interoperability-standards research campaign. Creates a standards:scope issue for the supplied standard and dispatches Phase 1 of the standards-research-analyst, which writes a query plan and creates downstream standards:research, standards:compare, and standards:organizations issues.",
@@ -25548,7 +25682,7 @@ function buildScopeStandardsResearchSkill(paths) {
25548
25682
  "## Steps",
25549
25683
  "",
25550
25684
  "1. Create a `standards:scope` issue with `type:standards-research`,",
25551
- " `priority:medium`, and `status:ready`. The body must include the",
25685
+ ` \`priority:${labelsForPhase(issueDefaults, "standards:scope").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:scope").status}\`. The body must include the`,
25552
25686
  " standard slug, the list of target versions (or a request to",
25553
25687
  " enumerate), and any known governance bodies.",
25554
25688
  "2. Execute Phase 1 (Scope) of the standards-research-analyst agent.",
@@ -25567,7 +25701,7 @@ function buildScopeStandardsResearchSkill(paths) {
25567
25701
  ].join("\n")
25568
25702
  };
25569
25703
  }
25570
- function buildResearchStandardSkill(paths) {
25704
+ function buildResearchStandardSkill(paths, issueDefaults) {
25571
25705
  return {
25572
25706
  name: "research-standard",
25573
25707
  description: "Kick off the research phase for one version of an interoperability standard. Creates a standards:research issue for the supplied standard and version and dispatches Phase 2 of the standards-research-analyst, which populates the version page with status, key changes, resources, adoption, and governance touch-points.",
@@ -25613,7 +25747,7 @@ function buildResearchStandardSkill(paths) {
25613
25747
  "## Steps",
25614
25748
  "",
25615
25749
  "1. Create a `standards:research` issue with",
25616
- " `type:standards-research`, `priority:medium`, and `status:ready`.",
25750
+ ` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:research").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:research").status}\`.`,
25617
25751
  " The body must include the standard slug and the version slug.",
25618
25752
  "2. Execute Phase 2 (Research) of the standards-research-analyst",
25619
25753
  " agent. The agent runs 6\u201310 targeted web searches and populates",
@@ -25632,7 +25766,7 @@ function buildResearchStandardSkill(paths) {
25632
25766
  ].join("\n")
25633
25767
  };
25634
25768
  }
25635
- function buildCompareStandardsSkill(paths) {
25769
+ function buildCompareStandardsSkill(paths, issueDefaults) {
25636
25770
  return {
25637
25771
  name: "compare-standards",
25638
25772
  description: "Kick off the compare phase across researched versions of an interoperability standard. Creates a standards:compare issue for the supplied standard and dispatches Phase 3 of the standards-research-analyst, which synthesizes the overview page using the ship-with comparison-grid template.",
@@ -25685,7 +25819,7 @@ function buildCompareStandardsSkill(paths) {
25685
25819
  "## Steps",
25686
25820
  "",
25687
25821
  "1. Create a `standards:compare` issue with",
25688
- " `type:standards-research`, `priority:medium`, and `status:ready`.",
25822
+ ` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:compare").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:compare").status}\`.`,
25689
25823
  " Body must include the standard slug and the list of version",
25690
25824
  " pages under comparison.",
25691
25825
  "2. Execute Phase 3 (Compare) of the standards-research-analyst",
@@ -25702,7 +25836,7 @@ function buildCompareStandardsSkill(paths) {
25702
25836
  ].join("\n")
25703
25837
  };
25704
25838
  }
25705
- function buildExtensionStandardSkill(paths) {
25839
+ function buildExtensionStandardSkill(paths, issueDefaults) {
25706
25840
  return {
25707
25841
  name: "extension-standard",
25708
25842
  description: "Kick off the extension phase for one domain entity against an interoperability standard. Creates a standards:extension issue for the supplied standard and domain entity and dispatches Phase 4 of the standards-research-analyst, which analyzes the gap and hands off a Proposed ADR to the requirements pipeline.",
@@ -25752,7 +25886,7 @@ function buildExtensionStandardSkill(paths) {
25752
25886
  "## Steps",
25753
25887
  "",
25754
25888
  "1. Create a `standards:extension` issue with",
25755
- " `type:standards-research`, `priority:medium`, and `status:ready`.",
25889
+ ` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:extension").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:extension").status}\`.`,
25756
25890
  " The body must include the standard slug, the entity slug, the",
25757
25891
  " closest resource, and a link to the source BCM or canvas",
25758
25892
  " document.",
@@ -25772,7 +25906,7 @@ function buildExtensionStandardSkill(paths) {
25772
25906
  ].join("\n")
25773
25907
  };
25774
25908
  }
25775
- function buildOrganizationsStandardSkill(paths) {
25909
+ function buildOrganizationsStandardSkill(paths, issueDefaults) {
25776
25910
  return {
25777
25911
  name: "organizations-standard",
25778
25912
  description: "Kick off the organizations phase for one standards-body organization. Creates a standards:organizations issue for the supplied standard and organization and dispatches Phase 5 of the standards-research-analyst, which writes a standards-organization page and hands off canonical company and people profiles to the company-profile and people-profile bundles.",
@@ -25818,7 +25952,7 @@ function buildOrganizationsStandardSkill(paths) {
25818
25952
  "## Steps",
25819
25953
  "",
25820
25954
  "1. Create a `standards:organizations` issue with",
25821
- " `type:standards-research`, `priority:medium`, and `status:ready`.",
25955
+ ` \`type:standards-research\`, \`priority:${labelsForPhase(issueDefaults, "standards:organizations").priority}\`, and \`status:${labelsForPhase(issueDefaults, "standards:organizations").status}\`.`,
25822
25956
  " Body must include the standard slug, the organization slug, and",
25823
25957
  " the organization's governance role.",
25824
25958
  "2. Execute Phase 5 (Organizations) of the",
@@ -25839,7 +25973,7 @@ function buildOrganizationsStandardSkill(paths) {
25839
25973
  ].join("\n")
25840
25974
  };
25841
25975
  }
25842
- function buildStandardsResearchBundle(paths = DEFAULT_AGENT_PATHS) {
25976
+ function buildStandardsResearchBundle(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
25843
25977
  return {
25844
25978
  name: "standards-research",
25845
25979
  description: "Interoperability-standards research pipeline: scope, research, compare, extension, organizations. 5 phases with standards:* phase labels. Version-aware research, cross-version comparison, extension/profile profiling, and standards-body organization profiling. Hands off canonical profiles to company-profile and people-profile via company:research and people:research issues, extension ADRs to requirements-writer via req:write, and domain-entity mappings to bcm-writer. Enabled by default; domain-neutral; filesystem-durable between phases.",
@@ -25905,13 +26039,13 @@ function buildStandardsResearchBundle(paths = DEFAULT_AGENT_PATHS) {
25905
26039
  }
25906
26040
  ],
25907
26041
  skills: [
25908
- buildScopeStandardsResearchSkill(paths),
25909
- buildResearchStandardSkill(paths),
25910
- buildCompareStandardsSkill(paths),
25911
- buildExtensionStandardSkill(paths),
25912
- buildOrganizationsStandardSkill(paths)
26042
+ buildScopeStandardsResearchSkill(paths, issueDefaults),
26043
+ buildResearchStandardSkill(paths, issueDefaults),
26044
+ buildCompareStandardsSkill(paths, issueDefaults),
26045
+ buildExtensionStandardSkill(paths, issueDefaults),
26046
+ buildOrganizationsStandardSkill(paths, issueDefaults)
25913
26047
  ],
25914
- subAgents: [buildStandardsResearchAnalystSubAgent(paths)],
26048
+ subAgents: [buildStandardsResearchAnalystSubAgent(paths, issueDefaults)],
25915
26049
  labels: [
25916
26050
  {
25917
26051
  name: "type:standards-research",
@@ -27135,7 +27269,7 @@ function renderPriorityRulesSection(rules) {
27135
27269
  }
27136
27270
 
27137
27271
  // src/agent/bundles/index.ts
27138
- function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS) {
27272
+ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS, issueDefaults = DEFAULT_RESOLVED_ISSUE_DEFAULTS) {
27139
27273
  return [
27140
27274
  buildBaseBundle(paths),
27141
27275
  upstreamConfigulatorDocsBundle,
@@ -27156,15 +27290,15 @@ function buildBuiltInBundles(paths = DEFAULT_AGENT_PATHS) {
27156
27290
  buildRequirementsWriterBundle(paths),
27157
27291
  buildRequirementsReviewerBundle(paths),
27158
27292
  buildResearchPipelineBundle(paths),
27159
- buildCompanyProfileBundle(paths),
27160
- buildCustomerProfileBundle(paths),
27161
- buildPeopleProfileBundle(paths),
27162
- buildSoftwareProfileBundle(paths),
27163
- buildIndustryDiscoveryBundle(paths),
27293
+ buildCompanyProfileBundle(paths, issueDefaults),
27294
+ buildCustomerProfileBundle(paths, issueDefaults),
27295
+ buildPeopleProfileBundle(paths, issueDefaults),
27296
+ buildSoftwareProfileBundle(paths, issueDefaults),
27297
+ buildIndustryDiscoveryBundle(paths, issueDefaults),
27164
27298
  buildBusinessModelsBundle(paths),
27165
27299
  buildBcmWriterBundle(paths),
27166
- buildStandardsResearchBundle(paths),
27167
- buildRegulatoryResearchBundle(paths),
27300
+ buildStandardsResearchBundle(paths, issueDefaults),
27301
+ buildRegulatoryResearchBundle(paths, issueDefaults),
27168
27302
  buildMaintenanceAuditBundle(paths),
27169
27303
  buildDocsSyncBundle(paths)
27170
27304
  ];
@@ -27203,6 +27337,152 @@ function prefix(rel, entry) {
27203
27337
  return path.posix.join(rel, entry);
27204
27338
  }
27205
27339
 
27340
+ // src/agent/renderers/cursor-renderer.ts
27341
+ var import_projen6 = require("projen");
27342
+ var import_textfile2 = require("projen/lib/textfile");
27343
+ var GENERATED_MARKER = "# ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~";
27344
+ var CursorRenderer = class _CursorRenderer {
27345
+ /**
27346
+ * Render all Cursor configuration files.
27347
+ */
27348
+ static render(component, rules, skills, subAgents, mcpServers, settings) {
27349
+ _CursorRenderer.renderRules(component, rules);
27350
+ _CursorRenderer.renderSkills(component, skills);
27351
+ _CursorRenderer.renderSubAgents(component, subAgents);
27352
+ _CursorRenderer.renderMcpServers(component, mcpServers);
27353
+ _CursorRenderer.renderHooks(component, settings);
27354
+ _CursorRenderer.renderIgnoreFiles(component, settings);
27355
+ }
27356
+ static renderRules(component, rules) {
27357
+ for (const rule of rules) {
27358
+ if (rule.platforms?.cursor?.exclude) continue;
27359
+ const lines = [];
27360
+ const description = rule.platforms?.cursor?.description ?? rule.description;
27361
+ const isAlways = rule.scope === AGENT_RULE_SCOPE.ALWAYS;
27362
+ lines.push("---");
27363
+ lines.push(`description: "${description}"`);
27364
+ lines.push(`alwaysApply: ${isAlways}`);
27365
+ if (!isAlways && rule.filePatterns && rule.filePatterns.length > 0) {
27366
+ lines.push(`path: ${JSON.stringify([...rule.filePatterns])}`);
27367
+ }
27368
+ lines.push("---");
27369
+ lines.push("");
27370
+ lines.push(...rule.content.split("\n"));
27371
+ new import_textfile2.TextFile(component, `.cursor/rules/${rule.name}.mdc`, { lines });
27372
+ }
27373
+ }
27374
+ static renderSkills(component, skills) {
27375
+ for (const skill of skills) {
27376
+ if (skill.platforms?.cursor?.exclude) continue;
27377
+ const lines = [];
27378
+ lines.push("---");
27379
+ lines.push(`name: "${skill.name}"`);
27380
+ lines.push(`description: "${skill.description}"`);
27381
+ if (skill.disableModelInvocation) {
27382
+ lines.push(`disable-model-invocation: true`);
27383
+ }
27384
+ if (skill.userInvocable === false) {
27385
+ lines.push(`user-invocable: false`);
27386
+ }
27387
+ if (skill.context) {
27388
+ lines.push(`context: "${skill.context}"`);
27389
+ }
27390
+ if (skill.agent) {
27391
+ lines.push(`agent: "${skill.agent}"`);
27392
+ }
27393
+ if (skill.shell) {
27394
+ lines.push(`shell: "${skill.shell}"`);
27395
+ }
27396
+ if (skill.allowedTools && skill.allowedTools.length > 0) {
27397
+ lines.push(`allowed-tools:`);
27398
+ for (const tool of skill.allowedTools) {
27399
+ lines.push(` - "${tool}"`);
27400
+ }
27401
+ }
27402
+ lines.push("---");
27403
+ lines.push("");
27404
+ lines.push(...skill.instructions.split("\n"));
27405
+ new import_textfile2.TextFile(component, `.cursor/skills/${skill.name}/SKILL.md`, {
27406
+ lines
27407
+ });
27408
+ if (skill.referenceFiles && skill.referenceFiles.length > 0) {
27409
+ for (const file of skill.referenceFiles) {
27410
+ new import_textfile2.TextFile(component, `.cursor/skills/${skill.name}/${file.path}`, {
27411
+ lines: file.content.split("\n")
27412
+ });
27413
+ }
27414
+ }
27415
+ }
27416
+ }
27417
+ static renderSubAgents(component, subAgents) {
27418
+ for (const agent of subAgents) {
27419
+ if (agent.platforms?.cursor?.exclude) continue;
27420
+ const lines = [];
27421
+ lines.push("---");
27422
+ lines.push(`name: ${agent.name}`);
27423
+ lines.push(`description: >-`);
27424
+ lines.push(` ${agent.description}`);
27425
+ if (agent.platforms?.cursor?.readonly) {
27426
+ lines.push(`readonly: true`);
27427
+ }
27428
+ if (agent.platforms?.cursor?.isBackground) {
27429
+ lines.push(`is_background: true`);
27430
+ }
27431
+ lines.push("---");
27432
+ lines.push("");
27433
+ lines.push(...agent.prompt.split("\n"));
27434
+ new import_textfile2.TextFile(component, `.cursor/agents/${agent.name}.md`, { lines });
27435
+ }
27436
+ }
27437
+ static renderMcpServers(component, mcpServers) {
27438
+ const serverNames = Object.keys(mcpServers);
27439
+ if (serverNames.length === 0) return;
27440
+ const obj = { mcpServers: {} };
27441
+ const servers = obj.mcpServers;
27442
+ for (const [name, config] of Object.entries(mcpServers)) {
27443
+ const server = {};
27444
+ if (config.transport) server.transport = config.transport;
27445
+ if (config.command) server.command = config.command;
27446
+ if (config.args) server.args = [...config.args];
27447
+ if (config.url) server.url = config.url;
27448
+ if (config.headers && Object.keys(config.headers).length > 0) {
27449
+ server.headers = { ...config.headers };
27450
+ }
27451
+ if (config.env) server.env = { ...config.env };
27452
+ servers[name] = server;
27453
+ }
27454
+ new import_projen6.JsonFile(component, ".cursor/mcp.json", { obj });
27455
+ }
27456
+ static renderHooks(component, settings) {
27457
+ if (!settings?.hooks) return;
27458
+ const hooks = {};
27459
+ const hookEntries = settings.hooks;
27460
+ for (const [event, actions] of Object.entries(hookEntries)) {
27461
+ if (actions && actions.length > 0) {
27462
+ hooks[event] = actions.map((h) => ({
27463
+ command: h.command
27464
+ }));
27465
+ }
27466
+ }
27467
+ if (Object.keys(hooks).length === 0) return;
27468
+ new import_projen6.JsonFile(component, ".cursor/hooks.json", {
27469
+ obj: { version: 1, hooks }
27470
+ });
27471
+ }
27472
+ static renderIgnoreFiles(component, settings) {
27473
+ if (settings?.ignorePatterns && settings.ignorePatterns.length > 0) {
27474
+ new import_textfile2.TextFile(component, ".cursorignore", {
27475
+ lines: [GENERATED_MARKER, "", ...settings.ignorePatterns]
27476
+ });
27477
+ }
27478
+ if (settings?.indexingIgnorePatterns && settings.indexingIgnorePatterns.length > 0) {
27479
+ new import_textfile2.TextFile(component, ".cursorindexingignore", {
27480
+ lines: [GENERATED_MARKER, "", ...settings.indexingIgnorePatterns]
27481
+ });
27482
+ }
27483
+ }
27484
+ };
27485
+
27206
27486
  // src/agent/template-resolver.ts
27207
27487
  var FALLBACKS = {
27208
27488
  "repository.owner": "<owner>",
@@ -27258,9 +27538,9 @@ function resolveTemplateVariables(template, metadata) {
27258
27538
  }
27259
27539
 
27260
27540
  // src/agent/renderers/claude-renderer.ts
27261
- var import_projen6 = require("projen");
27262
- var import_textfile2 = require("projen/lib/textfile");
27263
- var GENERATED_MARKER = "<!-- ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~ -->";
27541
+ var import_projen7 = require("projen");
27542
+ var import_textfile3 = require("projen/lib/textfile");
27543
+ var GENERATED_MARKER2 = "<!-- ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~ -->";
27264
27544
  var ClaudeRenderer = class _ClaudeRenderer {
27265
27545
  /**
27266
27546
  * Render all Claude Code configuration files.
@@ -27282,12 +27562,12 @@ var ClaudeRenderer = class _ClaudeRenderer {
27282
27562
  return target === CLAUDE_RULE_TARGET.CLAUDE_MD;
27283
27563
  });
27284
27564
  if (claudeMdRules.length === 0) return;
27285
- const lines = [GENERATED_MARKER, ""];
27565
+ const lines = [GENERATED_MARKER2, ""];
27286
27566
  for (let i = 0; i < claudeMdRules.length; i++) {
27287
27567
  if (i > 0) lines.push("", "---", "");
27288
27568
  lines.push(...claudeMdRules[i].content.split("\n"));
27289
27569
  }
27290
- new import_textfile2.TextFile(component, "CLAUDE.md", { lines });
27570
+ new import_textfile3.TextFile(component, "CLAUDE.md", { lines });
27291
27571
  }
27292
27572
  static renderScopedRules(component, rules) {
27293
27573
  const scopedRules = rules.filter((r) => {
@@ -27307,7 +27587,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
27307
27587
  lines.push("");
27308
27588
  }
27309
27589
  lines.push(...rule.content.split("\n"));
27310
- new import_textfile2.TextFile(component, `.claude/rules/${rule.name}.md`, { lines });
27590
+ new import_textfile3.TextFile(component, `.claude/rules/${rule.name}.md`, { lines });
27311
27591
  }
27312
27592
  }
27313
27593
  static renderSettings(component, mcpServers, settings) {
@@ -27432,7 +27712,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
27432
27712
  hasContent = true;
27433
27713
  }
27434
27714
  if (!hasContent) return;
27435
- new import_projen6.JsonFile(component, ".claude/settings.json", { obj });
27715
+ new import_projen7.JsonFile(component, ".claude/settings.json", { obj });
27436
27716
  }
27437
27717
  static buildSandboxObj(sandbox) {
27438
27718
  const obj = {};
@@ -27519,12 +27799,12 @@ var ClaudeRenderer = class _ClaudeRenderer {
27519
27799
  lines.push("---");
27520
27800
  lines.push("");
27521
27801
  lines.push(...skill.instructions.split("\n"));
27522
- new import_textfile2.TextFile(component, `.claude/skills/${skill.name}/SKILL.md`, {
27802
+ new import_textfile3.TextFile(component, `.claude/skills/${skill.name}/SKILL.md`, {
27523
27803
  lines
27524
27804
  });
27525
27805
  if (skill.referenceFiles && skill.referenceFiles.length > 0) {
27526
27806
  for (const file of skill.referenceFiles) {
27527
- new import_textfile2.TextFile(component, `.claude/skills/${skill.name}/${file.path}`, {
27807
+ new import_textfile3.TextFile(component, `.claude/skills/${skill.name}/${file.path}`, {
27528
27808
  lines: file.content.split("\n")
27529
27809
  });
27530
27810
  }
@@ -27582,7 +27862,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
27582
27862
  lines.push("---");
27583
27863
  lines.push("");
27584
27864
  lines.push(...agent.prompt.split("\n"));
27585
- new import_textfile2.TextFile(component, `.claude/agents/${agent.name}.md`, { lines });
27865
+ new import_textfile3.TextFile(component, `.claude/agents/${agent.name}.md`, { lines });
27586
27866
  }
27587
27867
  }
27588
27868
  static buildMcpServerObj(config) {
@@ -27599,7 +27879,7 @@ var ClaudeRenderer = class _ClaudeRenderer {
27599
27879
  }
27600
27880
  static renderProcedures(component, procedures) {
27601
27881
  for (const proc of procedures) {
27602
- new import_textfile2.TextFile(component, `.claude/procedures/${proc.name}`, {
27882
+ new import_textfile3.TextFile(component, `.claude/procedures/${proc.name}`, {
27603
27883
  lines: proc.content.split("\n"),
27604
27884
  executable: true
27605
27885
  });
@@ -27626,152 +27906,6 @@ var CopilotRenderer = class {
27626
27906
  }
27627
27907
  };
27628
27908
 
27629
- // src/agent/renderers/cursor-renderer.ts
27630
- var import_projen7 = require("projen");
27631
- var import_textfile3 = require("projen/lib/textfile");
27632
- var GENERATED_MARKER2 = "# ~~ Generated by @codedrifters/configulator. Edits welcome \u2014 please contribute improvements back. ~~";
27633
- var CursorRenderer = class _CursorRenderer {
27634
- /**
27635
- * Render all Cursor configuration files.
27636
- */
27637
- static render(component, rules, skills, subAgents, mcpServers, settings) {
27638
- _CursorRenderer.renderRules(component, rules);
27639
- _CursorRenderer.renderSkills(component, skills);
27640
- _CursorRenderer.renderSubAgents(component, subAgents);
27641
- _CursorRenderer.renderMcpServers(component, mcpServers);
27642
- _CursorRenderer.renderHooks(component, settings);
27643
- _CursorRenderer.renderIgnoreFiles(component, settings);
27644
- }
27645
- static renderRules(component, rules) {
27646
- for (const rule of rules) {
27647
- if (rule.platforms?.cursor?.exclude) continue;
27648
- const lines = [];
27649
- const description = rule.platforms?.cursor?.description ?? rule.description;
27650
- const isAlways = rule.scope === AGENT_RULE_SCOPE.ALWAYS;
27651
- lines.push("---");
27652
- lines.push(`description: "${description}"`);
27653
- lines.push(`alwaysApply: ${isAlways}`);
27654
- if (!isAlways && rule.filePatterns && rule.filePatterns.length > 0) {
27655
- lines.push(`path: ${JSON.stringify([...rule.filePatterns])}`);
27656
- }
27657
- lines.push("---");
27658
- lines.push("");
27659
- lines.push(...rule.content.split("\n"));
27660
- new import_textfile3.TextFile(component, `.cursor/rules/${rule.name}.mdc`, { lines });
27661
- }
27662
- }
27663
- static renderSkills(component, skills) {
27664
- for (const skill of skills) {
27665
- if (skill.platforms?.cursor?.exclude) continue;
27666
- const lines = [];
27667
- lines.push("---");
27668
- lines.push(`name: "${skill.name}"`);
27669
- lines.push(`description: "${skill.description}"`);
27670
- if (skill.disableModelInvocation) {
27671
- lines.push(`disable-model-invocation: true`);
27672
- }
27673
- if (skill.userInvocable === false) {
27674
- lines.push(`user-invocable: false`);
27675
- }
27676
- if (skill.context) {
27677
- lines.push(`context: "${skill.context}"`);
27678
- }
27679
- if (skill.agent) {
27680
- lines.push(`agent: "${skill.agent}"`);
27681
- }
27682
- if (skill.shell) {
27683
- lines.push(`shell: "${skill.shell}"`);
27684
- }
27685
- if (skill.allowedTools && skill.allowedTools.length > 0) {
27686
- lines.push(`allowed-tools:`);
27687
- for (const tool of skill.allowedTools) {
27688
- lines.push(` - "${tool}"`);
27689
- }
27690
- }
27691
- lines.push("---");
27692
- lines.push("");
27693
- lines.push(...skill.instructions.split("\n"));
27694
- new import_textfile3.TextFile(component, `.cursor/skills/${skill.name}/SKILL.md`, {
27695
- lines
27696
- });
27697
- if (skill.referenceFiles && skill.referenceFiles.length > 0) {
27698
- for (const file of skill.referenceFiles) {
27699
- new import_textfile3.TextFile(component, `.cursor/skills/${skill.name}/${file.path}`, {
27700
- lines: file.content.split("\n")
27701
- });
27702
- }
27703
- }
27704
- }
27705
- }
27706
- static renderSubAgents(component, subAgents) {
27707
- for (const agent of subAgents) {
27708
- if (agent.platforms?.cursor?.exclude) continue;
27709
- const lines = [];
27710
- lines.push("---");
27711
- lines.push(`name: ${agent.name}`);
27712
- lines.push(`description: >-`);
27713
- lines.push(` ${agent.description}`);
27714
- if (agent.platforms?.cursor?.readonly) {
27715
- lines.push(`readonly: true`);
27716
- }
27717
- if (agent.platforms?.cursor?.isBackground) {
27718
- lines.push(`is_background: true`);
27719
- }
27720
- lines.push("---");
27721
- lines.push("");
27722
- lines.push(...agent.prompt.split("\n"));
27723
- new import_textfile3.TextFile(component, `.cursor/agents/${agent.name}.md`, { lines });
27724
- }
27725
- }
27726
- static renderMcpServers(component, mcpServers) {
27727
- const serverNames = Object.keys(mcpServers);
27728
- if (serverNames.length === 0) return;
27729
- const obj = { mcpServers: {} };
27730
- const servers = obj.mcpServers;
27731
- for (const [name, config] of Object.entries(mcpServers)) {
27732
- const server = {};
27733
- if (config.transport) server.transport = config.transport;
27734
- if (config.command) server.command = config.command;
27735
- if (config.args) server.args = [...config.args];
27736
- if (config.url) server.url = config.url;
27737
- if (config.headers && Object.keys(config.headers).length > 0) {
27738
- server.headers = { ...config.headers };
27739
- }
27740
- if (config.env) server.env = { ...config.env };
27741
- servers[name] = server;
27742
- }
27743
- new import_projen7.JsonFile(component, ".cursor/mcp.json", { obj });
27744
- }
27745
- static renderHooks(component, settings) {
27746
- if (!settings?.hooks) return;
27747
- const hooks = {};
27748
- const hookEntries = settings.hooks;
27749
- for (const [event, actions] of Object.entries(hookEntries)) {
27750
- if (actions && actions.length > 0) {
27751
- hooks[event] = actions.map((h) => ({
27752
- command: h.command
27753
- }));
27754
- }
27755
- }
27756
- if (Object.keys(hooks).length === 0) return;
27757
- new import_projen7.JsonFile(component, ".cursor/hooks.json", {
27758
- obj: { version: 1, hooks }
27759
- });
27760
- }
27761
- static renderIgnoreFiles(component, settings) {
27762
- if (settings?.ignorePatterns && settings.ignorePatterns.length > 0) {
27763
- new import_textfile3.TextFile(component, ".cursorignore", {
27764
- lines: [GENERATED_MARKER2, "", ...settings.ignorePatterns]
27765
- });
27766
- }
27767
- if (settings?.indexingIgnorePatterns && settings.indexingIgnorePatterns.length > 0) {
27768
- new import_textfile3.TextFile(component, ".cursorindexingignore", {
27769
- lines: [GENERATED_MARKER2, "", ...settings.indexingIgnorePatterns]
27770
- });
27771
- }
27772
- }
27773
- };
27774
-
27775
27909
  // src/agent/agent-config.ts
27776
27910
  var DEFAULT_CLAUDE_ALLOW = [
27777
27911
  // ── Git ──────────────────────────────────────────────────────────────
@@ -27997,7 +28131,10 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
27997
28131
  */
27998
28132
  get pathAwareBundles() {
27999
28133
  if (!this.cachedBundles) {
28000
- this.cachedBundles = buildBuiltInBundles(this.resolvedPaths);
28134
+ this.cachedBundles = buildBuiltInBundles(
28135
+ this.resolvedPaths,
28136
+ resolveIssueDefaults(this.options.issueDefaults)
28137
+ );
28001
28138
  }
28002
28139
  return this.cachedBundles;
28003
28140
  }
@@ -28043,6 +28180,7 @@ var AgentConfig = class _AgentConfig extends import_projen8.Component {
28043
28180
  this.project.gitignore.addPatterns(`/${resolvedRunRatio.stateFilePath}`);
28044
28181
  }
28045
28182
  validateUnblockDependentsConfig(this.options.unblockDependents);
28183
+ validateIssueDefaultsConfig(this.options.issueDefaults);
28046
28184
  const resolvedProgressFiles = validateProgressFilesConfig(
28047
28185
  this.options.progressFiles
28048
28186
  );
@@ -32918,6 +33056,8 @@ var TypeScriptConfig = class extends import_projen23.Component {
32918
33056
  DEFAULT_DISPATCH_MODEL,
32919
33057
  DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO,
32920
33058
  DEFAULT_HOUSEKEEPING_MODEL,
33059
+ DEFAULT_ISSUE_PRIORITY,
33060
+ DEFAULT_ISSUE_STATUS,
32921
33061
  DEFAULT_ISSUE_TEMPLATES_BUNDLE_PATH_PATTERNS,
32922
33062
  DEFAULT_ISSUE_TEMPLATES_EMIT_CHECKER,
32923
33063
  DEFAULT_ISSUE_TEMPLATES_EMIT_STARTER,
@@ -32934,6 +33074,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
32934
33074
  DEFAULT_PROGRESS_FILES_STALE_AFTER_HOURS,
32935
33075
  DEFAULT_PROGRESS_FILES_STATE_DIR,
32936
33076
  DEFAULT_REQUIRE_PRODUCT_CONTEXT,
33077
+ DEFAULT_RESOLVED_ISSUE_DEFAULTS,
32937
33078
  DEFAULT_SAMPLE_COMPILER_OPTIONS,
32938
33079
  DEFAULT_SCHEDULED_TASKS_ROOT,
32939
33080
  DEFAULT_SCHEDULED_TASK_ENTRIES,
@@ -32985,6 +33126,8 @@ var TypeScriptConfig = class extends import_projen23.Component {
32985
33126
  TypeScriptConfig,
32986
33127
  TypeScriptProject,
32987
33128
  UNKNOWN_TYPE_FALLBACK_TIER,
33129
+ VALID_PRIORITY_VALUES,
33130
+ VALID_STATUS_VALUES,
32988
33131
  VERSION,
32989
33132
  VERSION_KEYS_SKIP,
32990
33133
  VERSION_NPM_PACKAGES,
@@ -33043,6 +33186,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33043
33186
  githubWorkflowBundle,
33044
33187
  industryDiscoveryBundle,
33045
33188
  jestBundle,
33189
+ labelsForPhase,
33046
33190
  maintenanceAuditBundle,
33047
33191
  meetingAnalysisBundle,
33048
33192
  orchestratorBundle,
@@ -33085,6 +33229,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33085
33229
  renderSkillEvalsRuleContent,
33086
33230
  renderSkillEvalsRunnerScript,
33087
33231
  renderSourceTierExamples,
33232
+ renderStubIndexConventionRuleContent,
33088
33233
  renderUnblockDependentsScript,
33089
33234
  renderUnblockDependentsSection,
33090
33235
  requirementsAnalystBundle,
@@ -33095,6 +33240,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33095
33240
  resolveAgentTiers,
33096
33241
  resolveAstroProjectOutdir,
33097
33242
  resolveAwsCdkProjectOutdir,
33243
+ resolveIssueDefaults,
33098
33244
  resolveIssueTemplates,
33099
33245
  resolveModelAlias,
33100
33246
  resolveOrchestratorAssets,
@@ -33118,6 +33264,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
33118
33264
  typescriptBundle,
33119
33265
  upstreamConfigulatorDocsBundle,
33120
33266
  validateAgentTierConfig,
33267
+ validateIssueDefaultsConfig,
33121
33268
  validateIssueTemplatesConfig,
33122
33269
  validateMonorepoLayout,
33123
33270
  validateProgressFilesConfig,