@metasession.co/devaudit-cli 0.1.60 → 0.1.62

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.60",
3
+ "version": "0.1.62",
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.60",
36
+ "@metasession.co/devaudit-plugin-sdk": "^0.1.62",
37
37
  "ajv": "^8.20.0",
38
38
  "commander": "^12.1.0",
39
39
  "consola": "^3.2.3",
@@ -32,6 +32,11 @@
32
32
  # as `gateStatus`; unknown values are
33
33
  # silently dropped server-side.
34
34
  # DevAudit-Installer#96.
35
+ # --sdlc-stage <1-5> SDLC stage that produced this artefact:
36
+ # 1 plan, 2 implement/test, 3 compile-evidence,
37
+ # 4 submit-for-review, 5 deploy. Forwarded as
38
+ # `sdlcStage`; unknown to older portals (ignored
39
+ # server-side, no error).
35
40
  #
36
41
  # Required environment variables:
37
42
  # DEVAUDIT_BASE_URL e.g. https://meta-comply-production.up.railway.app
@@ -72,6 +77,7 @@ EVIDENCE_CATEGORY=""
72
77
  RELEASE_TITLE=""
73
78
  CHANGE_TYPE=""
74
79
  GATE_STATUS=""
80
+ SDLC_STAGE=""
75
81
  # Repeatable `--meta-key key=value` accumulator. Each pair gets merged
76
82
  # into the metadata JSON sent to the portal. Used by the screenshot
77
83
  # upload loop to pass `origin=feature|regression` from the per-PNG
@@ -96,6 +102,7 @@ while [ "$#" -gt 0 ]; do
96
102
  # ran-and-failed != never-ran. Unknown values dropped server-side.
97
103
  # DevAudit-Installer#96.
98
104
  --gate-status) GATE_STATUS="$2"; shift 2 ;;
105
+ --sdlc-stage) SDLC_STAGE="$2"; shift 2 ;;
99
106
  # --meta-key key=value (repeatable). Merged into the metadata JSON
100
107
  # before posting. Validates the `key=value` shape; rejects bare
101
108
  # keys without `=`.
@@ -119,6 +126,10 @@ if [ -n "$RELEASE_VERSION" ] && [ -z "$EVIDENCE_CATEGORY" ]; then
119
126
  echo "Error: --category is required when --release is specified (gate validation)"
120
127
  exit 1
121
128
  fi
129
+ if [ -n "$SDLC_STAGE" ] && ! [[ "$SDLC_STAGE" =~ ^[1-5]$ ]]; then
130
+ echo "Error: --sdlc-stage must be an integer 1-5 (got: $SDLC_STAGE)"
131
+ exit 1
132
+ fi
122
133
 
123
134
  if [ -z "${DEVAUDIT_BASE_URL:-}" ]; then
124
135
  echo "Error: DEVAUDIT_BASE_URL environment variable is required"
@@ -277,6 +288,7 @@ for FILE in "${FILES[@]}"; do
277
288
  [ -n "$RELEASE_TITLE" ] && CURL_ARGS+=(-F "releaseTitle=${RELEASE_TITLE}")
278
289
  [ -n "$CHANGE_TYPE" ] && CURL_ARGS+=(-F "changeType=${CHANGE_TYPE}")
279
290
  [ -n "$GATE_STATUS" ] && CURL_ARGS+=(-F "gateStatus=${GATE_STATUS}")
291
+ [ -n "$SDLC_STAGE" ] && CURL_ARGS+=(-F "sdlcStage=${SDLC_STAGE}")
280
292
 
281
293
  ATTEMPT=1
282
294
  BACKOFF=$INITIAL_BACKOFF_SECONDS
@@ -189,6 +189,30 @@ For **visual regression** specifically:
189
189
 
190
190
  Do additions, updates, and (approved) deletions in the same change so the suite stays internally consistent.
191
191
 
