@metasession.co/devaudit-cli 0.3.14 → 0.3.16

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.
@@ -97,10 +97,18 @@ jobs:
97
97
  # release ticket (the same set the dev/UAT pipeline versioned via
98
98
  # derive-release-version.sh → REQ-XXX). A bundled develop→main PR
99
99
  # carries several; promote ALL of them, not just the first. A manual
100
- # dispatch can target one via the `release` input. Fall back to a
101
- # bare date for date-versioned (ticketless) releases.
100
+ # dispatch can target one via the `release` input. A ticketless
101
+ # main promotion is only valid when its explicit standalone
102
+ # housekeeping declaration is present and valid.
102
103
  if [ -n "${RELEASE_INPUT}" ]; then
103
104
  REQS="${RELEASE_INPUT}"
105
+ if [[ "$REQS" =~ ^v[0-9]{4}\.[0-9]{2}\.[0-9]{2}(\.[0-9]+)?$ ]]; then
106
+ chmod +x scripts/standalone-housekeeping-release.sh 2>/dev/null || true
107
+ DECLARATION="compliance/standalone-housekeeping/STANDALONE-HOUSEKEEPING-${REQS}.json"
108
+ bash scripts/standalone-housekeeping-release.sh validate "$REQS" "$DECLARATION"
109
+ echo "STANDALONE_DECLARATION=${DECLARATION}" >> "$GITHUB_ENV"
110
+ echo "TERMINAL_STATUS=released" >> "$GITHUB_ENV"
111
+ fi
104
112
  else
105
113
  REQS=""
106
114
  if [ -d compliance/pending-releases ]; then
@@ -111,7 +119,20 @@ jobs:
111
119
  fi
