@metasession.co/devaudit-cli 0.1.0 → 0.1.2

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 (70) hide show
  1. package/README.md +23 -11
  2. package/dist/index.js +21 -5
  3. package/dist/index.js.map +1 -1
  4. package/package.json +9 -5
  5. package/scripts/upload-evidence.sh +225 -0
  6. package/sdlc/.claude/settings.local.json +11 -0
  7. package/sdlc/CLAUDE.md +73 -0
  8. package/sdlc/HOST_ADAPTER.md +127 -0
  9. package/sdlc/SKILLS.md +137 -0
  10. package/sdlc/STACK_ADAPTER.md +130 -0
  11. package/sdlc/ai-rules/INSTRUCTIONS-SDLC.md +172 -0
  12. package/sdlc/ai-rules/README.md +103 -0
  13. package/sdlc/ai-rules/SDLC_RULES.md +584 -0
  14. package/sdlc/ai-rules/claude/CLAUDE.md +192 -0
  15. package/sdlc/ai-rules/cursor/.cursorrules +167 -0
  16. package/sdlc/ai-rules/windsurf/.windsurfrules +167 -0
  17. package/sdlc/article.md +219 -0
  18. package/sdlc/files/_common/0-project-setup.md +410 -0
  19. package/sdlc/files/_common/1-plan-requirement.md +381 -0
  20. package/sdlc/files/_common/2-implement-and-test.md +276 -0
  21. package/sdlc/files/_common/3-compile-evidence.md +603 -0
  22. package/sdlc/files/_common/4-submit-for-review.md +362 -0
  23. package/sdlc/files/_common/5-deploy-main.md +251 -0
  24. package/sdlc/files/_common/Periodic_Security_Review_Schedule.md +169 -0
  25. package/sdlc/files/_common/README_TEMPLATE.md +441 -0
  26. package/sdlc/files/_common/Test_Architecture.md +461 -0
  27. package/sdlc/files/_common/Test_Plan_TEMPLATE.md +311 -0
  28. package/sdlc/files/_common/Test_Policy.md +277 -0
  29. package/sdlc/files/_common/Test_Strategy.md +359 -0
  30. package/sdlc/files/_common/github/ISSUE_TEMPLATE/bug.yml +75 -0
  31. package/sdlc/files/_common/github/ISSUE_TEMPLATE/config.yml +11 -0
  32. package/sdlc/files/_common/github/ISSUE_TEMPLATE/requirement.yml +75 -0
  33. package/sdlc/files/_common/github/ISSUE_TEMPLATE/task.yml +48 -0
  34. package/sdlc/files/_common/github/pull_request_template.md +69 -0
  35. package/sdlc/files/_common/implementing-an-sdlc-issue.md +413 -0
  36. package/sdlc/files/_common/scripts/derive-release-version.sh +40 -0
  37. package/sdlc/files/_common/scripts/derive-release-version.test.sh +98 -0
  38. package/sdlc/files/_common/scripts/submit-for-uat-review.sh +162 -0
  39. package/sdlc/files/_common/scripts/validate-commits.sh +83 -0
  40. package/sdlc/files/_common/scripts/validate-compliance-artifacts.sh +202 -0
  41. package/sdlc/files/_common/scripts/validate-compliance-artifacts.test.sh +202 -0
  42. package/sdlc/files/_common/skills/_schema/skill.schema.json +36 -0
  43. package/sdlc/files/_common/skills/e2e-test-engineer/SKILL.md +254 -0
  44. package/sdlc/files/_common/skills/e2e-test-engineer/references/bootstrap.md +244 -0
  45. package/sdlc/files/_common/skills/e2e-test-engineer/references/evidence.ts +40 -0
  46. package/sdlc/files/_common/skills/sdlc-implementer/SKILL.md +189 -0
  47. package/sdlc/files/_common/skills/sdlc-implementer/references/call-graph.md +64 -0
  48. package/sdlc/files/_common/skills/sdlc-implementer/references/change-request-loop.md +192 -0
  49. package/sdlc/files/_common/skills/sdlc-implementer/references/compliance-constraints.md +81 -0
  50. package/sdlc/files/ci/check-release-approval.yml.template +201 -0
  51. package/sdlc/files/ci/ci-status-fallback.yml.template +41 -0
  52. package/sdlc/files/ci/ci.yml.template +390 -0
  53. package/sdlc/files/ci/compliance-evidence.yml.template +161 -0
  54. package/sdlc/files/ci/compliance-validation.yml.template +34 -0
  55. package/sdlc/files/ci/post-deploy-prod.yml.template +159 -0
  56. package/sdlc/files/ci/python/ci.yml.template +335 -0
  57. package/sdlc/files/hosts/_schema/adapter.schema.json +103 -0
  58. package/sdlc/files/hosts/railway/adapter.json +32 -0
  59. package/sdlc/files/sdlc-config.example.json +74 -0
  60. package/sdlc/files/stacks/_schema/adapter.schema.json +151 -0
  61. package/sdlc/files/stacks/node/adapter.json +54 -0
  62. package/sdlc/files/stacks/node/hooks/.prettierrc.json +9 -0
  63. package/sdlc/files/stacks/node/hooks/commit-msg +7 -0
  64. package/sdlc/files/stacks/node/hooks/commitlint.config.mjs +64 -0
  65. package/sdlc/files/stacks/node/hooks/lint-staged.config.mjs +16 -0
  66. package/sdlc/files/stacks/node/hooks/pre-commit +13 -0
  67. package/sdlc/files/stacks/node/hooks/pre-push +15 -0
  68. package/sdlc/files/stacks/node/scripts/check-requirement-jsdoc.sh +54 -0
  69. package/sdlc/files/stacks/python/adapter.json +36 -0
  70. package/sdlc/files/stacks/python/hooks/.pre-commit-config.yaml +51 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metasession.co/devaudit-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "DevAudit CLI — installs, syncs, and operates the Metasession SDLC across consumer projects.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,6 +13,8 @@