192
+ ### Phase 5½ — Evidence wiring validation
193
+
194
+ Before running the suite (Phase 6), verify that the evidence traceability wiring is in place. A spec can pass Phase 6's "AC covered" check by having a correct assertion without ever calling `evidenceShot()` or tagging `@requirement` — producing zero portal evidence and letting the release reach UAT with no traceable screenshots (DevAudit-Installer #170, #169).
195
+
196
+ **For each in-scope REQ and its ACs from Phase 2's scenario table:**
197
+
198
+ 1. **Check `@requirement` annotation.** Grep the authored/modified spec files for `@requirement REQ-XXX` tags. Every spec file that covers an in-scope REQ must carry at least one `@requirement REQ-XXX` annotation so the CI's `detect-req` step and the portal's evidence-by-requirement view can find it.
199
+
200
+ 2. **Check `evidenceShot()` calls.** For each UI spec covering an in-scope REQ, grep for at least one `evidenceShot(page, 'REQ-XXX', <ac>, ...)` call per AC. The call must be placed **at the assertion that proves the AC**, before any further interaction or navigation. API-only specs that don't have a visual surface are exempt — note the exemption in the test-execution-summary.
201
+
202
+ 3. **Check test title annotations.** Each test for an in-scope REQ must carry a `[REQ-XXX]` tag in the test title or `test.info().annotations` so the Playwright JSON reporter emits the REQ association. The portal uses this to map test results to requirements.
203
+
204
+ **If any check fails:**
205
+
206
+ Halt and report the gap to the user:
207
+ > Evidence wiring incomplete for REQ-XXX:
208
+ > - Missing `@requirement REQ-XXX` annotation in `e2e/<area>/foo.spec.ts`
209
+ > - Missing `evidenceShot()` call for AC2 in `e2e/<area>/bar.spec.ts`
210
+ > - Missing `[REQ-XXX]` tag in test title for "should filter by status"
211
+ >
212
+ > These must be fixed before running the suite — without them the portal will show zero screenshots and zero tagged tests for this REQ, and the CI gate (#169) will block the release.
213
+
214
+ 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.
215
+
192
216
  ### Phase 6 — Execute and report
193
217
 
194
218
  Run the suite. Strategy:
@@ -59,6 +59,39 @@ The only pauses in the whole workflow are the explicitly-named checkpoints:
59
59
 
60
60
  Everything else is silent continuation. The rule is **opt-in-to-pause, not opt-out-of-pause**. If you find yourself stopping after a sub-skill's "Return to the running `sdlc-implementer` context" line and waiting for the operator to ask _"is anything happening?"_ — that is the bug this section exists to prevent. Keep going.
61
61
 
62
+ ## Scope-expansion halt gate (devaudit-installer#171)
63
+
64
+ The change-request loop's scope-expansion halt rule (see [`references/change-request-loop.md`](./references/change-request-loop.md) §"If the change-request is fundamentally a different REQ") only fires during Phase 5 — after a UAT reviewer clicks "Request Changes" and the portal state is `uat_changes_requested`. In practice, scope-expanding requests also arrive from the user at any point after Phase 1:
65
+
66
+ - During Phase 2 (implementation) — user spots a related improvement and asks the agent to add it
67
+ - During Phase 3 (evidence compile) — user asks for an additional evidence artefact not in the plan
68
+ - During Phase 4 (UAT submission) — user exercises the deployed app and asks for a behaviour change
69
+ - Between UAT submission and approval — same scenario
70
+ - After approval but before merge — user makes a last-minute request
71
+
72
+ In all these cases, the portal state is NOT `uat_changes_requested`, so the change-request loop's halt rule never fires. The agent implements the out-of-scope change without flagging it.
73
+
74
+ **This gate fires on every user work request while a REQ is active, in any phase.**
75
+
76
+ When the user asks for a change that goes beyond the current REQ's acceptance criteria:
77
+
78
+ 1. **Read the current REQ's `test-scope.md`** (or `implementation-plan.md` § Acceptance Criteria if no test-scope exists yet) to identify the defined ACs.
79
+
80
+ 2. **Check whether the user's request maps to an existing AC.** If yes — proceed (or enter the change-request loop if in Phase 5).
81
+
82
+ 3. **If no — halt with the scope-expansion message:**
83
+
84
+ > This request adds behaviour outside REQ-XXX's acceptance criteria (AC1–ACn defined in test-scope.md). Recommend filing a separate issue for \<subject\> and shipping REQ-XXX as originally scoped.
85
+
86
+ 4. **Wait for the user to confirm one of:**
87
+ - **(a) File a separate issue** (new REQ) — ship the current REQ as-is. The agent continues with the original scope.
88
+ - **(b) Amend REQ-XXX's scope** — explicitly expand `test-scope.md` / `implementation-plan.md`, update the plan, invalidate existing evidence, and re-walk Stage 3. This option carries a warning: *"Amending scope after evidence is compiled (Stage 3+) invalidates the existing test-execution-summary, screenshots, and UAT verification. All Stage 3 evidence must be re-compiled."*
89
+ - **(c) Abandon the request** — do nothing, continue with the original scope.
90
+
91
+ **Do not implement the out-of-scope change before the user picks (a), (b), or (c).** The inertia trap is real: the agent is mid-flow, the codebase is open, and the request sounds reasonable. The gate exists to interrupt that inertia — STOP, surface the scope gap, and let the user decide.
92
+
93
+ This gate is distinct from Phase 2 step 4's "any deviation from the plan must be noted" rule: that covers implementation *approach* deviations (how to build something the plan says to build), not *scope* expansions (building something the plan doesn't say to build at all).
94
+
62
95
  ## SDLC navigability — LAST/NEXT status sticky (devaudit#131)