112
120
  REQS=$(echo ${REQS} | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/[[:space:]]*$//')
113
121
  if [ -z "${REQS}" ]; then
114
- REQS="v$(date +%Y.%m.%d)"
122
+ chmod +x scripts/derive-release-version.sh scripts/standalone-housekeeping-release.sh 2>/dev/null || true
123
+ VERSION=$(bash scripts/derive-release-version.sh)
124
+ DECLARATION="compliance/standalone-housekeeping/STANDALONE-HOUSEKEEPING-${VERSION}.json"
125
+ if [ -f "$DECLARATION" ]; then
126
+ bash scripts/standalone-housekeeping-release.sh validate "$VERSION" "$DECLARATION"
127
+ REQS="$VERSION"
128
+ echo "STANDALONE_DECLARATION=${DECLARATION}" >> "$GITHUB_ENV"
129
+ # Standalone housekeeping is reviewed in its GitHub promotion
130
+ # PR. It does not enter the portal UAT/production queue unless
131
+ # a project deliberately supplies a tracked REQ instead.
132
+ echo "TERMINAL_STATUS=released" >> "$GITHUB_ENV"
133
+ else
134
+ echo "No tracked release ticket or standalone declaration: ordinary housekeeping has no portal promotion."
135
+ fi
115
136
  fi
116
137
  fi
117
138
  echo "In-scope releases to promote: ${REQS}"
@@ -413,6 +434,9 @@ jobs:
413
434
  # Carry the release ticket into the production environment so the
414
435
  # prod-review gate is self-contained.
415
436
  TICKET=""
437
+ if [ -n "${STANDALONE_DECLARATION:-}" ] && [ "$VERSION" = "${REQS}" ]; then
438
+ TICKET="$STANDALONE_DECLARATION"
439
+ fi
416
440
  for DIR in compliance/pending-releases compliance/approved-releases; do
417
441
  if [ -f "${DIR}/RELEASE-TICKET-${VERSION}.md" ]; then
418
442
  TICKET="${DIR}/RELEASE-TICKET-${VERSION}.md"; break
@@ -447,6 +471,11 @@ jobs:
447
471
  fi
448
472
  # Advance status (idempotent — re-PATCHing an already-promoted release is a no-op).
449
473
  if [ -n "$RELEASE_ID" ]; then
474
+ if [ -n "${STANDALONE_DECLARATION:-}" ] && [ "$VERSION" = "${REQS}" ]; then
475
+ chmod +x scripts/standalone-housekeeping-release.sh 2>/dev/null || true
476
+ bash scripts/standalone-housekeeping-release.sh promote \
477
+ "$PROJECT_SLUG" "$VERSION" "$STANDALONE_DECLARATION"
478
+ fi
450
479
  curl -s -o /dev/null -w " ${VERSION} status patch: HTTP %{http_code}\n" \
451
480
  -X PATCH "${BASE}/api/ci/releases/${RELEASE_ID}" \
452
481
  -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
package/sdlc/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metasession.co/devaudit-sdlc",
3
- "version": "0.3.14",
3
+ "version": "0.3.16",
4
4
  "description": "DevAudit SDLC CLI Engine — cross-agent terminal-driven SDLC orchestrator.",
5
5
  "bin": {
6
6
  "devaudit-sdlc": "./src/bin/devaudit-sdlc.js"
@@ -70,37 +70,21 @@ Both `ci.yml` and `compliance-evidence.yml` call the same helper, so a feature s
70
70
 
71
71
  If you need a separate release container for a sub-piece of work — e.g. carving REQ-038 out of an in-flight feature — give it its own REQ-ID and tag the commits accordingly.
72
72
 
73
- ## Two release shapes
73
+ ## Release modes
74
74
 
75
- A release is classified by its version pattern. **Most of this doc walks the tracked path** (a REQ-XXX-tagged release for a single requirement). For develop pushes that don't carry a REQ tag — typically `docs:`, `chore:`, `ci:`, `build:`, `test:`, `compliance:`, `revert:` — the version-deriver falls back to a bare date and the release is **housekeeping**.
75
+ A release is classified by version shape and release mode. **Most of this doc walks the tracked path** (a REQ-XXX-tagged release for a single requirement). For develop pushes without a REQ tag — typically `docs:`, `chore:`, `ci:`, `build:`, `test:`, `compliance:`, `revert:` — the version deriver falls back to a bare date.
76
76
 
77
- | Shape | Version pattern | Triggered by | Per-REQ ceremony |
77
+ | Mode | Version pattern | Triggered by | Outcome |
78
78
  | --- | --- | --- | --- |
79
79
  | **Tracked** | `REQ-037`, `REQ-046-FIX`, etc. | A `feat`/`fix`/`refactor`/`perf` commit (REQ tag required by commitlint) | Yes — full Steps 1-9 |
80
- | **Housekeeping** | `v2026.06.04` (bare date, optionally `.N`) | A push containing only REQ-exempt commit types | **No** per-REQ artefacts; the portal auto-skips test-scope, test-plan, implementation-plan, and test-execution-summary completeness checks |
80
+ | **Integration housekeeping** | `v2026.06.04` (bare date, optionally `.N`) | A normal REQ-exempt change | Terminal-green reviewed integration history; no tracked approval ceremony |
81
+ | **Standalone housekeeping** | `v2026.06.04` (bare date, optionally `.N`) | An explicitly declared exception | Distinct release only after its validated declaration, reason, and production verification |
81
82
 
82
- ### Housekeeping releases — what's required
83
+ ### Housekeeping outcomes
83
84
 
84
- Housekeeping releases **skip** the per-requirement evidence (no REQ no `compliance/evidence/REQ-XXX/` folder) but **still produce two release-scoped artefacts**:
85
+ Normal housekeeping skips the per-requirement evidence and approval path. Run the relevant gates, obtain terminal-green PR review, and merge to `develop`; the bare-date portal row is integration history. When a tracked release later absorbs the work, its bundled-change manifest preserves the source title, evidence ownership, stage, and cycles.
85
86
 
86
- | Artefact | Tracked path | Housekeeping path | Auto-generated by CI? |
87
- | --- | --- | --- | --- |
88
- | Release ticket | `compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md` (Step 8) | `compliance/pending-releases/RELEASE-TICKET-<version>.md` (e.g. `RELEASE-TICKET-v2026.06.04.md`) | **Yes** — `generate-housekeeping-release-ticket.sh` runs after `derive-release-version.sh` and emits a stub the operator reviews + signs off |
89
- | Security summary | `compliance/evidence/REQ-XXX/security-summary.md` (Step 4) | `compliance/security-summary-<version>.md` at the compliance root (release-scoped, not REQ-scoped) | **Yes** — `generate-security-summary.sh` scrapes the SAST + dep-audit gate JSON and emits a stub with an operator sign-off block |
90
-
91
- **Filename conventions are enforced.** Release tickets must match `RELEASE-TICKET-REQ-XXX.md` or `RELEASE-TICKET-vYYYY.MM.DD.md` exactly. Security summaries must be named `security-summary.md` exactly. The CI upload pipeline (`compliance-evidence.yml`) routes per-REQ artifacts by basename to specific `evidence_type` values — unrecognized filenames are skipped with a warning (DevAudit-Installer#205). The `validate-compliance-artifacts.sh` PR-time check also warns on unrecognized filenames in `compliance/evidence/REQ-XXX/`. The version-suffixed conventions above are recommended for **searchability + audit trail** when a project has many housekeeping releases stacked up — they keep the artefacts distinct per release without needing folder scoping.
92
-
93
- **What housekeeping operators do, end to end:**
94
-
95
- 1. Push the `docs:` / `chore:` / `ci:` commits to develop. CI runs the four gates as usual.
96
- 2. CI's `compliance-evidence.yml` workflow auto-opens a PR (`chore/housekeeping-release-<version>`) containing the two stubs.
97
- 3. Review the stubs — confirm the commit-summary list in the release ticket is sensible, confirm the SAST + dep-audit summary reads correctly, fill in the operator sign-off block on each.
98
- 4. Merge that PR. The next CI run picks up the artefacts and the portal's release-completeness checklist flips both items to ✓.
99
- 5. Submit for UAT review on the portal. The approval flow is identical to the tracked path — same four-eyes rules (per project risk tier), same `draft → uat_review → uat_approved → prod_review → prod_approved → released` state machine.
100
-
101
- **No auto-approval.** Housekeeping releases still require operator action to advance through the gates. The CI-generated stubs replace the operator's authoring effort, not the operator's review.
102
-
103
- > **Versions of the framework before 2026-06 produced housekeeping stubs by hand.** Older release records may have `security-summary.md` under a REQ-XXX-shaped folder or no release ticket at all — leave those in DRAFT for the audit trail; backfilling isn't required.
87
+ Use standalone housekeeping only when the change cannot reasonably wait for that tracked release. Follow `docs/release-playbooks/housekeeping-release.md`: add the validated `STANDALONE-HOUSEKEEPING-vYYYY.MM.DD.json` declaration, document why promotion is necessary, pass the required checks, and verify production. There is no automatic release-ticket or security-summary stub PR for either housekeeping outcome.
104
88
 
105
89
  ## Steps
106
90
 
@@ -45,13 +45,13 @@ gh pr merge [PR-NUMBER] --merge --delete-branch=false
45
45
 
46
46
  **Do NOT delete `develop`** — it's the permanent working branch.
47
47
 
48
- ### Step 2: Sync Branches
48
+ ### Step 2: Preserve GitFlow
49
49
 
50
- ```bash
51
- git checkout main && git pull origin main
52
- git checkout develop && git pull origin develop
53
- git merge main --no-edit && git push origin develop
54
- ```
50
+ Normal release synchronization is performed by the portal-dispatched close-out
51
+ PR after the release reaches `released`; do not directly merge the release
52
+ branch into the integration branch. A real hotfix is the exception: after its
53
+ reviewed merge to the release branch, open the mandatory `backmerge/*` PR to the
54
+ integration branch and merge it only after terminal-green checks.
55
55
 
56
56
  ### Step 3: Verify Production Deployment
57
57
 
@@ -149,11 +149,11 @@ The backend stores both with reviewer identity, SHA, and timestamp. This satisfi
149
149
 
150
150
  #### Steps
151
151
 
152
- 1. Wait for `post-deploy-prod.yml` to complete (the workflow's "Advance release status" step prints `Release vYYYY.MM.DD prod_review` when done).
152
+ 1. Wait for `post-deploy-prod.yml` to complete successfully **and** for its host-deployment check to confirm terminal success for the merged SHA.
153
153
  2. Open the release in DevAudit: `https://[DEVAUDIT_BASE_URL]/projects/[PROJECT_SLUG]/releases/[releaseId]`.
154
- 3. Review the `prod-smoke-results.json` evidence (uploaded by the workflow) plus any post-deploy actions logged in the release ticket.
154
+ 3. Review the production deployment and smoke cycle records, their evidence, and any post-deploy actions logged in the release ticket. Do not approve while either cycle or the host deployment remains queued/in progress.
155
155
  4. Click **Approve Production** — status transitions to `prod_approved`.
156
- 5. Click **Mark as Released** — status transitions to `released`. Pipeline lifecycle complete in DevAudit.
156
+ 5. Click **Mark as Released** — status transitions to `released`. This dispatches the automated close-out flow.
157
157
 
158
158
  If the smoke results look wrong or a manual verification fails, click **Reject** on the production approval and follow the Rollback procedure below before retrying.
159
159
 
@@ -161,41 +161,21 @@ If the smoke results look wrong or a manual verification fails, click **Reject**
161
161
 
162
162
  `approval.mode` is checked again here. `dual_actor` means the post-deploy approver must differ from the release creator. `solo_with_gap` accepts self-approval but records the control gap. `auto_low_risk` allows LOW-risk requirements to auto-advance through both transitions on workflow completion; MEDIUM/HIGH always require a human click.
163
163
 
164
- ### Step 6: Finalize Compliance (Tracked Requirements Only)
165
-
166
- > **Automated path (preferred).** Run the synced helper instead of doing this by hand — it flips the ticket Status → `RELEASED` (+ backlinks the release PR and records the sign-off), flips the matching `RTM.md` row, and `git mv`s the ticket to `approved-releases/`, then stages the changes for you to commit:
167
- >
168
- > ```bash
169
- > ./scripts/close-out-release.sh REQ-XXX --release-pr <release-PR-#>
170
- > git add -A && git commit -m "docs(compliance): close out REQ-XXX release ticket (RELEASED)" && git push origin develop
171
- > ```
172
- >
173
- > It is **idempotent** (a no-op if already closed out) and, when `DEVAUDIT_API_KEY` + `DEVAUDIT_BASE_URL` are set, **refuses** unless the portal reports the release as `released` (so you can't flip the local tree ahead of the Production approval). The `close-out-release.yml` workflow runs the same script automatically when the portal marks a release released (and is `workflow_dispatch`-able for catch-up). The manual steps below are the fallback / reference for what the script does.
174
-
175
- ```bash
176
- mv compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md compliance/approved-releases/
177
- ```
164
+ ### Step 6: Automated Close-out (Tracked Requirements Only)
178
165
 
179
- Update `compliance/RTM.md`:
180
- ```markdown
181
- | REQ-XXX | Description | [RISK] | files | evidence | APPROVED - DEPLOYED | [Reviewer] | [Date] |
182
- ```
166
+ When the portal status becomes `released`, it dispatches `release-closed` to the
167
+ consumer repository. `close-out-release.yml` then opens a
168
+ `chore/close-out-REQ-XXX` PR to the configured integration branch. That PR is
169
+ the canonical reconciliation record: it updates the RTM, moves the release
170
+ ticket to `approved-releases/`, and moves manifest-listed absorbed predecessors
171
+ to `superseded-releases/`.
183
172
 
184
- Add audit trail to release ticket:
185
- ```markdown
186
- | [date] | UAT verification passed | [who] | Health + smoke + feature verified on UAT |
187
- | [date] | PR approved | [reviewer] | PR #[number] |
188
- | [date] | CI verification | GitHub Actions | All gates passed independently |
189
- | [date] | Deployed to production | System | Auto-deploy from main |
190
- | [date] | PROD post-deploy verification | [who] | Health + security checks passed on PROD |
191
- ```
192
-
193
- ```bash
194
- git add compliance/RTM.md compliance/approved-releases/ compliance/evidence/REQ-XXX/
195
- git rm compliance/pending-releases/RELEASE-TICKET-REQ-XXX.md 2>/dev/null
196
- git commit -m "compliance: [REQ-XXX] approved and deployed - PR #[number]"
197
- git push origin develop
198
- ```
173
+ Review and merge the close-out PR after its required checks are terminal green
174
+ on its current head SHA. It is an administrative reconciliation PR, not a new
175
+ production release. If the dispatch did not arrive, manually dispatch the
176
+ Release Close-out workflow. Run `scripts/close-out-release.sh` locally only for
177
+ documented recovery or historical catch-up; never create a normal direct
178
+ close-out commit on a protected branch.
199
179
 
200
180
  ### Step 7: Close the GitHub Issue
201
181
 
@@ -207,17 +187,10 @@ gh issue close [ISSUE-NUMBER] --comment "Implemented in PR #[PR-NUMBER] (REQ-XXX
207
187
 
208
188
  This is the final traceability link: Issue → Requirement → PR → Deployment → Issue closed.
209
189
 
210
- ### Step 8: Final Sync
211
-
212
- ```bash
213
- git checkout main && git merge develop --no-edit && git push origin main
214
- git checkout develop
215
- ```
216
-
217
190
  ## Rollback
218
191
 
219
192
  1. **Hosting dashboard:** Redeploy previous version
220
- 2. **Git:** `git checkout main && git revert HEAD --no-edit && git push origin main`
193
+ 2. **Git:** create `hotfix/revert-REQ-XXX` from the release branch, revert the merge, and open a reviewed PR to the release branch. After terminal-green checks and merge, open the mandatory backmerge PR to integration.
221
194
  3. **Document:** Add rollback entry to release ticket audit trail
222
195
  4. **Correlate with incident (DevAudit-Installer#210 §10a):** If the rollback was triggered by a post-deploy smoke failure, the `post-deploy-prod.yml` workflow files an incident issue with the `incident` label. Reference this incident in the rollback commit message (`Fixes #N` or a comment on the issue) so the incident report captures the containment action. This ensures `incident-export.yml` exports the full incident timeline including the rollback.
223
196
 
@@ -55,7 +55,7 @@ A worked end-to-end example for a zero-risk change (a typo, a dependency bump, a
55
55
  3. **Commit with a housekeeping type.** `docs:` / `chore:` / `ci:` / `build:` / `test:` / `revert:` are **exempt** from the `[REQ-XXX]` rule — e.g. `git commit -m "docs: fix typo in README"`. A `feat` / `fix` / `refactor` / `perf` subject without a `[REQ-XXX]` or `Ref: REQ-XXX` is **rejected** by commitlint and `validate-commits.sh` — if that fires, you picked the wrong type and the change isn't trivial.
56
56
  4. **Run the gates locally — not optional.** `npx tsc --noEmit`, lint, and the test suite must pass before you push. Trivial ≠ unverified.
57
57
  5. **Push and open a PR.** CI runs the same quality gates. `compliance-validation.yml` finds no `REQ-XXX` and **skips** artifact validation; no release ticket, no RTM row, no evidence pack is required.
58
- 6. **Merge once CI is green** and a reviewer approves the PR. A housekeeping push **does** produce a portal release record — a bare-date release (`vYYYY.MM.DD`) and it **does** go through the same UATproduction four-eyes flow as a tracked release. What the portal **auto-skips for housekeeping** is the four per-REQ completeness items (test-scope / test-plan / implementation-plan / test-execution-summary) — those have nothing to evaluate without a `REQ-XXX`. What's still required: all four CI gates green, a release ticket (`compliance/pending-releases/RELEASE-TICKET-<version>.md`), and a security summary (`compliance/security-summary-<version>.md`). **CI auto-generates both stubs as an operator-sign-off PR** (DevAudit-Installer v0.1.41+, scripts `generate-housekeeping-release-ticket.sh` + `generate-security-summary.sh`). Review the stubs + replace the `REPLACE — …` markers + merge → next CI run uploads them matrix flips both items to submit for UAT review on the portal. See [stage-3 housekeeping section](./3-compile-evidence.md) for the full walkthrough.
58
+ 6. **Merge only after terminal-green CI** and reviewer approval. A housekeeping push may create a bare-date portal row, but it is integration history, not a UAT/production approval release. It needs no release ticket, security-summary stub, per-REQ evidence pack, or portal sign-off. The next tracked REQ records absorbed work through bundled-change lineage. Use standalone housekeeping only through the explicit declaration and production-verification path in the release playbook.
59
59
 
60
60
  If at any step it stops feeling trivial — it changes behaviour, touches auth/payments/data, or an auditor would ask about it — switch to a tracked change and run `sdlc-implementer`. When unsure, it's not trivial.
61
61