@@ -621,11 +621,6 @@ export type FocusManifestReviewConfig = {
621621 /** `review.auto_review`: deterministic eligibility filters that skip the AI review (never a gate failure).
622622 * Empty/default ⇒ every PR is reviewed (byte-identical). (#1954 / #2038–#2041) */
623623 autoReview : AutoReviewConfig ;
624- /** `review.labeling_rules`: deterministic `{label, when}` rules that SUGGEST a non-scoring label when a PR's
625- * changed paths / title / description match. Surfaced as advisory suggestions, and auto-applied only when the
626- * repo's `autoLabelEnabled` is set. Reserved `gittensor:` labels are refused at parse. Empty (default) ⇒ no
627- * suggestion (byte-identical). (#2045, part of #1959) */
628- labelingRules : LabelingRule [ ] ;
629624 /** `review.ai_model`: per-repo self-host reviewer model/effort overrides (claude-code / codex). Self-host only
630625 * — a hosted (Workers-AI) repo ignores this entirely. All-null (default, absent) ⇒ the operator's global
631626 * CLAUDE_AI_MODEL/CLAUDE_AI_EFFORT/CODEX_AI_MODEL/CODEX_AI_EFFORT env vars apply unchanged (byte-identical).
@@ -660,15 +655,6 @@ export type CommentVerbosity = (typeof COMMENT_VERBOSITY_LEVELS)[number];
660655export const E2E_TEST_DELIVERY_MODES = [ "comment" , "commit" ] as const ;
661656export type E2eTestDeliveryMode = ( typeof E2E_TEST_DELIVERY_MODES ) [ number ] ;
662657
663- /** One `review.labeling_rules[]` entry: a non-reserved `label` plus the deterministic `when` criteria that must ALL
664- * match for it to fire. A rule always has at least one criterion (enforced at parse). */
665- export type LabelingRule = {
666- label : string ;
667- whenPaths : string [ ] ;
668- titleContains : string | null ;
669- descriptionContains : string | null ;
670- } ;
671-
672658/** `review.auto_review.cadence` (#one-shot-review-cadence). `one_shot` = the AI-generated content (main review,
673659 * slop advisory, linked-issue satisfaction) is produced once per PR and never automatically regenerated
674660 * afterward — not on a new push, not on CI-check completion, not on a scheduled sweep tick; only an explicit
@@ -1043,7 +1029,7 @@ const EMPTY_MANIFEST: FocusManifest = {
10431029 publicNotes : [ ] ,
10441030 gate : { ...EMPTY_GATE_CONFIG } ,
10451031 settings : { } ,
1046- review : { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , labelingRules : [ ] , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ,
1032+ review : { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ,
10471033 features : { ...EMPTY_FEATURES_CONFIG } ,
10481034 contentLane : { ...EMPTY_CONTENT_LANE_CONFIG } ,
10491035 repoDocGeneration : { ...EMPTY_REPO_DOC_GENERATION_CONFIG } ,
@@ -1074,7 +1060,7 @@ function emptyManifest(source: FocusManifestSource, warnings: string[] = []): Fo
10741060 warnings,
10751061 gate : { ...EMPTY_GATE_CONFIG } ,
10761062 settings : { } ,
1077- review : { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , labelingRules : [ ] , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ,
1063+ review : { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ,
10781064 features : { ...EMPTY_FEATURES_CONFIG } ,
10791065 contentLane : { ...EMPTY_CONTENT_LANE_CONFIG } ,
10801066 repoDocGeneration : { ...EMPTY_REPO_DOC_GENERATION_CONFIG } ,
@@ -2179,7 +2165,7 @@ function parsePublicSafeText(value: JsonValue | undefined, field: string, warnin
21792165 * throws; invalid/unsafe values are dropped with warnings.
21802166 */
21812167function parseReviewConfig ( value : JsonValue | undefined , warnings : string [ ] ) : FocusManifestReviewConfig {
2182- const empty : FocusManifestReviewConfig = { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , labelingRules : [ ] , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ;
2168+ const empty : FocusManifestReviewConfig = { present : false , footerText : null , note : null , fields : { } , enrichmentAnalyzers : { } , profile : null , tone : null , securityFocus : null , inlineComments : null , fixHandoff : null , autoMergeSummary : null , suggestions : null , changedFilesSummary : null , effortScore : null , impactMap : null , cultureProfile : null , selftune : null , reviewMemory : null , findingCategories : null , inlineCommentsPerCategory : null , minFindingSeverity : null , maxFindings : { ...EMPTY_MAX_FINDINGS_CONFIG } , commentVerbosity : null , e2eTestDelivery : null , e2eTestAutoTrigger : null , pathInstructions : [ ] , instructions : null , excludePaths : [ ] , pathFilters : [ ] , preMergeChecks : [ ] , autoReview : { ...EMPTY_AUTO_REVIEW_CONFIG } , aiModel : { ...EMPTY_SELF_HOST_AI_MODEL_CONFIG } , visual : { ...EMPTY_VISUAL_CONFIG } , linkedIssueSatisfaction : null , sharedConfigSource : null } ;
21832169 if ( value === undefined || value === null ) return empty ;
21842170 if ( typeof value !== "object" || Array . isArray ( value ) ) {
21852171 warnings . push ( `Manifest field "review" must be a mapping; ignoring it.` ) ;
@@ -2247,7 +2233,6 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
22472233 const pathFilters = parseReviewPathFilters ( r . path_filters , warnings ) ;
22482234 const preMergeChecks = parseReviewPreMergeChecks ( r . pre_merge_checks , warnings ) ;
22492235 const autoReview = parseAutoReviewConfig ( r . auto_review , warnings ) ;
2250- const labelingRules = parseReviewLabelingRules ( r . labeling_rules , warnings ) ;
22512236 const aiModel = parseSelfHostAiModelConfig ( r . ai_model , warnings ) ;
22522237 const visual = parseVisualConfig ( r . visual , warnings ) ;
22532238 const linkedIssueSatisfaction = normalizeOptionalEnum ( r . linkedIssueSatisfaction , "review.linkedIssueSatisfaction" , LINKED_ISSUE_SATISFACTION_MODES , warnings ) ;
@@ -2281,7 +2266,6 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
22812266 pathFilters . length > 0 ||
22822267 preMergeChecks . length > 0 ||
22832268 autoReviewPresent ( autoReview ) ||
2284- labelingRules . length > 0 ||
22852269 selfHostAiModelPresent ( aiModel ) ||
22862270 visualConfigPresent ( visual ) ||
22872271 linkedIssueSatisfaction !== null ||
@@ -2320,7 +2304,6 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
23202304 excludePaths,
23212305 pathFilters,
23222306 preMergeChecks,
2323- labelingRules,
23242307 sharedConfigSource : null ,
23252308 } ;
23262309}
@@ -2421,7 +2404,6 @@ function computeReviewConfigPresent(review: Omit<FocusManifestReviewConfig, "pre
24212404 review . pathFilters . length > 0 ||
24222405 review . preMergeChecks . length > 0 ||
24232406 autoReviewPresent ( review . autoReview ) ||
2424- review . labelingRules . length > 0 ||
24252407 selfHostAiModelPresent ( review . aiModel ) ||
24262408 visualConfigPresent ( review . visual ) ||
24272409 review . linkedIssueSatisfaction !== null ||
@@ -2467,7 +2449,6 @@ export function overlayReviewConfig(
24672449 pathFilters : pickOverlayStringList ( override . pathFilters , base . pathFilters ) ,
24682450 preMergeChecks : override . preMergeChecks . length > 0 ? [ ...override . preMergeChecks ] : [ ...base . preMergeChecks ] ,
24692451 autoReview : overlayAutoReviewConfig ( base . autoReview , override . autoReview ) ,
2470- labelingRules : override . labelingRules . length > 0 ? [ ...override . labelingRules ] : [ ...base . labelingRules ] ,
24712452 aiModel : overlaySelfHostAiModelConfig ( base . aiModel , override . aiModel ) ,
24722453 visual : overlayVisualConfig ( base . visual , override . visual ) ,
24732454 linkedIssueSatisfaction : pickOverlayNullable ( override . linkedIssueSatisfaction , base . linkedIssueSatisfaction ) ,
@@ -2501,48 +2482,6 @@ function parseMaxFindingsConfig(value: JsonValue | undefined, warnings: string[]
25012482 } ;
25022483}
25032484
2504- /** The reserved label namespace Gittensor uses for scoring/type/priority (`gittensor:bug`, `gittensor:feature`,
2505- * `gittensor:priority`, …). A maintainer's `labeling_rules` must not drive these — they're managed by the scorer
2506- * and the type-labeler, never by ad-hoc manifest rules — so any `gittensor:`-prefixed label is refused at parse. */
2507- const RESERVED_LABEL_PREFIX = "gittensor:" ;
2508-
2509- function parseReviewLabelingRules ( value : JsonValue | undefined , warnings : string [ ] ) : LabelingRule [ ] {
2510- if ( value === undefined || value === null ) return [ ] ;
2511- if ( ! Array . isArray ( value ) ) {
2512- warnings . push ( `Manifest "review.labeling_rules" must be a list of rules; ignoring it.` ) ;
2513- return [ ] ;
2514- }
2515- const out : LabelingRule [ ] = [ ] ;
2516- for ( const [ index , entry ] of value . entries ( ) ) {
2517- if ( out . length >= MAX_PATH_INSTRUCTIONS ) {
2518- warnings . push ( `Manifest "review.labeling_rules" is capped at ${ MAX_PATH_INSTRUCTIONS } entries; dropping the rest.` ) ;
2519- break ;
2520- }
2521- if ( entry === null || typeof entry !== "object" || Array . isArray ( entry ) ) {
2522- warnings . push ( `Manifest "review.labeling_rules[${ index } ]" must be a mapping; ignoring it.` ) ;
2523- continue ;
2524- }
2525- const e = entry as Record < string , JsonValue > ;
2526- const label = e . label === undefined || e . label === null ? null : parsePublicSafeText ( e . label , `review.labeling_rules[${ index } ].label` , warnings ) ;
2527- if ( label === null ) {
2528- if ( e . label === undefined || e . label === null ) warnings . push ( `Manifest "review.labeling_rules[${ index } ].label" is required; ignoring the entry.` ) ;
2529- continue ; // non-string / empty / not-public-safe already warned by parsePublicSafeText
2530- }
2531- if ( label . toLowerCase ( ) . startsWith ( RESERVED_LABEL_PREFIX ) ) {
2532- warnings . push ( `Manifest "review.labeling_rules[${ index } ].label" ("${ label } ") uses the reserved "${ RESERVED_LABEL_PREFIX } " namespace; ignoring the entry.` ) ;
2533- continue ;
2534- }
2535- const titleContains = e . title_contains === undefined || e . title_contains === null ? null : parsePublicSafeText ( e . title_contains , `review.labeling_rules[${ index } ].title_contains` , warnings ) ;
2536- const descriptionContains = e . description_contains === undefined || e . description_contains === null ? null : parsePublicSafeText ( e . description_contains , `review.labeling_rules[${ index } ].description_contains` , warnings ) ;
2537- const whenPaths = parseManifestGlobList ( e . when_paths , `review.labeling_rules[${ index } ].when_paths` , warnings ) ;
2538- if ( whenPaths . length === 0 && titleContains === null && descriptionContains === null ) {
2539- warnings . push ( `Manifest "review.labeling_rules[${ index } ]" needs at least one of when_paths / title_contains / description_contains; ignoring it.` ) ;
2540- continue ;
2541- }
2542- out . push ( { label, whenPaths, titleContains, descriptionContains } ) ;
2543- }
2544- return out ;
2545- }
25462485
25472486function autoReviewPresent ( config : AutoReviewConfig ) : boolean {
25482487 return (
@@ -3020,15 +2959,6 @@ export function reviewConfigToJson(review: FocusManifestReviewConfig): JsonValue
30202959 }
30212960 if ( Object . keys ( review . fields ) . length > 0 ) out . fields = { ...review . fields } as Record < string , JsonValue > ;
30222961 if ( Object . keys ( review . enrichmentAnalyzers ) . length > 0 ) out . enrichment = { ...review . enrichmentAnalyzers } as Record < string , JsonValue > ;
3023- if ( review . labelingRules . length > 0 ) {
3024- out . labeling_rules = review . labelingRules . map ( ( rule ) => {
3025- const entry : Record < string , JsonValue > = { label : rule . label } ;
3026- if ( rule . whenPaths . length > 0 ) entry . when_paths = [ ...rule . whenPaths ] ;
3027- if ( rule . titleContains !== null ) entry . title_contains = rule . titleContains ;
3028- if ( rule . descriptionContains !== null ) entry . description_contains = rule . descriptionContains ;
3029- return entry ;
3030- } ) ;
3031- }
30322962 if ( selfHostAiModelPresent ( review . aiModel ) ) {
30332963 const aiModel : Record < string , JsonValue > = { } ;
30342964 if ( review . aiModel . claudeModel !== null ) aiModel . claude_model = review . aiModel . claudeModel ;
0 commit comments