From b4bd96e50ef3ed5dfe741302d59fc1452fbdc591 Mon Sep 17 00:00:00 2001 From: Conal <33135619+Conalh@users.noreply.github.com> Date: Fri, 29 May 2026 08:32:23 -0700 Subject: [PATCH] fix(diff): surface same-severity in-place finding changes as [CHANGED] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diffReports keyed findings on (kind, subject, file) and only included a finding in the PR delta when its severity rank increased. A finding mutated in place at the same kind/subject/file and the same severity (e.g. a medium rewritten into a different medium) matched the natural key and was silently dropped as pre-existing — undercutting the "gate only on findings introduced or worsened by this PR" promise. Compare content identity (signature, falling back to message for reports that predate signatures) when the natural key matches and severity did not increase, and surface a genuine change as [CHANGED]. Severity decreases remain out of the delta as improvements. Co-Authored-By: Claude Opus 4.8 --- dist/diff.js | Bin 2767 -> 4128 bytes src/diff.ts | Bin 2842 -> 4109 bytes test/heuristics.test.mjs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/dist/diff.js b/dist/diff.js index 1502b99ba3808c047554ca9bdc320360f657caf6..e885738856a0e6fd292bed65a6339953e7f9618f 100644 GIT binary patch delta 1251 zcmY+Ezityj5XKb}r$`wohz1zkU|aqp(I645C?pn8B%lNdAp~N5JLg++w`+FyVk{Jy zM<6Zq%1mVF)2u>vQg{NqhpLSuFK<7WMpZ{(( z7@6;eN=v0j5Gu<*sSYBcM<|&^i0t;tja53F4Oafn_R6jD9S1HFmWqKEKD8o-6P$w3 za$XW9%14Y*HW$lP1Cwfxb}X!iVd_DuFhtAc0z(_xL&K?2PNe2S5yz}+D1wt2_e?OR zB5N~Wz3XdeLBDf~CO{b+w6Y8<(HAy|4lFU(>m;zdb3aZZN{P5xk zPw2&-o2A3I82DbOVk&IXI42lVWGBiY3~AQ1rF}dFZ;?xYa4f2W@0Ih^$2Pdsh9cmW zl&4+RP=8ta_o_}4#Iei0tB(i(Mib2FT>1-o%dui>WEv2hoSzu$P#3)nscfViJUyyY zQIoKy$Y^vPLORNJcd9VZ#3mF98kIMud(pUZZ7plpVAkuwF^6Ws(e|aCQc2LplZJr$ zbI7x8Nh}^{n2y}vfbv5qm5`28OxV>t7hX&q7;@c&d6N=jFS_u6R)i+(tW)H-jKU(T z$Yqu6t=hk&T7Bk&)(JU%m_-(@TGoS zVf$4?yYm3U&dz+X4E^@JG*7y~@L$0Kh93`v529tz<#K}e^9!`hQXw>!1l{WQ^NU-d uoA4nop8Z?9nSHNqWCaACF85j4lIH!n1gh6oq9-QiOueK!J2)C}QK-)I?U49}6OsfRcg&A!WRK*E?i)#+sRpWkr#B z0jfVi(WLI=5HIFL;Nn^M^c4SjVY4G ze`P9&g&K3{X$we+#mGpzm<&&}ah9a@#Gj47^ZjZ~1+!#hVW5MQaG4Pao%4)@3Kwc< zDggpt8X5`9UQVDh<=9MwaWu*tg))lRcpZVp3*~6j%5g#DE=3|qyx@@t&gbN`hj~iM z)`~IHG-d?>rB<344uxX~s|mIZM=(2-S&GA#CZw6etk83$0#i_@RDs<+x|n?1-E%DL z+fFw6%z^7iGQq|=O9}$4Vl$PNX@nT?O1WePyB^QC$z~=Jf!8k`3GXAdK2|w?YQZj^ z*uwtS7=lQvWQIqr6V@wdbeILm2?dyHV_B8DM>DLGmfoMVaB7|U{bQ}zI*KsWcjD1j zT?*JUMLFP$)4F$aeXqHa|5|O%`+Yj~<+&AKcbQ!%LsHs7L|_=3<~65mW!>!4-J{`BkKYg{ z85=||;gYZIrcVZ%%VfGW#wXM++87As&tTcRixePgs_4&`YwUcSqJ&&<>gvf5C%`rG zhp1s?h+IZUi}=dwA=k1xwwM22ZQmaZ2Km3$?i@fw5wi#nYviELwYO*|?d&WDt441Z z+mbg10Doz20sP-1;ez-sVmVwxdKE=Rw0TFw#$a#<+NMiP%{SJb<$G(*0o51l6`d_l a`uwuGIlYR1byo3-uG+QYtDEm@*~))0Fq(P* delta 124 zcmeBGm?gG>k&!RIh)Y3BA>2PG*wxR~Wik(=q_UoZqe5C{UP@+OxNik5v { + // A medium finding mutated into a *different* medium at the same + // place. The (kind, subject, file) key matches, so without a content + // check this would be dropped as pre-existing. + const base = makeReport([makeFinding({ message: 'github launches npx server-github.' })]); + const head = makeReport([makeFinding({ message: 'github launches npx server-evil.' })]); + + const delta = diffReports(base, head); + assert.equal(delta.findingCount, 1); + assert.equal(delta.findings[0].severity, 'medium'); + assert.match(delta.findings[0].message, /^\[CHANGED\]/); + assert.match(delta.findings[0].message, /server-evil/); +}); + +test('diffReports: same severity with a changed signature is surfaced as [CHANGED]', () => { + // When reports carry signatures (the audit path always signs), the + // content identity comes from the signature rather than the message. + const base = makeReport([makeFinding({ signature: 'aaaaaaaaaaaaaaaa' })]); + const head = makeReport([makeFinding({ signature: 'bbbbbbbbbbbbbbbb' })]); + + const delta = diffReports(base, head); + assert.equal(delta.findingCount, 1); + assert.match(delta.findings[0].message, /^\[CHANGED\]/); +}); + +test('diffReports: same severity and identical signature stays out of the delta', () => { + // Identical signatures mean the violation is unchanged even if some + // unrelated report field differs — it is pre-existing, not a regression. + const base = makeReport([makeFinding({ signature: 'cafef00dcafef00d', message: 'phrasing A' })]); + const head = makeReport([makeFinding({ signature: 'cafef00dcafef00d', message: 'phrasing B' })]); + + const delta = diffReports(base, head); + assert.equal(delta.findingCount, 0); +}); + test('makeMeshContext: indexes servers by name across surfaces in a single pass', () => { const policies = { mcpSurfaces: [