@metasession.co/devaudit-cli 0.1.10 → 0.1.11
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 +39 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/sdlc/ai-rules/INSTRUCTIONS-SDLC.md +6 -0
- package/sdlc/files/_common/2-implement-and-test.md +2 -0
- package/sdlc/files/_common/3-compile-evidence.md +3 -1
- package/sdlc/files/_common/scripts/validate-commits.sh +22 -0
- package/sdlc/files/ci/ci.yml.template +2 -1
- package/sdlc/files/ci/compliance-evidence.yml.template +25 -7
- package/sdlc/files/sdlc-config.example.json +6 -1
- package/sdlc/files/stacks/node/hooks/commitlint.config.mjs +26 -10
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.11",
|
|
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.11",
|
|
37
37
|
"commander": "^12.1.0",
|
|
38
38
|
"consola": "^3.2.3",
|
|
39
39
|
"env-paths": "^3.0.0",
|
|
@@ -15,6 +15,12 @@ Detailed workflow instructions are in this project's `SDLC/` directory. Read the
|
|
|
15
15
|
|
|
16
16
|
When a workflow step requires detailed commands or templates, read the full workflow file rather than relying on the summary below.
|
|
17
17
|
|
|
18
|
+
### Entry point: the `sdlc-implementer` skill
|
|
19
|
+
|
|
20
|
+
The default way to implement a tracked change is the **`sdlc-implementer`** skill (`.claude/skills/sdlc-implementer/SKILL.md`): give it one GitHub issue and it runs Stage 1 (classify risk, assign the next `REQ-XXX`, write the implementation plan, update `RTM.md`) through Stage 4 (PR + UAT review), delegating all end-to-end / visual test work to `e2e-test-engineer`. **Do NOT hand-roll implementation outside this flow** — every change starts from a requirement, which starts from an issue. The only exceptions are trivial housekeeping (docs, formatting, dependency bumps, CI tweaks).
|
|
21
|
+
|
|
22
|
+
**This is enforced, not just advised.** `feat` / `fix` / `refactor` / `perf` commits that cite no requirement (`[REQ-XXX]` in the subject or a `Ref: REQ-XXX` trailer) are **rejected** locally by the commit-msg hook (commitlint) and at PR CI by `validate-commits.sh` (which `--no-verify` cannot skip). So implementation work cannot reach `develop` without a requirement — which is also what keeps release labels correct (the version-deriver only falls back to a bare date for genuine housekeeping, never for real feature work). Housekeeping commit types remain exempt.
|
|
23
|
+
|
|
18
24
|
### Before ANY Code Change
|
|
19
25
|
|
|
20
26
|
1. Ask: "Which GitHub Issue is this for?" before writing code. Fetch it with `gh issue view NNN`.
|
|
@@ -126,6 +126,8 @@ Write or update E2E tests **after** implementation. E2E tests need working UI/AP
|
|
|
126
126
|
|
|
127
127
|
> **Skill available:** invoke the **`e2e-test-engineer`** skill for this step (at `.claude/skills/e2e-test-engineer/SKILL.md`). It derives scenarios from the requirement's acceptance criteria, reconciles with the existing test pack (flags obsoletes — but never deletes without confirmation), runs the suite, and files defects for failures or missed ACs. Framework-agnostic (Playwright, Cypress, pytest-playwright, etc.) and tracker-agnostic (GitHub, Linear, Jira, etc.). For projects with no e2e suite yet, the skill also covers bootstrapping one. See [`sdlc/SKILLS.md`](../sdlc/SKILLS.md) for the full list of available skills.
|
|
128
128
|
|
|
129
|
+
> **Run authenticated flows in CI.** Tests that need a logged-in session (admin forms, role-gated flows) belong in their own Playwright project that depends on `auth-setup`. Register that project name in `sdlc-config.json` `e2e_projects` and set `e2e_seed_command` / `e2e_env` so CI seeds fixtures and runs it as a **report-only** gate (continue-on-error — it surfaces failures as evidence without blocking the merge until proven stable). Prove each AC with an `evidenceShot(page, 'REQ-XXX', 'ACn-…')` so the PNG lands in `compliance/evidence/REQ-XXX/screenshots/`. This is what lets Stage 3 Step 10 reduce manual UAT to a light smoke instead of a full re-click.
|
|
130
|
+
|
|
129
131
|
**4a. Review the test plan for E2E items:**
|
|
130
132
|
```bash
|
|
131
133
|
cat compliance/evidence/REQ-XXX/test-plan.md
|
|
@@ -399,7 +399,7 @@ If it fails — typically a stale `devaudit.base_url`, a revoked `DEVAUDIT_API_K
|
|
|
399
399
|
**Skip this step entirely if any of these are true:**
|
|
400
400
|
|
|
401
401
|
- Project's `sdlc-config.json` has `uat.enabled: false` — meaning the project has no deployed UAT environment configured (internal services, retroactive-compliance pickups, etc.).
|
|
402
|
-
- Requirement's risk class is **not** listed in project's `uat.required_risk_classes` (defaults: `payment`, `destructive_migration`, `realtime`, `physical_ux`). Text-only fixes, internal refactors, low-risk UI tweaks carry none of these and skip UAT-env verification.
|
|
402
|
+
- Requirement's risk class is **not** listed in project's `uat.required_risk_classes` (defaults: `payment`, `destructive_migration`, `realtime`, `physical_ux`). Text-only fixes, internal refactors, low-risk UI tweaks carry none of these and skip UAT-env verification. **Wildcard:** if `required_risk_classes` contains `"*"`, every requirement requires UAT-env verification regardless of risk class — use this for projects that deploy `develop` to a UAT environment and exercise every release there before promotion.
|
|
403
403
|
|
|
404
404
|
When skipped, proceed directly to Step 11.
|
|
405
405
|
|
|
@@ -407,6 +407,8 @@ When skipped, proceed directly to Step 11.
|
|
|
407
407
|
|
|
408
408
|
When this step DOES apply, the develop branch's auto-deploy to UAT must complete first. **Wait for the deployment to complete**, then verify the change works in the UAT environment.
|
|
409
409
|
|
|
410
|
+
> **Automated e2e shrinks this step — it does not delete it.** When a requirement's acceptance criteria are covered by **passing CI e2e tests** authored with the `e2e-test-engineer` skill (each AC proven by an `evidenceShot`, run via the report-only authenticated-e2e gate — see `sdlc-config.json` `e2e_projects` / `e2e_seed_command`), those ACs are already exercised against the running app on every push. For those ACs, this step is **not** a full manual re-click of every criterion: it reduces to a **light manual smoke** on the deployed UAT environment — confirm the build is live, the changed area loads, and spot-check anything the e2e couldn't reach (real third-party integrations, environment-specific config, payment sandboxes). Record which ACs were discharged by automated e2e vs. exercised manually. ACs **not** covered by a passing e2e test still need full manual verification here.
|
|
411
|
+
|
|
410
412
|
#### WAIT CHECKPOINT: Confirm CI + Deployment Complete
|
|
411
413
|
|
|
412
414
|
Before UAT verification, confirm BOTH CI and deployment are complete:
|
|
@@ -52,6 +52,28 @@ while IFS= read -r sha; do
|
|
|
52
52
|
continue
|
|
53
53
|
fi
|
|
54
54
|
|
|
55
|
+
# Requirement traceability: implementation commits (feat/fix/refactor/perf)
|
|
56
|
+
# MUST cite a requirement — [REQ-XXX] in the subject or a Ref: REQ-XXX
|
|
57
|
+
# trailer. Housekeeping types (docs/chore/ci/build/test/compliance/revert)
|
|
58
|
+
# are exempt. Mirrors the commitlint rule; this is the PR-CI half that
|
|
59
|
+
# `--no-verify` can't skip. Work starts from a requirement (which starts
|
|
60
|
+
# from an issue) — use the sdlc-implementer skill to assign one.
|
|
61
|
+
TYPE=$(echo "$SUBJECT" | grep -oE '^[a-z]+' || true)
|
|
62
|
+
case "$TYPE" in
|
|
63
|
+
feat|fix|refactor|perf)
|
|
64
|
+
if ! echo "$SUBJECT" | grep -qP '\[REQ-\d{3,}\]' \
|
|
65
|
+
&& ! echo "$BODY" | grep -qiP 'Ref:\s*REQ-\d{3,}'; then
|
|
66
|
+
echo "ERROR [$SHORT]: '$TYPE' is an implementation commit but cites no requirement."
|
|
67
|
+
echo " Add [REQ-XXX] to the subject or a 'Ref: REQ-XXX' trailer. Start work"
|
|
68
|
+
echo " from a requirement via the sdlc-implementer skill (it assigns the REQ"
|
|
69
|
+
echo " from the originating issue in Phase 1)."
|
|
70
|
+
FAILED=$((FAILED + 1))
|
|
71
|
+
EXIT_CODE=1
|
|
72
|
+
continue
|
|
73
|
+
fi
|
|
74
|
+
;;
|
|
75
|
+
esac
|
|
76
|
+
|
|
55
77
|
# Check Co-Authored-By on commits that touch code files
|
|
56
78
|
CODE_FILES=$(git diff-tree --no-commit-id --name-only -r "$sha" -- '*.ts' '*.tsx' '*.js' '*.jsx' '*.py' 2>/dev/null || true)
|
|
57
79
|
if [ -n "$CODE_FILES" ]; then
|
|
@@ -150,7 +150,7 @@ jobs:
|
|
|
150
150
|
PLAYWRIGHT_HTML_REPORTER_OPEN: never
|
|
151
151
|
PLAYWRIGHT_JSON_OUTPUT_NAME: e2e-results.json
|
|
152
152
|
run: npx playwright test --project={{E2E_PROJECT}} --reporter=json,html
|
|
153
|
-
|
|
153
|
+
{{E2E_AUTHENTICATED_STEP}}
|
|
154
154
|
# ── Gate 5: Build ──
|
|
155
155
|
|
|
156
156
|
- name: Build Check
|
|
@@ -169,6 +169,7 @@ jobs:
|
|
|
169
169
|
sast-results.json
|
|
170
170
|
dependency-audit.json
|
|
171
171
|
e2e-results.json
|
|
172
|
+
e2e-auth-results.json
|
|
172
173
|
playwright-report/
|
|
173
174
|
coverage/coverage-summary.json
|
|
174
175
|
retention-days: 90
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
name: Compliance Evidence Upload
|
|
21
21
|
|
|
22
22
|
on:
|
|
23
|
+
workflow_dispatch:
|
|
23
24
|
push:
|
|
24
25
|
branches: [develop]
|
|
25
26
|
paths:
|
|
@@ -98,9 +99,16 @@ jobs:
|
|
|
98
99
|
if: steps.resolve.outputs.skip != 'true'
|
|
99
100
|
run: |
|
|
100
101
|
chmod +x scripts/upload-evidence.sh 2>/dev/null || true
|
|
102
|
+
# Common flags WITHOUT --release. Each upload appends its OWN
|
|
103
|
+
# --release so per-requirement artifacts land in their own release
|
|
104
|
+
# record (version = REQ-ID) instead of all collapsing into whichever
|
|
105
|
+
# single version the triggering commit derived. DevAudit #135 follow-
|
|
106
|
+
# up: this fixes release *attribution* (not just duplication) — an
|
|
107
|
+
# untagged docs commit must not sweep every in-scope REQ into a date
|
|
108
|
+
# release. Note: upload-evidence.sh keeps the LAST --release seen.
|
|
101
109
|
FLAGS="--git-sha ${{ github.sha }} --ci-run-id ${{ github.run_id }} --branch ${{ github.ref_name }}"
|
|
102
|
-
FLAGS="${FLAGS} --
|
|
103
|
-
|
|
110
|
+
FLAGS="${FLAGS} --create-release-if-missing --environment uat"
|
|
111
|
+
DERIVED_RELEASE="${{ steps.version.outputs.version }}"
|
|
104
112
|
|
|
105
113
|
# Upload compliance docs (planning category)
|
|
106
114
|
for DOC in compliance/RTM.md compliance/test-plan.md compliance/test-cases.md compliance/test-summary-report.md; do
|
|
@@ -108,7 +116,7 @@ jobs:
|
|
|
108
116
|
echo "Uploading: $(basename "$DOC")"
|
|
109
117
|
bash scripts/upload-evidence.sh \
|
|
110
118
|
{{PROJECT_SLUG}} _compliance-docs compliance_document "$DOC" \
|
|
111
|
-
--category planning ${FLAGS} || echo "Warning: Failed to upload $(basename "$DOC")"
|
|
119
|
+
--category planning ${FLAGS} --release "${DERIVED_RELEASE}" || echo "Warning: Failed to upload $(basename "$DOC")"
|
|
112
120
|
fi
|
|
113
121
|
done
|
|
114
122
|
|
|
@@ -116,10 +124,20 @@ jobs:
|
|
|
116
124
|
if [ -d "compliance/pending-releases" ]; then
|
|
117
125
|
for TICKET in compliance/pending-releases/*.md; do
|
|
118
126
|
[ -f "$TICKET" ] || continue
|
|
119
|
-
|
|
127
|
+
# A RELEASE-TICKET-REQ-XXX.md belongs to that requirement's
|
|
128
|
+
# release record; any other ticket rides the derived release.
|
|
129
|
+
TICKET_BASE=$(basename "$TICKET" .md)
|
|
130
|
+
case "$TICKET_BASE" in
|
|
131
|
+
RELEASE-TICKET-REQ-*)
|
|
132
|
+
TICKET_REQ="${TICKET_BASE#RELEASE-TICKET-}"
|
|
133
|
+
TICKET_OWNER="$TICKET_REQ"; TICKET_RELEASE="$TICKET_REQ" ;;
|
|
134
|
+
*)
|
|
135
|
+
TICKET_OWNER="_compliance-docs"; TICKET_RELEASE="$DERIVED_RELEASE" ;;
|
|
136
|
+
esac
|
|
137
|
+
echo "Uploading: $(basename "$TICKET") -> release ${TICKET_RELEASE}"
|
|
120
138
|
bash scripts/upload-evidence.sh \
|
|
121
|
-
{{PROJECT_SLUG}}
|
|
122
|
-
--category release_artifact ${FLAGS} || echo "Warning: Failed to upload $(basename "$TICKET")"
|
|
139
|
+
{{PROJECT_SLUG}} "${TICKET_OWNER}" compliance_document "$TICKET" \
|
|
140
|
+
--category release_artifact ${FLAGS} --release "${TICKET_RELEASE}" || echo "Warning: Failed to upload $(basename "$TICKET")"
|
|
123
141
|
done
|
|
124
142
|
fi
|
|
125
143
|
|
|
@@ -152,7 +170,7 @@ jobs:
|
|
|
152
170
|
echo "Uploading: ${REQ_ID}/$(basename "$ARTIFACT")"
|
|
153
171
|
bash scripts/upload-evidence.sh \
|
|
154
172
|
{{PROJECT_SLUG}} "${REQ_ID}" compliance_document "$ARTIFACT" \
|
|
155
|
-
--category planning ${FLAGS} || echo "Warning: Failed to upload $(basename "$ARTIFACT")"
|
|
173
|
+
--category planning ${FLAGS} --release "${REQ_ID}" || echo "Warning: Failed to upload $(basename "$ARTIFACT")"
|
|
156
174
|
done
|
|
157
175
|
done
|
|
158
176
|
fi
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"e2e_project": "chromium",
|
|
33
33
|
"e2e_start_command": "npm run dev",
|
|
34
34
|
|
|
35
|
+
"_comment_e2e_authenticated": "Optional report-only authenticated e2e gate (continue-on-error, never blocks the merge). e2e_projects = Playwright project names that need a logged-in session (auth-setup runs automatically as their dependency); e2e_seed_command seeds admins/fixtures before the run; e2e_env maps repo secrets onto the seed + e2e steps. Author these specs with the e2e-test-engineer skill (evidenceShot per AC). Leave empty to run only the blocking smoke project above.",
|
|
36
|
+
"e2e_seed_command": "",
|
|
37
|
+
"e2e_projects": [],
|
|
38
|
+
"e2e_env": {},
|
|
39
|
+
|
|
35
40
|
"paths_ignore": [
|
|
36
41
|
".github/workflows/**",
|
|
37
42
|
"SDLC/**",
|
|
@@ -53,7 +58,7 @@
|
|
|
53
58
|
"api_key_secret": "DEVAUDIT_API_KEY"
|
|
54
59
|
},
|
|
55
60
|
|
|
56
|
-
"_comment_uat": "UAT-environment verification (Stage 3 Step 10). Opt-in: enabled=false skips Step 10 entirely. When enabled, only requirements whose risk class is listed in required_risk_classes go through UAT-env verification.",
|
|
61
|
+
"_comment_uat": "UAT-environment verification (Stage 3 Step 10). Opt-in: enabled=false skips Step 10 entirely. When enabled, only requirements whose risk class is listed in required_risk_classes go through UAT-env verification; use [\"*\"] to require it for every requirement (projects that UAT every release).",
|
|
57
62
|
"uat": {
|
|
58
63
|
"enabled": false,
|
|
59
64
|
"url": "",
|
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
* Commitlint configuration for Metasession SDLC.
|
|
3
3
|
*
|
|
4
4
|
* Enforces:
|
|
5
|
-
* - Conventional Commits format (feat, fix, docs, test, refactor, chore,
|
|
6
|
-
* -
|
|
7
|
-
*
|
|
5
|
+
* - Conventional Commits format (feat, fix, docs, test, refactor, chore, …).
|
|
6
|
+
* - Requirement traceability: **implementation** commits (feat / fix /
|
|
7
|
+
* refactor / perf) MUST cite a requirement via `[REQ-XXX]` in the subject
|
|
8
|
+
* or a `Ref: REQ-XXX` trailer (ERROR). Housekeeping types (docs, chore, ci,
|
|
9
|
+
* build, test, compliance, revert) are exempt. This is the local half of
|
|
10
|
+
* the "no implementation without a requirement" rule; `validate-commits.sh`
|
|
11
|
+
* enforces the same at PR CI (which `--no-verify` can't skip). Work starts
|
|
12
|
+
* from a requirement, which starts from an issue — run the `sdlc-implementer`
|
|
13
|
+
* skill, whose Phase 1 assigns the REQ from the originating issue.
|
|
14
|
+
* - Co-Authored-By trailer (warning — not every commit is AI-generated).
|
|
8
15
|
*
|
|
9
16
|
* Install:
|
|
10
17
|
* npm install --save-dev @commitlint/cli @commitlint/config-conventional
|
|
11
18
|
* cp this file to your project root as commitlint.config.mjs
|
|
12
19
|
*/
|
|
13
20
|
|
|
21
|
+
const IMPLEMENTATION_TYPES = ['feat', 'fix', 'refactor', 'perf'];
|
|
22
|
+
|
|
14
23
|
export default {
|
|
15
24
|
extends: ['@commitlint/config-conventional'],
|
|
16
25
|
rules: {
|
|
@@ -35,20 +44,29 @@ export default {
|
|
|
35
44
|
],
|
|
36
45
|
// Warn (not error) when body is missing — some commits are one-liners
|
|
37
46
|
'body-empty': [1, 'never'],
|
|
47
|
+
// Implementation commits must trace to a requirement (ERROR)
|
|
48
|
+
'requirement-ref-for-impl': [2, 'always'],
|
|
49
|
+
// AI-authored commits should be attributed (warning)
|
|
50
|
+
'trailer-co-authored-by': [1, 'always'],
|
|
38
51
|
},
|
|
39
52
|
plugins: [
|
|
40
53
|
{
|
|
41
54
|
rules: {
|
|
42
|
-
'
|
|
43
|
-
//
|
|
44
|
-
|
|
55
|
+
'requirement-ref-for-impl': ({ type, raw }) => {
|
|
56
|
+
// Only implementation work is requirement-gated; housekeeping is exempt.
|
|
57
|
+
if (!IMPLEMENTATION_TYPES.includes(type)) return [true];
|
|
58
|
+
const hasRef =
|
|
59
|
+
/\[REQ-\d{3,}\]/i.test(raw) || /Ref:\s*REQ-\d{3,}/i.test(raw);
|
|
45
60
|
return [
|
|
46
61
|
hasRef,
|
|
47
|
-
|
|
62
|
+
`"${type}" is an implementation commit and must cite a requirement: ` +
|
|
63
|
+
`add [REQ-XXX] to the subject or a "Ref: REQ-XXX" trailer. Work must ` +
|
|
64
|
+
`start from a requirement (which starts from an issue) — run the ` +
|
|
65
|
+
`sdlc-implementer skill to assign one. Housekeeping types ` +
|
|
66
|
+
`(docs/chore/ci/build/test/compliance/revert) are exempt.`,
|
|
48
67
|
];
|
|
49
68
|
},
|
|
50
69
|
'trailer-co-authored-by': ({ raw }) => {
|
|
51
|
-
// Warn if Co-Authored-By is missing — not every commit is AI-generated
|
|
52
70
|
const hasCoAuthor = /Co-Authored-By:/i.test(raw);
|
|
53
71
|
return [
|
|
54
72
|
hasCoAuthor,
|
|
@@ -58,7 +76,5 @@ export default {
|
|
|
58
76
|
},
|
|
59
77
|
},
|
|
60
78
|
],
|
|
61
|
-
// Apply custom rules as warnings (level 1), not errors
|
|
62
|
-
// Override in your project if you want stricter enforcement
|
|
63
79
|
helpUrl: 'https://www.conventionalcommits.org/',
|
|
64
80
|
};
|