forgedock 1.1.1 → 1.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.
- package/README.md +53 -8
- package/bin/batch-runner.mjs +339 -0
- package/bin/demo.mjs +92 -7
- package/bin/engine/phases.mjs +20 -0
- package/bin/engine/state.mjs +8 -3
- package/bin/engine-cli.mjs +177 -5
- package/bin/forgedock.mjs +409 -26
- package/bin/hooks/interactive-engine.mjs +509 -0
- package/bin/hooks/pre-tool-use.mjs +498 -0
- package/bin/hooks/subagent-stop-enforce.mjs +197 -0
- package/bin/journey.mjs +72 -14
- package/bin/registry.mjs +139 -0
- package/bin/report.mjs +447 -0
- package/bin/runner.mjs +68 -19
- package/bin/settings-hook.mjs +235 -1
- package/commands/adopt.md +4 -1
- package/commands/analytics.md +4 -1
- package/commands/audit-agents.md +110 -27
- package/commands/audit.md +20 -1
- package/commands/autopilot.md +80 -8
- package/commands/changelog.md +2 -1
- package/commands/ci-audit.md +2 -1
- package/commands/cleanup.md +161 -1
- package/commands/compat-audit.md +2 -1
- package/commands/deploy-info.md +58 -1
- package/commands/design-bench.md +5 -1
- package/commands/design-render-critique-loop.md +1 -1
- package/commands/diagnose.md +2 -1
- package/commands/explain.md +2 -1
- package/commands/forge-stats.md +121 -2
- package/commands/forgedock-init.md +1 -1
- package/commands/geo-audit.md +3 -0
- package/commands/incident-response.md +2 -1
- package/commands/issue.md +23 -2
- package/commands/milestone.md +77 -12
- package/commands/optimize.md +2 -1
- package/commands/orchestrate/config.md +67 -0
- package/commands/orchestrate/phase-1-resolve.md +159 -0
- package/commands/orchestrate/phase-2-triage.md +126 -0
- package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
- package/commands/orchestrate/phase-3-dependency.md +591 -0
- package/commands/orchestrate/phase-4-execution.md +962 -0
- package/commands/orchestrate/phase-5-cleanup.md +47 -0
- package/commands/orchestrate/phase-6-report.md +198 -0
- package/commands/orchestrate/safety.md +62 -0
- package/commands/orchestrate.md +25 -2045
- package/commands/pipeline-health/config.md +34 -0
- package/commands/pipeline-health/phase-1-context.md +180 -0
- package/commands/pipeline-health/phase-2-metrics.md +1729 -0
- package/commands/pipeline-health/phase-3-analyze.md +204 -0
- package/commands/pipeline-health/phase-4-proposals.md +117 -0
- package/commands/pipeline-health/phase-5-report.md +284 -0
- package/commands/pipeline-health/phase-6-summary.md +52 -0
- package/commands/pipeline-health.md +25 -2401
- package/commands/pipeline-resume.md +24 -1
- package/commands/pipeline-status.md +65 -0
- package/commands/qa-sweep.md +4 -1
- package/commands/quality-gate.md +248 -10
- package/commands/replay.md +2 -1
- package/commands/review-pr-agents/api.md +135 -0
- package/commands/review-pr-agents/auth.md +137 -0
- package/commands/review-pr-agents/billing.md +101 -0
- package/commands/review-pr-agents/concurrency.md +145 -0
- package/commands/review-pr-agents/database.md +103 -0
- package/commands/review-pr-agents/frontend.md +89 -0
- package/commands/review-pr-agents/infra.md +385 -0
- package/commands/review-pr-agents/protocols.md +185 -0
- package/commands/review-pr-agents/scraper.md +185 -0
- package/commands/review-pr-agents/security.md +406 -0
- package/commands/review-pr-agents.md +45 -1722
- package/commands/review-pr-staging.md +196 -40
- package/commands/review-pr.md +591 -52
- package/commands/rollback.md +2 -1
- package/commands/scope.md +2 -1
- package/commands/security-audit.md +2 -1
- package/commands/signal-planner.md +623 -0
- package/commands/sync-ecosystem.md +1 -0
- package/commands/test-gate.md +17 -1
- package/commands/validate.md +2 -1
- package/commands/work-on/build/architect.md +28 -0
- package/commands/work-on/build/context.md +2 -0
- package/commands/work-on/build/implement.md +3 -1
- package/commands/work-on/build/validate.md +26 -7
- package/commands/work-on/build.md +163 -24
- package/commands/work-on/close.md +130 -3
- package/commands/work-on/decompose.md +19 -1
- package/commands/work-on/investigate.md +117 -2
- package/commands/work-on/review.md +24 -4
- package/commands/work-on-monolithic.md +7 -2
- package/commands/work-on.md +202 -4
- package/docs/BRAND.md +14 -7
- package/docs/CI.md +2 -2
- package/docs/CODEX.md +36 -1
- package/docs/CONFIG.md +5 -8
- package/docs/FORGE-PROTOCOL.md +15 -1064
- package/docs/anthropic-devrel-outreach.md +2 -2
- package/docs/articles/command-decomposition-token-savings.md +214 -0
- package/docs/articles/model-release-playbook.md +131 -0
- package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
- package/docs/claude-breakpoints.json +75 -5
- package/docs/design/abc-benchmark.md +1 -1
- package/docs/design/design-spec-schema.md +1 -1
- package/docs/design/divergent-generation.md +1 -1
- package/docs/design/eval-gate-runbook.md +178 -0
- package/docs/design/show-hn-draft.md +26 -1
- package/docs/design/token-cost-baseline-1298.md +59 -0
- package/docs/eval/README.md +117 -0
- package/docs/eval/corpus/seed-v1.json +6 -0
- package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
- package/docs/site/annotations-explained.md +24 -0
- package/docs/site/command-learning-path.md +51 -14
- package/docs/site/command-reference.md +339 -113
- package/docs/site/for-companies.md +95 -0
- package/docs/site/forge-annotation-protocol.md +12 -256
- package/docs/site/getting-started.md +43 -4
- package/docs/site/github-is-the-memory.md +113 -0
- package/docs/site/how-it-works.md +3 -13
- package/docs/site/index.md +9 -1
- package/docs/spec/eval-run-result.md +147 -0
- package/docs/spec/forge-protocol-v1.md +441 -18
- package/docs/spec/label-state-machine.md +55 -0
- package/docs/spec/review-protocol.md +158 -0
- package/docs/spec-graph-schema.md +28 -0
- package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
- package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
- package/examples/forgedock-demo/README.md +41 -22
- package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
- package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
- package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
- package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
- package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
- package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
- package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
- package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
- package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
- package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
- package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
- package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
- package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
- package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
- package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
- package/examples/forgedock-demo/scripts/smoke.js +18 -1
- package/examples/forgedock-demo/src/db.js +36 -11
- package/examples/forgedock-demo/src/routes/notes.js +106 -9
- package/examples/forgedock-demo/src/server.js +4 -1
- package/package.json +3 -1
- package/packages/protocol/LICENSE +21 -0
- package/packages/protocol/src/cli.js +135 -0
- package/packages/protocol/src/emit.js +146 -0
- package/packages/protocol/src/index.js +43 -0
- package/packages/protocol/src/parse.js +229 -0
- package/packages/protocol/src/types.js +171 -0
- package/packages/protocol/src/validate.js +122 -0
- package/scripts/bench-topology-cost.mjs +372 -0
- package/scripts/check-command-docs-drift.sh +198 -0
- package/scripts/check-protocol-restatements.sh +176 -0
- package/scripts/check-registry/README.md +72 -0
- package/scripts/check-registry/manifest.json +6 -0
- package/scripts/code-index.sh +454 -0
- package/scripts/conformance-check.mjs +168 -0
- package/scripts/doctor-pipeline-state.sh +484 -0
- package/scripts/eval-gate-baseline.json +17 -0
- package/scripts/eval-gate-scorecard.mjs +242 -0
- package/scripts/eval-scorecard-aggregator.mjs +252 -0
- package/scripts/flaky-quarantine.sh +241 -0
- package/scripts/forge-annotation.sh +567 -0
- package/scripts/issue-dedup.sh +236 -0
- package/scripts/validate-annotation-node.mjs +233 -0
- package/scripts/worktree-lifecycle.sh +3 -3
- package/templates/devdocs/agent/using-forgedock.md +14 -0
- package/docs/site/.vitepress/config.mjs +0 -85
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# Agent: Auth Conventions Auditor
|
|
8
|
+
|
|
9
|
+
> Read `review-pr-agents/protocols.md` for the Evidence-Based Review Protocol, Structured Findings Protocol, Per-Agent Input Scoping rules, and Tool-Result Truncation Discipline that all agents must follow.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**Trigger**: AUTH domain detected
|
|
14
|
+
**Type**: `security-exploit-auditor` | **Model**: `sonnet`
|
|
15
|
+
|
|
16
|
+
**Prompt template:**
|
|
17
|
+
```
|
|
18
|
+
You are auditing PR #[PR_NUMBER] for authentication and authorization correctness in [PROJECT_NAME].
|
|
19
|
+
|
|
20
|
+
## CRITICAL PROJECT CONVENTIONS — You MUST enforce these:
|
|
21
|
+
|
|
22
|
+
[DOMAIN_CONTEXT]
|
|
23
|
+
|
|
24
|
+
### How to Check
|
|
25
|
+
```bash
|
|
26
|
+
# Find auth patterns in changed files
|
|
27
|
+
grep -rn "auth\|Depends\|get_current\|verify_token\|require_auth" [CHANGED_FILES]
|
|
28
|
+
|
|
29
|
+
# Cross-reference with route path to determine if correct
|
|
30
|
+
grep -rn "@router\.(get\|post\|put\|delete)\|app\.(get\|post\|put\|delete)" [CHANGED_FILES]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### What to Verify
|
|
34
|
+
1. Every new endpoint has an auth dependency (no unauthenticated endpoints without justification)
|
|
35
|
+
2. The CORRECT auth dependency is used based on route type (refer to project conventions in [DOMAIN_CONTEXT] above — if absent, derive from surrounding code patterns)
|
|
36
|
+
3. Multi-tenancy: resource access checks `user_id` ownership BEFORE returning data
|
|
37
|
+
4. Rate limiting is applied to public-facing endpoints
|
|
38
|
+
5. No IDOR vulnerabilities (different error codes for 404 vs 403 leak existence)
|
|
39
|
+
6. Header forwarding trust model: when the diff touches Next.js middleware, route handlers, or FastAPI rate-limiting middleware, verify that attacker-controlled `X-Forwarded-For` headers cannot spoof the IP used for rate limit keying
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Check if Next.js proxy layer strips or validates X-Forwarded-For before forwarding
|
|
43
|
+
grep -nE "x-forwarded-for|X-Forwarded-For|headers.*forwarded|forwarded.*headers" \
|
|
44
|
+
web/src/middleware.ts web/src/app/api/ 2>/dev/null
|
|
45
|
+
# If found without a strip/validate step: CONFIRMED HIGH — complete rate limit bypass
|
|
46
|
+
# Safe pattern: headers.delete("x-forwarded-for") or rightmost-IP-only extraction
|
|
47
|
+
|
|
48
|
+
# Check if the backend trusts X-Forwarded-For for rate limit keying
|
|
49
|
+
grep -rn "X-Forwarded-For\|x_forwarded_for\|forwarded_for\|client_ip\|real_ip" \
|
|
50
|
+
$(git ls-files | grep -E "\.(py|ts|js)$" | head -20) | head -10
|
|
51
|
+
# If found without trusted-proxy-range validation: CONFIRMED HIGH
|
|
52
|
+
# The backend must only trust X-Forwarded-For when the immediate caller is in a known trusted proxy range
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Flag as CONFIRMED HIGH** if: X-Forwarded-For is forwarded from client to backend without stripping or rightmost-only extraction AND the backend keys rate limits on that header value.
|
|
56
|
+
|
|
57
|
+
7. JWT secret/algorithm separation: when the diff touches JWT signing, verification, or token generation, verify that different token classes (user session, admin-proxy, API key) use distinct signing secrets or asymmetric algorithms — not a shared secret differentiated only by claims
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Check signing configuration across token classes — adapt paths to the project's auth files
|
|
61
|
+
AUTH_FILES=$(git ls-files | grep -iE "auth|security|jwt|token" | grep -E "\.(py|ts|js)$" | head -10)
|
|
62
|
+
grep -nE "SECRET|algorithm|HS256|RS256|verify|decode" $AUTH_FILES | head -20
|
|
63
|
+
# Flag if: multiple token classes reference the same secret variable AND the only differentiator is a claim (e.g., aud, role)
|
|
64
|
+
# Safe pattern: privileged tokens use a separate secret or RS256 (asymmetric)
|
|
65
|
+
# so that a user-level token CANNOT be escalated to admin by claim manipulation
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Flag as CONFIRMED HIGH** if: two or more token classes with different privilege levels share the same signing secret and algorithm, with only claim values (e.g., `aud="admin-proxy"`) preventing privilege escalation.
|
|
69
|
+
|
|
70
|
+
## Context
|
|
71
|
+
- Files changed: [AUTH_RELEVANT_FILES]
|
|
72
|
+
- PR description: [PR_BODY]
|
|
73
|
+
|
|
74
|
+
## Steps
|
|
75
|
+
1. Read the diff: `gh pr diff [PR_NUMBER]`
|
|
76
|
+
2. For each endpoint, verify auth dependency matches route type
|
|
77
|
+
3. Check ownership queries for multi-tenancy
|
|
78
|
+
4. Search for auth dependency patterns: `grep -rn "get_current\|require_auth\|authenticated_user\|current_user" $(git ls-files | grep -E "router|route|endpoint" | head -20)`
|
|
79
|
+
5. Compare against existing route patterns for consistency
|
|
80
|
+
6. If diff touches middleware, route handlers, or rate-limit code: run header forwarding check (item 6 grep commands above)
|
|
81
|
+
7. If diff touches auth/JWT/token files: run JWT secret separation check (item 7 grep commands above)
|
|
82
|
+
|
|
83
|
+
## Post Findings
|
|
84
|
+
```bash
|
|
85
|
+
gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
|
|
86
|
+
## Auth Conventions Audit
|
|
87
|
+
|
|
88
|
+
### Endpoints Reviewed
|
|
89
|
+
| Endpoint | Method | Auth Dep Used | Expected Auth Dep | Correct? | Ownership Check |
|
|
90
|
+
|----------|--------|--------------|-------------------|----------|-----------------|
|
|
91
|
+
| /path | POST | [auth_dep] | [expected_dep] | Yes/No | Yes/No/N/A |
|
|
92
|
+
|
|
93
|
+
### Convention Violations
|
|
94
|
+
[List any violations of the project's auth convention (from [DOMAIN_CONTEXT]) with file:line]
|
|
95
|
+
|
|
96
|
+
### Multi-Tenancy Check
|
|
97
|
+
[For each resource access, show the ownership check or flag missing]
|
|
98
|
+
|
|
99
|
+
### Header Forwarding Trust Model (Item 6)
|
|
100
|
+
[If proxy/middleware files touched: state whether X-Forwarded-For is stripped/validated before rate-limit IP keying, or SKIPPED if no middleware changes in this PR]
|
|
101
|
+
|
|
102
|
+
### JWT Secret Separation (Item 7)
|
|
103
|
+
[If auth.py or JWT signing files touched: state whether each token class uses a distinct secret/algorithm, or SKIPPED if no JWT configuration changes in this PR]
|
|
104
|
+
|
|
105
|
+
### Files Reviewed
|
|
106
|
+
[List all auth-related files checked]
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
*Auth conventions audit*
|
|
110
|
+
|
|
111
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
112
|
+
<!-- FINDING:AUTH-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
|
|
113
|
+
<!-- (add one FINDING line per issue found — include ALL confidence levels) -->
|
|
114
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
115
|
+
EOF
|
|
116
|
+
)"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `AUTH`. See the Structured Findings Protocol section above for format rules.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Coverage Matrix — AUTH Agent
|
|
123
|
+
|
|
124
|
+
| Defect Category | Check Item(s) | Status | Ref |
|
|
125
|
+
|----------------|---------------|--------|-----|
|
|
126
|
+
| Missing auth dependency on endpoint | Item 1 | COVERED | |
|
|
127
|
+
| Wrong auth dependency (convention from [DOMAIN_CONTEXT]) | Item 2 | COVERED | |
|
|
128
|
+
| Multi-tenancy / IDOR | Item 3 | COVERED | |
|
|
129
|
+
| Missing rate limiting on public endpoints | Item 4 | COVERED | |
|
|
130
|
+
| IDOR via error code differentiation | Item 5 | COVERED | |
|
|
131
|
+
| X-Forwarded-For trust model bypass | Item 6 | COVERED | #299 |
|
|
132
|
+
| JWT shared-secret privilege escalation | Item 7 | COVERED | #299 |
|
|
133
|
+
| OAuth state parameter CSRF | — | GAP | |
|
|
134
|
+
| Session fixation / session invalidation on privilege change | — | GAP | |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# Agent: Billing Integrity Auditor
|
|
8
|
+
|
|
9
|
+
> Read `review-pr-agents/protocols.md` for the Evidence-Based Review Protocol, Structured Findings Protocol, Per-Agent Input Scoping rules, and Tool-Result Truncation Discipline that all agents must follow.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**Trigger**: BILLING domain detected
|
|
14
|
+
**Type**: `codebase-explorer` | **Model**: `sonnet`
|
|
15
|
+
|
|
16
|
+
**Prompt template:**
|
|
17
|
+
```
|
|
18
|
+
You are auditing PR #[PR_NUMBER] for billing integrity in [PROJECT_NAME].
|
|
19
|
+
|
|
20
|
+
CRITICAL: Any billing bug = revenue loss or user overcharging.
|
|
21
|
+
|
|
22
|
+
## Project Billing Architecture
|
|
23
|
+
|
|
24
|
+
[DOMAIN_CONTEXT]
|
|
25
|
+
|
|
26
|
+
If no billing context is configured above, derive the billing flow from the changed files: trace credit check → debit → execution → reconciliation paths.
|
|
27
|
+
|
|
28
|
+
## What to Verify
|
|
29
|
+
1. **Trace the full flow**: charge check → pre-debit → execution → reconciliation
|
|
30
|
+
2. **Charge calculation accuracy**: Where is the charge amount set? Is it the final value or intermediate?
|
|
31
|
+
3. **No double-charging**: Verify pre-debit and reconciliation don't overlap
|
|
32
|
+
4. **Failure handling**: What happens to charges when an operation fails?
|
|
33
|
+
5. **Idempotency**: Can a retry cause double-debit?
|
|
34
|
+
6. **Bypass paths**: Is there any code path that bypasses billing entirely?
|
|
35
|
+
7. **Gate regression check**: If the PR contains or preserves a feature gate that restricts endpoint access (e.g., `if "feature_name" not in features`, tier checks, balance thresholds blocking a route), verify the gate existed in the base branch BEFORE the commits being reviewed. Run `git show origin/{base}:{file} | grep -n "gate_pattern"` to check. If the gate was introduced by the same commit chain being fixed — not an independent historical addition — flag it as a potential rogue gate with HIGH severity: the correct fix is to fully revert the gate block, not to patch around it. A rogue gate silently restricts access for all users below a tier or balance threshold without any intentional review of that restriction. This finding is **informational — not a merge blocker**, but must appear in the Findings table so it can be tracked as a follow-up. <!-- Added: forge#278 -->
|
|
36
|
+
|
|
37
|
+
## MANDATORY Before Reporting
|
|
38
|
+
- Search for reconciliation logic before claiming "no reconciliation": `grep -rn "reconcil" $(git ls-files | grep -E "\.(py|js|ts)$")`
|
|
39
|
+
- Trace the charge amount variable before claiming "wrong amount charged"
|
|
40
|
+
- Read the job completion handler (from [DOMAIN_CONTEXT] or `grep -rn "job_complete\|on_complete\|after_execute" $(git ls-files)`) before claiming "charges not refunded"
|
|
41
|
+
|
|
42
|
+
## Post Findings
|
|
43
|
+
```bash
|
|
44
|
+
gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
|
|
45
|
+
## Billing Integrity Audit
|
|
46
|
+
|
|
47
|
+
### Billing Impact: [NONE/LOW/MEDIUM/HIGH]
|
|
48
|
+
|
|
49
|
+
### Flow Traced
|
|
50
|
+
1. Credit check: [file:line]
|
|
51
|
+
2. Pre-debit: [file:line]
|
|
52
|
+
3. Execution: [file:line]
|
|
53
|
+
4. Tier determination: [file:line] — tier_used = [how set]
|
|
54
|
+
5. Reconciliation: [file:line]
|
|
55
|
+
|
|
56
|
+
### Findings
|
|
57
|
+
| Issue | Confidence | Evidence | Revenue Impact |
|
|
58
|
+
|-------|------------|----------|----------------|
|
|
59
|
+
| ... | CONFIRMED/LIKELY | [code path] | [estimated impact] |
|
|
60
|
+
|
|
61
|
+
### What I Verified
|
|
62
|
+
- [ ] Traced credit deduction from API to worker
|
|
63
|
+
- [ ] Found reconciliation logic at [file:line]
|
|
64
|
+
- [ ] Verified tier_used source
|
|
65
|
+
- [ ] Checked idempotency
|
|
66
|
+
- [ ] Checked feature gates for rogue-gate regression (item 7)
|
|
67
|
+
|
|
68
|
+
### Files Reviewed
|
|
69
|
+
[List all billing-related files checked]
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
*Billing integrity audit*
|
|
73
|
+
|
|
74
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
75
|
+
<!-- FINDING:BILL-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
|
|
76
|
+
<!-- (add one FINDING line per issue found — include ALL confidence levels) -->
|
|
77
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
78
|
+
EOF
|
|
79
|
+
)"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `BILL`. See the Structured Findings Protocol section above for format rules.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Coverage Matrix — BILL Agent
|
|
86
|
+
|
|
87
|
+
| Defect Category | Check Item(s) | Status | Ref |
|
|
88
|
+
|----------------|---------------|--------|-----|
|
|
89
|
+
| Credit check → debit → reconciliation flow integrity | Item 1 | COVERED | |
|
|
90
|
+
| tier_used accuracy (wrong tier charged) | Item 2 | COVERED | |
|
|
91
|
+
| Double-charging (pre-debit + reconciliation overlap) | Item 3 | COVERED | |
|
|
92
|
+
| Credit loss on scrape failure | Item 4 | COVERED | |
|
|
93
|
+
| Retry idempotency (double-debit) | Item 5 | COVERED | |
|
|
94
|
+
| Free scrape bypass paths | Item 6 | COVERED | |
|
|
95
|
+
| Rogue feature gate regression | Item 7 | COVERED | #278 |
|
|
96
|
+
| Webhook handler completeness | — | PARTIAL | #297 |
|
|
97
|
+
| Spend limit / budget cap accuracy | — | PARTIAL | #297 |
|
|
98
|
+
| Promo/voucher redemption integrity | — | GAP | |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# Agent: Concurrency & Race Condition Auditor
|
|
8
|
+
|
|
9
|
+
> Read `review-pr-agents/protocols.md` for the Evidence-Based Review Protocol, Structured Findings Protocol, Per-Agent Input Scoping rules, and Tool-Result Truncation Discipline that all agents must follow.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**Trigger**: CONCURRENCY domain detected OR BILLING domain detected
|
|
14
|
+
**Type**: `general-purpose` | **Model**: `sonnet`
|
|
15
|
+
|
|
16
|
+
**Prompt template:**
|
|
17
|
+
```
|
|
18
|
+
You are auditing PR #[PR_NUMBER] for concurrency bugs and race conditions in [PROJECT_NAME].
|
|
19
|
+
|
|
20
|
+
CRITICAL: Any race condition in financial or stateful operations can cause data corruption or duplicate charges.
|
|
21
|
+
|
|
22
|
+
## What to Look For
|
|
23
|
+
1. **Read-modify-write without locks**: `balance = get(); if balance >= cost: deduct(cost)`
|
|
24
|
+
2. **Non-atomic Redis operations**: Multiple Redis calls that should be a pipeline/transaction
|
|
25
|
+
3. **Missing FOR UPDATE**: DB queries that read-then-write without row locks
|
|
26
|
+
4. **Shared state in async**: Global/module-level state modified by concurrent requests
|
|
27
|
+
5. **Job idempotency**: Can running a job twice cause double-billing or duplicate work?
|
|
28
|
+
6. **Incomplete state mutation**: When the PR introduces a new counter/dict/set that mirrors or is paired with an existing one (e.g., `_user_active_browsers` alongside `_browser_active_count`), grep for ALL sites that mutate the existing variable. Each site must also handle the new variable, or document why not. The agent's job is NOT just to verify new code is locked — it's to verify that ALL pre-existing mutation sites were updated to maintain the invariant.
|
|
29
|
+
7. **Reservation TOCTOU**: Any pattern where a "check availability" read is followed by a "claim" write as two separate statements (not atomic). Required safe patterns:
|
|
30
|
+
- `SELECT ... FOR UPDATE SKIP LOCKED` (advisory lock on the row during the transaction)
|
|
31
|
+
- `UPDATE ... WHERE reserved_by IS NULL RETURNING id` (single atomic claim — no separate read)
|
|
32
|
+
- Database UNIQUE constraint on the reservation column (prevents duplicate claims at DB level)
|
|
33
|
+
|
|
34
|
+
Search for check-then-claim patterns in promo, voucher, or coupon redemption code:
|
|
35
|
+
```bash
|
|
36
|
+
grep -n "reserved_by\|voucher.*claim\|promo.*redeem\|coupon.*use" <billing_files> | head -20
|
|
37
|
+
# If found without FOR UPDATE or RETURNING in same transaction: CONFIRMED HIGH
|
|
38
|
+
```
|
|
39
|
+
If `WHERE reserved_by IS NULL` appears in a SELECT that is followed by a separate UPDATE (not in the same atomic statement), this is a CONFIRMED HIGH finding — two concurrent sessions can both pass the read check before either writes.
|
|
40
|
+
|
|
41
|
+
8. **Cross-service flag staleness**: When a discount or pricing flag (e.g. `has_active_subscription`, a `discount_type` field) is set by the API layer at job submission and read by the Worker layer at billing time, verify the flag is re-validated at debit time — not trusted from the queued job payload.
|
|
42
|
+
|
|
43
|
+
Search for flags passed through job payloads:
|
|
44
|
+
```bash
|
|
45
|
+
grep -rn "discount.*flag\|flag.*discount\|subscription.*flag\|plan_type\|discount_type\|entitlement" \
|
|
46
|
+
$(git ls-files | grep -E "\.(py|js|ts)$") | head -20
|
|
47
|
+
# If the flag flows through a job payload and is not re-validated at execution: CONFIRMED HIGH
|
|
48
|
+
```
|
|
49
|
+
A race window exists when a flag is checked at submission but consumed at billing: the underlying condition (e.g., subscription status, entitlement) may have changed between the two operations. The fix must re-validate the flag atomically at the point of debit, not rely on a stale value from the job payload.
|
|
50
|
+
|
|
51
|
+
## Safe Patterns in This Codebase
|
|
52
|
+
```bash
|
|
53
|
+
# Search for existing protections
|
|
54
|
+
grep -rn "with_for_update\|FOR UPDATE" $(git ls-files | grep -E "\.(py|sql)$") | head -20
|
|
55
|
+
grep -rn "MULTI\|pipeline\|transaction" $(git ls-files | grep -E "\.(py|js|ts)$") | head -20
|
|
56
|
+
grep -rn "distributed_lock\|acquire_lock" $(git ls-files | grep -E "\.(py|js|ts)$") | head -20
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Verify State Completeness
|
|
60
|
+
For every new state variable (counter, dict, set) introduced by the PR:
|
|
61
|
+
1. Identify its "sibling" — the existing state variable it mirrors or is paired with
|
|
62
|
+
2. `grep -n "sibling_variable_name"` in the same module/file
|
|
63
|
+
3. For each mutation site of the sibling: verify the new variable is also mutated (or explicitly excluded with justification)
|
|
64
|
+
4. Flag any site that mutates the sibling but NOT the new variable — this is a CONFIRMED finding (invariant violation, not a style issue)
|
|
65
|
+
|
|
66
|
+
Example: PR adds `_user_active_browsers`. Sibling is `_browser_active_count`. Grep finds 3 mutation sites: `get_browser()` ✅, `_release_browser_ref()` ✅, `invalidate_browser()` ❌ — missing update = CONFIRMED HIGH finding.
|
|
67
|
+
|
|
68
|
+
## Cancellation Safety — Prove, Don't Reason
|
|
69
|
+
When reviewing `asyncio.shield`, `asyncio.wait_for`, or `Task.cancel()` patterns:
|
|
70
|
+
|
|
71
|
+
1. NEVER assert "this is correct" without identifying the specific CancelledError delivery point
|
|
72
|
+
2. For `asyncio.shield`: the outer `await asyncio.shield(coro())` is itself an await point — if CancelledError is ALREADY PENDING on the task (e.g., injected by `asyncio.wait_for` timeout), it fires HERE before the inner coroutine starts. The shield does not protect against a pending cancellation.
|
|
73
|
+
3. For `asyncio.wait_for`: timeout injects CancelledError into the wrapped task — trace what happens in every `finally` block after this injection. Does any `finally` block contain an `await`? That await is also a cancellation point.
|
|
74
|
+
4. If you cannot write a test that proves the cancellation path works, report confidence as **POSSIBLE**, not CONFIRMED-safe.
|
|
75
|
+
5. Flag any `asyncio.shield` usage with: "Requires test: simulate CancelledError pending before shield await"
|
|
76
|
+
|
|
77
|
+
## Verify Before Claiming
|
|
78
|
+
- Check if the code you're analyzing is already protected by locks/transactions elsewhere
|
|
79
|
+
- Read the FULL function scope, not just the diff
|
|
80
|
+
- For state completeness: read ALL mutation sites of the sibling variable, not just the ones modified in the PR diff
|
|
81
|
+
- For asyncio patterns: identify the exact await point where CancelledError fires — do not reason about "what the code intends"
|
|
82
|
+
|
|
83
|
+
## Post Findings
|
|
84
|
+
```bash
|
|
85
|
+
gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
|
|
86
|
+
## Concurrency & Race Condition Audit
|
|
87
|
+
|
|
88
|
+
### Risk Level: [LOW/MEDIUM/HIGH/CRITICAL]
|
|
89
|
+
|
|
90
|
+
### Race Conditions Found
|
|
91
|
+
| Pattern | Location | Protected? | Confidence | Evidence |
|
|
92
|
+
|---------|----------|------------|------------|----------|
|
|
93
|
+
| read-modify-write | file:line | No | CONFIRMED | [code path] |
|
|
94
|
+
|
|
95
|
+
### Protections Searched For
|
|
96
|
+
- FOR UPDATE: [found/not found]
|
|
97
|
+
- Redis transactions: [found/not found]
|
|
98
|
+
- Distributed locks: [found/not found]
|
|
99
|
+
- Idempotency keys: [found/not found]
|
|
100
|
+
|
|
101
|
+
### Asyncio Cancellation Safety
|
|
102
|
+
| Pattern | Location | Outer await cancellation-safe? | Confidence | Evidence |
|
|
103
|
+
|---------|----------|-------------------------------|------------|----------|
|
|
104
|
+
| asyncio.shield | file:line | Yes/No/POSSIBLE — [explain CancelledError delivery point] | CONFIRMED/POSSIBLE | [code path] |
|
|
105
|
+
|
|
106
|
+
### State Completeness Check
|
|
107
|
+
| New Variable | Sibling Variable | Mutation Sites Found | All Sites Updated? |
|
|
108
|
+
|-------------|-----------------|---------------------|-------------------|
|
|
109
|
+
| [new_var] | [sibling_var] | [count] | Yes/No — [missing sites if No] |
|
|
110
|
+
|
|
111
|
+
### Files Reviewed
|
|
112
|
+
[List files checked]
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
*Concurrency audit*
|
|
116
|
+
|
|
117
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
118
|
+
<!-- FINDING:CONC-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
|
|
119
|
+
<!-- (add one FINDING line per issue found — include ALL confidence levels) -->
|
|
120
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
121
|
+
EOF
|
|
122
|
+
)"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `CONC`. See the Structured Findings Protocol section above for format rules.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Coverage Matrix — CONC Agent
|
|
129
|
+
|
|
130
|
+
| Defect Category | Check Item(s) | Status | Ref |
|
|
131
|
+
|----------------|---------------|--------|-----|
|
|
132
|
+
| Read-modify-write without locks | Item 1 | COVERED | |
|
|
133
|
+
| Non-atomic Redis operations | Item 2 | COVERED | |
|
|
134
|
+
| Missing FOR UPDATE on read-then-write | Item 3 | COVERED | |
|
|
135
|
+
| Shared state in async handlers | Item 4 | COVERED | |
|
|
136
|
+
| Job idempotency (double-billing) | Item 5 | COVERED | |
|
|
137
|
+
| Incomplete state mutation (new counter/dict) | Item 6 | COVERED | |
|
|
138
|
+
| Reservation TOCTOU (check-then-claim) | Item 7 | COVERED | #298 |
|
|
139
|
+
| Cross-service flag staleness | Item 8 | COVERED | #298 |
|
|
140
|
+
| asyncio.shield cancellation safety | Cancellation Safety | COVERED | |
|
|
141
|
+
| Distributed lock timeout / deadlock | — | GAP | |
|
|
142
|
+
| Connection pool exhaustion under concurrency | — | GAP | |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# Agent: Database & Migration Auditor
|
|
8
|
+
|
|
9
|
+
> Read `review-pr-agents/protocols.md` for the Evidence-Based Review Protocol, Structured Findings Protocol, Per-Agent Input Scoping rules, and Tool-Result Truncation Discipline that all agents must follow.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**Trigger**: DATABASE domain detected
|
|
14
|
+
**Type**: `general-purpose` | **Model**: `sonnet`
|
|
15
|
+
|
|
16
|
+
**Prompt template:**
|
|
17
|
+
```
|
|
18
|
+
You are auditing PR #[PR_NUMBER] for database changes in [PROJECT_NAME].
|
|
19
|
+
|
|
20
|
+
[DOMAIN_CONTEXT]
|
|
21
|
+
|
|
22
|
+
## What to Check
|
|
23
|
+
1. **SQL correctness** (CHECK FIRST — a query that errors at runtime breaks the whole page):
|
|
24
|
+
- **Ambiguous references**: `SELECT t.col, t.*` creates duplicate columns — will `DISTINCT ON`, `GROUP BY`, `ORDER BY`, or `UNION` choke on the duplicate?
|
|
25
|
+
- **Column visibility**: CTEs and subqueries that produce duplicate column names, then are referenced by `SELECT *`
|
|
26
|
+
- **Type mismatches**: Comparing UUID to text, integer to string without cast
|
|
27
|
+
- **Invalid aggregations**: Non-aggregated columns in SELECT with GROUP BY
|
|
28
|
+
- **Mental-execute the query**: Read the full SQL top-to-bottom. What columns does each CTE produce? What does the final SELECT see? Would PostgreSQL accept this or throw an error?
|
|
29
|
+
2. **Migration safety**: Can this run on a live database without downtime?
|
|
30
|
+
- `ALTER TABLE ... ADD COLUMN ... NOT NULL` without `DEFAULT` → table lock + failure on existing rows
|
|
31
|
+
- `DROP TABLE/COLUMN` without `IF EXISTS` → fails on fresh DBs
|
|
32
|
+
- Large table operations → may lock for minutes
|
|
33
|
+
3. **Reversibility**: Is there a rollback path?
|
|
34
|
+
4. **Index usage**: New queries without indexes on filtered/joined columns? IVFFlat indexes on empty tables create degenerate indexes — check if the table has data at index creation time.
|
|
35
|
+
5. **Unbounded queries**: SELECT without LIMIT, time-bound WHERE, or pagination. A query loading "all sessions" without a date filter will degrade as data grows. Also check for deleted/soft-deleted records — queries without `WHERE deleted_at IS NULL` may include GDPR-relevant data.
|
|
36
|
+
6. **N+1 queries**: Loop fetching rows one at a time instead of batch?
|
|
37
|
+
7. **SQL injection**: Raw SQL with string formatting instead of parameterized queries? f-string SQL is the #1 finding — `f"WHERE {column} = '{value}'"` instead of parameterized `WHERE $1 = $2`.
|
|
38
|
+
8. **Migration number collisions (CRITICAL — full-tree scan required)**:
|
|
39
|
+
This check is structurally different from the others — it must scan the **entire `infra/migrations/` directory**, not just files in the PR diff. Pre-existing duplicates already on the branch are invisible in the diff but will fail deploy.
|
|
40
|
+
Steps:
|
|
41
|
+
a. List ALL `*.sql` files in `infra/migrations/` on the PR's target branch (use `git ls-tree` or `ls`)
|
|
42
|
+
b. Extract the 4-digit numeric prefix from each filename (the leading digits before the first `_`)
|
|
43
|
+
c. Identify any prefix that appears more than once
|
|
44
|
+
d. Identify if the project maintains a grandfathered-duplicates allowlist (e.g., a config file or comment block listing known-safe legacy duplicate prefixes). If one exists, cross-reference against it. <!-- Updated: forge#1349 — removed stale validate-migration-order.sh reference (script does not exist in ForgeDock) -->
|
|
45
|
+
e. **DEPLOY GATE — CRITICAL**: If ANY non-allowlisted duplicate prefix exists → flag as **CRITICAL BLOCKER** and reject the PR. **Do NOT apply migration runner reasoning here.** Deploy gates that enforce migration ordering hard-fail on any non-allowed duplicate regardless of whether the migration runner executes files correctly. The runner may handle duplicate filenames fine; the deploy script does not. A PR that passes this reasoning trap ("unique filenames, so the runner is safe") will still halt production deploy. The only safe classification is CRITICAL BLOCKER.
|
|
46
|
+
f. Additionally: if the PR adds new migration files, verify their prefixes don't collide with existing files in the directory
|
|
47
|
+
9. **FK and CHECK constraints**: New tables should have appropriate foreign keys and CHECK constraints. Missing FK allows orphaned rows; missing CHECK allows invalid enum values.
|
|
48
|
+
10. **asyncpg gotchas**:
|
|
49
|
+
- Must use `CAST(:param AS type)` for nullable params (asyncpg can't infer NULL types)
|
|
50
|
+
- `::jsonb` after `:param` conflicts with SQLAlchemy binding — use `CAST(:param AS jsonb)`
|
|
51
|
+
|
|
52
|
+
## Post Findings
|
|
53
|
+
```bash
|
|
54
|
+
gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
|
|
55
|
+
## Database & Migration Audit
|
|
56
|
+
|
|
57
|
+
### Migration Safety: [SAFE/CAUTION/DANGEROUS]
|
|
58
|
+
|
|
59
|
+
### Findings
|
|
60
|
+
| Issue | Location | Severity | Evidence |
|
|
61
|
+
|-------|----------|----------|----------|
|
|
62
|
+
| ... | file:line | HIGH | [explanation] |
|
|
63
|
+
|
|
64
|
+
### Migration Review
|
|
65
|
+
[For each SQL file: what it does, is it safe, is it reversible?]
|
|
66
|
+
|
|
67
|
+
### Files Reviewed
|
|
68
|
+
[List files checked]
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
*Database audit*
|
|
72
|
+
|
|
73
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
74
|
+
<!-- FINDING:DB-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
|
|
75
|
+
<!-- (add one FINDING line per issue found — include ALL confidence levels) -->
|
|
76
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
77
|
+
EOF
|
|
78
|
+
)"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `DB`. See the Structured Findings Protocol section above for format rules.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Coverage Matrix — DB Agent
|
|
85
|
+
|
|
86
|
+
| Defect Category | Check Item(s) | Status | Ref |
|
|
87
|
+
|----------------|---------------|--------|-----|
|
|
88
|
+
| Ambiguous column references / duplicate cols | Item 1 | COVERED | |
|
|
89
|
+
| Type mismatches in SQL (UUID vs text) | Item 1 | COVERED | |
|
|
90
|
+
| Migration safety (NOT NULL without DEFAULT) | Item 2 | COVERED | |
|
|
91
|
+
| Migration reversibility | Item 3 | COVERED | |
|
|
92
|
+
| Missing indexes on filtered/joined columns | Item 4 | COVERED | |
|
|
93
|
+
| Unbounded queries (no LIMIT, no date filter) | Item 5 | COVERED | |
|
|
94
|
+
| N+1 query patterns | Item 6 | COVERED | |
|
|
95
|
+
| SQL injection (f-string SQL) | Item 7 | COVERED | |
|
|
96
|
+
| Migration number collisions | Item 8 | COVERED | #222 |
|
|
97
|
+
| Missing FK / CHECK constraints | Item 9 | COVERED | |
|
|
98
|
+
| asyncpg parameter casting | Item 10 | COVERED | |
|
|
99
|
+
| ORM field rename without migration | — | GAP | #240 |
|
|
100
|
+
| Ghost migration (rename-to-fill-gap) | — | GAP | #227 |
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
install: internal
|
|
3
|
+
---
|
|
4
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
6
|
+
|
|
7
|
+
# Agent: Frontend Quality Auditor
|
|
8
|
+
|
|
9
|
+
> Read `review-pr-agents/protocols.md` for the Evidence-Based Review Protocol, Structured Findings Protocol, Per-Agent Input Scoping rules, and Tool-Result Truncation Discipline that all agents must follow.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
**Trigger**: WEB service touched
|
|
14
|
+
**Type**: `codebase-explorer` | **Model**: `sonnet`
|
|
15
|
+
|
|
16
|
+
**Prompt template:**
|
|
17
|
+
```
|
|
18
|
+
You are auditing PR #[PR_NUMBER] for frontend quality in [PROJECT_NAME].
|
|
19
|
+
|
|
20
|
+
## Project Frontend Conventions
|
|
21
|
+
|
|
22
|
+
[DOMAIN_CONTEXT]
|
|
23
|
+
|
|
24
|
+
If no frontend context is configured above, derive conventions from the changed files: check package.json for framework versions and look at existing patterns in surrounding components.
|
|
25
|
+
|
|
26
|
+
## What to Check
|
|
27
|
+
1. **Server vs Client components**: Is 'use client' used appropriately? Could this be a Server Component instead?
|
|
28
|
+
2. **React lifecycle**: Missing useEffect cleanup (subscriptions, timers, AbortControllers not cancelled on unmount). This is the #1 frontend defect — causes memory leaks and stale state.
|
|
29
|
+
3. **useCallback/useMemo deps**: Dependencies must be stable values (ids, primitives), NOT full objects (SWR responses, arrays). An unstable dep causes infinite re-render loops.
|
|
30
|
+
4. **Data fetching**: Loading/error states handled, stale data invalidated, race conditions in parallel fetches
|
|
31
|
+
5. **Type safety**: Zod schemas match API response types, no `any` types. Check that component props match what the parent passes — wrong prop types (e.g., passing a component reference instead of a rendered element) cause build failures.
|
|
32
|
+
6. **Component imports**: Verify imported components actually exist. Check `@/components/ui/*` imports against what's installed via shadcn. Missing components pass `tsc` if types exist but fail `next build`.
|
|
33
|
+
7. **XSS**: User input rendered with `dangerouslySetInnerHTML` without sanitization
|
|
34
|
+
8. **Accessibility**: Interactive elements have proper labels, keyboard navigation works
|
|
35
|
+
9. **Performance**: Large bundles, unnecessary client-side rendering, missing dynamic imports
|
|
36
|
+
10. **Hook provider scope**: For any new `useX()` hook call added to a component, verify the hook is safe to call outside its provider. If `useX` internally calls `useContext(XContext)` and throws when context is undefined (i.e., the hook contains `if (!ctx) throw new Error(...)`), check ALL mount sites of the component across the codebase. If the component is used in both authenticated routes (e.g., `app/dashboard/`) AND public routes (e.g., `app/(public)/`, `app/playground/`) that do not wrap children in the provider, the hook call will crash the public route with a React error boundary cascade. Flag as CONFIRMED HIGH if a public mount site exists without the provider. <!-- Added: forge#381 -->
|
|
37
|
+
|
|
38
|
+
## Post Findings
|
|
39
|
+
```bash
|
|
40
|
+
gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
|
|
41
|
+
## Frontend Quality Audit
|
|
42
|
+
|
|
43
|
+
### Quality Level: [GOOD/ACCEPTABLE/NEEDS WORK]
|
|
44
|
+
|
|
45
|
+
### Findings
|
|
46
|
+
| Category | Issue | File:Line | Severity |
|
|
47
|
+
|----------|-------|-----------|----------|
|
|
48
|
+
| React | missing useEffect dep | file:line | MEDIUM |
|
|
49
|
+
| A11y | button without label | file:line | LOW |
|
|
50
|
+
|
|
51
|
+
### Component Architecture
|
|
52
|
+
[Server vs Client component usage assessment]
|
|
53
|
+
|
|
54
|
+
### Files Reviewed
|
|
55
|
+
[List files checked]
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
*Frontend quality audit*
|
|
59
|
+
|
|
60
|
+
<!-- REVIEW-FINDINGS-START -->
|
|
61
|
+
<!-- FINDING:FE-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
|
|
62
|
+
<!-- (add one FINDING line per issue found — include ALL confidence levels) -->
|
|
63
|
+
<!-- REVIEW-FINDINGS-END -->
|
|
64
|
+
EOF
|
|
65
|
+
)"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `FE`. See the Structured Findings Protocol section above for format rules.
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Coverage Matrix — FE Agent
|
|
72
|
+
|
|
73
|
+
| Defect Category | Check Item(s) | Status | Ref |
|
|
74
|
+
|----------------|---------------|--------|-----|
|
|
75
|
+
| Unnecessary 'use client' directive | Item 1 | COVERED | |
|
|
76
|
+
| Missing useEffect cleanup (memory leaks) | Item 2 | COVERED | |
|
|
77
|
+
| Unstable useCallback/useMemo dependencies | Item 3 | COVERED | |
|
|
78
|
+
| Missing loading/error states | Item 4 | COVERED | |
|
|
79
|
+
| Type safety (Zod schema / prop mismatch) | Item 5 | COVERED | |
|
|
80
|
+
| Missing component imports (shadcn) | Item 6 | COVERED | |
|
|
81
|
+
| XSS via dangerouslySetInnerHTML | Item 7 | COVERED | |
|
|
82
|
+
| Accessibility (labels, keyboard nav) | Item 8 | COVERED | |
|
|
83
|
+
| Performance (bundle size, dynamic imports) | Item 9 | COVERED | |
|
|
84
|
+
| Hook outside provider scope (crash on public routes) | Item 10 | COVERED | forge#381 |
|
|
85
|
+
| Server Component data leakage to client | — | GAP | |
|
|
86
|
+
| Next.js App Router caching pitfalls | — | GAP | |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|