63
96
 
64
97
  Long-running SDLC issues accumulate dozens of comments across multiple Claude Code sessions. The operator returning to the thread should be able to answer two questions in under five seconds:
@@ -412,6 +412,7 @@ jobs:
412
412
  FLAGS="--git-sha ${{ github.sha }} --ci-run-id ${{ github.run_id }} --branch ${{ github.ref_name }}"
413
413
  FLAGS="${FLAGS} --release ${{ needs.register-release.outputs.version }} --create-release-if-missing"
414
414
  FLAGS="${FLAGS} --environment uat"
415
+ FLAGS="${FLAGS} --sdlc-stage 2"
415
416
 
416
417
  # Track failures across all uploads so we can fail the job at the
417
418
  # end with the full picture. Previously each upload used
@@ -548,6 +549,8 @@ jobs:
548
549
  # compliance/pending-releases/. Failures now bump UPLOAD_FAILURES
549
550
  # so the step exits non-zero and the release PR turns red.
550
551
  SHOT_REQS=()
552
+ ZERO_Screenshot_REQS=()
553
+ EVIDENCE_GAPS=0
551
554
  if [ -d compliance/pending-releases ]; then
552
555
  for TICKET in compliance/pending-releases/RELEASE-TICKET-REQ-*.md; do
553
556
  [ -f "$TICKET" ] || continue
@@ -579,6 +582,12 @@ jobs:
579
582
  REQ_SHOTS=(ci-evidence/compliance/evidence/"$REQ"/screenshots/*.png)
580
583
  if [ "${#REQ_SHOTS[@]}" -eq 0 ]; then
581
584
  echo "No per-AC screenshots for ${REQ} (none captured by evidenceShot this run)"
585
+ # devaudit-installer#169 — track REQs with zero screenshots
586
+ # so the evidence-completeness gate below can fail the job
587
+ # if the REQ also has zero tagged tests in the Playwright
588
+ # report. Previously this was a silent continue — the release
589
+ # proceeded to UAT with no traceable evidence.
590
+ ZERO_Screenshot_REQS+=("$REQ")
582
591
  continue
583
592
  fi
584
593
  echo "Uploading ${#REQ_SHOTS[@]} screenshot(s) for ${REQ}"
@@ -625,6 +634,52 @@ jobs:
625
634
  fi
626
635
  shopt -u nullglob
627
636
 
637
+ # devaudit-installer#169 — Evidence-completeness gate.
638
+ # For each in-scope REQ that had zero screenshots, check whether
639
+ # the Playwright JSON report contains at least one test tagged
640
+ # with that REQ. If a REQ has zero screenshots AND zero tagged
641
+ # tests, the release has no traceable evidence and must not
642
+ # proceed to UAT. Previously this was a silent pass — the release
643
+ # arrived in UAT review with "SCREENSHOTS: none" and "TESTS: no
644
+ # tests in report tagged with this REQ" on the portal.
645
+ if [ "${#ZERO_Screenshot_REQS[@]}" -gt 0 ]; then
646
+ for REQ in "${ZERO_Screenshot_REQS[@]}"; do
647
+ TAGGED_COUNT=0
648
+ if [ -f ci-evidence/e2e-results.json ]; then
649
+ TAGGED_COUNT=$(python3 -c "
650
+ import json, sys
651
+ with open('ci-evidence/e2e-results.json') as f:
652
+ data = json.load(f)
653
+ def count(specs):
654
+ n = 0
655
+ for s in specs:
656
+ tags = []
657
+ for a in s.get('annotations', []):
658
+ tags.append(a.get('type','') + ':' + a.get('description',''))
659
+ for t in s.get('tags', []):
660
+ tags.append(t)
661
+ title = s.get('title', '')
662
+ if '${REQ}' in title or any('${REQ}' in t for t in tags):
663
+ n += 1
664
+ n += count(s.get('suites', []))
665
+ return n
666
+ print(count(data.get('suites', [])))
667
+ " 2>/dev/null || echo "0")
668
+ fi
669
+ if [ "$TAGGED_COUNT" -eq 0 ]; then
670
+ echo "::error::Evidence completeness gate: ${REQ} has zero tagged tests AND zero per-AC screenshots. The release cannot proceed to UAT with no traceable evidence. Ensure specs carry @requirement ${REQ} annotations and evidenceShot() calls (skill Phase 5½, issue #170)."
671
+ EVIDENCE_GAPS=$((EVIDENCE_GAPS + 1))
672
+ else
673
+ echo "${REQ} has zero screenshots but ${TAGGED_COUNT} tagged test(s) — evidence-completeness gate passed (screenshot gap is non-blocking)"
674
+ fi
675
+ done
676
+ fi
677
+
678
+ if [ "$EVIDENCE_GAPS" -gt 0 ]; then
679
+ echo "::error::${EVIDENCE_GAPS} in-scope REQ(s) have zero traceable evidence (no tagged tests, no screenshots) — release cannot pass UAT review"
680
+ exit 1
681
+ fi
682
+
628
683
  # NOTE: committed compliance docs (planning category: RTM/test-plan/
629
684
  # test-cases, release tickets, and per-requirement
630
685
  # compliance/evidence/REQ-*/ folders) are intentionally NOT uploaded
