@@ -499,7 +499,9 @@ export type FocusManifestPrReconciliationConfig = {
499499 * (LOOPOVER_ACTIVE_REVIEW_RECONCILIATION), declared under top-level `activeReviewReconciliation:`
500500 * (#webhook-reorder-clobber). Same shape and precedence as `prReconciliation:` above -- the sweep re-checks
501501 * `active_review_tracking` rows a delayed webhook job left stuck "active" for a PR that already closed.
502- * Not present ⇒ the caller falls back to the LOOPOVER_ACTIVE_REVIEW_RECONCILIATION env var.
502+ * Not present ⇒ the caller falls back to the LOOPOVER_ACTIVE_REVIEW_RECONCILIATION env var. Distinct from
503+ * the per-repo FORCE-OFF under `review.activeReviewReconciliation` (which only excludes one repo's rows
504+ * from the scan set once this fleet-wide gate is ON).
503505 */
504506export type FocusManifestActiveReviewReconciliationConfig = {
505507 present : boolean ;
@@ -793,6 +795,14 @@ export type FocusManifestReviewConfig = {
793795 * above, for the identical reason. A manifest-load error fails OPEN (the repo stays watched). null/true
794796 * (default, absent) ⇒ no change to today's watched-repo-set behavior. */
795797 prReconciliation : boolean | null ;
798+ /** `review.activeReviewReconciliation` (#webhook-reorder-clobber): explicit per-repo FORCE-OFF for the
799+ * active-review-tracking reconciliation sweep (`runActiveReviewReconciliation`,
800+ * `src/review/active-review-reconciliation.ts`) — `false` excludes this repo's stale `active_review_tracking`
801+ * rows from the sweep's scan even though the global `LOOPOVER_ACTIVE_REVIEW_RECONCILIATION` kill-switch is
802+ * on. Deliberately FORCE-OFF-ONLY (no `true` override), mirroring `selftune`/`sweepWatchdog`/`prReconciliation`
803+ * above, for the identical reason. A manifest-load error fails OPEN (the repo's rows stay eligible). null/true
804+ * (default, absent) ⇒ no change to today's scanned-row-set behavior. */
805+ activeReviewReconciliation : boolean | null ;
796806 /** `review.memory` (#2179, config slice of #1964): when true, gates repeat-false-positive SUPPRESSION —
797807 * before an advisory (non-blocking) AI finding is surfaced in the unified review comment, it is matched
798808 * against this repo's stored `review_suppression` signals (a maintainer's own past false-positive
@@ -1412,7 +1422,7 @@ const EMPTY_MANIFEST: FocusManifest = {
14121422 publicNotes : [ ] ,
14131423 gate : { ...EMPTY_GATE_CONFIG } ,
14141424 settings : { } ,
1415- 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 , sweepWatchdog : null , prReconciliation : 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 } ,
1425+ 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 , sweepWatchdog : null , prReconciliation : null , activeReviewReconciliation : 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 } ,
14161426 features : { ...EMPTY_FEATURES_CONFIG } ,
14171427 experimental : { ...EMPTY_EXPERIMENTAL_CONFIG } ,
14181428 contentLane : { ...EMPTY_CONTENT_LANE_CONFIG } ,
@@ -1453,7 +1463,7 @@ function emptyManifest(source: FocusManifestSource, warnings: string[] = []): Fo
14531463 warnings,
14541464 gate : { ...EMPTY_GATE_CONFIG } ,
14551465 settings : { } ,
1456- 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 , sweepWatchdog : null , prReconciliation : 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 } ,
1466+ 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 , sweepWatchdog : null , prReconciliation : null , activeReviewReconciliation : 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 } ,
14571467 features : { ...EMPTY_FEATURES_CONFIG } ,
14581468 experimental : { ...EMPTY_EXPERIMENTAL_CONFIG } ,
14591469 contentLane : { ...EMPTY_CONTENT_LANE_CONFIG } ,
@@ -2937,7 +2947,7 @@ function parsePublicSafeText(value: JsonValue | undefined, field: string, warnin
29372947 * throws; invalid/unsafe values are dropped with warnings.
29382948 */
29392949function parseReviewConfig ( value : JsonValue | undefined , warnings : string [ ] ) : FocusManifestReviewConfig {
2940- 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 , sweepWatchdog : null , prReconciliation : 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 } ;
2950+ 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 , sweepWatchdog : null , prReconciliation : null , activeReviewReconciliation : 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 } ;
29412951 if ( value === undefined || value === null ) return empty ;
29422952 if ( typeof value !== "object" || Array . isArray ( value ) ) {
29432953 warnings . push ( `Manifest field "review" must be a mapping; ignoring it.` ) ;
@@ -2984,6 +2994,7 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
29842994 const selftune = normalizeOptionalBoolean ( r . selftune , "review.selftune" , warnings ) ;
29852995 const sweepWatchdog = normalizeOptionalBoolean ( r . sweepWatchdog , "review.sweepWatchdog" , warnings ) ;
29862996 const prReconciliation = normalizeOptionalBoolean ( r . prReconciliation , "review.prReconciliation" , warnings ) ;
2997+ const activeReviewReconciliation = normalizeOptionalBoolean ( r . activeReviewReconciliation , "review.activeReviewReconciliation" , warnings ) ;
29872998 const reviewMemory = normalizeOptionalBoolean ( r . memory , "review.memory" , warnings ) ;
29882999 const findingCategories = normalizeOptionalBoolean ( r . finding_categories , "review.finding_categories" , warnings ) ;
29893000 const inlineCommentsPerCategory = normalizeOptionalNonNegativeInt (
@@ -3028,6 +3039,7 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
30283039 selftune !== null ||
30293040 sweepWatchdog !== null ||
30303041 prReconciliation !== null ||
3042+ activeReviewReconciliation !== null ||
30313043 reviewMemory !== null ||
30323044 findingCategories !== null ||
30333045 inlineCommentsPerCategory !== null ||
@@ -3069,6 +3081,7 @@ function parseReviewConfig(value: JsonValue | undefined, warnings: string[]): Fo
30693081 selftune,
30703082 sweepWatchdog,
30713083 prReconciliation,
3084+ activeReviewReconciliation,
30723085 reviewMemory,
30733086 findingCategories,
30743087 inlineCommentsPerCategory,
@@ -3174,6 +3187,7 @@ function computeReviewConfigPresent(review: Omit<FocusManifestReviewConfig, "pre
31743187 review . selftune !== null ||
31753188 review . sweepWatchdog !== null ||
31763189 review . prReconciliation !== null ||
3190+ review . activeReviewReconciliation !== null ||
31773191 review . reviewMemory !== null ||
31783192 review . findingCategories !== null ||
31793193 review . inlineCommentsPerCategory !== null ||
@@ -3221,6 +3235,7 @@ export function overlayReviewConfig(
32213235 selftune : pickOverlayNullable ( override . selftune , base . selftune ) ,
32223236 sweepWatchdog : pickOverlayNullable ( override . sweepWatchdog , base . sweepWatchdog ) ,
32233237 prReconciliation : pickOverlayNullable ( override . prReconciliation , base . prReconciliation ) ,
3238+ activeReviewReconciliation : pickOverlayNullable ( override . activeReviewReconciliation , base . activeReviewReconciliation ) ,
32243239 reviewMemory : pickOverlayNullable ( override . reviewMemory , base . reviewMemory ) ,
32253240 findingCategories : pickOverlayNullable ( override . findingCategories , base . findingCategories ) ,
32263241 inlineCommentsPerCategory : pickOverlayNullable ( override . inlineCommentsPerCategory , base . inlineCommentsPerCategory ) ,
@@ -3796,6 +3811,7 @@ export function reviewConfigToJson(review: FocusManifestReviewConfig): JsonValue
37963811 if ( review . selftune !== null ) out . selftune = review . selftune ;
37973812 if ( review . sweepWatchdog !== null ) out . sweepWatchdog = review . sweepWatchdog ;
37983813 if ( review . prReconciliation !== null ) out . prReconciliation = review . prReconciliation ;
3814+ if ( review . activeReviewReconciliation !== null ) out . activeReviewReconciliation = review . activeReviewReconciliation ;
37993815 if ( review . reviewMemory !== null ) out . memory = review . reviewMemory ;
38003816 if ( review . findingCategories !== null ) out . finding_categories = review . findingCategories ;
38013817 if ( review . inlineCommentsPerCategory !== null ) out . inline_comments_per_category = review . inlineCommentsPerCategory ;
0 commit comments