From 08b4a25dee92566c204ceede6526ef5b1ca10414 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 01:01:07 -0700 Subject: [PATCH 1/2] test(slop): update golden fixtures for the #3939 band recalibration #3939 raised the elevated-band floor from 25 to 31, so two stacked weak signals (30) now land in low, not elevated. Five fixtures still asserted the pre-recalibration boundary; adjust the genuine multi- signal cases to a real 3-signal stack (45) and the single-signal cases to their now-correct low band, per the recalibration's own stated design (elevated requires >=45 or 3x weak). --- test/unit/slop.test.ts | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/test/unit/slop.test.ts b/test/unit/slop.test.ts index d43dc895d6..4c77f50556 100644 --- a/test/unit/slop.test.ts +++ b/test/unit/slop.test.ts @@ -113,16 +113,18 @@ describe("buildSlopAssessment", () => { expect(buildDuplicateClusterFinding({ inDuplicateCluster: false })).toBeNull(); }); - it("stacks the duplicate-cluster weight with another signal into the expected band (#563)", () => { + it("stacks the duplicate-cluster weight with two other signals into the expected band (#563, #3939 recalibration)", () => { const result = buildSlopAssessment({ - // code file with no test evidence → missing_test_evidence (30); non-empty description suppresses empty_description. + // code file with no test evidence → missing_test_evidence (15); non-empty description suppresses empty_description. changedFiles: [{ path: "src/parser.ts", additions: 10, deletions: 1 }], description: "Refactor the parser.", inDuplicateCluster: true, // → duplicate_cluster_membership (15) + hasLinkedIssue: false, // → no_linked_issue_without_rationale (15) -- a third weak signal, needed post-#3939: + // two weak signals alone (30) now land in `low` (1-30), not `elevated` (31-59); three reaches 45. }); - expect(result.slopRisk).toBe(SLOP_WEIGHTS.missingTestEvidence + SLOP_WEIGHTS.duplicateClusterMembership); + expect(result.slopRisk).toBe(SLOP_WEIGHTS.missingTestEvidence + SLOP_WEIGHTS.duplicateClusterMembership + SLOP_WEIGHTS.noLinkedIssueWithoutRationale); expect(result.band).toBe("elevated"); - expect(result.findings.map((finding) => finding.code).sort()).toEqual(["duplicate_cluster_membership", "missing_test_evidence"]); + expect(result.findings.map((finding) => finding.code).sort()).toEqual(["duplicate_cluster_membership", "missing_test_evidence", "no_linked_issue_without_rationale"]); expect(JSON.stringify(result)).not.toMatch(FORBIDDEN_PUBLIC_TERMS); }); @@ -196,7 +198,8 @@ describe("buildSlopAssessment", () => { }); expect(result.slopRisk).toBe(SLOP_WEIGHTS.trivialWhitespaceChurn); - expect(result.band).toBe("elevated"); + // A single strong signal (30) alone is `low` (1-30), not `elevated` (31-59) — post-#3939 recalibration. + expect(result.band).toBe("low"); expect(result.findings).toEqual([ expect.objectContaining({ code: "trivial_whitespace_churn", @@ -307,9 +310,10 @@ describe("buildSlopAssessment", () => { }); it("reaches the high band when multiple strong signals stack", () => { - // Code change, no tests, no description: missing-test-evidence (15) + empty-description (15) = 30 = elevated. - const elevated = buildSlopAssessment({ changedFiles: [{ path: "src/x.ts", additions: 10, deletions: 1 }], description: "" }); - expect(elevated.band).toBe("elevated"); + // Code change, no tests, no description: missing-test-evidence (15) + empty-description (15) = 30 = low + // (post-#3939 recalibration: two weak signals alone no longer reach `elevated`, which now needs ≥31). + const twoWeakSignals = buildSlopAssessment({ changedFiles: [{ path: "src/x.ts", additions: 10, deletions: 1 }], description: "" }); + expect(twoWeakSignals.band).toBe("low"); // High-whitespace-churn code change + no tests + no description: 30 + 15 + 15 = 60 -> high (>=60). const high = buildSlopAssessment({ @@ -625,7 +629,8 @@ describe("buildNonSubstantivePaddingFinding (#561 path-matcher signal)", () => { }); expect(result.findings.map((finding) => finding.code)).toEqual(["non_substantive_padding"]); expect(result.slopRisk).toBe(SLOP_WEIGHTS.nonSubstantivePadding); - expect(result.band).toBe("elevated"); + // A single strong signal (30) alone is `low` (1-30), not `elevated` (31-59) — post-#3939 recalibration. + expect(result.band).toBe("low"); expect(JSON.stringify(result)).not.toMatch(FORBIDDEN); }); }); @@ -643,11 +648,18 @@ describe("slop golden fixtures & determinism (#565)", () => { codes: ["missing_test_evidence"], }, { - name: "elevated — untested code change inside a duplicate cluster", - input: { changedFiles: [{ path: "src/svc.ts", additions: 12, deletions: 3 }], description: "Add retry logic to the sync client.", inDuplicateCluster: true }, - slopRisk: 30, + // Three weak signals (45), not two (30): post-#3939 recalibration, two weak signals alone land in `low` + // (1-30) -- `elevated` (31-59) now needs genuine multi-signal evidence. + name: "elevated — untested, unlinked code change inside a duplicate cluster", + input: { + changedFiles: [{ path: "src/svc.ts", additions: 12, deletions: 3 }], + description: "Add retry logic to the sync client.", + inDuplicateCluster: true, + hasLinkedIssue: false, + }, + slopRisk: 45, band: "elevated", - codes: ["duplicate_cluster_membership", "missing_test_evidence"], + codes: ["duplicate_cluster_membership", "missing_test_evidence", "no_linked_issue_without_rationale"], }, { name: "high — whitespace churn, untested code, and empty description", From 8a0ce04de270c7a7dc5c75272bb76f8af6c6ae75 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 7 Jul 2026 01:22:37 -0700 Subject: [PATCH 2/2] docs(slop): fix remaining #3939 threshold drift in issue rubric + comments The #3939 recalibration updated slopBandFor and SLOP_RUBRIC_MARKDOWN but left ISSUE_SLOP_RUBRIC_MARKDOWN (which renders through the same banding function) and two comments still documenting the old 1-24/25-59 split. --- src/signals/slop.ts | 18 ++++++++++-------- test/unit/slop.test.ts | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/signals/slop.ts b/src/signals/slop.ts index fb526a42f0..5ca5110745 100644 --- a/src/signals/slop.ts +++ b/src/signals/slop.ts @@ -360,8 +360,8 @@ export const ISSUE_SLOP_RUBRIC_MARKDOWN = [ "# Gittensory issue slop triage rubric", "", "- `clean`: 0", - "- `low`: 1-24", - "- `elevated`: 25-59", + "- `low`: 1-30", + "- `elevated`: 31-59", "- `high`: 60-100", "", "Advisory-only (issues never block). Current deterministic signals:", @@ -500,14 +500,16 @@ function ensurePublicSafeText(text: string, fallback: string): string { return isFocusManifestPublicSafe(text) ? text : fallback; } -// Documented thresholds (#565): the deterministic slopRisk (0-100) maps to fixed bands — clean = 0, -// low = 1-24, elevated = 25-59, high = 60-100. Strong signals (trivial churn, non-substantive padding) -// weigh 30 (any two reach `high`); weak/corroborating/traceability signals — including missing-test-evidence -// — weigh 15. Identical metadata always yields an identical band (see golden fixtures). +// Documented thresholds (#565, recalibrated by #3939): the deterministic slopRisk (0-100) maps to fixed +// bands — clean = 0, low = 1-30, elevated = 31-59, high = 60-100. Strong signals (trivial churn, +// non-substantive padding) weigh 30 (any two reach `high`); weak/corroborating/traceability signals — +// including missing-test-evidence — weigh 15, so a single strong or a pair of weak signals alone now lands +// in `low`, not `elevated` — `elevated` needs genuine multi-signal evidence (strong+weak ≥ 45, or 3×weak = +// 45). Identical metadata always yields an identical band (see golden fixtures). function slopBandFor(slopRisk: number): SlopBand { if (slopRisk <= 0) return "clean"; - if (slopRisk < 31) return "low"; // raised from 25: a single strong signal (30pts) is low, not elevated - if (slopRisk < 60) return "elevated"; // elevated now requires multi-signal evidence (strong+weak ≥ 45, or 3×weak = 45) + if (slopRisk < 31) return "low"; + if (slopRisk < 60) return "elevated"; return "high"; } diff --git a/test/unit/slop.test.ts b/test/unit/slop.test.ts index 4c77f50556..1a8b90a4d0 100644 --- a/test/unit/slop.test.ts +++ b/test/unit/slop.test.ts @@ -134,7 +134,7 @@ describe("buildSlopAssessment", () => { description: "Add retry-with-backoff to the registry sync client.", }); - // De-weighted to 15: missing-test alone is corroborating, not decisive, and lands in `low` (1-24). + // De-weighted to 15: missing-test alone is corroborating, not decisive, and lands in `low` (1-30). expect(result.slopRisk).toBe(SLOP_WEIGHTS.missingTestEvidence); expect(result.band).toBe("low"); expect(result.findings).toEqual([