docorbit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +660 -0
- package/apps/cli/bin/docorbit.js +8 -0
- package/apps/cli/src/commands/add.ts +44 -0
- package/apps/cli/src/commands/api.ts +38 -0
- package/apps/cli/src/commands/context.ts +47 -0
- package/apps/cli/src/commands/dashboard.ts +55 -0
- package/apps/cli/src/commands/diff.ts +30 -0
- package/apps/cli/src/commands/evaluate.ts +133 -0
- package/apps/cli/src/commands/examples.ts +39 -0
- package/apps/cli/src/commands/export.ts +89 -0
- package/apps/cli/src/commands/impact.ts +31 -0
- package/apps/cli/src/commands/init.ts +69 -0
- package/apps/cli/src/commands/inspect.ts +30 -0
- package/apps/cli/src/commands/mcp.ts +72 -0
- package/apps/cli/src/commands/pitfalls.ts +38 -0
- package/apps/cli/src/commands/recipes.ts +35 -0
- package/apps/cli/src/commands/search.ts +48 -0
- package/apps/cli/src/commands/update.ts +73 -0
- package/apps/cli/src/commands/verify.ts +48 -0
- package/apps/cli/src/formatters/colors.ts +23 -0
- package/apps/cli/src/formatters/inspection.ts +102 -0
- package/apps/cli/src/formatters/knowledge.ts +272 -0
- package/apps/cli/src/formatters/retrieval.ts +74 -0
- package/apps/cli/src/formatters/terminal.ts +6 -0
- package/apps/cli/src/formatters/verification.ts +126 -0
- package/apps/cli/src/index.ts +409 -0
- package/bin/docorbit.js +8 -0
- package/package.json +46 -0
- package/packages/core/src/dashboard/server.ts +314 -0
- package/packages/core/src/dashboard/ui.ts +586 -0
- package/packages/core/src/implementation-service.ts +451 -0
- package/packages/core/src/index.ts +7 -0
- package/packages/core/src/inspector.ts +71 -0
- package/packages/core/src/pipeline.ts +331 -0
- package/packages/crawler/src/config.ts +12 -0
- package/packages/crawler/src/fetcher.ts +185 -0
- package/packages/crawler/src/index.ts +2 -0
- package/packages/discovery/src/index.ts +31 -0
- package/packages/discovery/src/provider.ts +47 -0
- package/packages/discovery/src/providers/generic.ts +98 -0
- package/packages/discovery/src/providers/github.ts +61 -0
- package/packages/discovery/src/providers/llms-txt.ts +73 -0
- package/packages/discovery/src/providers/markdown.ts +48 -0
- package/packages/discovery/src/providers/openapi.ts +91 -0
- package/packages/discovery/src/providers/sitemap.ts +62 -0
- package/packages/discovery/src/providers/skill.ts +54 -0
- package/packages/discovery/src/ranker.ts +123 -0
- package/packages/evaluation/src/dataset.ts +963 -0
- package/packages/evaluation/src/index.ts +8 -0
- package/packages/evaluation/src/runner.ts +241 -0
- package/packages/evaluation/src/strategies/context7-runner.ts +269 -0
- package/packages/evaluation/src/strategies/docorbit-runner.ts +228 -0
- package/packages/evaluation/src/strategies/firecrawl-runner.ts +172 -0
- package/packages/evaluation/src/strategies/web-search-runner.ts +194 -0
- package/packages/evaluation/src/types.ts +34 -0
- package/packages/evaluation/src/version-matcher.ts +73 -0
- package/packages/export/src/agents-md.ts +200 -0
- package/packages/export/src/claude-md.ts +141 -0
- package/packages/export/src/docs-map.ts +150 -0
- package/packages/export/src/index.ts +6 -0
- package/packages/export/src/llms-txt.ts +96 -0
- package/packages/export/src/service.ts +250 -0
- package/packages/export/src/skill-md.ts +128 -0
- package/packages/mcp/src/index.ts +46 -0
- package/packages/mcp/src/resources/index.ts +189 -0
- package/packages/mcp/src/server.ts +278 -0
- package/packages/mcp/src/tools/analyze-impact.ts +74 -0
- package/packages/mcp/src/tools/check-api.ts +86 -0
- package/packages/mcp/src/tools/diff-docs.ts +68 -0
- package/packages/mcp/src/tools/export-context.ts +73 -0
- package/packages/mcp/src/tools/find-api.ts +99 -0
- package/packages/mcp/src/tools/find-example.ts +100 -0
- package/packages/mcp/src/tools/find-pitfall.ts +94 -0
- package/packages/mcp/src/tools/find-recipe.ts +98 -0
- package/packages/mcp/src/tools/get-doc.ts +130 -0
- package/packages/mcp/src/tools/get-docs-map.ts +64 -0
- package/packages/mcp/src/tools/get-version.ts +118 -0
- package/packages/mcp/src/tools/implementation-context.ts +88 -0
- package/packages/mcp/src/tools/index.ts +59 -0
- package/packages/mcp/src/tools/list-sources.ts +85 -0
- package/packages/mcp/src/tools/search-docs.ts +123 -0
- package/packages/mcp/src/tools/types.ts +28 -0
- package/packages/mcp/src/transports/http.ts +256 -0
- package/packages/mcp/src/transports/stdio.ts +105 -0
- package/packages/mcp/src/transports/types.ts +6 -0
- package/packages/mcp/src/types.ts +102 -0
- package/packages/normalizer/src/example-indexer.ts +240 -0
- package/packages/normalizer/src/html.ts +253 -0
- package/packages/normalizer/src/index.ts +8 -0
- package/packages/normalizer/src/llms.ts +83 -0
- package/packages/normalizer/src/openapi/endpoint-parser.ts +406 -0
- package/packages/normalizer/src/openapi/schema-resolver.ts +111 -0
- package/packages/normalizer/src/openapi.ts +2 -0
- package/packages/normalizer/src/page.ts +184 -0
- package/packages/normalizer/src/pitfall-extractor.ts +190 -0
- package/packages/normalizer/src/slicer.ts +455 -0
- package/packages/retrieval/src/engine.ts +120 -0
- package/packages/retrieval/src/index.ts +7 -0
- package/packages/retrieval/src/intent.ts +43 -0
- package/packages/retrieval/src/packer.ts +145 -0
- package/packages/retrieval/src/recipe-engine.ts +313 -0
- package/packages/retrieval/src/scorer.ts +139 -0
- package/packages/retrieval/src/weights.ts +31 -0
- package/packages/security/src/annotations.ts +112 -0
- package/packages/security/src/index.ts +2 -0
- package/packages/security/src/ssrf.ts +153 -0
- package/packages/shared/src/errors.ts +53 -0
- package/packages/shared/src/hashing.ts +23 -0
- package/packages/shared/src/index.ts +3 -0
- package/packages/shared/src/types.ts +881 -0
- package/packages/storage/src/db.ts +72 -0
- package/packages/storage/src/index.ts +11 -0
- package/packages/storage/src/interfaces.ts +115 -0
- package/packages/storage/src/repositories/api-repository.ts +219 -0
- package/packages/storage/src/repositories/chunk-repository.ts +316 -0
- package/packages/storage/src/repositories/example-repository.ts +206 -0
- package/packages/storage/src/repositories/page-repository.ts +205 -0
- package/packages/storage/src/repositories/pitfall-repository.ts +188 -0
- package/packages/storage/src/repositories/source-repository.ts +205 -0
- package/packages/storage/src/repository.ts +256 -0
- package/packages/storage/src/schema.ts +269 -0
- package/packages/storage/src/search-tokens.ts +28 -0
- package/packages/verification/src/diff-engine.ts +258 -0
- package/packages/verification/src/extractor.ts +339 -0
- package/packages/verification/src/impact-scanner.ts +203 -0
- package/packages/verification/src/index.ts +5 -0
- package/packages/verification/src/services.ts +238 -0
- package/packages/verification/src/verifier.ts +375 -0
- package/packages/workspace/src/detector.ts +143 -0
- package/packages/workspace/src/ecosystems/cargo.ts +84 -0
- package/packages/workspace/src/ecosystems/composer.ts +42 -0
- package/packages/workspace/src/ecosystems/go.ts +54 -0
- package/packages/workspace/src/ecosystems/index.ts +34 -0
- package/packages/workspace/src/ecosystems/maven.ts +34 -0
- package/packages/workspace/src/ecosystems/npm.ts +83 -0
- package/packages/workspace/src/ecosystems/pub.ts +40 -0
- package/packages/workspace/src/ecosystems/pypi.ts +100 -0
- package/packages/workspace/src/ecosystems/rubygems.ts +30 -0
- package/packages/workspace/src/ecosystems/types.ts +18 -0
- package/packages/workspace/src/index.ts +5 -0
- package/packages/workspace/src/lockfile.ts +194 -0
- package/packages/workspace/src/resolver.ts +234 -0
- package/packages/workspace/src/semver.ts +259 -0
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
import type { BenchmarkTaskDef } from './types.ts';
|
|
2
|
+
|
|
3
|
+
export const BENCHMARK_DATASET: BenchmarkTaskDef[] = [
|
|
4
|
+
// ==========================================
|
|
5
|
+
// TRAIN / DEVELOPMENT SPLIT (4 tasks)
|
|
6
|
+
// ==========================================
|
|
7
|
+
{
|
|
8
|
+
id: 'train_nextjs_14_route_sync',
|
|
9
|
+
split: 'train',
|
|
10
|
+
title: 'Next.js 14 Synchronous Dynamic Route Parameters',
|
|
11
|
+
ecosystem: 'typescript',
|
|
12
|
+
library: 'next',
|
|
13
|
+
targetVersion: '14.2.5',
|
|
14
|
+
taskPrompt: 'Implement dynamic route parameter handling in Next.js 14 App Router GET handler',
|
|
15
|
+
docsUrl: 'https://nextjs.org/docs/14/app/api-reference/file-conventions/route',
|
|
16
|
+
workspaceFiles: {
|
|
17
|
+
'package.json': JSON.stringify({
|
|
18
|
+
name: 'my-next-app',
|
|
19
|
+
dependencies: {
|
|
20
|
+
next: '^14.2.0',
|
|
21
|
+
react: '^18.2.0',
|
|
22
|
+
},
|
|
23
|
+
}, null, 2),
|
|
24
|
+
},
|
|
25
|
+
docs: [
|
|
26
|
+
{
|
|
27
|
+
url: 'https://nextjs.org/docs/14/routing',
|
|
28
|
+
title: 'Next.js 14 App Router: Route Handlers and Params',
|
|
29
|
+
version: '14.2.5',
|
|
30
|
+
content: `# Next.js 14 Route Handlers
|
|
31
|
+
In Next.js 14, Route Handlers receive context with synchronous parameters:
|
|
32
|
+
\`export async function GET(request: Request, { params }: { params: { id: string } })\`.
|
|
33
|
+
The params object is a plain synchronous object: \`const id = params.id;\`.
|
|
34
|
+
Do not await params in Next.js 14.`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
url: 'https://nextjs.org/docs/15/routing',
|
|
38
|
+
title: 'Next.js 15 Asynchronous Route Parameters Breaking Change',
|
|
39
|
+
version: '15.0.0',
|
|
40
|
+
content: `# Next.js 15 Async Dynamic Route Parameters
|
|
41
|
+
Breaking Change: In Next.js 15, route handler parameters are asynchronous Promises.
|
|
42
|
+
Must use: \`const { id } = await params;\`. Accessing properties synchronously causes a runtime warning/error.`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
groundTruth: {
|
|
46
|
+
expectedVersion: '14.2.5',
|
|
47
|
+
expectedApi: {
|
|
48
|
+
symbol: 'GET',
|
|
49
|
+
path: '/api/users/[id]',
|
|
50
|
+
},
|
|
51
|
+
fatalPitfalls: ['await params in Next.js 14 is unnecessary and params is synchronous'],
|
|
52
|
+
validCode: `export async function GET(request: Request, { params }: { params: { id: string } }) {
|
|
53
|
+
const userId = params.id;
|
|
54
|
+
return Response.json({ id: userId });
|
|
55
|
+
}`,
|
|
56
|
+
invalidCode: {
|
|
57
|
+
snippet: `export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
58
|
+
const { id } = await params;
|
|
59
|
+
return Response.json({ id });
|
|
60
|
+
}`,
|
|
61
|
+
expectedRule: 'version_mismatch',
|
|
62
|
+
},
|
|
63
|
+
dynamicCode: `export async function GET(req: Request, ctx: any) {
|
|
64
|
+
const field = eval("ctx.params.id");
|
|
65
|
+
return Response.json({ field });
|
|
66
|
+
}`,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
{
|
|
71
|
+
id: 'train_stripe_v1_charges',
|
|
72
|
+
split: 'train',
|
|
73
|
+
title: 'Stripe Legacy Charges Direct Payment',
|
|
74
|
+
ecosystem: 'javascript',
|
|
75
|
+
library: 'stripe',
|
|
76
|
+
targetVersion: '12.18.0',
|
|
77
|
+
taskPrompt: 'Create a direct credit card charge with Stripe API legacy charges endpoint',
|
|
78
|
+
docsUrl: 'https://stripe.com/docs/api/charges/create',
|
|
79
|
+
workspaceFiles: {
|
|
80
|
+
'package.json': JSON.stringify({
|
|
81
|
+
name: 'legacy-store',
|
|
82
|
+
dependencies: {
|
|
83
|
+
stripe: '^12.0.0',
|
|
84
|
+
},
|
|
85
|
+
}, null, 2),
|
|
86
|
+
},
|
|
87
|
+
docs: [
|
|
88
|
+
{
|
|
89
|
+
url: 'https://stripe.com/docs/api/charges',
|
|
90
|
+
title: 'Stripe API: Charges Resource',
|
|
91
|
+
version: '12.18.0',
|
|
92
|
+
content: `# Charges API
|
|
93
|
+
POST /v1/charges
|
|
94
|
+
Creates a new charge object.
|
|
95
|
+
Required parameters:
|
|
96
|
+
- amount: integer (required)
|
|
97
|
+
- currency: string (required)
|
|
98
|
+
- source: string (required token or card ID)`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
groundTruth: {
|
|
102
|
+
expectedVersion: '12.18.0',
|
|
103
|
+
expectedApi: {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
path: '/v1/charges',
|
|
106
|
+
requiredParams: ['amount', 'currency'],
|
|
107
|
+
},
|
|
108
|
+
fatalPitfalls: ['Do not omit amount or currency when creating a charge'],
|
|
109
|
+
validCode: `const charge = await stripe.charges.create({
|
|
110
|
+
amount: 2000,
|
|
111
|
+
currency: 'usd',
|
|
112
|
+
source: 'tok_visa'
|
|
113
|
+
});`,
|
|
114
|
+
invalidCode: {
|
|
115
|
+
snippet: `const charge = await stripe.charges.create({
|
|
116
|
+
currency: 'usd',
|
|
117
|
+
source: 'tok_visa'
|
|
118
|
+
});`,
|
|
119
|
+
expectedRule: 'required_parameters',
|
|
120
|
+
},
|
|
121
|
+
dynamicCode: `const fn = stripe['charges']['create'];
|
|
122
|
+
await fn({ amount: 1000, currency: 'usd' });`,
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
{
|
|
127
|
+
id: 'train_pydantic_v1_validator',
|
|
128
|
+
split: 'train',
|
|
129
|
+
title: 'Pydantic v1 Custom Field Validator',
|
|
130
|
+
ecosystem: 'python',
|
|
131
|
+
library: 'pydantic',
|
|
132
|
+
targetVersion: '1.10.12',
|
|
133
|
+
taskPrompt: 'Validate age field using Pydantic v1 validator decorator',
|
|
134
|
+
docsUrl: 'https://docs.pydantic.dev/1.10/usage/validators/',
|
|
135
|
+
workspaceFiles: {
|
|
136
|
+
'pyproject.toml': `[tool.poetry.dependencies]\npython = "^3.10"\npydantic = "^1.10.0"\n`,
|
|
137
|
+
},
|
|
138
|
+
docs: [
|
|
139
|
+
{
|
|
140
|
+
url: 'https://docs.pydantic.dev/1.10/usage/validators/',
|
|
141
|
+
title: 'Pydantic 1.10 Validators',
|
|
142
|
+
version: '1.10.12',
|
|
143
|
+
content: `# Pydantic 1.x Validators
|
|
144
|
+
Use @validator decorator with pre=True/False.
|
|
145
|
+
Example:
|
|
146
|
+
\`\`\`python
|
|
147
|
+
from pydantic import BaseModel, validator
|
|
148
|
+
class User(BaseModel):
|
|
149
|
+
age: int
|
|
150
|
+
@validator('age')
|
|
151
|
+
def check_age(cls, v):
|
|
152
|
+
if v < 0: raise ValueError('Age cannot be negative')
|
|
153
|
+
return v
|
|
154
|
+
\`\`\``,
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
groundTruth: {
|
|
158
|
+
expectedVersion: '1.10.12',
|
|
159
|
+
expectedApi: {
|
|
160
|
+
symbol: 'validator',
|
|
161
|
+
},
|
|
162
|
+
fatalPitfalls: ['@field_validator is not supported in Pydantic 1.x; use @validator'],
|
|
163
|
+
validCode: `from pydantic import BaseModel, validator
|
|
164
|
+
class User(BaseModel):
|
|
165
|
+
age: int
|
|
166
|
+
@validator('age')
|
|
167
|
+
def validate_age(cls, v):
|
|
168
|
+
if v < 0: raise ValueError('invalid age')
|
|
169
|
+
return v`,
|
|
170
|
+
invalidCode: {
|
|
171
|
+
snippet: `from pydantic import BaseModel, field_validator
|
|
172
|
+
class User(BaseModel):
|
|
173
|
+
age: int
|
|
174
|
+
@field_validator('age')
|
|
175
|
+
@classmethod
|
|
176
|
+
def validate_age(cls, v): return v`,
|
|
177
|
+
expectedRule: 'version_mismatch',
|
|
178
|
+
},
|
|
179
|
+
dynamicCode: `def make_validator():
|
|
180
|
+
return getattr(__import__('pydantic'), 'validator')('age')`,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
{
|
|
185
|
+
id: 'train_fastapi_095_sync_dep',
|
|
186
|
+
split: 'train',
|
|
187
|
+
title: 'FastAPI 0.95 Database Dependency Injection',
|
|
188
|
+
ecosystem: 'python',
|
|
189
|
+
library: 'fastapi',
|
|
190
|
+
targetVersion: '0.95.2',
|
|
191
|
+
taskPrompt: 'Inject database session in FastAPI 0.95 endpoint using Depends',
|
|
192
|
+
docsUrl: 'https://fastapi.tiangolo.com/tutorial/dependencies/',
|
|
193
|
+
workspaceFiles: {
|
|
194
|
+
'pyproject.toml': `[tool.poetry.dependencies]\npython = "^3.10"\nfastapi = "^0.95.0"\n`,
|
|
195
|
+
},
|
|
196
|
+
docs: [
|
|
197
|
+
{
|
|
198
|
+
url: 'https://fastapi.tiangolo.com/0.95/dependencies/',
|
|
199
|
+
title: 'FastAPI Dependencies with yield',
|
|
200
|
+
version: '0.95.2',
|
|
201
|
+
content: `# FastAPI Dependencies
|
|
202
|
+
Use \`Depends(get_db)\` where get_db yields a database session and closes it in a finally block.`,
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
groundTruth: {
|
|
206
|
+
expectedVersion: '0.95.2',
|
|
207
|
+
expectedApi: {
|
|
208
|
+
symbol: 'Depends',
|
|
209
|
+
},
|
|
210
|
+
fatalPitfalls: ['Ensure DB connection closes after yield in generator dependency'],
|
|
211
|
+
validCode: `from fastapi import FastAPI, Depends
|
|
212
|
+
app = FastAPI()
|
|
213
|
+
def get_db():
|
|
214
|
+
db = SessionLocal()
|
|
215
|
+
try: yield db
|
|
216
|
+
finally: db.close()
|
|
217
|
+
@app.get('/items')
|
|
218
|
+
def read_items(db = Depends(get_db)):
|
|
219
|
+
return db.query(Item).all()`,
|
|
220
|
+
invalidCode: {
|
|
221
|
+
snippet: `@app.get('/items')
|
|
222
|
+
def read_items(db = get_db()): # Missing Depends wrapper
|
|
223
|
+
return db.query(Item).all()`,
|
|
224
|
+
expectedRule: 'parameter_misconfiguration',
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
// ==========================================
|
|
230
|
+
// HELD-OUT EVALUATION SPLIT (6 tasks)
|
|
231
|
+
// ==========================================
|
|
232
|
+
{
|
|
233
|
+
id: 'eval_nextjs_15_async_params',
|
|
234
|
+
split: 'eval',
|
|
235
|
+
title: 'Next.js 15 Async Dynamic Route Parameters Breaking Change',
|
|
236
|
+
ecosystem: 'typescript',
|
|
237
|
+
library: 'next',
|
|
238
|
+
targetVersion: '15.0.3',
|
|
239
|
+
taskPrompt: 'Implement dynamic route parameter handling in Next.js 15 App Router GET route handler',
|
|
240
|
+
docsUrl: 'https://nextjs.org/docs/app/api-reference/file-conventions/route',
|
|
241
|
+
workspaceFiles: {
|
|
242
|
+
'package.json': JSON.stringify({
|
|
243
|
+
name: 'modern-next15',
|
|
244
|
+
dependencies: {
|
|
245
|
+
next: '^15.0.0',
|
|
246
|
+
react: '^19.0.0',
|
|
247
|
+
},
|
|
248
|
+
}, null, 2),
|
|
249
|
+
},
|
|
250
|
+
docs: [
|
|
251
|
+
{
|
|
252
|
+
url: 'https://nextjs.org/docs/15/routing',
|
|
253
|
+
title: 'Next.js 15 Asynchronous Route Parameters',
|
|
254
|
+
version: '15.0.3',
|
|
255
|
+
content: `# Next.js 15 Dynamic Route Parameters
|
|
256
|
+
Breaking change in Next.js 15: \`params\` in Page and Route Handlers is now an asynchronous Promise.
|
|
257
|
+
You must use: \`const { id } = await params;\`.
|
|
258
|
+
Accessing \`params.id\` directly without await is deprecated and throws runtime errors in production.`,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
groundTruth: {
|
|
262
|
+
expectedVersion: '15.0.3',
|
|
263
|
+
expectedApi: {
|
|
264
|
+
symbol: 'GET',
|
|
265
|
+
path: '/api/items/[id]',
|
|
266
|
+
},
|
|
267
|
+
fatalPitfalls: ['Do not access params synchronously in Next.js 15; it is a Promise that must be awaited'],
|
|
268
|
+
validCode: `export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
269
|
+
const { id } = await params;
|
|
270
|
+
return Response.json({ id });
|
|
271
|
+
}`,
|
|
272
|
+
invalidCode: {
|
|
273
|
+
snippet: `export async function GET(request: Request, { params }: { params: { id: string } }) {
|
|
274
|
+
const id = params.id;
|
|
275
|
+
return Response.json({ id });
|
|
276
|
+
}`,
|
|
277
|
+
expectedRule: 'version_mismatch',
|
|
278
|
+
},
|
|
279
|
+
dynamicCode: `export async function GET(req: Request, ctx: any) {
|
|
280
|
+
const p = await (ctx['params']);
|
|
281
|
+
return Response.json(p);
|
|
282
|
+
}`,
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
{
|
|
287
|
+
id: 'eval_stripe_payment_intents_2024',
|
|
288
|
+
split: 'eval',
|
|
289
|
+
title: 'Stripe Modern Payment Intents Creation',
|
|
290
|
+
ecosystem: 'typescript',
|
|
291
|
+
library: 'stripe',
|
|
292
|
+
targetVersion: '16.12.0',
|
|
293
|
+
taskPrompt: 'Create a Stripe Payment Intent with automatic payment methods enabled',
|
|
294
|
+
docsUrl: 'https://stripe.com/docs/api/payment_intents/create',
|
|
295
|
+
workspaceFiles: {
|
|
296
|
+
'package.json': JSON.stringify({
|
|
297
|
+
name: 'modern-payments',
|
|
298
|
+
dependencies: {
|
|
299
|
+
stripe: '^16.0.0',
|
|
300
|
+
},
|
|
301
|
+
}, null, 2),
|
|
302
|
+
},
|
|
303
|
+
docs: [
|
|
304
|
+
{
|
|
305
|
+
url: 'https://stripe.com/docs/api/payment_intents',
|
|
306
|
+
title: 'Stripe API: Payment Intents Resource',
|
|
307
|
+
version: '16.12.0',
|
|
308
|
+
content: `# Payment Intents API
|
|
309
|
+
POST /v1/payment_intents
|
|
310
|
+
Creates a PaymentIntent object.
|
|
311
|
+
Required parameters:
|
|
312
|
+
- amount: integer (required)
|
|
313
|
+
- currency: string (required)
|
|
314
|
+
Recommended:
|
|
315
|
+
- automatic_payment_methods: object with enabled: boolean
|
|
316
|
+
Notice: Direct charges via /v1/charges are deprecated for standard checkout.`,
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
groundTruth: {
|
|
320
|
+
expectedVersion: '16.12.0',
|
|
321
|
+
expectedApi: {
|
|
322
|
+
method: 'POST',
|
|
323
|
+
path: '/v1/payment_intents',
|
|
324
|
+
requiredParams: ['amount', 'currency'],
|
|
325
|
+
},
|
|
326
|
+
fatalPitfalls: ['Do not use /v1/charges in modern Stripe integrations; use /v1/payment_intents'],
|
|
327
|
+
validCode: `const intent = await stripe.paymentIntents.create({
|
|
328
|
+
amount: 5000,
|
|
329
|
+
currency: 'usd',
|
|
330
|
+
automatic_payment_methods: { enabled: true }
|
|
331
|
+
});`,
|
|
332
|
+
invalidCode: {
|
|
333
|
+
snippet: `const intent = await stripe.paymentIntents.create({
|
|
334
|
+
amount: 5000
|
|
335
|
+
});`,
|
|
336
|
+
expectedRule: 'required_parameters',
|
|
337
|
+
},
|
|
338
|
+
dynamicCode: `const res = await stripe[Math.random() > 0 ? 'paymentIntents' : 'charges'].create({ amount: 100 });`,
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
{
|
|
343
|
+
id: 'eval_pydantic_v2_field_validator',
|
|
344
|
+
split: 'eval',
|
|
345
|
+
title: 'Pydantic v2 Migration: field_validator Replacement',
|
|
346
|
+
ecosystem: 'python',
|
|
347
|
+
library: 'pydantic',
|
|
348
|
+
targetVersion: '2.6.0',
|
|
349
|
+
taskPrompt: 'Implement custom field validation for email field in Pydantic v2',
|
|
350
|
+
docsUrl: 'https://docs.pydantic.dev/latest/concepts/validators/',
|
|
351
|
+
workspaceFiles: {
|
|
352
|
+
'pyproject.toml': `[tool.poetry.dependencies]\npython = "^3.11"\npydantic = "^2.6.0"\n`,
|
|
353
|
+
},
|
|
354
|
+
docs: [
|
|
355
|
+
{
|
|
356
|
+
url: 'https://docs.pydantic.dev/2.6/migration/',
|
|
357
|
+
title: 'Pydantic 2.6 Migration Guide: @validator to @field_validator',
|
|
358
|
+
version: '2.6.0',
|
|
359
|
+
content: `# Pydantic V2 Migration
|
|
360
|
+
Breaking change: @validator is deprecated in V2.
|
|
361
|
+
Replace with @field_validator('fieldname', mode='before'|'after') combined with @classmethod.
|
|
362
|
+
Example:
|
|
363
|
+
\`\`\`python
|
|
364
|
+
from pydantic import BaseModel, field_validator
|
|
365
|
+
class User(BaseModel):
|
|
366
|
+
email: str
|
|
367
|
+
@field_validator('email', mode='before')
|
|
368
|
+
@classmethod
|
|
369
|
+
def lower_email(cls, v: str) -> str:
|
|
370
|
+
return v.lower()
|
|
371
|
+
\`\`\``,
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
groundTruth: {
|
|
375
|
+
expectedVersion: '2.6.0',
|
|
376
|
+
expectedApi: {
|
|
377
|
+
symbol: 'field_validator',
|
|
378
|
+
},
|
|
379
|
+
fatalPitfalls: ['@validator is removed/deprecated in Pydantic v2; use @field_validator with @classmethod'],
|
|
380
|
+
validCode: `from pydantic import BaseModel, field_validator
|
|
381
|
+
class User(BaseModel):
|
|
382
|
+
email: str
|
|
383
|
+
@field_validator('email', mode='before')
|
|
384
|
+
@classmethod
|
|
385
|
+
def validate_email(cls, v: str) -> str:
|
|
386
|
+
if '@' not in v: raise ValueError('invalid email')
|
|
387
|
+
return v.lower()`,
|
|
388
|
+
invalidCode: {
|
|
389
|
+
snippet: `from pydantic import BaseModel, validator
|
|
390
|
+
class User(BaseModel):
|
|
391
|
+
email: str
|
|
392
|
+
@validator('email') # Deprecated in v2
|
|
393
|
+
def validate_email(cls, v): return v`,
|
|
394
|
+
expectedRule: 'deprecation',
|
|
395
|
+
},
|
|
396
|
+
dynamicCode: `validator_decorator = getattr(__import__('pydantic'), 'field_validator')`,
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
{
|
|
401
|
+
id: 'eval_fastapi_100_lifespan',
|
|
402
|
+
split: 'eval',
|
|
403
|
+
title: 'FastAPI 0.100+ Lifespan Handler Deprecation of on_event',
|
|
404
|
+
ecosystem: 'python',
|
|
405
|
+
library: 'fastapi',
|
|
406
|
+
targetVersion: '0.110.0',
|
|
407
|
+
taskPrompt: 'Manage application startup and shutdown events using FastAPI modern lifespan context manager',
|
|
408
|
+
docsUrl: 'https://fastapi.tiangolo.com/advanced/events/',
|
|
409
|
+
workspaceFiles: {
|
|
410
|
+
'pyproject.toml': `[tool.poetry.dependencies]\npython = "^3.11"\nfastapi = "^0.110.0"\n`,
|
|
411
|
+
},
|
|
412
|
+
docs: [
|
|
413
|
+
{
|
|
414
|
+
url: 'https://fastapi.tiangolo.com/advanced/events/',
|
|
415
|
+
title: 'FastAPI Lifespan Events',
|
|
416
|
+
version: '0.110.0',
|
|
417
|
+
content: `# FastAPI Lifespan Events
|
|
418
|
+
In FastAPI 0.100+, \`@app.on_event('startup')\` and \`@app.on_event('shutdown')\` are deprecated.
|
|
419
|
+
Use the \`lifespan\` async context manager parameter on \`FastAPI(lifespan=...)\`.
|
|
420
|
+
Example:
|
|
421
|
+
\`\`\`python
|
|
422
|
+
from contextlib import asynccontextmanager
|
|
423
|
+
from fastapi import FastAPI
|
|
424
|
+
@asynccontextmanager
|
|
425
|
+
async def lifespan(app: FastAPI):
|
|
426
|
+
yield
|
|
427
|
+
app = FastAPI(lifespan=lifespan)
|
|
428
|
+
\`\`\``,
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
groundTruth: {
|
|
432
|
+
expectedVersion: '0.110.0',
|
|
433
|
+
expectedApi: {
|
|
434
|
+
symbol: 'lifespan',
|
|
435
|
+
},
|
|
436
|
+
fatalPitfalls: ['@app.on_event is deprecated; use asynccontextmanager lifespan parameter'],
|
|
437
|
+
validCode: `from contextlib import asynccontextmanager
|
|
438
|
+
from fastapi import FastAPI
|
|
439
|
+
|
|
440
|
+
@asynccontextmanager
|
|
441
|
+
async def lifespan(app: FastAPI):
|
|
442
|
+
# Startup tasks
|
|
443
|
+
yield
|
|
444
|
+
# Shutdown tasks
|
|
445
|
+
|
|
446
|
+
app = FastAPI(lifespan=lifespan)`,
|
|
447
|
+
invalidCode: {
|
|
448
|
+
snippet: `from fastapi import FastAPI
|
|
449
|
+
app = FastAPI()
|
|
450
|
+
@app.on_event('startup') # Deprecated in FastAPI 0.100+
|
|
451
|
+
async def startup_event(): pass`,
|
|
452
|
+
expectedRule: 'deprecation',
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
|
|
457
|
+
{
|
|
458
|
+
id: 'eval_tokio_postgres_07',
|
|
459
|
+
split: 'eval',
|
|
460
|
+
title: 'Tokio-Postgres 0.7 Asynchronous Connection and Query Execution',
|
|
461
|
+
ecosystem: 'rust',
|
|
462
|
+
library: 'tokio-postgres',
|
|
463
|
+
targetVersion: '0.7.10',
|
|
464
|
+
taskPrompt: 'Connect asynchronously to Postgres and spawn the connection worker task in Tokio',
|
|
465
|
+
docsUrl: 'https://docs.rs/tokio-postgres/0.7.10/tokio_postgres/',
|
|
466
|
+
workspaceFiles: {
|
|
467
|
+
'Cargo.toml': `[package]\nname = "rust-pg"\nversion = "0.1.0"\n\n[dependencies]\ntokio = { version = "1.36", features = ["full"] }\ntokio-postgres = "0.7.10"\n`,
|
|
468
|
+
},
|
|
469
|
+
docs: [
|
|
470
|
+
{
|
|
471
|
+
url: 'https://docs.rs/tokio-postgres/0.7.10/tokio_postgres/',
|
|
472
|
+
title: 'tokio_postgres 0.7.10 Documentation',
|
|
473
|
+
version: '0.7.10',
|
|
474
|
+
content: `# tokio_postgres
|
|
475
|
+
The connect function returns a client and a Connection object.
|
|
476
|
+
The connection object must be spawned onto an executor (tokio::spawn) to drive network I/O.
|
|
477
|
+
Example:
|
|
478
|
+
\`\`\`rust
|
|
479
|
+
let (client, connection) = tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
|
|
480
|
+
tokio::spawn(async move {
|
|
481
|
+
if let Err(e) = connection.await {
|
|
482
|
+
eprintln!("connection error: {}", e);
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
\`\`\``,
|
|
486
|
+
},
|
|
487
|
+
],
|
|
488
|
+
groundTruth: {
|
|
489
|
+
expectedVersion: '0.7.10',
|
|
490
|
+
expectedApi: {
|
|
491
|
+
symbol: 'connect',
|
|
492
|
+
},
|
|
493
|
+
fatalPitfalls: ['Connection object must be spawned onto Tokio runtime or queries will hang indefinitely'],
|
|
494
|
+
validCode: `let (client, connection) = tokio_postgres::connect("host=localhost user=postgres", tokio_postgres::NoTls).await?;
|
|
495
|
+
tokio::spawn(async move {
|
|
496
|
+
if let Err(e) = connection.await {
|
|
497
|
+
eprintln!("connection error: {}", e);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
let rows = client.query("SELECT id, name FROM users", &[]).await?;`,
|
|
501
|
+
invalidCode: {
|
|
502
|
+
snippet: `let (client, connection) = tokio_postgres::connect("host=localhost user=postgres", tokio_postgres::NoTls).await?;
|
|
503
|
+
// Forgot tokio::spawn(connection) - queries will block indefinitely!
|
|
504
|
+
let rows = client.query("SELECT id, name FROM users", &[]).await?;`,
|
|
505
|
+
expectedRule: 'concurrency_deadlock',
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
{
|
|
511
|
+
id: 'eval_gin_gonic_v19',
|
|
512
|
+
split: 'eval',
|
|
513
|
+
title: 'Gin Gonic v1.9 JSON Binding via ShouldBindJSON',
|
|
514
|
+
ecosystem: 'go',
|
|
515
|
+
library: 'github.com/gin-gonic/gin',
|
|
516
|
+
targetVersion: '1.9.1',
|
|
517
|
+
taskPrompt: 'Bind and validate incoming JSON request payload in Gin route handler',
|
|
518
|
+
docsUrl: 'https://gin-gonic.com/docs/examples/binding-and-validation/',
|
|
519
|
+
workspaceFiles: {
|
|
520
|
+
'go.mod': `module myapi\n\ngo 1.21\n\nrequire github.com/gin-gonic/gin v1.9.1\n`,
|
|
521
|
+
},
|
|
522
|
+
docs: [
|
|
523
|
+
{
|
|
524
|
+
url: 'https://gin-gonic.com/docs/examples/binding-and-validation/',
|
|
525
|
+
title: 'Gin Model Binding and Validation',
|
|
526
|
+
version: '1.9.1',
|
|
527
|
+
content: `# Gin JSON Binding
|
|
528
|
+
In Gin 1.9+, use \`c.ShouldBindJSON(&obj)\` to parse request body into a struct.
|
|
529
|
+
\`c.BindWith\` is deprecated and sets HTTP 400 automatically without programmatic recovery.
|
|
530
|
+
\`ShouldBindJSON\` allows custom error formatting.`,
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
groundTruth: {
|
|
534
|
+
expectedVersion: '1.9.1',
|
|
535
|
+
expectedApi: {
|
|
536
|
+
symbol: 'ShouldBindJSON',
|
|
537
|
+
},
|
|
538
|
+
fatalPitfalls: ['Do not use deprecated BindWith; use ShouldBindJSON for custom error responses'],
|
|
539
|
+
validCode: `func HandleCreate(c *gin.Context) {
|
|
540
|
+
var req CreateRequest
|
|
541
|
+
if err := c.ShouldBindJSON(&req); err != nil {
|
|
542
|
+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
543
|
+
return
|
|
544
|
+
}
|
|
545
|
+
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
|
546
|
+
}`,
|
|
547
|
+
invalidCode: {
|
|
548
|
+
snippet: `func HandleCreate(c *gin.Context) {
|
|
549
|
+
var req CreateRequest
|
|
550
|
+
c.BindWith(&req, binding.JSON) // Deprecated BindWith
|
|
551
|
+
}`,
|
|
552
|
+
expectedRule: 'deprecation',
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
|
|
557
|
+
// ==========================================
|
|
558
|
+
// DEDICATED VERIFICATION SPLIT (7 tasks)
|
|
559
|
+
// Intentionally incorrect generated code testing:
|
|
560
|
+
// - wrong endpoint
|
|
561
|
+
// - wrong HTTP method
|
|
562
|
+
// - missing required parameter
|
|
563
|
+
// - deprecated API
|
|
564
|
+
// - removed API
|
|
565
|
+
// - version mismatch
|
|
566
|
+
// - dynamic/ambiguous code
|
|
567
|
+
// ==========================================
|
|
568
|
+
{
|
|
569
|
+
id: 'verify_wrong_endpoint',
|
|
570
|
+
split: 'verification',
|
|
571
|
+
title: 'Verification: Non-Existent Endpoint Detection',
|
|
572
|
+
ecosystem: 'javascript',
|
|
573
|
+
library: 'stripe',
|
|
574
|
+
targetVersion: 'v14',
|
|
575
|
+
verificationCategory: 'wrong_endpoint',
|
|
576
|
+
taskPrompt: 'Verify detection of non-existent API endpoint',
|
|
577
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
578
|
+
workspaceFiles: {
|
|
579
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
580
|
+
},
|
|
581
|
+
docs: [
|
|
582
|
+
{
|
|
583
|
+
url: 'https://docs.stripe.com/api',
|
|
584
|
+
title: 'Stripe API Reference',
|
|
585
|
+
version: 'v14',
|
|
586
|
+
content: '# Stripe API v14\nPOST /v1/webhook_endpoints\nCreate a webhook endpoint.',
|
|
587
|
+
},
|
|
588
|
+
],
|
|
589
|
+
endpoints: [
|
|
590
|
+
{
|
|
591
|
+
id: 'ep_v1_wh',
|
|
592
|
+
pageId: 'p_wh',
|
|
593
|
+
snapshotId: 'snap_v14',
|
|
594
|
+
method: 'post',
|
|
595
|
+
path: '/v1/webhook_endpoints',
|
|
596
|
+
summary: 'Create webhook endpoint',
|
|
597
|
+
parameters: [{ name: 'url', in: 'query', required: true, type: 'string' }],
|
|
598
|
+
docVersion: 'v14',
|
|
599
|
+
},
|
|
600
|
+
],
|
|
601
|
+
groundTruth: {
|
|
602
|
+
expectedVersion: 'v14',
|
|
603
|
+
expectedApi: { symbol: 'webhook_endpoints', path: '/v1/webhook_endpoints' },
|
|
604
|
+
fatalPitfalls: ['Endpoint does not exist'],
|
|
605
|
+
validCode: `const res = await fetch('https://api.stripe.com/v1/webhook_endpoints', {
|
|
606
|
+
method: 'POST',
|
|
607
|
+
body: JSON.stringify({ url: 'https://example.com/wh', enabled_events: ['charge.failed'] })
|
|
608
|
+
});`,
|
|
609
|
+
invalidCode: {
|
|
610
|
+
snippet: `fetch('https://api.stripe.com/v1/non_existent_portal_endpoint', { method: 'POST' });`,
|
|
611
|
+
expectedRule: 'endpoint_validity',
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
|
|
616
|
+
{
|
|
617
|
+
id: 'verify_wrong_http_method',
|
|
618
|
+
split: 'verification',
|
|
619
|
+
title: 'Verification: Unsupported HTTP Method Detection',
|
|
620
|
+
ecosystem: 'javascript',
|
|
621
|
+
library: 'stripe',
|
|
622
|
+
targetVersion: 'v14',
|
|
623
|
+
verificationCategory: 'wrong_http_method',
|
|
624
|
+
taskPrompt: 'Verify detection of unsupported HTTP method on valid endpoint',
|
|
625
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
626
|
+
workspaceFiles: {
|
|
627
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
628
|
+
},
|
|
629
|
+
docs: [
|
|
630
|
+
{
|
|
631
|
+
url: 'https://docs.stripe.com/api',
|
|
632
|
+
title: 'Stripe API Reference',
|
|
633
|
+
version: 'v14',
|
|
634
|
+
content: '# Stripe API v14\nPOST /v1/webhook_endpoints\nCreate a webhook endpoint.',
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
endpoints: [
|
|
638
|
+
{
|
|
639
|
+
id: 'ep_v2_wh',
|
|
640
|
+
pageId: 'p_wh',
|
|
641
|
+
snapshotId: 'snap_v14',
|
|
642
|
+
method: 'post',
|
|
643
|
+
path: '/v1/webhook_endpoints',
|
|
644
|
+
summary: 'Create webhook endpoint',
|
|
645
|
+
parameters: [{ name: 'url', in: 'query', required: true, type: 'string' }],
|
|
646
|
+
docVersion: 'v14',
|
|
647
|
+
},
|
|
648
|
+
],
|
|
649
|
+
groundTruth: {
|
|
650
|
+
expectedVersion: 'v14',
|
|
651
|
+
expectedApi: { symbol: 'webhook_endpoints', path: '/v1/webhook_endpoints' },
|
|
652
|
+
fatalPitfalls: ['GET is not supported on /v1/webhook_endpoints'],
|
|
653
|
+
validCode: `const res = await fetch('https://api.stripe.com/v1/webhook_endpoints', {
|
|
654
|
+
method: 'POST',
|
|
655
|
+
body: JSON.stringify({ url: 'https://example.com/wh', enabled_events: ['charge.failed'] })
|
|
656
|
+
});`,
|
|
657
|
+
invalidCode: {
|
|
658
|
+
snippet: `fetch('https://api.stripe.com/v1/webhook_endpoints', { method: 'GET' });`,
|
|
659
|
+
expectedRule: 'method_validity',
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
|
|
664
|
+
{
|
|
665
|
+
id: 'verify_missing_required_param',
|
|
666
|
+
split: 'verification',
|
|
667
|
+
title: 'Verification: Missing Required Parameter Detection',
|
|
668
|
+
ecosystem: 'javascript',
|
|
669
|
+
library: 'stripe',
|
|
670
|
+
targetVersion: 'v14',
|
|
671
|
+
verificationCategory: 'missing_required_parameter',
|
|
672
|
+
taskPrompt: 'Verify detection of missing required request body parameters',
|
|
673
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
674
|
+
workspaceFiles: {
|
|
675
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
676
|
+
},
|
|
677
|
+
docs: [
|
|
678
|
+
{
|
|
679
|
+
url: 'https://docs.stripe.com/api',
|
|
680
|
+
title: 'Stripe API Reference',
|
|
681
|
+
version: 'v14',
|
|
682
|
+
content: '# Stripe API v14\nPOST /v1/webhook_endpoints\nRequires url and enabled_events.',
|
|
683
|
+
},
|
|
684
|
+
],
|
|
685
|
+
endpoints: [
|
|
686
|
+
{
|
|
687
|
+
id: 'ep_v3_wh',
|
|
688
|
+
pageId: 'p_wh',
|
|
689
|
+
snapshotId: 'snap_v14',
|
|
690
|
+
method: 'post',
|
|
691
|
+
path: '/v1/webhook_endpoints',
|
|
692
|
+
summary: 'Create webhook endpoint',
|
|
693
|
+
parameters: [{ name: 'url', in: 'query', required: true, type: 'string' }],
|
|
694
|
+
requestSchema: {
|
|
695
|
+
type: 'object',
|
|
696
|
+
required: ['enabled_events'],
|
|
697
|
+
properties: {
|
|
698
|
+
url: { type: 'string' },
|
|
699
|
+
enabled_events: { type: 'array' },
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
docVersion: 'v14',
|
|
703
|
+
},
|
|
704
|
+
],
|
|
705
|
+
groundTruth: {
|
|
706
|
+
expectedVersion: 'v14',
|
|
707
|
+
expectedApi: { symbol: 'webhook_endpoints', path: '/v1/webhook_endpoints' },
|
|
708
|
+
fatalPitfalls: ['Missing required body field enabled_events'],
|
|
709
|
+
validCode: `fetch('https://api.stripe.com/v1/webhook_endpoints', {
|
|
710
|
+
method: 'POST',
|
|
711
|
+
body: JSON.stringify({ url: 'https://example.com/wh', enabled_events: ['charge.failed'] })
|
|
712
|
+
});`,
|
|
713
|
+
invalidCode: {
|
|
714
|
+
snippet: `fetch('https://api.stripe.com/v1/webhook_endpoints', {
|
|
715
|
+
method: 'POST',
|
|
716
|
+
body: JSON.stringify({ url: 'https://example.com/wh' })
|
|
717
|
+
});`,
|
|
718
|
+
expectedRule: 'required_parameters',
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
|
|
723
|
+
{
|
|
724
|
+
id: 'verify_deprecated_api',
|
|
725
|
+
split: 'verification',
|
|
726
|
+
title: 'Verification: Deprecated API Detection',
|
|
727
|
+
ecosystem: 'javascript',
|
|
728
|
+
library: 'stripe',
|
|
729
|
+
targetVersion: 'v14',
|
|
730
|
+
verificationCategory: 'deprecated_api',
|
|
731
|
+
taskPrompt: 'Verify warning detection on deprecated API endpoints',
|
|
732
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
733
|
+
workspaceFiles: {
|
|
734
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
735
|
+
},
|
|
736
|
+
docs: [
|
|
737
|
+
{
|
|
738
|
+
url: 'https://docs.stripe.com/api',
|
|
739
|
+
title: 'Stripe API Reference',
|
|
740
|
+
version: 'v14',
|
|
741
|
+
content: '# Stripe API v14\nPOST /v1/charges\nDeprecated in favor of PaymentIntents.\nPOST /v1/payment_intents\nModern payment intents.',
|
|
742
|
+
},
|
|
743
|
+
],
|
|
744
|
+
endpoints: [
|
|
745
|
+
{
|
|
746
|
+
id: 'ep_v4_charges',
|
|
747
|
+
pageId: 'p_charges',
|
|
748
|
+
snapshotId: 'snap_v14',
|
|
749
|
+
method: 'post',
|
|
750
|
+
path: '/v1/charges',
|
|
751
|
+
summary: 'Create charge (deprecated)',
|
|
752
|
+
deprecated: true,
|
|
753
|
+
docVersion: 'v14',
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
id: 'ep_v4_pi',
|
|
757
|
+
pageId: 'p_pi',
|
|
758
|
+
snapshotId: 'snap_v14',
|
|
759
|
+
method: 'post',
|
|
760
|
+
path: '/v1/payment_intents',
|
|
761
|
+
summary: 'Create payment intent',
|
|
762
|
+
deprecated: false,
|
|
763
|
+
docVersion: 'v14',
|
|
764
|
+
},
|
|
765
|
+
],
|
|
766
|
+
pitfalls: [
|
|
767
|
+
{
|
|
768
|
+
id: 'pit_dep_charges',
|
|
769
|
+
pageId: 'p_charges',
|
|
770
|
+
snapshotId: 'snap_v14',
|
|
771
|
+
kind: 'deprecated',
|
|
772
|
+
title: 'Charges API Deprecated',
|
|
773
|
+
content: 'Use /v1/payment_intents instead of /v1/charges.',
|
|
774
|
+
relatedApi: '/v1/charges',
|
|
775
|
+
docVersion: 'v14',
|
|
776
|
+
createdAt: '2026-09-07T00:00:00Z',
|
|
777
|
+
},
|
|
778
|
+
],
|
|
779
|
+
groundTruth: {
|
|
780
|
+
expectedVersion: 'v14',
|
|
781
|
+
expectedApi: { symbol: 'payment_intents', path: '/v1/payment_intents' },
|
|
782
|
+
fatalPitfalls: ['Charges API is deprecated'],
|
|
783
|
+
validCode: `fetch('https://api.stripe.com/v1/payment_intents', {
|
|
784
|
+
method: 'POST',
|
|
785
|
+
body: JSON.stringify({ amount: 2000, currency: 'usd' })
|
|
786
|
+
});`,
|
|
787
|
+
invalidCode: {
|
|
788
|
+
snippet: `fetch('https://api.stripe.com/v1/charges', {
|
|
789
|
+
method: 'POST',
|
|
790
|
+
body: JSON.stringify({ amount: 2000 })
|
|
791
|
+
});`,
|
|
792
|
+
expectedRule: 'deprecation',
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
|
|
797
|
+
{
|
|
798
|
+
id: 'verify_removed_api',
|
|
799
|
+
split: 'verification',
|
|
800
|
+
title: 'Verification: Removed API Endpoint Detection',
|
|
801
|
+
ecosystem: 'javascript',
|
|
802
|
+
library: 'stripe',
|
|
803
|
+
targetVersion: 'v14',
|
|
804
|
+
verificationCategory: 'removed_api',
|
|
805
|
+
taskPrompt: 'Verify error detection on removed legacy endpoints',
|
|
806
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
807
|
+
workspaceFiles: {
|
|
808
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
809
|
+
},
|
|
810
|
+
docs: [
|
|
811
|
+
{
|
|
812
|
+
url: 'https://docs.stripe.com/api',
|
|
813
|
+
title: 'Stripe API Reference',
|
|
814
|
+
version: 'v14',
|
|
815
|
+
content: '# Stripe API v14\nPOST /v1/payment_methods\nSources API has been removed.',
|
|
816
|
+
},
|
|
817
|
+
],
|
|
818
|
+
endpoints: [
|
|
819
|
+
{
|
|
820
|
+
id: 'ep_v5_pm',
|
|
821
|
+
pageId: 'p_pm',
|
|
822
|
+
snapshotId: 'snap_v14',
|
|
823
|
+
method: 'post',
|
|
824
|
+
path: '/v1/payment_methods',
|
|
825
|
+
summary: 'Payment methods',
|
|
826
|
+
deprecated: false,
|
|
827
|
+
docVersion: 'v14',
|
|
828
|
+
},
|
|
829
|
+
// Note: /v1/sources exists in older snapshot v12, but was removed in v14
|
|
830
|
+
{
|
|
831
|
+
id: 'ep_v5_sources_legacy',
|
|
832
|
+
pageId: 'p_sources',
|
|
833
|
+
snapshotId: 'snap_v12',
|
|
834
|
+
method: 'post',
|
|
835
|
+
path: '/v1/sources',
|
|
836
|
+
summary: 'Sources (legacy v12)',
|
|
837
|
+
deprecated: true,
|
|
838
|
+
docVersion: 'v12',
|
|
839
|
+
},
|
|
840
|
+
],
|
|
841
|
+
pitfalls: [
|
|
842
|
+
{
|
|
843
|
+
id: 'pit_rem_sources',
|
|
844
|
+
pageId: 'p_pm',
|
|
845
|
+
snapshotId: 'snap_v14',
|
|
846
|
+
kind: 'removed',
|
|
847
|
+
title: 'Sources API Removed in v14',
|
|
848
|
+
content: 'Endpoint /v1/sources was removed in API version v14; migrate to PaymentMethods.',
|
|
849
|
+
relatedApi: '/v1/sources',
|
|
850
|
+
docVersion: 'v14',
|
|
851
|
+
createdAt: '2026-09-07T00:00:00Z',
|
|
852
|
+
},
|
|
853
|
+
],
|
|
854
|
+
groundTruth: {
|
|
855
|
+
expectedVersion: 'v14',
|
|
856
|
+
expectedApi: { symbol: 'payment_methods', path: '/v1/payment_methods' },
|
|
857
|
+
fatalPitfalls: ['/v1/sources was removed in v14'],
|
|
858
|
+
validCode: `fetch('https://api.stripe.com/v1/payment_methods', {
|
|
859
|
+
method: 'POST',
|
|
860
|
+
body: JSON.stringify({ type: 'card' })
|
|
861
|
+
});`,
|
|
862
|
+
invalidCode: {
|
|
863
|
+
snippet: `fetch('https://api.stripe.com/v1/sources', {
|
|
864
|
+
method: 'POST',
|
|
865
|
+
body: JSON.stringify({ type: 'card' })
|
|
866
|
+
});`,
|
|
867
|
+
expectedRule: 'removed_api',
|
|
868
|
+
},
|
|
869
|
+
},
|
|
870
|
+
},
|
|
871
|
+
|
|
872
|
+
{
|
|
873
|
+
id: 'verify_version_mismatch',
|
|
874
|
+
split: 'verification',
|
|
875
|
+
title: 'Verification: Version Syntax Conflict Detection (Next.js 14 sync vs 15 async)',
|
|
876
|
+
ecosystem: 'typescript',
|
|
877
|
+
library: 'next',
|
|
878
|
+
targetVersion: '14.2.0',
|
|
879
|
+
verificationCategory: 'version_mismatch',
|
|
880
|
+
taskPrompt: 'Verify detection of Next.js 15 async route parameters in a Next.js 14 project',
|
|
881
|
+
docsUrl: 'https://nextjs.org/docs/14/app/api-reference/file-conventions/route',
|
|
882
|
+
workspaceFiles: {
|
|
883
|
+
'package.json': JSON.stringify({ name: 'next-app', dependencies: { next: '^14.2.0', react: '^18.2.0' } }, null, 2),
|
|
884
|
+
},
|
|
885
|
+
docs: [
|
|
886
|
+
{
|
|
887
|
+
url: 'https://nextjs.org/docs/14/routing',
|
|
888
|
+
title: 'Next.js 14 Routing',
|
|
889
|
+
version: '14.2.0',
|
|
890
|
+
content: '# Next.js 14 Route Handlers\nNext.js 14 parameters are synchronous.',
|
|
891
|
+
},
|
|
892
|
+
],
|
|
893
|
+
groundTruth: {
|
|
894
|
+
expectedVersion: '14.2.0',
|
|
895
|
+
expectedApi: { symbol: 'GET', path: '/api/users/[id]' },
|
|
896
|
+
fatalPitfalls: ['Do not use await params in Next.js 14'],
|
|
897
|
+
validCode: `export default function Page({ params }: { params: { slug: string } }) {
|
|
898
|
+
const { slug } = params;
|
|
899
|
+
return <div>{slug}</div>;
|
|
900
|
+
}`,
|
|
901
|
+
invalidCode: {
|
|
902
|
+
snippet: `export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
|
|
903
|
+
const { slug } = await params;
|
|
904
|
+
return <div>{slug}</div>;
|
|
905
|
+
}`,
|
|
906
|
+
expectedRule: 'version_mismatch',
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
|
|
911
|
+
{
|
|
912
|
+
id: 'verify_dynamic_ambiguous_code',
|
|
913
|
+
split: 'verification',
|
|
914
|
+
title: 'Verification: Dynamic / Ambiguous Expression Safe Fallback',
|
|
915
|
+
ecosystem: 'javascript',
|
|
916
|
+
library: 'stripe',
|
|
917
|
+
targetVersion: 'v14',
|
|
918
|
+
verificationCategory: 'dynamic_ambiguous_code',
|
|
919
|
+
taskPrompt: 'Verify dynamic expression returns insufficient_evidence without false rejections',
|
|
920
|
+
docsUrl: 'https://docs.stripe.com/api',
|
|
921
|
+
workspaceFiles: {
|
|
922
|
+
'package.json': JSON.stringify({ name: 'stripe-test', dependencies: { stripe: '^14.0.0' } }, null, 2),
|
|
923
|
+
},
|
|
924
|
+
docs: [
|
|
925
|
+
{
|
|
926
|
+
url: 'https://docs.stripe.com/api',
|
|
927
|
+
title: 'Stripe API Reference',
|
|
928
|
+
version: 'v14',
|
|
929
|
+
content: '# Stripe API v14\nPOST /v1/webhook_endpoints',
|
|
930
|
+
},
|
|
931
|
+
],
|
|
932
|
+
endpoints: [
|
|
933
|
+
{
|
|
934
|
+
id: 'ep_v7_wh',
|
|
935
|
+
pageId: 'p_wh',
|
|
936
|
+
snapshotId: 'snap_v14',
|
|
937
|
+
method: 'post',
|
|
938
|
+
path: '/v1/webhook_endpoints',
|
|
939
|
+
summary: 'Create webhook endpoint',
|
|
940
|
+
docVersion: 'v14',
|
|
941
|
+
},
|
|
942
|
+
],
|
|
943
|
+
groundTruth: {
|
|
944
|
+
expectedVersion: 'v14',
|
|
945
|
+
expectedApi: { symbol: 'webhook_endpoints', path: '/v1/webhook_endpoints' },
|
|
946
|
+
fatalPitfalls: ['Dynamic URLs cannot be statically verified'],
|
|
947
|
+
validCode: `fetch('https://api.stripe.com/v1/webhook_endpoints', {
|
|
948
|
+
method: 'POST',
|
|
949
|
+
body: JSON.stringify({ url: 'https://example.com/wh', enabled_events: ['charge.failed'] })
|
|
950
|
+
});`,
|
|
951
|
+
invalidCode: {
|
|
952
|
+
snippet: `async function callDynamic(userSuppliedUrl: string) {
|
|
953
|
+
return fetch(userSuppliedUrl);
|
|
954
|
+
}`,
|
|
955
|
+
expectedRule: 'endpoint_validity',
|
|
956
|
+
},
|
|
957
|
+
dynamicCode: `async function callDynamic(userSuppliedUrl: string) {
|
|
958
|
+
return fetch(userSuppliedUrl);
|
|
959
|
+
}`,
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
];
|
|
963
|
+
|