@windyroad/risk-scorer 0.12.2 → 0.12.3-preview.544
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.
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generated by scripts/sync-shim-wrappers.sh from
|
|
3
|
+
# packages/shared/lib/shim-wrapper-template.sh. DO NOT EDIT individual
|
|
4
|
+
# shim files in packages/*/bin/wr-* directly; edit the template + run
|
|
5
|
+
# `npm run sync:shim-wrappers` to regenerate.
|
|
6
|
+
#
|
|
7
|
+
# Resolution (ADR-080):
|
|
8
|
+
# 1. If the wrapper's parent dir is semver-shaped, treat as installed-
|
|
9
|
+
# cache execution and resolve to the highest-version sibling's
|
|
10
|
+
# scripts/ entry below.
|
|
11
|
+
# 2. Otherwise (parent dir is e.g. `architect`), treat as source-
|
|
12
|
+
# monorepo execution and dispatch to own scripts/. The source-repo-
|
|
13
|
+
# guard `exec` is the anchor parsed by
|
|
14
|
+
# packages/retrospective/scripts/check-tarball-shipped-shims.sh.
|
|
15
|
+
# 3. If the cache parent contains zero semver-shaped siblings, exit
|
|
16
|
+
# 127 with a stderr message naming the cache parent (per SQ-080-2).
|
|
17
|
+
#
|
|
18
|
+
# @adr ADR-080 (highest-version-wins shim wrapper plugin scaffold)
|
|
19
|
+
# @adr ADR-049 (plugin-bundled scripts resolve via bin/ on $PATH — amended)
|
|
20
|
+
# @problem P343 (mid-session staleness window)
|
|
21
|
+
|
|
22
|
+
set -euo pipefail
|
|
23
|
+
|
|
24
|
+
SHIM_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
25
|
+
OWN_VERSION_DIR="$(dirname "$SHIM_DIR")"
|
|
26
|
+
OWN_VERSION_NAME="$(basename "$OWN_VERSION_DIR")"
|
|
27
|
+
CACHE_PARENT="$(dirname "$OWN_VERSION_DIR")"
|
|
28
|
+
|
|
29
|
+
SEMVER_RE='^[0-9]+\.[0-9]+\.[0-9]+([-+][0-9A-Za-z.-]+)?$'
|
|
30
|
+
|
|
31
|
+
# Source-repo guard: own parent dir is NOT semver → dispatch to own scripts/.
|
|
32
|
+
if ! [[ "$OWN_VERSION_NAME" =~ $SEMVER_RE ]]; then
|
|
33
|
+
exec "$SHIM_DIR/../scripts/restage-commit.sh" "$@"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Cache execution: pick the highest-semver sibling under CACHE_PARENT.
|
|
37
|
+
HIGHEST=""
|
|
38
|
+
while IFS= read -r dir; do
|
|
39
|
+
name="$(basename "$dir")"
|
|
40
|
+
[[ "$name" =~ $SEMVER_RE ]] || continue
|
|
41
|
+
if [[ -z "$HIGHEST" ]] || [[ "$(printf '%s\n%s\n' "$HIGHEST" "$name" | sort -V | tail -1)" == "$name" ]]; then
|
|
42
|
+
HIGHEST="$name"
|
|
43
|
+
fi
|
|
44
|
+
done < <(find "$CACHE_PARENT" -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
|
|
45
|
+
|
|
46
|
+
if [[ -z "$HIGHEST" ]]; then
|
|
47
|
+
printf 'wr-shim: no cached versions in %s\n' "$CACHE_PARENT" >&2
|
|
48
|
+
exit 127
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
exec "$CACHE_PARENT/$HIGHEST/scripts/restage-commit.sh" "$@"
|
package/package.json
CHANGED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# packages/risk-scorer/scripts/restage-commit.sh
|
|
3
|
+
#
|
|
4
|
+
# Atomic re-stage-and-commit helper for the ADR-014 commit-gate flow.
|
|
5
|
+
#
|
|
6
|
+
# After the caller delegates to `wr-risk-scorer:pipeline` via the Agent tool
|
|
7
|
+
# (or invokes `/wr-risk-scorer:assess-release`), the Agent-tool boundary
|
|
8
|
+
# sometimes clears the parent index — a previously-staged set comes back as
|
|
9
|
+
# `Changes not staged for commit` and the subsequent `git commit` fails with
|
|
10
|
+
# "no changes added to commit" (P326). The workaround is a re-`git add` before
|
|
11
|
+
# the commit; this helper bundles the re-add + commit into a single atomic call
|
|
12
|
+
# so the SKILL.md surface no longer documents the double-tap.
|
|
13
|
+
#
|
|
14
|
+
# Surface:
|
|
15
|
+
# wr-risk-scorer-restage-commit -m "<msg>" [-m "<trailer>"] -- <path1> [<path2>...]
|
|
16
|
+
#
|
|
17
|
+
# Behaviour:
|
|
18
|
+
# - Accumulates all -m flags (repeatable; supports RISK_BYPASS-style trailers).
|
|
19
|
+
# - Requires `--` separator before paths (P326 grammar — avoids the path-vs-flag
|
|
20
|
+
# ambiguity when a path begins with `-`).
|
|
21
|
+
# - Runs `git add -- <paths>` (propagates `git add` exit code on bad paths).
|
|
22
|
+
# - Asserts the cached diff is non-empty (`git diff --cached --name-only`); exits
|
|
23
|
+
# 1 if nothing got staged, so the caller sees the empty-stage condition rather
|
|
24
|
+
# than committing an empty-or-misordered set.
|
|
25
|
+
# - Runs `git commit "${msg_args[@]}"` with the accumulated -m flags.
|
|
26
|
+
#
|
|
27
|
+
# Exit codes:
|
|
28
|
+
# 0 — commit landed
|
|
29
|
+
# 1 — usage error (missing -m, missing --, no paths) OR empty staging
|
|
30
|
+
# non-zero — propagated from `git add` or `git commit`
|
|
31
|
+
#
|
|
32
|
+
# @adr ADR-014 (governance skills commit their own work)
|
|
33
|
+
# @adr ADR-049 (resolved via bin/wr-risk-scorer-restage-commit shim)
|
|
34
|
+
# @adr ADR-052 (behavioural-fixture coverage at scripts/test/restage-commit.bats)
|
|
35
|
+
# @problem P326 (staged index cleared after risk-scorer pipeline delegation)
|
|
36
|
+
# @problem P057 (git mv + Edit re-stage discipline — composes with this helper)
|
|
37
|
+
|
|
38
|
+
set -uo pipefail
|
|
39
|
+
|
|
40
|
+
usage() {
|
|
41
|
+
cat >&2 <<'USAGE'
|
|
42
|
+
Usage: wr-risk-scorer-restage-commit -m "<msg>" [-m "<trailer>"] -- <path1> [<path2>...]
|
|
43
|
+
|
|
44
|
+
Atomic re-stage-and-commit after a wr-risk-scorer:pipeline Agent-tool delegation.
|
|
45
|
+
At least one -m flag is required. The `--` separator is mandatory before paths.
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
wr-risk-scorer-restage-commit -m "docs(problems): open P999 widget" -- docs/problems/open/999-widget.md docs/problems/README.md
|
|
49
|
+
|
|
50
|
+
wr-risk-scorer-restage-commit \
|
|
51
|
+
-m "docs(problems): capture P999 widget" \
|
|
52
|
+
-m "RISK_BYPASS: capture-deferred-readme" \
|
|
53
|
+
-- docs/problems/open/999-widget.md
|
|
54
|
+
USAGE
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
msg_args=()
|
|
58
|
+
saw_separator=0
|
|
59
|
+
paths=()
|
|
60
|
+
|
|
61
|
+
while [ "$#" -gt 0 ]; do
|
|
62
|
+
case "$1" in
|
|
63
|
+
-m)
|
|
64
|
+
if [ "$#" -lt 2 ]; then
|
|
65
|
+
echo "ERROR: -m requires a message argument" >&2
|
|
66
|
+
usage
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
msg_args+=( -m "$2" )
|
|
70
|
+
shift 2
|
|
71
|
+
;;
|
|
72
|
+
--)
|
|
73
|
+
saw_separator=1
|
|
74
|
+
shift
|
|
75
|
+
while [ "$#" -gt 0 ]; do
|
|
76
|
+
paths+=( "$1" )
|
|
77
|
+
shift
|
|
78
|
+
done
|
|
79
|
+
;;
|
|
80
|
+
-h|--help)
|
|
81
|
+
usage
|
|
82
|
+
exit 0
|
|
83
|
+
;;
|
|
84
|
+
*)
|
|
85
|
+
echo "ERROR: unexpected argument '$1' — paths must follow a '--' separator" >&2
|
|
86
|
+
usage
|
|
87
|
+
exit 1
|
|
88
|
+
;;
|
|
89
|
+
esac
|
|
90
|
+
done
|
|
91
|
+
|
|
92
|
+
if [ "${#msg_args[@]}" -eq 0 ]; then
|
|
93
|
+
echo "ERROR: at least one -m message flag is required" >&2
|
|
94
|
+
usage
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
if [ "$saw_separator" -eq 0 ]; then
|
|
99
|
+
echo "ERROR: missing '--' separator before paths" >&2
|
|
100
|
+
usage
|
|
101
|
+
exit 1
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if [ "${#paths[@]}" -eq 0 ]; then
|
|
105
|
+
echo "ERROR: no paths supplied after '--'" >&2
|
|
106
|
+
usage
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
git add -- "${paths[@]}"
|
|
111
|
+
ADD_STATUS=$?
|
|
112
|
+
if [ "$ADD_STATUS" -ne 0 ]; then
|
|
113
|
+
exit "$ADD_STATUS"
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
if [ -z "$(git diff --cached --name-only)" ]; then
|
|
117
|
+
echo "ERROR: nothing staged after re-add — supplied paths produced an empty index diff" >&2
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
git commit "${msg_args[@]}"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Behavioural-fixture coverage for packages/risk-scorer/scripts/restage-commit.sh
|
|
3
|
+
# per ADR-052 (behavioural tests default) and P326 (re-stage-after-scorer-delegation).
|
|
4
|
+
#
|
|
5
|
+
# The script is invoked AFTER the agent delegates to wr-risk-scorer:pipeline
|
|
6
|
+
# to land the commit atomically — re-stages paths the Agent-tool boundary cleared
|
|
7
|
+
# from the index, asserts staging is non-empty, then runs `git commit` with the
|
|
8
|
+
# caller's -m args. Eliminates the silent re-add round-trip P326 documented.
|
|
9
|
+
#
|
|
10
|
+
# Surface:
|
|
11
|
+
# wr-risk-scorer-restage-commit -m "<msg>" [-m "<trailer>"] -- <path1> [<path2>...]
|
|
12
|
+
|
|
13
|
+
setup() {
|
|
14
|
+
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../.." && pwd)"
|
|
15
|
+
SCRIPT="$REPO_ROOT/packages/risk-scorer/scripts/restage-commit.sh"
|
|
16
|
+
SHIM="$REPO_ROOT/packages/risk-scorer/bin/wr-risk-scorer-restage-commit"
|
|
17
|
+
WORK_DIR="$(mktemp -d)"
|
|
18
|
+
cd "$WORK_DIR"
|
|
19
|
+
git init --quiet
|
|
20
|
+
git config user.email "restage-test@example.com"
|
|
21
|
+
git config user.name "Restage Test"
|
|
22
|
+
git config commit.gpgsign false
|
|
23
|
+
git commit --quiet --allow-empty -m "init"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
teardown() {
|
|
27
|
+
cd /
|
|
28
|
+
rm -rf "$WORK_DIR"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@test "shim wrapper exists and is executable" {
|
|
32
|
+
[ -x "$SHIM" ]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@test "shim resolves canonical script (not exit 127)" {
|
|
36
|
+
echo "seed" > seed.txt
|
|
37
|
+
run "$SHIM" -m "test" -- seed.txt
|
|
38
|
+
[ "$status" -ne 127 ]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@test "single path: re-stages and commits (the P326 happy path)" {
|
|
42
|
+
echo "content" > file.txt
|
|
43
|
+
run bash "$SCRIPT" -m "test: commit file" -- file.txt
|
|
44
|
+
[ "$status" -eq 0 ]
|
|
45
|
+
run git log -1 --name-only --format=
|
|
46
|
+
echo "$output" | grep -q '^file\.txt$'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@test "multi-path: re-stages all paths and commits them in one commit" {
|
|
50
|
+
echo "a" > a.txt
|
|
51
|
+
echo "b" > b.txt
|
|
52
|
+
echo "c" > c.txt
|
|
53
|
+
run bash "$SCRIPT" -m "test: multi" -- a.txt b.txt c.txt
|
|
54
|
+
[ "$status" -eq 0 ]
|
|
55
|
+
run git log -1 --name-only --format=
|
|
56
|
+
echo "$output" | grep -q '^a\.txt$'
|
|
57
|
+
echo "$output" | grep -q '^b\.txt$'
|
|
58
|
+
echo "$output" | grep -q '^c\.txt$'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@test "multiple -m flags pass through (trailer like RISK_BYPASS)" {
|
|
62
|
+
echo "x" > x.txt
|
|
63
|
+
run bash "$SCRIPT" \
|
|
64
|
+
-m "docs(problems): capture P999 test" \
|
|
65
|
+
-m "RISK_BYPASS: capture-deferred-readme" \
|
|
66
|
+
-- x.txt
|
|
67
|
+
[ "$status" -eq 0 ]
|
|
68
|
+
run git log -1 --format=%B
|
|
69
|
+
echo "$output" | grep -q '^docs(problems): capture P999 test'
|
|
70
|
+
echo "$output" | grep -q 'RISK_BYPASS: capture-deferred-readme'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@test "missing -m flag → exit 1, no commit" {
|
|
74
|
+
echo "x" > x.txt
|
|
75
|
+
run bash "$SCRIPT" -- x.txt
|
|
76
|
+
[ "$status" -ne 0 ]
|
|
77
|
+
echo "$output" | grep -qi 'message\|usage'
|
|
78
|
+
run git log --oneline
|
|
79
|
+
[ "$(echo "$output" | wc -l | tr -d ' ')" = "1" ]
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@test "missing -- separator → exit 1" {
|
|
83
|
+
echo "x" > x.txt
|
|
84
|
+
run bash "$SCRIPT" -m "test" x.txt
|
|
85
|
+
[ "$status" -ne 0 ]
|
|
86
|
+
echo "$output" | grep -qi 'separator\|usage'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@test "no paths after -- → exit 1, no commit" {
|
|
90
|
+
run bash "$SCRIPT" -m "test" --
|
|
91
|
+
[ "$status" -ne 0 ]
|
|
92
|
+
echo "$output" | grep -qi 'path\|usage'
|
|
93
|
+
run git log --oneline
|
|
94
|
+
[ "$(echo "$output" | wc -l | tr -d ' ')" = "1" ]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@test "nothing staged after re-add → exit 1, no commit (e.g. unchanged file)" {
|
|
98
|
+
echo "tracked" > tracked.txt
|
|
99
|
+
git add tracked.txt
|
|
100
|
+
git commit --quiet -m "seed tracked"
|
|
101
|
+
run bash "$SCRIPT" -m "test: should fail" -- tracked.txt
|
|
102
|
+
[ "$status" -ne 0 ]
|
|
103
|
+
echo "$output" | grep -qi 'nothing staged\|empty'
|
|
104
|
+
run git log --oneline
|
|
105
|
+
[ "$(echo "$output" | wc -l | tr -d ' ')" = "2" ]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@test "path that doesn't exist → exit non-zero (git add propagates)" {
|
|
109
|
+
run bash "$SCRIPT" -m "test" -- nonexistent.txt
|
|
110
|
+
[ "$status" -ne 0 ]
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@test "rename via git mv survives the re-stage-and-commit (P057 + P326 compose)" {
|
|
114
|
+
echo "v1" > orig.md
|
|
115
|
+
git add orig.md
|
|
116
|
+
git commit --quiet -m "seed"
|
|
117
|
+
git mv orig.md renamed.md
|
|
118
|
+
echo "v2" >> renamed.md
|
|
119
|
+
run bash "$SCRIPT" -m "test: rename+edit" -- renamed.md
|
|
120
|
+
[ "$status" -eq 0 ]
|
|
121
|
+
run git log -1 --name-only --format=
|
|
122
|
+
echo "$output" | grep -q '^renamed\.md$'
|
|
123
|
+
[ ! -f orig.md ]
|
|
124
|
+
run cat renamed.md
|
|
125
|
+
echo "$output" | grep -q 'v2'
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@test "doesn't touch unrelated unstaged changes" {
|
|
129
|
+
echo "subject" > subject.txt
|
|
130
|
+
echo "bystander" > bystander.txt
|
|
131
|
+
run bash "$SCRIPT" -m "test: subject only" -- subject.txt
|
|
132
|
+
[ "$status" -eq 0 ]
|
|
133
|
+
run git status --porcelain bystander.txt
|
|
134
|
+
echo "$output" | grep -q '^?? bystander\.txt'
|
|
135
|
+
run git log -1 --name-only --format=
|
|
136
|
+
! echo "$output" | grep -q '^bystander\.txt$'
|
|
137
|
+
}
|