@metasession.co/devaudit-cli 0.3.11 → 0.3.13

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.
Files changed (68) hide show
  1. package/dist/index.js +94 -6
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -2
  4. package/scripts/upload-evidence.sh +55 -1
  5. package/sdlc/ai-rules/SDLC_RULES.md +27 -7
  6. package/sdlc/files/_common/0-project-setup.md +13 -7
  7. package/sdlc/files/_common/Periodic_Security_Review_Schedule.md +5 -5
  8. package/sdlc/files/_common/README_TEMPLATE.md +8 -8
  9. package/sdlc/files/_common/Test_Architecture.md +15 -15
  10. package/sdlc/files/_common/Test_Plan_TEMPLATE.md +13 -13
  11. package/sdlc/files/_common/Test_Policy.md +2 -2
  12. package/sdlc/files/_common/Test_Strategy.md +10 -10
  13. package/sdlc/files/_common/governance/ai-disclosure.md.template +3 -3
  14. package/sdlc/files/_common/governance/dpia.md.template +3 -3
  15. package/sdlc/files/_common/governance/incident-report.md.template +3 -3
  16. package/sdlc/files/_common/governance/nil-incident-report.md.template +1 -1
  17. package/sdlc/files/_common/governance/periodic-review.md.template +3 -3
  18. package/sdlc/files/_common/governance/risk-register.md.template +1 -1
  19. package/sdlc/files/_common/governance/ropa.md.template +2 -2
  20. package/sdlc/files/_common/joining-an-existing-project.md +4 -4
  21. package/sdlc/files/_common/scripts/check-host-deployment.sh +107 -0
  22. package/sdlc/files/_common/scripts/check-host-deployment.test.sh +119 -0
  23. package/sdlc/files/_common/scripts/check-release-pr-scope.sh +95 -0
  24. package/sdlc/files/_common/scripts/check-release-pr-scope.test.sh +137 -0
  25. package/sdlc/files/_common/scripts/close-out-release.sh +175 -54
  26. package/sdlc/files/_common/scripts/close-out-release.test.sh +90 -0
  27. package/sdlc/files/_common/scripts/extract-release-metadata.sh +65 -0
  28. package/sdlc/files/_common/scripts/extract-release-metadata.test.sh +38 -0
  29. package/sdlc/files/_common/scripts/generate-bundled-changes.sh +307 -58
  30. package/sdlc/files/_common/scripts/generate-bundled-changes.test.sh +128 -78
  31. package/sdlc/files/_common/scripts/generate-housekeeping-release-ticket.sh +18 -9
  32. package/sdlc/files/_common/scripts/generate-housekeeping-release-ticket.test.sh +66 -0
  33. package/sdlc/files/_common/scripts/generate-security-summary.sh +14 -5
  34. package/sdlc/files/_common/scripts/generate-security-summary.test.sh +57 -0
  35. package/sdlc/files/_common/scripts/prepare-release-pr.sh +44 -4
  36. package/sdlc/files/_common/scripts/render-test-cycles.sh +227 -0
  37. package/sdlc/files/_common/scripts/render-test-cycles.test.sh +107 -0
  38. package/sdlc/files/_common/scripts/report-test-cycle.sh +344 -0
  39. package/sdlc/files/_common/scripts/submit-bundle-manifest.sh +100 -0
  40. package/sdlc/files/_common/scripts/submit-bundle-manifest.test.sh +138 -0
  41. package/sdlc/files/_common/scripts/upload-evidence.sh +55 -1
  42. package/sdlc/files/_common/scripts/upload-evidence.test.sh +119 -0
  43. package/sdlc/files/_common/scripts/validate-compliance-artifacts.sh +169 -2
  44. package/sdlc/files/_common/scripts/validate-compliance-artifacts.test.sh +169 -0
  45. package/sdlc/files/_common/scripts/validate-test-summary.test.sh +4 -4
  46. package/sdlc/files/_common/skills/adr-author/SKILL.md +2 -2
  47. package/sdlc/files/_common/skills/e2e-test-engineer/SKILL.md +2 -2
  48. package/sdlc/files/_common/skills/e2e-test-engineer/references/bootstrap.md +5 -5
  49. package/sdlc/files/_common/skills/governance-doc-author/references/incident-classification.md +1 -1
  50. package/sdlc/files/_common/skills/requirements-aligner/SKILL.md +4 -4
  51. package/sdlc/files/_common/skills/sdlc-implementer/SKILL.md +57 -3
  52. package/sdlc/files/_common/skills/sdlc-implementer/references/change-request-loop.md +1 -1
  53. package/sdlc/files/_common/skills/sdlc-implementer/references/compliance-constraints.md +7 -14
  54. package/sdlc/files/ci/check-release-approval.yml.template +18 -28
  55. package/sdlc/files/ci/ci.yml.template +95 -35
  56. package/sdlc/files/ci/close-out-release.yml.template +7 -4
  57. package/sdlc/files/ci/compliance-evidence.yml.template +234 -49
  58. package/sdlc/files/ci/feature-e2e.yml.template +84 -1
  59. package/sdlc/files/ci/post-deploy-prod.yml.template +59 -4
  60. package/sdlc/files/ci/python/ci.yml.template +60 -12
  61. package/sdlc/files/ci/quality-gates-provenance.yml.template +123 -28
  62. package/sdlc/package.json +1 -1
  63. package/sdlc/src/bin/devaudit-sdlc.js +44 -2
  64. package/sdlc/src/blueprints/1-plan-requirement.raw.md +6 -1
  65. package/sdlc/src/blueprints/2-implement-and-test.raw.md +1 -1
  66. package/sdlc/src/blueprints/3-compile-evidence.raw.md +102 -20
  67. package/sdlc/src/blueprints/4-submit-for-review.raw.md +3 -3
  68. package/sdlc/src/blueprints/5-deploy-main.raw.md +2 -2
@@ -126,6 +126,7 @@ make_fixture "$WORKDIR/case3" "Ref: REQ-030"
126
126
  mkdir -p compliance/evidence/REQ-030
127
127
  echo "scope" > compliance/evidence/REQ-030/test-scope.md
128
128
  echo "plan" > compliance/evidence/REQ-030/test-plan.md
129
+ echo "summary" > compliance/evidence/REQ-030/test-execution-summary.md
129
130
  touch compliance/pending-releases/RELEASE-TICKET-REQ-030.md
130
131
  git add . && git commit -q --amend --no-edit
131
132
  run_validator
@@ -147,6 +148,7 @@ make_fixture "$WORKDIR/case4" "Ref: REQ-031"
147
148
  mkdir -p compliance/evidence/REQ-031
148
149
  echo "scope" > compliance/evidence/REQ-031/test-scope.md
