@codedrifters/configulator 0.0.289 → 0.0.291
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.mts +166 -2
- package/lib/index.d.ts +167 -3
- package/lib/index.js +373 -135
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +370 -135
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -205,6 +205,7 @@ __export(index_exports, {
|
|
|
205
205
|
DEFAULT_API_EXTRACTOR_REPORT_FILENAME: () => DEFAULT_API_EXTRACTOR_REPORT_FILENAME,
|
|
206
206
|
DEFAULT_API_EXTRACTOR_REPORT_FOLDER: () => DEFAULT_API_EXTRACTOR_REPORT_FOLDER,
|
|
207
207
|
DEFAULT_AUDIT_REPORT_DIR: () => DEFAULT_AUDIT_REPORT_DIR,
|
|
208
|
+
DEFAULT_BUNDLE_OVERRIDES: () => DEFAULT_BUNDLE_OVERRIDES,
|
|
208
209
|
DEFAULT_DECOMPOSITION_TEMPLATE: () => DEFAULT_DECOMPOSITION_TEMPLATE,
|
|
209
210
|
DEFAULT_DISPATCH_MODEL: () => DEFAULT_DISPATCH_MODEL,
|
|
210
211
|
DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO: () => DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO,
|
|
@@ -376,6 +377,7 @@ __export(index_exports, {
|
|
|
376
377
|
renderSkillEvalsRuleContent: () => renderSkillEvalsRuleContent,
|
|
377
378
|
renderSkillEvalsRunnerScript: () => renderSkillEvalsRunnerScript,
|
|
378
379
|
renderSourceTierExamples: () => renderSourceTierExamples,
|
|
380
|
+
renderStubIndexConventionRuleContent: () => renderStubIndexConventionRuleContent,
|
|
379
381
|
renderUnblockDependentsScript: () => renderUnblockDependentsScript,
|
|
380
382
|
renderUnblockDependentsSection: () => renderUnblockDependentsSection,
|
|
381
383
|
requirementsAnalystBundle: () => requirementsAnalystBundle,
|
|
@@ -390,6 +392,7 @@ __export(index_exports, {
|
|
|
390
392
|
resolveModelAlias: () => resolveModelAlias,
|
|
391
393
|
resolveOrchestratorAssets: () => resolveOrchestratorAssets,
|
|
392
394
|
resolveOutdirFromPackageName: () => resolveOutdirFromPackageName,
|
|
395
|
+
resolveOverrideForLabels: () => resolveOverrideForLabels,
|
|
393
396
|
resolveProgressFiles: () => resolveProgressFiles,
|
|
394
397
|
resolveRunRatio: () => resolveRunRatio,
|
|
395
398
|
resolveScheduledTasks: () => resolveScheduledTasks,
|
|
@@ -835,13 +838,16 @@ var agendaAnalystSubAgent = {
|
|
|
835
838
|
" `duration_min` \xB1 5 minutes. If it doesn't, adjust section times",
|
|
836
839
|
" or cut content \u2014 do not ship a math-broken agenda.",
|
|
837
840
|
"",
|
|
838
|
-
"7. **Create the folder `index.md` if missing.** Populate it
|
|
841
|
+
"7. **Create the folder `index.md` if missing.** Populate it",
|
|
842
|
+
" following the `stub-index-convention` rule:",
|
|
839
843
|
" - Frontmatter `title` (short sidebar label) and `description`",
|
|
840
844
|
" (one line).",
|
|
841
845
|
" - A 2\u20134 sentence summary of the meeting's objective and desired",
|
|
842
846
|
" outcomes pulled from the agenda.",
|
|
843
847
|
" - A `## Documents` section linking to `./agenda.md` (and",
|
|
844
848
|
" `./notes.md` once the meeting-analyst produces it).",
|
|
849
|
+
" - No body `# Heading` \u2014 the frontmatter `title:` already",
|
|
850
|
+
" renders as the page H1.",
|
|
845
851
|
"",
|
|
846
852
|
" Do NOT set `sidebar.hidden: true` on `index.md` \u2014 it is the page",
|
|
847
853
|
" that should appear in the sidebar.",
|
|
@@ -1605,8 +1611,6 @@ function renderIssueTemplatesStarterPage(_it) {
|
|
|
1605
1611
|
"description: Canonical gh issue create recipes \u2014 one per downstream phase label.",
|
|
1606
1612
|
"---",
|
|
1607
1613
|
"",
|
|
1608
|
-
"# Issue Templates",
|
|
1609
|
-
"",
|
|
1610
1614
|
"This page lists the canonical `gh issue create` recipe for every",
|
|
1611
1615
|
"downstream issue kind dispatched by an agent in this monorepo.",
|
|
1612
1616
|
"Bundles and agent prompts cite the matching section below instead",
|
|
@@ -3041,6 +3045,71 @@ function assertValidProductContextPath(value) {
|
|
|
3041
3045
|
}
|
|
3042
3046
|
}
|
|
3043
3047
|
|
|
3048
|
+
// src/agent/bundles/stub-index-convention.ts
|
|
3049
|
+
function renderStubIndexConventionRuleContent() {
|
|
3050
|
+
return [
|
|
3051
|
+
"# Section Index Pages",
|
|
3052
|
+
"",
|
|
3053
|
+
"When any agent creates or updates an `index.md` (or `README.md`)",
|
|
3054
|
+
"in a docs subdirectory under a Starlight content root, the file's",
|
|
3055
|
+
"body must include:",
|
|
3056
|
+
"",
|
|
3057
|
+
"1. **A 1\u20132 paragraph summary** of the section's purpose and how",
|
|
3058
|
+
" it fits into the larger research, requirements, or capability",
|
|
3059
|
+
" area. Readers landing on the page should understand what's in",
|
|
3060
|
+
" the section without falling back to the sidebar.",
|
|
3061
|
+
"",
|
|
3062
|
+
"2. **A grouped, linked listing of the directory's children**",
|
|
3063
|
+
" (table or bullet list). When a natural taxonomy exists (e.g.",
|
|
3064
|
+
" organizations grouped by sub-segment, regulations grouped by",
|
|
3065
|
+
" jurisdiction, capabilities grouped by tier), use it. Otherwise",
|
|
3066
|
+
" sort alphabetically by title. Every listing entry must link",
|
|
3067
|
+
" to the child page.",
|
|
3068
|
+
"",
|
|
3069
|
+
"3. **No body `# Heading`.** Starlight renders the frontmatter",
|
|
3070
|
+
" `title:` as the page H1 automatically \u2014 a body H1 produces a",
|
|
3071
|
+
" duplicate. The same no-body-H1 contract that applies to skill",
|
|
3072
|
+
" templates and inline agent templates also applies to every",
|
|
3073
|
+
" index page emitted by an agent.",
|
|
3074
|
+
"",
|
|
3075
|
+
"## When this applies",
|
|
3076
|
+
"",
|
|
3077
|
+
"The convention applies to every `index.md` / `README.md` file",
|
|
3078
|
+
"covered by the shared-index path globs documented in the",
|
|
3079
|
+
"`shared-editing-safety` rule:",
|
|
3080
|
+
"",
|
|
3081
|
+
"- `docs/src/content/docs/**/index.md`",
|
|
3082
|
+
"- `docs/src/content/docs/**/README.md`",
|
|
3083
|
+
"",
|
|
3084
|
+
"Any agent that scaffolds a new directory under a Starlight",
|
|
3085
|
+
"content root MUST populate the directory's index page following",
|
|
3086
|
+
"this contract \u2014 a one-sentence stub is not acceptable.",
|
|
3087
|
+
"",
|
|
3088
|
+
"## Reference shapes",
|
|
3089
|
+
"",
|
|
3090
|
+
"Existing rich indexes are the canonical reference shape. Examples:",
|
|
3091
|
+
"",
|
|
3092
|
+
"- A `<MEETINGS_ROOT>/<YYYY-MM-DD>-<slug>/index.md` populated by",
|
|
3093
|
+
" the `agenda-analyst` bundle: frontmatter `title` /",
|
|
3094
|
+
" `description`, a 2\u20134 sentence summary, and a `## Documents`",
|
|
3095
|
+
" section listing every page in the folder.",
|
|
3096
|
+
"- A regulations scope index that opens with two paragraphs of",
|
|
3097
|
+
" context and groups every linked regulation under a",
|
|
3098
|
+
" `## Regulations` table by jurisdiction.",
|
|
3099
|
+
"- A standards-organizations index that groups every linked",
|
|
3100
|
+
" organization under a `## Organizations` heading by role",
|
|
3101
|
+
" (governance, working group, implementer).",
|
|
3102
|
+
"",
|
|
3103
|
+
"## Out of scope",
|
|
3104
|
+
"",
|
|
3105
|
+
"- Auto-generated child listings via Astro/Starlight components.",
|
|
3106
|
+
" Agents emit hand-curated tables or bullet lists; the rule",
|
|
3107
|
+
" defines the shape, not the rendering technology.",
|
|
3108
|
+
"- Backfilling pre-existing stub indexes is a downstream-consumer",
|
|
3109
|
+
" cleanup task, not a configulator change."
|
|
3110
|
+
].join("\n");
|
|
3111
|
+
}
|
|
3112
|
+
|
|
3044
3113
|
// src/agent/bundles/base.ts
|
|
3045
3114
|
var createPackageSkill = {
|
|
3046
3115
|
name: "create-package",
|
|
@@ -4126,6 +4195,16 @@ function buildBaseBundle(paths = DEFAULT_AGENT_PATHS) {
|
|
|
4126
4195
|
},
|
|
4127
4196
|
tags: ["workflow"]
|
|
4128
4197
|
},
|
|
4198
|
+
{
|
|
4199
|
+
name: "stub-index-convention",
|
|
4200
|
+
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).",
|
|
4201
|
+
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
4202
|
+
content: renderStubIndexConventionRuleContent(),
|
|
4203
|
+
platforms: {
|
|
4204
|
+
cursor: { exclude: true }
|
|
4205
|
+
},
|
|
4206
|
+
tags: ["workflow"]
|
|
4207
|
+
},
|
|
4129
4208
|
{
|
|
4130
4209
|
name: "skill-evals",
|
|
4131
4210
|
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.",
|
|
@@ -4401,8 +4480,6 @@ function buildBcmWriterSubAgent(paths) {
|
|
|
4401
4480
|
" tier: L1 | L2 | L3",
|
|
4402
4481
|
" ---",
|
|
4403
4482
|
"",
|
|
4404
|
-
" # BCM Outline: <Capability Name>",
|
|
4405
|
-
"",
|
|
4406
4483
|
" ## Capability Name",
|
|
4407
4484
|
" <noun or noun phrase \u2014 never a verb>",
|
|
4408
4485
|
"",
|
|
@@ -4482,8 +4559,6 @@ function buildBcmWriterSubAgent(paths) {
|
|
|
4482
4559
|
" date: YYYY-MM-DD",
|
|
4483
4560
|
" ---",
|
|
4484
4561
|
"",
|
|
4485
|
-
" # <Capability Name>",
|
|
4486
|
-
"",
|
|
4487
4562
|
" ## Capability Definitions",
|
|
4488
4563
|
" <1\u20132 sentences from the outline's Proposed Definition, refined>",
|
|
4489
4564
|
"",
|
|
@@ -4893,8 +4968,6 @@ title: "Business Model: <Segment Name>"
|
|
|
4893
4968
|
description: "Business Model Canvas analysis for the <segment name> segment of the <industry> industry."
|
|
4894
4969
|
---
|
|
4895
4970
|
|
|
4896
|
-
# Business Model: <Segment Name>
|
|
4897
|
-
|
|
4898
4971
|
| Field | Value |
|
|
4899
4972
|
|-------|-------|
|
|
4900
4973
|
| **Industry** | <industry name> |
|
|
@@ -5278,8 +5351,6 @@ function buildBusinessModelsAnalystSubAgent(paths) {
|
|
|
5278
5351
|
" status: complete",
|
|
5279
5352
|
" ---",
|
|
5280
5353
|
"",
|
|
5281
|
-
" # Business Model Scan: <Industry Name>",
|
|
5282
|
-
"",
|
|
5283
5354
|
" ## Source Inputs",
|
|
5284
5355
|
" - Industry plan: <relative path>",
|
|
5285
5356
|
" - Prior research: <relative path> (optional)",
|
|
@@ -5367,8 +5438,12 @@ function buildBusinessModelsAnalystSubAgent(paths) {
|
|
|
5367
5438
|
"",
|
|
5368
5439
|
"7. **Create the segment index** at",
|
|
5369
5440
|
" `<BUSINESS_MODELS_ROOT>/<industry>/segments/<SEGMENT_SLUG>/index.md`",
|
|
5370
|
-
" if it does not already exist.
|
|
5371
|
-
"
|
|
5441
|
+
" if it does not already exist. Follow the",
|
|
5442
|
+
" `stub-index-convention` rule: a 1\u20132 paragraph summary of the",
|
|
5443
|
+
" segment plus a linked listing of every page in the folder",
|
|
5444
|
+
" (`./business-model.md` and any value-stream / capability pages",
|
|
5445
|
+
" that land later). No body `# Heading` \u2014 the frontmatter",
|
|
5446
|
+
" `title:` already renders as the page H1.",
|
|
5372
5447
|
"",
|
|
5373
5448
|
"8. **Create one `business-models:complete` issue** with",
|
|
5374
5449
|
" `Depends on: #<canvas-issue>`. Its body references the path to",
|
|
@@ -6159,8 +6234,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
|
|
|
6159
6234
|
" parent_issue: <N>",
|
|
6160
6235
|
" ---",
|
|
6161
6236
|
"",
|
|
6162
|
-
" # Research Notes: <company name>",
|
|
6163
|
-
"",
|
|
6164
6237
|
" ## Framing",
|
|
6165
6238
|
" <why this company was requested and what to learn>",
|
|
6166
6239
|
"",
|
|
@@ -6222,8 +6295,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
|
|
|
6222
6295
|
" referencedIn: []",
|
|
6223
6296
|
" ---",
|
|
6224
6297
|
"",
|
|
6225
|
-
" # <company name>",
|
|
6226
|
-
"",
|
|
6227
6298
|
" ## Summary",
|
|
6228
6299
|
" <2\u20134 sentence elevator description: what they do, who they sell to>",
|
|
6229
6300
|
"",
|
|
@@ -6634,8 +6705,6 @@ function buildCompanyProfileAnalystSubAgent(paths) {
|
|
|
6634
6705
|
" - <relative path to profile 2>",
|
|
6635
6706
|
" ---",
|
|
6636
6707
|
"",
|
|
6637
|
-
" # <segment name> Competitive Analysis",
|
|
6638
|
-
"",
|
|
6639
6708
|
" ## Market Overview",
|
|
6640
6709
|
" <landscape summary \u2014 total players, market structure, trends",
|
|
6641
6710
|
" visible from the profiles>",
|
|
@@ -7198,8 +7267,6 @@ archetype: <ARCHETYPE_SLUG>
|
|
|
7198
7267
|
segment: <SEGMENT_SLUG>
|
|
7199
7268
|
---
|
|
7200
7269
|
|
|
7201
|
-
# <Customer Archetype Name>
|
|
7202
|
-
|
|
7203
7270
|
| Field | Value |
|
|
7204
7271
|
|-------|-------|
|
|
7205
7272
|
| **Archetype** | <short noun phrase identifying the archetype> |
|
|
@@ -7565,8 +7632,6 @@ function buildCustomerProfileAnalystSubAgent(paths) {
|
|
|
7565
7632
|
" scope: <SCOPE_SLUG>",
|
|
7566
7633
|
" ---",
|
|
7567
7634
|
"",
|
|
7568
|
-
" # Customer Discovery: <Scope>",
|
|
7569
|
-
"",
|
|
7570
7635
|
" ## Scope Context",
|
|
7571
7636
|
" - **Scope:** <SCOPE_SLUG>",
|
|
7572
7637
|
" - **Sources scanned:** <counts by source type>",
|
|
@@ -7712,8 +7777,6 @@ function buildCustomerProfileAnalystSubAgent(paths) {
|
|
|
7712
7777
|
" archetype: <ARCHETYPE_SLUG>",
|
|
7713
7778
|
" ---",
|
|
7714
7779
|
"",
|
|
7715
|
-
" # Competitors: <Archetype Name>",
|
|
7716
|
-
"",
|
|
7717
7780
|
" ## Market Overview",
|
|
7718
7781
|
" <Brief overview of the competitive landscape this archetype",
|
|
7719
7782
|
" evaluates.>",
|
|
@@ -9620,8 +9683,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
|
|
|
9620
9683
|
" candidate_count: <N>",
|
|
9621
9684
|
" ---",
|
|
9622
9685
|
"",
|
|
9623
|
-
" # Industry Candidates: <scope>",
|
|
9624
|
-
"",
|
|
9625
9686
|
" ## Scope",
|
|
9626
9687
|
" <verbatim scope statement from the issue>",
|
|
9627
9688
|
"",
|
|
@@ -9682,8 +9743,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
|
|
|
9682
9743
|
" threshold: <0.0\u20131.0>",
|
|
9683
9744
|
" ---",
|
|
9684
9745
|
"",
|
|
9685
|
-
" # Industry Evaluation: <scope>",
|
|
9686
|
-
"",
|
|
9687
9746
|
" ## Fit Rubric",
|
|
9688
9747
|
" <verbatim rubric table, including weights and threshold>",
|
|
9689
9748
|
"",
|
|
@@ -9740,8 +9799,6 @@ function buildIndustryDiscoveryAnalystSubAgent(paths) {
|
|
|
9740
9799
|
" evaluation_source: <EVALUATIONS_DIR>/<DISCOVERY_SLUG>.evaluation.md",
|
|
9741
9800
|
" ---",
|
|
9742
9801
|
"",
|
|
9743
|
-
" # Industry Plan: <scope>",
|
|
9744
|
-
"",
|
|
9745
9802
|
" ## Cleared Verticals",
|
|
9746
9803
|
" | Vertical | Score | Downstream Issue |",
|
|
9747
9804
|
" |----------|-------|------------------|",
|
|
@@ -10194,8 +10251,6 @@ function buildMaintenanceAuditSubAgent(paths) {
|
|
|
10194
10251
|
" status: complete",
|
|
10195
10252
|
" ---",
|
|
10196
10253
|
"",
|
|
10197
|
-
" # Maintenance Audit: <AUDIT_SLUG>",
|
|
10198
|
-
"",
|
|
10199
10254
|
" ## Scope",
|
|
10200
10255
|
" - **Docs root:** `<DOCS_ROOT>`",
|
|
10201
10256
|
" - **Checks run:** <list of check categories>",
|
|
@@ -10317,8 +10372,6 @@ function buildMaintenanceAuditSubAgent(paths) {
|
|
|
10317
10372
|
" status: complete",
|
|
10318
10373
|
" ---",
|
|
10319
10374
|
"",
|
|
10320
|
-
" # Maintenance Fix: <AUDIT_SLUG>",
|
|
10321
|
-
"",
|
|
10322
10375
|
" ## Source Audit Report",
|
|
10323
10376
|
" <link to the Phase 1 audit report>",
|
|
10324
10377
|
"",
|
|
@@ -10419,8 +10472,6 @@ function buildMaintenanceAuditSubAgent(paths) {
|
|
|
10419
10472
|
" status: complete",
|
|
10420
10473
|
" ---",
|
|
10421
10474
|
"",
|
|
10422
|
-
" # Maintenance Verify: <AUDIT_SLUG>",
|
|
10423
|
-
"",
|
|
10424
10475
|
" ## Source Reports",
|
|
10425
10476
|
" - Scan report: <link>",
|
|
10426
10477
|
" - Fix report: <link>",
|
|
@@ -12011,6 +12062,14 @@ var DEFAULT_SOURCES_THRESHOLDS = {
|
|
|
12011
12062
|
smallMax: 2,
|
|
12012
12063
|
mediumMax: 5
|
|
12013
12064
|
};
|
|
12065
|
+
var DEFAULT_BUNDLE_OVERRIDES = {
|
|
12066
|
+
"req:write": {
|
|
12067
|
+
acceptanceCriteria: { smallMax: 3, mediumMax: 20 }
|
|
12068
|
+
},
|
|
12069
|
+
"bcm:scaffold": {
|
|
12070
|
+
acceptanceCriteria: { smallMax: 3, mediumMax: 12 }
|
|
12071
|
+
}
|
|
12072
|
+
};
|
|
12014
12073
|
var DEFAULT_DECOMPOSITION_TEMPLATE = [
|
|
12015
12074
|
"## Scope gate: issue is too large to dispatch",
|
|
12016
12075
|
"",
|
|
@@ -12050,22 +12109,58 @@ function resolveScopeGate(config) {
|
|
|
12050
12109
|
DEFAULT_SOURCES_THRESHOLDS,
|
|
12051
12110
|
"sources"
|
|
12052
12111
|
);
|
|
12112
|
+
const bundleOverrides = resolveBundleOverrides(
|
|
12113
|
+
config?.bundleOverrides,
|
|
12114
|
+
DEFAULT_BUNDLE_OVERRIDES
|
|
12115
|
+
);
|
|
12053
12116
|
return {
|
|
12054
12117
|
enabled: config?.enabled ?? true,
|
|
12055
12118
|
acceptanceCriteria: ac,
|
|
12056
12119
|
sources,
|
|
12057
12120
|
autoFile: config?.autoFile ?? false,
|
|
12058
|
-
decompositionTemplate: config?.decompositionTemplate ?? DEFAULT_DECOMPOSITION_TEMPLATE
|
|
12121
|
+
decompositionTemplate: config?.decompositionTemplate ?? DEFAULT_DECOMPOSITION_TEMPLATE,
|
|
12122
|
+
bundleOverrides
|
|
12123
|
+
};
|
|
12124
|
+
}
|
|
12125
|
+
function resolveOverrideForLabels(gate, labels) {
|
|
12126
|
+
const overrideKeys = Object.keys(gate.bundleOverrides);
|
|
12127
|
+
if (overrideKeys.length === 0 || labels.length === 0) {
|
|
12128
|
+
return {
|
|
12129
|
+
acceptanceCriteria: gate.acceptanceCriteria,
|
|
12130
|
+
sources: gate.sources
|
|
12131
|
+
};
|
|
12132
|
+
}
|
|
12133
|
+
const sortedLabels = [...labels].sort((a, b) => a.localeCompare(b));
|
|
12134
|
+
const matchedLabel = sortedLabels.find(
|
|
12135
|
+
(label) => Object.prototype.hasOwnProperty.call(gate.bundleOverrides, label)
|
|
12136
|
+
);
|
|
12137
|
+
if (matchedLabel === void 0) {
|
|
12138
|
+
return {
|
|
12139
|
+
acceptanceCriteria: gate.acceptanceCriteria,
|
|
12140
|
+
sources: gate.sources
|
|
12141
|
+
};
|
|
12142
|
+
}
|
|
12143
|
+
const override = gate.bundleOverrides[matchedLabel];
|
|
12144
|
+
return {
|
|
12145
|
+
acceptanceCriteria: override.acceptanceCriteria ?? gate.acceptanceCriteria,
|
|
12146
|
+
sources: override.sources ?? gate.sources,
|
|
12147
|
+
matchedLabel
|
|
12059
12148
|
};
|
|
12060
12149
|
}
|
|
12061
12150
|
function validateScopeGateConfig(config) {
|
|
12062
12151
|
return resolveScopeGate(config);
|
|
12063
12152
|
}
|
|
12064
|
-
function classifyIssueScope(body, gate) {
|
|
12153
|
+
function classifyIssueScope(body, gate, labels = []) {
|
|
12065
12154
|
const acCount = countAcceptanceCriteria(body);
|
|
12066
12155
|
const sourcesCount = countSources(body);
|
|
12067
|
-
const
|
|
12068
|
-
|
|
12156
|
+
const effective = resolveOverrideForLabels(gate, labels);
|
|
12157
|
+
const scope = resolveScopeClass(acCount, sourcesCount, effective);
|
|
12158
|
+
return {
|
|
12159
|
+
scope,
|
|
12160
|
+
acCount,
|
|
12161
|
+
sourcesCount,
|
|
12162
|
+
matchedLabel: effective.matchedLabel
|
|
12163
|
+
};
|
|
12069
12164
|
}
|
|
12070
12165
|
function renderScopeGateSection(gate) {
|
|
12071
12166
|
const { acceptanceCriteria: ac, sources } = gate;
|
|
@@ -12141,6 +12236,38 @@ function renderScopeGateSection(gate) {
|
|
|
12141
12236
|
" is in place."
|
|
12142
12237
|
);
|
|
12143
12238
|
}
|
|
12239
|
+
const overrideEntries = Object.entries(gate.bundleOverrides);
|
|
12240
|
+
if (overrideEntries.length > 0) {
|
|
12241
|
+
lines.push(
|
|
12242
|
+
"",
|
|
12243
|
+
"### Per-phase-label thresholds",
|
|
12244
|
+
"",
|
|
12245
|
+
"Issues whose `type:*` or phase label matches an entry below are",
|
|
12246
|
+
"classified against the override's thresholds instead of the",
|
|
12247
|
+
"global `acceptance-criteria` / `sources` defaults. This",
|
|
12248
|
+
"accommodates **content-spec workflows** \u2014 issues whose AC list",
|
|
12249
|
+
"is the per-section content checklist for one cohesive document,",
|
|
12250
|
+
"not a phase-completion checklist that can be decomposed.",
|
|
12251
|
+
"",
|
|
12252
|
+
"| Phase label | AC `mediumMax` | Sources `mediumMax` |",
|
|
12253
|
+
"|-------------|----------------|---------------------|"
|
|
12254
|
+
);
|
|
12255
|
+
const sortedKeys = overrideEntries.map(([k]) => k).sort();
|
|
12256
|
+
for (const label of sortedKeys) {
|
|
12257
|
+
const override = gate.bundleOverrides[label];
|
|
12258
|
+
const acMax = override.acceptanceCriteria?.mediumMax;
|
|
12259
|
+
const sourcesMax = override.sources?.mediumMax;
|
|
12260
|
+
const acCell = acMax === void 0 ? "_(global)_" : `${acMax}`;
|
|
12261
|
+
const sourcesCell = sourcesMax === void 0 ? "_(global)_" : `${sourcesMax}`;
|
|
12262
|
+
lines.push(`| \`${label}\` | ${acCell} | ${sourcesCell} |`);
|
|
12263
|
+
}
|
|
12264
|
+
lines.push(
|
|
12265
|
+
"",
|
|
12266
|
+
"When an issue carries multiple labels that each match an entry",
|
|
12267
|
+
"in this table, the orchestrator picks the **first match in",
|
|
12268
|
+
"alphabetical order on the label name** \u2014 first-wins, deterministic."
|
|
12269
|
+
);
|
|
12270
|
+
}
|
|
12144
12271
|
lines.push(
|
|
12145
12272
|
"",
|
|
12146
12273
|
"### Decomposition-proposal template",
|
|
@@ -12157,12 +12284,21 @@ function renderScopeGateSection(gate) {
|
|
|
12157
12284
|
}
|
|
12158
12285
|
function renderScopeGateShellHelpers(gate) {
|
|
12159
12286
|
const { acceptanceCriteria: ac, sources } = gate;
|
|
12160
|
-
|
|
12287
|
+
const lines = [
|
|
12161
12288
|
"# Classify an issue body against the scope-gate thresholds.",
|
|
12162
12289
|
"# Reads the issue body from stdin. Echoes one of 'small',",
|
|
12163
12290
|
"# 'medium', or 'large' on stdout. Writes the observed counts to",
|
|
12164
12291
|
"# stderr as `ac=<n> sources=<n>` so the caller can embed them in",
|
|
12165
12292
|
"# the decomposition-proposal comment.",
|
|
12293
|
+
"#",
|
|
12294
|
+
"# Effective per-issue thresholds are read from the four",
|
|
12295
|
+
"# `_EFFECTIVE_*` shell variables. The caller is expected to set",
|
|
12296
|
+
"# them via `bundle_override_for()` before invoking scope_of();",
|
|
12297
|
+
"# defaults preserve the global thresholds.",
|
|
12298
|
+
`_EFFECTIVE_AC_SMALL_MAX="\${_EFFECTIVE_AC_SMALL_MAX:-${ac.smallMax}}"`,
|
|
12299
|
+
`_EFFECTIVE_AC_MEDIUM_MAX="\${_EFFECTIVE_AC_MEDIUM_MAX:-${ac.mediumMax}}"`,
|
|
12300
|
+
`_EFFECTIVE_SOURCES_SMALL_MAX="\${_EFFECTIVE_SOURCES_SMALL_MAX:-${sources.smallMax}}"`,
|
|
12301
|
+
`_EFFECTIVE_SOURCES_MEDIUM_MAX="\${_EFFECTIVE_SOURCES_MEDIUM_MAX:-${sources.mediumMax}}"`,
|
|
12166
12302
|
"scope_of() {",
|
|
12167
12303
|
" local body",
|
|
12168
12304
|
" body=$(cat)",
|
|
@@ -12191,15 +12327,79 @@ function renderScopeGateShellHelpers(gate) {
|
|
|
12191
12327
|
" END { print count }",
|
|
12192
12328
|
" ')",
|
|
12193
12329
|
` printf 'ac=%s sources=%s\\n' "$ac_count" "$sources_count" >&2`,
|
|
12194
|
-
|
|
12330
|
+
' if [ "$ac_count" -le "$_EFFECTIVE_AC_SMALL_MAX" ] && [ "$sources_count" -le "$_EFFECTIVE_SOURCES_SMALL_MAX" ]; then',
|
|
12195
12331
|
" echo small",
|
|
12196
|
-
|
|
12332
|
+
' elif [ "$ac_count" -le "$_EFFECTIVE_AC_MEDIUM_MAX" ] && [ "$sources_count" -le "$_EFFECTIVE_SOURCES_MEDIUM_MAX" ]; then',
|
|
12197
12333
|
" echo medium",
|
|
12198
12334
|
" else",
|
|
12199
12335
|
" echo large",
|
|
12200
12336
|
" fi",
|
|
12337
|
+
"}",
|
|
12338
|
+
"",
|
|
12339
|
+
"# Resolve per-phase-label threshold overrides. Reads a newline-",
|
|
12340
|
+
"# separated list of label names on stdin and echoes effective",
|
|
12341
|
+
"# threshold variable assignments (one per line) on stdout. The",
|
|
12342
|
+
"# caller `eval`s the output to set the four `_EFFECTIVE_*`",
|
|
12343
|
+
"# variables before calling `scope_of()`. Also echoes",
|
|
12344
|
+
"# `MATCHED_LABEL=<label>` (or `MATCHED_LABEL=`) so the caller can",
|
|
12345
|
+
"# report which override fired.",
|
|
12346
|
+
"#",
|
|
12347
|
+
"# Tie-breaking: when more than one label matches an override key,",
|
|
12348
|
+
"# the alphabetical first-wins rule applies \u2014 the same rule the",
|
|
12349
|
+
"# TypeScript classifier uses.",
|
|
12350
|
+
"bundle_override_for() {",
|
|
12351
|
+
` local default_ac_small=${ac.smallMax}`,
|
|
12352
|
+
` local default_ac_medium=${ac.mediumMax}`,
|
|
12353
|
+
` local default_sources_small=${sources.smallMax}`,
|
|
12354
|
+
` local default_sources_medium=${sources.mediumMax}`,
|
|
12355
|
+
" # Sort labels alphabetically so the first match is deterministic.",
|
|
12356
|
+
" local sorted_labels",
|
|
12357
|
+
" sorted_labels=$(LC_ALL=C sort)",
|
|
12358
|
+
" local matched_label=''",
|
|
12359
|
+
" local ac_small=$default_ac_small",
|
|
12360
|
+
" local ac_medium=$default_ac_medium",
|
|
12361
|
+
" local sources_small=$default_sources_small",
|
|
12362
|
+
" local sources_medium=$default_sources_medium",
|
|
12363
|
+
" while IFS= read -r label; do",
|
|
12364
|
+
' [ -z "$label" ] && continue',
|
|
12365
|
+
` case "$label" in`
|
|
12366
|
+
];
|
|
12367
|
+
const sortedKeys = Object.keys(gate.bundleOverrides).sort();
|
|
12368
|
+
if (sortedKeys.length === 0) {
|
|
12369
|
+
lines.push(" *) ;;");
|
|
12370
|
+
} else {
|
|
12371
|
+
for (const label of sortedKeys) {
|
|
12372
|
+
const override = gate.bundleOverrides[label];
|
|
12373
|
+
const acThresholds = override.acceptanceCriteria;
|
|
12374
|
+
const sourcesThresholds = override.sources;
|
|
12375
|
+
const branchLines = [` '${label}')`];
|
|
12376
|
+
if (acThresholds !== void 0) {
|
|
12377
|
+
branchLines.push(` ac_small=${acThresholds.smallMax}`);
|
|
12378
|
+
branchLines.push(` ac_medium=${acThresholds.mediumMax}`);
|
|
12379
|
+
}
|
|
12380
|
+
if (sourcesThresholds !== void 0) {
|
|
12381
|
+
branchLines.push(` sources_small=${sourcesThresholds.smallMax}`);
|
|
12382
|
+
branchLines.push(
|
|
12383
|
+
` sources_medium=${sourcesThresholds.mediumMax}`
|
|
12384
|
+
);
|
|
12385
|
+
}
|
|
12386
|
+
branchLines.push(` matched_label='${label}'`);
|
|
12387
|
+
branchLines.push(" break");
|
|
12388
|
+
branchLines.push(" ;;");
|
|
12389
|
+
lines.push(...branchLines);
|
|
12390
|
+
}
|
|
12391
|
+
}
|
|
12392
|
+
lines.push(
|
|
12393
|
+
" esac",
|
|
12394
|
+
` done <<<"$sorted_labels"`,
|
|
12395
|
+
` printf 'MATCHED_LABEL=%s\\n' "$matched_label"`,
|
|
12396
|
+
` printf '_EFFECTIVE_AC_SMALL_MAX=%s\\n' "$ac_small"`,
|
|
12397
|
+
` printf '_EFFECTIVE_AC_MEDIUM_MAX=%s\\n' "$ac_medium"`,
|
|
12398
|
+
` printf '_EFFECTIVE_SOURCES_SMALL_MAX=%s\\n' "$sources_small"`,
|
|
12399
|
+
` printf '_EFFECTIVE_SOURCES_MEDIUM_MAX=%s\\n' "$sources_medium"`,
|
|
12201
12400
|
"}"
|
|
12202
|
-
|
|
12401
|
+
);
|
|
12402
|
+
return lines.join("\n");
|
|
12203
12403
|
}
|
|
12204
12404
|
function resolveThresholds(supplied, defaults, field) {
|
|
12205
12405
|
const merged = {
|
|
@@ -12209,6 +12409,42 @@ function resolveThresholds(supplied, defaults, field) {
|
|
|
12209
12409
|
assertValidThresholds(merged, field);
|
|
12210
12410
|
return merged;
|
|
12211
12411
|
}
|
|
12412
|
+
function resolveBundleOverrides(supplied, defaults) {
|
|
12413
|
+
const out = {};
|
|
12414
|
+
for (const [label, override] of Object.entries(defaults)) {
|
|
12415
|
+
out[label] = override;
|
|
12416
|
+
}
|
|
12417
|
+
if (supplied !== void 0) {
|
|
12418
|
+
for (const label of Object.keys(supplied)) {
|
|
12419
|
+
const value = supplied[label];
|
|
12420
|
+
if (value === void 0) {
|
|
12421
|
+
delete out[label];
|
|
12422
|
+
continue;
|
|
12423
|
+
}
|
|
12424
|
+
const resolved = {};
|
|
12425
|
+
if (value.acceptanceCriteria !== void 0) {
|
|
12426
|
+
resolved.acceptanceCriteria = resolveThresholds(
|
|
12427
|
+
value.acceptanceCriteria,
|
|
12428
|
+
DEFAULT_AC_THRESHOLDS,
|
|
12429
|
+
"acceptanceCriteria"
|
|
12430
|
+
);
|
|
12431
|
+
}
|
|
12432
|
+
if (value.sources !== void 0) {
|
|
12433
|
+
resolved.sources = resolveThresholds(
|
|
12434
|
+
value.sources,
|
|
12435
|
+
DEFAULT_SOURCES_THRESHOLDS,
|
|
12436
|
+
"sources"
|
|
12437
|
+
);
|
|
12438
|
+
}
|
|
12439
|
+
if (resolved.acceptanceCriteria === void 0 && resolved.sources === void 0) {
|
|
12440
|
+
delete out[label];
|
|
12441
|
+
continue;
|
|
12442
|
+
}
|
|
12443
|
+
out[label] = resolved;
|
|
12444
|
+
}
|
|
12445
|
+
}
|
|
12446
|
+
return out;
|
|
12447
|
+
}
|
|
12212
12448
|
function assertValidThresholds(thresholds, field) {
|
|
12213
12449
|
const { smallMax, mediumMax } = thresholds;
|
|
12214
12450
|
for (const [key, value] of [
|
|
@@ -12232,8 +12468,8 @@ function assertValidThresholds(thresholds, field) {
|
|
|
12232
12468
|
);
|
|
12233
12469
|
}
|
|
12234
12470
|
}
|
|
12235
|
-
function resolveScopeClass(acCount, sourcesCount,
|
|
12236
|
-
const { acceptanceCriteria: ac, sources } =
|
|
12471
|
+
function resolveScopeClass(acCount, sourcesCount, thresholds) {
|
|
12472
|
+
const { acceptanceCriteria: ac, sources } = thresholds;
|
|
12237
12473
|
if (acCount <= ac.smallMax && sourcesCount <= sources.smallMax) {
|
|
12238
12474
|
return "small";
|
|
12239
12475
|
}
|
|
@@ -12813,7 +13049,9 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
12813
13049
|
"STALE_BLOCKED_HOURS=168",
|
|
12814
13050
|
`SCOPE_GATE_ENABLED=${scopeGate.enabled ? "1" : "0"}`,
|
|
12815
13051
|
`SCOPE_GATE_AUTO_FILE=${scopeGate.autoFile ? "1" : "0"}`,
|
|
13052
|
+
`SCOPE_AC_SMALL_MAX=${scopeGate.acceptanceCriteria.smallMax}`,
|
|
12816
13053
|
`SCOPE_AC_MEDIUM_MAX=${scopeGate.acceptanceCriteria.mediumMax}`,
|
|
13054
|
+
`SCOPE_SOURCES_SMALL_MAX=${scopeGate.sources.smallMax}`,
|
|
12817
13055
|
`SCOPE_SOURCES_MEDIUM_MAX=${scopeGate.sources.mediumMax}`,
|
|
12818
13056
|
`RUN_RATIO_ENABLED=${runRatio.enabled ? "1" : "0"}`,
|
|
12819
13057
|
`RUN_RATIO_DISPATCH_PER_HOUSEKEEPING=${runRatio.ratio}`,
|
|
@@ -13167,12 +13405,45 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13167
13405
|
' echo "SCOPE #${issue_num} disabled"',
|
|
13168
13406
|
" return 0",
|
|
13169
13407
|
" fi",
|
|
13408
|
+
" # Fetch the body and labels in a single API call so we resolve",
|
|
13409
|
+
" # any per-phase-label override against the issue's actual labels.",
|
|
13410
|
+
" local issue_json",
|
|
13411
|
+
' issue_json=$(gh issue view "$issue_num" --json body,labels 2>/dev/null || echo "")',
|
|
13412
|
+
' if [[ -z "$issue_json" ]]; then',
|
|
13413
|
+
' echo "SCOPE #${issue_num} unknown \u2014 could not read issue body"',
|
|
13414
|
+
" return 1",
|
|
13415
|
+
" fi",
|
|
13170
13416
|
" local body",
|
|
13171
|
-
` body=$(
|
|
13417
|
+
` body=$(printf '%s' "$issue_json" | jq -r '.body // ""')`,
|
|
13172
13418
|
' if [[ -z "$body" ]]; then',
|
|
13173
13419
|
' echo "SCOPE #${issue_num} unknown \u2014 could not read issue body"',
|
|
13174
13420
|
" return 1",
|
|
13175
13421
|
" fi",
|
|
13422
|
+
" local labels",
|
|
13423
|
+
` labels=$(printf '%s' "$issue_json" | jq -r '.labels[]?.name // empty')`,
|
|
13424
|
+
" # Resolve the effective thresholds. `bundle_override_for` reads",
|
|
13425
|
+
" # labels on stdin and emits `KEY=VALUE` assignments (one per line)",
|
|
13426
|
+
" # for the four `_EFFECTIVE_*` variables plus `MATCHED_LABEL`.",
|
|
13427
|
+
" local override_output",
|
|
13428
|
+
` override_output=$(printf '%s\\n' "$labels" | bundle_override_for)`,
|
|
13429
|
+
" local matched_label=''",
|
|
13430
|
+
" local _EFFECTIVE_AC_SMALL_MAX=$SCOPE_AC_SMALL_MAX",
|
|
13431
|
+
" local _EFFECTIVE_AC_MEDIUM_MAX=$SCOPE_AC_MEDIUM_MAX",
|
|
13432
|
+
" local _EFFECTIVE_SOURCES_SMALL_MAX=$SCOPE_SOURCES_SMALL_MAX",
|
|
13433
|
+
" local _EFFECTIVE_SOURCES_MEDIUM_MAX=$SCOPE_SOURCES_MEDIUM_MAX",
|
|
13434
|
+
" while IFS= read -r assignment; do",
|
|
13435
|
+
' [ -z "$assignment" ] && continue',
|
|
13436
|
+
' case "$assignment" in',
|
|
13437
|
+
" MATCHED_LABEL=*) matched_label=${assignment#MATCHED_LABEL=} ;;",
|
|
13438
|
+
" _EFFECTIVE_AC_SMALL_MAX=*) _EFFECTIVE_AC_SMALL_MAX=${assignment#_EFFECTIVE_AC_SMALL_MAX=} ;;",
|
|
13439
|
+
" _EFFECTIVE_AC_MEDIUM_MAX=*) _EFFECTIVE_AC_MEDIUM_MAX=${assignment#_EFFECTIVE_AC_MEDIUM_MAX=} ;;",
|
|
13440
|
+
" _EFFECTIVE_SOURCES_SMALL_MAX=*) _EFFECTIVE_SOURCES_SMALL_MAX=${assignment#_EFFECTIVE_SOURCES_SMALL_MAX=} ;;",
|
|
13441
|
+
" _EFFECTIVE_SOURCES_MEDIUM_MAX=*) _EFFECTIVE_SOURCES_MEDIUM_MAX=${assignment#_EFFECTIVE_SOURCES_MEDIUM_MAX=} ;;",
|
|
13442
|
+
" esac",
|
|
13443
|
+
' done <<<"$override_output"',
|
|
13444
|
+
" # Export the effective thresholds so scope_of() picks them up.",
|
|
13445
|
+
" export _EFFECTIVE_AC_SMALL_MAX _EFFECTIVE_AC_MEDIUM_MAX",
|
|
13446
|
+
" export _EFFECTIVE_SOURCES_SMALL_MAX _EFFECTIVE_SOURCES_MEDIUM_MAX",
|
|
13176
13447
|
" local scope counts",
|
|
13177
13448
|
" # scope_of writes counts to stderr (ac=N sources=N); capture both.",
|
|
13178
13449
|
` scope=$(printf '%s' "$body" | scope_of 2> >(read -r counts; echo "$counts" >&2))`,
|
|
@@ -13186,9 +13457,17 @@ function buildCheckBlockedScript(tiers, scopeGate, runRatio) {
|
|
|
13186
13457
|
` sources_count=$(echo "$stderr_capture" | grep -oE 'sources=[0-9]+' | head -1 | cut -d= -f2)`,
|
|
13187
13458
|
" ac_count=${ac_count:-0}",
|
|
13188
13459
|
" sources_count=${sources_count:-0}",
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
'
|
|
13460
|
+
' if [ -n "$matched_label" ]; then',
|
|
13461
|
+
" printf 'SCOPE #%s %s ac=%s sources=%s ac_limit=%s sources_limit=%s auto_file=%s matched_label=%s\\n' \\",
|
|
13462
|
+
' "$issue_num" "$scope" "$ac_count" "$sources_count" \\',
|
|
13463
|
+
' "$_EFFECTIVE_AC_MEDIUM_MAX" "$_EFFECTIVE_SOURCES_MEDIUM_MAX" \\',
|
|
13464
|
+
' "$SCOPE_GATE_AUTO_FILE" "$matched_label"',
|
|
13465
|
+
" else",
|
|
13466
|
+
" printf 'SCOPE #%s %s ac=%s sources=%s ac_limit=%s sources_limit=%s auto_file=%s\\n' \\",
|
|
13467
|
+
' "$issue_num" "$scope" "$ac_count" "$sources_count" \\',
|
|
13468
|
+
' "$_EFFECTIVE_AC_MEDIUM_MAX" "$_EFFECTIVE_SOURCES_MEDIUM_MAX" \\',
|
|
13469
|
+
' "$SCOPE_GATE_AUTO_FILE"',
|
|
13470
|
+
" fi",
|
|
13192
13471
|
"}",
|
|
13193
13472
|
"",
|
|
13194
13473
|
"cmd_tick() {",
|
|
@@ -13393,9 +13672,16 @@ var orchestratorSubAgent = {
|
|
|
13393
13672
|
"The output is one line of the form:",
|
|
13394
13673
|
"",
|
|
13395
13674
|
"```",
|
|
13396
|
-
"SCOPE #<n> <small|medium|large> ac=<n> sources=<n> ac_limit=<n> sources_limit=<n> auto_file=<0|1>",
|
|
13675
|
+
"SCOPE #<n> <small|medium|large> ac=<n> sources=<n> ac_limit=<n> sources_limit=<n> auto_file=<0|1> [matched_label=<label>]",
|
|
13397
13676
|
"```",
|
|
13398
13677
|
"",
|
|
13678
|
+
"When `matched_label=<label>` is present, the scope gate applied a",
|
|
13679
|
+
"per-phase-label override (e.g. `req:write` raises the AC ceiling to",
|
|
13680
|
+
"20 for content-spec workflows whose AC list is the per-section",
|
|
13681
|
+
"checklist for one document). The `ac_limit` / `sources_limit`",
|
|
13682
|
+
"values reflect the override; the global thresholds are documented",
|
|
13683
|
+
"in the **Scope gate** section in `CLAUDE.md`.",
|
|
13684
|
+
"",
|
|
13399
13685
|
"If the scope is `small` or `medium`, continue \u2014 the issue is",
|
|
13400
13686
|
"dispatchable. Record the first `PICK` line as the next work item",
|
|
13401
13687
|
"and proceed to Phase G:",
|
|
@@ -14352,8 +14638,6 @@ function buildPeopleProfileAnalystSubAgent(paths) {
|
|
|
14352
14638
|
" parent_issue: <N>",
|
|
14353
14639
|
" ---",
|
|
14354
14640
|
"",
|
|
14355
|
-
" # Research Notes: <person name>",
|
|
14356
|
-
"",
|
|
14357
14641
|
" ## Framing",
|
|
14358
14642
|
" <why this person was requested and what to learn>",
|
|
14359
14643
|
"",
|
|
@@ -14415,8 +14699,6 @@ function buildPeopleProfileAnalystSubAgent(paths) {
|
|
|
14415
14699
|
" notes: <NOTES_DIR>/<PERSON_SLUG>.notes.md",
|
|
14416
14700
|
" ---",
|
|
14417
14701
|
"",
|
|
14418
|
-
" # <person name>",
|
|
14419
|
-
"",
|
|
14420
14702
|
" ## Summary",
|
|
14421
14703
|
" <2\u20134 sentence elevator description: who they are, what they do,",
|
|
14422
14704
|
" why they matter to this project>",
|
|
@@ -17000,8 +17282,6 @@ jurisdiction: <federal | state | provincial | international | local>
|
|
|
17000
17282
|
industry: <industry-slug or 'platform'>
|
|
17001
17283
|
---
|
|
17002
17284
|
|
|
17003
|
-
# <Regulation Name>
|
|
17004
|
-
|
|
17005
17285
|
| Field | Value |
|
|
17006
17286
|
|-------|-------|
|
|
17007
17287
|
| **Official name** | <full legal name> |
|
|
@@ -17372,8 +17652,6 @@ function buildRegulatoryResearchAnalystSubAgent(paths) {
|
|
|
17372
17652
|
" scope: <SCOPE_SLUG>",
|
|
17373
17653
|
" ---",
|
|
17374
17654
|
"",
|
|
17375
|
-
" # Regulatory Scan: <Scope>",
|
|
17376
|
-
"",
|
|
17377
17655
|
" ## Scope Context",
|
|
17378
17656
|
" - **Scope type:** <industry / jurisdiction / platform>",
|
|
17379
17657
|
" - **Scope identifier:** <SCOPE_SLUG>",
|
|
@@ -17424,7 +17702,12 @@ function buildRegulatoryResearchAnalystSubAgent(paths) {
|
|
|
17424
17702
|
"",
|
|
17425
17703
|
"7. **Create or update the scope index page** at",
|
|
17426
17704
|
" `<SCOPE_INDEX_PAGE>` so downstream regulations link back to a",
|
|
17427
|
-
" coherent landing page for the scope.",
|
|
17705
|
+
" coherent landing page for the scope. Follow the",
|
|
17706
|
+
" `stub-index-convention` rule: the body must carry a 1\u20132",
|
|
17707
|
+
" paragraph contextual summary plus a grouped, linked listing of",
|
|
17708
|
+
" every regulation in the scope (e.g. by jurisdiction). No body",
|
|
17709
|
+
" `# Heading` \u2014 the frontmatter `title:` already renders as the",
|
|
17710
|
+
" page H1.",
|
|
17428
17711
|
"",
|
|
17429
17712
|
"8. **Commit and push** the scan report and the scope index page.",
|
|
17430
17713
|
" Close the scan issue.",
|
|
@@ -18282,8 +18565,6 @@ function buildRequirementsAnalystSubAgent(paths) {
|
|
|
18282
18565
|
" status: complete",
|
|
18283
18566
|
" ---",
|
|
18284
18567
|
"",
|
|
18285
|
-
" # Requirements Scan: <scope>",
|
|
18286
|
-
"",
|
|
18287
18568
|
" ## Source Documents Reviewed",
|
|
18288
18569
|
" - <path> \u2014 <brief description>",
|
|
18289
18570
|
"",
|
|
@@ -18419,42 +18700,32 @@ function buildRequirementsAnalystSubAgent(paths) {
|
|
|
18419
18700
|
" directory under `<REQUIREMENTS_ROOT>/<category>/` to find the next",
|
|
18420
18701
|
" available `NNN` for each proposed requirement.",
|
|
18421
18702
|
"",
|
|
18422
|
-
"5. **Create requirement issues.** For each proposal
|
|
18703
|
+
"5. **Create requirement issues.** For each proposal, file a",
|
|
18704
|
+
" `req:write` issue using the canonical recipe documented in",
|
|
18705
|
+
" `## Template: req:write` of",
|
|
18706
|
+
" `docs/src/content/docs/agents/issue-templates.md`.",
|
|
18423
18707
|
"",
|
|
18424
18708
|
" All `type:requirement` issues default to `priority:medium` (override",
|
|
18425
18709
|
" only if the proposal's priority was explicitly High or Low). Each",
|
|
18426
18710
|
" issue must also carry the `req:write` phase label plus the matching",
|
|
18427
18711
|
" `tier:*` label so the downstream `requirements-writer` bundle picks",
|
|
18428
|
-
" it up with the correct tier.",
|
|
18429
|
-
"",
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
' --title "docs(<category>): <PREFIX>-<NNN> \u2014 <title>" \\',
|
|
18433
|
-
' --label "type:requirement" --label "req:write" --label "tier:<tier-slug>" --label "status:ready" --label "priority:medium" \\',
|
|
18434
|
-
' --body "## Objective',
|
|
18435
|
-
" Write <PREFIX>-<NNN> \u2014 <title>.",
|
|
18436
|
-
"",
|
|
18437
|
-
" **Category:** <BR/FR/NFR/TR/ADR/SEC/DR/INT/OPS/UX/MT>",
|
|
18438
|
-
" **Tier:** <platform/industry/customer-workflow/consumer-app>",
|
|
18439
|
-
" **Output Path:** <REQUIREMENTS_ROOT>/<category-dir>/<PREFIX>-<NNN>-<slug>.md",
|
|
18440
|
-
"",
|
|
18441
|
-
" ## Context",
|
|
18442
|
-
" - **Gap identified by:** requirements scan of <source>",
|
|
18443
|
-
" - **Proposals file:** <RESEARCH_REQUIREMENTS_ROOT>/req-proposals-<scope>-<date>.md",
|
|
18712
|
+
" it up with the correct tier. Concretely, the label list includes",
|
|
18713
|
+
' `--label "type:requirement"`, `--label "req:write"`,',
|
|
18714
|
+
' `--label "tier:<tier-slug>"`, `--label "status:ready"`, and',
|
|
18715
|
+
' `--label "priority:medium"`.',
|
|
18444
18716
|
"",
|
|
18445
|
-
"
|
|
18446
|
-
" -
|
|
18447
|
-
"
|
|
18717
|
+
" The body must carry the three writer-required fields in an",
|
|
18718
|
+
" `## Objective` block, written as bold-prefixed lines so the",
|
|
18719
|
+
" writer's intake parser can pull them out:",
|
|
18448
18720
|
"",
|
|
18449
|
-
"
|
|
18450
|
-
" -
|
|
18451
|
-
" -
|
|
18452
|
-
" - [ ] Registry index updated",
|
|
18453
|
-
" - [ ] Decision authority rules followed (direct write vs. proposed)",
|
|
18721
|
+
" - `**Category:** <BR/FR/NFR/TR/ADR/SEC/DR/INT/OPS/UX/MT>`",
|
|
18722
|
+
" - `**Tier:** <platform/industry/customer-workflow/consumer-app>`",
|
|
18723
|
+
" - `**Output Path:** <REQUIREMENTS_ROOT>/<category-dir>/<PREFIX>-<NNN>-<slug>.md`",
|
|
18454
18724
|
"",
|
|
18455
|
-
"
|
|
18456
|
-
|
|
18457
|
-
"
|
|
18725
|
+
" Then under `## Inputs / Read`, list the proposals file",
|
|
18726
|
+
" (`<RESEARCH_REQUIREMENTS_ROOT>/req-proposals-<scope>-<date>.md`)",
|
|
18727
|
+
" and any source documents the writer should consult (BCM model",
|
|
18728
|
+
" docs, competitive analyses, product docs).",
|
|
18458
18729
|
"",
|
|
18459
18730
|
" When one of Category / Tier / Output Path could not be derived",
|
|
18460
18731
|
" from the proposal (for example, the proposal omitted the Tier",
|
|
@@ -18630,8 +18901,6 @@ var TEMPLATE_BR = `---
|
|
|
18630
18901
|
title: "BR-NNN: [Business Requirement Title]"
|
|
18631
18902
|
---
|
|
18632
18903
|
|
|
18633
|
-
# BR-NNN: [Business Requirement Title]
|
|
18634
|
-
|
|
18635
18904
|
## Metadata
|
|
18636
18905
|
|
|
18637
18906
|
| Field | Value |
|
|
@@ -18739,8 +19008,6 @@ var TEMPLATE_FR = `---
|
|
|
18739
19008
|
title: "FR-NNN: [Functional Requirement Title]"
|
|
18740
19009
|
---
|
|
18741
19010
|
|
|
18742
|
-
# FR-NNN: [Functional Requirement Title]
|
|
18743
|
-
|
|
18744
19011
|
## Metadata
|
|
18745
19012
|
|
|
18746
19013
|
| Field | Value |
|
|
@@ -18880,8 +19147,6 @@ var TEMPLATE_NFR = `---
|
|
|
18880
19147
|
title: "NFR-NNN: [Non-Functional Requirement Title]"
|
|
18881
19148
|
---
|
|
18882
19149
|
|
|
18883
|
-
# NFR-NNN: [Non-Functional Requirement Title]
|
|
18884
|
-
|
|
18885
19150
|
## Metadata
|
|
18886
19151
|
|
|
18887
19152
|
| Field | Value |
|
|
@@ -18982,8 +19247,6 @@ var TEMPLATE_TR = `---
|
|
|
18982
19247
|
title: "TR-NNN: [Technical Requirement Title]"
|
|
18983
19248
|
---
|
|
18984
19249
|
|
|
18985
|
-
# TR-NNN: [Technical Requirement Title]
|
|
18986
|
-
|
|
18987
19250
|
## Metadata
|
|
18988
19251
|
|
|
18989
19252
|
| Field | Value |
|
|
@@ -19135,8 +19398,6 @@ var TEMPLATE_ADR = `---
|
|
|
19135
19398
|
title: "ADR-NNN: [Decision Title]"
|
|
19136
19399
|
---
|
|
19137
19400
|
|
|
19138
|
-
# ADR-NNN: [Decision Title]
|
|
19139
|
-
|
|
19140
19401
|
## Metadata
|
|
19141
19402
|
|
|
19142
19403
|
| Field | Value |
|
|
@@ -19265,8 +19526,6 @@ var TEMPLATE_SEC = `---
|
|
|
19265
19526
|
title: "SEC-NNN: [Security Requirement Title]"
|
|
19266
19527
|
---
|
|
19267
19528
|
|
|
19268
|
-
# SEC-NNN: [Security Requirement Title]
|
|
19269
|
-
|
|
19270
19529
|
## Metadata
|
|
19271
19530
|
|
|
19272
19531
|
| Field | Value |
|
|
@@ -19378,8 +19637,6 @@ var TEMPLATE_DR = `---
|
|
|
19378
19637
|
title: "DR-NNN: [Data Requirement Title]"
|
|
19379
19638
|
---
|
|
19380
19639
|
|
|
19381
|
-
# DR-NNN: [Data Requirement Title]
|
|
19382
|
-
|
|
19383
19640
|
## Metadata
|
|
19384
19641
|
|
|
19385
19642
|
| Field | Value |
|
|
@@ -19494,8 +19751,6 @@ var TEMPLATE_INT = `---
|
|
|
19494
19751
|
title: "INT-NNN: [Integration Requirement Title]"
|
|
19495
19752
|
---
|
|
19496
19753
|
|
|
19497
|
-
# INT-NNN: [Integration Requirement Title]
|
|
19498
|
-
|
|
19499
19754
|
## Metadata
|
|
19500
19755
|
|
|
19501
19756
|
| Field | Value |
|
|
@@ -19627,8 +19882,6 @@ var TEMPLATE_OPS = `---
|
|
|
19627
19882
|
title: "OPS-NNN: [Operational Requirement Title]"
|
|
19628
19883
|
---
|
|
19629
19884
|
|
|
19630
|
-
# OPS-NNN: [Operational Requirement Title]
|
|
19631
|
-
|
|
19632
19885
|
## Metadata
|
|
19633
19886
|
|
|
19634
19887
|
| Field | Value |
|
|
@@ -19743,8 +19996,6 @@ var TEMPLATE_UX = `---
|
|
|
19743
19996
|
title: "UX-NNN: [UX Requirement Title]"
|
|
19744
19997
|
---
|
|
19745
19998
|
|
|
19746
|
-
# UX-NNN: [UX Requirement Title]
|
|
19747
|
-
|
|
19748
19999
|
## Metadata
|
|
19749
20000
|
|
|
19750
20001
|
| Field | Value |
|
|
@@ -19861,8 +20112,6 @@ var TEMPLATE_MT = `---
|
|
|
19861
20112
|
title: "MT-NNN: [Multi-Tenancy Requirement Title]"
|
|
19862
20113
|
---
|
|
19863
20114
|
|
|
19864
|
-
# MT-NNN: [Multi-Tenancy Requirement Title]
|
|
19865
|
-
|
|
19866
20115
|
## Metadata
|
|
19867
20116
|
|
|
19868
20117
|
| Field | Value |
|
|
@@ -20015,8 +20264,6 @@ var TEMPLATE_REQUIREMENTS_README = `---
|
|
|
20015
20264
|
title: "[Project Name] \u2014 Requirements Documentation"
|
|
20016
20265
|
---
|
|
20017
20266
|
|
|
20018
|
-
# [Project Name] \u2014 Requirements Documentation
|
|
20019
|
-
|
|
20020
20267
|
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.
|
|
20021
20268
|
|
|
20022
20269
|
## Taxonomy Overview
|
|
@@ -20773,12 +21020,9 @@ function buildRequirementsWriterSubAgent(paths) {
|
|
|
20773
21020
|
"tier: platform",
|
|
20774
21021
|
"---",
|
|
20775
21022
|
"",
|
|
20776
|
-
"# FR-001: User Registration",
|
|
20777
|
-
"",
|
|
20778
21023
|
"...",
|
|
20779
21024
|
"```",
|
|
20780
21025
|
"",
|
|
20781
|
-
"The `title` value must match the document's `# Heading` line.",
|
|
20782
21026
|
"Titles containing colons must be wrapped in double quotes. The",
|
|
20783
21027
|
"`tier` field must be one of `platform`, `industry`,",
|
|
20784
21028
|
"`customer-workflow`, or `consumer-app` (use whatever tier slugs the",
|
|
@@ -22842,8 +23086,6 @@ function buildResearchAnalystSubAgent(paths) {
|
|
|
22842
23086
|
" slice_count: <N>",
|
|
22843
23087
|
" ---",
|
|
22844
23088
|
"",
|
|
22845
|
-
" # Research Scope: <question>",
|
|
22846
|
-
"",
|
|
22847
23089
|
" ## Question",
|
|
22848
23090
|
" <verbatim question from the issue>",
|
|
22849
23091
|
"",
|
|
@@ -22913,8 +23155,6 @@ function buildResearchAnalystSubAgent(paths) {
|
|
|
22913
23155
|
" parent_issue: <N>",
|
|
22914
23156
|
" ---",
|
|
22915
23157
|
"",
|
|
22916
|
-
" # Slice NN: <title>",
|
|
22917
|
-
"",
|
|
22918
23158
|
" ## Question",
|
|
22919
23159
|
" <the slice-level question>",
|
|
22920
23160
|
"",
|
|
@@ -22979,8 +23219,6 @@ function buildResearchAnalystSubAgent(paths) {
|
|
|
22979
23219
|
" slices_read: <count>",
|
|
22980
23220
|
" ---",
|
|
22981
23221
|
"",
|
|
22982
|
-
" # Verification Report: <question>",
|
|
22983
|
-
"",
|
|
22984
23222
|
" ## Acceptance Criteria Coverage",
|
|
22985
23223
|
" - [x] <criterion> \u2014 covered by slice(s) <NN, NN>",
|
|
22986
23224
|
" - [ ] <criterion> \u2014 **not covered**; gap noted in deliverable",
|
|
@@ -23588,8 +23826,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
|
|
|
23588
23826
|
" parent_issue: <N>",
|
|
23589
23827
|
" ---",
|
|
23590
23828
|
"",
|
|
23591
|
-
" # Research Notes: <product name>",
|
|
23592
|
-
"",
|
|
23593
23829
|
" ## Framing",
|
|
23594
23830
|
" <why this product was requested and what to learn>",
|
|
23595
23831
|
"",
|
|
@@ -23650,8 +23886,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
|
|
|
23650
23886
|
" notes: <NOTES_DIR>/<PRODUCT_SLUG>.notes.md",
|
|
23651
23887
|
" ---",
|
|
23652
23888
|
"",
|
|
23653
|
-
" # <product name>",
|
|
23654
|
-
"",
|
|
23655
23889
|
" ## Summary",
|
|
23656
23890
|
" <2\u20134 sentence elevator description: what it does, who it's for>",
|
|
23657
23891
|
"",
|
|
@@ -23736,8 +23970,6 @@ function buildSoftwareProfileAnalystSubAgent(paths) {
|
|
|
23736
23970
|
"updated: YYYY-MM-DD",
|
|
23737
23971
|
"---",
|
|
23738
23972
|
"",
|
|
23739
|
-
"# Software Feature Matrix",
|
|
23740
|
-
"",
|
|
23741
23973
|
"| product | feature | <segment-1> | <segment-2> | ... | score | source |",
|
|
23742
23974
|
"|---------|---------|-------------|-------------|-----|-------|--------|",
|
|
23743
23975
|
"| <slug> | <feature-name> | 0\u20131 | 0\u20131 | ... | <weighted-sum> | <profile-path> |",
|
|
@@ -24365,8 +24597,6 @@ title: "<Standard Name>"
|
|
|
24365
24597
|
description: "Overview and cross-version comparison of <Standard Name>."
|
|
24366
24598
|
---
|
|
24367
24599
|
|
|
24368
|
-
# <Standard Name>
|
|
24369
|
-
|
|
24370
24600
|
| Field | Value |
|
|
24371
24601
|
|-------|-------|
|
|
24372
24602
|
| **Standard** | <standard name> |
|
|
@@ -24684,8 +24914,6 @@ function buildStandardsResearchAnalystSubAgent(paths) {
|
|
|
24684
24914
|
" standard: <STANDARD_SLUG>",
|
|
24685
24915
|
" ---",
|
|
24686
24916
|
"",
|
|
24687
|
-
" # Query Plan: <Standard Name>",
|
|
24688
|
-
"",
|
|
24689
24917
|
" ## Context",
|
|
24690
24918
|
" <1\u20132 paragraphs on why this standard matters to the consuming",
|
|
24691
24919
|
" project and what gaps this research campaign fills.>",
|
|
@@ -24887,7 +25115,14 @@ function buildStandardsResearchAnalystSubAgent(paths) {
|
|
|
24887
25115
|
" the overview page, then populate each section from the version",
|
|
24888
25116
|
" pages.",
|
|
24889
25117
|
"",
|
|
24890
|
-
"4. **Write the overview page** at `<OVERVIEW_PAGE>`.
|
|
25118
|
+
"4. **Write the overview page** at `<OVERVIEW_PAGE>`. Follow",
|
|
25119
|
+
" the `stub-index-convention` rule: the body opens with a",
|
|
25120
|
+
" 1\u20132 paragraph contextual summary of the standard and its",
|
|
25121
|
+
" versions, and the version pages, modules, and extensions",
|
|
25122
|
+
" sections below double as the grouped, linked listing of",
|
|
25123
|
+
" every child page in the standard's folder. No body",
|
|
25124
|
+
" `# Heading` \u2014 the frontmatter `title:` already renders as",
|
|
25125
|
+
" the page H1. Required sections to fill:",
|
|
24891
25126
|
" - **Version Timeline** \u2014 publication dates, status, milestones",
|
|
24892
25127
|
" - **Module / Resource Maturity Progression** \u2014 matrix with",
|
|
24893
25128
|
" modules as rows and versions as columns, using the standard's",
|
|
@@ -32676,6 +32911,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
|
|
|
32676
32911
|
DEFAULT_API_EXTRACTOR_REPORT_FILENAME,
|
|
32677
32912
|
DEFAULT_API_EXTRACTOR_REPORT_FOLDER,
|
|
32678
32913
|
DEFAULT_AUDIT_REPORT_DIR,
|
|
32914
|
+
DEFAULT_BUNDLE_OVERRIDES,
|
|
32679
32915
|
DEFAULT_DECOMPOSITION_TEMPLATE,
|
|
32680
32916
|
DEFAULT_DISPATCH_MODEL,
|
|
32681
32917
|
DEFAULT_DISPATCH_TO_HOUSEKEEPING_RATIO,
|
|
@@ -32847,6 +33083,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
|
|
|
32847
33083
|
renderSkillEvalsRuleContent,
|
|
32848
33084
|
renderSkillEvalsRunnerScript,
|
|
32849
33085
|
renderSourceTierExamples,
|
|
33086
|
+
renderStubIndexConventionRuleContent,
|
|
32850
33087
|
renderUnblockDependentsScript,
|
|
32851
33088
|
renderUnblockDependentsSection,
|
|
32852
33089
|
requirementsAnalystBundle,
|
|
@@ -32861,6 +33098,7 @@ var TypeScriptConfig = class extends import_projen23.Component {
|
|
|
32861
33098
|
resolveModelAlias,
|
|
32862
33099
|
resolveOrchestratorAssets,
|
|
32863
33100
|
resolveOutdirFromPackageName,
|
|
33101
|
+
resolveOverrideForLabels,
|
|
32864
33102
|
resolveProgressFiles,
|
|
32865
33103
|
resolveRunRatio,
|
|
32866
33104
|
resolveScheduledTasks,
|