forgedock 1.16.2 → 1.17.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.
- package/bin/engine/outcome-codes.mjs +92 -0
- package/bin/engine/phases.mjs +86 -26
- package/bin/engine/projector.mjs +48 -1
- package/bin/engine/runlog.mjs +13 -5
- package/bin/engine/telemetry-seam.mjs +62 -0
- package/bin/engine/telemetry-seam.test.mjs +60 -0
- package/bin/engine/telemetry.mjs +148 -0
- package/bin/engine/telemetry.test.mjs +120 -0
- package/bin/engine-cli.mjs +12 -1
- package/bin/engine.mjs +145 -40
- package/bin/forgedock.mjs +7 -1
- package/bin/hooks/interactive-engine.mjs +10 -0
- package/bin/hooks/pre-tool-use.mjs +187 -0
- package/bin/runner.mjs +7 -0
- package/bin/stats/aggregate.mjs +231 -0
- package/bin/stats/cache.mjs +40 -0
- package/bin/stats/github-source.mjs +140 -0
- package/bin/stats/index.mjs +154 -0
- package/bin/stats/local-source.mjs +79 -0
- package/bin/stats/package.json +6 -0
- package/bin/stats/render.mjs +82 -0
- package/bin/stats/stats.test.mjs +224 -0
- package/commands/cleanup.md +83 -2
- package/commands/deploy-info.md +8 -4
- package/commands/orchestrate/phase-1-resolve.md +4 -1
- package/commands/orchestrate/phase-4-execution.md +17 -2
- package/commands/orchestrate/phase-5-cleanup.md +18 -2
- package/commands/pipeline-health/phase-1-context.md +2 -0
- package/commands/pipeline-health/phase-2-metrics.md +12 -5
- package/commands/pipeline-status.md +21 -1
- package/commands/review-pr-agents/protocols.md +1 -0
- package/commands/review-pr-agents.md +10 -2
- package/commands/review-pr-staging.md +102 -25
- package/commands/review-pr.md +119 -103
- package/commands/work-on/build/implement.md +26 -5
- package/commands/work-on/build/validate.md +3 -2
- package/commands/work-on/build.md +95 -64
- package/commands/work-on/close.md +17 -6
- package/commands/work-on/decompose.md +45 -4
- package/commands/work-on/investigate.md +6 -2
- package/commands/work-on/remediate.md +22 -6
- package/commands/work-on/review.md +2 -2
- package/docs/CONFIG.md +33 -0
- package/docs/OUTCOME-CODES.md +48 -0
- package/docs/RELEASE-NOTES.md +12 -0
- package/docs/STATS.md +62 -0
- package/docs/TELEMETRY.md +65 -0
- package/docs/WORK-ON-RUNTIME.md +13 -0
- package/docs/site/command-reference.md +1 -1
- package/docs/spec/label-state-machine.md +1 -1
- package/package.json +3 -2
- package/scripts/builder-resume-match.test.sh +58 -0
- package/scripts/cap-findings.sh +110 -0
- package/scripts/cap-findings.test.sh +130 -0
- package/scripts/check-spec-markers.sh +2 -0
- package/scripts/classify-finding.sh +65 -16
- package/scripts/classify-finding.test.sh +43 -1
- package/scripts/classify-grep-exit.sh +20 -0
- package/scripts/classify-grep-exit.test.sh +46 -0
- package/scripts/close-parent-c3.test.sh +54 -0
- package/scripts/cost-report.sh +146 -0
- package/scripts/cost-report.test.sh +80 -0
- package/scripts/diff-size.sh +5 -0
- package/scripts/doctor-pipeline-state.sh +43 -0
- package/scripts/file-deferred-followups.sh +159 -0
- package/scripts/file-deferred-followups.test.sh +106 -0
- package/scripts/fixtures/cost-report/a-merged1.jsonl +6 -0
- package/scripts/fixtures/cost-report/a-merged2-remediated.jsonl +7 -0
- package/scripts/fixtures/cost-report/a-needs-human.jsonl +4 -0
- package/scripts/fixtures/cost-report/b-merged.jsonl +3 -0
- package/scripts/fixtures/cost-report/c-merged-attempt-usage.jsonl +8 -0
- package/scripts/fixtures/cost-report/hydrated-no-usage.jsonl +3 -0
- package/scripts/fixtures/cost-report/old-log-no-version.jsonl +3 -0
- package/scripts/fixtures/cost-report/unfinished-no-terminal.jsonl +2 -0
- package/scripts/fixtures/cost-report/unfinished-reopened.jsonl +5 -0
- package/scripts/forge-root.test.sh +8 -3
- package/scripts/lib/fence-bootstrap.sh +4 -3
- package/scripts/lib/pr-issue-number.sh +18 -0
- package/scripts/lib/review-template-resolve.sh +41 -0
- package/scripts/lib/telemetry.sh +168 -0
- package/scripts/remediate-liveness.sh +42 -6
- package/scripts/review-acceptance-gate.sh +16 -7
- package/scripts/review-acceptance-gate.test.sh +13 -0
- package/scripts/review-pr-domain-map.test.sh +8 -3
- package/scripts/review-pr-gate2.test.sh +15 -0
- package/scripts/review-pr-staging-finding-filter.test.sh +44 -0
- package/scripts/review-pr-staging-scope.test.sh +65 -5
- package/scripts/review-prepare.sh +517 -0
- package/scripts/review-prepare.test.sh +270 -0
- package/scripts/review-roster.sh +172 -0
- package/scripts/review-roster.test.sh +163 -0
- package/scripts/run-shell-tests.sh +3 -0
- package/scripts/telemetry.test.sh +106 -0
- package/scripts/wait-ci-green.sh +8 -1
- package/templates/forge.yaml.minimal +9 -0
|
@@ -147,13 +147,22 @@ OUT9=$( ( SELECTED_AGENT_COUNT="abc"; . "$TMP/selcase.sh"; echo "$SELECTED_COUNT
|
|
|
147
147
|
[ "$OUT9" = "true" ] && ok || bad "Phase 6: non-integer SELECTED_AGENT_COUNT must be invalid (got '$OUT9')"
|
|
148
148
|
mkdir -p "$TMP/sd8/full" "$TMP/sd8/empty" "$TMP/sd8/bad" "$TMP/bin"
|
|
149
149
|
printf '#!/bin/sh\necho stub-value\n' > "$TMP/bin/yq"; chmod +x "$TMP/bin/yq"
|
|
150
|
-
printf '42\n' > "$TMP/sd8/full/staging_pr_number"; printf '7\n8\n' > "$TMP/sd8/full/42_bundle-prs.txt"
|
|
151
|
-
printf '
|
|
150
|
+
printf '42\n' > "$TMP/sd8/full/staging_pr_number.runA"; printf '7\n8\n' > "$TMP/sd8/full/42_bundle-prs.txt"
|
|
151
|
+
printf '43\n' > "$TMP/sd8/full/staging_pr_number.runB"; printf '9\n' > "$TMP/sd8/full/43_bundle-prs.txt"
|
|
152
|
+
printf '42; rm -rf /\n' > "$TMP/sd8/bad/staging_pr_number.runA"
|
|
152
153
|
boot() { # scratch-dir -> prints "PR_NUMBER|ALL_PR_NUMBERS(joined)|GH_REPO" then any warning
|
|
153
|
-
( unset PR_NUMBER ALL_PR_NUMBERS GH_REPO DEFAULT_BRANCH STAGING_BRANCH; export PATH="$TMP/bin:$PATH" FORGE_SCRATCHPAD="$1"
|
|
154
|
+
( unset PR_NUMBER ALL_PR_NUMBERS GH_REPO DEFAULT_BRANCH STAGING_BRANCH; export PATH="$TMP/bin:$PATH" FORGE_SCRATCHPAD="$1" FORGE_RUN_KEY="${2:-runA}"
|
|
154
155
|
export FORGEDOCK_HOME="$ROOT"; . "$TMP/boot.sh" 2>&1; echo "PR=${PR_NUMBER:-}|ALL=$(echo ${ALL_PR_NUMBERS:-})|REPO=${GH_REPO:-}|BR=${STAGING_BRANCH:-}" ) 2>&1; }
|
|
155
156
|
OUT8=$(boot "$TMP/sd8/full")
|
|
156
157
|
[ "$OUT8" = "PR=42|ALL=7 8|REPO=stub-value|BR=stub-value" ] && ok || bad "fresh shell must reload staging_pr_number and bundle-prs from the scratchpad (got '$OUT8')"
|
|
158
|
+
OUT8=$(boot "$TMP/sd8/full" runB)
|
|
159
|
+
[ "$OUT8" = "PR=43|ALL=9|REPO=stub-value|BR=stub-value" ] && ok || bad "two runs in one scratchpad must each reload their own PR (got '$OUT8')"
|
|
160
|
+
OUT8=$(boot "$TMP/sd8/full" runC)
|
|
161
|
+
case "$OUT8" in *"WARNING: PR_NUMBER is empty"*"PR=|"*) ok ;; *) bad "a run with no pointer must not read another run's pointer (got '$OUT8')" ;; esac
|
|
162
|
+
OUT8=$(boot "$TMP/sd8/full" '../x')
|
|
163
|
+
case "$OUT8" in *"PR=|"*) ok ;; *) bad "a path-like run key must be sanitised (got '$OUT8')" ;; esac
|
|
164
|
+
_KD='FORGE_RUN_KEY=$(printf'
|
|
165
|
+
[ "$(grep -F "$_KD" "$SPEC" | grep -F 'FORGE_RUN_KEY="${FORGE_RUN_KEY:-' | head -1)" = "$(grep -F "$_KD" "$ROOT/scripts/lib/fence-bootstrap.sh" | grep -F 'FORGE_RUN_KEY="${FORGE_RUN_KEY:-' | head -1)" ] && grep -qF 'FORGE_RUN_KEY="${FORGE_RUN_KEY:-' "$SPEC" && ok || bad "FORGE_RUN_KEY derivation must be identical in spec and fence-bootstrap.sh"
|
|
157
166
|
OUT8=$(boot "$TMP/sd8/empty")
|
|
158
167
|
case "$OUT8" in *"WARNING: PR_NUMBER is empty"*"PR=|ALL=|"*) ok ;; *) bad "empty scratchpad must leave PR_NUMBER empty and warn (got '$OUT8')" ;; esac
|
|
159
168
|
OUT8=$(boot "$TMP/sd8/bad")
|
|
@@ -191,16 +200,38 @@ jq -n --arg sha "$OLDSHA" '[{author_association:"MEMBER",user:{type:"User",login
|
|
|
191
200
|
PRIOR_OUT=$( ( export FIX_COMMENTS="$TMP/member-comments.json" PATH="$TMP/bin:$PATH"; REPO=o/r; _pscr="$TMP"; TRUSTED_SCRIPT="$TC"; . "$TMP/prior-fn.sh"; PF_SKIP="" PF_PRS=41 prior_findings_tsv ) 2>/dev/null )
|
|
192
201
|
printf '%s\n' "$PRIOR_OUT" > "$TMP/prior.tsv"
|
|
193
202
|
[ "$(printf '%s\n' "$PRIOR_OUT" | grep -c .)" = "1" ] && printf '%s' "$PRIOR_OUT" | grep -q '^src/api.py 12 12 Missing retry on timeout handler filed 123$' && ok || bad "member PR finding must reach the TSV (open issue linked) and an untrusted comment must not (got: $PRIOR_OUT)"
|
|
203
|
+
awk '/^cap_pass\(\) \{/,/^\}/' "$SPEC" > "$TMP/cap-fn.sh"
|
|
204
|
+
[ -s "$TMP/cap-fn.sh" ] && ok || bad "cap_pass not found in the spec"
|
|
194
205
|
run_dup() { # finding-file finding-line -> "DISPOSITION|FILED|REFLAG|LISTED"
|
|
195
206
|
( _SD="$TMP"; PR_NUMBER=9; CLASSIFY_SCRIPT="$ROOT/scripts/classify-finding.sh"; PRIOR_FILE="$TMP/prior.tsv"; SCOPE_MODE=full; CROSS_PR_FILES=""; UNREVIEWED_FILES=""; DEPLOY_WIRING_FILES=""
|
|
196
207
|
NOTE_LIST_FILE="$TMP/dup-notes.md"; : > "$NOTE_LIST_FILE"; NOTES_LISTED=0; FINDINGS_FILED=0; OUT_OF_SCOPE=0; NOTES_REFLAG=0
|
|
197
208
|
FINDING_ID=Z1; FINDING_SEVERITY="${3:-MEDIUM}"; FINDING_CONFIDENCE=CONFIRMED; FINDING_AGENT="General"; FINDING_TITLE="${4:-retry missing for the timeout handler}"; FINDING_BODY=b; FINDING_FILE="$1"; FINDING_PATHS="$1"
|
|
198
|
-
|
|
209
|
+
CAP_ROWS_FILE="$TMP/dup-rows.tsv"; : > "$CAP_ROWS_FILE"; CAPPED_IDS_FILE="$TMP/dup-capped.txt"; CAP_SCRIPT="$ROOT/scripts/cap-findings.sh"; NOTES_CAPPED=0
|
|
210
|
+
. "$TMP/fn.sh"; . "$TMP/cap-fn.sh"; classify_one; cap_pass >/dev/null; echo "$DISPOSITION|$FINDINGS_FILED|$NOTES_REFLAG|$NOTES_LISTED" ) 2>&1 | tail -1; }
|
|
199
211
|
[ "$(run_dup src/api.py:12)" = "NOTE reflag-filed #123|0|1|0" ] && ok || bad "a staging finding duplicating a member PR finding must be NOTE reflag-filed and file nothing (got '$(run_dup src/api.py:12)')"
|
|
200
212
|
[ "$(run_dup src/api.py:12 x HIGH)" = "ISSUE severity-HIGH|1|0|0" ] && ok || bad "a HIGH duplicate of a member PR finding must still be an ISSUE (got '$(run_dup src/api.py:12 x HIGH)')"
|
|
201
213
|
[ "$(run_dup src/other.py:12)" = "ISSUE MEDIUM-CONFIRMED|1|0|0" ] && ok || bad "a non-duplicate on another file must classify normally (got '$(run_dup src/other.py:12)')"
|
|
202
214
|
run_dup src/api.py:12 >/dev/null
|
|
203
215
|
grep -q 'reflag-filed #123' "$TMP/dup-notes.md" && ok || bad "a re-flag NOTE must be listed, not dropped"
|
|
216
|
+
# (8b) per-review cap (forge#3642): classify_one only records ISSUE rows; cap_pass keeps review.max_filed_findings (default 2), lists the rest as NOTE capped, never caps HIGH.
|
|
217
|
+
run_cap() { # "<sev>:<conf>:<id>"... -> "FILED|CAPPED|NOTES_LISTED|capped-ids(comma)|note-lines-with-capped"
|
|
218
|
+
( _SD="$TMP"; PR_NUMBER=9; CLASSIFY_SCRIPT="$ROOT/scripts/classify-finding.sh"; PRIOR_FILE=""; SCOPE_MODE=full; CROSS_PR_FILES=""; UNREVIEWED_FILES=""; DEPLOY_WIRING_FILES=""
|
|
219
|
+
NOTE_LIST_FILE="$TMP/cap-notes.md"; : > "$NOTE_LIST_FILE"; NOTES_LISTED=0; FINDINGS_FILED=0; OUT_OF_SCOPE=0; NOTES_REFLAG=0; NOTES_CAPPED=0
|
|
220
|
+
CAP_ROWS_FILE="$TMP/cap-rows.tsv"; : > "$CAP_ROWS_FILE"; CAPPED_IDS_FILE="$TMP/cap-capped.txt"; CAP_SCRIPT="$ROOT/scripts/cap-findings.sh"; MAX_FILED_FINDINGS="${CAPMAX:-}"
|
|
221
|
+
. "$TMP/fn.sh"; . "$TMP/cap-fn.sh"
|
|
222
|
+
for spec in "$@"; do
|
|
223
|
+
IFS=: read -r FINDING_SEVERITY FINDING_CONFIDENCE FINDING_ID <<EOF3
|
|
224
|
+
$spec
|
|
225
|
+
EOF3
|
|
226
|
+
FINDING_AGENT=General; FINDING_TITLE="finding $FINDING_ID"; FINDING_BODY=b; FINDING_FILE="src/$FINDING_ID.py"; FINDING_PATHS="$FINDING_FILE"
|
|
227
|
+
classify_one
|
|
228
|
+
done
|
|
229
|
+
cap_pass >/dev/null
|
|
230
|
+
echo "$FINDINGS_FILED|$NOTES_CAPPED|$NOTES_LISTED|$(paste -sd, "$CAPPED_IDS_FILE")|$(grep -c 'NOTE capped (' "$NOTE_LIST_FILE")" ) 2>&1 | tail -1; }
|
|
231
|
+
[ "$(run_cap MEDIUM:LIKELY:a MEDIUM:CONFIRMED:b MEDIUM:LIKELY:c)" = "2|1|0|c|1" ] && ok || bad "3 MEDIUM findings: 2 filed, the lowest-ranked capped and listed (got '$(run_cap MEDIUM:LIKELY:a MEDIUM:CONFIRMED:b MEDIUM:LIKELY:c)')"
|
|
232
|
+
[ "$(run_cap HIGH:LIKELY:a HIGH:POSSIBLE:b CRITICAL:CONFIRMED:c MEDIUM:LIKELY:d)" = "4|0|0||0" ] && ok || bad "HIGH/CRITICAL must never be capped (got '$(run_cap HIGH:LIKELY:a HIGH:POSSIBLE:b CRITICAL:CONFIRMED:c MEDIUM:LIKELY:d)')"
|
|
233
|
+
[ "$(CAPMAX=1 run_cap MEDIUM:LIKELY:a MEDIUM:CONFIRMED:b)" = "1|1|0|a|1" ] && ok || bad "review.max_filed_findings=1 must be honoured (got '$(CAPMAX=1 run_cap MEDIUM:LIKELY:a MEDIUM:CONFIRMED:b)')"
|
|
234
|
+
[ "$(CAPMAX=zzz run_cap MEDIUM:LIKELY:a MEDIUM:LIKELY:b MEDIUM:LIKELY:c)" = "2|1|0|c|1" ] && ok || bad "an invalid review.max_filed_findings must fall back to the default 2"
|
|
204
235
|
# (9) stale-head delta credit (forge#3638): the spec's bundle_delta_credit runs against real git fixtures and the REAL review-delta.sh / trusted-comments.sh.
|
|
205
236
|
# Fail-closed cases first: every FULL / error / untrusted path must leave the PR's commits UNREVIEWED (empty credit).
|
|
206
237
|
if command -v git >/dev/null 2>&1; then
|
|
@@ -284,10 +315,39 @@ if grep -qE 'merge-base --is-ancestor.*REVIEWED_SHA_STALE|diff_shape\(\)' "$SPEC
|
|
|
284
315
|
grep -qF 'printf '"'"'%s\n'"'"' "$_FILES" | sort -u | sed "s|^|$pr |" >> "$_PF"' "$SPEC" && grep -qF 'git diff-tree --no-commit-id --name-only -r --cc "$c"' "$SPEC" && ok || bad "CROSS_PR_FILES accumulation and --cc merge scoping must stay intact"
|
|
285
316
|
[ "$(grep -c '# FENCE_BOOTSTRAP$' "$SPEC" | head -1)" -ge 3 ] && ok || bad "FENCE_BOOTSTRAP stubs must remain"
|
|
286
317
|
# an unresolvable helper fails the fence closed (exit 1), never an unsourced bootstrap
|
|
287
|
-
OUT8=$( ( unset FORGEDOCK_HOME; export HOME="$TMP/nohome"; cd "$TMP" && bash -c "$(cat "$TMP/boot.sh"); echo reached" ) 2>&1 )
|
|
318
|
+
OUT8=$( ( unset FORGEDOCK_HOME FORGE_HOME FORGE_ROOT CLAUDE_PLUGIN_ROOT CLAUDE_CONFIG_DIR CODEX_HOME FORGE_SOURCED_ROOT FORGEDOCK_MARKETPLACE; export HOME="$TMP/nohome"; cd "$TMP" && bash -c "$(cat "$TMP/boot.sh"); echo reached" ) 2>&1 )
|
|
288
319
|
case "$OUT8" in *BLOCKED*) case "$OUT8" in *reached*) bad "unresolved bootstrap helper must stop the fence" ;; *) ok ;; esac ;; *) bad "unresolved bootstrap helper must print BLOCKED (got '$OUT8')" ;; esac
|
|
289
320
|
# a stale-head PR must not credit its own merge commit (it contains the post-review commits): the DELTA branch only appends DELTA_COMMITS
|
|
290
321
|
if awk '/^bundle_delta_credit\(\)/,/^\}/' "$SPEC" | grep -q 'mergeCommit'; then bad "the DELTA path must not credit the PR merge commit"; else ok; fi
|
|
322
|
+
# (10) fail-closed gate verdict (forge#3734): an empty/missing/invalid persisted verdict must never become SKIP
|
|
323
|
+
awk '/^\*\*Verdict handling\*\*:/{f=1;next} f&&/^```bash/{g=1;next} g&&/^```/{exit} g' "$SPEC" | grep -v '# FENCE_BOOTSTRAP$' > "$TMP/vh.sh"
|
|
324
|
+
[ -s "$TMP/vh.sh" ] && ok || bad "could not extract the Phase 6.5 verdict-handling fence"
|
|
325
|
+
if awk '/^ \*\)/,/;;/' "$SPEC" | grep -q 'TEST_GATE_VERDICT="SKIP"'; then bad "catch-all arm must not set TEST_GATE_VERDICT=SKIP"; else ok; fi
|
|
326
|
+
grep -qF 'missing/invalid' "$SPEC" && ok || bad "spec must document missing/invalid gate-verdict handling"
|
|
327
|
+
if grep -F 'FORGE:TEST_GATE:RESULT=' "$SPEC" | grep -q 'tail -1 || echo "SKIP"'; then bad "producer must not coerce an absent marker to SKIP"; else ok; fi
|
|
328
|
+
vh10() { # $1 posture, $2 persisted verdict content ('-' = no file), $3 env verdict (optional)
|
|
329
|
+
local sd="$TMP/vh10.$RANDOM"; mkdir -p "$sd"
|
|
330
|
+
[ "$2" = "-" ] || printf '%s\n' "$2" > "$sd/5_test_gate_verdict"
|
|
331
|
+
( export _SD="$sd" PR_NUMBER=5 GH_REPO=o/r DEFAULT_BRANCH=main ALL_PR_NUMBERS="5" CONFIG_FILE=/dev/null P10="$1"
|
|
332
|
+
[ -z "${3:-}" ] || export TEST_GATE_VERDICT="$3"
|
|
333
|
+
forge_resolve() { :; }; yq() { case "$*" in *posture*) echo "$P10" ;; *) echo "OVERRIDE: x" ;; esac; }; gh() { return 0; }
|
|
334
|
+
. "$TMP/vh.sh" >"$sd/out" 2>&1; echo "rc=0" >> "$sd/out" ) ; local rc=$?
|
|
335
|
+
VH10_OUT=$(cat "$sd/out"); VH10_V=$(cat "$sd/5_test_gate_verdict" 2>/dev/null); VH10_R=$(cat "$sd/5_test_gate_reason" 2>/dev/null)
|
|
336
|
+
}
|
|
337
|
+
for case10 in "-" "" "garbage" "pass" "SKIP extra"; do
|
|
338
|
+
vh10 blocking "$case10"
|
|
339
|
+
case "$VH10_OUT" in *rc=0*) bad "blocking posture must exit non-zero for persisted verdict '$case10'" ;; *) ok ;; esac
|
|
340
|
+
[ "$VH10_V" = "BLOCK" ] && case "$VH10_R" in *missing/invalid*) true ;; *) false ;; esac && ok || bad "blocking posture must persist BLOCK + missing/invalid reason for '$case10' (got '$VH10_V' / '$VH10_R')"
|
|
341
|
+
vh10 advisory "$case10"
|
|
342
|
+
case "$VH10_OUT" in *rc=0*) ok ;; *) bad "advisory posture must not block for persisted verdict '$case10'" ;; esac
|
|
343
|
+
[ "$VH10_V" = "BLOCK" ] && case "$VH10_R" in *advisory*missing/invalid*) true ;; *) false ;; esac && ok || bad "advisory posture must record BLOCK (advisory) missing/invalid for '$case10' (got '$VH10_V' / '$VH10_R')"
|
|
344
|
+
done
|
|
345
|
+
vh10 blocking "-" "bogus"
|
|
346
|
+
case "$VH10_OUT" in *rc=0*) bad "an unrecognised in-env verdict must fail closed under blocking posture" ;; *) ok ;; esac
|
|
347
|
+
vh10 blocking "PASS"
|
|
348
|
+
case "$VH10_OUT" in *rc=0*) [ "$VH10_V" = "PASS" ] && ok || bad "a valid persisted PASS must stay PASS" ;; *) bad "a valid persisted PASS must not block" ;; esac
|
|
349
|
+
vh10 blocking "SKIP"
|
|
350
|
+
case "$VH10_OUT" in *rc=0*) [ "$VH10_V" = "SKIP" ] && ok || bad "a valid persisted SKIP must stay SKIP" ;; *) bad "a valid persisted SKIP must not block" ;; esac
|
|
291
351
|
else echo "review-pr-staging-scope.test.sh: git missing, delta section skipped"; fi
|
|
292
352
|
echo "review-pr-staging-scope.test.sh: passed=$PASS failed=$FAILN"
|
|
293
353
|
[ "$FAILN" -eq 0 ]
|