@codedrifters/configulator 0.0.255 → 0.0.256

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 CHANGED
@@ -970,6 +970,156 @@ interface PriorityRule {
970
970
  */
971
971
  readonly rationale: string;
972
972
  }
973
+ /*******************************************************************************
974
+ *
975
+ * Focus Scoring
976
+ *
977
+ ******************************************************************************/
978
+ /**
979
+ * Match predicate for a single focus area. At least one sub-field
980
+ * should be set; multiple sub-fields on the same match combine as a
981
+ * logical OR (any one matching contributes the focus area's weight).
982
+ *
983
+ * @see FocusArea
984
+ */
985
+ interface FocusAreaMatch {
986
+ /** Any of these labels present on the issue matches. */
987
+ readonly labels?: ReadonlyArray<string>;
988
+ /**
989
+ * Case-insensitive substrings matched against the issue title.
990
+ * A hit on any single keyword fires the match.
991
+ */
992
+ readonly titleKeywords?: ReadonlyArray<string>;
993
+ /**
994
+ * Case-insensitive substrings matched against the issue body.
995
+ * A hit on any single keyword fires the match.
996
+ */
997
+ readonly bodyKeywords?: ReadonlyArray<string>;
998
+ }
999
+ /**
1000
+ * A single scored focus area — a named customer, segment,
1001
+ * organization, software product, regulation, or person the project
1002
+ * cares about right now. Matching issues receive this area's
1003
+ * `weight` as a priority boost at triage time.
1004
+ *
1005
+ * @see FocusConfig
1006
+ * @see ./bundles/focus.ts#renderFocusSection
1007
+ */
1008
+ interface FocusArea {
1009
+ /** Human-readable name for the focus area (e.g. "Acme Corp"). */
1010
+ readonly name: string;
1011
+ /**
1012
+ * Consuming-repo-defined vocabulary describing what kind of entity
1013
+ * this focus area represents (e.g. `"customer"`, `"segment"`,
1014
+ * `"organization"`, `"software"`, `"regulation"`, `"person"`).
1015
+ * The `AgentExpansionRules.allowedTypes` /
1016
+ * `AgentExpansionRules.forbiddenTypes` lists gate what values
1017
+ * agents are permitted to introduce.
1018
+ */
1019
+ readonly type: string;
1020
+ /**
1021
+ * Provenance. `"human"` entries are curated by a maintainer;
1022
+ * `"agent"` entries were appended by an agent under the
1023
+ * agent-expansion rules and must carry a `discoveredIn` reference.
1024
+ */
1025
+ readonly source: "human" | "agent";
1026
+ /**
1027
+ * Issue reference (e.g. `"#123"`) that introduced the focus area.
1028
+ * Required when `source` is `"agent"` so the provenance of every
1029
+ * agent-appended entry is auditable; optional for human entries.
1030
+ */
1031
+ readonly discoveredIn?: string;
1032
+ /** Match predicate that decides which issues this area applies to. */
1033
+ readonly match: FocusAreaMatch;
1034
+ /**
1035
+ * Positive integer weight contributed to the issue's focus score
1036
+ * when the match fires. Consuming repos typically cap this with
1037
+ * `AgentExpansionRules.maxWeight` (default 8 in openhi's reference
1038
+ * implementation).
1039
+ */
1040
+ readonly weight: number;
1041
+ }
1042
+ /**
1043
+ * Guard-rails on what agents are allowed to append to `focus.json`
1044
+ * without human review. The agent-expansion contract is append-only:
1045
+ * agents never modify or remove existing entries.
1046
+ */
1047
+ interface AgentExpansionRules {
1048
+ /**
1049
+ * Hard cap on the `weight` an agent may set on a newly appended
1050
+ * focus area. Human curators may use higher weights.
1051
+ */
1052
+ readonly maxWeight: number;
1053
+ /**
1054
+ * Whitelist of `FocusArea.type` values agents are permitted to
1055
+ * introduce. Any type outside this list must be added by a human.
1056
+ */
1057
+ readonly allowedTypes: ReadonlyArray<string>;
1058
+ /**
1059
+ * Explicit blocklist of `FocusArea.type` values agents must never
1060
+ * introduce, even if the list accidentally overlaps
1061
+ * `allowedTypes`. `forbiddenTypes` wins on conflict.
1062
+ */
1063
+ readonly forbiddenTypes: ReadonlyArray<string>;
1064
+ /**
1065
+ * Optional cap on the number of entries in each keyword array
1066
+ * (`match.labels`, `match.titleKeywords`, `match.bodyKeywords`)
1067
+ * on an agent-appended focus area. Prevents runaway keyword
1068
+ * expansion. Human entries are not subject to this cap.
1069
+ */
1070
+ readonly maxKeywords?: number;
1071
+ }
1072
+ /**
1073
+ * Top-level configuration for the focus-scoring engine. The schema
1074
+ * and agent-expansion rules live in the configulator bundle; the
1075
+ * actual `focus.json` file is authored and curated in the consuming
1076
+ * repo.
1077
+ *
1078
+ * When supplied via `AgentConfigOptions.focus`, the `base` bundle
1079
+ * appends a "Focus scoring" subsection to the
1080
+ * `issue-label-conventions` rule that teaches agents how to read
1081
+ * `focus.json`, how focus weight interacts with the
1082
+ * `priority:*` taxonomy, and what they may and may not append to
1083
+ * the file.
1084
+ *
1085
+ * @see FocusArea
1086
+ * @see AgentExpansionRules
1087
+ * @see ./bundles/focus.ts#renderFocusSection
1088
+ */
1089
+ interface FocusConfig {
1090
+ /**
1091
+ * Path to the focus file relative to the repo root.
1092
+ * @default ".claude/focus.json"
1093
+ */
1094
+ readonly focusFilePath?: string;
1095
+ /**
1096
+ * Schema version the consuming repo's `focus.json` conforms to.
1097
+ * Bump when the schema changes in a backwards-incompatible way.
1098
+ * @default 1
1099
+ */
1100
+ readonly schemaVersion?: number;
1101
+ /**
1102
+ * Cumulative focus-score thresholds that map into the
1103
+ * `priority:*` taxonomy. An issue whose total focus score
1104
+ * (sum of matched focus-area weights) reaches `high` is boosted
1105
+ * to `priority:high`; reaching `medium` keeps it at
1106
+ * `priority:medium`. Scores below `medium` do not affect the
1107
+ * inferred priority.
1108
+ *
1109
+ * @remarks `high` and `medium` must be integers. The JSON schema
1110
+ * at `schemas/focus.schema.json` enforces this for `focus.json`.
1111
+ */
1112
+ readonly thresholds?: {
1113
+ readonly high: number;
1114
+ readonly medium: number;
1115
+ };
1116
+ /**
1117
+ * Guard-rails that govern what agents may append to `focus.json`.
1118
+ * When omitted, the rendered rule documents that agents must
1119
+ * **not** append to `focus.json` without human review.
1120
+ */
1121
+ readonly agentExpansionRules?: AgentExpansionRules;
1122
+ }
973
1123
  /*******************************************************************************
974
1124
  *
975
1125
  * AgentConfig Options
@@ -1082,6 +1232,26 @@ interface AgentConfigOptions {
1082
1232
  * @see ./bundles/priority-rules.ts#renderPriorityRulesSection
1083
1233
  */
