@windyroad/risk-scorer 0.13.0 → 0.13.1-preview.709

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.
@@ -310,5 +310,5 @@
310
310
  }
311
311
  },
312
312
  "name": "wr-risk-scorer",
313
- "version": "0.13.0"
313
+ "version": "0.13.1"
314
314
  }
@@ -54,8 +54,21 @@ surface = os.environ.get('EXTCOMMS_SURFACE', '')
54
54
  # changeset-author: strip the leading YAML frontmatter block + blank line.
55
55
  if surface == 'changeset-author':
56
56
  draft = re.sub(r'^---\n.*?\n---\n\n?', '', draft, count=1, flags=re.DOTALL)
57
- # Single canonical newline normalization: strip all trailing whitespace.
58
- draft = draft.rstrip()
57
+ # Substance-aware whitespace normalization (P276 / ADR-009 + ADR-028 amended
58
+ # 2026-06-06). Tolerate trivial PASS-class reformatting so a marker survives
59
+ # interior CRLF/CR line endings and per-line trailing whitespace — the same
60
+ # normalization _substance_normalize_then_hash (gate-helpers.sh) applies to
61
+ # the policy-file-drift gates. Conservative boundary preserved: single-numeral
62
+ # edits and frontmatter-key changes stay substantive (key changes → review
63
+ # re-fires), so the leak-detection guarantee is never weakened.
64
+ # 1. CRLF / CR -> LF
65
+ # 2. strip trailing whitespace per line
66
+ # 3. strip trailing whitespace of the whole draft (subsumes the prior
67
+ # single-canonical rstrip; NO trailing '\n' is appended here so the key
68
+ # shape sha256(normalize(draft) + '\n' + surface) is byte-stable for
69
+ # already-clean drafts — existing markers and keys do not shift).
70
+ draft = draft.replace('\r\n', '\n').replace('\r', '\n')
71
+ draft = '\n'.join(line.rstrip() for line in draft.split('\n')).rstrip()
59
72
  print(hashlib.sha256((draft + '\n' + surface).encode('utf-8')).hexdigest())
60
73
  " 2>/dev/null
61
74
  }
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env bats
2
+ # Behavioural tests for compute_external_comms_key substance-aware draft
3
+ # normalization (P276 — external-comms gate marker over-fires on PASS-class
4
+ # content edits).
5
+ #
6
+ # Contract (ADR-009 + ADR-028 amended 2026-06-06, ratified): the marker key
7
+ # must survive TRIVIAL whitespace-class edits to the draft body — interior
8
+ # CRLF/CR line endings and per-line trailing whitespace — so a PASS review
9
+ # does not have to re-fire on a no-op reformat. The conservative boundary is
10
+ # preserved: single-numeral edits and frontmatter-key changes remain
11
+ # SUBSTANTIVE (the key changes → review re-fires) so the leak-detection
12
+ # guarantee is never weakened.
13
+ #
14
+ # These exercise compute_external_comms_key directly (its stdout = the 64-char
15
+ # sha256 key) — behavioural assertions on the function's output, not a
16
+ # structural grep of the source.
17
+
18
+ setup() {
19
+ HOOKS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
20
+ # shellcheck source=../lib/external-comms-key.sh
21
+ source "$HOOKS_DIR/lib/external-comms-key.sh"
22
+ }
23
+
24
+ # ---------- Trivial edits must NOT change the key (P276) ----------
25
+
26
+ @test "P276: interior CRLF line endings produce the same key as LF" {
27
+ lf=$(compute_external_comms_key $'Line one\nLine two\nLine three' 'gh-issue-comment')
28
+ crlf=$(compute_external_comms_key $'Line one\r\nLine two\r\nLine three' 'gh-issue-comment')
29
+ [ -n "$lf" ]
30
+ [ "$lf" = "$crlf" ]
31
+ }
32
+
33
+ @test "P276: per-line trailing whitespace produces the same key as clean lines" {
34
+ clean=$(compute_external_comms_key $'Line one\nLine two' 'gh-issue-comment')
35
+ trailing=$(compute_external_comms_key $'Line one \nLine two\t' 'gh-issue-comment')
36
+ [ -n "$clean" ]
37
+ [ "$clean" = "$trailing" ]
38
+ }
39
+
40
+ @test "P276: trailing whitespace at end of draft produces the same key (regression guard for prior rstrip)" {
41
+ clean=$(compute_external_comms_key 'A short draft body' 'gh-issue-comment')
42
+ trailed=$(compute_external_comms_key $'A short draft body\n\n ' 'gh-issue-comment')
43
+ [ "$clean" = "$trailed" ]
44
+ }
45
+
46
+ # ---------- Conservative boundary: substantive edits MUST change the key ----------
47
+
48
+ @test "P276 boundary: a single-numeral edit changes the key (review re-fires)" {
49
+ before=$(compute_external_comms_key 'We support 12 plugins today' 'gh-issue-comment')
50
+ after=$(compute_external_comms_key 'We support 11 plugins today' 'gh-issue-comment')
51
+ [ "$before" != "$after" ]
52
+ }
53
+
54
+ @test "P276 boundary: a word/content edit changes the key (review re-fires)" {
55
+ before=$(compute_external_comms_key 'The release is ready' 'gh-issue-comment')
56
+ after=$(compute_external_comms_key 'The release is delayed' 'gh-issue-comment')
57
+ [ "$before" != "$after" ]
58
+ }
59
+
60
+ # ---------- Surface binding + changeset frontmatter strip preserved ----------
61
+
62
+ @test "P276: the surface remains part of the key (same body, different surface → different key)" {
63
+ a=$(compute_external_comms_key 'Same body text' 'gh-issue-comment')
64
+ b=$(compute_external_comms_key 'Same body text' 'gh-pr-comment')
65
+ [ "$a" != "$b" ]
66
+ }
67
+
68
+ @test "P276: changeset frontmatter strip still holds — full content keys equal the body-only key" {
69
+ body=$'Add the substance-aware normalization to the external-comms key.'
70
+ full=$'---\n"@windyroad/risk-scorer": patch\n---\n\n'"$body"
71
+ body_key=$(compute_external_comms_key "$body" 'changeset-author')
72
+ full_key=$(compute_external_comms_key "$full" 'changeset-author')
73
+ [ "$body_key" = "$full_key" ]
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/risk-scorer",
3
- "version": "0.13.0",
3
+ "version": "0.13.1-preview.709",
4
4
  "description": "Pipeline risk scoring, commit/push gates, and secret leak detection",
5
5
  "bin": {
6
6
  "windyroad-risk-scorer": "./bin/install.mjs"