149
150
  echo "plan" > compliance/evidence/REQ-031/test-plan.md
151
+ echo "summary" > compliance/evidence/REQ-031/test-execution-summary.md
150
152
  # Only the superseded location — neither pending- nor approved-releases.
151
153
  touch compliance/superseded-releases/RELEASE-TICKET-REQ-031.md
152
154
  git add . && git commit -q --amend --no-edit
@@ -252,8 +254,175 @@ assert_grep "no evidence-dir ERROR for prose-only REQ-002" 'ERROR: Evidence dire
252
254
  assert_exit "validator exits 0 when future REQ is only prose-mentioned" 0
253
255
  cd "$WORKDIR"
254
256
 
257
+ # --- case 8: tracked REQ without test-execution-summary fails ---
258
+ #
259
+ # Regression for devaudit-installer#341: tracked releases must not pass
260
+ # validation without the per-release test report that satisfies the
261
+ # portal's Test Reports gate.
262
+
263
+ echo "Case 8: tracked REQ missing test-execution-summary fails"
264
+ make_fixture "$WORKDIR/case8" "Ref: REQ-341"
265
+ {
266
+ echo '# RTM'
267
+ echo
268
+ echo '| ID | Description | Status |'
269
+ echo '| --- | --- | --- |'
270
+ echo '| REQ-341 | Missing test summary | TESTED - PENDING SIGN-OFF |'
271
+ } > compliance/RTM.md
272
+ mkdir -p compliance/evidence/REQ-341
273
+ echo "scope" > compliance/evidence/REQ-341/test-scope.md
274
+ echo "plan" > compliance/evidence/REQ-341/test-plan.md
275
+ touch compliance/pending-releases/RELEASE-TICKET-REQ-341.md
276
+ git add . && git commit -q --amend --no-edit
277
+ run_validator
278
+ assert_grep "missing-summary ERROR emitted" 'ERROR: Test execution summary missing: compliance/evidence/REQ-341/test-execution-summary.md' 1
279
+ assert_exit "validator exits 1 when tracked REQ lacks test-execution-summary" 1
280
+ cd "$WORKDIR"
281
+
255
282
  # --- summary ---
256
283
 