1084
1234
  readonly priorityRules?: ReadonlyArray<PriorityRule>;
1235
+ /**
1236
+ * Focus-scoring configuration. Declares the path to the consuming
1237
+ * repo's `focus.json` file, score thresholds, and the
1238
+ * agent-expansion rules that govern what agents may append to the
1239
+ * file.
1240
+ *
1241
+ * When set, the `base` bundle appends a "Focus scoring"
1242
+ * subsection to the `issue-label-conventions` rule that teaches
1243
+ * agents (a) how to read `focus.json`, (b) how focus weight
1244
+ * interacts with the `priority:*` taxonomy, and (c) the
1245
+ * agent-driven expansion contract. The actual `focus.json` file
1246
+ * is authored and curated in the consuming repo — configulator
1247
+ * ships the schema and agent instructions only.
1248
+ *
1249
+ * @see FocusConfig
1250
+ * @see FocusArea
1251
+ * @see AgentExpansionRules
1252
+ * @see ./bundles/focus.ts#renderFocusSection
1253
+ */
1254
+ readonly focus?: FocusConfig;
1085
1255
  }
1086
1256
 
1087
1257
  /**
@@ -1354,6 +1524,24 @@ declare const prReviewBundle: AgentRuleBundle;
1354
1524
  */
1355
1525
  declare const projenBundle: AgentRuleBundle;
1356
1526
 
