forgedock 1.0.0
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/LICENSE +244 -0
- package/README.md +251 -0
- package/bin/forgedock.mjs +232 -0
- package/commands/analytics.md +777 -0
- package/commands/audit-agents.md +410 -0
- package/commands/audit.md +410 -0
- package/commands/autopilot.md +432 -0
- package/commands/cleanup.md +264 -0
- package/commands/deploy-info.md +292 -0
- package/commands/failure-recon.md +375 -0
- package/commands/forge-stats.md +183 -0
- package/commands/geo-audit.md +343 -0
- package/commands/incident-response.md +384 -0
- package/commands/issue.md +506 -0
- package/commands/milestone.md +599 -0
- package/commands/orchestrate.md +1044 -0
- package/commands/pipeline-health.md +2343 -0
- package/commands/qa-sweep.md +237 -0
- package/commands/quality-gate.md +777 -0
- package/commands/review-pr-agents.md +1711 -0
- package/commands/review-pr-staging.md +325 -0
- package/commands/review-pr.md +888 -0
- package/commands/rollback.md +253 -0
- package/commands/security-audit.md +529 -0
- package/commands/sync-ecosystem.md +527 -0
- package/commands/validate.md +131 -0
- package/commands/work-on/build/architect.md +291 -0
- package/commands/work-on/build/context.md +349 -0
- package/commands/work-on/build/implement.md +280 -0
- package/commands/work-on/build/validate.md +292 -0
- package/commands/work-on/build.md +262 -0
- package/commands/work-on/close.md +350 -0
- package/commands/work-on/decompose.md +254 -0
- package/commands/work-on/investigate.md +437 -0
- package/commands/work-on/review.md +245 -0
- package/commands/work-on-monolithic.md +298 -0
- package/commands/work-on.md +1089 -0
- package/docs/CODEX.md +92 -0
- package/docs/WORKFLOW.md +104 -0
- package/package.json +45 -0
- package/scripts/verify-env-vars.sh +201 -0
- package/scripts/verify-host-headers.sh +117 -0
- package/scripts/verify-route-registration.sh +118 -0
- package/scripts/verify-sops-chain.sh +163 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Staging review mode — comprehensive review of staging branch before deploy to main
|
|
3
|
+
argument-hint: [PR number or "staging"]
|
|
4
|
+
allowed-tools: Task, Bash, Read, Grep, Glob, WebFetch
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Staging Review
|
|
8
|
+
|
|
9
|
+
**Trigger**: Invoked by the orchestrator via `Skill("review-pr-staging", $ARGUMENTS)`, or directly with `$ARGUMENTS` = "staging", a PR number targeting main, or "staging:feature".
|
|
10
|
+
|
|
11
|
+
Performs comprehensive review of `staging` before merging to `main`. Handles large diffs (1,000-10,000+ lines), diverse changes, deep analysis, and business impact assessment.
|
|
12
|
+
|
|
13
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Evidence-Based Review Protocol (ALL Agents)
|
|
18
|
+
|
|
19
|
+
### Diff-First Approach
|
|
20
|
+
```bash
|
|
21
|
+
git fetch origin main staging
|
|
22
|
+
git diff origin/main...origin/staging
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Dynamic Exploration
|
|
26
|
+
From each changed file, follow imports and function calls. Trace data flows across service boundaries (API → Redis → Worker).
|
|
27
|
+
|
|
28
|
+
### Validation Before Reporting
|
|
29
|
+
|
|
30
|
+
| Confidence | Criteria | Action |
|
|
31
|
+
|------------|----------|--------|
|
|
32
|
+
| CONFIRMED | Traced full code path, found specific proof | Report as P1 |
|
|
33
|
+
| LIKELY | Pattern suggests issue, mitigations might exist | Report as P2 |
|
|
34
|
+
| POSSIBLE | Suspicious but couldn't trace fully | Report as P3 |
|
|
35
|
+
| UNFOUNDED | Found correct handling | Do NOT report |
|
|
36
|
+
|
|
37
|
+
### Severity Decision Tree
|
|
38
|
+
1. Runtime error → HIGH/CRITICAL
|
|
39
|
+
2. Wrong data silently → HIGH
|
|
40
|
+
3. Degraded performance → MEDIUM
|
|
41
|
+
4. Genuinely cosmetic after tracing all consumers → LOW
|
|
42
|
+
|
|
43
|
+
### Interaction Analysis
|
|
44
|
+
NEVER dismiss as "pre-existing" without checking whether NEW code interacts with it to create a bug. List every new line referencing the pre-existing construct; if any would fail at runtime → CONFIRMED finding.
|
|
45
|
+
|
|
46
|
+
### False Positive Prevention
|
|
47
|
+
- Variable scope: Read FULL function, count indentation, check if/else structure
|
|
48
|
+
- Type mismatches: Trace variable to source, check naming
|
|
49
|
+
- Missing functions: `grep -rn "functionName" .` — check re-exports/aliases
|
|
50
|
+
- Unreachable code: Check all callers, dynamic dispatch, tests
|
|
51
|
+
- Redundant imports: In Python, local `import X` makes X local for entire function scope — check for UnboundLocalError
|
|
52
|
+
|
|
53
|
+
### Report Format
|
|
54
|
+
Every finding: File:Line, code snippet, evidence, confidence, files checked.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Structured Findings Protocol
|
|
59
|
+
|
|
60
|
+
Append at end of every agent comment:
|
|
61
|
+
```
|
|
62
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
63
|
+
<!-- FINDING:PREFIX-N|CONFIDENCE|SEVERITY|file.py:line|One-line summary -->
|
|
64
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Include ALL findings (CONFIRMED, LIKELY, POSSIBLE). One line per finding, sequential numbering.
|
|
68
|
+
|
|
69
|
+
**Prefixes**: SEC, AUTH, BILL, CONC, SCRP, FE, API, DB, INFRA, BUG, QA, REG
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Phase 0A: Open Review-Finding Gate (BLOCKING — runs before scope analysis)
|
|
74
|
+
|
|
75
|
+
**Purpose**: Prevent deploying commits that have known, unfixed review findings. The review system catches bugs before merging; this gate ensures the merge path acts on that information.
|
|
76
|
+
|
|
77
|
+
**Why this matters**: Review findings are filed before the originating PR merges to staging. Without this gate, a staging→main bundle can include commits with known unfixed bugs — the review system caught the issue, but the deploy path ignored it. This gate closes the gap between issue discovery and deploy execution. <!-- Added: forge#303 -->
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git fetch origin main staging
|
|
81
|
+
|
|
82
|
+
# Step 1: Find all PR numbers in the staging→main bundle
|
|
83
|
+
# These are the PRs whose commits are included in staging but not yet in main
|
|
84
|
+
BUNDLE_PRS=$(git log origin/main..origin/staging --oneline \
|
|
85
|
+
| grep -oP '#\d+' \
|
|
86
|
+
| sort -u \
|
|
87
|
+
| tr -d '#')
|
|
88
|
+
|
|
89
|
+
# Also extract PR numbers from merge commit subjects (most reliable)
|
|
90
|
+
MERGE_PRS=$(git log origin/main..origin/staging --merges --oneline \
|
|
91
|
+
| grep -oP '(?<=pull request #)\d+' \
|
|
92
|
+
| sort -u)
|
|
93
|
+
|
|
94
|
+
ALL_PR_NUMBERS=$(echo "$BUNDLE_PRS $MERGE_PRS" | tr ' ' '\n' | sort -u | grep -E '^[0-9]+$')
|
|
95
|
+
|
|
96
|
+
echo "PRs in staging→main bundle: $(echo $ALL_PR_NUMBERS | tr '\n' ' ')"
|
|
97
|
+
|
|
98
|
+
# Step 2: For each PR in the bundle, check for open review-finding issues
|
|
99
|
+
BLOCKING_FINDINGS=""
|
|
100
|
+
for pr_num in $ALL_PR_NUMBERS; do
|
|
101
|
+
# Search for open review-finding issues that reference this PR
|
|
102
|
+
OPEN_FINDINGS=$(gh issue list -R {GH_REPO} \
|
|
103
|
+
--label "review-finding" \
|
|
104
|
+
--state open \
|
|
105
|
+
--search "PR #${pr_num}" \
|
|
106
|
+
--limit 20 \
|
|
107
|
+
--json number,title \
|
|
108
|
+
--jq ".[] | \" - #\(.number): \(.title)\"" 2>/dev/null)
|
|
109
|
+
|
|
110
|
+
if [ -n "$OPEN_FINDINGS" ]; then
|
|
111
|
+
BLOCKING_FINDINGS="${BLOCKING_FINDINGS}
|
|
112
|
+
**PR #${pr_num}** has open review findings:
|
|
113
|
+
${OPEN_FINDINGS}"
|
|
114
|
+
fi
|
|
115
|
+
done
|
|
116
|
+
|
|
117
|
+
# Step 3: Block deploy if open findings exist (unless human override present)
|
|
118
|
+
if [ -n "$BLOCKING_FINDINGS" ]; then
|
|
119
|
+
# Check for human override comment on the staging→main PR
|
|
120
|
+
if [ -n "$PR_NUMBER" ]; then
|
|
121
|
+
OVERRIDE=$(gh pr view "$PR_NUMBER" -R {GH_REPO} \
|
|
122
|
+
--json comments \
|
|
123
|
+
--jq '[.comments[].body | select(startswith("OVERRIDE: shipping with open findings"))] | length' 2>/dev/null)
|
|
124
|
+
else
|
|
125
|
+
OVERRIDE=0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
if [ "${OVERRIDE:-0}" -eq 0 ]; then
|
|
129
|
+
echo "⛔ DEPLOY BLOCKED — Open review-finding issues exist for PRs in this bundle."
|
|
130
|
+
echo ""
|
|
131
|
+
echo "$BLOCKING_FINDINGS"
|
|
132
|
+
echo ""
|
|
133
|
+
echo "Options:"
|
|
134
|
+
echo " 1. Wait for the open findings to be fixed and merged to staging first."
|
|
135
|
+
echo " 2. Post a comment on this PR starting with \"OVERRIDE: shipping with open findings — <reason>\" to bypass this gate."
|
|
136
|
+
echo ""
|
|
137
|
+
echo "This gate exists to prevent deploying commits with known unfixed review findings."
|
|
138
|
+
echo "RESULT: BLOCK DEPLOY"
|
|
139
|
+
|
|
140
|
+
# Post structured FORGE:GATE_FAILURE comment for pipeline-health tracking
|
|
141
|
+
FINDING_COUNT=$(echo "$BLOCKING_FINDINGS" | grep -c '^\s*- #' || echo "unknown")
|
|
142
|
+
GATE_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
143
|
+
if [ -n "$PR_NUMBER" ]; then
|
|
144
|
+
gh pr comment "$PR_NUMBER" -R {GH_REPO} --body "<!-- FORGE:GATE_FAILURE -->
|
|
145
|
+
## Deploy Gate: BLOCKED
|
|
146
|
+
|
|
147
|
+
**Gate**: open-review-finding
|
|
148
|
+
**Timestamp**: ${GATE_TIMESTAMP}
|
|
149
|
+
**Blocking findings**: ${FINDING_COUNT}
|
|
150
|
+
|
|
151
|
+
### Open Review-Finding Issues
|
|
152
|
+
|
|
153
|
+
${BLOCKING_FINDINGS}
|
|
154
|
+
|
|
155
|
+
### Resolution
|
|
156
|
+
|
|
157
|
+
Fix the open findings above and merge fixes to staging before retrying the staging→main deploy.
|
|
158
|
+
To override (ship known issues with documented reason), post a comment starting with:
|
|
159
|
+
\`OVERRIDE: shipping with open findings — <reason>\`
|
|
160
|
+
|
|
161
|
+
<!-- FORGE:GATE_FAILURE:TYPE=open-review-finding|FINDINGS=${FINDING_COUNT} -->" 2>/dev/null || true
|
|
162
|
+
fi
|
|
163
|
+
exit 1
|
|
164
|
+
else
|
|
165
|
+
echo "⚠️ Open review findings exist but human override detected — proceeding with deploy."
|
|
166
|
+
echo "$BLOCKING_FINDINGS"
|
|
167
|
+
echo "Override comment found on PR #${PR_NUMBER}. Continuing."
|
|
168
|
+
fi
|
|
169
|
+
else
|
|
170
|
+
echo "✅ Open review-finding gate: PASSED — no open findings for PRs in this bundle."
|
|
171
|
+
fi
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
If the gate exits with `RESULT: BLOCK DEPLOY` → **STOP**. Do NOT proceed to Phase 0B or any downstream phases. A `<!-- FORGE:GATE_FAILURE -->` structured comment is automatically posted on the staging→main PR (if `$PR_NUMBER` is set) for pipeline-health tracking. Report the blocking finding list.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Phase 0B: Scope Analysis
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
git fetch origin main staging
|
|
182
|
+
git diff origin/main...origin/staging --stat | tail -20
|
|
183
|
+
git diff origin/main...origin/staging --numstat | awk '{add+=$1; del+=$2} END {print "Added:", add, "Deleted:", del, "Total:", add+del}'
|
|
184
|
+
git diff origin/main...origin/staging --name-only | sort | uniq
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Categorize by service (API, Worker, Web, Shared, Infra). Identify high-risk files (billing, credits, pricing, auth, security, migration, scraper).
|
|
188
|
+
|
|
189
|
+
Create review chunks by priority: Billing/Pricing (CRITICAL) → Security/Auth (CRITICAL) → Scraper Core (HIGH) → API Routers (HIGH) → Worker (HIGH) → Web (MEDIUM) → Shared (MEDIUM) → Infra (MEDIUM) → Other (LOW).
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Phase 1: Automated Checks
|
|
194
|
+
|
|
195
|
+
### 1A: Python Linting
|
|
196
|
+
```bash
|
|
197
|
+
cd services/api && poetry run black --check app/ && poetry run isort --check app/
|
|
198
|
+
cd services/worker && poetry run black --check worker/ && poetry run isort --check worker/
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 1B: TypeScript Type-Check + Build (MANDATORY)
|
|
202
|
+
```bash
|
|
203
|
+
cd web && npx tsc --noEmit 2>&1
|
|
204
|
+
cd web && npx next build 2>&1 | tail -50
|
|
205
|
+
```
|
|
206
|
+
`next build` failure is BLOCKING — deploy WILL fail. `tsc` alone misses SSG prerender failures.
|
|
207
|
+
|
|
208
|
+
### 1C: Python Tests
|
|
209
|
+
```bash
|
|
210
|
+
cd services/api && poetry run pytest tests/ -x -q --tb=short 2>&1 | tail -50
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 1D: Secrets Scan
|
|
214
|
+
```bash
|
|
215
|
+
git diff origin/main...origin/staging | grep -iE "(api[_-]?key|secret|password|token|credential)" | grep -vE "(#|//|\.example|placeholder)" | head -20
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 1E: CI Status Gate (BLOCKING)
|
|
219
|
+
```bash
|
|
220
|
+
gh pr checks ${PR_NUMBER} 2>&1
|
|
221
|
+
```
|
|
222
|
+
Any CI failure → BLOCK DEPLOY (unless autofixed in Phase 1F).
|
|
223
|
+
|
|
224
|
+
### Phase 1F: CI Autofix
|
|
225
|
+
|
|
226
|
+
If CI fails, attempt automatic fix before blocking:
|
|
227
|
+
|
|
228
|
+
| Failure Pattern | Category | Autofixable? |
|
|
229
|
+
|----------------|----------|--------------|
|
|
230
|
+
| Black/isort formatting | FORMATTING | Yes |
|
|
231
|
+
| Type error in next build | TYPE_ERROR | Yes |
|
|
232
|
+
| Module not found | IMPORT_ERROR | Yes |
|
|
233
|
+
| Prerender error | PRERENDER | Maybe |
|
|
234
|
+
| Test assertion failure | TEST_FAILURE | No |
|
|
235
|
+
| Infrastructure flake | FLAKE | No |
|
|
236
|
+
|
|
237
|
+
For fixable failures: checkout staging, apply fix, verify locally, commit as `fix(ci): ...`, push, wait for CI re-run (max 10 min). Max 1 autofix attempt. If it fails → BLOCK DEPLOY.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Phase 2: Material Change Analysis
|
|
242
|
+
|
|
243
|
+
Launch agent (model: sonnet) to analyze all commits since last deploy. Categorize as: NEW FEATURE, ENHANCEMENT, BUG FIX, REFACTOR, SECURITY, PERFORMANCE, INFRASTRUCTURE, DEPENDENCY. Separate user-facing vs internal. Document breaking changes and required pre-deploy actions.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Phase 3: Bug Hunter Review (Per-Service)
|
|
248
|
+
|
|
249
|
+
Launch Bug Hunter agents for each service with changes:
|
|
250
|
+
|
|
251
|
+
**API Bug Hunter** (services/api/): Logic errors, error handling, type issues, resource leaks, state issues, auth bugs, data flow tracing. Prefix: BUG/AUTH.
|
|
252
|
+
|
|
253
|
+
**Worker Bug Hunter** (services/worker/): Job processing bugs, queue issues, tier escalation, reconciliation errors, scraping logic, async issues, Cortex integration. Prefix: BUG/SCRP/CONC.
|
|
254
|
+
|
|
255
|
+
**Web Bug Hunter** (web/src/): React issues (keys, closures, hydration), data fetching, security (XSS), UX, build-breaking patterns, type issues. Prefix: FE.
|
|
256
|
+
|
|
257
|
+
Each reads the service diff, hunts for bugs, traces context across imports, posts findings with structured block.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Phase 4: Code Quality Review
|
|
262
|
+
|
|
263
|
+
Agent hunts for: dead code, duplicate logic, complexity (>50 line functions), naming issues, missing abstractions, logging quality, magic numbers. Prefix: QA.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Phase 5: Security & Billing Deep Dive
|
|
268
|
+
|
|
269
|
+
Read agent catalog from `.claude/commands/review-pr-agents.md`. Launch domain-specific agents based on which domains have changes. Substitute PR diff commands with staging diff commands. Agents: General Security (always), Auth, Billing, Concurrency, Scraper, API Design, Database, Infrastructure.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Phase 6: Regression Risk Assessment
|
|
274
|
+
|
|
275
|
+
Agent maps dependencies, assesses integration points (service boundaries, env vars, Docker changes, workflow sibling drift between ci.yml and deploy-production.yml), evaluates rollback difficulty (easy/hard/destructive/state-dependent), checks test coverage. Posts risk matrix with rollback plan. Prefix: REG.
|
|
276
|
+
|
|
277
|
+
**Workflow sibling drift (MANDATORY)**: Deep-diff ci.yml and deploy-production.yml shared jobs. Compare PYTHONPATH, dependency install steps, step names. Pre-existing drift is invisible until deploy fails.
|
|
278
|
+
|
|
279
|
+
**Database container restart risk (MANDATORY when `docker-compose*.yml` changes touch `postgres` or `redis` service)**: Any change to a stateful container's `command:`, `image:`, `volumes:`, or `environment:` forces container recreation on deploy. Auto-escalate to HIGH risk. Verify: `stop_grace_period` is sufficient (≥30s for PG), `full_page_writes = on`, `fsync = on`, no active long-running transactions will be interrupted. Recommend maintenance window — stateful container restarts must NOT happen as a side effect of routine deploys. A Postgres restart under active write load can corrupt btree indexes and bypass UNIQUE constraints. <!-- Added: forge#146 -->
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Phase 7: Finding Triage & Issue Creation
|
|
284
|
+
|
|
285
|
+
### 7A: Extract Findings
|
|
286
|
+
From PR comments, extract structured findings (`<!-- FINDING:... -->`). If none found, scan for unstructured findings. If still 0 → skip to Phase 8.
|
|
287
|
+
|
|
288
|
+
### 7B: Filter & Deduplicate
|
|
289
|
+
Keep ALL findings (CONFIRMED/LIKELY/POSSIBLE). Deduplicate by file:line (keep higher confidence). Sort: CONFIRMED first, then by severity.
|
|
290
|
+
|
|
291
|
+
### 7C: Ensure Labels
|
|
292
|
+
```bash
|
|
293
|
+
gh label create "review-finding" --color "D93F0B" --force 2>/dev/null
|
|
294
|
+
gh label create "needs-validation" --color "FBCA04" --force 2>/dev/null
|
|
295
|
+
gh label create "staging-review" --color "1D76DB" --force 2>/dev/null
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 7D: Milestone Detection
|
|
299
|
+
Only assign milestone if reviewing a milestone/* branch. Plain staging reviews get no milestone.
|
|
300
|
+
|
|
301
|
+
### 7E: Deduplicate Against Existing Issues
|
|
302
|
+
Check for open review-finding issues at same file:line → skip. Closed issues at same location → potential regression (elevate priority).
|
|
303
|
+
|
|
304
|
+
### 7F: Create Issues
|
|
305
|
+
Sequential creation. Title: `Staging Review: {summary} (staging → main)`. Labels: review-finding, needs-validation, staging-review, P1/P2/P3. Body includes: source branch context (`staging`), code context, evidence, validation checklist.
|
|
306
|
+
|
|
307
|
+
**No pre-filtering**: Every finding becomes an issue. Validation agents sort out false positives downstream.
|
|
308
|
+
|
|
309
|
+
### 7G: Add to Project Board
|
|
310
|
+
### 7H: Update PR Description with Findings Table
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Phase 8: Final Summary & Deployment Checklist
|
|
315
|
+
|
|
316
|
+
Post summary with verdict:
|
|
317
|
+
1. CI failed + autofix failed → BLOCK DEPLOY
|
|
318
|
+
2. CI failed + autofix succeeded → continue
|
|
319
|
+
3. CONFIRMED CRITICAL (non-CI) → BLOCK DEPLOY
|
|
320
|
+
4. CONFIRMED HIGH blocking (crashes, data loss) → NEEDS FIXES FIRST
|
|
321
|
+
5. All else → APPROVE FOR DEPLOY
|
|
322
|
+
|
|
323
|
+
Include: Material Changes Summary, Risk Matrix (CI, Build, Bugs, Security, Billing, Quality, Regression), Finding Triage Results, Blocking Issues, Deployment Checklist (pre-deploy, deploy, post-deploy verification, rollback triggers), Stats.
|
|
324
|
+
|
|
325
|
+
**CRITICAL**: This review NEVER merges staging → main. User makes deploy decision via GitHub web UI.
|