forgedock 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +53 -8
  2. package/bin/batch-runner.mjs +339 -0
  3. package/bin/demo.mjs +92 -7
  4. package/bin/engine/phases.mjs +24 -2
  5. package/bin/engine/state.mjs +8 -3
  6. package/bin/engine-cli.mjs +177 -5
  7. package/bin/forgedock.mjs +409 -26
  8. package/bin/hooks/interactive-engine.mjs +509 -0
  9. package/bin/hooks/pre-tool-use.mjs +498 -0
  10. package/bin/hooks/subagent-stop-enforce.mjs +197 -0
  11. package/bin/journey.mjs +72 -14
  12. package/bin/registry.mjs +139 -0
  13. package/bin/report.mjs +447 -0
  14. package/bin/runner.mjs +70 -20
  15. package/bin/settings-hook.mjs +235 -1
  16. package/commands/adopt.md +4 -1
  17. package/commands/analytics.md +4 -1
  18. package/commands/audit-agents.md +110 -27
  19. package/commands/audit.md +20 -1
  20. package/commands/autopilot.md +518 -361
  21. package/commands/changelog.md +2 -1
  22. package/commands/ci-audit.md +2 -1
  23. package/commands/cleanup.md +161 -1
  24. package/commands/compat-audit.md +2 -1
  25. package/commands/deploy-info.md +58 -1
  26. package/commands/deploy-pr.md +485 -0
  27. package/commands/design-bench.md +5 -1
  28. package/commands/design-render-critique-loop.md +1 -1
  29. package/commands/diagnose.md +2 -1
  30. package/commands/explain.md +2 -1
  31. package/commands/fix-ci.md +577 -0
  32. package/commands/forge-stats.md +121 -2
  33. package/commands/forgedock-init.md +1 -1
  34. package/commands/geo-audit.md +3 -0
  35. package/commands/incident-response.md +2 -1
  36. package/commands/issue.md +23 -2
  37. package/commands/milestone.md +77 -12
  38. package/commands/optimize.md +2 -1
  39. package/commands/orchestrate/config.md +67 -0
  40. package/commands/orchestrate/phase-1-resolve.md +159 -0
  41. package/commands/orchestrate/phase-2-triage.md +126 -0
  42. package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
  43. package/commands/orchestrate/phase-3-dependency.md +591 -0
  44. package/commands/orchestrate/phase-4-execution.md +962 -0
  45. package/commands/orchestrate/phase-5-cleanup.md +47 -0
  46. package/commands/orchestrate/phase-6-report.md +198 -0
  47. package/commands/orchestrate/safety.md +62 -0
  48. package/commands/orchestrate.md +25 -2045
  49. package/commands/pipeline-health/config.md +34 -0
  50. package/commands/pipeline-health/phase-1-context.md +180 -0
  51. package/commands/pipeline-health/phase-2-metrics.md +1729 -0
  52. package/commands/pipeline-health/phase-3-analyze.md +204 -0
  53. package/commands/pipeline-health/phase-4-proposals.md +117 -0
  54. package/commands/pipeline-health/phase-5-report.md +284 -0
  55. package/commands/pipeline-health/phase-6-summary.md +52 -0
  56. package/commands/pipeline-health.md +25 -2401
  57. package/commands/pipeline-resume.md +24 -1
  58. package/commands/pipeline-status.md +65 -0
  59. package/commands/qa-sweep.md +4 -1
  60. package/commands/quality-gate.md +248 -10
  61. package/commands/recover-orphans.md +576 -0
  62. package/commands/replay.md +2 -1
  63. package/commands/review-pr-agents/api.md +135 -0
  64. package/commands/review-pr-agents/auth.md +137 -0
  65. package/commands/review-pr-agents/billing.md +101 -0
  66. package/commands/review-pr-agents/concurrency.md +145 -0
  67. package/commands/review-pr-agents/database.md +103 -0
  68. package/commands/review-pr-agents/frontend.md +89 -0
  69. package/commands/review-pr-agents/infra.md +385 -0
  70. package/commands/review-pr-agents/protocols.md +185 -0
  71. package/commands/review-pr-agents/scraper.md +185 -0
  72. package/commands/review-pr-agents/security.md +406 -0
  73. package/commands/review-pr-agents.md +45 -1722
  74. package/commands/review-pr-staging.md +196 -40
  75. package/commands/review-pr.md +591 -52
  76. package/commands/rollback.md +2 -1
  77. package/commands/scope.md +2 -1
  78. package/commands/security-audit.md +2 -1
  79. package/commands/signal-planner.md +623 -0
  80. package/commands/sync-ecosystem.md +1 -0
  81. package/commands/test-gate.md +17 -1
  82. package/commands/validate.md +2 -1
  83. package/commands/work-on/build/architect.md +28 -0
  84. package/commands/work-on/build/context.md +2 -0
  85. package/commands/work-on/build/implement.md +3 -1
  86. package/commands/work-on/build/validate.md +26 -7
  87. package/commands/work-on/build.md +163 -24
  88. package/commands/work-on/close.md +130 -3
  89. package/commands/work-on/decompose.md +19 -1
  90. package/commands/work-on/investigate.md +117 -2
  91. package/commands/work-on/review.md +24 -4
  92. package/commands/work-on-monolithic.md +7 -2
  93. package/commands/work-on.md +202 -4
  94. package/docs/BRAND.md +14 -7
  95. package/docs/CI.md +16 -2
  96. package/docs/CODEX.md +36 -1
  97. package/docs/CONFIG.md +5 -8
  98. package/docs/FORGE-PROTOCOL.md +15 -1064
  99. package/docs/anthropic-devrel-outreach.md +2 -2
  100. package/docs/articles/command-decomposition-token-savings.md +214 -0
  101. package/docs/articles/model-release-playbook.md +131 -0
  102. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
  103. package/docs/claude-breakpoints.json +75 -5
  104. package/docs/design/abc-benchmark.md +1 -1
  105. package/docs/design/design-spec-schema.md +1 -1
  106. package/docs/design/divergent-generation.md +1 -1
  107. package/docs/design/eval-gate-runbook.md +178 -0
  108. package/docs/design/show-hn-draft.md +26 -1
  109. package/docs/design/token-cost-baseline-1298.md +59 -0
  110. package/docs/eval/README.md +120 -0
  111. package/docs/eval/corpus/seed-v1.json +6 -0
  112. package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
  113. package/docs/site/annotations-explained.md +24 -0
  114. package/docs/site/command-learning-path.md +51 -14
  115. package/docs/site/command-reference.md +386 -111
  116. package/docs/site/for-companies.md +95 -0
  117. package/docs/site/forge-annotation-protocol.md +12 -256
  118. package/docs/site/getting-started.md +43 -4
  119. package/docs/site/github-is-the-memory.md +113 -0
  120. package/docs/site/how-it-works.md +3 -13
  121. package/docs/site/index.md +9 -1
  122. package/docs/spec/eval-run-result.md +147 -0
  123. package/docs/spec/forge-protocol-v1.md +441 -18
  124. package/docs/spec/label-state-machine.md +55 -0
  125. package/docs/spec/review-protocol.md +158 -0
  126. package/docs/spec-graph-schema.md +28 -0
  127. package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
  128. package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
  129. package/examples/forgedock-demo/README.md +41 -22
  130. package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
  131. package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
  132. package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
  133. package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
  134. package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
  135. package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
  136. package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
  137. package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
  138. package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
  139. package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
  140. package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
  141. package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
  142. package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
  143. package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
  144. package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
  145. package/examples/forgedock-demo/scripts/smoke.js +18 -1
  146. package/examples/forgedock-demo/src/db.js +36 -11
  147. package/examples/forgedock-demo/src/routes/notes.js +106 -9
  148. package/examples/forgedock-demo/src/server.js +4 -1
  149. package/package.json +3 -1
  150. package/packages/protocol/LICENSE +21 -0
  151. package/packages/protocol/src/cli.js +135 -0
  152. package/packages/protocol/src/emit.js +146 -0
  153. package/packages/protocol/src/index.js +43 -0
  154. package/packages/protocol/src/parse.js +254 -0
  155. package/packages/protocol/src/types.js +171 -0
  156. package/packages/protocol/src/validate.js +122 -0
  157. package/scripts/bench-topology-cost.mjs +372 -0
  158. package/scripts/check-command-docs-drift.sh +198 -0
  159. package/scripts/check-protocol-restatements.sh +176 -0
  160. package/scripts/check-registry/README.md +72 -0
  161. package/scripts/check-registry/manifest.json +6 -0
  162. package/scripts/code-index.sh +454 -0
  163. package/scripts/conformance-check.mjs +168 -0
  164. package/scripts/doctor-pipeline-state.sh +484 -0
  165. package/scripts/eval-gate-baseline.json +17 -0
  166. package/scripts/eval-gate-scorecard.mjs +242 -0
  167. package/scripts/eval-scorecard-aggregator.mjs +252 -0
  168. package/scripts/flaky-quarantine.sh +241 -0
  169. package/scripts/forge-annotation.sh +567 -0
  170. package/scripts/issue-dedup.sh +236 -0
  171. package/scripts/validate-annotation-node.mjs +233 -0
  172. package/scripts/worktree-lifecycle.sh +3 -3
  173. package/templates/devdocs/agent/using-forgedock.md +14 -0
  174. package/docs/site/.vitepress/config.mjs +0 -85