1527
+ /**
1528
+ * Render the markdown subsection appended to the
1529
+ * `issue-label-conventions` rule when `AgentConfigOptions.focus` is
1530
+ * supplied. Returns an empty string when `focus` is undefined so
1531
+ * callers can unconditionally concatenate the result.
1532
+ *
1533
+ * The section documents three things for agents:
1534
+ *
1535
+ * 1. How to read `focus.json` at triage time
1536
+ * 2. How focus weight interacts with the `priority:*` taxonomy
1537
+ * 3. The agent-driven expansion contract (what agents may append)
1538
+ *
1539
+ * Configulator ships this rule content plus a JSON Schema that
1540
+ * validates the `focus.json` file; the file itself is authored and
1541
+ * curated in the consuming repo.
1542
+ */
1543
+ declare function renderFocusSection(focus: FocusConfig | undefined): string;
1544
+
1357
1545
  /**
1358
1546
  * Render the markdown subsection appended to the
1359
1547
  * `issue-label-conventions` rule when `AgentConfigOptions.priorityRules`
@@ -4088,4 +4276,4 @@ declare const COMPLETE_JOB_ID = "complete";
4088
4276
  */
4089
4277
  declare function addBuildCompleteJob(buildWorkflow: BuildWorkflow): void;
4090
4278
 
