@codedrifters/configulator 0.0.255 → 0.0.257

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.ts CHANGED
@@ -1019,6 +1019,314 @@ interface PriorityRule {
1019
1019
  */
1020
1020
  readonly rationale: string;
1021
1021
  }
1022
+ /*******************************************************************************
1023
+ *
1024
+ * Focus Scoring
1025
+ *
1026
+ ******************************************************************************/
1027
+ /**
1028
+ * Match predicate for a single focus area. At least one sub-field
1029
+ * should be set; multiple sub-fields on the same match combine as a
1030
+ * logical OR (any one matching contributes the focus area's weight).
1031
+ *
1032
+ * @see FocusArea
1033
+ */
1034
+ interface FocusAreaMatch {
1035
+ /** Any of these labels present on the issue matches. */
1036
+ readonly labels?: ReadonlyArray<string>;
1037
+ /**
1038
+ * Case-insensitive substrings matched against the issue title.
1039
+ * A hit on any single keyword fires the match.
1040
+ */
1041
+ readonly titleKeywords?: ReadonlyArray<string>;
1042
+ /**
1043
+ * Case-insensitive substrings matched against the issue body.
1044
+ * A hit on any single keyword fires the match.
1045
+ */
1046
+ readonly bodyKeywords?: ReadonlyArray<string>;
1047
+ }
1048
+ /**
1049
+ * A single scored focus area — a named customer, segment,
1050
+ * organization, software product, regulation, or person the project
1051
+ * cares about right now. Matching issues receive this area's
1052
+ * `weight` as a priority boost at triage time.
1053
+ *
1054
+ * @see FocusConfig
1055
+ * @see ./bundles/focus.ts#renderFocusSection
1056
+ */
1057
+ interface FocusArea {
1058
+ /** Human-readable name for the focus area (e.g. "Acme Corp"). */
1059
+ readonly name: string;
1060
+ /**
1061
+ * Consuming-repo-defined vocabulary describing what kind of entity
1062
+ * this focus area represents (e.g. `"customer"`, `"segment"`,
1063
+ * `"organization"`, `"software"`, `"regulation"`, `"person"`).
1064
+ * The `AgentExpansionRules.allowedTypes` /
1065
+ * `AgentExpansionRules.forbiddenTypes` lists gate what values
1066
+ * agents are permitted to introduce.
1067
+ */
1068
+ readonly type: string;
1069
+ /**
1070
+ * Provenance. `"human"` entries are curated by a maintainer;
1071
+ * `"agent"` entries were appended by an agent under the
1072
+ * agent-expansion rules and must carry a `discoveredIn` reference.
1073
+ */
1074
+ readonly source: "human" | "agent";
1075
+ /**
1076
+ * Issue reference (e.g. `"#123"`) that introduced the focus area.
1077
+ * Required when `source` is `"agent"` so the provenance of every
1078
+ * agent-appended entry is auditable; optional for human entries.
1079
+ */
1080
+ readonly discoveredIn?: string;
1081
+ /** Match predicate that decides which issues this area applies to. */
1082
+ readonly match: FocusAreaMatch;
1083
+ /**
1084
+ * Positive integer weight contributed to the issue's focus score
1085
+ * when the match fires. Consuming repos typically cap this with
1086
+ * `AgentExpansionRules.maxWeight` (default 8 in openhi's reference
1087
+ * implementation).
1088
+ */
1089
+ readonly weight: number;
1090
+ }
1091
+ /**
1092
+ * Guard-rails on what agents are allowed to append to `focus.json`
1093
+ * without human review. The agent-expansion contract is append-only:
1094
+ * agents never modify or remove existing entries.
1095
+ */
1096
+ interface AgentExpansionRules {
1097
+ /**
1098
+ * Hard cap on the `weight` an agent may set on a newly appended
1099
+ * focus area. Human curators may use higher weights.
1100
+ */
1101
+ readonly maxWeight: number;
1102
+ /**
1103
+ * Whitelist of `FocusArea.type` values agents are permitted to
1104
+ * introduce. Any type outside this list must be added by a human.
1105
+ */
1106
+ readonly allowedTypes: ReadonlyArray<string>;
1107
+ /**
1108
+ * Explicit blocklist of `FocusArea.type` values agents must never
1109
+ * introduce, even if the list accidentally overlaps
1110
+ * `allowedTypes`. `forbiddenTypes` wins on conflict.
1111
+ */
1112
+ readonly forbiddenTypes: ReadonlyArray<string>;
1113
+ /**
1114
+ * Optional cap on the number of entries in each keyword array
1115
+ * (`match.labels`, `match.titleKeywords`, `match.bodyKeywords`)
1116
+ * on an agent-appended focus area. Prevents runaway keyword
1117
+ * expansion. Human entries are not subject to this cap.
1118
+ */
1119
+ readonly maxKeywords?: number;
1120
+ }
1121
+ /**
1122
+ * Top-level configuration for the focus-scoring engine. The schema
1123
+ * and agent-expansion rules live in the configulator bundle; the
1124
+ * actual `focus.json` file is authored and curated in the consuming
1125
+ * repo.
1126
+ *
1127
+ * When supplied via `AgentConfigOptions.focus`, the `base` bundle
1128
+ * appends a "Focus scoring" subsection to the
1129
+ * `issue-label-conventions` rule that teaches agents how to read
1130
+ * `focus.json`, how focus weight interacts with the
1131
+ * `priority:*` taxonomy, and what they may and may not append to
1132
+ * the file.
1133
+ *
1134
+ * @see FocusArea
1135
+ * @see AgentExpansionRules
1136
+ * @see ./bundles/focus.ts#renderFocusSection
1137
+ */
1138
+ interface FocusConfig {
1139
+ /**
1140
+ * Path to the focus file relative to the repo root.
1141
+ * @default ".claude/focus.json"
1142
+ */
1143
+ readonly focusFilePath?: string;
1144
+ /**
1145
+ * Schema version the consuming repo's `focus.json` conforms to.
1146
+ * Bump when the schema changes in a backwards-incompatible way.
1147
+ * @default 1
1148
+ */
1149
+ readonly schemaVersion?: number;
1150
+ /**
1151
+ * Cumulative focus-score thresholds that map into the
1152
+ * `priority:*` taxonomy. An issue whose total focus score
1153
+ * (sum of matched focus-area weights) reaches `high` is boosted
1154
+ * to `priority:high`; reaching `medium` keeps it at
1155
+ * `priority:medium`. Scores below `medium` do not affect the
1156
+ * inferred priority.
1157
+ *
1158
+ * @remarks `high` and `medium` must be integers. The JSON schema
1159
+ * at `schemas/focus.schema.json` enforces this for `focus.json`.
1160
+ */
1161
+ readonly thresholds?: {
1162
+ readonly high: number;
1163
+ readonly medium: number;
1164
+ };
1165
+ /**
1166
+ * Guard-rails that govern what agents may append to `focus.json`.
1167
+ * When omitted, the rendered rule documents that agents must
1168
+ * **not** append to `focus.json` without human review.
1169
+ */
1170
+ readonly agentExpansionRules?: AgentExpansionRules;
1171
+ }
1172
+ /*******************************************************************************
1173
+ *
1174
+ * Meetings Config
1175
+ *
1176
+ ******************************************************************************/
1177
+ /**
1178
+ * Scope classifier for a meeting type. Used by the `meeting-analysis`
1179
+ * bundle to reason about where a given meeting belongs (internal vs
1180
+ * external) and, for external meetings, the nature of the other party.
1181
+ *
1182
+ * - `internal-recurring` — recurring internal meeting (weekly standup,
1183
+ * team sync, planning cadence).
1184
+ * - `internal-oneoff` — one-off internal meeting (brainstorm, kickoff,
1185
+ * retro).
1186
+ * - `external-customer` — meeting with an existing paying customer.
1187
+ * - `external-prospect` — meeting with a sales prospect not yet under
1188
+ * contract.
1189
+ * - `external-partner` — meeting with a partner (integration, vendor,
1190
+ * channel).
1191
+ * - `external-other` — any external meeting that does not fit the
1192
+ * customer / prospect / partner buckets.
1193
+ */
1194
+ type MeetingScope = "internal-recurring" | "internal-oneoff" | "external-customer" | "external-prospect" | "external-partner" | "external-other";
1195
+ /**
1196
+ * A single meeting-type taxonomy entry declared by the consuming repo.
1197
+ * Each entry names a kind of meeting the project recognizes
1198
+ * (`founders-weekly`, `customer-discovery`, etc.) and supplies the
1199
+ * per-type metadata agents need to route, default, and template that
1200
+ * meeting.
1201
+ *
1202
+ * When `AgentConfigOptions.meetings.meetingTypes` is non-empty, the
1203
+ * `meeting-analysis` bundle renders a "Recognized meeting types"
1204
+ * subsection listing every declared type so agents pick from the
1205
+ * project's vocabulary rather than guessing.
1206
+ *
1207
+ * @see MeetingsConfig
1208
+ * @see ./bundles/meeting-types.ts#renderMeetingTypesSection
1209
+ */
1210
+ interface MeetingType {
1211
+ /**
1212
+ * Stable machine identifier for the meeting type. Used as the
1213
+ * `meeting_type` frontmatter value on meeting notes and as the key
1214
+ * that the future `agenda` bundle will look up when selecting a
1215
+ * pre-meeting template.
1216
+ * @example 'founders-weekly', 'customer-discovery', 'sprint-review'
1217
+ */
1218
+ readonly id: string;
1219
+ /** Human-readable label shown in generated rule content. */
1220
+ readonly label: string;
1221
+ /**
1222
+ * Scope classification — whether the meeting is internal (recurring
1223
+ * or one-off) or external (customer / prospect / partner / other).
1224
+ */
1225
+ readonly scope: MeetingScope;
1226
+ /**
1227
+ * Default scheduled duration in minutes. Optional; agents may use
1228
+ * this when proposing calendar holds or when validating a
1229
+ * transcript's recorded duration against the type's expected
1230
+ * duration.
1231
+ */
1232
+ readonly defaultDurationMinutes?: number;
1233
+ /**
1234
+ * Path to a pre-meeting agenda skeleton for this type, resolved
1235
+ * relative to `MeetingsConfig.agendaTemplateRoot`. Optional — a
1236
+ * type without a template simply has no canned agenda.
1237
+ * @example 'founders-weekly.md', 'customer-discovery/v2.md'
1238
+ */
1239
+ readonly agendaTemplatePath?: string;
1240
+ /**
1241
+ * Human-readable cadence descriptor. Free-form text — agents
1242
+ * surface the string verbatim rather than parsing it.
1243
+ * @example 'weekly', 'every 2 weeks', 'one-off'
1244
+ */
1245
+ readonly cadence?: string;
1246
+ }
1247
+ /**
1248
+ * A single meeting-area entry. Meeting areas provide a coarse
1249
+ * routing map from an `area` frontmatter value on a meeting note to
1250
+ * the sub-tree of the docs root where phase-4 direct edits should
1251
+ * land.
1252
+ *
1253
+ * Example: declaring `{ id: 'product-engineering', label: 'Product &
1254
+ * Engineering', docRoot: 'product' }` tells the `meeting-analysis`
1255
+ * bundle that a meeting whose frontmatter carries
1256
+ * `area: product-engineering` should have its direct edits routed
1257
+ * under `<docsRoot>/product/`.
1258
+ *
1259
+ * When `AgentConfigOptions.meetings.meetingAreas` is non-empty, the
1260
+ * `meeting-analysis` bundle renders an "Area → doc-root mapping"
1261
+ * subsection documenting every declared area and its resolved
1262
+ * destination.
1263
+ *
1264
+ * @see MeetingsConfig
1265
+ * @see ./bundles/meeting-types.ts#renderMeetingTypesSection
1266
+ */
1267
+ interface MeetingArea {
1268
+ /**
1269
+ * Stable machine identifier for the area. Matches the `area`
1270
+ * frontmatter value on meeting notes.
1271
+ * @example 'product-engineering', 'go-to-market', 'operations'
1272
+ */
1273
+ readonly id: string;
1274
+ /** Human-readable label shown in generated rule content. */
1275
+ readonly label: string;
1276
+ /**
1277
+ * Destination folder for phase-4 direct edits on meeting notes
1278
+ * carrying this area. Interpreted **relative to the resolved
1279
+ * docs root** (`AgentPathsConfig.docsRoot`, default
1280
+ * `docs/src/content/docs`). Do not include a leading slash.
1281
+ * @example 'product', 'gtm', 'operations'
1282
+ */
1283
+ readonly docRoot: string;
1284
+ }
1285
+ /**
1286
+ * Meeting-analysis injection points — the set of typed
1287
+ * configurations agents consult when classifying, routing, and
1288
+ * templating a meeting. Every field is optional.
1289
+ *
1290
+ * - `meetingTypes` — the set of meeting types the repo recognizes.
1291
+ * - `meetingAreas` — maps `area` frontmatter to doc-root sub-trees.
1292
+ * - `agendaTemplateRoot` — where pre-meeting agenda skeletons live.
1293
+ *
1294
+ * When supplied, the `meeting-analysis` bundle conditionally renders
1295
+ * two new subsections into the `meeting-processing-workflow` rule —
1296
+ * "Recognized meeting types" (when `meetingTypes` is non-empty) and
1297
+ * "Area → doc-root mapping" (when `meetingAreas` is non-empty).
1298
+ *
1299
+ * @see MeetingType
1300
+ * @see MeetingArea
1301
+ * @see ./bundles/meeting-types.ts#renderMeetingTypesSection
1302
+ */
1303
+ interface MeetingsConfig {
1304
+ /**
1305
+ * Meeting-type taxonomy. An empty or missing list means the
1306
+ * consuming repo does not classify meetings by type; the
1307
+ * `meeting-analysis` bundle falls back to its generic 4-phase
1308
+ * behaviour.
1309
+ */
1310
+ readonly meetingTypes?: ReadonlyArray<MeetingType>;
1311
+ /**
1312
+ * Meeting-area map. An empty or missing list means the consuming
1313
+ * repo does not route meetings by area; phase-4 direct edits
1314
+ * continue to land under the default meetings root.
1315
+ */
1316
+ readonly meetingAreas?: ReadonlyArray<MeetingArea>;
1317
+ /**
1318
+ * Root folder containing pre-meeting agenda-template skeletons.
1319
+ * Resolved at issue-creation time by the (future) `agenda` bundle
1320
+ * when selecting a template for a given `meeting_type`.
1321
+ *
1322
+ * When unset, the `meeting-analysis` bundle documents the default
1323
+ * of `<meetingsRoot>/_agenda-templates` — consumers that wire a
1324
+ * custom `AgentPathsConfig.meetingsRoot` inherit the override
1325
+ * automatically.
1326
+ * @default "<meetingsRoot>/_agenda-templates"
1327
+ */
1328
+ readonly agendaTemplateRoot?: string;
1329
+ }
1022
1330
  /*******************************************************************************
1023
1331
  *
1024
1332
  * AgentConfig Options
@@ -1131,6 +1439,46 @@ interface AgentConfigOptions {
1131
1439
  * @see ./bundles/priority-rules.ts#renderPriorityRulesSection
1132
1440
  */
