@metasession.co/devaudit-cli 0.1.70 → 0.1.72
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 +41 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/sdlc/files/_common/scripts/derive-release-version.sh +7 -0
- package/sdlc/files/_common/scripts/generate-bundled-changes.sh +88 -0
- package/sdlc/files/_common/scripts/generate-bundled-changes.test.sh +183 -0
- package/sdlc/files/_common/scripts/validate-commits.sh +23 -0
- package/sdlc/files/_common/skills/e2e-test-engineer/SKILL.md +14 -0
- package/sdlc/files/_common/skills/sdlc-implementer/SKILL.md +111 -9
- package/sdlc/files/ci/ci.yml.template +41 -3
- package/sdlc/files/ci/compliance-evidence.yml.template +59 -41
- package/sdlc/files/ci/incident-export.yml.template +18 -8
- package/sdlc/files/stacks/node/hooks/pre-push +118 -2
|
@@ -288,14 +288,47 @@ jobs:
|
|
|
288
288
|
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
289
289
|
echo "Release version: ${VERSION}"
|
|
290
290
|
|
|
291
|
-
- name:
|
|
291
|
+
- name: Check release exists (no creation — deferred to upload-evidence)
|
|
292
292
|
if: env.DEVAUDIT_BASE_URL != ''
|
|
293
293
|
run: |
|
|
294
|
+
# Release creation is deferred to the upload-evidence job (which
|
|
295
|
+
# runs after gates pass) so the portal never shows a release from
|
|
296
|
+
# a push where gates weren't verified (devaudit-installer#226).
|
|
297
|
+
# This step only checks whether the release already exists (e.g.
|
|
298
|
+
# created earlier by sdlc-implementer Phase 1 step 3).
|
|
294
299
|
chmod +x scripts/upload-evidence.sh 2>/dev/null || true
|
|
295
|
-
# Create the release in DevAudit (no evidence yet — just registration)
|
|
296
300
|
bash scripts/upload-evidence.sh \
|
|
297
301
|
{{PROJECT_SLUG}} _compliance-docs release_registration README.md \
|
|
298
|
-
--release ${{ steps.version.outputs.version }}
|
|
302
|
+
--release ${{ steps.version.outputs.version }} \
|
|
303
|
+
--environment uat --category planning \
|
|
304
|
+
--git-sha ${{ github.sha }} --branch ${{ github.ref_name }} || true
|
|
305
|
+
|
|
306
|
+
- name: Generate and upload bundled changes (REQ releases only)
|
|
307
|
+
if: env.DEVAUDIT_BASE_URL != ''
|
|
308
|
+
run: |
|
|
309
|
+
VERSION="${{ steps.version.outputs.version }}"
|
|
310
|
+
# Only generate bundled changes for REQ-tagged releases —
|
|
311
|
+
# housekeeping (bare-date) releases don't bundle other housekeeping.
|
|
312
|
+
if [[ "$VERSION" =~ ^v[0-9]{4}\.[0-9]{2}\.[0-9]{2}(\.[0-9]+)?$ ]]; then
|
|
313
|
+
echo "Version ${VERSION} is housekeeping — skipping bundled changes."
|
|
314
|
+
exit 0
|
|
315
|
+
fi
|
|
316
|
+
chmod +x scripts/generate-bundled-changes.sh 2>/dev/null || true
|
|
317
|
+
chmod +x scripts/upload-evidence.sh 2>/dev/null || true
|
|
318
|
+
# Find the previous release tag to scan from. Fall back to last 50
|
|
319
|
+
# commits if no prior tag exists.
|
|
320
|
+
SINCE_REF=$(git tag --sort=-creatordate | head -1 || true)
|
|
321
|
+
if [ -z "$SINCE_REF" ]; then
|
|
322
|
+
SINCE_REF="HEAD~50"
|
|
323
|
+
fi
|
|
324
|
+
echo "Scanning bundled changes since ${SINCE_REF} for ${VERSION}"
|
|
325
|
+
BUNDLED_FILE="compliance/pending-releases/BUNDLED-CHANGES-${VERSION}.md"
|
|
326
|
+
mkdir -p compliance/pending-releases
|
|
327
|
+
bash scripts/generate-bundled-changes.sh "$SINCE_REF" "$VERSION" > "$BUNDLED_FILE"
|
|
328
|
+
# Upload as bundled_changes evidence against the REQ release.
|
|
329
|
+
bash scripts/upload-evidence.sh \
|
|
330
|
+
{{PROJECT_SLUG}} _compliance-docs bundled_changes "$BUNDLED_FILE" \
|
|
331
|
+
--release "$VERSION" \
|
|
299
332
|
--environment uat --category planning \
|
|
300
333
|
--git-sha ${{ github.sha }} --branch ${{ github.ref_name }} || true
|
|
301
334
|
|
|
@@ -409,6 +442,11 @@ jobs:
|
|
|
409
442
|
if: env.DEVAUDIT_BASE_URL != ''
|
|
410
443
|
run: |
|
|
411
444
|
chmod +x scripts/upload-evidence.sh 2>/dev/null || true
|
|
445
|
+
# --create-release-if-missing is intentionally here (post-gate) rather
|
|
446
|
+
# than in register-release. This ensures the portal release record only
|
|
447
|
+
# appears after gates have run — even if gates failed, the release
|
|
448
|
+
# record is created here so failure evidence attaches to it.
|
|
449
|
+
# (devaudit-installer#226)
|
|
412
450
|
FLAGS="--git-sha ${{ github.sha }} --ci-run-id ${{ github.run_id }} --branch ${{ github.ref_name }}"
|
|
413
451
|
FLAGS="${FLAGS} --release ${{ needs.register-release.outputs.version }} --create-release-if-missing"
|
|
414
452
|
FLAGS="${FLAGS} --environment uat"
|
|
@@ -909,35 +909,43 @@ jobs:
|
|
|
909
909
|
|
|
910
910
|
echo " [INCIDENT] $TEST_NAME — filing with incident label"
|
|
911
911
|
|
|
912
|
-
|
|
912
|
+
# DevAudit-Installer#228 — heredoc to keep markdown content
|
|
913
|
+
# inside the YAML literal block scalar (0-indent continuation
|
|
914
|
+
# lines were terminating the block and ** was parsed as YAML
|
|
915
|
+
# alias references).
|
|
916
|
+
ISSUE_BODY=$(cat <<EOF
|
|
917
|
+
## E2E Regression Failure — ${CLASSIFICATION}
|
|
913
918
|
|
|
914
|
-
**Test name:** ${TEST_NAME}
|
|
915
|
-
**Error message:**
|
|
916
|
-
\`\`\`
|
|
917
|
-
${ERROR_MSG}
|
|
918
|
-
\`\`\`
|
|
919
|
+
**Test name:** ${TEST_NAME}
|
|
920
|
+
**Error message:**
|
|
921
|
+
\`\`\`
|
|
922
|
+
${ERROR_MSG}
|
|
923
|
+
\`\`\`
|
|
919
924
|
|
|
920
|
-
**Classification:** ${CLASSIFICATION}
|
|
921
|
-
**Classification rationale:** ${RATIONALE}
|
|
925
|
+
**Classification:** ${CLASSIFICATION}
|
|
926
|
+
**Classification rationale:** ${RATIONALE}
|
|
922
927
|
|
|
923
|
-
**testCycleId:** ${CI_RUN_ID}
|
|
924
|
-
**Workflow run:** ${WORKFLOW_URL}
|
|
925
|
-
**Git SHA:** ${GIT_SHA}
|
|
928
|
+
**testCycleId:** ${CI_RUN_ID}
|
|
929
|
+
**Workflow run:** ${WORKFLOW_URL}
|
|
930
|
+
**Git SHA:** ${GIT_SHA}
|
|
926
931
|
|
|
927
|
-
This regression was detected and classified by the autonomous E2E Regression CI run. A human should confirm the classification, adjust severity if needed, and close once fixed. The \`incident\` label ensures an \`incident_report\` will be generated on close.
|
|
932
|
+
This regression was detected and classified by the autonomous E2E Regression CI run. A human should confirm the classification, adjust severity if needed, and close once fixed. The \`incident\` label ensures an \`incident_report\` will be generated on close.
|
|
928
933
|
|
|
929
|
-
### Framework attribution
|
|
934
|
+
### Framework attribution
|
|
930
935
|
|
|
931
|
-
This defect, once closed with the \`incident\` label, will be auto-exported as \`incident_report\` evidence and attribute to:
|
|
936
|
+
This defect, once closed with the \`incident\` label, will be auto-exported as \`incident_report\` evidence and attribute to:
|
|
932
937
|
|
|
933
|
-
- [x] \`ISO29119.3.5.4\` (baseline — every incident_report)
|
|
934
|
-
- [x] \`SOC2.CC7.2\` — ops impact: a regression in production-adjacent code is an ops concern
|
|
935
|
-
- [ ] \`GDPR.Art-33\` — personal data scope: <REPLACE — yes/no>
|
|
936
|
-
- [ ] \`GDPR.Art-34\` — data-subject notification required: <REPLACE — yes/no>
|
|
937
|
-
- [ ] \`EUAIA.Art-9 / Art-14 / Art-15\` — AI failure: <REPLACE — yes/no, which article(s)>
|
|
938
|
+
- [x] \`ISO29119.3.5.4\` (baseline — every incident_report)
|
|
939
|
+
- [x] \`SOC2.CC7.2\` — ops impact: a regression in production-adjacent code is an ops concern
|
|
940
|
+
- [ ] \`GDPR.Art-33\` — personal data scope: <REPLACE — yes/no>
|
|
941
|
+
- [ ] \`GDPR.Art-34\` — data-subject notification required: <REPLACE — yes/no>
|
|
942
|
+
- [ ] \`EUAIA.Art-9 / Art-14 / Art-15\` — AI failure: <REPLACE — yes/no, which article(s)>
|
|
938
943
|
|
|
939
|
-
Once closed, the \`incident-export.yml\` workflow exports this issue's body to \`compliance/governance/incident-report-<N>.md\`.
|
|
940
|
-
|
|
944
|
+
Once closed, the \`incident-export.yml\` workflow exports this issue's body to \`compliance/governance/incident-report-<N>.md\`.
|
|
945
|
+
EOF
|
|
946
|
+
)
|
|
947
|
+
# Strip the 14-space heredoc indentation so the issue body is clean.
|
|
948
|
+
ISSUE_BODY=$(echo "$ISSUE_BODY" | sed 's/^ //')
|
|
941
949
|
|
|
942
950
|
gh issue create \
|
|
943
951
|
--title "[REGRESSION] ${TEST_NAME}" \
|
|
@@ -947,23 +955,27 @@ Once closed, the \`incident-export.yml\` workflow exports this issue's body to \
|
|
|
947
955
|
elif [ "$FILE_LABEL" = "test-bug" ]; then
|
|
948
956
|
echo " [TEST-BUG] $TEST_NAME — filing with test-bug label (no incident label)"
|
|
949
957
|
|
|
950
|
-
|
|
958
|
+
# DevAudit-Installer#228 — heredoc (see comment above).
|
|
959
|
+
ISSUE_BODY=$(cat <<EOF
|
|
960
|
+
## E2E Regression Failure — ${CLASSIFICATION}
|
|
951
961
|
|
|
952
|
-
**Test name:** ${TEST_NAME}
|
|
953
|
-
**Error message:**
|
|
954
|
-
\`\`\`
|
|
955
|
-
${ERROR_MSG}
|
|
956
|
-
\`\`\`
|
|
962
|
+
**Test name:** ${TEST_NAME}
|
|
963
|
+
**Error message:**
|
|
964
|
+
\`\`\`
|
|
965
|
+
${ERROR_MSG}
|
|
966
|
+
\`\`\`
|
|
957
967
|
|
|
958
|
-
**Classification:** ${CLASSIFICATION}
|
|
959
|
-
**Classification rationale:** ${RATIONALE}
|
|
968
|
+
**Classification:** ${CLASSIFICATION}
|
|
969
|
+
**Classification rationale:** ${RATIONALE}
|
|
960
970
|
|
|
961
|
-
**testCycleId:** ${CI_RUN_ID}
|
|
962
|
-
**Workflow run:** ${WORKFLOW_URL}
|
|
963
|
-
**Git SHA:** ${GIT_SHA}
|
|
971
|
+
**testCycleId:** ${CI_RUN_ID}
|
|
972
|
+
**Workflow run:** ${WORKFLOW_URL}
|
|
973
|
+
**Git SHA:** ${GIT_SHA}
|
|
964
974
|
|
|
965
|
-
This failure appears to be a ${CLASSIFICATION} (not an application defect). A human should confirm and fix the ${CLASSIFICATION}, not the application. Filed with the \`test-bug\` label — this does NOT produce \`incident_report\` evidence.
|
|
966
|
-
|
|
975
|
+
This failure appears to be a ${CLASSIFICATION} (not an application defect). A human should confirm and fix the ${CLASSIFICATION}, not the application. Filed with the \`test-bug\` label — this does NOT produce \`incident_report\` evidence.
|
|
976
|
+
EOF
|
|
977
|
+
)
|
|
978
|
+
ISSUE_BODY=$(echo "$ISSUE_BODY" | sed 's/^ //')
|
|
967
979
|
|
|
968
980
|
gh issue create \
|
|
969
981
|
--title "[TEST-BUG] ${TEST_NAME}" \
|
|
@@ -974,13 +986,19 @@ This failure appears to be a ${CLASSIFICATION} (not an application defect). A hu
|
|
|
974
986
|
done <<< "$FAILING_TESTS"
|
|
975
987
|
|
|
976
988
|
# --- Post summary comment on the workflow run ---
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
-
|
|
982
|
-
-
|
|
983
|
-
-
|
|
989
|
+
# DevAudit-Installer#228 — heredoc to keep continuation lines
|
|
990
|
+
# inside the YAML literal block scalar.
|
|
991
|
+
SUMMARY=$(cat <<EOF
|
|
992
|
+
E2E Regression triage summary:
|
|
993
|
+
- Flakes (not filed): ${FLAKE_COUNT}
|
|
994
|
+
- Test bugs (filed without incident label): ${TEST_BUG_COUNT}
|
|
995
|
+
- Seed-data gaps (filed without incident label): ${SEED_GAP_COUNT}
|
|
996
|
+
- Visual diffs intended (not filed): ${VISUAL_INTENDED_COUNT}
|
|
997
|
+
- Visual diffs unintended (filed as incident): ${VISUAL_UNINTENDED_COUNT}
|
|
998
|
+
- Application defects (filed as incident): ${APP_DEFECT_COUNT}
|
|
999
|
+
EOF
|
|
1000
|
+
)
|
|
1001
|
+
SUMMARY=$(echo "$SUMMARY" | sed 's/^ //')
|
|
984
1002
|
|
|
985
1003
|
echo "$SUMMARY"
|
|
986
1004
|
# Post summary as a workflow run comment (using gh api).
|
|
@@ -198,15 +198,25 @@ jobs:
|
|
|
198
198
|
MERGE_SHA=$(echo "$CLOSING_PRS" | jq -r '.mergeCommit.oid // .mergeCommit // "unknown"' 2>/dev/null | head -1)
|
|
199
199
|
PR_TITLE=$(echo "$CLOSING_PRS" | jq -r '.title' 2>/dev/null | head -1)
|
|
200
200
|
PR_NUM=$(echo "$CLOSING_PRS" | jq -r '.number' 2>/dev/null | head -1)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
- **
|
|
201
|
+
# DevAudit-Installer#228 — heredoc to keep markdown content
|
|
202
|
+
# inside the YAML literal block scalar.
|
|
203
|
+
CONTAINMENT=$(cat <<EOF
|
|
204
|
+
- **Containment actions:** auto-derived from PR #${PR_NUM}: ${PR_TITLE}
|
|
205
|
+
- **Mitigation deployed:** [PR #${PR_NUM}](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/pull/${PR_NUM}) (${MERGE_SHA})
|
|
206
|
+
- **Recovery actions:** REPLACE — if additional recovery steps were taken
|
|
207
|
+
- **Verification that the incident is resolved:** REPLACE — how was the fix verified (re-run E2E, manual check, etc.)
|
|
208
|
+
EOF
|
|
209
|
+
)
|
|
210
|
+
CONTAINMENT=$(echo "$CONTAINMENT" | sed 's/^ //')
|
|
205
211
|
else
|
|
206
|
-
CONTAINMENT
|
|
207
|
-
- **
|
|
208
|
-
- **
|
|
209
|
-
- **
|
|
212
|
+
CONTAINMENT=$(cat <<EOF
|
|
213
|
+
- **Containment actions:** REPLACE — no linked PR found
|
|
214
|
+
- **Mitigation deployed:** REPLACE
|
|
215
|
+
- **Recovery actions:** REPLACE
|
|
216
|
+
- **Verification that the incident is resolved:** REPLACE
|
|
217
|
+
EOF
|
|
218
|
+
)
|
|
219
|
+
CONTAINMENT=$(echo "$CONTAINMENT" | sed 's/^ //')
|
|
210
220
|
fi
|
|
211
221
|
|
|
212
222
|
# §4g — Lessons learned: scan comments for follow-up issue references.
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Husky pre-push hook —
|
|
3
|
-
#
|
|
2
|
+
# Husky pre-push hook — fast gates + E2E evidence + skill-invocation sentinel + compliance validator.
|
|
3
|
+
#
|
|
4
|
+
# Runs four checks before allowing a push:
|
|
5
|
+
# 1. TypeScript check (fast gate)
|
|
6
|
+
# 2. E2E evidence check — if UI-facing files changed, verify Playwright ran
|
|
7
|
+
# 3. Skill-invocation sentinel — if feat/fix/refactor/perf commits present,
|
|
8
|
+
# verify sdlc-implementer was invoked
|
|
9
|
+
# 4. Compliance artifact validation — if feat/fix/refactor/perf commits present,
|
|
10
|
+
# run validate-compliance-artifacts.sh to catch missing evidence files
|
|
11
|
+
#
|
|
12
|
+
# Bypass with --no-verify (last resort, not a habit).
|
|
4
13
|
#
|
|
5
14
|
# Install: cp this file to .husky/pre-push && chmod +x .husky/pre-push
|
|
6
15
|
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# ── 1. TypeScript check ──────────────────────────────────────────────
|
|
7
19
|
echo "Pre-push: running TypeScript check..."
|
|
8
20
|
npx tsc --noEmit
|
|
9
21
|
if [ $? -ne 0 ]; then
|
|
@@ -13,3 +25,107 @@ if [ $? -ne 0 ]; then
|
|
|
13
25
|
exit 1
|
|
14
26
|
fi
|
|
15
27
|
echo "Pre-push: TypeScript check passed."
|
|
28
|
+
|
|
29
|
+
# ── 2. E2E evidence check (devaudit-installer#226) ───────────────────
|
|
30
|
+
# Only fires if UI-facing files are in the push. Checks for either
|
|
31
|
+
# playwright-report/ directory or .e2e-gate-passed sentinel (written by
|
|
32
|
+
# e2e-test-engineer after a successful run).
|
|
33
|
+
INTEGRATION_BRANCH=$(jq -r '.integration_branch // "develop"' sdlc-config.json 2>/dev/null || echo "develop")
|
|
34
|
+
|
|
35
|
+
# Read stdin to get the pushed refs (husky pre-push protocol)
|
|
36
|
+
while read -r local_ref local_sha remote_ref remote_sha; do
|
|
37
|
+
# Check if pushing to the integration branch
|
|
38
|
+
if [[ "$remote_ref" != *"refs/heads/$INTEGRATION_BRANCH" ]]; then
|
|
39
|
+
continue
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Determine the commit range being pushed
|
|
43
|
+
if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
|
|
44
|
+
RANGE="$local_sha"
|
|
45
|
+
else
|
|
46
|
+
RANGE="${remote_sha}..${local_sha}"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check for UI-facing files in the push
|
|
50
|
+
UI_FILES=$(git diff --name-only "$RANGE" -- 'app/**/*.tsx' 'src/**/*.tsx' 'pages/**/*.tsx' 'app/**/*.jsx' 'src/**/*.jsx' 'pages/**/*.jsx' 2>/dev/null || true)
|
|
51
|
+
|
|
52
|
+
if [ -n "$UI_FILES" ]; then
|
|
53
|
+
E2E_PASSED=false
|
|
54
|
+
if [ -f .e2e-gate-passed ]; then
|
|
55
|
+
E2E_PASSED=true
|
|
56
|
+
elif [ -d playwright-report ] && [ "$(find playwright-report -type f -newer .git/HEAD 2>/dev/null | head -1)" ]; then
|
|
57
|
+
E2E_PASSED=true
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if [ "$E2E_PASSED" = "false" ]; then
|
|
61
|
+
echo ""
|
|
62
|
+
echo "ERROR: E2E gate was not run before pushing."
|
|
63
|
+
echo " UI-facing files changed in this push:"
|
|
64
|
+
echo "$UI_FILES" | sed 's/^/ /'
|
|
65
|
+
echo ""
|
|
66
|
+
echo " Run 'npx playwright test' (or invoke e2e-test-engineer) before pushing."
|
|
67
|
+
echo " Bypass with --no-verify (last resort, not a habit)."
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
echo "Pre-push: E2E evidence check passed."
|
|
71
|
+
fi
|
|
72
|
+
done
|
|
73
|
+
|
|
74
|
+
# ── 3. Skill-invocation sentinel (devaudit-installer#226) ────────────
|
|
75
|
+
# If feat/fix/refactor/perf commits are in the push, verify the
|
|
76
|
+
# sdlc-implementer skill was invoked (writes .sdlc-implementer-invoked).
|
|
77
|
+
# Housekeeping types (docs/chore/ci/build/test/revert) are exempt.
|
|
78
|
+
TRACKED_TYPES='^(feat|fix|refactor|perf)(\(.+\))?!?:'
|
|
79
|
+
HAS_TRACKED=false
|
|
80
|
+
|
|
81
|
+
while read -r local_ref local_sha remote_ref remote_sha; do
|
|
82
|
+
if [[ "$remote_ref" != *"refs/heads/$INTEGRATION_BRANCH" ]]; then
|
|
83
|
+
continue
|
|
84
|
+
fi
|
|
85
|
+
if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
|
|
86
|
+
RANGE="$local_sha"
|
|
87
|
+
else
|
|
88
|
+
RANGE="${remote_sha}..${local_sha}"
|
|
89
|
+
fi
|
|
90
|
+
COMMITS=$(git log "$RANGE" --format='%s' 2>/dev/null || true)
|
|
91
|
+
if echo "$COMMITS" | grep -qE "$TRACKED_TYPES"; then
|
|
92
|
+
HAS_TRACKED=true
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
|
|
96
|
+
if [ "$HAS_TRACKED" = "true" ]; then
|
|
97
|
+
if [ ! -f .sdlc-implementer-invoked ]; then
|
|
98
|
+
echo ""
|
|
99
|
+
echo "ERROR: sdlc-implementer skill was not invoked."
|
|
100
|
+
echo " This push contains feat/fix/refactor/perf commits which require"
|
|
101
|
+
echo " the SDLC skill flow. Invoke sdlc-implementer to drive the process,"
|
|
102
|
+
echo " or use --no-verify to bypass (not recommended — CI will also check"
|
|
103
|
+
echo " RTM provenance via validate-commits.sh)."
|
|
104
|
+
exit 1
|
|
105
|
+
fi
|
|
106
|
+
echo "Pre-push: skill-invocation sentinel check passed."
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# ── 4. Compliance artifact validation (devaudit-installer#226) ──────
|
|
110
|
+
# If feat/fix/refactor/perf commits are in the push, run
|
|
111
|
+
# validate-compliance-artifacts.sh to catch missing test-scope.md,
|
|
112
|
+
# test-plan.md, implementation-plan.md in compliance/evidence/.
|
|
113
|
+
# Reuses HAS_TRACKED from check 3.
|
|
114
|
+
if [ "$HAS_TRACKED" = "true" ]; then
|
|
115
|
+
if [ -f scripts/validate-compliance-artifacts.sh ]; then
|
|
116
|
+
echo "Pre-push: running compliance artifact validation..."
|
|
117
|
+
if ! bash scripts/validate-compliance-artifacts.sh "origin/$INTEGRATION_BRANCH"; then
|
|
118
|
+
echo ""
|
|
119
|
+
echo "ERROR: Compliance artifact validation failed."
|
|
120
|
+
echo " Missing or incomplete artifacts in compliance/evidence/."
|
|
121
|
+
echo " Run 'bash scripts/validate-compliance-artifacts.sh' locally to see details."
|
|
122
|
+
echo " Bypass with --no-verify (last resort, not a habit)."
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
echo "Pre-push: compliance artifact validation passed."
|
|
126
|
+
else
|
|
127
|
+
echo "Pre-push: compliance artifact validation skipped (script not found)."
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
echo "Pre-push: all checks passed."
|