@metasession.co/devaudit-cli 0.1.7 → 0.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metasession.co/devaudit-cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
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.7",
36
+ "@metasession.co/devaudit-plugin-sdk": "^0.1.9",
37
37
  "commander": "^12.1.0",
38
38
  "consola": "^3.2.3",
39
39
  "env-paths": "^3.0.0",
@@ -6,14 +6,18 @@
6
6
  # VERSION=$(./scripts/derive-release-version.sh)
7
7
  #
8
8
  # Priority:
9
- # 1. REQ tag in commit subject: "[REQ-037] feat(kitchen): ..." -> REQ-037
10
- # 2. Ref in commit body: "Ref: REQ-037" -> REQ-037
11
- # 3. Fallback: bare date -> v2026.05.17
9
+ # 1. REQ tag in commit subject: "[REQ-037] feat(kitchen): ..." -> REQ-037
10
+ # 2. Ref in commit body: "Ref: REQ-037" -> REQ-037
11
+ # 3. Bracketed tag in commit body: merge commit whose body is the PR title
12
+ # "... [REQ-037] ..." -> REQ-037
13
+ # 4. Fallback: bare date -> v2026.05.17
12
14
  #
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.
16
- # Output: single line on stdout. Exit 0 in all normal cases.
15
+ # The id is taken from a bracketed [REQ-XXX] tag (subject or body) or the
16
+ # `Ref:` line NOT from unbracketed prose (e.g. "target close: REQ-002" must
17
+ # not win over "Ref: REQ-001"). Step 3 exists because a "Merge pull request"
18
+ # commit carries the PR title (with its [REQ-XXX] tag) in the body, not the
19
+ # subject — without it, PR-merged work falls through to the date fallback and
20
+ # fragments onto a phantom date release. Output: single line on stdout.
17
21
  #
18
22
  # This ties a release record (project_id, version) to the feature the
19
23
  # commits belong to, so all CI uploads for one REQ converge on one
@@ -40,5 +44,14 @@ if echo "$BODY" | grep -qiE 'Ref:[[:space:]]*REQ-[0-9]+'; then
40
44
  exit 0
41
45
  fi
42
46
 
43
- # 3. Fallback: bare date in UTC
47
+ # 3. Body: a bracketed [REQ-XXX] anywhere in the body. Catches a merge commit
48
+ # whose body is the PR title — e.g. subject "Merge pull request #7 from …",
49
+ # body "chore(deps): [REQ-002] …". Bracketed-only, so an unbracketed prose
50
+ # mention ("target close: REQ-002") still cannot win over a real Ref: above.
51
+ if echo "$BODY" | grep -qE '\[REQ-[0-9]+\]'; then
52
+ echo "$BODY" | grep -oE '\[REQ-[0-9]+\]' | head -1 | grep -oE 'REQ-[0-9]+'
53
+ exit 0
54
+ fi
55
+
56
+ # 4. Fallback: bare date in UTC
44
57
  echo "v$(date -u +%Y.%m.%d)"
@@ -101,6 +101,16 @@ Dependency advisories accepted under R-001; target close: REQ-002.
101
101
  Ref: REQ-001"
102
102
  assert_eq "prose REQ-002 before Ref: REQ-001 -> REQ-001" "REQ-001" "$(run_helper)"
103
103
 
104
+ # Case 8: a "Merge pull request" commit carries the PR title (with its
105
+ # bracketed [REQ-XXX] tag) in the BODY, not the subject, and no Ref: line.
106
+ # Must resolve from the body bracket, not fall through to the date.
107
+ # Regression for REQ-002 landing on a phantom v<date> release after a
108
+ # feature->develop PR merge.
109
+ make_fixture "$WORK/c8" "Merge pull request #7 from metasession-dev/feat/req-002
110
+
111
+ chore(deps): [REQ-002] dependency hardening — close R-001"
112
+ assert_eq "merge-commit body [REQ-002] -> REQ-002" "REQ-002" "$(run_helper)"
113
+
104
114
  echo ""