@@ -0,0 +1,135 @@
1
+ ---
2
+ install: internal
3
+ ---
4
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
+
7
+ # Agent: API Design & Consistency 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**: New or modified routers/routes, OR SDK/OpenAPI files changed (`sdk/`, `openapi*.json`, `openapi-versions/`)
14
+ **Type**: `general-purpose` | **Model**: `sonnet`
15
+
16
+ **Prompt template:**
17
+ ```
18
+ You are auditing PR #[PR_NUMBER] for API design consistency in [PROJECT_NAME].
19
+
20
+ ## Project API Conventions
21
+
22
+ [DOMAIN_CONTEXT]
23
+
24
+ If no API context is configured above, derive conventions from the changed files: read the main router/application entrypoint to understand registration patterns, and check neighboring endpoints for error format and naming conventions.
25
+
26
+ ## What to Check
27
+ 1. **Registration**: Is the new router registered in main.py?
28
+ 2. **Schema completeness**: Request/response models defined? Types correct?
29
+ 3. **Error handling**: Consistent error responses? HTTPException with proper status codes?
30
+ 4. **Endpoint naming**: RESTful conventions? Consistent with existing endpoints?
31
+ 5. **Query parameters**: Validated? Reasonable defaults?
32
+ 6. **Response format**: Consistent with other endpoints in the same domain?
33
+ 7. **External response type-safety**: Any code that consumes an external API response (HTTP client calls, SDK calls, third-party service responses) must guard against unexpected shapes. Flag direct dict/attribute access on an external response without a prior `isinstance` check or `None` guard — the response may be a dict, list, `None`, or an error string depending on the upstream service's behavior. Look for patterns like `data["key"]` or `data.field` immediately after `requests.get(...)`, `httpx.get(...)`, `await client.get(...)`, or similar calls without a guard. Exception: internal Pydantic-validated models are safe; only flag unvalidated external payloads.
34
+ 8. **Code generator field coverage**: Any function that builds a code snippet, SDK usage example, or serialized representation of a model must include ALL fields defined in the relevant Pydantic model or schema. Flag generators where the field list is hardcoded rather than derived from the model, or where the model has gained new fields that the generator does not emit. Search for functions named `generate_*`, `build_snippet_*`, `get_code_*`, `example_*`, or similar that reference a model class — compare their emitted fields against the model's field list.
35
+ 9. **New-field propagation**: When a PR adds a new field to a Pydantic model or database schema, verify that all downstream consumers are updated: serializers, snippet generators, SDK example builders, and any function that enumerates the model's fields. Search for all locations that reference the model class by name and check whether they handle the new field.
36
+
37
+ 10. **Cross-PR SDK/schema consistency** (MANDATORY when PR touches `sdk/`, `openapi*.json`, or `openapi-versions/`): Documentation PRs that update SDK or OpenAPI files must be checked against recently-merged PRs to the same base branch. A concurrent schema PR may have already changed the API behavior being documented — producing contradictory docs that tell users to use methods the API now rejects.
38
+
39
+ ```bash
40
+ # Get the PR's base branch
41
+ BASE=$(gh pr view [PR_NUMBER] --json baseRefName --jq '.baseRefName')
42
+
43
+ # Find PRs merged to this base in the last 48 hours
44
+ CUTOFF="$(date -u -d '48 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-48H +%Y-%m-%dT%H:%M:%SZ)"
45
+ RECENT_MERGED=$(gh pr list --base "$BASE" --state merged --limit 20 \
46
+ --json number,title,mergedAt,files \
47
+ 2>/dev/null | jq --arg cutoff "$CUTOFF" \
48
+ '.[] | select(.mergedAt > $cutoff) | {number, title, schema_files: [.files[].path | select(test("schemas?/|scrape\\.py|models\\.py"))]}' \
49
+ 2>/dev/null | head -40)
50
+
51
+ echo "Recent merged PRs to $BASE (last 48h): $RECENT_MERGED"
52
+
53
+ # For each recent PR that touched schema files, check if Literal types changed
54
+ for PR_NUM in $(echo "$RECENT_MERGED" | grep -oP '"number":\s*\K\d+'); do
55
+ SCHEMA_DIFF=$(gh pr diff "$PR_NUM" 2>/dev/null | grep -E '^\+.*Literal\[|^\-.*Literal\[' | grep -v '^\+\+\+\|^---')
56
+ if [ -n "$SCHEMA_DIFF" ]; then
57
+ echo "SCHEMA CHANGE in PR #$PR_NUM (already merged to $BASE):"
58
+ echo "$SCHEMA_DIFF"
59
+ echo "--- Verify this PR's SDK/OpenAPI docs are consistent with the above Literal change ---"
60
+ fi
61
+ done
62
+ ```
63
+
64
+ For each schema Literal change found in recently-merged PRs:
65
+ - Read the diff of THIS PR (PR [PR_NUMBER]) to see what values the SDK/OpenAPI files now document
66
+ - If this PR's SDK documentation still lists values that the schema change removed (e.g., SDK JSDoc says `DELETE` is supported but schema now only accepts `GET`/`POST`) → this is a **CONFIRMED HIGH** finding
67
+ - If this PR's SDK documentation says DELETE is "use with caution" but the schema already returns 422 for DELETE → this is a **CONFIRMED HIGH** finding (false reassurance)
68
+ - Pattern: `sdk/*/client.py` `_valid_methods` list, TypeScript JSDoc `@param` literals, `openapi*.json` enum arrays — all must be consistent with the API schema's current `Literal[...]` type
69
+
70
+ ## Cross-Reference
71
+ ```bash
72
+ # Discover router entrypoints (adapt to project structure)
73
+ API_SRC=$(git ls-files | grep -E "(router|route|endpoint|app)" | grep -E "\.(py|ts|js)$" | head -20)
74
+ # See how existing routers are structured
75
+ grep -rn "APIRouter\|include_router\|app\.include\|express\.Router\|createRouter" $API_SRC 2>/dev/null | head -20
76
+ # Find external response consumers (unguarded dict/attribute access after HTTP calls)
77
+ grep -rn "\.get\|\.post\|\.put\|\.delete\|httpx\|requests\.\|axios\." $API_SRC 2>/dev/null | grep -v "test_\|#" | head -20
78
+ # Find code/snippet generators
79
+ grep -rn "def generate_\|def build_snippet\|def get_code_\|def.*example\b" $(git ls-files | grep -E "\.(py|ts|js)$") 2>/dev/null | head -20
80
+ # Find all locations that reference a modified model class
81
+ grep -rn "{ModelClassName}" $(git ls-files | grep -E "\.(py|ts|js)$") 2>/dev/null | head -20
82
+ # SDK method lists (for cross-PR check #10)
83
+ grep -rn "_valid_methods\|Literal\[" sdk/ 2>/dev/null | head -20
84
+ grep -rn "Literal\[" $(git ls-files | grep -E "schema" | grep -E "\.(py|ts)$") 2>/dev/null | head -20
85
+ ```
86
+
87
+ ## Post Findings
88
+ ```bash
89
+ gh pr comment [PR_NUMBER] --body "$(cat <<'EOF'
90
+ ## API Design & Consistency Audit
91
+
92
+ ### New/Modified Endpoints
93
+ | Endpoint | Method | Registered? | Schema? | Auth? | Consistent? |
94
+ |----------|--------|-------------|---------|-------|-------------|
95
+ | /path | POST | Yes/No | Yes/No | Yes/No | Yes/No |
96
+
97
+ ### Consistency Issues
98
+ [Any deviations from established patterns]
99
+
100
+ ### Files Reviewed
101
+ [List files checked]
102
+
103
+ ---
104
+ *API design audit*
105
+
106
+ <!-- REVIEW-FINDINGS-START -->
107
+ <!-- FINDING:API-1|CONFIDENCE|SEVERITY|file.py:line|Summary -->
108
+ <!-- (add one FINDING line per issue found — include ALL confidence levels) -->
109
+ <!-- REVIEW-FINDINGS-END -->
110
+ EOF
111
+ )"
112
+ ```
113
+
114
+ **Structured Findings**: Include the structured findings block above at the end of your comment. Your prefix: `API`. See the Structured Findings Protocol section above for format rules.
115
+ ```
116
+
117
+ ### Coverage Matrix — API Agent
118
+
119
+ | Defect Category | Check Item(s) | Status | Ref |
120
+ |----------------|---------------|--------|-----|
121
+ | Unregistered router | Item 1 | COVERED | |
122
+ | Missing request/response schema | Item 2 | COVERED | |
123
+ | Inconsistent error handling | Item 3 | COVERED | |
124
+ | Non-RESTful endpoint naming | Item 4 | COVERED | |
125
+ | Unvalidated query parameters | Item 5 | COVERED | |
126
+ | Inconsistent response format | Item 6 | COVERED | |
127
+ | External response type-safety | Item 7 | COVERED | |
128
+ | Code generator field coverage drift | Item 8 | COVERED | |
129
+ | New-field propagation to consumers | Item 9 | COVERED | |
130
+ | Cross-PR SDK/schema consistency | Item 10 | COVERED | #190 |
131
+ | API versioning contract breaks (v1 vs v2) | — | GAP | |
132
+ | Pagination contract consistency | — | GAP | |
133
+
134
+ ---
135
+
@@ -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
+