284
+ # --- case 9: bundled release context missing from canonical artefacts fails ---
285
+ echo "Case 9: bundled release artefacts without context headings fail"
286
+ make_fixture "$WORKDIR/case9" "Ref: REQ-344"
287
+ {
288
+ echo '# RTM'
289
+ echo
290
+ echo '| ID | Description | Status |'
291
+ echo '| --- | --- | --- |'
292
+ echo '| REQ-344 | Bundled release context missing | TESTED - PENDING SIGN-OFF |'
293
+ } > compliance/RTM.md
294
+ mkdir -p compliance/evidence/REQ-344
295
+ echo "scope" > compliance/evidence/REQ-344/test-scope.md
296
+ echo "plan" > compliance/evidence/REQ-344/test-plan.md
297
+ echo "summary" > compliance/evidence/REQ-344/test-execution-summary.md
298
+ echo "security" > compliance/evidence/REQ-344/security-summary.md
299
+ echo "ai note" > compliance/evidence/REQ-344/ai-use-note.md
300
+ cat > compliance/pending-releases/RELEASE-TICKET-REQ-344.md <<'EOF'
301
+ # Release Ticket — REQ-344
302
+
303
+ ## Summary
304
+ Tracked release without bundle section.
305
+ EOF
306
+ echo "## Bundled Changes" > compliance/pending-releases/BUNDLED-CHANGES-REQ-344.md
307
+ git add . && git commit -q --amend --no-edit
308
+ run_validator
309
+ assert_grep "missing bundled manifest is reported" "ERROR: Bundled release evidence exists but BUNDLED-CHANGES-REQ-344.json is missing" 1
310
+ assert_grep "missing structured fields on bundled evidence are reported" "ERROR: Bundled release evidence is missing bundled field '\\*\\*Core tracked release:\\*\\*'" 1
311
+ assert_grep "missing structured fields on ticket are reported" "ERROR: Release ticket is missing bundled field '\\*\\*Core tracked release:\\*\\*'" 1
312
+ assert_grep "missing bundled section on ticket is reported" "ERROR: Bundled release evidence exists but the release ticket is missing" 1
313
+ assert_grep "missing bundled section on summary is reported" "ERROR: Bundled release evidence exists but test-execution-summary.md is missing" 1
314
+ assert_grep "missing bundled section on security summary is reported" "ERROR: Bundled release evidence exists but security-summary.md is missing" 1
315
+ assert_grep "missing bundled section on ai note is reported" "ERROR: Bundled release evidence exists but ai-use-note.md is missing" 1
316
+ assert_exit "validator exits 1 when bundled artefacts lack required headings" 1
317
+ cd "$WORKDIR"
318
+
319
+ # --- case 10: bundled release context present in canonical artefacts passes ---
320
+ echo "Case 10: bundled release artefacts with context headings pass"
321
+ make_fixture "$WORKDIR/case10" "Ref: REQ-345"
322
+ {
323
+ echo '# RTM'
324
+ echo
325
+ echo '| ID | Description | Status |'
326
+ echo '| --- | --- | --- |'
327
+ echo '| REQ-345 | Bundled release context present | TESTED - PENDING SIGN-OFF |'
328
+ } > compliance/RTM.md
329
+ mkdir -p compliance/evidence/REQ-345
330
+ echo "scope" > compliance/evidence/REQ-345/test-scope.md
331
+ echo "plan" > compliance/evidence/REQ-345/test-plan.md
332
+ cat > compliance/evidence/REQ-345/test-execution-summary.md <<'EOF'
333
+ # Test Execution Summary — REQ-345
334
+
335
+ ## Bundled Release Context
336
+ - **Core tracked release:** REQ-345
337
+ - **Absorbed predecessor releases:** None
338
+ - **Absorbed non-release work:** housekeeping syncs only
339
+ - **Why bundled here:** housekeeping consolidation
340
+ - **Evidence impact:** core REQ proof unchanged; gate evidence covers full develop state
341
+ - **Reviewer impact:** reviewer is approving the tracked REQ plus absorbed housekeeping context
342
+ - **Security / risk impact:** None beyond core REQ
343
+ - **Reference:** compliance/pending-releases/BUNDLED-CHANGES-REQ-345.md
344
+ EOF
345
+ cat > compliance/evidence/REQ-345/security-summary.md <<'EOF'
346
+ # Security Summary — REQ-345
347
+
348
+ ## Bundled Release Context
349
+ - **Core tracked release:** REQ-345
350
+ - **Absorbed predecessor releases:** None
351
+ - **Absorbed non-release work:** housekeeping syncs only
352
+ - **Why bundled here:** housekeeping consolidation
353
+ - **Evidence impact:** no extra security evidence beyond the shared gate outputs
354
+ - **Reviewer impact:** reviewer should treat the shared gate results as covering the absorbed housekeeping work too
355
+ - **Security / risk impact:** None beyond core REQ
356
+ - **Reference:** compliance/pending-releases/BUNDLED-CHANGES-REQ-345.md
357
+ EOF
358
+ cat > compliance/evidence/REQ-345/ai-use-note.md <<'EOF'
359
+ # AI Use Record — REQ-345
360
+
361
+ ## Bundled Release Context
362
+ - **Core tracked release:** REQ-345
363
+ - **Absorbed predecessor releases:** None
364
+ - **Absorbed non-release work:** housekeeping syncs only
365
+ - **Why bundled here:** housekeeping consolidation
366
+ - **Evidence impact:** no AI-generated evidence split beyond the shared bundle context
367
+ - **Reviewer impact:** reviewer should read the bundle note as part of the approval scope
368
+ - **Security / risk impact:** None beyond core REQ
369
+ - **Reference:** compliance/pending-releases/BUNDLED-CHANGES-REQ-345.md
370
+ EOF
371
+ cat > compliance/pending-releases/RELEASE-TICKET-REQ-345.md <<'EOF'
372
+ # Release Ticket — REQ-345
373
+
374
+ ## Summary
375
+ Tracked release with bundle section.
376
+
377
+ ## Bundled Changes
378
+ - **Core tracked release:** REQ-345
379
+ - **Absorbed predecessor releases:** None
380
+ - **Absorbed non-release work:** housekeeping syncs only
381
+ - **Why bundled here:** housekeeping consolidation
382
+ - **Evidence impact:** gate evidence and release reports include the absorbed housekeeping changes
383
+ - **Reviewer impact:** approval scope is the tracked REQ plus the absorbed housekeeping context
384
+ - **Security / risk impact:** None beyond core REQ
385
+ - **Reference:** compliance/pending-releases/BUNDLED-CHANGES-REQ-345.md
386
+ EOF
387
+ cat > compliance/pending-releases/BUNDLED-CHANGES-REQ-345.md <<'EOF'
388
+ ## Bundled Changes
389
+
390
+ - **Core tracked release:** `REQ-345`
391
+ - **Bundle manifest:** `BUNDLED-CHANGES-REQ-345.json`
392
+ - **Manifest hash:** `sha256:test-bundle-hash`
393
+ - **Absorbed predecessor releases:** None
394
+ - **Absorbed non-release work:** housekeeping syncs only
395
+ - **Why bundled here:** housekeeping consolidation
396
+ - **Evidence impact:** gate evidence and release reports include the absorbed housekeeping changes
397
+ - **Reviewer impact:** approval scope is the tracked REQ plus the absorbed housekeeping context
398
+ - **Security / risk impact:** None beyond core REQ
399
+ - **Reference:** commit range `abc123..HEAD`
400
+
401
+ ### Absorbed Non-Release Work
402
+
403
+ - `abc123` chore: sync templates
404
+ EOF
405
+ cat > compliance/pending-releases/BUNDLED-CHANGES-REQ-345.json <<'EOF'
406
+ {
407
+ "schemaVersion": 1,
408
+ "approvalRelease": { "version": "REQ-345" },
409
+ "coreRelease": { "version": "REQ-345" },
410
+ "members": [],
411
+ "nonReleaseWorkItems": [],
412
+ "manifestHash": "sha256:test-bundle-hash"
413
+ }
414
+ EOF
415
+ git add . && git commit -q --amend --no-edit
416
+ run_validator
417
+ assert_grep "bundled manifest accepted" "OK: Bundled release manifest present: compliance/pending-releases/BUNDLED-CHANGES-REQ-345.json" 1
418
+ assert_grep "bundled ticket section accepted" "OK: Release ticket documents bundled release context" 1
419
+ assert_grep "bundled test summary section accepted" "OK: test-execution-summary.md documents bundled release context" 1
420
+ assert_grep "bundled security summary section accepted" "OK: security-summary.md documents bundled release context" 1
421
+ assert_grep "bundled ai note section accepted" "OK: ai-use-note.md documents bundled release context" 1
422
+ assert_grep "structured bundled evidence accepted" "OK: Bundled release evidence carries the required structured fields" 1
423
+ assert_exit "validator exits 0 when bundled artefacts carry required headings" 0
424
+ cd "$WORKDIR"
425
+
257
426
  echo
258
427
  echo "=== validate-compliance-artifacts.test.sh: $PASS passed, $FAIL failed ==="
259
428
  [ "$FAIL" -eq 0 ]
@@ -182,7 +182,7 @@ make_fixture "$D6" "REQ-006" << 'EOF'
182
182
  ## Accepted skips
183
183
 
184
184
  | Spec | Test | REQ/AC | Classification | Resolution attempted | Approved by | Rationale |
185
- |------|------|--------|---------------|---------------------|-------------|----------|
185
+ | ------ | ------ | -------- | --------------- | --------------------- | ------------- | ---------- |
186
186
  | e2e/foo.spec.ts | "AC1: bar dialog" | REQ-006/AC1 | intentional_non_applicability | N/A — API-only change | operator | API-only change, no UI surface |
187
187
 
188
188
  **Final assessment:** All gates passed. E2E skipped — API-only change.
@@ -279,7 +279,7 @@ make_fixture "$D12" "REQ-012" << 'EOF'
279
279
  ## Accepted skips
280
280
 
281
281
  | Spec | Test | REQ/AC | Classification | Resolution attempted | Approved by | Rationale |
282
- |------|------|--------|---------------|---------------------|-------------|----------|
282
+ | ------ | ------ | -------- | --------------- | --------------------- | ------------- | ---------- |
283
283
  | e2e/foo.spec.ts | "AC3: bar dialog" | REQ-012/AC3 | intentional_non_applicability | N/A — API-only change | operator | API-only change, no UI surface |
284
284
 
285
285
  **Final assessment:** All gates passed. E2E skipped — API-only change.
@@ -317,7 +317,7 @@ make_fixture "$D14" "REQ-014" << 'EOF'
317
317
  ## Accepted skips
318
318
 
319
319
  | Spec | Test | REQ/AC | Classification | Resolution attempted | Approved by | Rationale |
320
- |------|------|--------|---------------|---------------------|-------------|----------|
320
+ | ------ | ------ | -------- | --------------- | --------------------- | ------------- | ---------- |
321
321
 
322
322
  **Final assessment:** All gates passed. E2E skipped — API-only change.
323
323
  EOF