105
115
  echo "=== Summary: $PASS pass / $FAIL fail ==="
106
116
 
@@ -327,59 +327,18 @@ jobs:
327
327
  --category test_report ${FLAGS}
328
328
  fi
329
329
 
330
- # Upload compliance docs (planning category)
331
- for DOC in compliance/RTM.md compliance/test-plan.md compliance/test-cases.md; do
332
- if [ -f "$DOC" ]; then
333
- upload "$(basename "$DOC")" \
334
- {{PROJECT_SLUG}} _compliance-docs compliance_document "$DOC" \
335
- --category planning ${FLAGS}
336
- fi
337
- done
338
-
339
- # Upload release tickets (pending only approved releases are historical)
340
- for DIR in compliance/pending-releases; do
341
- if [ -d "$DIR" ]; then
342
- for TICKET in "$DIR"/*.md; do
343
- [ -f "$TICKET" ] || continue
344
- upload "$(basename "$TICKET")" \
345
- {{PROJECT_SLUG}} _compliance-docs compliance_document "$TICKET" \
346
- --category release_artifact ${FLAGS}
347
- done
348
- fi
349
- done
350
-
351
- # Upload per-requirement evidence — scoped to requirements with a
352
- # pending release ticket. Without this scoping every historical
353
- # compliance/evidence/REQ-*/ folder would be re-uploaded on every
354
- # run, re-populating the release-requirement matrix with the full
355
- # project catalogue (DevAudit #133).
356
- IN_SCOPE_REQS=()
357
- if [ -d compliance/pending-releases ]; then
358
- for TICKET in compliance/pending-releases/RELEASE-TICKET-REQ-*.md; do
359
- [ -f "$TICKET" ] || continue
360
- REQ_ID=$(basename "$TICKET" .md | sed 's/^RELEASE-TICKET-//')
361
- IN_SCOPE_REQS+=("$REQ_ID")
362
- done
363
- fi
364
-
365
- if [ ${#IN_SCOPE_REQS[@]} -eq 0 ]; then
366
- echo "No pending release tickets found — skipping per-requirement evidence upload"
367
- else
368
- echo "In-scope requirements for this release: ${IN_SCOPE_REQS[*]}"
369
- for REQ_ID in "${IN_SCOPE_REQS[@]}"; do
370
- REQ_DIR="compliance/evidence/${REQ_ID}/"
371
- if [ ! -d "$REQ_DIR" ]; then
372
- echo "Warning: pending ticket for ${REQ_ID} but no ${REQ_DIR} on disk"
373
- continue
374
- fi
375
- for ARTIFACT in "$REQ_DIR"*.md; do
376
- [ -f "$ARTIFACT" ] || continue
377
- upload "${REQ_ID}/$(basename "$ARTIFACT")" \
378
- {{PROJECT_SLUG}} "${REQ_ID}" compliance_document "$ARTIFACT" \
379
- --category planning ${FLAGS}
380
- done
381
- done
382
- fi
330
+ # NOTE: committed compliance docs (planning category: RTM/test-plan/
331
+ # test-cases, release tickets, and per-requirement
332
+ # compliance/evidence/REQ-*/ folders) are intentionally NOT uploaded
333
+ # here. compliance-evidence.yml is the single owner of those — it
334
+ # fires on every compliance/** push and uploads them to the same
335
+ # release (both workflows resolve the same version via
336
+ # derive-release-version.sh). Uploading them here too meant any push
337
+ # touching both code and compliance/ ran both workflows and inserted
338
+ # a duplicate row for every doc (evidence is append-only, no upsert),
339
+ # and re-populated the release matrix with the full catalogue. This
340
+ # job now uploads ONLY run-generated gate evidence (security_scan /
341
+ # ci_pipeline / test_report) above. See issue #45.
383
342
 
384
343
  if [ "$UPLOAD_FAILURES" -gt 0 ]; then
385
344
  echo "::error::${UPLOAD_FAILURES} evidence upload(s) failed — release is missing gate evidence and cannot pass UAT review"