1133
1441
  readonly priorityRules?: ReadonlyArray<PriorityRule>;
1442
+ /**
1443
+ * Focus-scoring configuration. Declares the path to the consuming
1444
+ * repo's `focus.json` file, score thresholds, and the
1445
+ * agent-expansion rules that govern what agents may append to the
1446
+ * file.
1447
+ *
1448
+ * When set, the `base` bundle appends a "Focus scoring"
1449
+ * subsection to the `issue-label-conventions` rule that teaches
1450
+ * agents (a) how to read `focus.json`, (b) how focus weight
1451
+ * interacts with the `priority:*` taxonomy, and (c) the
1452
+ * agent-driven expansion contract. The actual `focus.json` file
1453
+ * is authored and curated in the consuming repo — configulator
1454
+ * ships the schema and agent instructions only.
1455
+ *
1456
+ * @see FocusConfig
1457
+ * @see FocusArea
1458
+ * @see AgentExpansionRules
1459
+ * @see ./bundles/focus.ts#renderFocusSection
1460
+ */
1461
+ readonly focus?: FocusConfig;
1462
+ /**
1463
+ * Meeting-analysis injection points — typed configs the
1464
+ * `meeting-analysis` bundle consults when classifying, routing, and
1465
+ * templating meetings. Supplies the meeting-type taxonomy, the
1466
+ * area → doc-root routing map, and the agenda-template root used
1467
+ * by the (future) `agenda` bundle.
1468
+ *
1469
+ * When `meetingTypes` is non-empty, the `meeting-analysis` bundle
1470
+ * appends a "Recognized meeting types" subsection to the
1471
+ * `meeting-processing-workflow` rule. When `meetingAreas` is
1472
+ * non-empty, it appends an "Area → doc-root mapping" subsection.
1473
+ * When both are empty or unset, the generated rule content is
1474
+ * unchanged from the no-config baseline.
1475
+ *
1476
+ * @see MeetingsConfig
1477
+ * @see MeetingType
1478
+ * @see MeetingArea
1479
+ * @see ./bundles/meeting-types.ts#renderMeetingTypesSection
1480
+ */
1481
+ readonly meetings?: MeetingsConfig;
1134
1482
  }
