valent-pipeline 0.19.30 → 0.19.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valent-pipeline",
3
- "version": "0.19.30",
3
+ "version": "0.19.31",
4
4
  "description": "v3 multi-agent AI pipeline for software development lifecycle",
5
5
  "type": "module",
6
6
  "bin": {
@@ -96,7 +96,26 @@ export function crosscheckVerdict({ reported = null, bugsBlock = null, assertVer
96
96
  // but do not block; they are counted separately so they stay visible).
97
97
  if (bugsBlock && Array.isArray(bugsBlock.bugs)) {
98
98
  const isPre = (b) => b.preExisting === true || b.category === 'pre-existing';
99
- const open = bugsBlock.bugs.filter((b) => OPEN_STATUSES.has(b.status) && ['P1', 'P2', 'P3'].includes(b.priority));
99
+ // JUDGE severity-demotion auto-flow (HARNESS-GAPS 2026-06-18 Gap 1b; Matt 2026-06-18). JUDGE is the
100
+ // adjudication authority and may re-grade a bug (e.g. a test-only isolation bug P3->P4). When JUDGE
101
+ // EXPLICITLY carries a bug in its verdict at a LESS-blocking priority than bugs.md filed, the recount
102
+ // honors the adjudicated priority — the demotion is an explicit, audited decision (recorded in the
103
+ // verdict, the verdict-crosscheck.json, and the backlog carry). Safety is unchanged: only a CARRIED
104
+ // bug is re-graded, and only DOWNWARD; a bug JUDGE does not carry keeps its filed priority, so a
105
+ // SILENTLY-dropped open P1-P3 (the integrity breach this guards) still mismatches. A promotion is the
106
+ // safe over-report direction and is left as filed (the recount already tolerates JUDGE over-reporting).
107
+ const PRI_RANK = { P1: 1, P2: 2, P3: 3, P4: 4 };
108
+ const adjudicated = new Map(
109
+ (reported && Array.isArray(reported.bugs) ? reported.bugs : [])
110
+ .filter((b) => b && b.id && b.priority).map((b) => [b.id, b.priority]),
111
+ );
112
+ const effPriority = (b) => {
113
+ const adj = adjudicated.get(b.id);
114
+ return adj && (PRI_RANK[adj] ?? 99) > (PRI_RANK[b.priority] ?? 99) ? adj : b.priority;
115
+ };
116
+ const demotions = bugsBlock.bugs.filter((b) => effPriority(b) !== b.priority).map((b) => ({ id: b.id, from: b.priority, to: effPriority(b) }));
117
+ if (demotions.length) recounted.adjudicatedDemotions = demotions;
118
+ const open = bugsBlock.bugs.filter((b) => OPEN_STATUSES.has(b.status) && ['P1', 'P2', 'P3'].includes(effPriority(b)));
100
119
  recounted.preExistingOpen = open.filter(isPre).length;
101
120
  compare('openP1toP3', open.filter((b) => !isPre(b)).length);
102
121