SuperAPI AI Directory

grading-backend

Testing & quality

View repository

Updated 10-16 09:37

About this skill

grading-backend

Score the backend implementation of an AI training program. 50 students are divided into ~12 groups, implementing a locally deployed backend service in a spec-driven manner. This skill lets Claude (or Qoder / Cursor / Claude Code agent) score a given group's backend according to a unified rubric, producing a markdown report that can be given to students + JSON that can be aggregated into a leaderboard.


Prerequisites

  • Runnable locally: the backend to be evaluated can be started on the local machine (npm run dev / uvicorn ... / go run ./... / ./gradlew bootRun , etc.), default http://localhost:8080(adjust according to the project README), with a health check endpoint (/health / /healthz / /ping) or other readiness signal.
  • Spec document location:<project>/docs/spec.md or <project>/README.md or <project>/spec/*. If not found, confirm the spec path with the user before starting work; do not score out of thin air.
  • Node.js environment: Node ≥ 18, used to run npx ajv-cli to validate JSON,npx autocannon for load testing.
  • curl: all interface probes and evidence-gathering commands are based on curl, which is built in on macOS / Linux.
  • Output directory: all evidence and reports are written to .grading/under the root directory of the project to be evaluated (already agreed by spec to be gitignored).

Agreed working directory: all probe scripts and .grading/ output are by default inthe root directory of the project to be evaluatedexecuted under. That is, when scoring:

  1. cd to the project being evaluated (e.g. cd group-workshop/group-2)
  2. call the probe with an absolute path:bash $WORKSHOP_ROOT/skills/grading-backend/probes/probe-robustness.sh team-2 http://localhost:8080 /api/items
  3. .grading/ will land under the root of the project being evaluated, coexisting with that project

Shared contract (required reading)

Before scoring begins,you must first finish reading this file ## 评分标尺 / ## 报告模板 / ## 证据硬约束 three sections, as well as ../score-schema.json. These are hard constraints shared by the frontend / backend skills; not reading them will lead to inconsistent output formats and an inability to aggregate the leaderboard:

  1. See this file ## Scoring scale — meaning of the 0–10 scale + definitions of S/A/B/C/D tiers.All dimension scores must be compared against this scale。
  2. See this file ## Report template — unified Markdown report template. The produced report.md must be filled in according to this structure.
  3. ../score-schema.json — schema of the JSON summary. The produced summary.json must pass validation against this schema.
  4. See this file ## Evidence hard constraints — a score ≥7 or ≤4 requires ≥2 pieces of evidence, and a score of 5–6 requires ≥1. Violation makes the score invalid.

Scoring scale (0–10)

This section is grading-frontend and grading-backend shared by the two skillsthe onlyscoring anchor. All dimension scores on both sides must land according to this table, then use evidence to explain why it is not the adjacent anchor.

1. Score anchors

Score Name Judgment criteria
10 Industry-grade exemplar Can be used directly as a teaching sample for the next cohort; the scorer cannot find room for improvement in this dimension; clearly ahead of the best student work seen so far
9 Excellent The core is fully in place, with only 1–2 non-critical flaws (e.g. edge-case copy, extreme breakpoints, cold-path logging)
7 Good The main flow is in place, but there are ≥3 improvable points; it does not affect delivery but clearly shows signs of rushing
5 Pass Happy path runs, but clearly rough; there is 1 type of systemic vulnerability (such as missing state, missing validation) but not fatal
3 Fail There are traces of an attempt for this item but it is severely incomplete; major sub-items are missing or the logic is wrong
0 Not implemented Completely missing, or implemented but does not run
N/A Not applicable The spec explicitly does not require it, or this dimension is meaningless on this project's stack;the reason must be written, not counted toward the total score

Allowed scores: 0, 3, 5, 7, 9, 10 are anchors; 1/2/4/6/8 are used only when the evidence supports "between two anchors." Decimals are not allowed.

2. Scoring operation rules

  1. Choose the anchor first, then fine-tune: after obtaining the evidence, first align with the closest anchor (10/9/7/5/3/0), then use the evidence to decide on a ±1 fine-tuning. It is forbidden to "first pick an 8 and then find evidence."
  2. High and low scores must have evidence:
    • score ≥ 7 → at least 2 pieces of evidence
    • score ≤ 4 → at least 2 pieces of evidence
    • 5–6 → at least 1 piece of evidence
    • For detailed rules, see this file's ## 证据硬约束 section
  3. N/A must state the reason:na_reason field is required, format "spec §X.Y 未涉及此项" or "技术栈 Z 无此概念". N/A is not counted toward the total score.
  4. Cannot be both a low score + high praise: if the comment is "very good, just one small thing missing," the score cannot be ≤ 5.
  5. When anchors conflict, take the lower rather than the higher: if a dimension both matches the positive description of 9 and hits the negative description of 5, take 5 (as a warning effect).

3. Total score calculation

Formula(N/A is not counted in the denominator):

total = Σ(score_i × weight_i) / Σ(weight_i for dim_i where score_i != null) × 100 / 10

Equivalent form: first compute the weighted average over non-N/A dimensions (0–10), then normalize the effective weights to 100, and finally multiply by 10 to map to 0–100.

Example: the frontend has 10 dimensions with a total weight of 100. If 微文案 (权重 6) is judged N/A:

  • Total effective weight = 94
  • Weighted sum of the remaining 9 dimensions = Σ(score_i × weight_i)
  • total = (Σ / 94) × 10

4. Total score tiers

Tier Score range Meaning
S ≥ 90 Can be used as a teaching example for this cohort
A 80–89 Qualified delivery; can go live after small-scale polishing
B 70–79 Main process is OK; systemic issues require rework
C 60–69 Can demo, cannot deliver; multiple structural defects
D < 60 Did not meet the training objectives; key modules need to be redone

Tiers are only used for horizontal comparison on the class leaderboard; learner feedback is mainly based ondimension scores + evidence + improvement list.


Report template

The .grading/reports/<team>-<side>.md mustproduced by the two grading skills strictly follow this template. No field may be missing; when there is no information, fill in —,do not omit lines. The template body is presented as a Markdown code block wrapped in four backticks; when copying, remove the outermost backticks.

Usage instructions

  • Placeholders are in the form {队伍名}; when applied, replace them with actual values
  • The detailed dimension review blocks are grading-frontend 10 dimensions / grading-backend 9 dimensions fully expanded, and cannot be merged or omitted
  • When the evidence for any dimension is insufficient, fill score with null,na_reason fill in EVIDENCE_MISSING: ..., and summarize in the "Scoring Risks" section at the end
  • A corresponding JSON must exist at the same level as the report:<team>-<side>.json, see the schema at ../score-schema.json

Template

# 项目评分报告 — {队伍名}({前端 | 后端})

- 评分人:{Claude@model-id / 助教姓名}
- 日期:{YYYY-MM-DD}
- Spec 版本:{git sha 或 docs/spec.md 路径}
- 被评项目 commit:{sha}
- 评分耗时:{xx 分钟}

## 总分:{score} / 100 — 等级 {S | A | B | C | D}

## 维度汇总

| # | 维度 | 得分 | 权重 | 加权 | 一句话 |
|---:|---|---:|---:|---:|---|
| 1 | {维度名} | {0–10 或 N/A} | {w} | {score×w/10} | {一句话概述} |
| 2 | ... | ... | ... | ... | ... |

> 有效权重总和:{Σw_non-NA};N/A 维度:{列表或 "无"}

## 逐维度详评

### 1. {维度名} — {score}/10(权重 {w})

**证据**
- `path/to/file.ext:L12-L40` — {这条证据说明了什么}
- 截图:`.grading/shots/{team}-{view}.png`
- 命令:`curl -s localhost:8080/api/x` → `.grading/probes/{team}-x.log`

**要到 10 差什么**
1. {具体、可操作的改进建议}
2. {...}
3. {...}

---

### 2. {维度名} — {score}/10(权重 {w})

(同样模板,完整列出所有维度)

---

## 亮点

- {值得表扬的 2–4 条,要带证据}

## 最该优先修的 3 件事

1. **{问题}** — 影响:{哪个维度掉了多少分};改法:{一两句话说清}
2. ...
3. ...

## 评分风险(可选)

仅当出现以下情况时填写,否则删除整节:
- 证据不足被判 `EVIDENCE_MISSING` 的维度列表
- 评分人对某维度存疑但无法进一步取证的原因
- 项目未跑起来 / spec 缺失等影响评分可信度的事实

Checklist (self-check after writing the report)

  • Total score = Σ(weighted columns) × 10 / Σ(valid weights), the values match up
  • Every dimension has at least one citation (evidence / screenshot / log / spec entry)
  • All N/A entries have na_reason
  • Each of the "Top 3 things that should be fixed first" points back to a specific dimension
  • The corresponding JSON has been written to .grading/reports/<team>-<side>.json

Hard evidence constraints

This section contains thewhether the scoring is validdecision rules.grading-frontend and grading-backend The two skills, before writing the score for each dimension,mustcheck this table first; any score whose evidence does not meet the standard is considered invalid.

Design purpose: to prevent the agent from scoring off the top of its head without actual observation.Better one extra EVIDENCE_MISSING, than making up a nice-looking score。

1. Evidence count rules

Score range Minimum evidence count Description
9–10 3 A high score must be reproducible; at minimum cover: 1 code citation + 1 piece of runtime evidence (screenshot/probe/log) + 1 spec comparison
7–8 2 Must reflect both "the main flow is in place" and "non-critical flaws"
5–6 1 One is enough, but it must be able to point out a specific defect
3–4 2 A low score cannot rely on impressions; it must list ≥2 specific failure points
0 1 Must at least prove "it really doesn't exist": grep results, spec entries + codebase absence, startup failure logs
N/A 1 Must cite the spec entry or tech stack description to prove that the item is "not applicable"

2. Valid evidence forms

Each piece of evidence must be one of the following 4 types,must notbe a natural-language paraphrase:

  1. Code citation:path/to/file.ext:L{start}-L{end} or path/to/file.ext:L{line}
    • The path must be relative to the project root
    • Must actually exist (confirmed via open / grep before scoring)
  2. Screenshot:.grading/shots/<team>-<view>.png
    • The file must exist; generally not used for backend dimensions
    • A brief note may be added: "login page desktop 1280×800, has layout shift"
  3. Command log:.grading/probes/<team>-<probe>.log Or give the command and key output directly within the evidence line
    • Of the form:curl -s -o /dev/null -w "%{http_code}" localhost:8080/api/x -d '{}' → 500
    • Stress test results citing the autocannon output file
  4. Spec citation:spec §3.2 / docs/spec.md:L120-L145 / issue link
    • Required when determining N/A or Spec consistency

3. Handling violations

3.1 Insufficient evidence

If the required evidence count cannot be gathered per §1:

  1. score Set to null
  2. na_reason Written as "EVIDENCE_MISSING: 需要 N 条证据,仅能取得 M 条(已尝试:<动作清单>)"
  3. At the end of the report, in the ## 评分风险 section, list this dimension
  4. This dimensionis not counted in the total score denominator(consistent with a normal N/A), but mark it in the scoring risks section as a "non-spec exclusion item"

3.2 Evidence fabrication / placeholder

If the scorer/agent writes any of the following forms of evidence, that dimension is directly voided and downgraded to EVIDENCE_MISSING:

  • A file:line whose path does not exist (lint: after scoring use test -f for batch validation)
  • Screenshot file does not exist or has size 0
  • Command log content contradicts the conclusion
  • Descriptive language ("the code is well organized") without specific citations

3.3 High/low scores without evidence

  • score ≥ 7 but evidence < 2 items → downgrade to 6, or mark EVIDENCE_MISSING
  • score ≤ 4 but evidence < 2 items → upgrade to 5, or mark EVIDENCE_MISSING

Which handling to choose depends on the scorer's grasp of the dimension; both approaches must be noted in "Scoring Risk".

4. Recommended order for evidence collection

Do the cheap, batchable things first, then the expensive ones:

  1. Static (cheap):grep / rg scan keywords, look at package.json / schema / migration
  2. Spec alignment: map each spec checklist item to code files one by one
  3. Runtime: start the dev server / backend service, run screenshot scripts / probe scripts
  4. Interaction: walk through the main flow, check console / network / logs
  5. Testing: run the test suite, check coverage and the failure list

After each step, write the artifacts to disk under .grading/, and just cite the relative path in the report's evidence line.


Supporting resources

Read as needed (not all of them every time):

  • ./anti-patterns.md — backend anti-pattern checklist.Required reading when scoring the three dimensions "robustness", "code layering", and "performance", used to identify typical slippery slopes such as writing SQL in the controller, bare try/except: pass swallowing exceptions, queries inside loops causing N+1, non-idempotent write operations, and error response structures differing per endpoint.
  • ./examples/good-report.md and ./examples/mediocre-report.md — two calibration sample reports.Read once before scoring to calibrate the distribution, to avoid problems like the whole class getting 8 points and being unable to differentiate tiers.
  • ./probes/probe-robustness.sh — robustness probe suite, runs 8 scenarios (empty body / wrong type / overly long field / missing required field / privilege escalation / idempotent replay / concurrent conflict / not logged in). When gathering evidence, directly bash ./probes/probe-robustness.sh <team> <base-url> <path>, do not hand-roll curl. Each probe writes .grading/probes/<team>-<probe-name>.log, and the summary table writes .grading/probes/<team>-robustness-summary.md。
  • ./probes/probe-performance.sh — based on npx autocannon p50/p95/p99 load testing script, outputs .grading/probes/<team>-autocannon.log(raw autocannon output) and .grading/probes/<team>-perf-summary.txt(parsed p50/p95/rps + rubric suggestions).

Scoring process (5 steps)

Step 1: Locate and start

  1. Confirm the spec path, record spec_sha(if the spec is inside a git repository).
  2. Read the spec, list: endpoint inventory (method + path + input params + output params + status codes) / data model / permission roles / key write operations.
  3. Read package.json / pyproject.toml / go.mod / pom.xml to identify the tech stack (Node/Python/Go/Java, ORM, test framework, logging library), record project_sha。
  4. Start the backend service, confirm http://localhost:<port>/<health> is accessible (curl gets 200 or the readiness response specified by the spec). If startup fails, record it directly in the report's "Startup Blockers" section; do not force a 0 for this dimension, but deduct points in "Spec Consistency".

Step 2: Collect evidence (evidence-first)

Static evidence:

  • Use Grep/Glob to scan the endpoint inventory, layered directories (controller/service/repo), schema / migrations, test directories, and logging code.
  • Reserve at least 1 file:line citation for each dimension.

Dynamic evidence:

# 健壮性:对主要写接口跑一遍 8 个 probe
bash ./probes/probe-robustness.sh <team> http://localhost:8080 /api/items

# 性能:对 GET 主列表接口 & POST 主写接口各压一次
bash ./probes/probe-performance.sh <team> http://localhost:8080 /api/items

# 测试套件(按栈择一)
npm test -- --coverage        # Node
pytest --cov                  # Python
go test -cover ./...          # Go

# 手工 curl:对 spec 列出的每个接口至少调一次,记录 method + path + 状态码 + 响应体
curl -i -X GET  http://localhost:8080/api/items
curl -i -X POST http://localhost:8080/api/items -H 'Content-Type: application/json' -d '{"name":"demo"}'

All probe logs go to .grading/probes/<team>-*.log, and key outputs from manual curl should also be tee into .grading/probes/<team>-curl.log。

Interaction evidence: Walk through the spec's main business flow (register → login → create → query → update → delete, or the flow specified by the spec), recording the status code, response body snippet, and exceptions for each step.

Step 3: Score each of the 9 dimensions

⚠️ Mandatory behavior when evidence is insufficient

  • When a dimension score is ≥7 or ≤4, if the number of evidence items is below the minimum required by evidence-requirements.md → score must be set to null, and na_reason should state "EVIDENCE_MISSING: attempted X, Y, but failed to obtain Z"
  • This is different from the N/A for "not required by spec": N/A should state "N/A — not specified in spec §X.Y"
  • All EVIDENCE_MISSING dimensions must be summarized and listed in the "## Scoring Risks" section at the bottom of the report

Refer to the rubric below in this file (as well as this file's ## 评分标尺 section), and score each dimension from 0–10. Every score must be accompanied by evidence (file:line / curl log line number / probe log line number / test output line number). For dimensions not required by the spec, write "N/A — reason", and they are not counted toward the total score.

Step 4: Produce report.md + summary.json

Fill in ## 报告模板 according to this file's .grading/reports/<team>-backend.mdsection; fill in ../score-schema.json according to .grading/reports/<team>-backend.json. For each dimension, include 2–4 items on "what is missing to reach 10".

Step 5: Self-check (must pass)

# JSON schema 校验
npx ajv-cli validate -s skills/score-schema.json \
  -d .grading/reports/<team>-backend.json

# 证据数量自检(每维度统计 file:line + probe log + curl log 引用总数)
grep -cE "\.(ts|js|py|go|java|sql|log):" .grading/reports/<team>-backend.md

If the self-check does not pass, return to step 2 to gather more evidence; do not let it slide.


9 scoring dimensions (weights total 100)

# Dimension Weight
1 Spec consistency 20
2 Robustness 15
3 API design 12
4 Testing 12
5 Data modeling 10
6 Code layering 10
7 Performance 8
8 Observability 7
9 Documentation 6

1. Spec consistency (weight 20)

Focus points

  • Whether every interface listed in the spec (method + path) is implemented.
  • Whether input fields, output fields, status codes, and error codes align with the spec.
  • Whether permission / role branches (such as admin interfaces) are complete.
  • Neither cutting corners nor adding unrelated extras beyond the spec.

Anchors

  • 10: All interfaces listed in the spec are 100% implemented; input / output / status codes / error codes are fully aligned; features beyond the spec are clearly marked as enhancements.
  • 9: All interfaces are implemented, with only 1–2 minor deviations from the spec in non-critical fields or error codes (e.g., an extra harmless field in the response, using 400 for an error code when the spec requires 422), with the core path 100% aligned.
  • 8: All primary and secondary interfaces are implemented, with minor gaps at the edges of the spec (e.g., 1 non-main-path query parameter unsupported, 1 soft-delete restore interface missing), and the business loop is complete.
  • 7: Primary interfaces are complete, but 1–2 secondary interfaces are missing or there are 2–3 misalignments in field details / status codes.
  • 5: Core CRUD is present, but fields deviate from the spec in multiple places, or 1 key interface (such as review, permission switching) is not implemented.
  • 3: Large portions deviate from the spec; only demo-level interfaces are implemented, and the real business flow is missing.

Evidence-gathering method

  1. Map the spec interface list one by one against the route registrations in the code:
    # Node/Express 举例
    grep -rnE "app\.(get|post|put|patch|delete)|router\.(get|post|put|patch|delete)" src/
    # FastAPI
    grep -rnE "@(app|router)\.(get|post|put|patch|delete)" .
    # Go/Gin
    grep -rnE "\.(GET|POST|PUT|PATCH|DELETE)\(" .
    
  2. Manually curl each interface in the spec and record the status code and response body.
  3. For missing items, record the spec section number + expected behavior + actual behavior.

Evidence requirements

  • At least 4 file:line references to route / handler files.
  • A spec vs implementation alignment table (use a markdown table in the report: interface / spec requirement / actual / status).
  • At least 3 curl logs covering the key interfaces.

2. Robustness (weight 15)

Focus points

  • Whether all exception paths are handled (not try/except: pass swallowing errors).
  • Whether inputs are validated (type, range, required, length).
  • Whether key write operations are idempotent (retries do not create duplicates).
  • Whether concurrency conflicts are considered (optimistic locking / transactions).
  • Whether unauthenticated / unauthorized access is correctly rejected.

Anchors (based on the pass count of probe-robustness.sh 8 probes)

  • 10: ≥7 probes pass; there is a clear error code system; key write operations are idempotent; concurrent paths have locks or transactions.
  • 9: 7 of 8 probes pass, with only 1 boundary case returning 500 instead of a structured error (e.g., an overlong field is not truncated and a DB error is thrown); idempotency / concurrency / error code system are complete.
  • 8: 6/8 probes are reasonable (idempotency is implemented for the main operations, unauthorized / unauthenticated rejection is correct), 1–2 boundary cases are unhandled but return a unified error structure rather than a stack trace.
  • 7: ≥5 probes pass; the main path is robust, with 1–2 omissions in boundary / concurrency handling.
  • 5: ≥3 probes pass; the happy path works, but multiple exception paths directly return 500.
  • 3: <3 probes pass; basically no exception handling is done, or errors directly throw the stack trace to the frontend.

Evidence collection method

  1. Run bash ./probes/probe-robustness.sh <team> <base-url> <path>, record the pass count of the 8 probes (each probe has an expected status code).
  2. Check whether the response codes and error message format are unified:
    grep -rnE "try\s*\{|try:" src/ | head -20
    grep -rnE "except\s*:|catch\s*\(\s*\)" src/        # 裸 except / catch
    grep -rnE "pass\s*$|// ignore" src/
    
  3. For the same write interface, use curl to send the same payload twice, and see whether two records are created (idempotency).

Evidence requirements

  • 1 copy of <team>-robustness-summary.md(annotate the pass count X/8) + at least 3 copies of <team>-<probe-name>.log。
  • curl + response excerpts for at least 3 probes (paste snippets in the report).
  • At least 2 file:line references to validation / error handling code.

3. API design (weight 12)

Focus points

  • RESTful path semantics (plural resource nouns, clear hierarchy) or consistency of RPC style.
  • Status codes are used correctly (200/201/204/400/401/403/404/409/422/500).
  • Error response structure is unified (e.g., {code, message, details}), not a different shape for each interface.
  • Pagination / filtering / sorting have conventions (?page=&size= or cursor).
  • Request / response field naming is consistent (choose either camelCase or snake_case, do not mix).

Anchors

  • 10: Paths and status codes are all compliant; the error structure is unified; pagination / filtering / sorting are standardized; field naming is unified.
  • 9: Paths / status codes / error structure are all compliant, pagination and naming are unified, with only 1 filtering parameter style not fully consistent with the rest of the site (e.g., one interface uses q while others use keyword)。
  • 8: RESTful compliance and a unified error structure; pagination is implemented, but 1 interface returns 201 while the spec specifies 200 (or vice versa), and field naming is unified.
  • 7: Overall compliant, but 1–2 status codes are misaligned (e.g., POST success returns 200 instead of 201) or 1 place has an inconsistent error structure.
  • 5: Most endpoints work, but status codes are misused, each endpoint has its own error structure, and there is no pagination convention.
  • 3: Everything returns 200 + {ok: false}, no status code system, paths are arbitrary.

Evidence collection method

  1. Search route registrations + manually curl the key endpoints to inspect response structures:
    for p in /api/items /api/users /api/auth/login; do
      curl -s -o - -w "\n[HTTP %{http_code}]\n" http://localhost:8080$p
    done
    
  2. Extract 3–5 error responses and compare whether their shapes are consistent.
  3. Pagination endpoints:curl "http://localhost:8080/api/items?page=1&size=10" check whether it is recognized.

Evidence requirements

  • At least 5 curl logs covering the three categories: success / failure / pagination.
  • At least 2 file:line citing a unified error-handling middleware (or counter-evidence showing it is missing).
  • One error response structure comparison table (3–5 rows in the report is enough).

4. Testing (weight 12)

Focus points

  • Whether there are automated tests (unit + integration).
  • Whether critical paths (login, core write operations, error branches) are covered.
  • Whether the tests actually pass, rather than a bunch of skips.
  • Coverage data.

Anchors (based on test coverage)

  • 10: Coverage ≥70%; covers critical happy + error paths; integration tests hit the API for real; CI local npm test / pytest / go test once green.
  • 9: Coverage ≥65% and both happy + error paths are covered; integration tests hit the API for real; only 1 minor error branch (e.g., idempotency conflict) is untested.
  • 8: Coverage ≥55%; the main happy path + core error branches have integration tests; minor modules have only unit tests without integration coverage.
  • 7: Coverage ≥50%; the main happy path is covered, with a few error paths.
  • 5: Coverage exists but mostly only happy path, or integration tests are missing and only unit tests are present.
  • 3: Almost no tests (<20% or only 1–2 sanity tests) or many skips / TODOs.

Evidence collection method

  1. Run tests + coverage according to the stack:
    npm test -- --coverage              # Node
    pytest --cov --cov-report=term       # Python
    go test -cover ./...                 # Go
    ./gradlew test jacocoTestReport       # Java
    
    tee the output to .grading/probes/<team>-test.log。
  2. Count the number of test files and skipped cases:
    grep -rnE "\.skip|@pytest\.mark\.skip|t\.Skip\(|xit\(|xdescribe\(" .
    
  3. Pick one error-path test case and read 5–10 lines to see whether it actually asserts the error code rather than just passing through.

Evidence requirements

  • 1 test output log (including coverage numbers).
  • At least 3 file:line citing test files (good case) or missing ones (bad case).
  • One skip statistic:skip 数 / 总数。

5. Data modeling (weight 10)

Focus points

  • Schema / model definitions align with the spec (fields, types, constraints, relationships).
  • Primary keys, foreign keys, unique indexes, and necessary indexes are all present.
  • There are migration scripts / versioning, not manual table edits.
  • Field naming and type choices are reasonable (use timestamptz / datetimefor time, do not use float for money).

Anchors

  • 10: Schema aligns 100% with the spec; foreign keys / unique constraints / indexes are complete; there is a migration version chain; naming and types are both reasonable.
  • 9: Schema aligns and constraints are complete, the migration version chain is clean, with only 1 minor query index missing (does not affect the main hot path).
  • 8: Field types / foreign keys / primary keys / unique constraints are all correct, the migration exists, but 1 composite index is missing or 1 field uses text while the spec recommends varchar(n)。
  • 7: The schema is aligned, but 1–2 indexes are missing or 1 foreign key is missing, and the migration exists but is not well-formed.
  • 5: The schema barely runs, multiple field types are mismatched (e.g., using varchar to store time), and there are no indexes at all.
  • 3: No schema definition / no migration, or the fields deviate significantly from the spec.

Evidence collection method

  1. Find the schema file:
    find . -type f \( -name "*.sql" -o -name "schema.prisma" -o -name "models.py" -o -name "entity*.go" -o -name "*Entity.java" \) | head
    find . -type d -name "migrations" -o -name "migrate"
    
  2. For each core table, record: fields / types / constraints / indexes, and compare against the spec.
  3. Check whether the migration directory has version numbers and whether down scripts are complete.

Evidence requirements

  • At least 3 file:line citing schema / model / migration files.
  • A field comparison table for core tables (table name / field / type / spec expectation / actual).
  • Index list (extracted from CREATE INDEX or ORM annotations).

6. Code layering (weight 10)

Focus points

  • The controller / handler / route layer only does parameter parsing and response wrapping, and does not contain business logic.
  • The service / usecase layer carries business logic and does not directly write SQL.
  • The repository / dao layer encapsulates data access, and controllers do not bypass it to use the ORM directly.
  • Cross-layer dependencies flow in a single direction (controller → service → repo), with no reverse dependencies.

Anchors (based on grepping whether controllers contain SQL/ORM calls)

  • 10: The three layers are clear; there are no SQL / ORM calls in controllers; there is no HTTP response assembly in services; circular dependencies are 0.
  • 9: All controllers are thin shells (parameter parsing + forwarding to service), services do not touch HTTP, and there is only 1 place in a repo where a small amount of business judgment is assembled that should belong to the service.
  • 8: The layering is generally clear, and controllers basically only forward, but 1 handler directly calls the ORM once (e.g., a simple count query bypassing the repo), and the dependency direction is still one-way.
  • 7: The layering is overall present, but 1–2 controllers casually call the ORM or assemble complex business logic in a handler.
  • 5: There is an intent to layer but a lot of leakage: controllers often directly prisma.xxx / db.query, and services write res.json(...)。
  • 3: All in one pot; all logic is in route handlers, with no concept of service / repo.

Evidence collection method

  1. Grep the controller directory for direct SQL / ORM:
    # Node/TS
    grep -rnE "prisma\.|knex\(|db\.query|createQueryBuilder|sequelize\." src/controllers src/routes src/handlers 2>/dev/null
    # Python
    grep -rnE "session\.query|db\.execute|cursor\.execute" app/api app/routes 2>/dev/null
    # Go
    grep -rnE "db\.Query|db\.Exec|gorm\.|sqlx\." internal/handler internal/controller 2>/dev/null
    
    The more hits, the more leakage it indicates.
  2. Sample 2 controller files and read the first 30 lines to see whether the logic is "thin".
  3. Draw the dependency arrows (oral is fine):controller -> service -> repo whether it is one-way.

Evidence requirements

  • At least 1 set of grep statistics: "number of SQL/ORM hits in the controller directory / total number of controller files".
  • At least 3 file:line(examples of good services / bad leakage each).
  • Describe the dependency direction in one sentence.

7. Performance (weight 8)

Focus points

  • Response time of key endpoints (p50 / p95 / p99).
  • No N+1 queries (sending requests / queries inside loops).
  • Reasonable indexes support the main queries.
  • Necessary caching / batching (when required by the spec).

Anchors (based on autocannon p95, 10 concurrency, 5 seconds, local)

  • 10: Main GET list endpoint p95 < 100ms; write endpoint p95 < 300ms; zero N+1 hits.
  • 9: Main GET p95 < 150ms, write p95 < 400ms, zero N+1 hits, only 1 secondary aggregate query lacks an index but p95 is still in an acceptable range.
  • 8: Main GET p95 < 200ms, write p95 < 500ms, no N+1 on hot paths, 1 N+1 exists on a cold path (e.g., background export) but does not affect the production experience.
  • 7: p95 < 300ms; occasional 1–2 N+1 occurrences but not on hot paths.
  • 5: p95 < 800ms; obvious N+1 or missing indexes on hot paths.
  • 3: p95 ≥ 800ms or endpoints directly time out / take down the service.

Evidence collection method

  1. Run bash ./probes/probe-performance.sh <team> <base-url> <path>, read p50/p95/p99.
  2. Check N+1:
    # 找循环里调 query / repo 的反模式
    grep -rnE "for\s|forEach|\.map\(" src/ | grep -E "repo\.|query|findBy"
    
  3. For the main query, look at EXPLAIN (optional):EXPLAIN SELECT ... FROM items WHERE ...。

Evidence requirements

  • 1 <team>-autocannon.log + 1 <team>-perf-summary.txt(including p50/p95/p99).
  • At least 2 file:line demonstrating N+1 or optimization measures (or counter-evidence).
  • One conclusion about indexes / caching / batching.

8. Observability (weight 7)

Focus areas

  • Has structured logs (JSON or at least key=value), not a screen full of print / console.log。
  • Key operations have traces: request ID / user ID / business action.
  • Error logs include context (request body summary, stack trace).
  • Has metrics / health endpoints (at least /health)。

Anchors (based on console.log / print as a proportion of log statements)

  • 10: Unified logging library (pino / zap / loguru / slog / logback); all endpoints have request entry + exit logs + requestId;print/console.log count ≤ 2.
  • 9: Unified logging library + requestId on all endpoints + structured logs,print/console.log ≤ 5 and all on non-production paths (e.g., seed scripts),/health available.
  • 8: Structured logs cover the main endpoints and have requestId, but 1–2 secondary endpoints lack request exit logs,print/console.log 5–10 residual occurrences.
  • 7: Has a logging library, but some critical paths are missing logs, or occasional console.log residue (3–10 occurrences).
  • 5: Logging library exists but only logs errors;print/console.log proportion > 30%.
  • 3: Entirely relies on print / console.log, no requestId / structured logging, errors are handled by a try/catch printing one line.

Evidence collection method

  1. Count logging styles:
    grep -rncE "console\.log|console\.debug|\bprint\(" src/ | sort -t: -k2 -n -r | head
    grep -rncE "logger\.|log\.(info|warn|error|debug)" src/ | sort -t: -k2 -n -r | head
    
    Divide the two totals to get the "jank ratio".
  2. Check /health or /metrics:curl -i http://localhost:8080/health。
  3. Pick an error branch and read it to see whether context is logged.

Evidence requirements

  • A set of grep counts (logger count vs print/console.log count).
  • At least 2 file:line referencing logging configuration or key calls.
  • 1 /health or /metrics curl response.

9. Documentation (weight 6)

Focus areas

  • README includes startup steps, dependencies, environment variables, and example calls, without assuming the reader already understands.
  • API documentation (OpenAPI / Swagger / Postman collection / README section) exists and is in sync with the implementation.
  • Example curl / request bodies can be copied and run directly.
  • There is a short section on key design decisions (layering, authentication, data model).

Anchors

  • 10: README goes from zero to running within 5 minutes; OpenAPI documentation is complete and can be opened at /docs ; there is an architecture diagram or ADR.
  • 9: README runs smoothly from scratch, OpenAPI is complete and consistent with the implementation, there is an architecture diagram, only the ADR / design decision notes are brief (1–2 items covered in one sentence each).
  • 8: README startup steps + environment variables + example curl are complete, OpenAPI can be opened and the main interface fields are aligned, there is no architecture diagram but there is a paragraph of text explaining layering / authentication.
  • 7: README is sufficient, API documentation exists but 1–2 fields are outdated; no architecture diagram.
  • 5: README only has "npm install && npm start", API documentation relies on reading the code.
  • 3: Almost no documentation, no explanation beyond the spec.

Evidence collection method

  1. Run through it from scratch according to the README (or review the startup experience from step 1), and record any blockers.
  2. Find the API documentation:
    find . -type f \( -name "openapi*.y*ml" -o -name "swagger*.json" -o -name "*.postman_collection.json" \)
    curl -i http://localhost:8080/docs          # Swagger UI
    curl -i http://localhost:8080/openapi.json  # FastAPI / 多数框架
    
  3. Extract an example curl from the README, paste it, and run it once, recording whether it works.

Evidence requirements

  • At least 2 README.md:line or docs/*.md:line citations.
  • 1 actual test result of "running according to the README" (works / does not work + blockers).
  • Location of the API documentation + 1 example curl log.

Output checklist

Before finishing scoring, check each item one by one; if any does not pass, go back to the corresponding step and complete it:

  • .grading/reports/<team>-backend.md has been filled out according to this file's ## 报告模板 section structure, and all 9 dimensions have been fully scored (or explicitly marked N/A).
  • .grading/reports/<team>-backend.json has been produced and passed npx ajv-cli validate -s skills/score-schema.json verification.
  • Every dimension has evidence citations, and satisfies this file's ## 证据硬约束 section (≥7 / ≤4 points ≥2 items; 5–6 points ≥1 item).
  • .grading/probes/ Includes:<team>-robustness-summary.md + each probe <team>-<probe-name>.log、<team>-autocannon.log + <team>-perf-summary.txt、<team>-test.log、<team>-curl.log。
  • At the end of the report, give the "top 3 things that should be fixed first", each corresponding to a specific dimension and file:line.