@@ -338,7 +338,7 @@ make_fixture "$D15" "REQ-015" << 'EOF'
338
338
  ## Accepted skips
339
339
 
340
340
  | Spec | Test | REQ/AC | Classification | Resolution attempted | Approved by | Rationale |
341
- |------|------|--------|---------------|---------------------|-------------|----------|
341
+ | ------ | ------ | -------- | --------------- | --------------------- | ------------- | ---------- |
342
342
  | e2e/foo.spec.ts | "AC3: bar dialog" | REQ-015/AC3 | intentional_non_applicability | N/A — API-only change | | API-only change, no UI surface |
343
343
 
344
344
  **Final assessment:** All gates passed. E2E skipped — API-only change.
@@ -12,7 +12,7 @@ The skill is **Phase A scope** (per [DevAudit-Installer#120](https://github.com/
12
12
  ## What this skill owns
13
13
 
14
14
  | Artefact | Lives at | Tier |
15
- |---|---|---|
15
+ | --- | --- | --- |
16
16
  | `docs/ADR/ADR-NNN-<slug>.md` (the SoT, project-spanning) | Top-level project docs | 2 (project strategy) |
17
17
  | `compliance/evidence/REQ-XXX/architecture-decision.md` (per-REQ Tier 3 evidence) | Per-REQ evidence directory | 3 (per-REQ) |
18
18
 
@@ -57,7 +57,7 @@ Input: the REQ's `compliance/plans/REQ-XXX/implementation-plan.md` plus the work
57
57
  **Step 2 — Apply the ADR-worthiness decision tree.** The skill judges *architectural significance* via these signals — any one matching ⇒ ADR warranted:
58
58
 
59
59
  | Signal | Examples | Verdict |
60
- |---|---|---|
60
+ | --- | --- | --- |
61
61
  | New third-party runtime dependency | adding `redis`, `bull`, a new ORM, a new auth provider package | ADR |
62
62
  | New external service | introducing Stripe, Twilio, a new SaaS integration | ADR |
63
63
  | New database / cache / queue tier | adding Redis alongside Postgres, swapping MongoDB for Postgres | ADR |
@@ -136,7 +136,7 @@ For each scenario, write a one-line description. Present the full grouped list t
136
136
  When designing each scenario, also pick the tier it'll live in. Three tiers map to MoSCoW priority + gating point (see `Test_Strategy.md` § *E2E gating model*):
137
137
 
138
138
  | Tier | File location | Picks this when… |
139
- |---|---|---|
139
+ | --- | --- | --- |
140
140
  | **smoke** | `e2e/smoke/*.spec.ts` | Cross-cutting sanity that proves the app is up: login, basic nav, one canonical CRUD per main domain. Runs on every push to the integration branch. Keep small — total smoke wall-clock target is ~3–5 min. |
141
141
  | **critical** | `e2e/critical/*.spec.ts` | Must-priority SRS item that breaks a headline flow if it regresses. Examples: payment authorisation, order completion, admin permission editing, RBAC enforcement on financial surfaces. Runs on PR-to-release-branch. Total critical wall-clock target ~10–15 min (includes smoke). |
142
142
  | **regression** | `e2e/<area>/*.spec.ts` | Should/Could-priority SRS item, edge cases, less-load-bearing flows. Runs nightly + post-merge + dispatch. Total full pack can be 30+ min; that's the point of the tier. |
@@ -365,7 +365,7 @@ Every defect filed from Phase 6 becomes `incident_report` evidence when (a) the
365
365
  Classify the defect against this table when filing — the canonical version lives at `governance-doc-author/references/incident-classification.md`, mirrored here for the e2e workflow:
366
366
 
367
367
  | Defect characteristic | Frameworks/clauses attributed |
368
- |---|---|
368
+ | --- | --- |
369
369
  | **Any test failure / defect** (baseline — always) | `ISO29119.3.5.4` Test incident report |
370
370
  | **Ops impact** (downtime, persistent errors, perf regression, data corruption) | + `SOC2.CC7.2` System monitoring and incident response |
371
371
  | **Security vulnerability** (auth bypass, injection, data exposure) | + `SOC2.CC7.2` + relevant ISO 27001 controls |
@@ -20,7 +20,7 @@ Recommend a primary, mention the runner-up, get user confirmation before install
20
20
  ### Web apps — JavaScript / TypeScript
21
21
 
22
22
  | Stack | Primary | Runner-up | Rationale |
23
- |---|---|---|---|
23
+ | --- | --- | --- | --- |
24
24
  | React / Next.js / Remix | **Playwright** | Cypress | Fast, parallel by default, multi-browser, first-party TS, built-in visual regression, excellent trace viewer. |
25
25
  | Vue / Nuxt | **Playwright** | Cypress | Same reasons. |
26
26
  | Angular | **Playwright** | Cypress | Playwright has overtaken Cypress as the Angular community default; Cypress still common in established Angular shops. |
@@ -32,7 +32,7 @@ Recommend a primary, mention the runner-up, get user confirmation before install
32
32
  ### Mobile
33
33
 
34
34
  | Stack | Primary | Runner-up | Rationale |
35
- |---|---|---|---|
35
+ | --- | --- | --- | --- |
36
36
  | React Native | **Detox** | Appium | Native, fast, integrates with RN test infra. |
37
37
  | Native iOS / Android cross-platform | **Appium** | Maestro | Industry standard; Maestro is gaining popularity for simpler flows. |
38
38
  | Mobile web | **Playwright** (mobile emulation) | Appium (for real-device need) | Playwright covers viewport + UA emulation; Appium for real-device touch interactions. |
@@ -40,14 +40,14 @@ Recommend a primary, mention the runner-up, get user confirmation before install
40
40
  ### Desktop
41
41
 
42
42
  | Stack | Primary | Runner-up | Rationale |
43
- |---|---|---|---|
43
+ | --- | --- | --- | --- |
44
44
  | Electron | **Playwright** | WebdriverIO + Electron service | Playwright has first-party Electron support. |
45
45
  | Tauri | **WebdriverIO** + Tauri driver | — | Official path. |
46
46
 
47
47
  ### Backend-rendered / non-JS web apps
48
48
 
49
49
  | Stack | Primary | Runner-up | Rationale |
50
- |---|---|---|---|
50
+ | --- | --- | --- | --- |
51
51
  | Python (Django, Flask, FastAPI with templates) | **pytest-playwright** | Selenium + pytest | Same Playwright engine, idiomatic for Python test suites. |
52
52
  | Ruby on Rails | **Capybara + Cuprite** | Capybara + Selenium | Cuprite uses CDP, faster than Selenium. |
53
53
  | Java (Spring etc.) | **Playwright for Java** | Selenium + JUnit/TestNG | Playwright Java is mature; Selenium still dominant in enterprise Java. |
@@ -67,7 +67,7 @@ Recommend a primary, mention the runner-up, get user confirmation before install
67
67
  Only add visual regression if the user asked for it or the originating issue is visually significant. Default off for greenfield bootstrap unless explicitly requested.
68
68
 
69
69
  | Need | Recommendation | Notes |
70
- |---|---|---|
70
+ | --- | --- | --- |
71
71
  | Default for Playwright | **`toHaveScreenshot()` built-in** | Zero extra deps; baselines stored in repo. Configure `threshold` and `maxDiffPixels`. |
72
72
  | Default for Cypress | **`cypress-image-snapshot`** | Or `cypress-visual-regression`. Both store baselines in repo. |
73
73
  | Default for WebdriverIO | **`@wdio/visual-service`** | Maintained, image-comparison-based. |
@@ -7,7 +7,7 @@ Used by both `e2e-test-engineer` (when filing defects) and `governance-doc-autho
7
7
  Every `incident_report` evidence row closes `ISO29119.3.5.4` (baseline). Additional clauses depend on the incident's scope.
8
8
 
9
9
  | Defect / incident characteristic | Frameworks/clauses attributed |
10
- |---|---|
10
+ | --- | --- |
11
11
  | **Any test failure / defect** (baseline — always) | `ISO29119.3.5.4` Test incident report |
12
12
  | **Ops impact** (downtime, persistent errors, perf regression, data corruption) | + `SOC2.CC7.2` System monitoring and incident response |
13
13
  | **Security vulnerability** (auth bypass, injection, data exposure beyond GDPR scope) | + `SOC2.CC7.2` + relevant ISO 27001 controls |
@@ -12,7 +12,7 @@ The skill is **Phase A scope** (per [DevAudit-Installer#119](https://github.com/
12
12
  ## What this skill owns
13
13
 
14
14
  | Artefact | Lives at | Tier |
15
- |---|---|---|
15
+ | --- | --- | --- |
16
16
  | `docs/SRS.md` (the SoT, project-spanning) | Top-level project docs | 2 (project strategy) |
17
17
  | `compliance/evidence/REQ-XXX/srs-alignment.md` (per-REQ Tier 3 evidence) | Per-REQ evidence directory | 3 (per-REQ) |
18
18
 
@@ -65,7 +65,7 @@ Input: the REQ's `compliance/plans/REQ-XXX/implementation-plan.md` plus the work
65
65
  **Step 3 — Categorise each AC:**
66
66
 
67
67
  | AC ⇒ SRS state | Action |
68
- |---|---|
68
+ | --- | --- |
69
69
  | **Exact match** — AC traces 1:1 to an existing SRS item, no behavioural delta | Record the mapping; no SRS edit needed |
70
70
  | **Match + drift** — existing SRS item covers the AC's surface but the behaviour has shifted (e.g. new field, new edge case, new error path) | Flag the item as *potentially stale*; the plan must mark it for update in this cycle OR justify why the SRS prose still covers it |
71
71
  | **No match** — AC introduces behaviour the SRS doesn't yet describe | Propose new `REQ-AREA-NNN` (next free ID per area — see Step 4) with a Given/When/Then stub the operator edits |
@@ -79,7 +79,7 @@ Input: the REQ's `compliance/plans/REQ-XXX/implementation-plan.md` plus the work
79
79
  ## SRS items proposed/touched
80
80
 
81
81
  | AC | SRS item | Status | Notes |
82
- |---|---|---|---|
82
+ | --- | --- | --- | --- |
83
83
  | AC1 | REQ-ORDER-005 (existing) | unchanged | Trace-only |
84
84
  | AC2 | REQ-INV-010 (new — proposed) | stub | <one-line behaviour description> |
85
85
  | AC3 | REQ-INV-011 (new — proposed) | stub | <one-line> |
@@ -113,7 +113,7 @@ generated_at: <ISO timestamp>
113
113
  ## ACs traced
114
114
 
115
115
  | AC | SRS item | Action this cycle |
116
- |---|---|---|
116
+ | --- | --- | --- |
117
117
  | AC1 | REQ-ORDER-005 | unchanged |
118
118
  | AC2 | REQ-INV-010 | added (new — see Phase 1 stub) |
119
119
  | AC3 | REQ-INV-011 | added (new) |
@@ -385,7 +385,7 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
385
385
  - **`requirements-aligner` fails** (e.g. no `docs/SRS.md`): If `block_on_stage_1` is true, halt — "requirements-aligner could not find SRS.md. Operator action — create `docs/SRS.md` or disable `requirements_aligner.block_on_stage_1` in `sdlc-config.json`." If false, warn and continue with `@srs-deferred` on all ACs.
386
386
  - **`adr-author` fails**: Warn and continue — ADR is advisory by default. Mark the plan's "Architecture decisions" section as "ADR assessment skipped — <error>".
387
387
  - **`risk-register-keeper` fails**: If `block_on_stage_1` is true, halt. If false, warn and continue — mark the plan's "Risk register entries" section as "Risk assessment skipped — <error>".
388
- 9. **Update `compliance/RTM.md`** with the new entry: REQ-XXX, title, risk class, linked issue, linked test cases (placeholder), and a provenance marker `sdlc-implementer@<version>` (devaudit-installer#226). The provenance column is the last column in the RTM row — `validate-commits.sh` in CI checks for its presence when `feat`/`fix`/`refactor`/`perf` commits cite a REQ-XXX. Without the stamp, CI fails with "no sdlc-implementer provenance in RTM.md." If the RTM table doesn't have a provenance column, add one with header `Provenance`.
388
+ 9. **Update `compliance/RTM.md`** with the new entry: REQ-XXX, title, risk class, linked issue, linked test cases (placeholder), and a provenance marker `sdlc-implementer@<version>` (devaudit-installer#226). The provenance column is the last column in the RTM row — `validate-commits.sh` in CI checks for its presence when `feat`/`fix`/`refactor`/`perf` commits cite a REQ-XXX. Without the stamp, CI fails with "no sdlc-implementer provenance in RTM.md." If the RTM table doesn't have a provenance column, add one with header `Provenance`. If any RTM cell text needs literal pipe characters (regexes, enum examples, status notes), escape them as `\|` rather than writing bare `|`, otherwise markdownlint will misparse the row as extra columns.
389
389
  10. **Post plan summary as an issue comment.** Format: TL;DR; Risk class + signals; Acceptance criteria (with SRS-IDs); Architectural decisions (ADR-NNN reference or no-ADR rationale); Risk register entries (RISK-NNN list); Technical approach (one paragraph); Dependencies; Test scope.
390
390
  11. **Checkpoint** — pause for human approval **iff** risk class is HIGH or CRITICAL. LOW and MEDIUM pass through to Phase 2 automatically. The checkpoint can be forced on for all classes via the `--require-plan-approval` flag (or `DEVAUDIT_REQUIRE_PLAN_APPROVAL=1` env var) for orgs that want it always-on.
391
391
  12. **Update SDLC status sticky** before exiting Phase 1: `bash scripts/update-sdlc-status.sh "$ISSUE_NUM" "Phase 1 complete — plan written to compliance/plans/REQ-XXX/implementation-plan.md (risk class <CLASS>)" "Phase 2 — sdlc-implementer auto-continuing"` (or "Operator action — review plan + ping resume" if the HIGH/CRITICAL checkpoint paused).
@@ -511,6 +511,59 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
511
511
 
512
512
  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.
513
513
 
514
+ 5bb. **Render the Test Cycles table from the portal's cycle read model when available (devaudit-installer#394).** Do not hand-build cycle rows from uploaded artefacts if the portal exposes first-class cycle records. Query the release-journey / cycle API, save the JSON, and render the markdown table with:
515
+
516
+ ```bash
517
+ bash scripts/render-test-cycles.sh /tmp/release-journey.json
518
+ ```
519
+
520
+ First-class rows must preserve:
521
+ - source release
522
+ - SDLC stage
523
+ - cycle ordinal within that source release + stage
524
+ - cycle kind / outcome
525
+ - workflow or run link
526
+ - related evidence
527
+ - incident or remediation reference
528
+
529
+ If the portal does not yet expose first-class cycles, the same helper emits the legacy `testCycleId` grouping fallback and labels it as such. Keep the fallback note in the final `test-execution-summary.md`; it is part of the audit trail during rollout.
530
+
531
+ 5c. **Run the Phase 3 completion guard before any PR/release-review step (devaudit-installer#341).** The tracked-release evidence pack is incomplete until the required Git artefacts exist. Before proceeding past Phase 3, verify:
532
+
533
+ - `compliance/evidence/REQ-XXX/test-scope.md`
534
+ - `compliance/evidence/REQ-XXX/test-plan.md`
535
+ - `compliance/evidence/REQ-XXX/test-execution-summary.md`
536
+ - `compliance/evidence/REQ-XXX/security-summary.md`
537
+ - `compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md`
538
+ - `compliance/evidence/REQ-XXX/implementation-plan.md` when the REQ risk class requires it
539
+ - any already-mandatory AI artefacts required by the risk/usage rules
540
+ - if `compliance/pending-releases/BUNDLED-CHANGES-REQ-XXX.md` exists, regenerate the paired JSON manifest too and keep both aligned with the current approval scope
541
+ - if `compliance/pending-releases/BUNDLED-CHANGES-REQ-XXX.md` exists, the canonical artefacts must carry the bundle narrative too:
542
+ - release ticket includes `## Bundled Changes` or `## Absorbed Predecessor Releases`
543
+ - `test-execution-summary.md` includes `## Bundled Release Context`
544
+ - `security-summary.md` includes `## Bundled Release Context`
545
+ - `ai-use-note.md` includes `## Bundled Release Context` when AI use is documented
546
+
547
+ Run:
548
+
549
+ ```bash
550
+ MISSING=0
551
+ for f in \
552
+ compliance/evidence/REQ-XXX/test-scope.md \
553
+ compliance/evidence/REQ-XXX/test-plan.md \
554
+ compliance/evidence/REQ-XXX/test-execution-summary.md \
555
+ compliance/evidence/REQ-XXX/security-summary.md \
556
+ compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md
557
+ do
558
+ [ -f "$f" ] || { echo "MISSING: $f"; MISSING=1; }
559
+ done
560
+ [ "$MISSING" -eq 0 ] || exit 1
561
+ ```
562
+
563
+ If any required artefact is missing, halt with an explicit error and do **not** continue to Phase 4:
564
+
565
+ > "Phase 3 incomplete — `test-execution-summary.md` is missing. This file satisfies the portal's Test Reports gate (`evidence_type=test_report`). Create it before opening the release PR."
566
+
514
567
  6. **Organise artefacts** under `compliance/evidence/REQ-XXX/` with date-prefixed naming:
515
568
 
516
569
  ```
@@ -601,7 +654,7 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
601
654
  --base-url <devaudit-base-url>
602
655
  ```
603
656
 
604
- The watcher persists retry state in `.sdlc-pr-watch.json`, polls `gh pr view` + `gh pr checks`, re-runs likely flaky workflows automatically, and re-runs the Release Approval Gate when the portal is already approved but GitHub has not converged yet. Use `--once` when you only need a single classification pass.
657
+ The watcher persists retry state in `.sdlc-pr-watch.json`, polls `gh pr view` + `gh pr checks`, re-runs likely flaky workflows automatically, and re-runs the Release Approval Gate when the portal is already approved but GitHub has not converged yet. For a release PR (`$INTEGRATION_BRANCH -> $RELEASE_BRANCH`), it must not call the PR green until the full required release check set has reached terminal success: `Quality Gates`, `Release Scope Integrity`, `Compliance Validation`, `DevAudit Release Approval`, and `E2E Regression Suite`. Use `--once` when you only need a single classification pass.
605
658
 
606
659
  6. **Hard stop only after blocker classification.** Phase 4 ends here. Do not proceed to merge; the human's next action is reviewing on the portal or clearing the categorized blocker above.
607
660
  7. **Update SDLC status sticky** before halting: `bash scripts/update-sdlc-status.sh "$ISSUE_NUM" "Phase 4 — truthful release PR #<N> prepared against $RELEASE_BRANCH; blockers classified" "Operator action — review PR #<N> + approve UAT release on the portal; sdlc-implementer halts until you ping resume REQ-XXX"`. This is a critical handoff — the sticky must reflect that the agent has stopped + the operator is on the hook.
@@ -620,7 +673,7 @@ Reached only on the **tracked** route from Phase 0 (the issue is already fetched
620
673
 
621
674
  **Release Approval Gate retry (devaudit-installer#211 Gap 17).** If the Release Approval Gate check fails on the PR and the portal approval was already given (API sync delay, stale cache), retry logic: re-run the Release Approval Gate workflow up to 3 times with 30-second intervals (`gh workflow run check-release-approval.yml` or trigger via `workflow_dispatch`). If it still fails after 3 retries: halt — "Release Approval Gate still failing after 3 retries. Portal may show approval but the gate can't verify it. Operator action — check the portal release status manually, verify the API key is valid, and re-run the workflow from GitHub Actions if needed."
622
675
 
623
- **Auto-refresh on UAT approval (devaudit#562, devaudit-installer#283).** When the portal's UAT approval is granted, the portal automatically sends a `repository_dispatch('release-approved')` event to the consuming project's repo. This triggers `check-release-approval.yml` to re-run without manual intervention. The retry logic above is still needed for edge cases (API sync delays, network issues), but the common path is now fully automated. If the auto-refresh doesn't fire (e.g. portal GitHub trigger misconfigured), the manual retry sequence above remains the fallback.
676
+ **Auto-refresh on UAT approval (devaudit#562, devaudit-installer#283, #351).** When the portal's UAT approval is granted, the portal automatically sends a `repository_dispatch('release-approved')` event to the consuming project's repo. This triggers `check-release-approval.yml` to re-run without manual intervention and create a fresh passing `DevAudit Release Approval` check run on the approved PR head SHA. The retry logic above is still needed for edge cases (API sync delays, network issues), but the common path is now fully automated. If the auto-refresh doesn't fire (e.g. portal GitHub trigger misconfigured), the manual retry sequence above remains the fallback.
624
677
 
625
678
  ### Phase 5 — Finalise or change-request loop (SDLC stage 5)
626
679
 
@@ -640,6 +693,7 @@ Invoked separately by the user after UAT activity on the portal. Trigger: "resum
640
693
  - `gh pr merge <M> --merge` (merge commit; `--squash` and `--rebase` are blocked by branch protection on SDLC repos and would break the audit trail).
641
694
  - **Before watching `post-deploy-prod.yml`**, verify the workflow exists and has triggered: `gh run list --workflow post-deploy-prod.yml --limit 1 --json status,conclusion`. If no run appears within 5 minutes of the merge, halt — "post-deploy-prod.yml did not trigger after merge. Check workflow configuration, secrets, and deployment platform. Operator action — run `gh workflow run post-deploy-prod.yml` manually, then ping `resume REQ-XXX`."
642
695
  - Watch `post-deploy-prod.yml` via `gh run watch` — block until the workflow reaches a terminal state. Wrap in a timeout (30 minutes default, configurable via `sdlc-config.json:post_deploy.timeout_minutes`). If the timeout fires: halt — "post-deploy-prod.yml has not reached a terminal state in N minutes. The deployment may be stuck. Operator action — check hosting platform logs, decide whether to wait or rollback, then ping `resume REQ-XXX`."
696
+ - Treat `post-deploy-prod.yml` success as necessary but not sufficient. The workflow must also confirm the hosting platform's GitHub deployment status for the merged SHA reached terminal `success`. If the host deployment is still `queued` / `in_progress`, remain blocked. If it reaches `failure`, halt — "The host deployment for <sha> failed after merge. Do not approve Production or mark Released. Operator action — inspect hosting logs / rollback / resume once the production state is understood."
643
697
  - Verify production smoke evidence uploaded (`--environment production`) at `https://devaudit.metasession.co/projects/<slug>/releases/<version>`.
644
698
  - **Read `production_review.terminal_status` from `sdlc-config.json`** (default: `prod_review`). Branch:
645
699
  - If `released` (Option B): PATCH directly to `released` — `PATCH /releases/<version>` with `{"status": "released"}`.
@@ -193,7 +193,7 @@ If the portal state is `uat_rejected` (not `uat_changes_requested`), the reviewe
193
193
  The release ticket (`compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md`) `**Status:**` field is updated at each transition in the change-request loop, mirroring the portal's state machine for audit trail completeness:
194
194
 
195
195
  | Transition | Release ticket status |
196
- |---|---|
196
+ | --- | --- |
197
197
  | Entering iteration N | `CHANGES REQUESTED — ITERATION N` |
198
198
  | After evidence re-compile (Step 5) | `TESTED - PENDING SIGN-OFF (ITERATION N)` |
199
199
  | After UAT re-approval (Phase 5 happy path) | `APPROVED — READY FOR MERGE` |
@@ -8,8 +8,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
8
8
 
9
9
  ### 1. Never skip the UAT review gate
10
10
 
11
- | | |
12
- |---|---|
11
+ | | | | --- | --- |
13
12
  | **What** | The skill must not attempt to merge a PR while the `DevAudit Release Approval` check is red. |
14
13
  | **Why (framework)** | ISO 27001 A.8.32 (Change management); SOC 2 CC8 (Change management); EU AI Act Art. 14 (Human oversight). The UAT gate is the load-bearing human-oversight checkpoint. |
15
14
  | **Enforcement** | Portal-side via `check-release-approval.yml` workflow status check + branch protection. Skill-side: never call `gh pr merge` until the check is green. |
@@ -17,8 +16,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
17
16
 
18
17
  ### 2. For HIGH/CRITICAL, never act as the UAT approver
19
18
 
20
- | | |
21
- |---|---|
19
+ | | | | --- | --- |
22
20
  | **What** | The skill must verify at Phase 4 that the configured UAT reviewer (in `compliance/plans/REQ-XXX/implementation-plan.md` §Four-eyes attestation slot) differs from the skill-trigger user. If they match, halt. |
23
21
  | **Why (framework)** | SOC 2 CC8.1 — segregation of duties; ISO 27001 A.5.15 (Access control — duty segregation). The change-author cannot also be the change-approver for higher-risk work. |
24
22
  | **Enforcement** | Portal-side: the release-approval API rejects self-approval for MEDIUM/HIGH/CRITICAL risk classes. Skill-side: refuses to open the PR if the configured reviewer matches the trigger user. |
@@ -26,8 +24,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
26
24
 
27
25
  ### 3. Plan checkpoint mandatory for HIGH/CRITICAL
28
26
 
29
- | | |
30
- |---|---|
27
+ | | | | --- | --- |
31
28
  | **What** | At Phase 1 step 8, the skill pauses for human approval of the plan **iff** risk class is HIGH or CRITICAL. LOW/MEDIUM pass through automatically. Can be forced on for all classes via `--require-plan-approval` flag or `DEVAUDIT_REQUIRE_PLAN_APPROVAL=1` env var. |
32
29
  | **Why (framework)** | EU AI Act Art. 14 (Human oversight for high-risk AI systems); SOC 2 CC3 (Risk assessment requires human judgement); ISO 29119 §6 (Test management — planning is a documented human step). For HIGH/CRITICAL work the plan IS the design — human review must precede code. |
33
30
  | **Enforcement** | Skill-side. Phase 1 explicitly halts and waits for the human's "go" before Phase 2. |
@@ -35,8 +32,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
35
32
 
36
33
  ### 4. Change-request loop triggers full UAT re-review
37
34
 
38
- | | |
39
- |---|---|
35
+ | | | | --- | --- |
40
36
  | **What** | When new commits land on a PR after a UAT change-request, the portal's release-approval state resets. The skill respects the reset, surfaces a "UAT re-review needed" comment, and never assumes the prior approval still covers the new changes. |
41
37
  | **Why (framework)** | ISO 27001 A.14.2.4 (Restrictions on changes to software packages — each change goes through controls); SOC 2 CC8.1 (Each change requires approval). Treating "approval given once, all subsequent commits inherit it" would make UAT a one-shot rubber-stamp. |
42
38
  | **Enforcement** | Portal-side: the release-approval state machine resets on new commits to the linked branch. Skill-side: re-requests review explicitly via the portal API after each change-request iteration. |
@@ -44,8 +40,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
44
40
 
45
41
  ### 5. AI involvement disclosed on every commit
46
42
 
47
- | | |
48
- |---|---|
43
+ | | | | --- | --- |
49
44
  | **What** | Every commit the skill creates carries a `Co-Authored-By: Claude <noreply@anthropic.com>` trailer (or equivalent for the specific Claude model in use). |
50
45
  | **Why (framework)** | ISO 27001 — transparency norms; EU AI Act Art. 13 (Transparency and provision of information to deployers); GDPR Art. 22 (data subjects' right to know about automated decisions, where applicable). When an auditor traces a commit, the AI involvement must be visible. |
51
46
  | **Enforcement** | Skill-side. Every `git commit` call includes the trailer. CI's `compliance-validation.yml` workflow can be configured to grep for `Co-Authored-By` on PRs labelled with the AI-touched marker; this is optional but recommended. |
@@ -53,8 +48,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
53
48
 
54
49
  ### 6. All portal mutations through audit-logged APIs
55
50
 
56
- | | |
57
- |---|---|
51
+ | | | | --- | --- |
58
52
  | **What** | The skill calls `devaudit push` and the standard portal HTTP APIs — never a database back-channel, never a service-role-key-equivalent that bypasses the audit log. |
59
53
  | **Why (framework)** | ISO 27001 A.12.4 (Logging and monitoring); SOC 2 CC4 + CC7 (Monitoring activities + system operations). Every action that affects compliance state must produce an audit-log entry attributable to a human identity (the user whose PAT is in `DEVAUDIT_USER_TOKEN`). |
60
54
  | **Enforcement** | Skill-side. All portal interaction goes through `devaudit push` or `curl`/`gh api` against the documented REST endpoints. |
@@ -64,8 +58,7 @@ The constraints are enforced in `SKILL.md` and in the smoke pass. Where applicab
64
58
 
65
59
  ### 7. Rubber-stamping at UAT
66
60
 
67
- | | |
68
- |---|---|
61
+ | | | | --- | --- |
69
62
  | **What** | If the UAT reviewer approves without actually reading the change, the controls are formally satisfied but substantively hollow. |
70
63
  | **Why (framework)** | SOC 2 CC4.1 (Monitoring activities — the entity should detect this via its own QA sampling). Not enforced by any control mechanism; relies on human discipline. |
71
64
  | **Enforcement** | Not architectural. Mitigations: the SKILL.md's Principles section names the UAT reviewer as "the load-bearing human"; the portal's UAT-review UI intentionally adds friction (no one-click approve from email); org policy should random-sample approvals for QA. |
@@ -255,7 +255,7 @@ jobs:
255
255
  echo "::warning::Approved SHA (${APPROVED_SHA:0:8}) differs from PR HEAD (${PR_HEAD_SHA:0:8}). Code may have changed after approval."
256
256
  fi
257
257
 
258
- - name: Update PR check run (workflow_dispatch / repository_dispatch re-trigger)
258
+ - name: Create refreshed PR check run (workflow_dispatch / repository_dispatch re-trigger)
259
259
  if: env.BOOTSTRAP_MODE != 'true' && (github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch')
260
260
  env:
261
261
  GH_TOKEN: ${{ github.token }}
@@ -283,31 +283,21 @@ jobs:
283
283
  CHECK_NAME="DevAudit Release Approval"
284
284
  DETAILS_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
285
285
  COMPLETED_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)
286
- EXISTING_ID=$(gh api \
287
- "/repos/${{ github.repository }}/commits/${TARGET_SHA}/check-runs?name=DevAudit%20Release%20Approval" \
288
- --jq '.check_runs[] | select(.name == "DevAudit Release Approval") | .id' \
289
- | head -1 || true)
290
286
 
291
- if [ -n "$EXISTING_ID" ]; then
292
- gh api "/repos/${{ github.repository }}/check-runs/${EXISTING_ID}" \
293
- -X PATCH \
294
- -f status=completed \
295
- -f conclusion=success \
296
- -f completed_at="$COMPLETED_AT" \
297
- -f details_url="$DETAILS_URL" \
298
- -f "output[title]=DevAudit release approval confirmed" \
299
- -f "output[summary]=Release ${{ steps.release.outputs.version }} is approved in DevAudit."
300
- echo "Updated ${CHECK_NAME} check run ${EXISTING_ID} on ${TARGET_SHA}."
301
- else
302
- gh api "/repos/${{ github.repository }}/check-runs" \
303
- -X POST \
304
- -f name="$CHECK_NAME" \
305
- -f head_sha="$TARGET_SHA" \
306
- -f status=completed \
307
- -f conclusion=success \
308
- -f completed_at="$COMPLETED_AT" \
309
- -f details_url="$DETAILS_URL" \
310
- -f "output[title]=DevAudit release approval confirmed" \
311
- -f "output[summary]=Release ${{ steps.release.outputs.version }} is approved in DevAudit."
312
- echo "Created ${CHECK_NAME} check run on ${TARGET_SHA}."
313
- fi
287
+ # DevAudit-Installer#351 GitHub's Feb 2025 check-run changes
288
+ # forbid externally mutating an existing workflow-owned check run
289
+ # from a workflow_dispatch / repository_dispatch flow. The refresh
290
+ # path therefore creates a fresh success check run on the approved
291
+ # SHA instead of PATCHing the original failed PR check.
292
+ gh api "/repos/${{ github.repository }}/check-runs" \
293
+ -X POST \
294
+ -f name="$CHECK_NAME" \
295
+ -f head_sha="$TARGET_SHA" \
296
+ -f status=completed \
297
+ -f conclusion=success \
298
+ -f completed_at="$COMPLETED_AT" \
299
+ -f details_url="$DETAILS_URL" \
300
+ -f external_id="${{ github.run_id }}" \
301
+ -f "output[title]=DevAudit release approval confirmed" \
302
+ -f "output[summary]=Release ${{ steps.release.outputs.version }} is approved in DevAudit."
303
+ echo "Created refreshed ${CHECK_NAME} check run on ${TARGET_SHA}."