@windyroad/risk-scorer 0.17.4 → 0.18.0

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.
Files changed (55) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +13 -2
  5. package/bin/install.mjs +42 -8
  6. package/hooks/codex-agent-completion.mjs +82 -0
  7. package/hooks/hooks.json +5 -2
  8. package/hooks/risk-scorer-dispatch.sh +3 -0
  9. package/hooks/risk-scorer-scaffold-nudge.sh +15 -4
  10. package/package.json +5 -2
  11. package/scripts/codex-agents.mjs +208 -0
  12. package/scripts/sync-codex-skills.mjs +8 -3
  13. package/skills/assess-external-comms/SKILL.md +5 -4
  14. package/skills/assess-inbound-report/SKILL.md +5 -4
  15. package/skills/assess-release/SKILL.md +5 -4
  16. package/skills/assess-wip/SKILL.md +5 -4
  17. package/skills/bootstrap-catalog/SKILL.md +5 -4
  18. package/skills/create-risk/SKILL.md +5 -4
  19. package/skills/external-comms/SKILL.md +5 -4
  20. package/skills/pipeline/SKILL.md +5 -4
  21. package/skills/update-policy/SKILL.md +6 -5
  22. package/skills/wip/SKILL.md +5 -4
  23. package/agents/test/inbound-report-contract.bats +0 -225
  24. package/agents/test/risk-scorer-above-appetite-stop.bats +0 -80
  25. package/agents/test/risk-scorer-catalog-consumption.bats +0 -138
  26. package/agents/test/risk-scorer-commit-verdict.bats +0 -66
  27. package/agents/test/risk-scorer-monitoring-not-a-control.bats +0 -76
  28. package/agents/test/risk-scorer-reducing-bypass-criteria.bats +0 -62
  29. package/agents/test/risk-scorer-register-hint.bats +0 -111
  30. package/agents/test/risk-scorer-structured-remediations.bats +0 -123
  31. package/agents/test/risk-scorer-user-stated-preconditions.bats +0 -89
  32. package/hooks/test/ci-status-gate.bats +0 -234
  33. package/hooks/test/external-comms-gate.bats +0 -528
  34. package/hooks/test/external-comms-key-substance.bats +0 -74
  35. package/hooks/test/git-push-gate.bats +0 -82
  36. package/hooks/test/pipeline-state-changeset-partition.bats +0 -181
  37. package/hooks/test/pipeline-state-hash.bats +0 -195
  38. package/hooks/test/plan-risk-guidance-once-per-session.bats +0 -95
  39. package/hooks/test/reducing-marker-persistence.bats +0 -236
  40. package/hooks/test/risk-gate.bats +0 -330
  41. package/hooks/test/risk-policy-project-root.bats +0 -20
  42. package/hooks/test/risk-score-commit-gate-adr-031-bypass.bats +0 -98
  43. package/hooks/test/risk-score-commit-gate-cadence-staleness.bats +0 -105
  44. package/hooks/test/risk-score-mark-external-comms-prompt-parse.bats +0 -94
  45. package/hooks/test/risk-score-mark-register-queue.bats +0 -253
  46. package/hooks/test/risk-score-mark.bats +0 -112
  47. package/hooks/test/risk-scorer-hook-dispatch.bats +0 -77
  48. package/hooks/test/risk-scorer-no-stop-hook.bats +0 -19
  49. package/hooks/test/risk-scorer-scaffold-nudge.bats +0 -132
  50. package/hooks/test/slide-marker-on-subprocess-return.bats +0 -118
  51. package/hooks/test/wip-risk-mark.bats +0 -64
  52. package/scripts/test/drain-register-queue.bats +0 -359
  53. package/scripts/test/evaluate-graduation.bats +0 -533
  54. package/scripts/test/extract-risks-from-reports.bats +0 -366
  55. package/scripts/test/restage-commit.bats +0 -137
