fastapi-api-change
When to use
Any change to:
mantisanalysis/server.py(routes, schemas).mantisanalysis/session.py(source store, LRU, dark frame).mantisanalysis/figures.py(PNG byte serializer).mantisanalysis/image_io.py/extract.py/isp_modes.pywhen it changes what the server emits downstream.
Do NOT use this skill for:
- Pure analysis-math edits in
mantisanalysis/*_analysis.py/usaf_groups.pythat don't cross the API boundary (use unit tests only).
Workflow
Phase 1 — plan
- Identify which routes / schemas change.
- Check every frontend consumer of those routes:
grep -n "api/<route>" web/src/*.jsx. - If this is a new route, invoke
planner-architectto confirm the shape.
Phase 2 — edit the backend
- Define request / response models explicitly as
BaseModel. - Precise types (Tuple, List[float], Optional).
Field(default_factory=...)for mutable defaults.- Actionable
HTTPExceptiondetail strings on 4xx.
Phase 3 — run Tier 1 + Tier 2
python scripts/smoke_test.py --tier 1
python scripts/smoke_test.py --tier 2
Phase 4 — run Tier 3
python scripts/smoke_test.py --tier 3
Tier 3 boots the ASGI app in-process with fastapi.testclient and
hits health + sample load + thumbnail + USAF + FPN + DoF endpoints.
If your new route isn't exercised by Tier 3, either add it to the
smoke script OR add a targeted test in tests/unit/test_<route>.py.
Phase 5 — add a unit test
For schema additions / changes, add a test that:
- Sends a request with the new shape.
- Asserts every new field appears in the response.
- Asserts old fields still appear (backward compatibility) unless the change is explicitly documented as breaking.
Template:
# tests/unit/test_<route>.py
from fastapi.testclient import TestClient
from mantisanalysis.server import app
client = TestClient(app)
def test_<route>_happy_path():
r = client.post("/api/<route>", json={...})
assert r.status_code == 200
body = r.json()
assert "<new_field>" in body
# assertions on shape / values
Phase 6 — update the frontend consumer
If the response shape changed:
- Open every
web/src/*.jsxthat calls this route. - Update the parser / destructure to pick up new fields.
- Remove / handle removed fields.
- Verify with the
react-browser-ui-changeskill.
Phase 7 — error-path testing
For each new route:
- Test a
source_idthat doesn't exist → expect 404. - Test a malformed payload → expect 422 (Pydantic).
- If the route mutates state (
PUT /api/sources/{id}/isp), test the post-state is as expected (e.g., dark frame detached,raw_framere-extracted).
Phase 8 — document
If the change is non-trivial:
- Update
.agent/ARCHITECTURE.md— "Analysis response shape" table. - If new endpoint appears:
README.mdcurl example. - Add a
D-000Nentry inDECISIONS.mdif the shape choice was non-obvious.
Phase 9 — invoke reviewers
fastapi-backend-reviewer— contract + session state.test-coverage-reviewer— did the right level of test catch the risk?risk-skeptic— concurrency, eviction, partial failure.
Acceptance
- Tier 1 / Tier 2 / Tier 3 all green.
- pytest green (including any new targeted tests).
- Frontend updated if response shape changed; browser-verified.
- Error paths covered.
- Docs updated (ARCHITECTURE response-shape table at minimum).
-
fastapi-backend-reviewerpass with no P0/P1.
Escalation
- Channel-key schema change forbidden by rule 6 — stop and ask user.
- Session
STORELRU eviction behavior altered — add arisk-skepticreview and document inRISKS.md. - Heavy compute added to a debounced route — invoke
performance-reviewer.
Source: BioSensorsLab-Illinois/MantisAnalysis — distributed by TomeVault.