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,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show what will deploy next — diff staging vs main with issue/PR summary, risk assessment, and deploy checklist
|
|
3
|
+
argument-hint: [staging | milestone/{slug} | compare {branch}]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /deploy-info — Pre-Deploy Summary
|
|
7
|
+
|
|
8
|
+
**Input**: $ARGUMENTS (default: `staging`)
|
|
9
|
+
|
|
10
|
+
You are the pipeline's deploy awareness layer. Before the user merges staging → main (triggering CI/CD deployment), this command shows exactly what's going out: which PRs, which issues, what changed, and what risks exist.
|
|
11
|
+
|
|
12
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`.
|
|
13
|
+
|
|
14
|
+
**NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Phase 0: Review-Finding Readiness Check
|
|
19
|
+
|
|
20
|
+
**Purpose**: Surface open review-finding issues before the deploy workflow begins. Staging→main PRs that ship with open findings have a 50%+ failure rate — this check identifies the readiness gap at the earliest possible point. <!-- Added: forge#372 -->
|
|
21
|
+
|
|
22
|
+
**Non-blocking**: This phase emits a warning but does NOT block. Deploy-info is an informational tool. The authoritative gate is Phase 0A of `/review-pr-staging`.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd /home/mrdubey/projects/ScraperAPI/alterlab
|
|
26
|
+
git fetch origin main staging
|
|
27
|
+
|
|
28
|
+
SOURCE=${SOURCE_BRANCH:-staging}
|
|
29
|
+
TARGET=${TARGET_BRANCH:-main}
|
|
30
|
+
|
|
31
|
+
# Step 1: Find all PR numbers in the bundle (same logic as review-pr-staging Phase 0A)
|
|
32
|
+
BUNDLE_PRS=$(git log origin/$TARGET..origin/$SOURCE --oneline \
|
|
33
|
+
| grep -oP '#\d+' \
|
|
34
|
+
| sort -u \
|
|
35
|
+
| tr -d '#')
|
|
36
|
+
|
|
37
|
+
MERGE_PRS=$(git log origin/$TARGET..origin/$SOURCE --merges --oneline \
|
|
38
|
+
| grep -oP '(?<=pull request #)\d+' \
|
|
39
|
+
| sort -u)
|
|
40
|
+
|
|
41
|
+
ALL_PR_NUMBERS=$(echo "$BUNDLE_PRS $MERGE_PRS" | tr ' ' '\n' | sort -u | grep -E '^[0-9]+$')
|
|
42
|
+
|
|
43
|
+
if [ -z "$ALL_PR_NUMBERS" ]; then
|
|
44
|
+
echo "ℹ️ No PRs detected in bundle — skipping review-finding readiness check."
|
|
45
|
+
else
|
|
46
|
+
# Step 2: Check for open review-finding issues referencing each PR
|
|
47
|
+
OPEN_FINDINGS_SUMMARY=""
|
|
48
|
+
for pr_num in $ALL_PR_NUMBERS; do
|
|
49
|
+
OPEN_FINDINGS=$(gh issue list -R {GH_REPO} \
|
|
50
|
+
--label "review-finding" \
|
|
51
|
+
--state open \
|
|
52
|
+
--search "PR #${pr_num}" \
|
|
53
|
+
--limit 20 \
|
|
54
|
+
--json number,title \
|
|
55
|
+
--jq ".[] | \" - #\(.number): \(.title)\"" 2>/dev/null)
|
|
56
|
+
|
|
57
|
+
if [ -n "$OPEN_FINDINGS" ]; then
|
|
58
|
+
OPEN_FINDINGS_SUMMARY="${OPEN_FINDINGS_SUMMARY}
|
|
59
|
+
**PR #${pr_num}** has open review findings:
|
|
60
|
+
${OPEN_FINDINGS}"
|
|
61
|
+
fi
|
|
62
|
+
done
|
|
63
|
+
|
|
64
|
+
# Step 3: Report readiness state
|
|
65
|
+
if [ -n "$OPEN_FINDINGS_SUMMARY" ]; then
|
|
66
|
+
echo ""
|
|
67
|
+
echo "⚠️ READINESS WARNING — Open review-finding issues exist for PRs in this bundle."
|
|
68
|
+
echo ""
|
|
69
|
+
echo "$OPEN_FINDINGS_SUMMARY"
|
|
70
|
+
echo ""
|
|
71
|
+
echo "These findings will block deploy when /review-pr-staging runs (Phase 0A gate)."
|
|
72
|
+
echo "Fix the open findings and merge fixes to staging before deploying."
|
|
73
|
+
echo "Or post 'OVERRIDE: shipping with open findings — <reason>' on the staging→main PR to bypass."
|
|
74
|
+
echo ""
|
|
75
|
+
echo "READINESS: NOT READY — open findings present"
|
|
76
|
+
else
|
|
77
|
+
echo "✅ Review-finding readiness: READY — no open findings for PRs in this bundle."
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Phase 1: Resolve What to Compare
|
|
85
|
+
|
|
86
|
+
| Input | Source Branch | Target Branch | Scenario |
|
|
87
|
+
|-------|--------------|---------------|----------|
|
|
88
|
+
| `staging` or empty | `staging` | `main` | Normal fast-lane deploy |
|
|
89
|
+
| `milestone/{slug}` | `milestone/{slug}` | `staging` | Ship milestone to staging |
|
|
90
|
+
| `compare {branch}` | `{branch}` | `main` | Custom comparison |
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cd /home/mrdubey/projects/ScraperAPI/alterlab
|
|
94
|
+
git fetch origin main staging
|
|
95
|
+
|
|
96
|
+
# Determine source and target
|
|
97
|
+
SOURCE=${SOURCE_BRANCH:-staging}
|
|
98
|
+
TARGET=${TARGET_BRANCH:-main}
|
|
99
|
+
|
|
100
|
+
# Check if there are any differences
|
|
101
|
+
AHEAD=$(git rev-list --count origin/$TARGET..origin/$SOURCE)
|
|
102
|
+
if [ "$AHEAD" -eq 0 ]; then
|
|
103
|
+
echo "✅ $SOURCE is up to date with $TARGET — nothing to deploy."
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
echo "$AHEAD commits ahead"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Phase 2: Gather Deploy Payload
|
|
112
|
+
|
|
113
|
+
### Step 2A: Commit log
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# All commits that will deploy
|
|
117
|
+
git log --oneline origin/$TARGET..origin/$SOURCE --format="%h %s" | head -50
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Step 2B: PRs included
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Extract PR numbers from merge commits
|
|
124
|
+
PR_NUMBERS=$(git log origin/$TARGET..origin/$SOURCE --merges --format="%s" | grep -oP '#\d+' | sort -u)
|
|
125
|
+
|
|
126
|
+
# Get PR details
|
|
127
|
+
for PR in $PR_NUMBERS; do
|
|
128
|
+
NUM=${PR#\#}
|
|
129
|
+
gh pr view $NUM --json number,title,author,labels,mergedAt --jq '"\(.number) | \(.title) | \(.author.login) | \([.labels[].name] | join(","))"' 2>/dev/null
|
|
130
|
+
done
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Step 2C: Issues being closed
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Extract issue references from PR bodies
|
|
137
|
+
for PR in $PR_NUMBERS; do
|
|
138
|
+
NUM=${PR#\#}
|
|
139
|
+
CLOSES=$(gh pr view $NUM --json body --jq '.body' 2>/dev/null | grep -oP 'Closes #\K\d+')
|
|
140
|
+
for ISSUE in $CLOSES; do
|
|
141
|
+
gh issue view $ISSUE --json number,title,labels --jq '"\(.number) | \(.title) | \([.labels[].name] | join(","))"' 2>/dev/null
|
|
142
|
+
done
|
|
143
|
+
done
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Step 2D: Files changed
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Full file diff summary
|
|
150
|
+
git diff --stat origin/$TARGET..origin/$SOURCE
|
|
151
|
+
|
|
152
|
+
# Categorize by service
|
|
153
|
+
echo "=== By Service ==="
|
|
154
|
+
git diff --name-only origin/$TARGET..origin/$SOURCE | sort | while read f; do
|
|
155
|
+
case "$f" in
|
|
156
|
+
services/api/*) echo "API: $f" ;;
|
|
157
|
+
services/worker/*) echo "WORKER: $f" ;;
|
|
158
|
+
web/*) echo "WEB: $f" ;;
|
|
159
|
+
shared/*) echo "SHARED: $f" ;;
|
|
160
|
+
infra/*) echo "INFRA: $f" ;;
|
|
161
|
+
*) echo "OTHER: $f" ;;
|
|
162
|
+
esac
|
|
163
|
+
done | sort
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Step 2E: Migration check
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# Are there new migrations?
|
|
170
|
+
MIGRATIONS=$(git diff --name-only origin/$TARGET..origin/$SOURCE | grep "^infra/migrations/" | sort)
|
|
171
|
+
if [ -n "$MIGRATIONS" ]; then
|
|
172
|
+
echo "⚠️ DATABASE MIGRATIONS INCLUDED:"
|
|
173
|
+
echo "$MIGRATIONS"
|
|
174
|
+
# Show migration content for review
|
|
175
|
+
for m in $MIGRATIONS; do
|
|
176
|
+
echo "--- $m ---"
|
|
177
|
+
git show origin/$SOURCE:$m 2>/dev/null | head -30
|
|
178
|
+
done
|
|
179
|
+
fi
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Phase 3: Risk Assessment
|
|
185
|
+
|
|
186
|
+
Analyze the deploy payload and flag risks:
|
|
187
|
+
|
|
188
|
+
### Risk Signals
|
|
189
|
+
|
|
190
|
+
| Signal | Risk Level | Action |
|
|
191
|
+
|--------|-----------|--------|
|
|
192
|
+
| Database migrations present | MEDIUM | Verify migrations are reversible |
|
|
193
|
+
| `shared/` changes | LOW | Restart-only deploy possible (no rebuild) |
|
|
194
|
+
| `.env.example` changes | HIGH | Verify SOPS + decrypt-secrets has new vars |
|
|
195
|
+
| `docker-compose.prod.yml` changes | HIGH | Review infrastructure changes carefully |
|
|
196
|
+
| `infra/traefik/` changes | HIGH | Routing changes — test before full deploy |
|
|
197
|
+
| 10+ PRs in one deploy | MEDIUM | Consider deploying in smaller batches |
|
|
198
|
+
| P0 fixes included | LOW | Good — these should deploy ASAP |
|
|
199
|
+
| New endpoints added | MEDIUM | Verify auth model and proxy wiring |
|
|
200
|
+
|
|
201
|
+
### Automated Checks
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Check for new env vars that might not be in SOPS
|
|
205
|
+
NEW_ENV=$(git diff origin/$TARGET..origin/$SOURCE -- '.env.example' | grep "^+" | grep -v "^+++" | grep -v "^#")
|
|
206
|
+
if [ -n "$NEW_ENV" ]; then
|
|
207
|
+
echo "⚠️ NEW ENVIRONMENT VARIABLES — verify they exist in SOPS:"
|
|
208
|
+
echo "$NEW_ENV"
|
|
209
|
+
# Cross-check with decrypt-secrets.sh
|
|
210
|
+
for var in $(echo "$NEW_ENV" | grep -oP '^\+\K[A-Z_]+'); do
|
|
211
|
+
if ! grep -q "$var" scripts/decrypt-secrets.sh 2>/dev/null; then
|
|
212
|
+
echo " ❌ $var NOT in decrypt-secrets.sh ENV_MAPPING"
|
|
213
|
+
fi
|
|
214
|
+
done
|
|
215
|
+
fi
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Phase 4: Deploy Checklist
|
|
221
|
+
|
|
222
|
+
Generate a checklist based on what's in the deploy:
|
|
223
|
+
|
|
224
|
+
```markdown
|
|
225
|
+
## Deploy Checklist
|
|
226
|
+
|
|
227
|
+
### Pre-Deploy
|
|
228
|
+
- [ ] All PRs in this deploy have been reviewed
|
|
229
|
+
- [ ] No open `needs-human` issues blocking deploy
|
|
230
|
+
- [ ] {If migrations} Database backup verified
|
|
231
|
+
- [ ] {If new env vars} SOPS secrets updated and decrypt-secrets.sh has mapping
|
|
232
|
+
- [ ] {If traefik changes} Routing tested locally
|
|
233
|
+
|
|
234
|
+
### Deploy Command
|
|
235
|
+
```
|
|
236
|
+
# Standard deploy (merge staging → main via GitHub web UI)
|
|
237
|
+
# CI/CD auto-triggers on push to main
|
|
238
|
+
|
|
239
|
+
# Or manual trigger for specific services:
|
|
240
|
+
gh workflow run hotfix-deploy.yml --ref main -f services={affected_services} -f reason="Deploy: {summary}"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Post-Deploy
|
|
244
|
+
- [ ] Health check: `curl -s https://alterlab.io/api/health | jq .`
|
|
245
|
+
- [ ] {If migrations} Verify migration applied: check new tables/columns exist
|
|
246
|
+
- [ ] {If new features} Smoke test the new functionality
|
|
247
|
+
- [ ] Monitor error rates for 15 minutes
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Phase 5: Output Summary
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
## Deploy Summary: {SOURCE} → {TARGET}
|
|
256
|
+
|
|
257
|
+
**Commits**: {N} | **PRs**: {N} | **Issues closed**: {N} | **Files changed**: {N}
|
|
258
|
+
|
|
259
|
+
### Services Affected
|
|
260
|
+
| Service | Files Changed | Rebuild Required |
|
|
261
|
+
|---------|---------------|-----------------|
|
|
262
|
+
| API | {N} | Yes |
|
|
263
|
+
| Worker | {N} | Yes |
|
|
264
|
+
| Web | {N} | Yes |
|
|
265
|
+
| Shared | {N} | No (restart only) |
|
|
266
|
+
| Infra | {N} | N/A |
|
|
267
|
+
|
|
268
|
+
### PRs Included
|
|
269
|
+
| # | Title | Author | Labels |
|
|
270
|
+
|---|-------|--------|--------|
|
|
271
|
+
{table of PRs}
|
|
272
|
+
|
|
273
|
+
### Issues Being Resolved
|
|
274
|
+
| # | Title | Priority |
|
|
275
|
+
|---|-------|----------|
|
|
276
|
+
{table of issues}
|
|
277
|
+
|
|
278
|
+
### Risk Assessment
|
|
279
|
+
- **Overall risk**: {LOW / MEDIUM / HIGH}
|
|
280
|
+
- **Flags**: {list of risk signals triggered}
|
|
281
|
+
|
|
282
|
+
### Migrations
|
|
283
|
+
{migration details or "None"}
|
|
284
|
+
|
|
285
|
+
### New Environment Variables
|
|
286
|
+
{new vars or "None"}
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
**Ready to deploy?** Merge staging → main via GitHub web UI, or run:
|
|
291
|
+
`gh workflow run hotfix-deploy.yml --ref staging -f services={services} -f reason="Batch deploy"`
|
|
292
|
+
```
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Weekly failure recon — pull prod failures, test at each tier, create tier-hardening issues
|
|
3
|
+
argument-hint: [full | pull | test | report | issues-only]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /failure-recon — Weekly Scraper Tier Hardening Pipeline
|
|
7
|
+
|
|
8
|
+
**Input**: $ARGUMENTS (default: `full`)
|
|
9
|
+
|
|
10
|
+
You are AlterLab's scraper intelligence system. Your mission: **improve the platform's scraping capabilities holistically** — tiers, detection, content extraction, and the intelligence feedback loop that ties it all together.
|
|
11
|
+
|
|
12
|
+
**The scraping ecosystem is a closed loop:**
|
|
13
|
+
```
|
|
14
|
+
BlackBox Recorder → TrafficAnalyzer → Learnings → LearningApplier → playbook:active:{domain}
|
|
15
|
+
↓
|
|
16
|
+
Tier Feedback (cortex:domain:stats) → get_optimal_starting_tier() → Smarter tier selection
|
|
17
|
+
↓
|
|
18
|
+
Challenge Detection → notify_scrape_complete() → Cortex Queue → Agents (CodeFix, AntiBot, etc.)
|
|
19
|
+
↓
|
|
20
|
+
scrape_diagnostics / domain_analytics → This command (failure-recon) → Issues → /work-on → Improvement
|
|
21
|
+
```
|
|
22
|
+
Every fix to ANY part of this loop compounds — better detection feeds better tier intelligence, which reduces wasted escalations, which captures better traffic data in BlackBox, which generates better learnings.
|
|
23
|
+
|
|
24
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`. Pass the resolved model in every `Agent`/`Task` call. Each agent prompt specifies the exact tier to test, the Docker endpoint to hit, and the expected output format.
|
|
25
|
+
|
|
26
|
+
**Core principles:**
|
|
27
|
+
1. **Solve at the lowest tier.** Every URL should work at the cheapest, fastest tier possible.
|
|
28
|
+
2. **Platform improvements, not domain fixes.** Cortex + BlackBox Recorder handle per-domain learning automatically. This command improves the PLATFORM — the tiers, detection providers, content extraction, feedback loop, and intelligence pipeline.
|
|
29
|
+
3. **No domain-specific fixes.** NEVER create issues like "fix scraping for zillow.com" or "add playbook for X." Instead: "Tier 3 stealth headers don't spoof sec-fetch-* correctly" (evidenced by failures across 6 domains). Production URLs are EVIDENCE, not the target.
|
|
30
|
+
4. **Leverage the full ecosystem.** Issues should consider:
|
|
31
|
+
- Could BlackBox Recorder capture more useful data to feed this improvement?
|
|
32
|
+
- Could TrafficAnalyzer learn this pattern automatically with better signals?
|
|
33
|
+
- Could the tier feedback loop (`cortex:domain:stats`) make smarter decisions here?
|
|
34
|
+
- Could the LearningApplier auto-apply this fix with the right confidence threshold?
|
|
35
|
+
- Could the challenge detection providers (`shared/detection/providers/`) detect this pattern?
|
|
36
|
+
- Could `detected_antibot` in `scrape_diagnostics` inform future tier selection?
|
|
37
|
+
5. **No regressions.** Every fix must preserve what already works. Check previous fixes.
|
|
38
|
+
6. **GitHub is the memory.** Every issue links to prior work. Any agent picking this up later has full context.
|
|
39
|
+
7. **No defeatism.** "Unsolvable" means "needs a new technique," not "can't be done."
|
|
40
|
+
|
|
41
|
+
**Good issues from this command:**
|
|
42
|
+
- "Tier 2 TLS fingerprint provides 0% incremental bypass — rethink what capability T2 adds" (tier capability)
|
|
43
|
+
- "Browser tier crashes instead of extracting partial content — graceful degradation needed" (resilience)
|
|
44
|
+
- "CSR shell detection doesn't trigger hydration-aware waiting at T4" (content extraction)
|
|
45
|
+
- "detected_antibot never populated — breaking the diagnostics→intelligence feedback loop" (ecosystem plumbing)
|
|
46
|
+
- "Tier feedback loop doesn't account for challenge type — sites with Cloudflare should skip T1-T3" (intelligence)
|
|
47
|
+
- "BlackBox Recorder only captures T4 traffic — T2/T3 failures have no data for TrafficAnalyzer" (data collection gap)
|
|
48
|
+
|
|
49
|
+
**NOT acceptable:**
|
|
50
|
+
- "Fix scraping for zillow.com" (domain-specific — Cortex handles this)
|
|
51
|
+
- "Add playbook for easydrop.one" (domain-specific — CodeFixAgent handles this)
|
|
52
|
+
- "alternativeto.net needs X" (domain-specific — tier feedback loop handles this)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Phase 1: Pull & Normalize Production Failures
|
|
57
|
+
|
|
58
|
+
First, verify local containers are up:
|
|
59
|
+
```bash
|
|
60
|
+
cd /home/mrdubey/projects/ScraperAPI/alterlab
|
|
61
|
+
docker compose ps --format "{{.Name}} {{.Status}}" | grep -E "api|worker|redis|postgres"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If containers aren't running, tell the user and offer to start them.
|
|
65
|
+
|
|
66
|
+
Then run the recon script:
|
|
67
|
+
```bash
|
|
68
|
+
cd /home/mrdubey/projects/ScraperAPI
|
|
69
|
+
|
|
70
|
+
# Full pipeline: pull → normalize → tier-by-tier test → report
|
|
71
|
+
python3 tools/failure-recon/recon.py full --days 7 --sample-size 10 --max-total 200 --concurrency 3
|
|
72
|
+
|
|
73
|
+
# Or specific phases:
|
|
74
|
+
# python3 tools/failure-recon/recon.py pull --days 7 # Pull only (no testing)
|
|
75
|
+
# python3 tools/failure-recon/recon.py test # Re-test existing sample
|
|
76
|
+
# python3 tools/failure-recon/recon.py report # Re-read latest report
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If `$ARGUMENTS` is `issues-only`, skip directly to Phase 3 (read existing report, create issues).
|
|
80
|
+
|
|
81
|
+
**This takes 30-90 minutes** depending on sample size. The script tests each URL at Tier 1, then 2, then 3, then 4 — stopping at the first tier that returns useful content. This is how we find where each tier's boundary is.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Phase 2: Analyze the Report
|
|
86
|
+
|
|
87
|
+
Read the latest report:
|
|
88
|
+
```bash
|
|
89
|
+
ls -t /home/mrdubey/projects/ScraperAPI/tools/failure-recon/reports/recon_*.json | head -1
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Read the JSON. Key sections:
|
|
93
|
+
|
|
94
|
+
### 2A: Tier Pass Rates (`tier_pass_rates`)
|
|
95
|
+
|
|
96
|
+
This is the **scoreboard**. For each tier, what percentage of failed-in-prod URLs can it handle?
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Tier 1 (curl) : ██░░░░░░░░░░░░░░░░░░ 12/200 (6%)
|
|
100
|
+
Tier 2 (http) : █████░░░░░░░░░░░░░░░ 45/200 (22.5%)
|
|
101
|
+
Tier 3 (stealth) : ████████████░░░░░░░░ 110/200 (55%)
|
|
102
|
+
Tier 4 (browser) : ████████████████░░░░ 160/200 (80%)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The GAP between tiers is the hardening opportunity. If Tier 3 solves 55% but Tier 4 solves 80%, there are 50 URLs where Tier 3 ALMOST works — those are Tier 3 hardening candidates.
|
|
106
|
+
|
|
107
|
+
### 2B: Tier Hardening Findings (`tier_findings`)
|
|
108
|
+
|
|
109
|
+
Each finding says: "N URLs fail at Tier X but pass at Tier Y — here's what Tier X needs."
|
|
110
|
+
|
|
111
|
+
**Analyze the root cause for each finding:**
|
|
112
|
+
|
|
113
|
+
1. **What's the detection vector?** Read the errors and protection type.
|
|
114
|
+
- `blocked_403` + Cloudflare → TLS fingerprint or header mismatch at this tier
|
|
115
|
+
- `timeout` + DataDome → Solver not triggering or too slow
|
|
116
|
+
- `empty_response` → Content extraction failing, not necessarily blocked
|
|
117
|
+
- `soft_block` → Page loads but returns challenge HTML instead of content
|
|
118
|
+
|
|
119
|
+
2. **What does the passing tier do differently?** Compare tier capabilities:
|
|
120
|
+
- Tier 1→2: Chrome TLS fingerprint. If URLs pass at T2 but not T1, the site checks TLS.
|
|
121
|
+
- Tier 2→3: Proxy + stealth headers. If URLs pass at T3 but not T2, the site checks IP reputation or specific headers.
|
|
122
|
+
- Tier 3→4: Full browser JS. If URLs pass at T4 but not T3, the site requires JS execution — but CAN we do lighter JS at T3?
|
|
123
|
+
|
|
124
|
+
3. **What specific code change would make the lower tier work?**
|
|
125
|
+
- Better headers at Tier 1/2 (`services/worker/worker/consumers/unified_consumer.py`)
|
|
126
|
+
- Better fingerprinting at Tier 2 (`services/worker/worker/anti_detection/`)
|
|
127
|
+
- Better proxy selection at Tier 3 (proxy pool, country selection)
|
|
128
|
+
- Better challenge detection at Tier 4 (`services/worker/worker/browser/challenge_detector.py`, solvers)
|
|
129
|
+
|
|
130
|
+
### 2C: Unsolvable URLs
|
|
131
|
+
|
|
132
|
+
URLs failing at ALL tiers need new techniques. Analyze:
|
|
133
|
+
- Is the protection system one we have a solver for? (Check `shared/detection/providers/`)
|
|
134
|
+
- Is the solver being triggered? (Check `challenge_detector.py` patterns)
|
|
135
|
+
- Is it a new protection variant we haven't seen?
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Phase 3: Research Prior Work (CRITICAL)
|
|
140
|
+
|
|
141
|
+
**Before creating ANY issue**, search GitHub for prior work in the same area. This is the context layer.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Search for existing open scraper issues
|
|
145
|
+
gh issue list --state open --label "scraper" --limit 50 --json number,title
|
|
146
|
+
|
|
147
|
+
# Search for closed issues about the same protection type
|
|
148
|
+
gh issue list --state closed --label "scraper" --search "{protection_type}" --limit 20 --json number,title,closedAt
|
|
149
|
+
|
|
150
|
+
# Search for related PRs
|
|
151
|
+
gh pr list --state merged --search "tier hardening {protection}" --limit 10 --json number,title,mergedAt
|
|
152
|
+
|
|
153
|
+
# Check recent scraper-related commits
|
|
154
|
+
cd /home/mrdubey/projects/ScraperAPI/alterlab
|
|
155
|
+
git log --oneline --all --grep="tier" --grep="hardening" --since="3 months ago" | head -20
|
|
156
|
+
git log --oneline --all --grep="{protection_type}" --since="3 months ago" | head -20
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**For each finding, gather:**
|
|
160
|
+
1. Related closed issues (what was tried before?)
|
|
161
|
+
2. Related merged PRs (what code was changed?)
|
|
162
|
+
3. Any open issues that overlap (don't duplicate!)
|
|
163
|
+
|
|
164
|
+
If an open issue already covers this finding, **comment on it** with the new test data instead of creating a duplicate.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Phase 4: Create Platform Improvement Issues
|
|
169
|
+
|
|
170
|
+
**CRITICAL: Issues must describe PLATFORM-LEVEL capabilities to improve, not domain-specific fixes.**
|
|
171
|
+
|
|
172
|
+
Use production data as EVIDENCE (e.g., "observed on 6 domains including zillow.com and coles.com.au"), but the fix must be a general improvement (e.g., "add pre-timeout content extraction fallback to browser tier").
|
|
173
|
+
|
|
174
|
+
Issue categories to create:
|
|
175
|
+
|
|
176
|
+
### A. Tier Capability Gaps
|
|
177
|
+
When a tier has low incremental pass rate over the tier below it. The issue should propose specific anti-detection or protocol improvements to that tier.
|
|
178
|
+
|
|
179
|
+
Title pattern: `"Tier {N} ({name}): {capability problem} — {%} incremental pass rate"`
|
|
180
|
+
|
|
181
|
+
### B. Resilience / Graceful Degradation
|
|
182
|
+
When a tier fails catastrophically (crash, timeout with zero output) instead of returning partial results. The issue should propose fallback behaviors.
|
|
183
|
+
|
|
184
|
+
Title pattern: `"Tier {N}: {failure mode} should {graceful behavior} instead"`
|
|
185
|
+
|
|
186
|
+
### C. Content Extraction Pipeline
|
|
187
|
+
When content exists but isn't extracted properly (CSR shells, shadow DOM, iframes, lazy-loaded content). These are cross-tier issues.
|
|
188
|
+
|
|
189
|
+
Title pattern: `"{extraction problem} — affects {N} URLs across {M} domains"`
|
|
190
|
+
|
|
191
|
+
### D. Detection / Intelligence Pipeline
|
|
192
|
+
When the platform lacks data to make good decisions (e.g., `detected_antibot` not populated, tier intelligence over-escalating). These improve the feedback loop.
|
|
193
|
+
|
|
194
|
+
Title pattern: `"{data/intelligence problem} — blocking {downstream capability}"`
|
|
195
|
+
|
|
196
|
+
### Issue Body Structure
|
|
197
|
+
|
|
198
|
+
Every issue MUST include:
|
|
199
|
+
1. **Platform capability being improved** — what general capability is this? (fingerprinting, content extraction, wait strategy, etc.)
|
|
200
|
+
2. **Evidence from production** — URLs/domains as evidence, NOT as the fix target
|
|
201
|
+
3. **Prior work** — linked issues and PRs
|
|
202
|
+
4. **Investigation path** — code paths to examine, not "fix domain X"
|
|
203
|
+
5. **Validation plan** — how to verify the improvement works across the board, not just for one site
|
|
204
|
+
6. **Regression guard** — URLs that currently pass and must continue to
|
|
205
|
+
|
|
206
|
+
**NEVER frame an issue as "fix scraping for X.com" — always as "improve {capability} (evidenced by failures on X.com, Y.com, Z.com)"**
|
|
207
|
+
- **Prod impact**: {total_failures} failures/week from this protection type
|
|
208
|
+
EOF
|
|
209
|
+
)"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Issue Template: Unsolvable URLs (New Technique Needed)
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
gh issue create --title "feat(scraper): add {Protection} bypass technique — {count} URLs unsolvable at all tiers" --label "feature,P1,scraper" --body "$(cat <<'EOF'
|
|
216
|
+
## Problem
|
|
217
|
+
|
|
218
|
+
{count} URLs fail at ALL tiers (1-4) against {Protection} protection. The platform has no working bypass for this protection type or variant.
|
|
219
|
+
|
|
220
|
+
## Root Cause (if known)
|
|
221
|
+
|
|
222
|
+
{Analysis}: Our current solver either doesn't exist for this protection type, exists but doesn't trigger for this pattern, or triggers but can't complete the challenge.
|
|
223
|
+
- `shared/detection/providers/{protection}.py`: {does it detect correctly?}
|
|
224
|
+
- `challenge_detector.py`: {what happens when detected?}
|
|
225
|
+
|
|
226
|
+
## Affected Files
|
|
227
|
+
|
|
228
|
+
Files that need changes:
|
|
229
|
+
1. `services/worker/worker/browser/challenge_detector.py` — {what detection changes are needed}
|
|
230
|
+
2. `shared/detection/providers/{protection}.py` — {solver/detection updates}
|
|
231
|
+
3. `{other files}` — {what needs to change}
|
|
232
|
+
|
|
233
|
+
## Acceptance Criteria
|
|
234
|
+
|
|
235
|
+
- [ ] {Protection} protection detected correctly by challenge_detector.py
|
|
236
|
+
- [ ] Solver triggers and completes challenge for the failing URL pattern
|
|
237
|
+
- [ ] Regression guard: {N} currently-passing URLs continue to pass
|
|
238
|
+
- [ ] Verified in next failure-recon run
|
|
239
|
+
|
|
240
|
+
## Context
|
|
241
|
+
|
|
242
|
+
### Failing URLs
|
|
243
|
+
{table: URL | Domain | T4 Error | T4 Status Code}
|
|
244
|
+
|
|
245
|
+
### Error Pattern
|
|
246
|
+
{Common errors at Tier 4 — the highest tier we tried}
|
|
247
|
+
|
|
248
|
+
### Prior Work
|
|
249
|
+
{Related issues and PRs}
|
|
250
|
+
|
|
251
|
+
### Investigation Path
|
|
252
|
+
1. [ ] Run one URL manually in Playwright to observe the challenge
|
|
253
|
+
2. [ ] Check if detection provider identifies the protection correctly
|
|
254
|
+
3. [ ] Check if solver is triggered (add logging if needed)
|
|
255
|
+
4. [ ] Identify what the challenge requires (fingerprint, behavioral, CAPTCHA, etc.)
|
|
256
|
+
5. [ ] Prototype solver or enhance existing one
|
|
257
|
+
6. [ ] Test with URLs from this issue
|
|
258
|
+
EOF
|
|
259
|
+
)"
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Issue Template: Tier Intelligence (Over-Escalation)
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
gh issue create --title "refactor(scraper): tier intelligence over-escalation — {count} URLs use Tier {high} but solvable at Tier {low}" --label "refactor,P2,scraper" --body "$(cat <<'EOF'
|
|
266
|
+
## Problem
|
|
267
|
+
|
|
268
|
+
{count} URLs used Tier {high} in production but are solvable at Tier {low} locally. The tier escalation logic or Cortex tier prediction is overshooting by 2+ tiers, wasting browser resources unnecessarily.
|
|
269
|
+
|
|
270
|
+
## Root Cause (if known)
|
|
271
|
+
|
|
272
|
+
{Analysis — is Cortex over-recommending? Is the escalation too aggressive? Are there stale tier recommendations in Redis?}
|
|
273
|
+
|
|
274
|
+
## Affected Files
|
|
275
|
+
|
|
276
|
+
Files that need changes:
|
|
277
|
+
1. `{cortex/tier-selection file}` — {what needs to change in escalation logic}
|
|
278
|
+
2. `{Redis tier cache file}` — {stale recommendation handling if applicable}
|
|
279
|
+
|
|
280
|
+
## Acceptance Criteria
|
|
281
|
+
|
|
282
|
+
- [ ] Tier escalation for {protection type} reduced by {N} tiers on average
|
|
283
|
+
- [ ] No regression: URLs that genuinely need higher tiers still escalate correctly
|
|
284
|
+
- [ ] Verified in next failure-recon run
|
|
285
|
+
|
|
286
|
+
## Context
|
|
287
|
+
|
|
288
|
+
### Examples
|
|
289
|
+
| URL | Prod Tier | Actual Min Tier | Tiers Saved |
|
|
290
|
+
|-----|-----------|-----------------|-------------|
|
|
291
|
+
{table rows}
|
|
292
|
+
|
|
293
|
+
### Prior Work
|
|
294
|
+
{Related issues}
|
|
295
|
+
EOF
|
|
296
|
+
)"
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Phase 5: Link Everything Together
|
|
302
|
+
|
|
303
|
+
After creating issues, ensure the context web is connected:
|
|
304
|
+
|
|
305
|
+
1. **Cross-reference new issues** — if Issue A (Tier 2 Cloudflare) and Issue B (Tier 3 Cloudflare) are related, comment on each linking to the other.
|
|
306
|
+
|
|
307
|
+
2. **Reference the recon report** — include the report timestamp in each issue so agents know which data to look at:
|
|
308
|
+
```
|
|
309
|
+
> Data from failure-recon run {timestamp}. Report: `tools/failure-recon/reports/recon_{timestamp}.json`
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
3. **Label consistently**: All issues get `scraper` label. Tier hardening gets `bug`. New techniques get `feature`.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Phase 6: Summary
|
|
317
|
+
|
|
318
|
+
Print the final summary:
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
## Failure Recon — Tier Hardening Report ({date})
|
|
322
|
+
|
|
323
|
+
### Production Snapshot (Last 7 Days)
|
|
324
|
+
- Total failures: {N} | Unique URLs: {N} | Domains: {N}
|
|
325
|
+
|
|
326
|
+
### Tier Scoreboard
|
|
327
|
+
| Tier | Name | Passing | Rate | Hardening Opportunity |
|
|
328
|
+
|------|------|---------|------|----------------------|
|
|
329
|
+
| 1 | curl | {n}/{total} | {%} | {gap to next tier} URLs |
|
|
330
|
+
| 2 | http | {n}/{total} | {%} | {gap} URLs |
|
|
331
|
+
| 3 | stealth | {n}/{total} | {%} | {gap} URLs |
|
|
332
|
+
| 4 | browser | {n}/{total} | {%} | — |
|
|
333
|
+
| ALL | combined | {n}/{total} | {%} | {unsolvable} unsolvable |
|
|
334
|
+
|
|
335
|
+
### Issues Created
|
|
336
|
+
| # | Title | Priority | Tier | Protection | Hardening Target |
|
|
337
|
+
|---|-------|----------|------|------------|-----------------|
|
|
338
|
+
{table}
|
|
339
|
+
|
|
340
|
+
### Issues Updated (prior work found)
|
|
341
|
+
| # | Title | New Data Added |
|
|
342
|
+
|---|-------|---------------|
|
|
343
|
+
{table of existing issues that got new comments}
|
|
344
|
+
|
|
345
|
+
### Regression Watch
|
|
346
|
+
{N} URLs currently passing — these MUST be preserved. Any /work-on agent picking up
|
|
347
|
+
a tier-hardening issue should verify these still pass before merging.
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Modes Reference
|
|
353
|
+
|
|
354
|
+
| Argument | What It Does | Duration | When |
|
|
355
|
+
|----------|-------------|----------|------|
|
|
356
|
+
| `full` (default) | Pull → Test all tiers → Report → Issues | 30-90 min | Weekly ritual |
|
|
357
|
+
| `pull` | Pull + normalize only | 2 min | Quick status check |
|
|
358
|
+
| `test` | Re-test existing sample | 20-60 min | After deploying fixes |
|
|
359
|
+
| `report` | Re-read latest report | Instant | Review without re-pulling |
|
|
360
|
+
| `issues-only` | Read report → Create issues | 5 min | Create issues from reviewed report |
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Philosophy
|
|
365
|
+
|
|
366
|
+
AlterLab doesn't accept failure. Every bot protection is a puzzle — Cloudflare, DataDome, Akamai, Kasada, all of them. The question isn't "can we bypass this?" — it's "which tier should bypass this?"
|
|
367
|
+
|
|
368
|
+
**Tier 1 should handle everything that doesn't check fingerprints.**
|
|
369
|
+
**Tier 2 should handle everything that checks TLS but not IP.**
|
|
370
|
+
**Tier 3 should handle everything that checks IP but not JS.**
|
|
371
|
+
**Tier 4 should handle everything.**
|
|
372
|
+
|
|
373
|
+
When a URL fails at Tier 4, that's not a limitation — that's a solver bug or a new pattern to learn.
|
|
374
|
+
|
|
375
|
+
This command runs weekly. Each run should produce measurable tier improvements. Compare this week's scoreboard to last week's — the numbers should go UP, never down.
|