@metasession.co/devaudit-cli 0.1.76 → 0.3.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/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/sdlc/files/_common/1-plan-requirement.md +6 -456
- package/sdlc/files/_common/2-implement-and-test.md +6 -294
- package/sdlc/files/_common/3-compile-evidence.md +6 -809
- package/sdlc/files/_common/4-submit-for-review.md +7 -372
- package/sdlc/files/_common/5-deploy-main.md +6 -265
- package/sdlc/files/_common/implementing-an-sdlc-issue.md +7 -434
- package/sdlc/files/_common/scripts/close-out-release.sh +8 -1
- package/sdlc/files/_common/scripts/close-out-release.test.sh +59 -0
- package/sdlc/files/_common/scripts/derive-release-version.sh +2 -1
- package/sdlc/files/_common/scripts/derive-release-version.test.sh +29 -0
- package/sdlc/files/_common/scripts/validate-test-summary.sh +146 -0
- package/sdlc/files/_common/scripts/validate-test-summary.test.sh +268 -0
- package/sdlc/files/_common/skills/e2e-test-engineer/SKILL.md +28 -2
- package/sdlc/files/_common/skills/sdlc-implementer/SKILL.md +21 -2
- package/sdlc/files/ci/ci.yml.template +36 -1
- package/sdlc/files/ci/compliance-validation.yml.template +3 -0
- package/sdlc/files/stacks/node/hooks/pre-push +19 -0
- package/sdlc/package.json +21 -0
- package/sdlc/src/bin/devaudit-sdlc.js +95 -0
- package/sdlc/src/blueprints/1-plan-requirement.raw.md +464 -0
- package/sdlc/src/blueprints/2-implement-and-test.raw.md +314 -0
- package/sdlc/src/blueprints/3-compile-evidence.raw.md +817 -0
- package/sdlc/src/blueprints/4-submit-for-review.raw.md +379 -0
- package/sdlc/src/blueprints/5-deploy-main.raw.md +273 -0
- package/sdlc/src/blueprints/implementing-an-sdlc-issue.raw.md +441 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# validate-test-summary.sh — Validates test-execution-summary.md content.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./scripts/validate-test-summary.sh [base-branch]
|
|
6
|
+
#
|
|
7
|
+
# Checks that test-execution-summary.md files for in-scope REQs do not
|
|
8
|
+
# contain invalid gate states like "deferred" or "Deferred to CI".
|
|
9
|
+
# E2E gate results must be one of: PASS, FAIL, NOT_NEEDED (with reason),
|
|
10
|
+
# or SKIPPED (with operator-approved rationale). "Deferred to CI" is not
|
|
11
|
+
# a valid SDLC state (devaudit-installer#240).
|
|
12
|
+
#
|
|
13
|
+
# Designed to run as a CI job on PRs to main, alongside
|
|
14
|
+
# validate-compliance-artifacts.sh.
|
|
15
|
+
#
|
|
16
|
+
# Install: cp this file to your project's scripts/ directory && chmod +x scripts/validate-test-summary.sh
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
BASE_BRANCH="${1:-origin/main}"
|
|
21
|
+
EXIT_CODE=0
|
|
22
|
+
|
|
23
|
+
echo "=== Test Execution Summary Validation ==="
|
|
24
|
+
echo "Comparing: $BASE_BRANCH...HEAD"
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
# Extract the requirement(s) THIS PR implements — same logic as
|
|
28
|
+
# validate-compliance-artifacts.sh
|
|
29
|
+
PR_MSGS=$(git log "$BASE_BRANCH"..HEAD --format='%B' || true)
|
|
30
|
+
REQUIREMENTS=$(
|
|
31
|
+
{
|
|
32
|
+
printf '%s\n' "$PR_MSGS" | grep -oP '\[\KREQ-\d{3,}(?=\])' || true
|
|
33
|
+
printf '%s\n' "$PR_MSGS" | grep -iP '^\s*Ref:' | grep -oP 'REQ-\d{3,}' || true
|
|
34
|
+
} | sort -u
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if [ -z "$REQUIREMENTS" ]; then
|
|
38
|
+
echo "No REQ-XXX references found in PR commits — skipping test summary validation."
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Requirements found in PR commits: $REQUIREMENTS"
|
|
43
|
+
echo ""
|
|
44
|
+
|
|
45
|
+
for REQ in $REQUIREMENTS; do
|
|
46
|
+
echo "--- Checking $REQ ---"
|
|
47
|
+
|
|
48
|
+
SUMMARY="compliance/evidence/$REQ/test-execution-summary.md"
|
|
49
|
+
|
|
50
|
+
if [ ! -f "$SUMMARY" ]; then
|
|
51
|
+
echo " INFO: $SUMMARY not found — skipping (validate-compliance-artifacts.sh checks existence)"
|
|
52
|
+
echo ""
|
|
53
|
+
continue
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
echo " OK: test-execution-summary.md exists"
|
|
57
|
+
|
|
58
|
+
# Check 1: Reject "deferred" (case-insensitive) anywhere in the file
|
|
59
|
+
if grep -qi 'deferred' "$SUMMARY"; then
|
|
60
|
+
echo " ERROR: 'deferred' found in $SUMMARY — 'Deferred to CI' is not a valid gate state (devaudit-installer#238, #240)."
|
|
61
|
+
echo " E2E gate results must be: PASS, FAIL, NOT_NEEDED (with reason), or SKIPPED (with operator-approved rationale)."
|
|
62
|
+
echo " Offending lines:"
|
|
63
|
+
grep -in 'deferred' "$SUMMARY" | sed 's/^/ /'
|
|
64
|
+
EXIT_CODE=1
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Check 2: Reject "browsers not installed" as a gate outcome
|
|
68
|
+
if grep -qi 'browsers not installed' "$SUMMARY"; then
|
|
69
|
+
echo " ERROR: 'browsers not installed' found in $SUMMARY — this is an environment setup issue, not a gate state (devaudit-installer#238, #240)."
|
|
70
|
+
echo " Install browsers with 'npx playwright install' and re-run the E2E suite."
|
|
71
|
+
echo " Offending lines:"
|
|
72
|
+
grep -in 'browsers not installed' "$SUMMARY" | sed 's/^/ /'
|
|
73
|
+
EXIT_CODE=1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Check 3: Reject "Deferred to CI" explicitly (catches the exact pattern from #238)
|
|
77
|
+
if grep -qi 'deferred to ci' "$SUMMARY"; then
|
|
78
|
+
echo " ERROR: 'Deferred to CI' found in $SUMMARY — CI is a safety net, not a replacement for local E2E execution (devaudit-installer#238, #240)."
|
|
79
|
+
echo " Offending lines:"
|
|
80
|
+
grep -in 'deferred to ci' "$SUMMARY" | sed 's/^/ /'
|
|
81
|
+
EXIT_CODE=1
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Check 4: Validate E2E gate result in the gate results table
|
|
85
|
+
# Look for lines matching "| E2E ... | <result> |" pattern
|
|
86
|
+
E2E_LINES=$(grep -i '| *e2e' "$SUMMARY" 2>/dev/null || true)
|
|
87
|
+
if [ -n "$E2E_LINES" ]; then
|
|
88
|
+
while IFS= read -r line; do
|
|
89
|
+
# Extract the result column (2nd | field after "E2E")
|
|
90
|
+
RESULT=$(echo "$line" | grep -oP '\|\s*\K[^|]+(?=\s*\|)' | head -2 | tail -1 | xargs || true)
|
|
91
|
+
if [ -n "$RESULT" ]; then
|
|
92
|
+
RESULT_LOWER=$(echo "$RESULT" | tr '[:upper:]' '[:lower:]')
|
|
93
|
+
# Skip empty or separator lines
|
|
94
|
+
if [ -z "$RESULT_LOWER" ] || echo "$RESULT_LOWER" | grep -q '^[|-]*$'; then
|
|
95
|
+
continue
|
|
96
|
+
fi
|
|
97
|
+
# Check for invalid "deferred" state
|
|
98
|
+
if echo "$RESULT_LOWER" | grep -qi 'defer'; then
|
|
99
|
+
echo " ERROR: E2E gate result '$RESULT' is not valid — 'deferred' is not a gate state (devaudit-installer#240)"
|
|
100
|
+
EXIT_CODE=1
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
done <<< "$E2E_LINES"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Check 5: If E2E result is SKIPPED or NOT_NEEDED, require a rationale on the same line
|
|
107
|
+
if grep -qi '| *e2e.*| *skipped' "$SUMMARY" 2>/dev/null; then
|
|
108
|
+
SKIPPED_LINE=$(grep -i '| *e2e.*| *skipped' "$SUMMARY" | head -1)
|
|
109
|
+
# Rationale can be in the details column (after the result column) or inline with the state
|
|
110
|
+
if echo "$SKIPPED_LINE" | grep -qi 'skipped.*[—–-].*\|| *skipped.*|.*[a-z]'; then
|
|
111
|
+
echo " OK: E2E gate result is SKIPPED with rationale"
|
|
112
|
+
else
|
|
113
|
+
echo " ERROR: E2E gate result is SKIPPED but no rationale provided. Add a reason in the Details column (e.g. 'SKIPPED — API-only change, no UI surface (operator-approved)') (devaudit-installer#240)"
|
|
114
|
+
EXIT_CODE=1
|
|
115
|
+
fi
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if grep -qi '| *e2e.*| *not_needed' "$SUMMARY" 2>/dev/null; then
|
|
119
|
+
NN_LINE=$(grep -i '| *e2e.*| *not_needed' "$SUMMARY" | head -1)
|
|
120
|
+
if echo "$NN_LINE" | grep -qi 'not_needed.*[—–-].*\|| *not_needed.*|.*[a-z]'; then
|
|
121
|
+
echo " OK: E2E gate result is NOT_NEEDED with rationale"
|
|
122
|
+
else
|
|
123
|
+
echo " ERROR: E2E gate result is NOT_NEEDED but no rationale provided. Add a reason in the Details column (e.g. 'NOT_NEEDED — schema-only change, no UI surface') (devaudit-installer#240)"
|
|
124
|
+
EXIT_CODE=1
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
# Check 6: Reject "E2E deferred to CI" in final assessment lines
|
|
129
|
+
if grep -qi 'e2e deferred\|e2e.*deferred to ci' "$SUMMARY" 2>/dev/null; then
|
|
130
|
+
echo " ERROR: 'E2E deferred' language found in final assessment — 'deferred' is not a valid gate state (devaudit-installer#240)"
|
|
131
|
+
echo " Offending lines:"
|
|
132
|
+
grep -in 'e2e deferred\|e2e.*deferred to ci' "$SUMMARY" | sed 's/^/ /'
|
|
133
|
+
EXIT_CODE=1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
echo ""
|
|
137
|
+
done
|
|
138
|
+
|
|
139
|
+
echo ""
|
|
140
|
+
if [ $EXIT_CODE -eq 0 ]; then
|
|
141
|
+
echo "=== All test execution summary checks passed ==="
|
|
142
|
+
else
|
|
143
|
+
echo "=== FAILED: Invalid gate states found in test execution summary ==="
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
exit $EXIT_CODE
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-test-summary.test.sh — Tests for validate-test-summary.sh.
|
|
3
|
+
#
|
|
4
|
+
# Builds a throwaway git repo per case, creates compliance evidence with
|
|
5
|
+
# crafted test-execution-summary.md files, runs the validator, and asserts
|
|
6
|
+
# on the exit code. Hermetic: runs inside mktemp'd directories that are
|
|
7
|
+
# torn down at the end.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# ./scripts/validate-test-summary.test.sh
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
15
|
+
HELPER="$SCRIPT_DIR/validate-test-summary.sh"
|
|
16
|
+
[ -x "$HELPER" ] || chmod +x "$HELPER"
|
|
17
|
+
|
|
18
|
+
PASS=0
|
|
19
|
+
FAIL=0
|
|
20
|
+
|
|
21
|
+
WORK=$(mktemp -d)
|
|
22
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
23
|
+
|
|
24
|
+
# Build a fresh git fixture with a commit referencing REQ-XXX.
|
|
25
|
+
# Sets up compliance/evidence/REQ-XXX/ directory.
|
|
26
|
+
# $1 = dir, $2 = REQ ID, $3 = summary file content (via stdin)
|
|
27
|
+
make_fixture() {
|
|
28
|
+
local dir="$1" req="$2"
|
|
29
|
+
rm -rf "$dir"
|
|
30
|
+
mkdir -p "$dir"
|
|
31
|
+
cd "$dir"
|
|
32
|
+
git init -q --initial-branch=main
|
|
33
|
+
git config user.email "test@example.com"
|
|
34
|
+
git config user.name "test"
|
|
35
|
+
|
|
36
|
+
# Create a base branch and a feature branch with a REQ commit
|
|
37
|
+
echo "x" > f.txt
|
|
38
|
+
git add f.txt
|
|
39
|
+
git commit -q -m "initial"
|
|
40
|
+
|
|
41
|
+
git checkout -q -b feature
|
|
42
|
+
echo "y" > g.txt
|
|
43
|
+
git add g.txt
|
|
44
|
+
git commit -q -m "feat: [${req}] test change
|
|
45
|
+
|
|
46
|
+
Ref: ${req}"
|
|
47
|
+
|
|
48
|
+
# Create evidence directory and RTM row
|
|
49
|
+
mkdir -p "compliance/evidence/${req}"
|
|
50
|
+
echo "| ${req} | #999 | HIGH | compliance/evidence/${req}/ | TESTED - PENDING SIGN-OFF | TBD | -- |" > compliance/RTM.md
|
|
51
|
+
git add compliance/RTM.md
|
|
52
|
+
git commit -q -m "docs: add RTM row for ${req}"
|
|
53
|
+
|
|
54
|
+
# Write the test-execution-summary.md from stdin
|
|
55
|
+
cat > "compliance/evidence/${req}/test-execution-summary.md"
|
|
56
|
+
|
|
57
|
+
# Stay on feature branch so the validator sees the diff from main
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Run the validator against the fixture, capture exit code.
|
|
61
|
+
# $1 = fixture dir
|
|
62
|
+
run_validator() {
|
|
63
|
+
local dir="$1"
|
|
64
|
+
cd "$dir"
|
|
65
|
+
local exit_code=0
|
|
66
|
+
bash "$HELPER" main > /tmp/validate-test-summary-output.txt 2>&1 || exit_code=$?
|
|
67
|
+
echo "$exit_code"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
assert_exit() {
|
|
71
|
+
local desc="$1" want="$2" got="$3"
|
|
72
|
+
if [ "$got" = "$want" ]; then
|
|
73
|
+
echo " PASS: $desc"
|
|
74
|
+
PASS=$((PASS + 1))
|
|
75
|
+
else
|
|
76
|
+
echo " FAIL: $desc"
|
|
77
|
+
echo " want exit: $want"
|
|
78
|
+
echo " got exit: $got"
|
|
79
|
+
cat /tmp/validate-test-summary-output.txt | sed 's/^/ /'
|
|
80
|
+
FAIL=$((FAIL + 1))
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
echo "=== validate-test-summary.sh tests ==="
|
|
85
|
+
|
|
86
|
+
# --- Case 1: Clean summary with PASS — should pass ---
|
|
87
|
+
D1="$WORK/case1"
|
|
88
|
+
make_fixture "$D1" "REQ-001" << 'EOF'
|
|
89
|
+
# Test Execution Summary — REQ-001
|
|
90
|
+
|
|
91
|
+
## Test design
|
|
92
|
+
|
|
93
|
+
**Layers planned:** unit, e2e
|
|
94
|
+
**Layers covered:** unit ✓, e2e ✓
|
|
95
|
+
|
|
96
|
+
## Gate Results
|
|
97
|
+
|
|
98
|
+
| Gate | Result | Details |
|
|
99
|
+
| ---------------- | -------- | -------------------- |
|
|
100
|
+
| TypeScript | PASS | 0 errors |
|
|
101
|
+
| E2E Tests | PASS | All specs green |
|
|
102
|
+
| Unit Tests | PASS | 42 passed |
|
|
103
|
+
|
|
104
|
+
**Final assessment:** All gates passed.
|
|
105
|
+
EOF
|
|
106
|
+
EXIT1=$(run_validator "$D1")
|
|
107
|
+
assert_exit "clean summary with PASS — should pass" 0 "$EXIT1"
|
|
108
|
+
|
|
109
|
+
# --- Case 2: Summary with 'deferred' — should fail ---
|
|
110
|
+
D2="$WORK/case2"
|
|
111
|
+
make_fixture "$D2" "REQ-002" << 'EOF'
|
|
112
|
+
# Test Execution Summary — REQ-002
|
|
113
|
+
|
|
114
|
+
## Test design
|
|
115
|
+
|
|
116
|
+
**Layers covered:** unit ✓, e2e deferred
|
|
117
|
+
|
|
118
|
+
## Gate Results
|
|
119
|
+
|
|
120
|
+
| Gate | Result | Details |
|
|
121
|
+
| ---------------- | -------- | ---------------------------------------- |
|
|
122
|
+
| E2E Tests | DEFERRED | Playwright browsers not installed locally |
|
|
123
|
+
|
|
124
|
+
**Final assessment:** All local gates passed. E2E deferred to CI.
|
|
125
|
+
EOF
|
|
126
|
+
EXIT2=$(run_validator "$D2")
|
|
127
|
+
assert_exit "summary with 'deferred' — should fail" 1 "$EXIT2"
|
|
128
|
+
|
|
129
|
+
# --- Case 3: Summary with 'Deferred to CI' — should fail ---
|
|
130
|
+
D3="$WORK/case3"
|
|
131
|
+
make_fixture "$D3" "REQ-003" << 'EOF'
|
|
132
|
+
# Test Execution Summary — REQ-003
|
|
133
|
+
|
|
134
|
+
**Final assessment:** All gates passed. E2E Deferred to CI.
|
|
135
|
+
EOF
|
|
136
|
+
EXIT3=$(run_validator "$D3")
|
|
137
|
+
assert_exit "summary with 'Deferred to CI' — should fail" 1 "$EXIT3"
|
|
138
|
+
|
|
139
|
+
# --- Case 4: Summary with 'browsers not installed' — should fail ---
|
|
140
|
+
D4="$WORK/case4"
|
|
141
|
+
make_fixture "$D4" "REQ-004" << 'EOF'
|
|
142
|
+
# Test Execution Summary — REQ-004
|
|
143
|
+
|
|
144
|
+
## Gate Results
|
|
145
|
+
|
|
146
|
+
| Gate | Result | Details |
|
|
147
|
+
| ---------------- | -------- | ---------------------------------------- |
|
|
148
|
+
| E2E Tests | SKIPPED | Playwright browsers not installed locally |
|
|
149
|
+
|
|
150
|
+
**Final assessment:** E2E skipped — browsers not installed.
|
|
151
|
+
EOF
|
|
152
|
+
EXIT4=$(run_validator "$D4")
|
|
153
|
+
assert_exit "summary with 'browsers not installed' — should fail" 1 "$EXIT4"
|
|
154
|
+
|
|
155
|
+
# --- Case 5: Summary with NOT_NEEDED and rationale — should pass ---
|
|
156
|
+
D5="$WORK/case5"
|
|
157
|
+
make_fixture "$D5" "REQ-005" << 'EOF'
|
|
158
|
+
# Test Execution Summary — REQ-005
|
|
159
|
+
|
|
160
|
+
## Gate Results
|
|
161
|
+
|
|
162
|
+
| Gate | Result | Details |
|
|
163
|
+
| ---------------- | ------------ | ------------------------------------------ |
|
|
164
|
+
| E2E Tests | NOT_NEEDED | Schema-only change, no UI surface |
|
|
165
|
+
|
|
166
|
+
**Final assessment:** All gates passed. E2E not needed for this REQ.
|
|
167
|
+
EOF
|
|
168
|
+
EXIT5=$(run_validator "$D5")
|
|
169
|
+
assert_exit "summary with NOT_NEEDED and rationale — should pass" 0 "$EXIT5"
|
|
170
|
+
|
|
171
|
+
# --- Case 6: Summary with SKIPPED and rationale — should pass ---
|
|
172
|
+
D6="$WORK/case6"
|
|
173
|
+
make_fixture "$D6" "REQ-006" << 'EOF'
|
|
174
|
+
# Test Execution Summary — REQ-006
|
|
175
|
+
|
|
176
|
+
## Gate Results
|
|
177
|
+
|
|
178
|
+
| Gate | Result | Details |
|
|
179
|
+
| ---------------- | ------------ | ------------------------------------------ |
|
|
180
|
+
| E2E Tests | SKIPPED | API-only change, no UI surface (operator-approved) |
|
|
181
|
+
|
|
182
|
+
**Final assessment:** All gates passed. E2E skipped — API-only change.
|
|
183
|
+
EOF
|
|
184
|
+
EXIT6=$(run_validator "$D6")
|
|
185
|
+
assert_exit "summary with SKIPPED and rationale — should pass" 0 "$EXIT6"
|
|
186
|
+
|
|
187
|
+
# --- Case 7: Summary with SKIPPED but no rationale — should fail ---
|
|
188
|
+
D7="$WORK/case7"
|
|
189
|
+
make_fixture "$D7" "REQ-007" << 'EOF'
|
|
190
|
+
# Test Execution Summary — REQ-007
|
|
191
|
+
|
|
192
|
+
## Gate Results
|
|
193
|
+
|
|
194
|
+
| Gate | Result | Details |
|
|
195
|
+
| ---------------- | ------------ | ---------- |
|
|
196
|
+
| E2E Tests | SKIPPED | |
|
|
197
|
+
|
|
198
|
+
**Final assessment:** All gates passed.
|
|
199
|
+
EOF
|
|
200
|
+
EXIT7=$(run_validator "$D7")
|
|
201
|
+
assert_exit "summary with SKIPPED but no rationale — should fail" 1 "$EXIT7"
|
|
202
|
+
|
|
203
|
+
# --- Case 8: No REQ references — should pass (skip) ---
|
|
204
|
+
D8="$WORK/case8"
|
|
205
|
+
rm -rf "$D8"
|
|
206
|
+
mkdir -p "$D8"
|
|
207
|
+
cd "$D8"
|
|
208
|
+
git init -q --initial-branch=main
|
|
209
|
+
git config user.email "test@example.com"
|
|
210
|
+
git config user.name "test"
|
|
211
|
+
echo "x" > f.txt
|
|
212
|
+
git add f.txt
|
|
213
|
+
git commit -q -m "initial"
|
|
214
|
+
git checkout -q -b feature
|
|
215
|
+
echo "y" > g.txt
|
|
216
|
+
git add g.txt
|
|
217
|
+
git commit -q -m "docs: update README"
|
|
218
|
+
EXIT8=$(run_validator "$D8")
|
|
219
|
+
assert_exit "no REQ references — should pass (skip)" 0 "$EXIT8"
|
|
220
|
+
|
|
221
|
+
# --- Case 9: No test-execution-summary.md — should pass (skip) ---
|
|
222
|
+
D9="$WORK/case9"
|
|
223
|
+
make_fixture "$D9" "REQ-009" << 'EOF'
|
|
224
|
+
# placeholder
|
|
225
|
+
EOF
|
|
226
|
+
rm "$D9/compliance/evidence/REQ-009/test-execution-summary.md"
|
|
227
|
+
EXIT9=$(run_validator "$D9")
|
|
228
|
+
assert_exit "no test-execution-summary.md — should pass (skip)" 0 "$EXIT9"
|
|
229
|
+
|
|
230
|
+
# --- Case 10: Summary with 'e2e deferred' in final assessment — should fail ---
|
|
231
|
+
D10="$WORK/case10"
|
|
232
|
+
make_fixture "$D10" "REQ-010" << 'EOF'
|
|
233
|
+
# Test Execution Summary — REQ-010
|
|
234
|
+
|
|
235
|
+
## Gate Results
|
|
236
|
+
|
|
237
|
+
| Gate | Result | Details |
|
|
238
|
+
| ---------------- | -------- | --------------- |
|
|
239
|
+
| E2E Tests | PASS | All specs green |
|
|
240
|
+
|
|
241
|
+
**Final assessment:** All gates passed. E2E deferred to CI for critical tier.
|
|
242
|
+
EOF
|
|
243
|
+
EXIT10=$(run_validator "$D10")
|
|
244
|
+
assert_exit "summary with 'e2e deferred' in final assessment — should fail" 1 "$EXIT10"
|
|
245
|
+
|
|
246
|
+
# --- Case 11: NOT_NEEDED without rationale — should fail ---
|
|
247
|
+
D11="$WORK/case11"
|
|
248
|
+
make_fixture "$D11" "REQ-011" << 'EOF'
|
|
249
|
+
# Test Execution Summary — REQ-011
|
|
250
|
+
|
|
251
|
+
## Gate Results
|
|
252
|
+
|
|
253
|
+
| Gate | Result | Details |
|
|
254
|
+
| ---------------- | ------------ | ---------- |
|
|
255
|
+
| E2E Tests | NOT_NEEDED | |
|
|
256
|
+
|
|
257
|
+
**Final assessment:** All gates passed.
|
|
258
|
+
EOF
|
|
259
|
+
EXIT11=$(run_validator "$D11")
|
|
260
|
+
assert_exit "summary with NOT_NEEDED but no rationale — should fail" 1 "$EXIT11"
|
|
261
|
+
|
|
262
|
+
echo ""
|
|
263
|
+
echo "=== Summary: $PASS pass / $FAIL fail ==="
|
|
264
|
+
|
|
265
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
266
|
+
exit 1
|
|
267
|
+
fi
|
|
268
|
+
exit 0
|
|
@@ -241,8 +241,34 @@ Halt and report the gap to the user:
|
|
|
241
241
|
|
|
242
242
|
Do **not** proceed to Phase 6 until all gaps are resolved. The user may choose to skip an AC (e.g. API-only, transport-only) — that's valid, but it must be an explicit decision recorded in the test-execution-summary, not an omission.
|
|
243
243
|
|
|
244
|
+
**Write the evidence-wiring sentinel (devaudit-installer#226).** After all Phase 5½ checks pass (all `@requirement`, `evidenceShot()`, and `tagTest()` calls verified), write a `.e2e-evidence-wired` sentinel file in the repo root so the pre-push hook and `sdlc-implementer` Phase 2 step 5b can verify evidence wiring was validated:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
echo "WIRED $(date -u +%Y-%m-%dT%H:%M:%SZ) REQ-XXX" > .e2e-evidence-wired
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
If the user explicitly skipped an AC (e.g. API-only), note it in the sentinel:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
echo "WIRED $(date -u +%Y-%m-%dT%H:%M:%SZ) REQ-XXX (AC3 skipped — API-only)" > .e2e-evidence-wired
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The file is gitignored and never committed — it's a local-only signal that evidence wiring was validated in this working directory.
|
|
257
|
+
|
|
244
258
|
### Phase 6 — Execute and report
|
|
245
259
|
|
|
260
|
+
**Pre-flight: browser availability (devaudit-installer#238).** Before running the suite, verify Playwright browsers are installed:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npx playwright install --dry-run 2>&1 | grep -q "is already installed" || npx playwright install
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
If the install fails (e.g. missing system dependencies on Linux), run `npx playwright install --with-deps` (requires sudo on some systems — ask the operator). Do not defer E2E execution to CI because browsers are not installed. Installing browsers takes ~30 seconds; deferring breaks the evidence trail.
|
|
267
|
+
|
|
268
|
+
**Do not defer E2E to CI (devaudit-installer#238).** If browsers are not installed, install them. If the dev server will not start, debug it. If the database is not running, start it. CI is a safety net, not a replacement for local E2E execution. The `.e2e-gate-passed` sentinel must be written by a local run — skipping it by deferring to CI breaks the evidence-completeness chain and causes the evidence-completeness gate (#237) to fire with false negatives.
|
|
269
|
+
|
|
270
|
+
**Gate state vocabulary (devaudit-installer#240).** In `test-execution-summary.md`, E2E gate results must be one of: `PASS`, `FAIL`, `NOT_NEEDED` (with reason), or `SKIPPED` (with operator-approved rationale). The word "deferred" must never appear in `test-execution-summary.md` — not as a gate state, not in prose, not in final assessment. The CI validator (`validate-test-summary.sh`) rejects any file containing "deferred" anywhere. If E2E was not run locally, record it as `SKIPPED` with the reason and flag it as a gate failure for the reviewer. Do not write "E2E deferred to CI" or "Playwright browsers not installed locally" — these are environment issues, not gate states.
|
|
271
|
+
|
|
246
272
|
Run the suite. Strategy:
|
|
247
273
|
|
|
248
274
|
1. **Iterate focused.** During fix-and-verify, run only the failing specs (`--grep`, spec-path args, or a CI input that scopes to a subset). Cycle time is what makes the loop tractable — full regression for every iteration burns CI budget and operator patience. Expect to loop: fix → focused run → fix → focused run, many times.
|
|
@@ -404,8 +430,8 @@ Wrap up with a summary the user can drop into the PR or ticket:
|
|
|
404
430
|
**Then feed the test-design record (devaudit#50).** The Stage 3 `test-execution-summary.md` (generated per `3-compile-evidence.md` Step 1a) carries a `## Test design` section at the top. Before Stage 3 finalises the file, populate that section with the design-time decisions this skill made, so the SDLC has a recorded trace that scope was *decided*, not implicit:
|
|
405
431
|
|
|
406
432
|
- **Layers planned** — which of `unit | integration | e2e | visual | manual` applied to this REQ
|
|
407
|
-
- **Layers covered** — same list with ✓ or `
|
|
408
|
-
- **
|
|
433
|
+
- **Layers covered** — same list with ✓ or `NOT_NEEDED` (with reason)
|
|
434
|
+
- **Exemptions** — explicit one-line rationale per exempt layer (`e2e NOT_NEEDED — schema-only, no UI yet` rather than silent absence). Do not use "deferred" as a gate state — it is not a valid SDLC state (devaudit-installer#240). The CI validator (`validate-test-summary.sh`) will reject any summary containing "deferred".
|
|
409
435
|
- **Skill invocation** — _"`e2e-test-engineer` invoked on turn N during Phase 2"_, with a turn pointer the reviewer can verify against the chat transcript
|
|
410
436
|
|
|
411
437
|
If you authored or modified `e2e/**/*.spec.ts` directly without invoking this skill, that's a delegation gap — the `sdlc-implementer` Phase 2 audit (devaudit#132) will catch it before Phase 3. The honest record is: the skill ran (or didn't), the layers were chosen for stated reasons, and the test-execution-summary attribution points back at the chat turn where the decision happened.
|
|
@@ -265,7 +265,7 @@ Runs **first**, before any `REQ-XXX` is assigned. It decides which of the six ch
|
|
|
265
265
|
3. **Announce a "Workflow Decision" block** (template below): change-type, commit-type, whether a `REQ-XXX` is needed, risk class, which stages/gates run, which approvals the **operator** must perform (UAT four-eyes, Production approval), and what is **skipped**.
|
|
266
266
|
4. **Pause policy — pause-when-it-matters.** Pause for explicit confirmation on **tracked / heavier** paths, or when classification is **ambiguous**; **announce-and-auto-proceed** on trivial / housekeeping. The operator can always reclassify ("treat this as housekeeping" / "this is HIGH risk").
|
|
267
267
|
5. **Route — and stay on to completion.** A route is a choice of _which workflow to drive_, never a hand-off that abandons the operator. Whatever the path, the skill keeps guiding step by step until no further action is required (typically: merged).
|
|
268
|
-
- **tracked** (feature / bug fix / refactor / perf) → continue into Phase 1 below (full Stages 1–5). **Write the skill-invocation sentinel** (devaudit-installer#226): `
|
|
268
|
+
- **tracked** (feature / bug fix / refactor / perf) → continue into Phase 1 below (full Stages 1–5). **Write the skill-invocation sentinel** (devaudit-installer#226): `npx devaudit-sdlc --phase=issue`. This invokes the v0.2.0 CLI engine, which appends a JSON phase record to `.sdlc-implementer-invoked` (a gitignored, local-only file). The pre-push hook checks for this file's existence before allowing `feat`/`fix`/`refactor`/`perf` commits to be pushed. Without this sentinel, the pre-push hook will refuse the push and `validate-commits.sh` in CI will flag missing RTM provenance. Each subsequent phase transition (Phase 1, 2, 3, 4, 5) must also invoke `npx devaudit-sdlc --phase=<N>` to append its phase record to the sentinel.
|
|
269
269
|
- **housekeeping / trivial** → drive the **Lightweight path** below to completion. No `REQ-XXX`, no RTM row, no evidence pack, no portal release approvals — but the skill still branches, runs the gates, opens the PR, and walks the operator through review → merge.
|
|
270
270
|
- **compliance-doc-only** → drive the same Lightweight path as a docs push (or PR, per the project's flow) referencing the **existing** `REQ-XXX`: no new requirement and no quality-gate ceremony, but driven through to merge.
|
|
271
271
|
6. **Write labels back.** Apply the inferred `type:*` / `risk:*` labels so the issue ends up labelled — `gh label create <label> --force` to ensure the label exists (idempotent; no failure if a label-seeding step never ran), then `gh issue edit <N> --add-label <label>`. Future triage is then a glance.
|
|
@@ -409,6 +409,15 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
|
|
|
409
409
|
- **Requirements deviation** (an AC is wrong, incomplete, or missing) — trigger the [requirements gap flow](#requirements-gap-flow-devaudit-installer212). Do NOT just note it as a plan deviation. The AC table must be updated, `requirements-aligner` must be re-invoked to re-check SRS alignment, and the RTM must be updated.
|
|
410
410
|
|
|
411
411
|
The classification question: "Did the implementation deviate from the plan's approach (how to build it), or did the plan's requirements deviate from reality (what to build)?" If the former, note and continue. If the latter, trigger the requirements gap flow.
|
|
412
|
+
|
|
413
|
+
4b. **Reconcile test-plan.md file paths with actual files (devaudit-installer#241).** After writing/updating tests (both unit and E2E), diff the actual test file paths against `compliance/evidence/REQ-XXX/test-plan.md`. The test plan was authored during Stage 1 with predicted file paths — during implementation, tests are often added to existing files instead of creating new ones. This is a natural drift, but it must be reconciled before committing so `validate-compliance-artifacts.sh` doesn't fail at PR time.
|
|
414
|
+
|
|
415
|
+
For each file path referenced in `test-plan.md`:
|
|
416
|
+
- If the file exists on disk → OK, no action needed.
|
|
417
|
+
- If the file does not exist → check whether a test covering the same AC was added to a different file. If so, update `test-plan.md` to reference the actual file path.
|
|
418
|
+
- If the file does not exist and no equivalent test was found → **HALT**: "test-plan.md references <file> but no test file exists and no equivalent test covering the same AC was found. Either create the test file, update test-plan.md to point to the actual test file, or remove the entry if the AC is no longer relevant."
|
|
419
|
+
|
|
420
|
+
Commit the updated `test-plan.md` alongside the test code. This is a file-path reconciliation — it does not change the AC table (that's the step 5b plan ↔ test-scope AC consistency check, which is separate and checks AC drift, not file-path drift).
|
|
412
421
|
5. **Run gates locally, cheap-first.** The gates are not equivalent-cost — `npm run lint` is seconds, `npx playwright test` is 30–60 minutes. Iterate on the fast gates; spend the e2e cost once.
|
|
413
422
|
|
|
414
423
|
**Fast gates** (run on every change, ideally pre-commit):
|
|
@@ -428,7 +437,9 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
|
|
|
428
437
|
git diff --name-only "$INTEGRATION_BRANCH"...HEAD -- 'app/**/*.tsx' 'src/**/*.tsx' 'pages/**/*.tsx' 'app/**/*.jsx' 'src/**/*.jsx' 'pages/**/*.jsx'
|
|
429
438
|
```
|
|
430
439
|
|
|
431
|
-
- **If UI-facing files are present:** check for `.e2e-gate-passed` sentinel file (written by `e2e-test-engineer` after a successful run) or `playwright-report/` directory with recent content. If neither exists, **HALT**: "E2E gate was not run. The change touches UI-facing files. Run `npx playwright test` (or invoke `e2e-test-engineer`) before committing. The pre-push hook will also block this push."
|
|
440
|
+
- **If UI-facing files are present:** check for `.e2e-gate-passed` sentinel file (written by `e2e-test-engineer` after a successful run) or `playwright-report/` directory with recent content. If neither exists, **HALT**: "E2E gate was not run. The change touches UI-facing files. Run `npx playwright test` (or invoke `e2e-test-engineer`) before committing. Do not defer to CI — install Playwright browsers with `npx playwright install` if needed. The pre-push hook will also block this push."
|
|
441
|
+
|
|
442
|
+
**Also check for `.e2e-evidence-wired` sentinel (devaudit-installer#226).** If `e2e/**/*.spec.ts` files were authored or modified, verify the `.e2e-evidence-wired` sentinel exists (written by `e2e-test-engineer` Phase 5½ after validating `tagTest()` and `evidenceShot()` calls). If missing, **HALT**: "Evidence wiring validation (Phase 5½) was not run. The change includes E2E spec files but no evidence wiring sentinel. Invoke `e2e-test-engineer` to validate `tagTest()` and `evidenceShot()` calls before committing. The pre-push hook will also block this push."
|
|
432
443
|
- **If no UI-facing files (API-only, config, docs):** skip the check. Note the exemption in the commit body: "E2E gate skipped — no UI-facing files in this change."
|
|
433
444
|
- **If `e2e-test-engineer` was invoked and determined e2e is not needed** (e.g. schema-only change): the skill writes `.e2e-gate-passed` with a `NOT_NEEDED` reason. The sentinel check passes. Note the exemption in the commit body: "E2E gate not needed — e2e-test-engineer assessed no UI surface (turn N)."
|
|
434
445
|
|
|
@@ -491,6 +502,14 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
|
|
|
491
502
|
- The nil report uploads as `incident_report` evidence via `compliance-evidence.yml`'s `upload_incident_report` function, flipping `ISO29119.3.5.4` to COVERED for clean releases.
|
|
492
503
|
- If incidents WERE closed, skip nil report generation — the populated incident report(s) from `incident-export.yml` serve as the evidence.
|
|
493
504
|
|
|
505
|
+
5b. **Validate test-execution-summary.md gate states (devaudit-installer#240).** Before uploading evidence, verify that `compliance/evidence/REQ-XXX/test-execution-summary.md` does not contain invalid gate states. Run:
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
bash scripts/validate-test-summary.sh origin/main
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
If the validator fails, fix the summary before proceeding. E2E gate results must be one of: `PASS`, `FAIL`, `NOT_NEEDED` (with reason), or `SKIPPED` (with operator-approved rationale). The word "deferred" must never appear in `test-execution-summary.md` — not as a gate state, not in prose, not in final assessment. "Deferred to CI" and "Playwright browsers not installed locally" are environment issues, not gate states. The CI validator (`validate-test-summary.sh`) will reject any summary containing "deferred" or "browsers not installed" on PRs to main.
|
|
512
|
+
|
|
494
513
|
6. **Organise artefacts** under `compliance/evidence/REQ-XXX/` with date-prefixed naming:
|
|
495
514
|
|
|
496
515
|
```
|
|
@@ -246,6 +246,8 @@ jobs:
|
|
|
246
246
|
DEVAUDIT_API_KEY: ${{ secrets.DEVAUDIT_API_KEY }}
|
|
247
247
|
steps:
|
|
248
248
|
- uses: actions/checkout@v6
|
|
249
|
+
with:
|
|
250
|
+
fetch-depth: 0
|
|
249
251
|
|
|
250
252
|
- name: Resolve DevAudit base URL
|
|
251
253
|
run: |
|
|
@@ -321,6 +323,14 @@ jobs:
|
|
|
321
323
|
if [ -z "$SINCE_REF" ]; then
|
|
322
324
|
SINCE_REF="HEAD~50"
|
|
323
325
|
fi
|
|
326
|
+
if ! git rev-parse --verify "$SINCE_REF" >/dev/null 2>&1; then
|
|
327
|
+
echo "::warning::Ref ${SINCE_REF} not found — falling back to HEAD~10"
|
|
328
|
+
SINCE_REF="HEAD~10"
|
|
329
|
+
fi
|
|
330
|
+
if ! git rev-parse --verify "$SINCE_REF" >/dev/null 2>&1; then
|
|
331
|
+
echo "::warning::Ref ${SINCE_REF} not found — skipping bundled changes"
|
|
332
|
+
exit 0
|
|
333
|
+
fi
|
|
324
334
|
echo "Scanning bundled changes since ${SINCE_REF} for ${VERSION}"
|
|
325
335
|
BUNDLED_FILE="compliance/pending-releases/BUNDLED-CHANGES-${VERSION}.md"
|
|
326
336
|
mkdir -p compliance/pending-releases
|
|
@@ -783,10 +793,35 @@ jobs:
|
|
|
783
793
|
# specs exist on disk. If specs are found but weren't run in
|
|
784
794
|
# this tier, emit a non-blocking warning instead of an error.
|
|
785
795
|
SPECS_ON_DISK=$(grep -rl --include='*.spec.ts' -e "@requirement ${REQ}" -e "tagTest.*${REQ}" -e "'${REQ}'" e2e/ 2>/dev/null | wc -l)
|
|
796
|
+
|
|
797
|
+
# devaudit-installer#237 — also scan unit test files for
|
|
798
|
+
# @requirement REQ-XXX annotations. A REQ with thorough unit
|
|
799
|
+
# test coverage but no E2E specs (legitimate for API-only or
|
|
800
|
+
# backend-only changes) should not be hard-blocked.
|
|
801
|
+
UNIT_TESTS_ON_DISK=$(grep -rl --include='*.test.ts' --include='*.test.tsx' -e "@requirement ${REQ}" -e "'${REQ}'" e2e/ __tests__/ tests/ src/ 2>/dev/null | wc -l)
|
|
802
|
+
|
|
803
|
+
# devaudit-installer#237 — check for test-execution-summary.md
|
|
804
|
+
# as a secondary signal. This is a human-authored document and
|
|
805
|
+
# weaker than machine-generated evidence, so it only converts
|
|
806
|
+
# a hard error to a warning when combined with unit test files
|
|
807
|
+
# on disk — never alone.
|
|
808
|
+
HAS_SUMMARY=false
|
|
809
|
+
if [ -f "compliance/evidence/${REQ}/test-execution-summary.md" ]; then
|
|
810
|
+
HAS_SUMMARY=true
|
|
811
|
+
fi
|
|
812
|
+
|
|
786
813
|
if [ "$SPECS_ON_DISK" -gt 0 ]; then
|
|
814
|
+
# Scenario B: E2E specs exist on disk but outside the smoke tier
|
|
787
815
|
echo "::warning::Evidence completeness gate: ${REQ} has zero tagged tests in this smoke run and zero per-AC screenshots, but ${SPECS_ON_DISK} spec file(s) on disk reference it (outside the smoke project). Evidence exists but was not executed in this CI tier. Consider running --project=critical or --grep \"${REQ}\" to capture evidence."
|
|
816
|
+
elif [ "$UNIT_TESTS_ON_DISK" -gt 0 ] && [ "$HAS_SUMMARY" = "true" ]; then
|
|
817
|
+
# Scenario C: unit test files exist with @requirement annotations
|
|
818
|
+
# and a test-execution-summary.md documents coverage
|
|
819
|
+
echo "::warning::Evidence completeness gate: ${REQ} has zero E2E tagged tests and zero screenshots, but ${UNIT_TESTS_ON_DISK} unit test file(s) on disk reference it and a test-execution-summary.md exists. Unit test evidence found but execution was not verified in this run. If this is an API-only or backend-only change, this is expected."
|
|
788
820
|
else
|
|
789
|
-
|
|
821
|
+
# Scenario A: genuinely no evidence — no E2E specs, no unit tests,
|
|
822
|
+
# no test-execution-summary. Hard error preserved (#237 Constraint 3).
|
|
823
|
+
echo "::error::Evidence completeness gate: ${REQ} has zero traceable evidence — no tagged E2E tests, no per-AC screenshots, no unit test files with @requirement annotations, and no test-execution-summary.md. The release cannot proceed to UAT with no traceable per-REQ evidence."
|
|
824
|
+
echo "::error::If E2E specs exist for this REQ, ensure they carry @requirement ${REQ} JSDoc annotations and tagTest() calls (e2e-test-engineer Phase 5½, issue #170). If unit tests exist, add @requirement ${REQ} annotations to the .test.ts files. If this is a pure config/docs change with no testable surface, document it in test-execution-summary.md."
|
|
790
825
|
EVIDENCE_GAPS=$((EVIDENCE_GAPS + 1))
|
|
791
826
|
fi
|
|
792
827
|
else
|
|
@@ -30,5 +30,8 @@ jobs:
|
|
|
30
30
|
- name: Validate compliance artifacts
|
|
31
31
|
run: bash scripts/validate-compliance-artifacts.sh origin/main
|
|
32
32
|
|
|
33
|
+
- name: Validate test execution summaries
|
|
34
|
+
run: bash scripts/validate-test-summary.sh origin/main
|
|
35
|
+
|
|
33
36
|
- name: Validate commit conventions
|
|
34
37
|
run: bash scripts/validate-commits.sh origin/main
|
|
@@ -30,6 +30,8 @@ echo "Pre-push: TypeScript check passed."
|
|
|
30
30
|
# Only fires if UI-facing files are in the push. Checks for either
|
|
31
31
|
# playwright-report/ directory or .e2e-gate-passed sentinel (written by
|
|
32
32
|
# e2e-test-engineer after a successful run).
|
|
33
|
+
# Also checks .e2e-evidence-wired sentinel if e2e spec files changed
|
|
34
|
+
# (written by e2e-test-engineer Phase 5½ after validating tagTest/evidenceShot).
|
|
33
35
|
INTEGRATION_BRANCH=$(jq -r '.integration_branch // "develop"' sdlc-config.json 2>/dev/null || echo "develop")
|
|
34
36
|
|
|
35
37
|
# Read stdin to get the pushed refs (husky pre-push protocol)
|
|
@@ -70,6 +72,23 @@ while read -r local_ref local_sha remote_ref remote_sha; do
|
|
|
70
72
|
fi
|
|
71
73
|
echo "Pre-push: E2E evidence check passed."
|
|
72
74
|
fi
|
|
75
|
+
|
|
76
|
+
# Check for E2E spec file changes — require .e2e-evidence-wired sentinel
|
|
77
|
+
SPEC_FILES=$(git diff --name-only "$RANGE" -- 'e2e/**/*.spec.ts' 2>/dev/null || true)
|
|
78
|
+
|
|
79
|
+
if [ -n "$SPEC_FILES" ]; then
|
|
80
|
+
if [ ! -f .e2e-evidence-wired ]; then
|
|
81
|
+
echo ""
|
|
82
|
+
echo "ERROR: Evidence wiring validation (Phase 5½) was not run."
|
|
83
|
+
echo " E2E spec files changed in this push:"
|
|
84
|
+
echo "$SPEC_FILES" | sed 's/^/ /'
|
|
85
|
+
echo ""
|
|
86
|
+
echo " Invoke e2e-test-engineer to validate tagTest() and evidenceShot() calls."
|
|
87
|
+
echo " Bypass with --no-verify (last resort, not a habit)."
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
echo "Pre-push: E2E evidence wiring check passed."
|
|
91
|
+
fi
|
|
73
92
|
done
|
|
74
93
|
|
|
75
94
|
# ── 3. Skill-invocation sentinel (devaudit-installer#226) ────────────
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devaudit-sdlc",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "DevAudit SDLC CLI Engine — cross-agent terminal-driven SDLC orchestrator.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"devaudit-sdlc": "./src/bin/devaudit-sdlc.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"src/bin/devaudit-sdlc.js",
|
|
10
|
+
"src/blueprints"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/metasession-dev/DevAudit-Installer",
|
|
18
|
+
"directory": "sdlc"
|
|
19
|
+
},
|
|
20
|
+
"license": "Apache-2.0"
|
|
21
|
+
}
|