@@ -237,7 +237,7 @@ jobs:
237
237
  # untagged docs commit must not sweep every in-scope REQ into a date
238
238
  # release. Note: upload-evidence.sh keeps the LAST --release seen.
239
239
  FLAGS="--git-sha ${{ github.sha }} --ci-run-id ${{ github.run_id }} --branch ${{ github.ref_name }}"
240
- FLAGS="${FLAGS} --create-release-if-missing --environment uat"
240
+ FLAGS="${FLAGS} --create-release-if-missing --environment uat --sdlc-stage 3"
241
241
  DERIVED_RELEASE="${{ steps.version.outputs.version }}"
242
242
 
243
243
  # Derive change_type for the bare-date (housekeeping) DERIVED_RELEASE:
@@ -586,9 +586,9 @@ jobs:
586
586
  PRIOR_EVENT="${{ github.event.workflow_run.event }}"
587
587
  PRIOR_BRANCH="${{ github.event.workflow_run.head_branch }}"
588
588
  case "$PRIOR_EVENT" in
589
- pull_request) TIER=critical ;;
590
- push) TIER=regression ;;
591
- *) TIER="${PRIOR_EVENT}" ;;
589
+ pull_request) TIER=critical; STAGE=2 ;;
590
+ push) TIER=regression; STAGE=5 ;;
591
+ *) TIER="${PRIOR_EVENT}"; STAGE="" ;;
592
592
  esac
593
593
 
594
594
  # Common flags for upload-evidence.sh. Branch + SHA come from
@@ -597,6 +597,7 @@ jobs:
597
597
  --git-sha ${{ github.event.workflow_run.head_sha }} \
598
598
  --ci-run-id ${{ github.event.workflow_run.id }} \
599
599
  --branch ${PRIOR_BRANCH}"
600
+ [ -n "$STAGE" ] && FLAGS="${FLAGS} --sdlc-stage ${STAGE}"
600
601
 
601
602
  # In-scope REQs from pending release tickets at the triggering
602
603
  # SHA. Fall back to `_compliance-docs` if no tickets present so
@@ -634,10 +635,13 @@ jobs:
634
635
  # facing artefact (the formatted run summary). Skipped if
635
636
  # the report directory is missing (e.g. an upstream
636
637
  # infrastructure failure aborted before reporting).
637
- if [ -f e2e-artifacts/playwright-report/index.html ]; then
638
+ if [ -d e2e-artifacts/playwright-report ]; then
639
+ (cd e2e-artifacts && zip -qr playwright-report.zip playwright-report/) 2>/dev/null || true
640
+ fi
641
+ if [ -f e2e-artifacts/playwright-report.zip ]; then
638
642
  if bash scripts/upload-evidence.sh \
639
643
  {{PROJECT_SLUG}} "$REQ" test_report \
640
- e2e-artifacts/playwright-report/index.html \
644
+ e2e-artifacts/playwright-report.zip \
641
645
  --category test_report ${FLAGS} --release "${DERIVED_RELEASE}" \