@@ -1,66 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: wip.md and assess-wip SKILL.md must define the
3
- # RISK_VERDICT: COMMIT extension per ADR-016.
4
- #
5
- # Structural assertion — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- # These tests assert that the agent and skill specification documents conform to
7
- # the COMMIT verdict contract introduced by P024 / ADR-016.
8
- #
9
- # Cross-reference:
10
- # P024: docs/problems/024-risk-scorer-wip-flag-uncommitted-completed-work.open.md
11
- # ADR-016: docs/decisions/016-wip-verdict-commit-for-completed-governance-work.proposed.md
12
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
13
- # @jtbd JTBD-002 (ship with confidence)
14
- # @jtbd JTBD-001 (enforce governance without slowing down)
15
-
16
- setup() {
17
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
18
- WIP_FILE="${AGENTS_DIR}/wip.md"
19
- SKILL_DIR="$(cd "${AGENTS_DIR}/../skills/assess-wip" && pwd)"
20
- SKILL_FILE="${SKILL_DIR}/SKILL.md"
21
- }
22
-
23
- # ──────────────────────────────────────────────────────────────────────────────
24
- # wip.md — COMMIT verdict definition
25
- # ──────────────────────────────────────────────────────────────────────────────
26
-
27
- @test "wip.md defines RISK_VERDICT: COMMIT as a third verdict type" {
28
- # ADR-016 §Verdict Contract: COMMIT is distinct from CONTINUE and PAUSE.
29
- # The agent prompt must name this verdict so the LLM knows to emit it.
30
- run grep -n "RISK_VERDICT:.*COMMIT\|RISK_VERDICT: COMMIT" "$WIP_FILE"
31
- [ "$status" -eq 0 ]
32
- }
33
-
34
- @test "wip.md defines RISK_COMMIT_REASON: output field" {
35
- # ADR-016 §Verdict Contract: COMMIT verdict must include a one-line reason
36
- # so the calling skill can surface a meaningful message to the user.
37
- run grep -n "RISK_COMMIT_REASON" "$WIP_FILE"
38
- [ "$status" -eq 0 ]
39
- }
40
-
41
- @test "wip.md defines governance-artefact detection heuristic for COMMIT verdict" {
42
- # ADR-016 §Detection Heuristic: COMMIT fires only when all uncommitted changes
43
- # are in governance artefact paths (docs/problems/, packages/*/skills/).
44
- # This guards against false-positive COMMIT signals on mixed diffs.
45
- run grep -in "governance.artefact\|governance artefact\|docs/problems\|packages/\*/skills" "$WIP_FILE"
46
- [ "$status" -eq 0 ]
47
- }
48
-
49
- @test "wip.md COMMIT verdict is only emitted when risk is within appetite" {
50
- # ADR-016 §Detection Heuristic criterion 1: risk must be ≤ 4 for COMMIT to fire.
51
- # Above-appetite changes must be PAUSE regardless of governance-artefact status.
52
- # Look for the explicit appetite gate in the COMMIT detection section specifically.
53
- run grep -in "PAUSE.*governance\|governance.*PAUSE\|appetite.*COMMIT\|COMMIT.*appetite\|COMMIT.*within\|within.*COMMIT" "$WIP_FILE"
54
- [ "$status" -eq 0 ]
55
- }
56
-
57
- # ──────────────────────────────────────────────────────────────────────────────
58
- # assess-wip SKILL.md — COMMIT verdict handling
59
- # ──────────────────────────────────────────────────────────────────────────────
60
-
61
- @test "assess-wip SKILL.md handles RISK_VERDICT: COMMIT distinctly from CONTINUE/PAUSE" {
62
- # ADR-016 §Consequences: assess-wip Step 4 must surface RISK_VERDICT: COMMIT
63
- # as a prominent suggestion to commit, not treat it the same as CONTINUE.
64
- run grep -n "COMMIT\|commit.*now\|commit now" "$SKILL_FILE"
65
- [ "$status" -eq 0 ]
66
- }
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: risk-scorer agent prompts must explicitly state that
3
- # monitoring, alerting, and other post-release detection activities are
4
- # NOT controls and MUST NOT be credited against residual risk.
5
- #
6
- # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
7
- #
8
- # Background: P038 identified that scorer reports were crediting
9
- # "monitor for elevated errors", "be ready to rollback", and similar
10
- # post-release detection activities as controls that reduced residual
11
- # risk. These activities help detect failures after they occur — they
12
- # are incident response, not release-gate risk reduction. Crediting
13
- # them creates false confidence in risky releases.
14
- #
15
- # A genuine control exercises the failure scenario BEFORE the change
16
- # ships (tests, CI gates, feature flags, preview verification, architect
17
- # review). Monitoring shortens detection time; it does not prevent the
18
- # failure from reaching users.
19
- #
20
- # Cross-reference:
21
- # P038: docs/problems/038-risk-scorer-suggests-monitoring-as-control.open.md
22
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
23
- # @jtbd JTBD-001 (enforce governance — control list must reflect actual prevention)
24
- # @jtbd JTBD-002 (ship with confidence — no false-confidence releases)
25
- # @jtbd JTBD-202 (pre-flight governance — scorer must distinguish prevention from detection)
26
-
27
- setup() {
28
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
29
- PIPELINE="${AGENTS_DIR}/pipeline.md"
30
- WIP="${AGENTS_DIR}/wip.md"
31
- PLAN="${AGENTS_DIR}/plan.md"
32
- }
33
-
34
- # ──────────────────────────────────────────────────────────────────────────────
35
- # pipeline.md
36
- # ──────────────────────────────────────────────────────────────────────────────
37
-
38
- @test "pipeline.md states monitoring is not a control" {
39
- run grep -qE "[Mm]onitoring is (not|NOT) a control|[Mm]onitoring.*MUST NOT.*credit" "$PIPELINE"
40
- [ "$status" -eq 0 ]
41
- }
42
-
43
- @test "pipeline.md forbids crediting post-release detection as risk reduction" {
44
- # Post-release detection activities (monitoring, alerting, rollback readiness)
45
- # must not reduce residual risk.
46
- run grep -qE "post-release.*(not|NOT) (reduce|control|credit)|detection.*(not|NOT) (reduce|prevention)" "$PIPELINE"
47
- [ "$status" -eq 0 ]
48
- }
49
-
50
- # ──────────────────────────────────────────────────────────────────────────────
51
- # wip.md
52
- # ──────────────────────────────────────────────────────────────────────────────
53
-
54
- @test "wip.md states monitoring is not a control" {
55
- run grep -qE "[Mm]onitoring is (not|NOT) a control|[Mm]onitoring.*MUST NOT.*credit" "$WIP"
56
- [ "$status" -eq 0 ]
57
- }
58
-
59
- @test "wip.md forbids crediting post-release detection as risk reduction" {
60
- run grep -qE "post-release.*(not|NOT) (reduce|control|credit)|detection.*(not|NOT) (reduce|prevention)" "$WIP"
61
- [ "$status" -eq 0 ]
62
- }
63
-
64
- # ──────────────────────────────────────────────────────────────────────────────
65
- # plan.md
66
- # ──────────────────────────────────────────────────────────────────────────────
67
-
68
- @test "plan.md states monitoring is not a control" {
69
- run grep -qE "[Mm]onitoring is (not|NOT) a control|[Mm]onitoring.*MUST NOT.*credit" "$PLAN"
70
- [ "$status" -eq 0 ]
71
- }
72
-
73
- @test "plan.md forbids crediting post-release detection as risk reduction" {
74
- run grep -qE "post-release.*(not|NOT) (reduce|control|credit)|detection.*(not|NOT) (reduce|prevention)" "$PLAN"
75
- [ "$status" -eq 0 ]
76
- }
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: risk-scorer agent prompts must scope the
3
- # `RISK_BYPASS: reducing` label to commits that actually reduce risk.
4
- #
5
- # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- #
7
- # Background: P043 analysed 329 risk reports across 6 projects and found
8
- # `RISK_BYPASS: reducing` applied to 97.9% of commits in this repo and
9
- # 79.6% across consumer projects. The scorer treated changeset metadata,
10
- # ADR checkbox ticks, docs-only edits, and genuinely risk-reducing fixes
11
- # all the same way. When nearly every commit is "reducing", the label
12
- # provides no discriminating signal.
13
- #
14
- # The tightened criteria require the commit to:
15
- # 1. Close a problem ticket, OR
16
- # 2. Explicitly remediate a previously-flagged risk, OR
17
- # 3. Remove a documented risk
18
- # Ordinary docs-only or test-only commits that don't meet one of these
19
- # conditions are risk-neutral — no bypass label.
20
- #
21
- # Cross-reference:
22
- # P043: docs/problems/043-risk-bypass-reducing-lost-discriminating-power.open.md
23
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
24
- # @jtbd JTBD-001 (enforce governance — bypass must reflect real risk reduction)
25
- # @jtbd JTBD-202 (pre-flight governance — bypass label must be auditable)
26
-
27
- setup() {
28
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
29
- PIPELINE="${AGENTS_DIR}/pipeline.md"
30
- }
31
-
32
- # NOTE: wip.md is intentionally excluded from these assertions — wip-mode emits
33
- # RISK_VERDICT: CONTINUE/PAUSE, not RISK_BYPASS labels. Bypass criteria apply
34
- # only to the pipeline (commit/push/release) scorer.
35
-
36
- # ──────────────────────────────────────────────────────────────────────────────
37
- # pipeline.md: tightened reducing criteria
38
- # ──────────────────────────────────────────────────────────────────────────────
39
-
40
- @test "pipeline.md reducing bypass requires closing a ticket" {
41
- # Must reference ticket closure as a valid trigger for reducing bypass.
42
- run grep -qE "[Cc]lose[sd]?.*ticket|[Cc]loses P[0-9]|problem.*close" "$PIPELINE"
43
- [ "$status" -eq 0 ]
44
- }
45
-
46
- @test "pipeline.md reducing bypass requires remediating a flagged risk" {
47
- run grep -qE "remediate.*risk|remediates.*risk|flagged risk" "$PIPELINE"
48
- [ "$status" -eq 0 ]
49
- }
50
-
51
- @test "pipeline.md reducing bypass excludes docs-only neutral commits" {
52
- # Ordinary docs/test commits without ticket closure must NOT earn the bypass.
53
- run grep -qE "docs-only.*neutral|test-only.*neutral|ordinary.*neutral|neutral.*no bypass" "$PIPELINE"
54
- [ "$status" -eq 0 ]
55
- }
56
-
57
- @test "pipeline.md requires audit reason for reducing bypass" {
58
- # Audit trail: cite which ticket closed, which risk remediated, etc.
59
- run grep -qE "RISK_BYPASS_REASON|cite.*ticket|reason.*bypass|bypass.*reason" "$PIPELINE"
60
- [ "$status" -eq 0 ]
61
- }
62
-
@@ -1,111 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: pipeline scorer MUST emit a structured RISK_REGISTER_HINT
3
- # block when a register-worthy risk shape is identified.
4
- #
5
- # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- # These tests assert that the pipeline scorer's prompt defines the passive-trigger
7
- # contract required by P110. Agent prompts are specification documents; a
8
- # behavioural check of an LLM's output is out of scope for bats — the contract
9
- # document is what the PostToolUse hook and consuming orchestrator rely on.
10
- #
11
- # Background: P102 landed `/wr-risk-scorer:create-risk` as an on-demand
12
- # invocation surface for the risk register (docs/risks/). JTBD-001
13
- # (Enforce Governance Without Slowing Down) requires passive triggers that
14
- # fire "without a manual step" — assistant-remembering-to-invoke is the same
15
- # failure mode the job identifies as a pain point. P110 closes the gap by
16
- # having the pipeline scorer — which fires on every commit/push/release gate
17
- # — emit a structured hint line when it sees a register-worthy risk shape.
18
- # The calling orchestrator consumes the hint post-remediation-loop and
19
- # invokes /wr-risk-scorer:create-risk with pre-filled context.
20
- #
21
- # Cross-reference:
22
- # P110: docs/problems/110-risk-register-has-no-passive-trigger-slash-command-alone-partial-jtbd-001.open.md
23
- # P102: the parent ticket (slash-command MVP invocation surface)
24
- # ADR-015: docs/decisions/015-on-demand-assessment-skills.proposed.md (Scorer Output Contract)
25
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
26
- # ADR-042: docs/decisions/042-auto-apply-scorer-remediations-open-vocabulary.proposed.md (consumption timing)
27
- # @jtbd JTBD-001 (enforce governance without slowing down — passive trigger)
28
- # @jtbd JTBD-005 (invoke governance assessments on demand — composed via pre-filled create-risk)
29
-
30
- setup() {
31
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
32
- PIPELINE="${AGENTS_DIR}/pipeline.md"
33
- }
34
-
35
- # ──────────────────────────────────────────────────────────────────────────────
36
- # Contract surface: RISK_REGISTER_HINT block exists and is documented
37
- # ──────────────────────────────────────────────────────────────────────────────
38
-
39
- @test "pipeline.md defines RISK_REGISTER_HINT block" {
40
- # The structured hint line is the machine-readable passive-trigger contract.
41
- run grep -q "RISK_REGISTER_HINT:" "$PIPELINE"
42
- [ "$status" -eq 0 ]
43
- }
44
-
45
- @test "pipeline.md RISK_REGISTER_HINT uses bulleted-list shape" {
46
- # Multi-hint capable: a single pipeline run can surface both an
47
- # above-appetite residual AND a confidentiality-disclosure risk.
48
- # Shape parallels RISK_REMEDIATIONS: (list-valued), not RISK_BYPASS_REASON: (single).
49
- run grep -qE "^RISK_REGISTER_HINT:[[:space:]]*$" "$PIPELINE"
50
- [ "$status" -eq 0 ]
51
- }
52
-
53
- # ──────────────────────────────────────────────────────────────────────────────
54
- # Trigger conditions: architect-approved three-trigger set
55
- # ──────────────────────────────────────────────────────────────────────────────
56
-
57
- @test "pipeline.md names above-appetite-residual trigger" {
58
- # Trigger (a): any cumulative residual score > appetite.
59
- run grep -q "above-appetite-residual" "$PIPELINE"
60
- [ "$status" -eq 0 ]
61
- }
62
-
63
- @test "pipeline.md names confidentiality-disclosure trigger" {
64
- # Trigger (b): confidential information (client names, revenue, pricing) flagged.
65
- # Composes with the existing "Confidential Information Disclosure" section.
66
- run grep -q "confidentiality-disclosure" "$PIPELINE"
67
- [ "$status" -eq 0 ]
68
- }
69
-
70
- @test "pipeline.md names user-stated-precondition trigger" {
71
- # Trigger (c): unmet user-stated precondition flagged as a Risk item.
72
- # Composes with the existing "User-Stated Preconditions Check" section.
73
- run grep -q "user-stated-precondition" "$PIPELINE"
74
- [ "$status" -eq 0 ]
75
- }
76
-
77
- # ──────────────────────────────────────────────────────────────────────────────
78
- # Consumption semantics: hint is consumed post-loop, not interleaved
79
- # ──────────────────────────────────────────────────────────────────────────────
80
-
81
- @test "pipeline.md documents post-loop consumption semantics" {
82
- # Architect advisory: the hint is consumed by the orchestrator AFTER the
83
- # ADR-042 auto-apply remediation loop converges (or Rule 5 halts), not
84
- # interleaved — otherwise register entries would be created for risks the
85
- # loop might have remediated away.
86
- run grep -qiE "post.?loop|after.*remediation.*(converge|loop)|after.*auto.?apply" "$PIPELINE"
87
- [ "$status" -eq 0 ]
88
- }
89
-
90
- # ──────────────────────────────────────────────────────────────────────────────
91
- # Cross-reference: hint hands off to /wr-risk-scorer:create-risk
92
- # ──────────────────────────────────────────────────────────────────────────────
93
-
94
- @test "pipeline.md names the create-risk hand-off target" {
95
- # The hint routes the consuming orchestrator to the MVP invocation surface
96
- # from P102. Without the hand-off target, a hint line is undirected.
97
- run grep -q "create-risk" "$PIPELINE"
98
- [ "$status" -eq 0 ]
99
- }
100
-
101
- # ──────────────────────────────────────────────────────────────────────────────
102
- # Silence guarantee: below appetite + no special triggers = no hint
103
- # ──────────────────────────────────────────────────────────────────────────────
104
-
105
- @test "pipeline.md documents no-hint silence when within appetite and no triggers fire" {
106
- # JTBD-001 "without slowing down": no hint noise when nothing is
107
- # register-worthy. This parallels the Below-Appetite Output Rule for
108
- # RISK_REMEDIATIONS: and protects the solo-developer 60-second review budget.
109
- run grep -qE "[Dd]o NOT emit.*RISK_REGISTER_HINT|[Oo]mit.*RISK_REGISTER_HINT|no hint|no.*RISK_REGISTER_HINT" "$PIPELINE"
110
- [ "$status" -eq 0 ]
111
- }
@@ -1,123 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: risk-scorer agent prompts must define a structured
3
- # machine-readable RISK_REMEDIATIONS block with the full 5-column format.
4
- #
5
- # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- # These tests assert that agent specification documents conform to the
7
- # structured-interaction contract (ADR-013) and the machine-readable format
8
- # required by P021.
9
- #
10
- # Background: P021 identified that above-appetite risk-scorer output used
11
- # free-text "Your call:" prose. The fix defined a structured RISK_REMEDIATIONS:
12
- # block. This test guards that all three scoring modes (pipeline, wip, plan)
13
- # define the block AND include the full 5-column format so calling skills
14
- # can render structured option prompts with effort and risk-delta context.
15
- #
16
- # Cross-reference:
17
- # ADR-013: docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md
18
- # P021: docs/problems/021-governance-skill-structured-prompts.known-error.md
19
- # @jtbd JTBD-001 (enforce governance without slowing down)
20
- # @jtbd JTBD-002 (ship with confidence — structured remediations are auditable)
21
-
22
- setup() {
23
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
24
- PIPELINE="${AGENTS_DIR}/pipeline.md"
25
- WIP="${AGENTS_DIR}/wip.md"
26
- PLAN="${AGENTS_DIR}/plan.md"
27
- }
28
-
29
- # ──────────────────────────────────────────────────────────────────────────────
30
- # pipeline.md: above-appetite structured output
31
- # ──────────────────────────────────────────────────────────────────────────────
32
-
33
- @test "pipeline.md defines RISK_REMEDIATIONS block" {
34
- # Must emit a structured block, not free-text, above appetite (ADR-013 Rule 1).
35
- run grep -q "RISK_REMEDIATIONS:" "$PIPELINE"
36
- [ "$status" -eq 0 ]
37
- }
38
-
39
- @test "pipeline.md RISK_REMEDIATIONS format includes effort column" {
40
- # 5-column format: id | description | effort (S/M/L) | risk_delta (-N) | files_touched
41
- # This column allows calling skills to size each remediation and present
42
- # a structured AskUserQuestion with effort context.
43
- run grep -q "effort" "$PIPELINE"
44
- [ "$status" -eq 0 ]
45
- }
46
-
47
- @test "pipeline.md RISK_REMEDIATIONS format includes risk_delta column" {
48
- # risk_delta lets calling skills show how much each remediation reduces score.
49
- run grep -q "risk_delta" "$PIPELINE"
50
- [ "$status" -eq 0 ]
51
- }
52
-
53
- @test "pipeline.md defines Below-Appetite Output Rule" {
54
- # Below appetite: silent pass, no advisory prose (ADR-013 Rule 5).
55
- run grep -q "Below-Appetite" "$PIPELINE"
56
- [ "$status" -eq 0 ]
57
- }
58
-
59
- # ──────────────────────────────────────────────────────────────────────────────
60
- # wip.md: above-appetite structured output
61
- # ──────────────────────────────────────────────────────────────────────────────
62
-
63
- @test "wip.md defines RISK_REMEDIATIONS block" {
64
- run grep -q "RISK_REMEDIATIONS:" "$WIP"
65
- [ "$status" -eq 0 ]
66
- }
67
-
68
- @test "wip.md RISK_REMEDIATIONS format includes effort column" {
69
- run grep -q "effort" "$WIP"
70
- [ "$status" -eq 0 ]
71
- }
72
-
73
- @test "wip.md RISK_REMEDIATIONS format includes risk_delta column" {
74
- run grep -q "risk_delta" "$WIP"
75
- [ "$status" -eq 0 ]
76
- }
77
-
78
- @test "wip.md defines Below-Appetite Rule" {
79
- run grep -q "Below-Appetite" "$WIP"
80
- [ "$status" -eq 0 ]
81
- }
82
-
83
- # ──────────────────────────────────────────────────────────────────────────────
84
- # plan.md: FAIL-verdict structured output
85
- # ──────────────────────────────────────────────────────────────────────────────
86
-
87
- @test "plan.md defines RISK_REMEDIATIONS block" {
88
- run grep -q "RISK_REMEDIATIONS:" "$PLAN"
89
- [ "$status" -eq 0 ]
90
- }
91
-
92
- @test "plan.md RISK_REMEDIATIONS format includes effort column" {
93
- run grep -q "effort" "$PLAN"
94
- [ "$status" -eq 0 ]
95
- }
96
-
97
- @test "plan.md RISK_REMEDIATIONS format includes risk_delta column" {
98
- run grep -q "risk_delta" "$PLAN"
99
- [ "$status" -eq 0 ]
100
- }
101
-
102
- # ──────────────────────────────────────────────────────────────────────────────
103
- # P108: scorer writes prose descriptions; agent decides (ADR-042 Rule 2a)
104
- # ──────────────────────────────────────────────────────────────────────────────
105
-
106
- @test "pipeline.md RISK_REMEDIATIONS format has no action_class column" {
107
- # ADR-042 Rule 2a: no structured action_class column. The agent reads
108
- # the description and decides. Match only markdown-table column-header
109
- # rows so prose mentions of "action_class" (e.g. "No structured
110
- # action_class column.") do not trip the assertion (P114).
111
- run grep -qE '^\| *action_class\b' "$PIPELINE"
112
- [ "$status" -ne 0 ]
113
- }
114
-
115
- @test "wip.md RISK_REMEDIATIONS format has no action_class column" {
116
- run grep -qE '^\| *action_class\b' "$WIP"
117
- [ "$status" -ne 0 ]
118
- }
119
-
120
- @test "plan.md RISK_REMEDIATIONS format has no action_class column" {
121
- run grep -qE '^\| *action_class\b' "$PLAN"
122
- [ "$status" -ne 0 ]
123
- }
@@ -1,89 +0,0 @@
1
- #!/usr/bin/env bats
2
- # Doc-lint guard: risk-scorer agent prompts must define a User-Stated
3
- # Preconditions Check as a sub-rule of Control Discovery.
4
- #
5
- # Structural assertions — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
- # These tests assert that the pipeline, wip, and plan scorer prompts
7
- # instruct the scorer to detect user-stated conditional-delivery warnings
8
- # and surface unmet preconditions as Risk items.
9
- #
10
- # Background: P041 identified that the risk scorer evaluated technical
11
- # risk of a diff in isolation and missed explicit user-stated warnings
12
- # that a change was conditional on a paired capability. Downstream this
13
- # caused a breaking change to ship to production despite a twice-stated
14
- # user warning. This guard prevents regression of the fix: every scoring
15
- # agent must have a User-Stated Preconditions Check.
16
- #
17
- # Cross-reference:
18
- # P041: docs/problems/041-risk-scorer-misses-user-stated-dependencies.known-error.md
19
- # ADR-013: structured user interaction for governance decisions
20
- # @jtbd JTBD-002 (ship with confidence — user-stated preconditions are honoured)
21
- # @jtbd JTBD-202 (pre-flight governance checks surface explicit warnings)
22
-
23
- setup() {
24
- AGENTS_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
25
- PIPELINE="${AGENTS_DIR}/pipeline.md"
26
- WIP="${AGENTS_DIR}/wip.md"
27
- PLAN="${AGENTS_DIR}/plan.md"
28
- }
29
-
30
- # ──────────────────────────────────────────────────────────────────────────────
31
- # pipeline.md: user-stated precondition check
32
- # ──────────────────────────────────────────────────────────────────────────────
33
-
34
- @test "pipeline.md defines User-Stated Preconditions Check section" {
35
- run grep -q "User-Stated Preconditions" "$PIPELINE"
36
- [ "$status" -eq 0 ]
37
- }
38
-
39
- @test "pipeline.md precondition check surfaces unmet preconditions as Risk items" {
40
- # Unmet preconditions must flow through the existing Risk item structure,
41
- # which feeds RISK_REMEDIATIONS above appetite (>= 5).
42
- run grep -qE "precondition.*Risk item|Risk item.*precondition" "$PIPELINE"
43
- [ "$status" -eq 0 ]
44
- }
45
-
46
- @test "pipeline.md precondition check credits zero reduction when paired capability is unmet" {
47
- # Aligns with existing Control Discovery rule: if a control cannot be named,
48
- # or a stated precondition is unmet, the control provides 0 reduction.
49
- run grep -qE "zero reduction|0 reduction" "$PIPELINE"
50
- [ "$status" -eq 0 ]
51
- }
52
-
53
- # ──────────────────────────────────────────────────────────────────────────────
54
- # wip.md: user-stated precondition check
55
- # ──────────────────────────────────────────────────────────────────────────────
56
-
57
- @test "wip.md defines User-Stated Preconditions Check section" {
58
- run grep -q "User-Stated Preconditions" "$WIP"
59
- [ "$status" -eq 0 ]
60
- }
61
-
62
- @test "wip.md precondition check surfaces unmet preconditions as Risk items" {
63
- run grep -qE "precondition.*Risk item|Risk item.*precondition" "$WIP"
64
- [ "$status" -eq 0 ]
65
- }
66
-
67
- @test "wip.md precondition check credits zero reduction when paired capability is unmet" {
68
- run grep -qE "zero reduction|0 reduction" "$WIP"
69
- [ "$status" -eq 0 ]
70
- }
71
-
72
- # ──────────────────────────────────────────────────────────────────────────────
73
- # plan.md: user-stated precondition check
74
- # ──────────────────────────────────────────────────────────────────────────────
75
-
76
- @test "plan.md defines User-Stated Preconditions Check section" {
77
- run grep -q "User-Stated Preconditions" "$PLAN"
78
- [ "$status" -eq 0 ]
79
- }
80
-
81
- @test "plan.md precondition check surfaces unmet preconditions as Risk items" {
82
- run grep -qE "precondition.*Risk item|Risk item.*precondition" "$PLAN"
83
- [ "$status" -eq 0 ]
84
- }
85
-
86
- @test "plan.md precondition check credits zero reduction when paired capability is unmet" {
87
- run grep -qE "zero reduction|0 reduction" "$PLAN"
88
- [ "$status" -eq 0 ]
89
- }