@metasession.co/devaudit-cli 0.1.3 → 0.1.5
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 +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/sdlc/files/_common/scripts/derive-release-version.sh +9 -5
- package/sdlc/files/_common/scripts/derive-release-version.test.sh +11 -0
- package/sdlc/files/_common/scripts/validate-compliance-artifacts.sh +18 -7
- package/sdlc/files/_common/scripts/validate-compliance-artifacts.test.sh +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metasession.co/devaudit-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "DevAudit CLI — installs, syncs, and operates the Metasession SDLC across consumer projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^0.8.2",
|
|
36
|
-
"@metasession.co/devaudit-plugin-sdk": "^0.1.
|
|
36
|
+
"@metasession.co/devaudit-plugin-sdk": "^0.1.5",
|
|
37
37
|
"commander": "^12.1.0",
|
|
38
38
|
"consola": "^3.2.3",
|
|
39
39
|
"env-paths": "^3.0.0",
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
# 2. Ref in commit body: "Ref: REQ-037" -> REQ-037
|
|
11
11
|
# 3. Fallback: bare date -> v2026.05.17
|
|
12
12
|
#
|
|
13
|
-
#
|
|
13
|
+
# The id is taken from the bracketed subject tag or the `Ref:` line only —
|
|
14
|
+
# NOT from arbitrary REQ mentions in prose (e.g. a body line "target close:
|
|
15
|
+
# REQ-002" must not win over "Ref: REQ-001"). Subject takes priority over body.
|
|
14
16
|
# Output: single line on stdout. Exit 0 in all normal cases.
|
|
15
17
|
#
|
|
16
18
|
# This ties a release record (project_id, version) to the feature the
|
|
@@ -24,15 +26,17 @@ set -euo pipefail
|
|
|
24
26
|
SUBJECT=$(git log -1 --format='%s' 2>/dev/null || echo '')
|
|
25
27
|
BODY=$(git log -1 --format='%b' 2>/dev/null || echo '')
|
|
26
28
|
|
|
27
|
-
# 1. Subject: [REQ-XXX]
|
|
29
|
+
# 1. Subject: [REQ-XXX] — the bracketed tag only, not other REQ mentions.
|
|
28
30
|
if echo "$SUBJECT" | grep -qE '\[REQ-[0-9]+\]'; then
|
|
29
|
-
echo "$SUBJECT" | grep -oE 'REQ-[0-9]
|
|
31
|
+
echo "$SUBJECT" | grep -oE '\[REQ-[0-9]+\]' | head -1 | grep -oE 'REQ-[0-9]+'
|
|
30
32
|
exit 0
|
|
31
33
|
fi
|
|
32
34
|
|
|
33
|
-
# 2. Body: Ref
|
|
35
|
+
# 2. Body: the id on the `Ref:` line only (case-insensitive on "Ref"/"REQ").
|
|
36
|
+
# Scoping to the Ref: line prevents a prose mention earlier in the body
|
|
37
|
+
# (e.g. "target close: REQ-002") from being picked over the real ref.
|
|
34
38
|
if echo "$BODY" | grep -qiE 'Ref:[[:space:]]*REQ-[0-9]+'; then
|
|
35
|
-
echo "$BODY" | grep -ioE 'REQ-[0-9]+' | head -1 | tr '[:lower:]' '[:upper:]'
|
|
39
|
+
echo "$BODY" | grep -ioE 'Ref:[[:space:]]*REQ-[0-9]+' | head -1 | grep -oiE 'REQ-[0-9]+' | tr '[:lower:]' '[:upper:]'
|
|
36
40
|
exit 0
|
|
37
41
|
fi
|
|
38
42
|
|
|
@@ -90,6 +90,17 @@ assert_eq "subject overrides body conflict -> REQ-037" "REQ-037" "$(run_helper)"
|
|
|
90
90
|
make_fixture "$WORK/c6" "chore: bump deps"
|
|
91
91
|
assert_eq "no tag -> bare date $TODAY" "$TODAY" "$(run_helper)"
|
|
92
92
|
|
|
93
|
+
# Case 7: a prose REQ mention earlier in the body must NOT beat the Ref:
|
|
94
|
+
# line. Regression for the META-JOBS misattribution where "target close:
|
|
95
|
+
# REQ-002" caused gate evidence to land on a REQ-002 release instead of
|
|
96
|
+
# the real Ref: REQ-001.
|
|
97
|
+
make_fixture "$WORK/c7" "chore(sdlc): accept dep advisories
|
|
98
|
+
|
|
99
|
+
Dependency advisories accepted under R-001; target close: REQ-002.
|
|
100
|
+
|
|
101
|
+
Ref: REQ-001"
|
|
102
|
+
assert_eq "prose REQ-002 before Ref: REQ-001 -> REQ-001" "REQ-001" "$(run_helper)"
|
|
103
|
+
|
|
93
104
|
echo ""
|
|
94
105
|
echo "=== Summary: $PASS pass / $FAIL fail ==="
|
|
95
106
|
|
|
@@ -19,14 +19,25 @@ echo "=== Compliance Artifact Validation ==="
|
|
|
19
19
|
echo "Comparing: $BASE_BRANCH...HEAD"
|
|
20
20
|
echo ""
|
|
21
21
|
|
|
22
|
-
# Extract
|
|
22
|
+
# Extract the requirement(s) THIS PR implements — from the commit subject
|
|
23
|
+
# tag `[REQ-XXX]` and the `Ref: REQ-XXX` trailer only, NOT from arbitrary
|
|
24
|
+
# prose in commit bodies. A mention like "target close: REQ-002" or
|
|
25
|
+
# "prereq for REQ-034" is a forward-reference, not a requirement under
|
|
26
|
+
# change; scraping the whole body (%B) made CI demand evidence dirs for
|
|
27
|
+
# work that hasn't started (DevAudit: META-JOBS tracker, REQ-002 false
|
|
28
|
+
# positive). The RTM-row guard below is a secondary safety net.
|
|
23
29
|
#
|
|
24
|
-
# Requires ≥3 digits so placeholder patterns like `REQ-0XX`
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
# Requires ≥3 digits so placeholder patterns like `REQ-0XX` don't create
|
|
31
|
+
# phantom IDs. The project's stable id format is REQ-001 onwards (#232).
|
|
32
|
+
PR_MSGS=$(git log "$BASE_BRANCH"..HEAD --format='%B' || true)
|
|
33
|
+
REQUIREMENTS=$(
|
|
34
|
+
{
|
|
35
|
+
# Subject/anywhere tag, e.g. `feat: [REQ-001] …`
|
|
36
|
+
printf '%s\n' "$PR_MSGS" | grep -oP '\[\KREQ-\d{3,}(?=\])' || true
|
|
37
|
+
# `Ref:` line (may list several, e.g. `Ref: REQ-001, REQ-003`)
|
|
38
|
+
printf '%s\n' "$PR_MSGS" | grep -iP '^\s*Ref:' | grep -oP 'REQ-\d{3,}' || true
|
|
39
|
+
} | sort -u
|
|
40
|
+
)
|
|
30
41
|
|
|
31
42
|
if [ -z "$REQUIREMENTS" ]; then
|
|
32
43
|
echo "No REQ-XXX references found in PR commits — skipping artifact validation."
|
|
@@ -195,6 +195,33 @@ assert_grep "no missing-test ERROR" 'ERROR: Test file referenced in test-plan.md
|
|
|
195
195
|
assert_exit "validator exits 0 with depth-2 bare-filename reference" 0
|
|
196
196
|
cd "$WORKDIR"
|
|
197
197
|
|
|
198
|
+
# --- case 6: a future REQ mentioned only in commit prose is ignored ---
|
|
199
|
+
# Regression for the META-JOBS REQ-002 false positive: scraping the whole
|
|
200
|
+
# commit body pulled in `REQ-002` from "target close: REQ-002" and then
|
|
201
|
+
# ERRORed on its missing evidence dir even though REQ-002 hadn't started.
|
|
202
|
+
# Only `[REQ-XXX]` subject tags and `Ref:` lines count as under-change.
|
|
203
|
+
echo "Case 6: future REQ mentioned only in prose is not validated"
|
|
204
|
+
make_fixture "$WORKDIR/case6" "Implements the access-control boundary.
|
|
205
|
+
|
|
206
|
+
Dependency advisories accepted under R-001; target close: REQ-002.
|
|
207
|
+
|
|
208
|
+
Ref: REQ-001"
|
|
209
|
+
# REQ-002 HAS an RTM row (the trap) but no evidence dir; REQ-001 is the real
|
|
210
|
+
# Ref but has no RTM row, so it INFO-skips. Old code would ERROR on REQ-002.
|
|
211
|
+
{
|
|
212
|
+
echo '# RTM'
|
|
213
|
+
echo
|
|
214
|
+
echo '| ID | Description | Status |'
|
|
215
|
+
echo '| --- | --- | --- |'
|
|
216
|
+
echo '| REQ-002 | Dependency hardening (not started) | PLANNED |'
|
|
217
|
+
} > compliance/RTM.md
|
|
218
|
+
git add . && git commit -q -m "chore: seed RTM with future REQ-002 row"
|
|
219
|
+
run_validator
|
|
220
|
+
assert_grep "REQ-002 not pulled in from prose" 'Requirements found in PR commits:.*REQ-002' 0
|
|
221
|
+
assert_grep "no evidence-dir ERROR for prose-only REQ-002" 'ERROR: Evidence directory missing.*REQ-002' 0
|
|
222
|
+
assert_exit "validator exits 0 when future REQ is only prose-mentioned" 0
|
|
223
|
+
cd "$WORKDIR"
|
|
224
|
+
|
|
198
225
|
# --- summary ---
|
|
199
226
|
|
|
200
227
|
echo
|