642
646
  --meta-key "tier=${TIER}"
643
647
  then
@@ -0,0 +1,138 @@
1
+ # Feature-branch in-scope E2E (DEVAUDIT-003, issue #174)
2
+ #
3
+ # Generated by `devaudit install` / `devaudit update` from sdlc-config.json.
4
+ # Runs the E2E specs tagged with the branch's REQ on PRs to the integration
5
+ # branch, so regression-tier bugs surface during the feature cycle instead of
6
+ # at the release gate. Uploads the report as stage-2, origin=feature evidence
7
+ # so it does NOT co-mingle with the stage-3/5 regression runs and is NOT
8
+ # counted as release/UAT evidence by the portal.
9
+ name: Feature In-Scope E2E
10
+
11
+ on:
12
+ pull_request:
13
+ branches: [develop]
14
+
15
+ jobs:
16
+ detect-req:
17
+ name: Detect REQ from branch
18
+ runs-on: {{RUNNER}}
19
+ outputs:
20
+ req_id: ${{ steps.detect.outputs.req_id }}
21
+ has_tests: ${{ steps.detect.outputs.has_tests }}
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+ - name: Parse REQ from branch name
25
+ id: detect
26
+ run: |
27
+ BRANCH="${{ github.head_ref }}"
28
+ if [[ $BRANCH =~ (REQ-[0-9]+) ]]; then
29
+ REQ_ID="${BASH_REMATCH[1]}"
30
+ echo "req_id=$REQ_ID" >> "$GITHUB_OUTPUT"
31
+ if grep -rl "@requirement $REQ_ID" e2e/ --include="*.spec.ts" >/dev/null 2>&1; then
32
+ echo "has_tests=true" >> "$GITHUB_OUTPUT"
33
+ else
34
+ echo "has_tests=false" >> "$GITHUB_OUTPUT"
35
+ fi
36
+ else
37
+ echo "req_id=none" >> "$GITHUB_OUTPUT"
38
+ echo "has_tests=false" >> "$GITHUB_OUTPUT"
39
+ fi
40
+
41
+ run-feature-e2e:
42
+ name: Run in-scope E2E
43
+ needs: detect-req
44
+ if: needs.detect-req.outputs.has_tests == 'true'
45
+ runs-on: {{RUNNER}}
46
+
47
+ services:
48
+ {{DATABASE_SERVICE}}:
49
+ image: {{DATABASE_IMAGE}}
50
+ ports:
51
+ - {{DATABASE_PORT}}
52
+
53
+ env:
54
+ {{DATABASE_ENV}}
55
+ {{APP_ENV}}
56
+ DEVAUDIT_BASE_URL_VAR: ${{ vars.DEVAUDIT_BASE_URL }}
57
+ DEVAUDIT_API_KEY: ${{ secrets.DEVAUDIT_API_KEY }}
58
+
59
+ steps:
60
+ - uses: actions/checkout@v6
61
+ with:
62
+ fetch-depth: 0
63
+ - uses: actions/setup-node@v4
64
+ with:
65
+ node-version: {{NODE_VERSION}}
66
+ - name: Install dependencies (skip if lockfile unchanged)
67
+ run: |
68
+ LOCK_HASH=$(sha256sum package-lock.json | cut -d' ' -f1)
69
+ if [ -f node_modules/.lock-hash ] && [ "$(cat node_modules/.lock-hash)" = "$LOCK_HASH" ]; then
70
+ echo "node_modules up to date — skipping npm ci"
71
+ else
72
+ npm ci
73
+ echo "$LOCK_HASH" > node_modules/.lock-hash
74
+ fi
75
+ - name: Install Playwright (skip if already cached)
76
+ run: npx playwright install --with-deps chromium 2>/dev/null || npx playwright install chromium
77
+
78
+ {{DATABASE_URI_STEP}}
79
+ {{E2E_SETUP_STEP}}
80
+ - name: Kill stale dev server
81
+ run: lsof -ti:3000 | xargs kill -9 2>/dev/null || true
82
+
83
+ {{E2E_DEV_SERVER_STEP}}
84
+
85
+ - name: Wait for dev server
86
+ run: npx wait-on http://localhost:3000 --timeout 120000
87
+
88
+ # Compute the set of e2e spec files added on this branch (relative
89
+ # to the merge base). The evidenceShot helper reads E2E_NEW_SPECS
90
+ # at capture time and tags each screenshot `origin=feature` when
91
+ # its spec appears in the list, else `origin=regression`.
92
+ - name: Compute new-spec list for E2E origin tagging
93
+ run: |
94
+ BASE_REF="${{ github.base_ref || 'develop' }}"
95
+ BASE_SHA=$(git merge-base "origin/${BASE_REF}" HEAD 2>/dev/null || git rev-parse HEAD)
96
+ NEW_SPECS=$(git diff --name-only --diff-filter=A "${BASE_SHA}...HEAD" \
97
+ -- 'tests/e2e/**/*.spec.ts' 'tests/e2e/**/*.spec.tsx' \
98
+ 'e2e/**/*.spec.ts' 'e2e/**/*.spec.tsx' 2>/dev/null || true)
99
+ {
100
+ echo "E2E_NEW_SPECS<<EOF"
101
+ echo "$NEW_SPECS"
102
+ echo "EOF"
103
+ } >> "$GITHUB_ENV"
104
+ if [ -n "$NEW_SPECS" ]; then
105
+ echo "New e2e specs on this branch (origin=feature for captures):"
106
+ echo "$NEW_SPECS" | sed 's/^/ /'
107
+ else
108
+ echo "No new e2e specs detected — all captures will tag origin=regression."
109
+ fi
110
+
111
+ {{E2E_FEATURE_TEST_STEP}}
112
+ - name: Upload feature E2E evidence (stage 2, origin=feature)
113
+ if: always()
114
+ run: |
115
+ REQ_ID="${{ needs.detect-req.outputs.req_id }}"
116
+ CONFIG_URL=""
117
+ if [ -f sdlc-config.json ]; then
118
+ CONFIG_URL=$(jq -r '.devaudit.base_url // empty' sdlc-config.json 2>/dev/null || true)
119
+ fi
120
+ BASE="${CONFIG_URL:-$DEVAUDIT_BASE_URL_VAR}"
121
+ if [ -z "$BASE" ] || [ -z "$DEVAUDIT_API_KEY" ]; then
122
+ echo "::warning::DevAudit not configured — skipping feature E2E upload."
123
+ exit 0
124
+ fi
125
+ export DEVAUDIT_BASE_URL="${BASE%/}"
126
+ if [ -d playwright-report ]; then
127
+ zip -qr playwright-report.zip playwright-report/ 2>/dev/null || true
128
+ fi
129
+ if [ -f playwright-report.zip ]; then
130
+ bash scripts/upload-evidence.sh \
131
+ {{PROJECT_SLUG}} "$REQ_ID" test_report playwright-report.zip \
132
+ --category test_report --release "$REQ_ID" --create-release-if-missing \
133
+ --environment uat --sdlc-stage 2 \
134
+ --git-sha "${{ github.event.pull_request.head.sha }}" \
135
+ --ci-run-id "${{ github.run_id }}" --branch "${{ github.head_ref }}" \
136
+ --meta-key "origin=feature" \
137
+ || echo "::warning::feature E2E report upload failed"
138
+ fi
@@ -164,7 +164,7 @@ jobs:
164
164
  bash scripts/upload-evidence.sh \