1135
1483
 
1136
1484
  /**
@@ -1403,6 +1751,47 @@ declare const prReviewBundle: AgentRuleBundle;
1403
1751
  */
1404
1752
  declare const projenBundle: AgentRuleBundle;
1405
1753
 
1754
+ /**
1755
+ * Render the markdown subsection appended to the
1756
+ * `issue-label-conventions` rule when `AgentConfigOptions.focus` is
1757
+ * supplied. Returns an empty string when `focus` is undefined so
1758
+ * callers can unconditionally concatenate the result.
1759
+ *
1760
+ * The section documents three things for agents:
1761
+ *
1762
+ * 1. How to read `focus.json` at triage time
1763
+ * 2. How focus weight interacts with the `priority:*` taxonomy
1764
+ * 3. The agent-driven expansion contract (what agents may append)
1765
+ *
1766
+ * Configulator ships this rule content plus a JSON Schema that
1767
+ * validates the `focus.json` file; the file itself is authored and
1768
+ * curated in the consuming repo.
1769
+ */
1770
+ declare function renderFocusSection(focus: FocusConfig | undefined): string;
1771
+
1772
+ /**
1773
+ * Render the markdown subsections appended to the
1774
+ * `meeting-processing-workflow` rule when `AgentConfigOptions.meetings`
1775
+ * is supplied. Returns an empty string when the supplied config has
1776
+ * nothing to render (no meeting types and no meeting areas) so callers
1777
+ * can unconditionally concatenate the result.
1778
+ *
1779
+ * Two subsections are rendered, each gated on its own input array:
1780
+ *
1781
+ * 1. **Recognized meeting types** — rendered when `meetingTypes` is
1782
+ * non-empty. Lists every declared type with its scope, optional
1783
+ * cadence, default duration, and agenda template path. Also
1784
+ * documents the resolved `agendaTemplateRoot`.
1785
+ * 2. **Area → doc-root mapping** — rendered when `meetingAreas` is
1786
+ * non-empty. Lists every declared area with its `id`, label, and
1787
+ * docs-root-relative destination folder.
1788
+ *
1789
+ * Bundles consume the rendered string by appending it to their own
1790
+ * rule content. A caller that has no meeting types and no meeting
1791
+ * areas receives an empty string and can safely concatenate.
1792
+ */
1793
+ declare function renderMeetingTypesSection(meetings: MeetingsConfig | undefined): string;
1794
+
1406
1795
  /**
1407
1796
  * Render the markdown subsection appended to the
1408
1797
  * `issue-label-conventions` rule when `AgentConfigOptions.priorityRules`
@@ -4137,5 +4526,5 @@ declare const COMPLETE_JOB_ID = "complete";
4137
4526
  */