13
13
  "files": [
14
14
  "bin",
15
15
  "dist",
16
+ "sdlc",
17
+ "scripts",
16
18
  "README.md",
17
19
  "LICENSE"
18
20
  ],
@@ -22,25 +24,27 @@
22
24
  "scripts": {
23
25
  "build": "tsup",
24
26
  "dev": "tsup --watch",
27
+ "bundle:templates": "node tools/bundle-templates.mjs",
28
+ "prepack": "npm run build && npm run bundle:templates",
25
29
  "test": "vitest run",
26
30
  "test:watch": "vitest",
27
31
  "typecheck": "tsc --noEmit",
28
32
  "start": "node ./bin/devaudit.js"
29
33
  },
30
34
  "dependencies": {
31
- "commander": "^12.1.0",
32
35
  "@clack/prompts": "^0.8.2",
36
+ "@metasession.co/devaudit-plugin-sdk": "file:../plugin-sdk",
37
+ "commander": "^12.1.0",
33
38
  "consola": "^3.2.3",
34
- "execa": "^9.5.1",
35
39
  "env-paths": "^3.0.0",
36
- "@metasession.co/devaudit-plugin-sdk": "^0.1.0"
40
+ "execa": "^9.5.1"
37
41
  },
38
42
  "devDependencies": {
39
43
  "@types/node": "^22.9.0",
40
44
  "msw": "^2.7.0",
41
45
  "tsup": "^8.3.5",
42
46
  "typescript": "^5.7.2",
43
- "vitest": "^2.1.5"
47
+ "vitest": "^4.1.6"
44
48
  },