165
165
  "${PROJECT_SLUG}" "${VERSION}" test_report prod-smoke-results.json \
166
166
  --release "${VERSION}" --create-release-if-missing --environment production \
167
- --category test_report --git-sha "${GIT_SHA}" --ci-run-id "${CI_RUN}" --branch main \
167
+ --category test_report --sdlc-stage 5 --git-sha "${GIT_SHA}" --ci-run-id "${CI_RUN}" --branch main \
168
168
  || echo "Warning: smoke upload failed for ${VERSION}"
169
169
  fi
170
170
  # Carry the release ticket into the production environment so the
@@ -179,7 +179,7 @@ jobs:
179
179
  bash scripts/upload-evidence.sh \
180
180
  "${PROJECT_SLUG}" "${VERSION}" compliance_document "$TICKET" \
181
181
  --release "${VERSION}" --create-release-if-missing --environment production \
182
- --category release_artifact --git-sha "${GIT_SHA}" --ci-run-id "${CI_RUN}" --branch main \
182
+ --category release_artifact --sdlc-stage 5 --git-sha "${GIT_SHA}" --ci-run-id "${CI_RUN}" --branch main \
183
183
  || echo "Warning: ticket upload failed for ${VERSION}"
184
184
  else
185
185
  echo "No RELEASE-TICKET-${VERSION}.md found — skipping ticket (date-versioned or archived)."