4091
- export { AGENT_MODEL, AGENT_PLATFORM, AGENT_RULE_SCOPE, AgentConfig, type AgentConfigOptions, type AgentModel, type AgentPathsConfig, type AgentPlatform, type AgentPlatformOverrides, type AgentProcedure, type AgentRule, type AgentRuleBundle, type AgentRuleScope, type AgentSkill, type AgentSubAgent, type AgentSubAgentPlatformOverrides, type ApproveMergeUpgradeOptions, AstroConfig, type AstroConfigOptions, type AstroIntegrationSpec, AstroOutput, AstroProject, type AstroProjectOptions, type AwsAccount, AwsCdkProject, type AwsCdkProjectOptions, AwsDeployWorkflow, AwsDeploymentConfig, AwsDeploymentTarget, type AwsDeploymentTargetOptions, type AwsLocalDeploymentConfig, type AwsOrganization, type AwsRegion, AwsTeardownWorkflow, type AwsTeardownWorkflowOptions, BUILT_IN_BUNDLES, CLAUDE_RULE_TARGET, COMPLETE_JOB_ID, type CiDeploymentConfig, type ClassTypeOptions, type ClaudeAutoModeConfig, type ClaudeHookAction, type ClaudeHookEntry, type ClaudeHooksConfig, type ClaudePermissionsConfig, type ClaudeRuleTarget, type ClaudeSandboxConfig, type ClaudeSettingsConfig, type CopilotHandoff, type CursorHookAction, type CursorHooksConfig, type CursorSettingsConfig, DEFAULT_AGENT_PATHS, DEFAULT_PRIORITY_LABELS, DEFAULT_STATUS_LABELS, DEFAULT_TEARDOWN_BRANCH_PATTERNS, DEFAULT_TYPE_LABELS, type DeployWorkflowOptions, type DeploymentMetadata, type GitBranch, type GitHubBoardMetadata, type GitHubProjectMetadata, type GitHubSprintMetadata, type IDependencyResolver, JsiiFaker, LAYOUT_ENFORCEMENT, LAYOUT_ROOT_BY_PROJECT_TYPE, type LabelDefinition, type LayoutEnforcement, type LayoutViolation, MCP_TRANSPORT, MERGE_METHODS, MIMIMUM_RELEASE_AGE, MINIMUM_RELEASE_AGE, MONOREPO_LAYOUT, type McpServerConfig, type McpTransport, type MergeMethod, type MonorepoLayoutRoot, MonorepoProject, type MonorepoProjectOptions, type OrganizationMetadata, PROD_DEPLOY_NAME, PnpmWorkspace, type PnpmWorkspaceOptions, type PriorityRule, ProjectMetadata, type ProjectMetadataOptions, REQUIREMENTS_WRITER_PATHS, ROOT_CI_TASK_NAME, ROOT_TURBO_TASK_NAME, type RemoteCacheOptions, type RepositoryMetadata, ResetTask, type ResetTaskOptions, type ResolvedAgentPaths, type ResolvedProjectMetadata, STARLIGHT_ROLE, type SlackMetadata, type StarlightEditLink, type StarlightLogo, StarlightProject, type StarlightProjectOptions, type StarlightRole, type StarlightSidebarItem, type StarlightSingletonViolation, type StarlightSocialLink, type SyncLabelsOptions, type TemplateResolveResult, TestRunner, TurboRepo, type TurboRepoOptions, TurboRepoTask, type TurboRepoTaskOptions, TypeScriptConfig, TypeScriptProject, type TypeScriptProjectOptions, VERSION, VERSION_KEYS_SKIP, VERSION_NPM_PACKAGES, VSCodeConfig, type VersionKey, Vitest, type VitestConfigOptions, type VitestOptions, 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 };
4279
+ export { AGENT_MODEL, AGENT_PLATFORM, AGENT_RULE_SCOPE, AgentConfig, type AgentConfigOptions, type AgentExpansionRules, type AgentModel, type AgentPathsConfig, type AgentPlatform, type AgentPlatformOverrides, type AgentProcedure, type AgentRule, type AgentRuleBundle, type AgentRuleScope, type AgentSkill, type AgentSubAgent, type AgentSubAgentPlatformOverrides, type ApproveMergeUpgradeOptions, AstroConfig, type AstroConfigOptions, type AstroIntegrationSpec, AstroOutput, AstroProject, type AstroProjectOptions, type AwsAccount, AwsCdkProject, type AwsCdkProjectOptions, AwsDeployWorkflow, AwsDeploymentConfig, AwsDeploymentTarget, type AwsDeploymentTargetOptions, type AwsLocalDeploymentConfig, type AwsOrganization, type AwsRegion, AwsTeardownWorkflow, type AwsTeardownWorkflowOptions, BUILT_IN_BUNDLES, CLAUDE_RULE_TARGET, COMPLETE_JOB_ID, type CiDeploymentConfig, type ClassTypeOptions, type ClaudeAutoModeConfig, type ClaudeHookAction, type ClaudeHookEntry, type ClaudeHooksConfig, type ClaudePermissionsConfig, type ClaudeRuleTarget, type ClaudeSandboxConfig, type ClaudeSettingsConfig, type CopilotHandoff, type CursorHookAction, type CursorHooksConfig, type CursorSettingsConfig, DEFAULT_AGENT_PATHS, DEFAULT_PRIORITY_LABELS, DEFAULT_STATUS_LABELS, DEFAULT_TEARDOWN_BRANCH_PATTERNS, DEFAULT_TYPE_LABELS, type DeployWorkflowOptions, type DeploymentMetadata, type FocusArea, type FocusAreaMatch, type FocusConfig, type GitBranch, type GitHubBoardMetadata, type GitHubProjectMetadata, type GitHubSprintMetadata, type IDependencyResolver, JsiiFaker, LAYOUT_ENFORCEMENT, LAYOUT_ROOT_BY_PROJECT_TYPE, type LabelDefinition, type LayoutEnforcement, type LayoutViolation, MCP_TRANSPORT, MERGE_METHODS, MIMIMUM_RELEASE_AGE, MINIMUM_RELEASE_AGE, MONOREPO_LAYOUT, type McpServerConfig, type McpTransport, type MergeMethod, type MonorepoLayoutRoot, MonorepoProject, type MonorepoProjectOptions, type OrganizationMetadata, PROD_DEPLOY_NAME, PnpmWorkspace, type PnpmWorkspaceOptions, type PriorityRule, ProjectMetadata, type ProjectMetadataOptions, REQUIREMENTS_WRITER_PATHS, ROOT_CI_TASK_NAME, ROOT_TURBO_TASK_NAME, type RemoteCacheOptions, type RepositoryMetadata, ResetTask, type ResetTaskOptions, type ResolvedAgentPaths, type ResolvedProjectMetadata, STARLIGHT_ROLE, type SlackMetadata, type StarlightEditLink, type StarlightLogo, StarlightProject, type StarlightProjectOptions, type StarlightRole, type StarlightSidebarItem, type StarlightSingletonViolation, type StarlightSocialLink, type SyncLabelsOptions, type TemplateResolveResult, TestRunner, TurboRepo, type TurboRepoOptions, TurboRepoTask, type TurboRepoTaskOptions, TypeScriptConfig, TypeScriptProject, type TypeScriptProjectOptions, VERSION, VERSION_KEYS_SKIP, VERSION_NPM_PACKAGES, VSCodeConfig, type VersionKey, Vitest, type VitestConfigOptions, type VitestOptions, addApproveMergeUpgradeWorkflow, addBuildCompleteJob, addSyncLabelsWorkflow, awsCdkBundle, baseBundle, bcmWriterBundle, companyProfileBundle, formatLayoutViolation, formatStarlightSingletonViolation, getLatestEligibleVersion, githubWorkflowBundle, industryDiscoveryBundle, jestBundle, maintenanceAuditBundle, meetingAnalysisBundle, orchestratorBundle, peopleProfileBundle, pnpmBundle, prReviewBundle, projenBundle, renderFocusSection, renderPriorityRulesSection, requirementsAnalystBundle, requirementsReviewerBundle, requirementsWriterBundle, researchPipelineBundle, resolveAgentPaths, resolveAstroProjectOutdir, resolveAwsCdkProjectOutdir, resolveModelAlias, resolveOutdirFromPackageName, resolveTemplateVariables, resolveTypeScriptProjectOutdir, slackBundle, softwareProfileBundle, turborepoBundle, typescriptBundle, validateMonorepoLayout, validateStarlightSingleton, vitestBundle };
package/lib/index.d.ts CHANGED
@@ -1019,6 +1019,156 @@ 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
+ }
1022
1172
  /*******************************************************************************
1023
1173
  *
1024
1174
  * AgentConfig Options
@@ -1131,6 +1281,26 @@ interface AgentConfigOptions {
1131
1281
  * @see ./bundles/priority-rules.ts#renderPriorityRulesSection
1132
1282
  */
