@codedrifters/configulator 0.0.329 → 0.0.330

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
@@ -450,7 +450,6 @@ __export(index_exports, {
450
450
  renderSkillEvalsRuleContent: () => renderSkillEvalsRuleContent,
451
451
  renderSkillEvalsRunnerScript: () => renderSkillEvalsRunnerScript,
452
452
  renderSourceTierExamples: () => renderSourceTierExamples,
453
- renderStubIndexConventionRuleContent: () => renderStubIndexConventionRuleContent,
454
453
  renderTemporalFramingCheckerScript: () => renderTemporalFramingCheckerScript,
455
454
  renderTemporalFramingRuleContent: () => renderTemporalFramingRuleContent,
456
455
  renderUnblockDependentsScript: () => renderUnblockDependentsScript,
@@ -923,7 +922,8 @@ var agendaAnalystSubAgent = {
923
922
  " or cut content \u2014 do not ship a math-broken agenda.",
924
923
  "",
925
924
  "7. **Create the folder `index.md` if missing.** Populate it",
926
- " following the `stub-index-convention` rule:",
925
+ " following the section-index-page contract in the",
926
+ " `shared-editing-safety` rule:",
927
927
  " - Frontmatter `title` (short sidebar label) and `description`",
928
928
  " (one line).",
929
929
  " - A 2\u20134 sentence summary of the meeting's objective and desired",
@@ -1496,11 +1496,7 @@ var awsCdkBundle = {
1496
1496
  // src/agent/bundles/issue-templates.ts
1497
1497
  var DEFAULT_ISSUE_TEMPLATES_ENABLED = true;
1498
1498
  var DEFAULT_ISSUE_TEMPLATES_PATH = "docs/src/content/docs/agents/issue-templates.md";
1499
- var DEFAULT_ISSUE_TEMPLATES_BUNDLE_PATH_PATTERNS = [
1500
- "packages/@codedrifters/configulator/src/agent/bundles/**/*.ts",
1501
- ".claude/agents/**/*.md",
1502
- ".claude/skills/**/*.md"
1503
- ];
1499
+ var DEFAULT_ISSUE_TEMPLATES_BUNDLE_PATH_PATTERNS = [".claude/agents/**/*.md", ".claude/skills/**/*.md"];
1504
1500
  var DEFAULT_ISSUE_TEMPLATES_EMIT_CHECKER = false;
1505
1501
  var DEFAULT_ISSUE_TEMPLATES_EMIT_STARTER = false;
1506
1502
  var DEFAULT_ISSUE_TEMPLATES_REQUIRE_REFERENCE = true;
@@ -2669,7 +2665,66 @@ function renderSharedEditingRuleContent(se) {
2669
2665
  "conflicts; rewriting or reordering existing rows almost always",
2670
2666
  "does. If a shared index needs a structural change (column",
2671
2667
  "added, sort key changed), file a dedicated issue for the change",
2672
- "rather than bundling it into a content-contributing PR."
2668
+ "rather than bundling it into a content-contributing PR.",
2669
+ "",
2670
+ "## Section Index Page Shape",
2671
+ "",
2672
+ "When any agent creates or updates an `index.md` (or `README.md`)",
2673
+ "in a docs subdirectory under a Starlight content root, the file's",
2674
+ "body must include:",
2675
+ "",
2676
+ "1. **A 1\u20132 paragraph summary** of the section's purpose and how",
2677
+ " it fits into the larger research, requirements, or capability",
2678
+ " area. Readers landing on the page should understand what's in",
2679
+ " the section without falling back to the sidebar.",
2680
+ "",
2681
+ "2. **A grouped, linked listing of the directory's children**",
2682
+ " (table or bullet list). When a natural taxonomy exists (e.g.",
2683
+ " organizations grouped by sub-segment, regulations grouped by",
2684
+ " jurisdiction, capabilities grouped by tier), use it. Otherwise",
2685
+ " sort alphabetically by title. Every listing entry must link",
2686
+ " to the child page.",
2687
+ "",
2688
+ "3. **No body `# Heading`.** Starlight renders the frontmatter",
2689
+ " `title:` as the page H1 automatically \u2014 a body H1 produces a",
2690
+ " duplicate. The same no-body-H1 contract that applies to skill",
2691
+ " templates and inline agent templates also applies to every",
2692
+ " index page emitted by an agent.",
2693
+ "",
2694
+ "### When this applies",
2695
+ "",
2696
+ "The convention applies to every `index.md` / `README.md` file",
2697
+ "covered by the shared-index path globs listed above:",
2698
+ "",
2699
+ "- `docs/src/content/docs/**/index.md`",
2700
+ "- `docs/src/content/docs/**/README.md`",
2701
+ "",
2702
+ "Any agent that scaffolds a new directory under a Starlight",
2703
+ "content root MUST populate the directory's index page following",
2704
+ "this contract \u2014 a one-sentence stub is not acceptable.",
2705
+ "",
2706
+ "### Reference shapes",
2707
+ "",
2708
+ "Existing rich indexes are the canonical reference shape. Examples:",
2709
+ "",
2710
+ "- A `<MEETINGS_ROOT>/<YYYY-MM-DD>-<slug>/index.md` populated by",
2711
+ " the `agenda-analyst` bundle: frontmatter `title` /",
2712
+ " `description`, a 2\u20134 sentence summary, and a `## Documents`",
2713
+ " section listing every page in the folder.",
2714
+ "- A regulations scope index that opens with two paragraphs of",
2715
+ " context and groups every linked regulation under a",
2716
+ " `## Regulations` table by jurisdiction.",
2717
+ "- A standards-organizations index that groups every linked",
2718
+ " organization under a `## Organizations` heading by role",
2719
+ " (governance, working group, implementer).",
2720
+ "",
2721
+ "### Out of scope",
2722
+ "",
2723
+ "- Auto-generated child listings via Astro/Starlight components.",
2724
+ " Agents emit hand-curated tables or bullet lists; the rule",
2725
+ " defines the shape, not the rendering technology.",
2726
+ "- Backfilling pre-existing stub indexes is a downstream-consumer",
2727
+ " cleanup task, not a configulator change."
2673
2728
  );
2674
2729
  return lines.join("\n");
2675
2730
  }
@@ -3224,71 +3279,6 @@ function assertValidProductContextPath(value) {
3224
3279
  }
3225
3280
  }
3226
3281
 
3227
- // src/agent/bundles/stub-index-convention.ts
3228
- function renderStubIndexConventionRuleContent() {
3229
- return [
3230
- "# Section Index Pages",
3231
- "",
3232
- "When any agent creates or updates an `index.md` (or `README.md`)",
3233
- "in a docs subdirectory under a Starlight content root, the file's",
3234
- "body must include:",
3235
- "",
3236
- "1. **A 1\u20132 paragraph summary** of the section's purpose and how",
3237
- " it fits into the larger research, requirements, or capability",
3238
- " area. Readers landing on the page should understand what's in",
3239
- " the section without falling back to the sidebar.",
3240
- "",
3241
- "2. **A grouped, linked listing of the directory's children**",
3242
- " (table or bullet list). When a natural taxonomy exists (e.g.",
3243
- " organizations grouped by sub-segment, regulations grouped by",
3244
- " jurisdiction, capabilities grouped by tier), use it. Otherwise",
3245
- " sort alphabetically by title. Every listing entry must link",
3246
- " to the child page.",
3247
- "",
3248
- "3. **No body `# Heading`.** Starlight renders the frontmatter",
3249
- " `title:` as the page H1 automatically \u2014 a body H1 produces a",
3250
- " duplicate. The same no-body-H1 contract that applies to skill",
3251
- " templates and inline agent templates also applies to every",
3252
- " index page emitted by an agent.",
3253
- "",
3254
- "## When this applies",
3255
- "",
3256
- "The convention applies to every `index.md` / `README.md` file",
3257
- "covered by the shared-index path globs documented in the",
3258
- "`shared-editing-safety` rule:",
3259
- "",
3260
- "- `docs/src/content/docs/**/index.md`",
3261
- "- `docs/src/content/docs/**/README.md`",
3262
- "",
3263
- "Any agent that scaffolds a new directory under a Starlight",
3264
- "content root MUST populate the directory's index page following",
3265
- "this contract \u2014 a one-sentence stub is not acceptable.",
3266
- "",
3267
- "## Reference shapes",
3268
- "",
3269
- "Existing rich indexes are the canonical reference shape. Examples:",
3270
- "",
3271
- "- A `<MEETINGS_ROOT>/<YYYY-MM-DD>-<slug>/index.md` populated by",
3272
- " the `agenda-analyst` bundle: frontmatter `title` /",
3273
- " `description`, a 2\u20134 sentence summary, and a `## Documents`",
3274
- " section listing every page in the folder.",
3275
- "- A regulations scope index that opens with two paragraphs of",
3276
- " context and groups every linked regulation under a",
3277
- " `## Regulations` table by jurisdiction.",
3278
- "- A standards-organizations index that groups every linked",
3279
- " organization under a `## Organizations` heading by role",
3280
- " (governance, working group, implementer).",
3281
- "",
3282
- "## Out of scope",
3283
- "",
3284
- "- Auto-generated child listings via Astro/Starlight components.",
3285
- " Agents emit hand-curated tables or bullet lists; the rule",
3286
- " defines the shape, not the rendering technology.",
3287
- "- Backfilling pre-existing stub indexes is a downstream-consumer",
3288
- " cleanup task, not a configulator change."
3289
- ].join("\n");
3290
- }
3291
-
3292
3282
  // src/agent/bundles/temporal-framing.ts
3293
3283
  var DEFAULT_TEMPORAL_FRAMING_ENABLED = true;
3294
3284
  var DEFAULT_TEMPORAL_FRAMING_PATHS = [
@@ -4457,6 +4447,12 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4457
4447
  {
4458
4448
  name: "issue-label-conventions",
4459
4449
  description: "Priority and status label taxonomy, defaults, inference rules, and blocking rules for agent-created or updated issues",
4450
+ // ALWAYS scope: every agent (and the user) needs the label
4451
+ // taxonomy whenever an issue gets created or updated, which
4452
+ // happens from any context — not only when editing agent /
4453
+ // skill / bundle source. Consumers that want to narrow the
4454
+ // load can override via `agentConfig.additionalRulePaths`
4455
+ // or `excludeRules`.
4460
4456
  scope: AGENT_RULE_SCOPE.ALWAYS,
4461
4457
  content: [
4462
4458
  "# Issue Label Conventions",
@@ -4822,7 +4818,13 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4822
4818
  {
4823
4819
  name: "progress-file-convention",
4824
4820
  description: "Progress-file schema and write rules, partial-resume protocol, stale-branch decision tree, and [BLOCKED] comment format that let phased agents survive crashes without losing work.",
4825
- scope: AGENT_RULE_SCOPE.ALWAYS,
4821
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
4822
+ // Bundle defaults exclude paths into configulator's own source
4823
+ // (only meaningful when configulator is a workspace package,
4824
+ // i.e. in codedrifters/packages itself). That repo restores
4825
+ // them via `agentConfig.additionalRulePaths`; other consumers
4826
+ // get a clean default.
4827
+ filePatterns: [".claude/agents/*.md", ".claude/procedures/**"],
4826
4828
  content: renderProgressFilesRuleContent(resolveProgressFiles()),
4827
4829
  platforms: {
4828
4830
  cursor: { exclude: true }
@@ -4832,27 +4834,26 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4832
4834
  {
4833
4835
  name: "shared-editing-safety",
4834
4836
  description: "Shared-editing safety: single-entry deterministic-sort inserts on index files, commit-path verification, and the merge-conflict resolution recipe that keeps concurrent agent sessions from dropping each other's rows on shared registries and feature matrices.",
4835
- scope: AGENT_RULE_SCOPE.ALWAYS,
4837
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
4838
+ filePatterns: DEFAULT_SHARED_INDEX_PATHS,
4836
4839
  content: renderSharedEditingRuleContent(resolveSharedEditing()),
4837
4840
  platforms: {
4838
4841
  cursor: { exclude: true }
4839
4842
  },
4840
4843
  tags: ["workflow"]
4841
4844
  },
4842
- {
4843
- name: "stub-index-convention",
4844
- 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).",
4845
- scope: AGENT_RULE_SCOPE.ALWAYS,
4846
- content: renderStubIndexConventionRuleContent(),
4847
- platforms: {
4848
- cursor: { exclude: true }
4849
- },
4850
- tags: ["workflow"]
4851
- },
4852
4845
  {
4853
4846
  name: "temporal-framing-convention",
4854
4847
  description: "Temporal-framing convention: every agent-authored time-sensitive factual claim (ownership, leadership tenure, regulatory status, litigation, dated metrics) carries an inline `as of [YYYY-MM-DD]` or `as of [Month YYYY]` qualifier on first occurrence so refresh agents have a mechanical signal for which claims to re-verify.",
4855
- scope: AGENT_RULE_SCOPE.ALWAYS,
4848
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
4849
+ filePatterns: [
4850
+ "docs/src/content/docs/profiles/**/*.md",
4851
+ "docs/src/content/docs/industry-research/**/*.md",
4852
+ "docs/src/content/docs/software-research/**/*.md",
4853
+ "docs/src/content/docs/regulatory-research/**/*.md",
4854
+ "docs/src/content/docs/standards-research/**/*.md",
4855
+ "docs/src/content/docs/customer-research/**/*.md"
4856
+ ],
4856
4857
  content: renderTemporalFramingRuleContent(resolveTemporalFraming()),
4857
4858
  platforms: {
4858
4859
  cursor: { exclude: true }
@@ -4862,7 +4863,10 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4862
4863
  {
4863
4864
  name: "skill-evals",
4864
4865
  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.",
4865
- scope: AGENT_RULE_SCOPE.ALWAYS,
4866
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
4867
+ // Bundle defaults exclude paths into configulator's own
4868
+ // source — see comment on progress-file-convention above.
4869
+ filePatterns: [".claude/skills/**"],
4866
4870
  content: renderSkillEvalsRuleContent(resolveSkillEvals()),
4867
4871
  platforms: {
4868
4872
  cursor: { exclude: true }
@@ -4872,7 +4876,14 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
4872
4876
  {
4873
4877
  name: "issue-templates-convention",
4874
4878
  description: `Issue-templates convention: a single hand-authored reference page under \`${paths.docsRoot}/agents/issue-templates.md\` that carries one canonical \`gh issue create\` recipe per downstream phase label, and the reference-don't-inline rule that keeps bundle rules and agent prompts citing that page instead of duplicating full template invocations.`,
4875
- scope: AGENT_RULE_SCOPE.ALWAYS,
4879
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
4880
+ // Bundle defaults exclude paths into configulator's own
4881
+ // source — see comment on progress-file-convention above.
4882
+ filePatterns: [
4883
+ ".claude/skills/**/SKILL.md",
4884
+ ".claude/agents/*.md",
4885
+ `${paths.docsRoot}/agents/issue-templates.md`
4886
+ ],
4876
4887
  content: renderIssueTemplatesRuleContent(resolveIssueTemplates()),
4877
4888
  platforms: {
4878
4889
  cursor: { exclude: true }
@@ -6195,8 +6206,8 @@ function buildBusinessModelsAnalystSubAgent(paths) {
6195
6206
  "",
6196
6207
  "7. **Create the segment index** at",
6197
6208
  " `<BUSINESS_MODELS_ROOT>/<industry>/segments/<SEGMENT_SLUG>/index.md`",
6198
- " if it does not already exist. Follow the",
6199
- " `stub-index-convention` rule: a 1\u20132 paragraph summary of the",
6209
+ " if it does not already exist. Follow the section-index-page",
6210
+ " contract in the `shared-editing-safety` rule: a 1\u20132 paragraph summary of the",
6200
6211
  " segment plus a linked listing of every page in the folder",
6201
6212
  " (`./business-model.md` and any value-stream / capability pages",
6202
6213
  " that land later). No body `# Heading` \u2014 the frontmatter",
@@ -10563,6 +10574,10 @@ var githubWorkflowBundle = {
10563
10574
  {
10564
10575
  name: "create-issue-workflow",
10565
10576
  description: "Automated workflow for creating a new GitHub issue",
10577
+ // ALWAYS scope: users invoke "create an issue" from any
10578
+ // context, not only when editing agent / skill / bundle source.
10579
+ // Consumers that want to narrow the load can override via
10580
+ // `agentConfig.additionalRulePaths` or `excludeRules`.
10566
10581
  scope: AGENT_RULE_SCOPE.ALWAYS,
10567
10582
  content: [
10568
10583
  "# Create Issue Workflow",
@@ -16593,7 +16608,15 @@ var orchestratorBundle = {
16593
16608
  {
16594
16609
  name: "orchestrator-conventions",
16595
16610
  description: "Guidelines for orchestrator agent behavior and pipeline management, including the funnel-tier dispatch sort, scope gate, and per-agent scheduled-task layout",
16596
- scope: AGENT_RULE_SCOPE.ALWAYS,
16611
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
16612
+ // Bundle defaults exclude paths into configulator's own source
16613
+ // (only meaningful when configulator is a workspace package).
16614
+ // codedrifters/packages restores them via
16615
+ // `agentConfig.additionalRulePaths`.
16616
+ filePatterns: [
16617
+ ".claude/agents/orchestrator.md",
16618
+ ".claude/scheduled-tasks/**"
16619
+ ],
16597
16620
  content: buildOrchestratorConventionsContent(
16598
16621
  DEFAULT_AGENT_TIERS,
16599
16622
  resolveScopeGate(),
@@ -16602,7 +16625,6 @@ var orchestratorBundle = {
16602
16625
  resolveUnblockDependents()
16603
16626
  ),
16604
16627
  platforms: {
16605
- claude: { target: "claude-md" },
16606
16628
  cursor: { exclude: true }
16607
16629
  },
16608
16630
  tags: ["workflow"]
@@ -19173,7 +19195,15 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
19173
19195
  {
19174
19196
  name: "pr-review-policy",
19175
19197
  description: "Declarative policy that tells the pr-reviewer which PRs may auto-merge and which must wait for a human reviewer",
19176
- scope: AGENT_RULE_SCOPE.ALWAYS,
19198
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
19199
+ // Bundle defaults exclude paths into configulator's own source
19200
+ // (only meaningful when configulator is a workspace package).
19201
+ // codedrifters/packages restores them via
19202
+ // `agentConfig.additionalRulePaths`.
19203
+ filePatterns: [
19204
+ ".claude/agents/pr-reviewer.md",
19205
+ ".claude/skills/review-pr/**"
19206
+ ],
19177
19207
  content: [
19178
19208
  "# PR Review Policy",
19179
19209
  "",
@@ -19355,7 +19385,15 @@ function buildPrReviewBundle(policy = resolvePrReviewPolicy()) {
19355
19385
  {
19356
19386
  name: "pr-review-feedback-protocol",
19357
19387
  description: "Documents the human-in-the-loop feedback loop on PR review: reaction state machine, pushback resolution, fix-list comment format, sticky reviewer-notes comment, label glossary, and human-author opt-in flag.",
19358
- scope: AGENT_RULE_SCOPE.ALWAYS,
19388
+ scope: AGENT_RULE_SCOPE.FILE_PATTERN,
19389
+ // Bundle defaults exclude paths into configulator's own source
19390
+ // (only meaningful when configulator is a workspace package).
19391
+ // codedrifters/packages restores them via
19392
+ // `agentConfig.additionalRulePaths`.
19393
+ filePatterns: [
19394
+ ".claude/agents/pr-reviewer.md",
19395
+ ".claude/agents/issue-worker.md"
19396
+ ],
19359
19397
  content: [
19360
19398
  "# PR Review Feedback Protocol",
19361
19399
  "",
@@ -19590,6 +19628,10 @@ var projenBundle = {
19590
19628
  {
19591
19629
  name: "development-commands",
19592
19630
  description: "Projen development commands for building, testing, linting, and validating changes",
19631
+ // ALWAYS scope: developers ask "how do I build/test/lint?" from
19632
+ // anywhere in the repo, not only when editing projen config.
19633
+ // Consumers that want to narrow the load can override via
19634
+ // `agentConfig.additionalRulePaths` or `excludeRules`.
19593
19635
  scope: AGENT_RULE_SCOPE.ALWAYS,
19594
19636
  content: [
19595
19637
  "# Development Commands",
@@ -20298,7 +20340,8 @@ function buildRegulatoryResearchAnalystSubAgent(paths, issueDefaults) {
20298
20340
  "7. **Create or update the scope index page** at",
20299
20341
  " `<SCOPE_INDEX_PAGE>` so downstream regulations link back to a",
20300
20342
  " coherent landing page for the scope. Follow the",
20301
- " `stub-index-convention` rule: the body must carry a 1\u20132",
20343
+ " section-index-page contract in the `shared-editing-safety` rule:",
20344
+ " the body must carry a 1\u20132",
20302
20345
  " paragraph contextual summary plus a grouped, linked listing of",
20303
20346
  " every regulation in the scope (e.g. by jurisdiction). No body",
20304
20347
  " `# Heading` \u2014 the frontmatter `title:` already renders as the",
@@ -27783,7 +27826,8 @@ function buildStandardsResearchAnalystSubAgent(paths, issueDefaults) {
27783
27826
  " pages.",
27784
27827
  "",
27785
27828
  "4. **Write the overview page** at `<OVERVIEW_PAGE>`. Follow",
27786
- " the `stub-index-convention` rule: the body opens with a",
27829
+ " the section-index-page contract in the",
27830
+ " `shared-editing-safety` rule: the body opens with a",
27787
27831
  " 1\u20132 paragraph contextual summary of the standard and its",
27788
27832
  " versions, and the version pages, modules, and extensions",
27789
27833
  " sections below double as the grouped, linked listing of",
@@ -29616,6 +29660,62 @@ function bundleNameForWorkflowRule(ruleName) {
29616
29660
  );
29617
29661
  return entry?.bundle;
29618
29662
  }
29663
+ function buildConventionsRegistryRule(rules) {
29664
+ const entries = [];
29665
+ for (const rule of rules) {
29666
+ if (rule.scope !== AGENT_RULE_SCOPE.FILE_PATTERN) {
29667
+ continue;
29668
+ }
29669
+ if (rule.platforms?.claude?.exclude === true) {
29670
+ continue;
29671
+ }
29672
+ if (!rule.filePatterns || rule.filePatterns.length === 0) {
29673
+ continue;
29674
+ }
29675
+ entries.push(rule);
29676
+ }
29677
+ if (entries.length === 0) {
29678
+ return void 0;
29679
+ }
29680
+ entries.sort((a, b) => a.name.localeCompare(b.name));
29681
+ const lines = [
29682
+ "# Conventions Registry",
29683
+ "",
29684
+ "Each row below is a `FILE_PATTERN`-scoped convention rule that",
29685
+ "auto-loads on demand when the agent's current file matches one",
29686
+ "of the listed paths. Full rule bodies live under",
29687
+ "`.claude/rules/<slug>.md` so they only consume context when",
29688
+ "they apply. Consult the matching rule before doing work in any",
29689
+ "of the listed surfaces.",
29690
+ "",
29691
+ "| Rule | Auto-loads when editing | Purpose |",
29692
+ "| --- | --- | --- |"
29693
+ ];
29694
+ const MAX_PATTERNS_SHOWN = 3;
29695
+ for (const rule of entries) {
29696
+ const ruleLink = `[\`${rule.name}\`](.claude/rules/${rule.name}.md)`;
29697
+ const patterns = rule.filePatterns ?? [];
29698
+ let patternCell;
29699
+ if (patterns.length <= MAX_PATTERNS_SHOWN) {
29700
+ patternCell = patterns.map((p) => `\`${p}\``).join(", ");
29701
+ } else {
29702
+ const shown = patterns.slice(0, MAX_PATTERNS_SHOWN).map((p) => `\`${p}\``).join(", ");
29703
+ patternCell = `${shown}, \u2026 ([full list](.claude/rules/${rule.name}.md))`;
29704
+ }
29705
+ const purposeCell = rule.description.replace(/\s+/g, " ").replace(/\|/g, "\\|").trim();
29706
+ lines.push(`| ${ruleLink} | ${patternCell} | ${purposeCell} |`);
29707
+ }
29708
+ return {
29709
+ name: "conventions-registry",
29710
+ description: "Routing table for every FILE_PATTERN-scoped convention rule. Lists each rule's slug, the file patterns that auto-trigger it, and a one-line purpose so agents whose current file does not match any rule's paths: can still discover the full convention set.",
29711
+ scope: AGENT_RULE_SCOPE.ALWAYS,
29712
+ content: lines.join("\n"),
29713
+ platforms: {
29714
+ cursor: { exclude: true }
29715
+ },
29716
+ tags: ["workflow"]
29717
+ };
29718
+ }
29619
29719
  function buildAgentRegistryRule(bundles, paths) {
29620
29720
  const activeNames = new Set(bundles.map((b) => b.name));
29621
29721
  const rows = AGENT_REGISTRY_ENTRIES.filter(
@@ -31338,6 +31438,20 @@ ${extra}`
31338
31438
  }
31339
31439
  }
31340
31440
  }
31441
+ if (this.options.additionalRulePaths) {
31442
+ for (const [name, extraPaths] of Object.entries(
31443
+ this.options.additionalRulePaths
31444
+ )) {
31445
+ if (extraPaths.length === 0) continue;
31446
+ const existing = ruleMap.get(name);
31447
+ if (!existing) continue;
31448
+ if (existing.scope !== AGENT_RULE_SCOPE.FILE_PATTERN) continue;
31449
+ ruleMap.set(name, {
31450
+ ...existing,
31451
+ filePatterns: [...existing.filePatterns ?? [], ...extraPaths]
31452
+ });
31453
+ }
31454
+ }
31341
31455
  if (this.options.priorityRules && this.options.priorityRules.length > 0) {
31342
31456
  const issueLabelRule = ruleMap.get("issue-label-conventions");
31343
31457
  if (issueLabelRule) {
@@ -31544,9 +31658,6 @@ ${hook}`
31544
31658
  }
31545
31659
  }
31546
31660
  }
31547
- if (!hasAnyDocsEmittingBundle(excludedBundleNames)) {
31548
- ruleMap.delete("stub-index-convention");
31549
- }
31550
31661
  if (injectBundleHooks && resolvedIssueTemplatesForRules.enabled && hasDownstreamBundles) {
31551
31662
  for (const [ruleName, label] of ISSUE_TEMPLATES_BUNDLE_HOOKS) {
31552
31663
  const existing = ruleMap.get(ruleName);
@@ -31663,6 +31774,12 @@ ${meetingsSection}`;
31663
31774
  });
31664
31775
  }
31665
31776
  }
31777
+ const conventionsRegistryRule = buildConventionsRegistryRule(
31778
+ ruleMap.values()
31779
+ );
31780
+ if (conventionsRegistryRule) {
31781
+ ruleMap.set(conventionsRegistryRule.name, conventionsRegistryRule);
31782
+ }
31666
31783
  return [...ruleMap.values()].sort((a, b) => {
31667
31784
  if (a.name === "project-overview") return -1;
31668
31785
  if (b.name === "project-overview") return 1;
@@ -37885,7 +38002,6 @@ export const collections = {
37885
38002
  renderSkillEvalsRuleContent,
37886
38003
  renderSkillEvalsRunnerScript,
37887
38004
  renderSourceTierExamples,
37888
- renderStubIndexConventionRuleContent,
37889
38005
  renderTemporalFramingCheckerScript,
37890
38006
  renderTemporalFramingRuleContent,
37891
38007
  renderUnblockDependentsScript,