4138
4527
  declare function addBuildCompleteJob(buildWorkflow: BuildWorkflow): void;
4139
4528
 
4140
- export { AGENT_MODEL, AGENT_PLATFORM, AGENT_RULE_SCOPE, AgentConfig, AstroConfig, AstroOutput, AstroProject, AwsCdkProject, AwsDeployWorkflow, AwsDeploymentConfig, AwsDeploymentTarget, AwsTeardownWorkflow, BUILT_IN_BUNDLES, CLAUDE_RULE_TARGET, COMPLETE_JOB_ID, DEFAULT_AGENT_PATHS, DEFAULT_PRIORITY_LABELS, DEFAULT_STATUS_LABELS, DEFAULT_TEARDOWN_BRANCH_PATTERNS, DEFAULT_TYPE_LABELS, JsiiFaker, LAYOUT_ENFORCEMENT, LAYOUT_ROOT_BY_PROJECT_TYPE, MCP_TRANSPORT, MERGE_METHODS, MIMIMUM_RELEASE_AGE, MINIMUM_RELEASE_AGE, MONOREPO_LAYOUT, MonorepoProject, PROD_DEPLOY_NAME, PnpmWorkspace, ProjectMetadata, REQUIREMENTS_WRITER_PATHS, ROOT_CI_TASK_NAME, ROOT_TURBO_TASK_NAME, ResetTask, STARLIGHT_ROLE, StarlightProject, TestRunner, TurboRepo, TurboRepoTask, TypeScriptConfig, TypeScriptProject, VERSION, VERSION_KEYS_SKIP, VERSION_NPM_PACKAGES, VSCodeConfig, Vitest, addApproveMergeUpgradeWorkflow, addBuildCompleteJob, addSyncLabelsWorkflow, awsCdkBundle, baseBundle, bcmWriterBundle, companyProfileBundle, formatLayoutViolation, formatStarlightSingletonViolation, getLatestEligibleVersion, githubWorkflowBundle, industryDiscoveryBundle, jestBundle, maintenanceAuditBundle, meetingAnalysisBundle, orchestratorBundle, peopleProfileBundle, pnpmBundle, prReviewBundle, projenBundle, renderPriorityRulesSection, requirementsAnalystBundle, requirementsReviewerBundle, requirementsWriterBundle, researchPipelineBundle, resolveAgentPaths, resolveAstroProjectOutdir, resolveAwsCdkProjectOutdir, resolveModelAlias, resolveOutdirFromPackageName, resolveTemplateVariables, resolveTypeScriptProjectOutdir, slackBundle, softwareProfileBundle, turborepoBundle, typescriptBundle, validateMonorepoLayout, validateStarlightSingleton, vitestBundle };
4141
- export type { AgentConfigOptions, AgentModel, AgentPathsConfig, AgentPlatform, AgentPlatformOverrides, AgentProcedure, AgentRule, AgentRuleBundle, AgentRuleScope, AgentSkill, AgentSubAgent, AgentSubAgentPlatformOverrides, ApproveMergeUpgradeOptions, AstroConfigOptions, AstroIntegrationSpec, AstroProjectOptions, AwsAccount, AwsCdkProjectOptions, AwsDeploymentTargetOptions, AwsLocalDeploymentConfig, AwsOrganization, AwsRegion, AwsTeardownWorkflowOptions, CiDeploymentConfig, ClassTypeOptions, ClaudeAutoModeConfig, ClaudeHookAction, ClaudeHookEntry, ClaudeHooksConfig, ClaudePermissionsConfig, ClaudeRuleTarget, ClaudeSandboxConfig, ClaudeSettingsConfig, CopilotHandoff, CursorHookAction, CursorHooksConfig, CursorSettingsConfig, DeployWorkflowOptions, DeploymentMetadata, GitBranch, GitHubBoardMetadata, GitHubProjectMetadata, GitHubSprintMetadata, IDependencyResolver, LabelDefinition, LayoutEnforcement, LayoutViolation, McpServerConfig, McpTransport, MergeMethod, MonorepoLayoutRoot, MonorepoProjectOptions, OrganizationMetadata, PnpmWorkspaceOptions, PriorityRule, ProjectMetadataOptions, RemoteCacheOptions, RepositoryMetadata, ResetTaskOptions, ResolvedAgentPaths, ResolvedProjectMetadata, SlackMetadata, StarlightEditLink, StarlightLogo, StarlightProjectOptions, StarlightRole, StarlightSidebarItem, StarlightSingletonViolation, StarlightSocialLink, SyncLabelsOptions, TemplateResolveResult, TurboRepoOptions, TurboRepoTaskOptions, TypeScriptProjectOptions, VersionKey, VitestConfigOptions, VitestOptions };
4529
+ export { AGENT_MODEL, AGENT_PLATFORM, AGENT_RULE_SCOPE, AgentConfig, AstroConfig, AstroOutput, AstroProject, AwsCdkProject, AwsDeployWorkflow, AwsDeploymentConfig, AwsDeploymentTarget, AwsTeardownWorkflow, BUILT_IN_BUNDLES, CLAUDE_RULE_TARGET, COMPLETE_JOB_ID, DEFAULT_AGENT_PATHS, DEFAULT_PRIORITY_LABELS, DEFAULT_STATUS_LABELS, DEFAULT_TEARDOWN_BRANCH_PATTERNS, DEFAULT_TYPE_LABELS, JsiiFaker, LAYOUT_ENFORCEMENT, LAYOUT_ROOT_BY_PROJECT_TYPE, MCP_TRANSPORT, MERGE_METHODS, MIMIMUM_RELEASE_AGE, MINIMUM_RELEASE_AGE, MONOREPO_LAYOUT, MonorepoProject, PROD_DEPLOY_NAME, PnpmWorkspace, ProjectMetadata, REQUIREMENTS_WRITER_PATHS, ROOT_CI_TASK_NAME, ROOT_TURBO_TASK_NAME, ResetTask, STARLIGHT_ROLE, StarlightProject, TestRunner, TurboRepo, TurboRepoTask, TypeScriptConfig, TypeScriptProject, VERSION, VERSION_KEYS_SKIP, VERSION_NPM_PACKAGES, VSCodeConfig, Vitest, addApproveMergeUpgradeWorkflow, addBuildCompleteJob, addSyncLabelsWorkflow, awsCdkBundle, baseBundle, bcmWriterBundle, companyProfileBundle, formatLayoutViolation, formatStarlightSingletonViolation, getLatestEligibleVersion, githubWorkflowBundle, industryDiscoveryBundle, jestBundle, maintenanceAuditBundle, meetingAnalysisBundle, orchestratorBundle, peopleProfileBundle, pnpmBundle, prReviewBundle, projenBundle, renderFocusSection, renderMeetingTypesSection, renderPriorityRulesSection, requirementsAnalystBundle, requirementsReviewerBundle, requirementsWriterBundle, researchPipelineBundle, resolveAgentPaths, resolveAstroProjectOutdir, resolveAwsCdkProjectOutdir, resolveModelAlias, resolveOutdirFromPackageName, resolveTemplateVariables, resolveTypeScriptProjectOutdir, slackBundle, softwareProfileBundle, turborepoBundle, typescriptBundle, validateMonorepoLayout, validateStarlightSingleton, vitestBundle };
4530
+ export type { AgentConfigOptions, AgentExpansionRules, AgentModel, AgentPathsConfig, AgentPlatform, AgentPlatformOverrides, AgentProcedure, AgentRule, AgentRuleBundle, AgentRuleScope, AgentSkill, AgentSubAgent, AgentSubAgentPlatformOverrides, ApproveMergeUpgradeOptions, AstroConfigOptions, AstroIntegrationSpec, AstroProjectOptions, AwsAccount, AwsCdkProjectOptions, AwsDeploymentTargetOptions, AwsLocalDeploymentConfig, AwsOrganization, AwsRegion, AwsTeardownWorkflowOptions, CiDeploymentConfig, ClassTypeOptions, ClaudeAutoModeConfig, ClaudeHookAction, ClaudeHookEntry, ClaudeHooksConfig, ClaudePermissionsConfig, ClaudeRuleTarget, ClaudeSandboxConfig, ClaudeSettingsConfig, CopilotHandoff, CursorHookAction, CursorHooksConfig, CursorSettingsConfig, DeployWorkflowOptions, DeploymentMetadata, FocusArea, FocusAreaMatch, FocusConfig, GitBranch, GitHubBoardMetadata, GitHubProjectMetadata, GitHubSprintMetadata, IDependencyResolver, LabelDefinition, LayoutEnforcement, LayoutViolation, McpServerConfig, McpTransport, MeetingArea, MeetingScope, MeetingType, MeetingsConfig, MergeMethod, MonorepoLayoutRoot, MonorepoProjectOptions, OrganizationMetadata, PnpmWorkspaceOptions, PriorityRule, ProjectMetadataOptions, RemoteCacheOptions, RepositoryMetadata, ResetTaskOptions, ResolvedAgentPaths, ResolvedProjectMetadata, SlackMetadata, StarlightEditLink, StarlightLogo, StarlightProjectOptions, StarlightRole, StarlightSidebarItem, StarlightSingletonViolation, StarlightSocialLink, SyncLabelsOptions, TemplateResolveResult, TurboRepoOptions, TurboRepoTaskOptions, TypeScriptProjectOptions, VersionKey, VitestConfigOptions, VitestOptions };
package/lib/index.js CHANGED
@@ -243,6 +243,8 @@ __export(index_exports, {
243
243
  pnpmBundle: () => pnpmBundle,
244
244
  prReviewBundle: () => prReviewBundle,
245
245
  projenBundle: () => projenBundle,
246
+ renderFocusSection: () => renderFocusSection,
247
+ renderMeetingTypesSection: () => renderMeetingTypesSection,
246
248
  renderPriorityRulesSection: () => renderPriorityRulesSection,
247
249
  requirementsAnalystBundle: () => requirementsAnalystBundle,
248
250
  requirementsReviewerBundle: () => requirementsReviewerBundle,
@@ -14581,6 +14583,190 @@ var vitestBundle = {
14581
14583
  }
14582
14584
  };
14583
14585
 
14586
+ // src/agent/bundles/focus.ts
14587
+ var DEFAULT_FOCUS_FILE_PATH = ".claude/focus.json";
14588
+ var DEFAULT_SCHEMA_VERSION = 1;
14589
+ function renderFocusSection(focus) {
14590
+ if (!focus) {
14591
+ return "";
14592
+ }
14593
+ const focusFilePath = focus.focusFilePath ?? DEFAULT_FOCUS_FILE_PATH;
14594
+ const schemaVersion = focus.schemaVersion ?? DEFAULT_SCHEMA_VERSION;
14595
+ const lines = [
14596
+ "## Focus scoring",
14597
+ "",
14598
+ "This project runs a **focus-scoring engine** alongside the generic",
14599
+ "`priority:*` inference above. Focus scoring boosts the priority of",
14600
+ "issues that match the project's currently-declared focus areas \u2014",
14601
+ "named customers, segments, organizations, software products,",
14602
+ "regulations, or people the project cares about right now.",
14603
+ "",
14604
+ "### Reading `focus.json`",
14605
+ "",
14606
+ `The focus file lives at \`${focusFilePath}\` and conforms to schema`,
14607
+ `version \`${schemaVersion}\`. Each entry declares a match predicate`,
14608
+ "(any combination of `labels`, `titleKeywords`, `bodyKeywords`) and",
14609
+ "a positive integer `weight`. At triage time:",
14610
+ "",
14611
+ `1. Read \`${focusFilePath}\`. If the file is missing or empty,`,
14612
+ " skip focus scoring entirely \u2014 the generic priority heuristics",
14613
+ " apply unchanged.",
14614
+ "2. For each focus area, test its match predicate against the",
14615
+ " issue's labels, title, and body. A match on **any** sub-field",
14616
+ " (labels / title keywords / body keywords) fires the area and",
14617
+ " contributes its `weight` to the issue's focus score.",
14618
+ "3. Keyword matching is case-insensitive substring matching \u2014",
14619
+ ' `titleKeywords: ["Acme"]` matches an issue titled',
14620
+ " `feat: onboard acme corp`.",
14621
+ "4. Sum all matched weights to produce the issue's **focus score**.",
14622
+ ""
14623
+ ];
14624
+ lines.push("### How focus score interacts with `priority:*`");
14625
+ lines.push("");
14626
+ if (focus.thresholds) {
14627
+ const { high, medium } = focus.thresholds;
14628
+ lines.push(`A focus score of \`${high}\` or more boosts the`);
14629
+ const mediumBand = high - medium === 1 ? `A focus score of \`${medium}\` keeps` : `A focus score of \`${medium}\` up to \`${high - 1}\` keeps`;
14630
+ lines.push(
14631
+ "issue to `priority:high`.",
14632
+ `${mediumBand} the issue at \`priority:medium\`. Scores below`,
14633
+ `\`${medium}\` do **not** alter the priority that`,
14634
+ "the generic heuristics would otherwise infer."
14635
+ );
14636
+ } else {
14637
+ lines.push(
14638
+ "This project has not declared explicit focus-score thresholds.",
14639
+ "Treat any non-zero focus score as a soft signal to lift one",
14640
+ "priority tier (never above `priority:high`) unless the generic",
14641
+ "heuristics already pin a higher tier."
14642
+ );
14643
+ }
14644
+ lines.push("");
14645
+ lines.push(
14646
+ "Focus scoring **never lowers** an issue's priority \u2014 the generic",
14647
+ "heuristics set the floor, and focus weight can only lift it.",
14648
+ "`priority:critical` is never set by focus scoring alone; the",
14649
+ "generic heuristics own that tier."
14650
+ );
14651
+ lines.push("");
14652
+ lines.push("### Agent-driven expansion");
14653
+ lines.push("");
14654
+ if (focus.agentExpansionRules) {
14655
+ const rules = focus.agentExpansionRules;
14656
+ const allowedList = rules.allowedTypes.map((t) => `\`${t}\``).join(", ");
14657
+ const forbiddenList = rules.forbiddenTypes.map((t) => `\`${t}\``).join(", ");
14658
+ lines.push(
14659
+ `Agents may **append** new focus areas to \`${focusFilePath}\``,
14660
+ "when they discover a relevant entity during work, subject to",
14661
+ "these guard-rails:"
14662
+ );
14663
+ lines.push("");
14664
+ lines.push(
14665
+ `- **Max weight.** Agent-appended entries must set \`weight\` to`,
14666
+ ` \`${rules.maxWeight}\` or less. Higher weights require a human.`
14667
+ );
14668
+ lines.push(
14669
+ "- **Allowed types.** Agents may only introduce entries whose",
14670
+ ` \`type\` is one of: ${allowedList || "(none)"}.`
14671
+ );
14672
+ if (rules.forbiddenTypes.length > 0) {
14673
+ lines.push(
14674
+ "- **Forbidden types.** Even inside `allowedTypes`, agents must",
14675
+ ` never introduce entries whose \`type\` is one of: ${forbiddenList}.`
14676
+ );
14677
+ }
14678
+ if (rules.maxKeywords !== void 0) {
14679
+ lines.push(
14680
+ "- **Max keywords per match field.** Agent-appended entries",
14681
+ ` may list at most \`${rules.maxKeywords}\` items in each of`,
14682
+ " `match.labels`, `match.titleKeywords`, and `match.bodyKeywords`."
14683
+ );
14684
+ }
14685
+ lines.push(
14686
+ '- **Provenance.** Agent-appended entries must set `source: "agent"`',
14687
+ ' and `discoveredIn: "#<issue>"` referencing the issue that',
14688
+ " surfaced the focus area."
14689
+ );
14690
+ lines.push(
14691
+ "- **Append-only.** Never modify or remove existing entries.",
14692
+ " Human curators own edits and deletions."
14693
+ );
14694
+ } else {
14695
+ lines.push(
14696
+ `Agents must **not** append to \`${focusFilePath}\`. This project`,
14697
+ "has not declared agent-expansion rules \u2014 all focus-area curation",
14698
+ "is performed by humans. If you discover a relevant entity that",
14699
+ "is not covered by an existing focus area, raise it in the issue",
14700
+ "or PR discussion instead of editing the focus file."
14701
+ );
14702
+ }
14703
+ return lines.join("\n");
14704
+ }
14705
+
14706
+ // src/agent/bundles/meeting-types.ts
14707
+ var DEFAULT_AGENDA_TEMPLATE_ROOT = "<meetingsRoot>/_agenda-templates";
14708
+ function renderMeetingTypesSection(meetings) {
14709
+ if (!meetings) {
14710
+ return "";
14711
+ }
14712
+ const types = meetings.meetingTypes ?? [];
14713
+ const areas = meetings.meetingAreas ?? [];
14714
+ if (types.length === 0 && areas.length === 0) {
14715
+ return "";
14716
+ }
14717
+ const sections = [];
14718
+ if (types.length > 0) {
14719
+ sections.push(renderMeetingTypes(types, meetings.agendaTemplateRoot));
14720
+ }
14721
+ if (areas.length > 0) {
14722
+ sections.push(renderMeetingAreas(areas));
14723
+ }
14724
+ return sections.join("\n\n");
14725
+ }
14726
+ function renderMeetingTypes(types, agendaTemplateRoot) {
14727
+ const resolvedRoot = agendaTemplateRoot ?? DEFAULT_AGENDA_TEMPLATE_ROOT;
14728
+ const lines = [
14729
+ "## Recognized meeting types",
14730
+ "",
14731
+ "This project declares a meeting-type taxonomy through",
14732
+ "`AgentConfigOptions.meetings.meetingTypes`. When classifying a",
14733
+ "meeting transcript, pick the `id` from this list that best fits the",
14734
+ "meeting; do **not** invent new type identifiers. Agenda-template",
14735
+ `paths below are resolved relative to \`${resolvedRoot}\`.`,
14736
+ "",
14737
+ "| ID | Label | Scope | Cadence | Default duration | Agenda template |",
14738
+ "|----|-------|-------|---------|------------------|-----------------|"
14739
+ ];
14740
+ for (const type of types) {
14741
+ const cadence = type.cadence ? `\`${type.cadence}\`` : "\u2014";
14742
+ const duration = type.defaultDurationMinutes !== void 0 ? `${type.defaultDurationMinutes} min` : "\u2014";
14743
+ const template = type.agendaTemplatePath ? `\`${type.agendaTemplatePath}\`` : "\u2014";
14744
+ lines.push(
14745
+ `| \`${type.id}\` | ${type.label} | \`${type.scope}\` | ${cadence} | ${duration} | ${template} |`
14746
+ );
14747
+ }
14748
+ return lines.join("\n");
14749
+ }
14750
+ function renderMeetingAreas(areas) {
14751
+ const lines = [
14752
+ "## Area \u2192 doc-root mapping",
14753
+ "",
14754
+ "This project declares a meeting-area routing map through",
14755
+ "`AgentConfigOptions.meetings.meetingAreas`. When a meeting note's",
14756
+ "frontmatter carries an `area:` value matching an `id` below, route",
14757
+ "phase-4 direct edits into the corresponding sub-tree of the docs",
14758
+ "root (`AgentPathsConfig.docsRoot`). Meetings whose `area` does not",
14759
+ "match any declared entry fall back to the default meetings root.",
14760
+ "",
14761
+ "| Area ID | Label | Doc-root sub-folder |",
14762
+ "|---------|-------|---------------------|"
14763
+ ];
14764
+ for (const area of areas) {
14765
+ lines.push(`| \`${area.id}\` | ${area.label} | \`${area.docRoot}\` |`);
14766
+ }
14767
+ return lines.join("\n");
14768
+ }
14769
+
14584
14770
  // src/agent/bundles/priority-rules.ts
14585
14771
  function renderPriorityRulesSection(rules) {
14586
14772
  if (rules.length === 0) {
@@ -15554,6 +15740,38 @@ ${section}`
15554
15740
  });
15555
15741
  }
15556
15742
  }
15743
+ if (this.options.focus) {
15744
+ const issueLabelRule = ruleMap.get("issue-label-conventions");
15745
+ if (issueLabelRule) {
15746
+ const section = renderFocusSection(this.options.focus);
15747
+ if (section.length > 0) {
15748
+ ruleMap.set("issue-label-conventions", {
15749
+ ...issueLabelRule,
15750
+ content: `${issueLabelRule.content}
15751
+
15752
+ ---
15753
+
15754
+ ${section}`
15755
+ });
15756
+ }
15757
+ }
15758
+ }
15759
+ if (this.options.meetings) {
15760
+ const meetingRule = ruleMap.get("meeting-processing-workflow");
15761
+ if (meetingRule) {
15762
+ const section = renderMeetingTypesSection(this.options.meetings);
15763
+ if (section.length > 0) {
15764
+ ruleMap.set("meeting-processing-workflow", {
15765
+ ...meetingRule,
15766
+ content: `${meetingRule.content}
15767
+
15768
+ ---
15769
+
15770
+ ${section}`
15771
+ });
15772
+ }
15773
+ }
15774
+ }
15557
15775
  return [...ruleMap.values()].sort((a, b) => {
15558
15776
  if (a.name === "project-overview") return -1;
15559
15777
  if (b.name === "project-overview") return 1;
@@ -18365,6 +18583,8 @@ var TypeScriptConfig = class extends import_projen22.Component {
18365
18583
  pnpmBundle,
18366
18584
  prReviewBundle,
18367
18585
  projenBundle,
18586
+ renderFocusSection,
18587
+ renderMeetingTypesSection,
18368
18588
  renderPriorityRulesSection,
18369
18589
  requirementsAnalystBundle,
18370
18590
  requirementsReviewerBundle,