1133
1283
  readonly priorityRules?: ReadonlyArray<PriorityRule>;
1284
+ /**
1285
+ * Focus-scoring configuration. Declares the path to the consuming
1286
+ * repo's `focus.json` file, score thresholds, and the
1287
+ * agent-expansion rules that govern what agents may append to the
1288
+ * file.
1289
+ *
1290
+ * When set, the `base` bundle appends a "Focus scoring"
1291
+ * subsection to the `issue-label-conventions` rule that teaches
1292
+ * agents (a) how to read `focus.json`, (b) how focus weight
1293
+ * interacts with the `priority:*` taxonomy, and (c) the
1294
+ * agent-driven expansion contract. The actual `focus.json` file
1295
+ * is authored and curated in the consuming repo — configulator
1296
+ * ships the schema and agent instructions only.
1297
+ *
1298
+ * @see FocusConfig
1299
+ * @see FocusArea
1300
+ * @see AgentExpansionRules
1301
+ * @see ./bundles/focus.ts#renderFocusSection
1302
+ */
1303
+ readonly focus?: FocusConfig;
1134
1304
  }
1135
1305
 
1136
1306
  /**
@@ -1403,6 +1573,24 @@ declare const prReviewBundle: AgentRuleBundle;
1403
1573
  */
1404
1574
  declare const projenBundle: AgentRuleBundle;
1405
1575
 
1576
+ /**
1577
+ * Render the markdown subsection appended to the
1578
+ * `issue-label-conventions` rule when `AgentConfigOptions.focus` is
1579
+ * supplied. Returns an empty string when `focus` is undefined so
1580
+ * callers can unconditionally concatenate the result.
1581
+ *
1582
+ * The section documents three things for agents:
1583
+ *
1584
+ * 1. How to read `focus.json` at triage time
1585
+ * 2. How focus weight interacts with the `priority:*` taxonomy
1586
+ * 3. The agent-driven expansion contract (what agents may append)
1587
+ *
1588
+ * Configulator ships this rule content plus a JSON Schema that
1589
+ * validates the `focus.json` file; the file itself is authored and
1590
+ * curated in the consuming repo.
1591
+ */
1592
+ declare function renderFocusSection(focus: FocusConfig | undefined): string;
1593
+
1406
1594
  /**
1407
1595
  * Render the markdown subsection appended to the
1408
1596
  * `issue-label-conventions` rule when `AgentConfigOptions.priorityRules`
@@ -4137,5 +4325,5 @@ declare const COMPLETE_JOB_ID = "complete";
4137
4325
  */
4138
4326
  declare function addBuildCompleteJob(buildWorkflow: BuildWorkflow): void;