45
49
  "publishConfig": {
46
50
  "access": "public"
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env bash
2
+ # @requirement REQ-007 - CLI upload script for CI pipelines
3
+ # @requirement REQ-020 - Extended with release/environment/category flags
4
+ # @requirement REQ-XXX - #224: posts to META-COMPLY's API instead of Supabase
5
+ #
6
+ # Usage:
7
+ # ./scripts/upload-evidence.sh <project-slug> <requirement-id> <evidence-type> <file-or-directory>
8
+ #
9
+ # Optional flags:
10
+ # --git-sha <sha> Git commit SHA
11
+ # --ci-run-id <id> CI run identifier
12
+ # --branch <branch> Git branch name
13
+ # --release <version> Release version (e.g. v1.0.0). The route
14
+ # resolves it to a release UUID server-side.
15
+ # --create-release-if-missing Auto-create the release as 'draft' if absent
16
+ # --environment <env> Environment: uat or production
17
+ # --category <cat> Evidence category: ci_pipeline, local_dev,
18
+ # planning, test_report, security_scan,
19
+ # release_artifact
20
+ #
21
+ # Required environment variables:
22
+ # DEVAUDIT_BASE_URL e.g. https://meta-comply-production.up.railway.app
23
+ # DEVAUDIT_API_KEY project-scoped API key (uploader role); format `mc_…`.
24
+ # Issue from: Project Settings → API Keys in
25
+ # META-COMPLY's web UI.
26
+ #
27
+ # Examples:
28
+ # ./scripts/upload-evidence.sh meta-ats REQ-001 screenshot \
29
+ # compliance/evidence/REQ-001/screenshots/
30
+ # ./scripts/upload-evidence.sh meta-ats _compliance-docs compliance_document \
31
+ # compliance/RTM.md --git-sha abc123
32
+ # ./scripts/upload-evidence.sh meta-ats REQ-001 e2e_result \
33
+ # playwright-report/ --release v1.0.0 --environment uat \
34
+ # --category ci_pipeline --create-release-if-missing
35
+
36
+ set -euo pipefail
37
+
38
+ # --- Parse arguments ---
39
+ if [ "$#" -lt 4 ]; then
40
+ echo "Usage: $0 <project-slug> <requirement-id> <evidence-type> <file-or-directory> [flags…]"
41
+ exit 1
42
+ fi
43
+
44
+ PROJECT_SLUG="$1"
45
+ REQUIREMENT_ID="$2"
46
+ EVIDENCE_TYPE="$3"
47
+ FILE_PATH="$4"
48
+ shift 4
49
+
50
+ GIT_SHA=""
51
+ CI_RUN_ID=""
52
+ BRANCH=""
53
+ RELEASE_VERSION=""
54
+ CREATE_RELEASE_IF_MISSING=false
55
+ ENVIRONMENT=""
56
+ EVIDENCE_CATEGORY=""
57
+
58
+ while [ "$#" -gt 0 ]; do
59
+ case "$1" in
60
+ --git-sha) GIT_SHA="$2"; shift 2 ;;
61
+ --ci-run-id) CI_RUN_ID="$2"; shift 2 ;;
62
+ --branch) BRANCH="$2"; shift 2 ;;
63
+ --release) RELEASE_VERSION="$2"; shift 2 ;;
64
+ --create-release-if-missing) CREATE_RELEASE_IF_MISSING=true; shift ;;
65
+ --environment) ENVIRONMENT="$2"; shift 2 ;;
66
+ --category) EVIDENCE_CATEGORY="$2"; shift 2 ;;
67
+ *) echo "Unknown option: $1"; exit 1 ;;
68
+ esac
69
+ done
70
+
71
+ if [ -n "$ENVIRONMENT" ] && [ -z "$RELEASE_VERSION" ]; then
72
+ echo "Error: --environment requires --release (evidence without a release is orphaned)"
73
+ exit 1
74
+ fi
75
+ if [ -n "$RELEASE_VERSION" ] && [ -z "$EVIDENCE_CATEGORY" ]; then
76
+ echo "Error: --category is required when --release is specified (gate validation)"
77
+ exit 1
78
+ fi
79
+
80
+ if [ -z "${DEVAUDIT_BASE_URL:-}" ]; then
81
+ echo "Error: DEVAUDIT_BASE_URL environment variable is required"
82
+ exit 1
83
+ fi
84
+ if [ -z "${DEVAUDIT_API_KEY:-}" ]; then
85
+ echo "Error: DEVAUDIT_API_KEY environment variable is required (issue from"
86
+ echo " Project Settings → API Keys in META-COMPLY)"
87
+ exit 1
88
+ fi
89
+
90
+ # Strip any trailing slash so we don't double-up later.
91
+ DEVAUDIT_BASE_URL="${DEVAUDIT_BASE_URL%/}"
92
+
93
+ # --- Build metadata JSON ---
94
+ METADATA="{}"
95
+ if [ -n "$GIT_SHA" ] || [ -n "$CI_RUN_ID" ] || [ -n "$BRANCH" ]; then
96
+ METADATA="{"
97
+ FIRST=true
98
+ if [ -n "$GIT_SHA" ]; then
99
+ METADATA="${METADATA}\"gitSha\":\"${GIT_SHA}\""
100
+ FIRST=false
101
+ fi
102
+ if [ -n "$CI_RUN_ID" ]; then
103
+ [ "$FIRST" = false ] && METADATA="${METADATA},"
104
+ METADATA="${METADATA}\"ciRunId\":\"${CI_RUN_ID}\""
105
+ FIRST=false
106
+ fi
107
+ if [ -n "$BRANCH" ]; then
108
+ [ "$FIRST" = false ] && METADATA="${METADATA},"
109
+ METADATA="${METADATA}\"branch\":\"${BRANCH}\""
110
+ fi
111
+ METADATA="${METADATA}}"
112
+ fi
113
+
114
+ # --- Collect files ---
115
+ FILES=()
116
+ if [ -d "$FILE_PATH" ]; then
117
+ while IFS= read -r -d '' f; do
118
+ FILES+=("$f")
119
+ done < <(find "$FILE_PATH" -type f -print0)
120
+ else
121
+ FILES=("$FILE_PATH")
122
+ fi
123
+ if [ ${#FILES[@]} -eq 0 ]; then
124
+ echo "Error: No files found at $FILE_PATH"
125
+ exit 1
126
+ fi
127
+
128
+ # --- Upload each file via /api/evidence/upload ---
129
+ #
130
+ # Retry-on-429 / 5xx: consumer CI workflows fire 8-12 sequential uploads per
131
+ # requirement (test-scope, test-plan, implementation-plan, security-summary,
132
+ # test-execution-summary, ai-prompts, ai-use-note, uat-checklist, gates/*.json).
133
+ # That cadence trips DevAudit's per-IP rate limiter, marking otherwise-green
134
+ # CI runs as failed. Retry transiently with exponential backoff (1s → 16s),
135
+ # honouring Retry-After if the portal supplies it. Auth/validation errors
136
+ # (4xx other than 429) still fail fast — they won't fix themselves.
137
+ #
138
+ # Issue: devaudit#263.
139
+ SUCCEEDED=0
140
+ FAILED=0
141
+ TOTAL_SIZE=0
142
+ UPLOAD_URL="${DEVAUDIT_BASE_URL}/api/evidence/upload"
143
+ MAX_ATTEMPTS=${UPLOAD_MAX_ATTEMPTS:-5}
144
+ INITIAL_BACKOFF_SECONDS=${UPLOAD_INITIAL_BACKOFF_SECONDS:-1}
145
+
146
+ for FILE in "${FILES[@]}"; do
147
+ FILENAME=$(basename "$FILE")
148
+ FILE_SIZE=$(stat -c%s "$FILE" 2>/dev/null || stat -f%z "$FILE")
149
+ echo -n "Uploading ${FILENAME}... "
150
+ CURL_ARGS=(
151
+ -X POST "$UPLOAD_URL"
152
+ -H "Authorization: Bearer ${DEVAUDIT_API_KEY}"
153
+ -F "file=@${FILE}"
154
+ -F "projectSlug=${PROJECT_SLUG}"
155
+ -F "requirementId=${REQUIREMENT_ID}"
156
+ -F "evidenceType=${EVIDENCE_TYPE}"
157
+ -F "metadata=${METADATA}"
158
+ )
159
+ [ -n "$RELEASE_VERSION" ] && CURL_ARGS+=(-F "releaseVersion=${RELEASE_VERSION}")
160
+ if [ "$CREATE_RELEASE_IF_MISSING" = true ]; then
161
+ CURL_ARGS+=(-F "createReleaseIfMissing=true")
162
+ fi
163
+ [ -n "$BRANCH" ] && CURL_ARGS+=(-F "releaseBranch=${BRANCH}")
164
+ [ -n "$ENVIRONMENT" ] && CURL_ARGS+=(-F "environment=${ENVIRONMENT}")
165
+ [ -n "$EVIDENCE_CATEGORY" ] && CURL_ARGS+=(-F "evidenceCategory=${EVIDENCE_CATEGORY}")
166
+
167
+ ATTEMPT=1
168
+ BACKOFF=$INITIAL_BACKOFF_SECONDS
169
+ HTTP_CODE=0
170
+ RESP_BODY_FILE=""
171
+ while [ "$ATTEMPT" -le "$MAX_ATTEMPTS" ]; do
172
+ [ -n "$RESP_BODY_FILE" ] && rm -f "$RESP_BODY_FILE"
173
+ RESP_BODY_FILE=$(mktemp)
174
+ RESP_HEADERS_FILE=$(mktemp)
175
+ HTTP_CODE=$(curl -s -o "$RESP_BODY_FILE" -D "$RESP_HEADERS_FILE" -w "%{http_code}" "${CURL_ARGS[@]}")
176
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
177
+ rm -f "$RESP_HEADERS_FILE"
178
+ break
179
+ fi
180
+ # Decide whether the failure is retriable (429 or 5xx).
181
+ if [ "$HTTP_CODE" = "429" ] || { [ "$HTTP_CODE" -ge 500 ] && [ "$HTTP_CODE" -lt 600 ]; }; then
182
+ if [ "$ATTEMPT" -lt "$MAX_ATTEMPTS" ]; then
183
+ # Honour Retry-After (seconds) if the portal supplied it; otherwise back off.
184
+ WAIT_SECONDS=$BACKOFF
185
+ RETRY_AFTER=$(grep -i '^retry-after:' "$RESP_HEADERS_FILE" 2>/dev/null | head -1 | sed 's/^[Rr]etry-[Aa]fter:[[:space:]]*//' | tr -d '\r')
186
+ if [[ "$RETRY_AFTER" =~ ^[0-9]+$ ]] && [ "$RETRY_AFTER" -gt 0 ]; then
187
+ WAIT_SECONDS=$RETRY_AFTER
188
+ fi
189
+ echo -n "(HTTP ${HTTP_CODE}, retry in ${WAIT_SECONDS}s) "
190
+ rm -f "$RESP_HEADERS_FILE"
191
+ sleep "$WAIT_SECONDS"
192
+ ATTEMPT=$((ATTEMPT + 1))
193
+ BACKOFF=$((BACKOFF * 2))
194
+ continue
195
+ fi
196
+ fi
197
+ rm -f "$RESP_HEADERS_FILE"
198
+ break
199
+ done
200
+
201
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
202
+ rm -f "$RESP_BODY_FILE"
203
+ if [ "$ATTEMPT" -gt 1 ]; then
204
+ echo "OK (${FILE_SIZE} bytes, attempt ${ATTEMPT}/${MAX_ATTEMPTS})"
205
+ else
206
+ echo "OK (${FILE_SIZE} bytes)"
207
+ fi
208
+ SUCCEEDED=$((SUCCEEDED + 1))
209
+ TOTAL_SIZE=$((TOTAL_SIZE + FILE_SIZE))
210
+ else
211
+ echo "FAILED (HTTP ${HTTP_CODE} after ${ATTEMPT} attempt(s))"
212
+ echo " Response: $(head -c 500 "$RESP_BODY_FILE")"
213
+ rm -f "$RESP_BODY_FILE"
214
+ FAILED=$((FAILED + 1))
215
+ fi
216
+ done
217
+
218
+ # --- Summary ---
219
+ echo ""
220
+ echo "=== Upload Summary ==="
221
+ echo "Files: ${SUCCEEDED} succeeded, ${FAILED} failed (${#FILES[@]} total)"
222
+ echo "Total size: $((TOTAL_SIZE / 1024)) KB"
223
+ if [ "$FAILED" -gt 0 ]; then
224
+ exit 1
225
+ fi
@@ -0,0 +1,11 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git init:*)",
5
+ "Bash(git add:*)",
6
+ "Bash(git branch:*)",
7
+ "Bash(git commit:*)",
8
+ "Bash(gh repo:*)"
9
+ ]
10
+ }
11
+ }
package/sdlc/CLAUDE.md ADDED
@@ -0,0 +1,73 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What This Repository Is
6
+
7
+ This is a compliance-grade SDLC template system — a set of 12 documents across two tiers that implement a workflow-driven development pipeline satisfying ISO 29119, ISO 27001, GDPR, SOC 2, and EU AI Act requirements. It is not a software application; it contains markdown templates and an accompanying article.
8
+
9
+ ## Repository Structure
10
+
11
+ - `article.md` — Long-form article explaining the system's design and rationale
12
+ - `files/` — The 12 template documents:
13
+ - **Tier 1 (universal, never project-specific):** `Test_Policy.md`, `Test_Strategy.md`, `Test_Architecture.md`, `Periodic_Security_Review_Schedule.md`
14
+ - **Tier 2 (project-specific, customized per project):** `0-project-setup.md` through `5-deploy-main.md` (workflows), `Test_Plan_TEMPLATE.md`, `README_TEMPLATE.md`
15
+
16
+ ## Key Design Principles
17
+
18
+ - **Single responsibility per document.** Policy says _what_ and _why_, Strategy says _how methodically_, Architecture says _with what tools_. No content should appear in two places.
19
+ - **Tier 1 never references a specific project.** Tools are referenced by category in Policy/Strategy; only Architecture names specific products and versions.
20
+ - **Risk-based proportionality.** Documentation, testing depth, and review requirements scale with risk level (Low/Medium/High). AI involvement raises risk by one level for Medium/High categories.
21
+ - **Workflow-driven compliance.** The six workflows (0-5) are executable procedures with specific commands, not guidelines. Compliance artifacts are natural outputs of following the workflows.
22
+
23
+ ## Development Model: Developer + AI Partner
24
+
25
+ Each project follows a **single owner-developer partnered with AI coding agents** model:
26
+
27
+ - **Owner-developer** provides direction, judgment, and approval. They are accountable for the project.
28
+ - **AI agent** (Claude Code, Windsurf, Cursor) acts as implementation partner, compliance enforcer, and reviewer. The SDLC process is enforced by the AI on every code change via drop-in rules (`sdlc/ai-rules/`).
29
+ - **Branching is trunk-based** with a permanent `develop` branch — no feature branches. Parallel work is handled by the AI within a single stream, not by multiple developers on separate branches.
30
+ - **PR reviews** are owner-reviewed with AI-assisted verification. CI provides independent, tamper-resistant evidence. The SDLC workflows and compliance gates replace traditional team ceremonies (standups, sprint planning).
31
+ - **The AI is the second pair of eyes.** It asks which requirement a change is for, blocks implementation until planning is complete, enforces commit conventions, runs compliance gates, and guides evidence compilation.
32
+
33
+ ## Workflow Sequence
34
+
35
+ 0. **Project Setup** (run once) — repo, branches, CI, compliance directories
36
+ 1. **Plan Requirement** — define in RTM, classify risk, generate test scope _before_ implementation
37
+ 2. **Implement and Test** — code on `develop`, all local gates green on every commit
38
+ 3. **Compile Evidence** — gather artifacts, create release ticket, update RTM
39
+ 4. **Submit for Review** — PR triggers independent CI verification + human review
40
+ 5. **Deploy to Main** — merge, verify deployment, finalize compliance artifacts
41
+
42
+ ## Mandatory Gates
43
+
44
+ All templates assume these gates: TypeScript (0 errors), SAST/Semgrep (0 high/critical), dependency audit (0 high/critical), E2E tests (all pass), human PR approval.
45
+
46
+ ## Conventions in Templates
47
+
48
+ - **Commit format:** Conventional Commits with `Co-Authored-By` tags for AI, `Ref: REQ-XXX` for tracked requirements
49
+ - **Requirement IDs:** `REQ-XXX` format, tracked in `compliance/RTM.md`
50
+ - **Status lifecycle:** DRAFT → IN PROGRESS → TESTED - PENDING SIGN-OFF → APPROVED - DEPLOYED
51
+ - **Branching:** permanent `develop` branch, protected `main` (production), merge commits to preserve audit trail
52
+ - **Evidence model:** local testing (comprehensive) + CI testing (independent verification, tamper-resistant)
53
+ - **Placeholders:** Templates use `[BRACKETED_VALUES]` and `# UPDATE` markers for project-specific customization
54
+
55
+ ## When Editing These Templates
56
+
57
+ - Maintain the separation between Tier 1 and Tier 2 — if content applies universally, it belongs in Tier 1; if project-specific, Tier 2.
58
+ - Keep workflow documents as executable procedures with concrete commands, not abstract guidance.
59
+ - Risk classification rules and AI governance controls are defined in Test_Policy.md and Test_Strategy.md — don't duplicate them in workflow files.
60
+ - The article (`article.md`) should stay consistent with the templates; if you change a process in a template, check whether the article describes the old process.
61
+
62
+ ## Syncing Templates to Consuming Projects
63
+
64
+ After updating SDLC templates, sync to consuming projects:
65
+
66
+ ```bash
67
+ # Pass one path per active consumer. Only WGB is live as of 2026-05-19.
68
+ devaudit update v1.x.0 ../wawagardenbar-app
69
+ ```
70
+
71
+ This tags DevAudit, copies all templates (workflow files, AI rules, hooks, scripts, CI templates), and updates tag references in the consuming project's CI workflows. Review the diff in each project before committing.
72
+
73
+ META-AGENT / META-ATS / META-JOBS onboarding attempts were reverted (see [docs/consuming-projects.md](../docs/consuming-projects.md)); pass their paths to the same command if and when they return as live consumers.
@@ -0,0 +1,127 @@
1
+ # Host adapter contract
2
+
3
+ A host adapter teaches the Metasession SDLC how to deploy and verify on one platform — `railway`, `vercel`, `fly`, `kubernetes`, `self-hosted-docker`, etc. Each adapter is a single directory under `sdlc/files/hosts/` containing:
4
+
5
+ ```
6
+ sdlc/files/hosts/<name>/
7
+ └── adapter.json ← the manifest (validated against the schema)
8
+ ```
9
+
10
+ Hosts don't usually bring their own hooks or scripts the way stacks do — the host's contribution is the deploy trigger, the URL-resolution scheme, and the wait/verify snippet that lands inside the post-deploy workflow template. So most host adapters are just a manifest.
11
+
12
+ The schema lives at [`sdlc/files/hosts/_schema/adapter.schema.json`](./files/hosts/_schema/adapter.schema.json) (JSON Schema draft-07). The validator is `scripts/validate-adapter.cjs`; CI runs `node scripts/validate-adapter.cjs --all` on every push to `develop` and validates both stack and host adapters at once.
13
+
14
+ ## Required fields
15
+
16
+ ### Identity
17
+
18
+ | Field | Type | Purpose |
19
+ | ------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
20
+ | `name` | string (`[a-z0-9][a-z0-9-]{0,31}`) | Identifier matching the parent directory and the `host` key in consumer `sdlc-config.json`. |
21
+ | `description` | string | One-line human summary of the platform and how it deploys. |
22
+
23
+ ### Deploy trigger
24
+
25
+ | Field | Type | Purpose |
26
+ | ---------------- | ----------------------------------------------------- | ----------------------------------- |
27
+ | `deploy_trigger` | enum (`push_to_main`, `git_tag`, `manual`, `ci_step`) | What kicks off a production deploy. |
28
+
29
+ - `push_to_main` — Railway, Vercel default. The platform watches the repo and deploys whenever `main` changes. No explicit deploy step in CI.
30
+ - `git_tag` — Some setups deploy on tag push, not on every commit to main.
31
+ - `manual` — Operator clicks "deploy" in the platform's UI. CI doesn't trigger anything.
32
+ - `ci_step` — The CI workflow runs an explicit deploy command (`flyctl deploy`, `kubectl rollout`, `docker compose up`).
33
+
34
+ ### Production URL resolution
35
+
36
+ The post-deploy workflow needs to know **the URL** of the just-deployed production service so it can run smoke tests and record evidence.
37
+
38
+ | Field | Type | Purpose |
39
+ | --------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
40
+ | `production_url_from` | enum (`secret`, `static`, `api_lookup`, `env`) | Where the URL comes from. |
41
+ | `production_url_secret_key` | string (when `production_url_from = secret`) | The `sdlc-config.json` key whose value names the GitHub Secret holding the URL. Typically `production_url_secret`. |
42
+ | `production_url_static` | string (when `production_url_from = static`) | The literal URL (or template). |
43
+
44
+ - `secret` — URL stored as a GitHub Secret per-consumer. Most flexible; right when each project deploys to a different URL.
45
+ - `static` — URL hardcoded in the adapter. Right when all consumers on this host share a fixed URL pattern (rare).
46
+ - `api_lookup` — Adapter ships a snippet that resolves the URL by calling the host's API (e.g. `flyctl status --json`). Right when the URL is auto-generated and changes per deploy.
47
+ - `env` — URL is set as a workflow env var from elsewhere in the consumer's CI. Right for self-hosted setups that already know the URL out-of-band.
48
+
49
+ The schema enforces that `production_url_secret_key` is present iff `production_url_from = secret`, and same for `static`.
50
+
51
+ ## Optional fields
52
+
53
+ ### Wait and post-deploy
54
+
55
+ | Field | Type | Purpose |
56
+ | ------------------ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
57
+ | `wait_for_deploy` | string (shell snippet) | Blocks until the deploy is live and healthy. Embedded into `post-deploy-prod.yml.template` at sync time. Omit for hosts where deploy is synchronous. |
58
+ | `post_deploy_hook` | string (shell snippet) | Runs after a successful deploy — cache warmup, host-specific bookkeeping, additional smoke tests. |
59
+
60
+ Both snippets run in a `bash -e` step; they can reference `${PROD_URL}` and any `required_env` values.
61
+
62
+ ### Required secrets and env
63
+
64
+ | Field | Type | Purpose |
65
+ | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
66
+ | `required_secrets` | string[] | GitHub Secrets the adapter expects to be set on the consumer repo. CI workflows fail at runtime if these are missing. |
67
+ | `required_env` | string[] | Non-sensitive identifiers (app names, region IDs) the consumer must set — typically populated from `sdlc-config.json`. |
68
+
69
+ Sync may warn if these are absent; it's a soft check (the CI workflow is the hard check, since the script can't authenticate to the host on the dev's behalf).
70
+
71
+ ### sdlc-config.json keys
72
+
73
+ | Field | Type | Purpose |
74
+ | ---------------------- | -------- | -------------------------------------------------------------- |
75
+ | `config_keys.required` | string[] | Keys consumers must define. |
76
+ | `config_keys.optional` | string[] | Keys consumers may define (e.g. an optional database service). |
77
+ | `config_keys.defaults` | object | Fallback values when a key is absent. |
78
+
79
+ ### Notes
80
+
81
+ | Field | Type | Purpose |
82
+ | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
83
+ | `notes` | string[] | Free-form notes about the host's quirks. Backed up here so future maintainers don't rediscover them. Not consumed by templates. |
84
+
85
+ ## Adding a new host
86
+
87
+ See the step-by-step walkthrough: **[docs/adding-a-host.md](../docs/adding-a-host.md)** — uses Fly.io as the worked example. The high-level shape is:
88
+
89
+ 1. **Create the directory** `sdlc/files/hosts/<name>/`.
90
+ 2. **Author `adapter.json`** with every required field. Use `hosts/railway/adapter.json` as a worked example.
91
+ 3. **Run the validator:** `node scripts/validate-adapter.cjs sdlc/files/hosts/<name>/adapter.json`. Fix any errors.
92
+ 4. **Validate against a real consumer** before merging — at least one project on this host should sync cleanly and reach `released` end-to-end. A host adapter validated only against `examples/` isn't load-bearing.
93
+
94
+ ## Worked example: Fly.io
95
+
96
+ ```json
97
+ {
98
+ "$schema": "../_schema/adapter.schema.json",
99
+ "name": "fly",
100
+ "description": "Fly.io-hosted services. CI runs `flyctl deploy` explicitly; production URL discovered via the Fly API.",
101
+ "deploy_trigger": "ci_step",
102
+ "production_url_from": "api_lookup",
103
+ "wait_for_deploy": "for i in $(seq 1 30); do flyctl status --app \"${APP_NAME}\" --json | jq -e '.Deployment.Status == \"successful\"' && break; sleep 10; done",
104
+ "required_secrets": ["FLY_API_TOKEN", "DEVAUDIT_API_KEY"],
105
+ "required_env": ["APP_NAME"],
106
+ "notes": [
107
+ "Production URL is resolved at deploy time by flyctl — no GitHub Secret to maintain.",
108
+ "Deploy step runs `flyctl deploy --remote-only` in the post-deploy workflow; FLY_API_TOKEN is the auth."
109
+ ]
110
+ }
111
+ ```
112
+
113
+ This adapter isn't shipped yet — listed here as a sketch of what a non-Railway host adapter looks like.
114
+
115
+ ## Why JSON Schema
116
+
117
+ Same reasons as [STACK_ADAPTER.md](./STACK_ADAPTER.md#why-json-schema-not-zod-not-a-typescript-interface): IDE tooling, language-neutrality, stable versioned artifact. The validator script is the same one stacks use — auto-detects the type from path and applies the matching schema.
118
+
119
+ ## Evolution
120
+
121
+ Backward-compatible additions (new optional fields) need:
122
+
123
+ 1. Schema update.
124
+ 2. This doc updated.
125
+ 3. Existing adapters can stay as they are.
126
+
127
+ Backward-incompatible changes (renaming or removing required fields, narrowing an enum) need a v1.24.0-level version bump and a migration note for consumers.
package/sdlc/SKILLS.md ADDED
@@ -0,0 +1,137 @@
1
+ # SDLC Skills — contract and conventions
2
+
3
+ The Metasession SDLC framework ships **Claude Code Skills** alongside its stage docs, adapters, and CI templates. Skills are self-contained behaviour packs the AI agent invokes when it recognises a relevant trigger — "add e2e tests for [ticket]", "classify the risk tier of this REQ", "triage these SAST findings". They specialise within stages (the stage doc owns _when and why_; the skill owns _how_).
4
+
5
+ This document is the contract every framework-shipped skill must follow. For the walkthrough on adding a new skill, see [docs/adding-a-skill.md](../docs/adding-a-skill.md). For the architectural rationale on the framework's layered design, see [ADR-001](../docs/ADR/ADR-001-polyglot-sdlc-architecture.md).
6
+
7
+ ## Where skills live
8
+
9
+ Same layering as adapters:
10
+
11
+ ```
12
+ sdlc/files/
13
+ ├── _common/
14
+ │ └── skills/ ← universal skills (stack-agnostic)
15
+ │ ├── _schema/skill.schema.json ← frontmatter schema
16
+ │ └── <skill-name>/
17
+ │ ├── SKILL.md ← required: frontmatter + instructions
18
+ │ └── references/ ← optional: longer docs the skill links to
19
+ └── stacks/
20
+ ├── node/
21
+ │ └── skills/ ← node-only skills (when needed)
22
+ └── python/
23
+ └── skills/ ← python-only skills (when needed)
24
+ ```
25
+
26
+ A skill is `_common/` when its body is genuinely framework-agnostic (auto-detects toolchain, doesn't depend on a single ecosystem). It's stack-scoped when its instructions assume a specific package manager, test framework, or build tool that other stacks don't share.
27
+
28
+ ## How skills reach consumers
29
+
30
+ `devaudit update` (cli/src/update/skills.ts) copies every skill directory into the consumer's `.claude/skills/<skill-name>/` on every sync:
31
+
32
+ - All `_common/skills/<name>/` directories sync to every consumer.
33
+ - `stacks/<stack>/skills/<name>/` directories sync only when the consumer's `sdlc-config.json` selects that stack.
34
+ - The `_schema/` directory (and any other `_`-prefixed directory) is **not** synced — schemas are framework infrastructure.
35
+
36
+ Claude Code reads `.claude/skills/*/SKILL.md` for discovery; once synced, the skill is immediately available to the consumer's AI agent without further configuration.
37
+
38
+ Other AI tools (Cursor, Windsurf, Gemini CLI) don't have a native Skill mechanism. The skill content is referenced from `INSTRUCTIONS.md` so non-Claude agents can still consume it manually — they don't auto-invoke based on `description` triggers, but the content is reachable.
39
+
40
+ ### Additional emissions
41
+
42
+ A skill is allowed to ship code that the consumer's test/build tooling needs to `import` at runtime — a helper, a fixture, a shared utility. The canonical source lives under the skill's `references/` directory (so it's discoverable alongside the SKILL.md that teaches its use), and `devaudit update` emits a copy into the right place in the consumer's source tree.
43
+
44
+ Currently the only such emission is the e2e-test-engineer skill's `evidence.ts` helper, which syncs to `<consumer>/e2e/helpers/evidence.ts` on node-stack consumers. The pattern: add a guarded section to the CLI skill sync (`cli/src/update/skills.ts`) — the skill's main bundle still syncs to `.claude/skills/` as normal, but the extra file lands where the consumer's tests can import it.
45
+
46
+ Use this pattern sparingly. If the skill only needs to teach a concept, a Markdown example in SKILL.md is enough. If the skill prescribes a helper consumers must call from their own code, that helper deserves to be canonical and shipped — not copy-pasted from a doc.
47
+
48
+ ## SKILL.md frontmatter contract
49
+
50
+ Required fields:
51
+
52
+ | Field | Type | Constraint | Purpose |
53
+ | ------------- | ------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `name` | string | `^[a-z0-9][a-z0-9-]{1,63}$` | Identifier matching the parent directory. How Claude refers to the skill when reporting which one fired. |
55
+ | `description` | string | minLength 50 | What the skill does **and** when to invoke it. The "when" half drives discovery — without trigger phrases, the skill never fires. Aim for 100–500 chars. |
56
+
57
+ Optional fields:
58
+
59
+ | Field | Type | Purpose |
60
+ | --------- | -------- | ------------------------------------------------------------------------------------------ |
61
+ | `version` | string | Semver. Useful when a skill's behaviour changes incompatibly so consumers can pin. |
62
+ | `tags` | string[] | Documentation grouping (e.g. `testing`, `security`, `compliance`). Not consumed by Claude. |
63
+ | `license` | string | SPDX identifier or `proprietary`. |
64
+
65
+ `additionalProperties: false` — new fields require a deliberate schema update first.
66
+
67
+ The body of SKILL.md (everything after the closing `---`) is free-form Markdown. Claude reads it as the skill's instructions. Conventions worth following:
68
+
69
+ - Open with a one-paragraph summary of what the skill does.
70
+ - A **Scope** section: in-scope and out-of-scope behaviours.
71
+ - A **Workflow** section: numbered phases the skill walks through. Each phase should be self-contained enough that re-entering mid-skill is sensible.
72
+ - **Principles** at the end: cross-cutting rules the skill never violates (e.g. "never delete tests without explicit confirmation").
73
+
74
+ ## How to write a good `description`
75
+
76
+ This is the load-bearing field. Bad descriptions lead to "the skill never fires" or "the skill fires constantly on irrelevant requests". Aim for:
77
+
78
+ 1. **What the skill does**, in one clause. _"Maintain or bootstrap a project's end-to-end and visual regression test pack."_
79
+ 2. **When to invoke it.** Both natural-language phrasings and concrete triggers. _"Use when the user wants to add, update, or retire e2e or visual tests for a feature, ticket, issue, or PR."_ Then list explicit trigger phrases: _"Trigger on phrases like 'add e2e tests for [ticket]', 'update the test pack', 'what tests do we need for this issue'…"_
80
+ 3. **When NOT to invoke.** Explicit out-of-scope rules. _"Do NOT use for unit, component, or API-only tests, or performance tests."_
81
+
82
+ If a contributor reads only the description and gets the right invocation pattern, the description is doing its job.
83
+
84
+ ## Validation
85
+
86
+ CI runs `node scripts/validate-adapter.cjs --all` on every push to develop. The validator parses the YAML frontmatter at the top of every `SKILL.md` and validates against `sdlc/files/_common/skills/_schema/skill.schema.json`. Errors are reported with the offending field path.
87
+
88
+ To validate a single skill locally:
89
+
90
+ ```bash
91
+ node scripts/validate-adapter.cjs sdlc/files/_common/skills/<name>/SKILL.md
92
+ ```
93
+
94
+ ## Skills currently shipped
95
+
96
+ | Skill | Location | Triggers (paraphrased) | Additional emissions |
97
+ | ------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
98
+ | `e2e-test-engineer` | `_common/skills/` | "add e2e tests", "bootstrap an e2e suite", "update the test pack", "are any tests obsolete", "run e2e tests and file issues" | `e2e/helpers/evidence.ts` (node-stack consumers) |
99
+
100
+ ## Skills on the roadmap
101
+
102
+ | Candidate skill | Likely trigger surface | Supports SDLC stage |
103
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
104
+ | `sdlc-implementer` | "implement issue #N under the SDLC", "run the SDLC for issue #N", "automate REQ-XXX from issue to release", "do the SDLC for [issue]" | All stages (1–5) |
105
+
106
+ `sdlc-implementer` is an **orchestration skill** — it drives Claude Code's native tools (`gh`, shell, `devaudit` CLI, portal API) through the full 5-stage flow against a single GitHub issue, pausing only at the UAT-review gate (and at the plan checkpoint for HIGH/CRITICAL risk). It replaces an earlier roadmap of five atomic skills (`risk-classifier`, `commit-message-author`, `compliance-evidence-author`, `sast-triager`, `release-ticket-author`) that were deprioritised — Claude Code's innate capabilities already cover what those atomic skills wrapped; the value-add is end-to-end orchestration with framework-compliant pauses, not five discoverable helpers a human still has to compose.
107
+
108
+ **Current status.** SKILL.md + 3 references files are authored at [`sdlc/files/_common/skills/sdlc-implementer/`](./files/_common/skills/sdlc-implementer/) on `main` (Phase B, PR #31). Validator passes. Phase C — smoke against `wawagardenbar-app` — is the last step before this row moves to "Skills currently shipped" above.
109
+
110
+ **Sub-skill invocation requirement.** During its Phase 2 (Implement & test), the orchestrator **MUST** invoke `e2e-test-engineer` for any end-to-end or visual-regression test work — both scenario derivation from the implementation plan and execution of the resulting suite. The orchestrator does NOT author e2e tests directly. (Unit tests stay with the orchestrator until a unit-test counterpart skill ships.) The invocation pattern is documented in [docs/adding-a-skill.md §Orchestrator skills](../docs/adding-a-skill.md#orchestrator-skills-calling-other-skills); this is a hard contract — the orchestrator's SKILL.md fails review if it inlines `e2e-test-engineer`'s procedure.
111
+
112
+ Tracking: [`metasession-dev/DevAudit-Installer#29`](https://github.com/metasession-dev/DevAudit-Installer/issues/29) (umbrella).
113
+
114
+ Other speculative skills land when a real driver appears (a project's day-to-day work surfaces the same pain repeatedly and the orchestrator's internals demonstrably need it as a separable component).
115
+
116
+ ## When to make a skill vs. when to keep something in a stage doc
117
+
118
+ Three rules of thumb:
119
+
120
+ 1. **Stage docs own _when_ and _why_.** "After Stage 2 implementation, before Stage 3 evidence compilation, the team should…" — that's stage-doc material, not skill material.
121
+ 2. **Skills own _how_.** Multi-step procedures that are reusable across requirements, opinionated about technique, and benefit from being invoked by a discovery-trigger phrase belong in skills.
122
+ 3. **If two stage docs would each instruct the AI to do the same multi-step procedure, lift it into a skill.** Both Stage 2 ("update tests") and Stage 3 ("re-run the suite, file defects") need the same e2e-test-engineering procedure. Lifting that into a skill keeps the stage docs focused on flow and avoids drift.
123
+
124
+ ## Evolution
125
+
126
+ Backward-compatible additions to the frontmatter (new optional fields): update the schema first, then the docs, then the skills can adopt the new field.
127
+
128
+ Renaming or removing a required field is a v1.next-major change with a deprecation cycle (mirror `working_directory` rollout: warn for one minor version, refuse in the next).
129
+
130
+ When a skill's behaviour changes meaningfully, bump its `version`. Consumers pinning to an old version can re-sync at their own pace.
131
+
132
+ ## See also
133
+
134
+ - [docs/adding-a-skill.md](../docs/adding-a-skill.md) — walkthrough for authoring a new skill.
135
+ - [STACK_ADAPTER.md](./STACK_ADAPTER.md) / [HOST_ADAPTER.md](./HOST_ADAPTER.md) — sibling contracts for the adapter layers.
136
+ - [ADR-001](../docs/ADR/ADR-001-polyglot-sdlc-architecture.md) — why the framework is layered this way.
137
+ - [Anthropic's Claude Code Skills docs](https://docs.claude.com/en/docs/claude-code/skills) — upstream format reference.