4139
4327
 
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 };
4328
+ 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, renderPriorityRulesSection, requirementsAnalystBundle, requirementsReviewerBundle, requirementsWriterBundle, researchPipelineBundle, resolveAgentPaths, resolveAstroProjectOutdir, resolveAwsCdkProjectOutdir, resolveModelAlias, resolveOutdirFromPackageName, resolveTemplateVariables, resolveTypeScriptProjectOutdir, slackBundle, softwareProfileBundle, turborepoBundle, typescriptBundle, validateMonorepoLayout, validateStarlightSingleton, vitestBundle };
4329
+ 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, 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,7 @@ __export(index_exports, {
243
243
  pnpmBundle: () => pnpmBundle,
244
244
  prReviewBundle: () => prReviewBundle,
245
245
  projenBundle: () => projenBundle,
246
+ renderFocusSection: () => renderFocusSection,
246
247
  renderPriorityRulesSection: () => renderPriorityRulesSection,
247
248
  requirementsAnalystBundle: () => requirementsAnalystBundle,
248
249
  requirementsReviewerBundle: () => requirementsReviewerBundle,
@@ -14581,6 +14582,126 @@ var vitestBundle = {
14581
14582
  }
14582
14583
  };
14583
14584
 
14585
+ // src/agent/bundles/focus.ts
14586
+ var DEFAULT_FOCUS_FILE_PATH = ".claude/focus.json";
14587
+ var DEFAULT_SCHEMA_VERSION = 1;
14588
+ function renderFocusSection(focus) {
14589
+ if (!focus) {
14590
+ return "";
14591
+ }
14592
+ const focusFilePath = focus.focusFilePath ?? DEFAULT_FOCUS_FILE_PATH;
14593
+ const schemaVersion = focus.schemaVersion ?? DEFAULT_SCHEMA_VERSION;
14594
+ const lines = [
14595
+ "## Focus scoring",
14596
+ "",
14597
+ "This project runs a **focus-scoring engine** alongside the generic",
14598
+ "`priority:*` inference above. Focus scoring boosts the priority of",
14599
+ "issues that match the project's currently-declared focus areas \u2014",
14600
+ "named customers, segments, organizations, software products,",
14601
+ "regulations, or people the project cares about right now.",
14602
+ "",
14603
+ "### Reading `focus.json`",
14604
+ "",
14605
+ `The focus file lives at \`${focusFilePath}\` and conforms to schema`,
14606
+ `version \`${schemaVersion}\`. Each entry declares a match predicate`,
14607
+ "(any combination of `labels`, `titleKeywords`, `bodyKeywords`) and",
14608
+ "a positive integer `weight`. At triage time:",
14609
+ "",
14610
+ `1. Read \`${focusFilePath}\`. If the file is missing or empty,`,
14611
+ " skip focus scoring entirely \u2014 the generic priority heuristics",
14612
+ " apply unchanged.",
14613
+ "2. For each focus area, test its match predicate against the",
14614
+ " issue's labels, title, and body. A match on **any** sub-field",
14615
+ " (labels / title keywords / body keywords) fires the area and",
14616
+ " contributes its `weight` to the issue's focus score.",
14617
+ "3. Keyword matching is case-insensitive substring matching \u2014",
14618
+ ' `titleKeywords: ["Acme"]` matches an issue titled',
14619
+ " `feat: onboard acme corp`.",
14620
+ "4. Sum all matched weights to produce the issue's **focus score**.",
14621
+ ""
14622
+ ];
14623
+ lines.push("### How focus score interacts with `priority:*`");
14624
+ lines.push("");
14625
+ if (focus.thresholds) {
14626
+ const { high, medium } = focus.thresholds;
14627
+ lines.push(`A focus score of \`${high}\` or more boosts the`);
14628
+ const mediumBand = high - medium === 1 ? `A focus score of \`${medium}\` keeps` : `A focus score of \`${medium}\` up to \`${high - 1}\` keeps`;
14629
+ lines.push(
14630
+ "issue to `priority:high`.",
14631
+ `${mediumBand} the issue at \`priority:medium\`. Scores below`,
14632
+ `\`${medium}\` do **not** alter the priority that`,
14633
+ "the generic heuristics would otherwise infer."
14634
+ );
14635
+ } else {
14636
+ lines.push(
14637
+ "This project has not declared explicit focus-score thresholds.",
14638
+ "Treat any non-zero focus score as a soft signal to lift one",
14639
+ "priority tier (never above `priority:high`) unless the generic",
14640
+ "heuristics already pin a higher tier."
14641
+ );
14642
+ }
14643
+ lines.push("");
14644
+ lines.push(
14645
+ "Focus scoring **never lowers** an issue's priority \u2014 the generic",
14646
+ "heuristics set the floor, and focus weight can only lift it.",
14647
+ "`priority:critical` is never set by focus scoring alone; the",
14648
+ "generic heuristics own that tier."
14649
+ );
14650
+ lines.push("");
14651
+ lines.push("### Agent-driven expansion");
14652
+ lines.push("");
14653
+ if (focus.agentExpansionRules) {
14654
+ const rules = focus.agentExpansionRules;
14655
+ const allowedList = rules.allowedTypes.map((t) => `\`${t}\``).join(", ");
14656
+ const forbiddenList = rules.forbiddenTypes.map((t) => `\`${t}\``).join(", ");
14657
+ lines.push(
14658
+ `Agents may **append** new focus areas to \`${focusFilePath}\``,
14659
+ "when they discover a relevant entity during work, subject to",
14660
+ "these guard-rails:"
14661
+ );
14662
+ lines.push("");
14663
+ lines.push(
14664
+ `- **Max weight.** Agent-appended entries must set \`weight\` to`,
14665
+ ` \`${rules.maxWeight}\` or less. Higher weights require a human.`
14666
+ );
14667
+ lines.push(
14668
+ "- **Allowed types.** Agents may only introduce entries whose",
14669
+ ` \`type\` is one of: ${allowedList || "(none)"}.`
14670
+ );
14671
+ if (rules.forbiddenTypes.length > 0) {
14672
+ lines.push(
14673
+ "- **Forbidden types.** Even inside `allowedTypes`, agents must",
14674
+ ` never introduce entries whose \`type\` is one of: ${forbiddenList}.`
14675
+ );
14676
+ }
14677
+ if (rules.maxKeywords !== void 0) {
14678
+ lines.push(
14679
+ "- **Max keywords per match field.** Agent-appended entries",
14680
+ ` may list at most \`${rules.maxKeywords}\` items in each of`,
14681
+ " `match.labels`, `match.titleKeywords`, and `match.bodyKeywords`."
14682
+ );
14683
+ }
14684
+ lines.push(
14685
+ '- **Provenance.** Agent-appended entries must set `source: "agent"`',
14686
+ ' and `discoveredIn: "#<issue>"` referencing the issue that',
14687
+ " surfaced the focus area."
14688
+ );
14689
+ lines.push(
14690
+ "- **Append-only.** Never modify or remove existing entries.",
14691
+ " Human curators own edits and deletions."
14692
+ );
14693
+ } else {
14694
+ lines.push(
14695
+ `Agents must **not** append to \`${focusFilePath}\`. This project`,
14696
+ "has not declared agent-expansion rules \u2014 all focus-area curation",
14697
+ "is performed by humans. If you discover a relevant entity that",
14698
+ "is not covered by an existing focus area, raise it in the issue",
14699
+ "or PR discussion instead of editing the focus file."
14700
+ );
14701
+ }
14702
+ return lines.join("\n");
14703
+ }
14704
+
14584
14705
  // src/agent/bundles/priority-rules.ts
14585
14706
  function renderPriorityRulesSection(rules) {
14586
14707
  if (rules.length === 0) {
@@ -15554,6 +15675,22 @@ ${section}`
15554
15675
  });
15555
15676
  }
15556
15677
  }
15678
+ if (this.options.focus) {
15679
+ const issueLabelRule = ruleMap.get("issue-label-conventions");
15680
+ if (issueLabelRule) {
15681
+ const section = renderFocusSection(this.options.focus);
15682
+ if (section.length > 0) {
15683
+ ruleMap.set("issue-label-conventions", {
15684
+ ...issueLabelRule,
15685
+ content: `${issueLabelRule.content}
15686
+
15687
+ ---
15688
+
15689
+ ${section}`
15690
+ });
15691
+ }
15692
+ }
15693
+ }
15557
15694
  return [...ruleMap.values()].sort((a, b) => {
15558
15695
  if (a.name === "project-overview") return -1;
15559
15696
  if (b.name === "project-overview") return 1;
@@ -18365,6 +18502,7 @@ var TypeScriptConfig = class extends import_projen22.Component {
18365
18502
  pnpmBundle,
18366
18503
  prReviewBundle,
18367
18504
  projenBundle,
18505
+ renderFocusSection,
18368
18506
  renderPriorityRulesSection,
18369
18507
  requirementsAnalystBundle,
18370
18508
  requirementsReviewerBundle,