docs: tick off completed boxes in sub-project 1 plan (housekeeping)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Cyclone Production-Readiness (local-only) Implementation Plan
|
# Cyclone Production-Readiness (local-only) Implementation Plan
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking.
|
||||||
|
|
||||||
**Goal:** Add a backend in-memory batch store + 6 GET endpoints (with filter/sort/pagination and NDJSON streaming) to the Cyclone EDI suite, wire the existing 4 React pages + Upload page to live data via `@tanstack/react-query` v5, ship 4 fresh reference notes + a root README rewrite, and lock the local-only deploy posture (`127.0.0.1:8000`, no auth, no internet exposure). All on a single branch, with frequent commits, fully testable at every checkpoint.
|
**Goal:** Add a backend in-memory batch store + 6 GET endpoints (with filter/sort/pagination and NDJSON streaming) to the Cyclone EDI suite, wire the existing 4 React pages + Upload page to live data via `@tanstack/react-query` v5, ship 4 fresh reference notes + a root README rewrite, and lock the local-only deploy posture (`127.0.0.1:8000`, no auth, no internet exposure). All on a single branch, with frequent commits, fully testable at every checkpoint.
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
- Create: `backend/src/cyclone/store.py`
|
- Create: `backend/src/cyclone/store.py`
|
||||||
- Create: `backend/tests/test_store.py`
|
- Create: `backend/tests/test_store.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Write the failing test for `BatchRecord` construction + module import**
|
- [x] **Step 1: Write the failing test for `BatchRecord` construction + module import**
|
||||||
|
|
||||||
`backend/tests/test_store.py`:
|
`backend/tests/test_store.py`:
|
||||||
```python
|
```python
|
||||||
@@ -172,12 +172,12 @@ def test_get_missing_returns_none():
|
|||||||
|
|
||||||
> Note: if your `ClaimOutput` / `Envelope` / `ValidationReport` / `ParseResult` model fields differ, adjust the `_make_claim` / `_make_result` stubs to match the real field names. Run `python -c "from cyclone.parsers.models import ClaimOutput; help(ClaimOutput)"` to confirm.
|
> Note: if your `ClaimOutput` / `Envelope` / `ValidationReport` / `ParseResult` model fields differ, adjust the `_make_claim` / `_make_result` stubs to match the real field names. Run `python -c "from cyclone.parsers.models import ClaimOutput; help(ClaimOutput)"` to confirm.
|
||||||
|
|
||||||
- [ ] **Step 2: Run the test to verify it fails**
|
- [x] **Step 2: Run the test to verify it fails**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
||||||
Expected: `ModuleNotFoundError: No module named 'cyclone.store'` (or similar import error).
|
Expected: `ModuleNotFoundError: No module named 'cyclone.store'` (or similar import error).
|
||||||
|
|
||||||
- [ ] **Step 3: Implement `BatchRecord` + empty `InMemoryStore` (no mappers yet)**
|
- [x] **Step 3: Implement `BatchRecord` + empty `InMemoryStore` (no mappers yet)**
|
||||||
|
|
||||||
`backend/src/cyclone/store.py`:
|
`backend/src/cyclone/store.py`:
|
||||||
```python
|
```python
|
||||||
@@ -254,12 +254,12 @@ def utcnow_iso() -> str:
|
|||||||
|
|
||||||
> Note: the imports `from cyclone.parsers.models import ParseResult` and `from cyclone.parsers.models_835 import ParseResult835` are correct based on the existing project layout. If the Pydantic v2 union complains about the discriminator, drop the `discriminator=None` and let Pydantic use the default behavior — the actual class is determined at runtime by the field type.
|
> Note: the imports `from cyclone.parsers.models import ParseResult` and `from cyclone.parsers.models_835 import ParseResult835` are correct based on the existing project layout. If the Pydantic v2 union complains about the discriminator, drop the `discriminator=None` and let Pydantic use the default behavior — the actual class is determined at runtime by the field type.
|
||||||
|
|
||||||
- [ ] **Step 4: Run the tests to verify they pass**
|
- [x] **Step 4: Run the tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
||||||
Expected: all 4 tests pass.
|
Expected: all 4 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
||||||
@@ -274,7 +274,7 @@ git commit -m "feat(backend): add cyclone.store with BatchRecord and InMemorySto
|
|||||||
- Modify: `backend/src/cyclone/store.py`
|
- Modify: `backend/src/cyclone/store.py`
|
||||||
- Modify: `backend/tests/test_store.py`
|
- Modify: `backend/tests/test_store.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests for the mappers**
|
- [x] **Step 1: Add failing tests for the mappers**
|
||||||
|
|
||||||
Append to `backend/tests/test_store.py`:
|
Append to `backend/tests/test_store.py`:
|
||||||
```python
|
```python
|
||||||
@@ -359,12 +359,12 @@ def test_to_activity_event_uses_iso_timestamp():
|
|||||||
|
|
||||||
> Adjust stub values to match your actual Pydantic model field names. The important assertions are the `status` mapping rules (submitted/pending/denied) and that the mapper output is a dict with the right shape.
|
> Adjust stub values to match your actual Pydantic model field names. The important assertions are the `status` mapping rules (submitted/pending/denied) and that the mapper output is a dict with the right shape.
|
||||||
|
|
||||||
- [ ] **Step 2: Run the test to verify it fails**
|
- [x] **Step 2: Run the test to verify it fails**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
||||||
Expected: `ImportError: cannot import name 'to_ui_claim' from 'cyclone.store'`.
|
Expected: `ImportError: cannot import name 'to_ui_claim' from 'cyclone.store'`.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement the mappers**
|
- [x] **Step 3: Implement the mappers**
|
||||||
|
|
||||||
Add to `backend/src/cyclone/store.py` (after `utcnow_iso`):
|
Add to `backend/src/cyclone/store.py` (after `utcnow_iso`):
|
||||||
```python
|
```python
|
||||||
@@ -509,12 +509,12 @@ def to_activity_event(
|
|||||||
> from cyclone.parsers.models_835 import ClaimPayment, ParseResult835
|
> from cyclone.parsers.models_835 import ClaimPayment, ParseResult835
|
||||||
> ```)
|
> ```)
|
||||||
|
|
||||||
- [ ] **Step 4: Run the tests to verify they pass**
|
- [x] **Step 4: Run the tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
||||||
Expected: all 10 tests pass.
|
Expected: all 10 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
||||||
@@ -529,7 +529,7 @@ git commit -m "feat(backend): add store mappers (claim, remittance, provider, ac
|
|||||||
- Modify: `backend/src/cyclone/store.py`
|
- Modify: `backend/src/cyclone/store.py`
|
||||||
- Modify: `backend/tests/test_store.py`
|
- Modify: `backend/tests/test_store.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests for the iterators**
|
- [x] **Step 1: Add failing tests for the iterators**
|
||||||
|
|
||||||
Append to `backend/tests/test_store.py`:
|
Append to `backend/tests/test_store.py`:
|
||||||
```python
|
```python
|
||||||
@@ -595,12 +595,12 @@ def test_recent_activity_returns_newest_first():
|
|||||||
assert out[1]["timestamp"] == "2026-06-19T11:00:00Z"
|
assert out[1]["timestamp"] == "2026-06-19T11:00:00Z"
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [x] **Step 2: Run tests to verify they fail**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v -k "iter_ or distinct_ or recent_"`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v -k "iter_ or distinct_ or recent_"`
|
||||||
Expected: `AttributeError: 'InMemoryStore' object has no attribute 'iter_claims'`.
|
Expected: `AttributeError: 'InMemoryStore' object has no attribute 'iter_claims'`.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement the iterators**
|
- [x] **Step 3: Implement the iterators**
|
||||||
|
|
||||||
Add to `backend/src/cyclone/store.py` (as methods on `InMemoryStore`):
|
Add to `backend/src/cyclone/store.py` (as methods on `InMemoryStore`):
|
||||||
```python
|
```python
|
||||||
@@ -724,12 +724,12 @@ Add to `backend/src/cyclone/store.py` (as methods on `InMemoryStore`):
|
|||||||
return events[:limit]
|
return events[:limit]
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [x] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_store.py -v`
|
||||||
Expected: all tests pass (15 total now).
|
Expected: all tests pass (15 total now).
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
git add backend/src/cyclone/store.py backend/tests/test_store.py
|
||||||
@@ -744,7 +744,7 @@ git commit -m "feat(backend): add store iterators (claims, remits, providers, ac
|
|||||||
- Modify: `backend/src/cyclone/api.py`
|
- Modify: `backend/src/cyclone/api.py`
|
||||||
- Create: `backend/tests/test_api_parse_persists.py`
|
- Create: `backend/tests/test_api_parse_persists.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests**
|
- [x] **Step 1: Add failing tests**
|
||||||
|
|
||||||
`backend/tests/test_api_parse_persists.py`:
|
`backend/tests/test_api_parse_persists.py`:
|
||||||
```python
|
```python
|
||||||
@@ -807,12 +807,12 @@ def test_failed_parse_837_does_not_create_batch(client: TestClient):
|
|||||||
assert len(global_store.list()) == 0
|
assert len(global_store.list()) == 0
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [x] **Step 2: Run tests to verify they fail**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_parse_persists.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_parse_persists.py -v`
|
||||||
Expected: first test fails because `len(global_store.list()) == 1` is False (no batches added yet).
|
Expected: first test fails because `len(global_store.list()) == 1` is False (no batches added yet).
|
||||||
|
|
||||||
- [ ] **Step 3: Modify `cyclone.api` to call `store.add()` on success**
|
- [x] **Step 3: Modify `cyclone.api` to call `store.add()` on success**
|
||||||
|
|
||||||
In `backend/src/cyclone/api.py`, add the import near the top:
|
In `backend/src/cyclone/api.py`, add the import near the top:
|
||||||
```python
|
```python
|
||||||
@@ -853,12 +853,12 @@ import uuid
|
|||||||
|
|
||||||
> The exact location depends on your existing parse-route structure. The key invariant is: `store.add(record)` is called only after the parser successfully produces a result, and *before* the response is returned.
|
> The exact location depends on your existing parse-route structure. The key invariant is: `store.add(record)` is called only after the parser successfully produces a result, and *before* the response is returned.
|
||||||
|
|
||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [x] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_parse_persists.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_parse_persists.py -v`
|
||||||
Expected: both tests pass.
|
Expected: both tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/api.py backend/tests/test_api_parse_persists.py
|
git add backend/src/cyclone/api.py backend/tests/test_api_parse_persists.py
|
||||||
@@ -873,7 +873,7 @@ git commit -m "feat(backend): wire parse-837/parse-835 to persist to InMemorySto
|
|||||||
- Modify: `backend/src/cyclone/api.py`
|
- Modify: `backend/src/cyclone/api.py`
|
||||||
- Modify: `backend/tests/test_api_gets.py` (new)
|
- Modify: `backend/tests/test_api_gets.py` (new)
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests for the batch endpoints**
|
- [x] **Step 1: Add failing tests for the batch endpoints**
|
||||||
|
|
||||||
`backend/tests/test_api_gets.py`:
|
`backend/tests/test_api_gets.py`:
|
||||||
```python
|
```python
|
||||||
@@ -962,12 +962,12 @@ def test_get_batch_404_when_missing(client: TestClient):
|
|||||||
assert resp.status_code == 404
|
assert resp.status_code == 404
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [x] **Step 2: Run tests to verify they fail**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v`
|
||||||
Expected: all 4 tests fail with 404 (routes don't exist yet).
|
Expected: all 4 tests fail with 404 (routes don't exist yet).
|
||||||
|
|
||||||
- [ ] **Step 3: Implement the routes**
|
- [x] **Step 3: Implement the routes**
|
||||||
|
|
||||||
Add to `backend/src/cyclone/api.py`:
|
Add to `backend/src/cyclone/api.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1008,12 +1008,12 @@ def get_batch(batch_id: str):
|
|||||||
return rec.result
|
return rec.result
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [x] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "batches"`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "batches"`
|
||||||
Expected: 4 tests pass.
|
Expected: 4 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
||||||
@@ -1028,7 +1028,7 @@ git commit -m "feat(backend): add GET /api/batches and GET /api/batches/{id}"
|
|||||||
- Modify: `backend/src/cyclone/api.py`
|
- Modify: `backend/src/cyclone/api.py`
|
||||||
- Modify: `backend/tests/test_api_gets.py`
|
- Modify: `backend/tests/test_api_gets.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests**
|
- [x] **Step 1: Add failing tests**
|
||||||
|
|
||||||
Append to `backend/tests/test_api_gets.py`:
|
Append to `backend/tests/test_api_gets.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1076,12 +1076,12 @@ def test_claims_pagination_limit_offset(seeded_store):
|
|||||||
assert body1["has_more"] is True
|
assert body1["has_more"] is True
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [x] **Step 2: Run tests to verify they fail**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "claims_"`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "claims_"`
|
||||||
Expected: 404 / Not Found for `/api/claims`.
|
Expected: 404 / Not Found for `/api/claims`.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement the route**
|
- [x] **Step 3: Implement the route**
|
||||||
|
|
||||||
Add to `backend/src/cyclone/api.py`:
|
Add to `backend/src/cyclone/api.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1115,12 +1115,12 @@ def list_claims(
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [x] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "claims_"`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "claims_"`
|
||||||
Expected: 5 tests pass.
|
Expected: 5 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
||||||
@@ -1135,7 +1135,7 @@ git commit -m "feat(backend): add GET /api/claims with filter/sort/pagination"
|
|||||||
- Modify: `backend/src/cyclone/api.py`
|
- Modify: `backend/src/cyclone/api.py`
|
||||||
- Modify: `backend/tests/test_api_gets.py`
|
- Modify: `backend/tests/test_api_gets.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing tests**
|
- [x] **Step 1: Add failing tests**
|
||||||
|
|
||||||
Append to `backend/tests/test_api_gets.py`:
|
Append to `backend/tests/test_api_gets.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1198,12 +1198,12 @@ def test_activity_returns_one_event_per_claim(seeded_store):
|
|||||||
assert all(e["kind"] == "claim_submitted" for e in body["items"])
|
assert all(e["kind"] == "claim_submitted" for e in body["items"])
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [x] **Step 2: Run tests to verify they fail**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "remittances_ or providers_ or activity_"`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "remittances_ or providers_ or activity_"`
|
||||||
Expected: 6 tests fail with 404.
|
Expected: 6 tests fail with 404.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement the three routes**
|
- [x] **Step 3: Implement the three routes**
|
||||||
|
|
||||||
Add to `backend/src/cyclone/api.py`:
|
Add to `backend/src/cyclone/api.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1269,12 +1269,12 @@ def list_activity(
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [x] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "remittances_ or providers_ or activity_"`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_gets.py -v -k "remittances_ or providers_ or activity_"`
|
||||||
Expected: 6 tests pass.
|
Expected: 6 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
git add backend/src/cyclone/api.py backend/tests/test_api_gets.py
|
||||||
@@ -1289,7 +1289,7 @@ git commit -m "feat(backend): add GET /api/{remittances,providers,activity}"
|
|||||||
- Modify: `backend/src/cyclone/api.py`
|
- Modify: `backend/src/cyclone/api.py`
|
||||||
- Create: `backend/tests/test_api_streaming.py`
|
- Create: `backend/tests/test_api_streaming.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Add failing test**
|
- [x] **Step 1: Add failing test**
|
||||||
|
|
||||||
`backend/tests/test_api_streaming.py`:
|
`backend/tests/test_api_streaming.py`:
|
||||||
```python
|
```python
|
||||||
@@ -1346,12 +1346,12 @@ def test_claims_ndjson_returns_parseable_lines(seeded_client):
|
|||||||
assert summary["data"]["has_more"] is False
|
assert summary["data"]["has_more"] is False
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run test to verify it fails**
|
- [x] **Step 2: Run test to verify it fails**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_streaming.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_streaming.py -v`
|
||||||
Expected: response is JSON, not NDJSON — content-type assertion fails.
|
Expected: response is JSON, not NDJSON — content-type assertion fails.
|
||||||
|
|
||||||
- [ ] **Step 3: Implement streaming on `/api/claims` (and apply the same pattern to remittances/providers/activity)**
|
- [x] **Step 3: Implement streaming on `/api/claims` (and apply the same pattern to remittances/providers/activity)**
|
||||||
|
|
||||||
In `backend/src/cyclone/api.py`, refactor `list_claims` to content-negotiate:
|
In `backend/src/cyclone/api.py`, refactor `list_claims` to content-negotiate:
|
||||||
|
|
||||||
@@ -1405,12 +1405,12 @@ def list_claims(
|
|||||||
|
|
||||||
Apply the same pattern to `list_remittances`, `list_providers`, and `list_activity` (each branches on `request.headers.get("accept") == "application/x-ndjson"` and returns `StreamingResponse` when set).
|
Apply the same pattern to `list_remittances`, `list_providers`, and `list_activity` (each branches on `request.headers.get("accept") == "application/x-ndjson"` and returns `StreamingResponse` when set).
|
||||||
|
|
||||||
- [ ] **Step 4: Run test to verify it passes**
|
- [x] **Step 4: Run test to verify it passes**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest tests/test_api_streaming.py -v`
|
Run: `cd backend && .venv/bin/pytest tests/test_api_streaming.py -v`
|
||||||
Expected: test passes.
|
Expected: test passes.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [x] **Step 5: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/api.py backend/tests/test_api_streaming.py
|
git add backend/src/cyclone/api.py backend/tests/test_api_streaming.py
|
||||||
@@ -1424,7 +1424,7 @@ git commit -m "feat(backend): add NDJSON streaming on list endpoints"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `backend/src/cyclone/__main__.py`
|
- Modify: `backend/src/cyclone/__main__.py`
|
||||||
|
|
||||||
- [ ] **Step 1: Update `__main__.py` to bind loopback and honor env vars**
|
- [x] **Step 1: Update `__main__.py` to bind loopback and honor env vars**
|
||||||
|
|
||||||
Replace `backend/src/cyclone/__main__.py` with:
|
Replace `backend/src/cyclone/__main__.py` with:
|
||||||
```python
|
```python
|
||||||
@@ -1470,7 +1470,7 @@ if __name__ == "__main__":
|
|||||||
main()
|
main()
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify locally (manual)**
|
- [x] **Step 2: Verify locally (manual)**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/python -m cyclone serve &`
|
Run: `cd backend && .venv/bin/python -m cyclone serve &`
|
||||||
Then: `curl -s http://127.0.0.1:8000/api/health | jq .` → should print `{"status": "ok", "version": "0.1.0"}`.
|
Then: `curl -s http://127.0.0.1:8000/api/health | jq .` → should print `{"status": "ok", "version": "0.1.0"}`.
|
||||||
@@ -1478,7 +1478,7 @@ Then: `curl -s http://0.0.0.0:8000/api/health` → should fail (refused; loopbac
|
|||||||
|
|
||||||
Kill the server: `kill %1` (or `pkill -f 'cyclone.api:app'`).
|
Kill the server: `kill %1` (or `pkill -f 'cyclone.api:app'`).
|
||||||
|
|
||||||
- [ ] **Step 3: Commit**
|
- [x] **Step 3: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add backend/src/cyclone/__main__.py
|
git add backend/src/cyclone/__main__.py
|
||||||
@@ -1489,12 +1489,12 @@ git commit -m "feat(backend): bind serve to 127.0.0.1:8000, honor CYCLONE_PORT/C
|
|||||||
|
|
||||||
### Task 10: Run the full backend test suite + manual smoke
|
### Task 10: Run the full backend test suite + manual smoke
|
||||||
|
|
||||||
- [ ] **Step 1: Run all backend tests**
|
- [x] **Step 1: Run all backend tests**
|
||||||
|
|
||||||
Run: `cd backend && .venv/bin/pytest -v`
|
Run: `cd backend && .venv/bin/pytest -v`
|
||||||
Expected: all tests pass (existing 121 + new ~23 = 144+ total).
|
Expected: all tests pass (existing 121 + new ~23 = 144+ total).
|
||||||
|
|
||||||
- [ ] **Step 2: Manual smoke (in two terminals)**
|
- [x] **Step 2: Manual smoke (in two terminals)**
|
||||||
|
|
||||||
Terminal 1: `cd backend && .venv/bin/python -m cyclone serve`
|
Terminal 1: `cd backend && .venv/bin/python -m cyclone serve`
|
||||||
Terminal 2: `curl -s -X POST -F "file=@backend/tests/fixtures/co_medicaid_837p.txt" -H "Accept: application/json" http://127.0.0.1:8000/api/parse-837 | jq .summary`
|
Terminal 2: `curl -s -X POST -F "file=@backend/tests/fixtures/co_medicaid_837p.txt" -H "Accept: application/json" http://127.0.0.1:8000/api/parse-837 | jq .summary`
|
||||||
@@ -1502,7 +1502,7 @@ Then: `curl -s 'http://127.0.0.1:8000/api/claims?status=submitted' | jq '{total,
|
|||||||
Then: `curl -s 'http://127.0.0.1:8000/api/claims' -H 'Accept: application/x-ndjson' | head -4`
|
Then: `curl -s 'http://127.0.0.1:8000/api/claims' -H 'Accept: application/x-ndjson' | head -4`
|
||||||
Expected: parse succeeds; `/api/claims` returns 2 items; NDJSON returns 2 item lines + 1 summary line.
|
Expected: parse succeeds; `/api/claims` returns 2 items; NDJSON returns 2 item lines + 1 summary line.
|
||||||
|
|
||||||
- [ ] **Step 3: Commit any leftover changes (likely none)**
|
- [x] **Step 3: Commit any leftover changes (likely none)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git status # should be clean
|
git status # should be clean
|
||||||
@@ -1517,12 +1517,12 @@ git status # should be clean
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `package.json`
|
- Modify: `package.json`
|
||||||
|
|
||||||
- [ ] **Step 1: Add the dep**
|
- [x] **Step 1: Add the dep**
|
||||||
|
|
||||||
Run: `cd /Users/openclaw/dev/cyclone && npm install @tanstack/react-query@^5.59.0`
|
Run: `cd /Users/openclaw/dev/cyclone && npm install @tanstack/react-query@^5.59.0`
|
||||||
Expected: `package.json` updated; `node_modules` grows.
|
Expected: `package.json` updated; `node_modules` grows.
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add package.json package-lock.json
|
git add package.json package-lock.json
|
||||||
@@ -1536,7 +1536,7 @@ git commit -m "feat(frontend): add @tanstack/react-query ^5.59.0"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/main.tsx`
|
- Modify: `src/main.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Update `main.tsx`**
|
- [x] **Step 1: Update `main.tsx`**
|
||||||
|
|
||||||
Replace `src/main.tsx` with:
|
Replace `src/main.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1567,12 +1567,12 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build still passes**
|
- [x] **Step 2: Verify build still passes**
|
||||||
|
|
||||||
Run: `npm run build`
|
Run: `npm run build`
|
||||||
Expected: build succeeds with no TS errors.
|
Expected: build succeeds with no TS errors.
|
||||||
|
|
||||||
- [ ] **Step 3: Commit**
|
- [x] **Step 3: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add src/main.tsx
|
git add src/main.tsx
|
||||||
@@ -1586,7 +1586,7 @@ git commit -m "feat(frontend): wrap App in QueryClientProvider"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `tailwind.config.js`
|
- Modify: `tailwind.config.js`
|
||||||
|
|
||||||
- [ ] **Step 1: Add the keyframes**
|
- [x] **Step 1: Add the keyframes**
|
||||||
|
|
||||||
In `tailwind.config.js`, inside `theme.extend.keyframes`, add three new entries (next to the existing `fade-in`):
|
In `tailwind.config.js`, inside `theme.extend.keyframes`, add three new entries (next to the existing `fade-in`):
|
||||||
```js
|
```js
|
||||||
@@ -1605,7 +1605,7 @@ In `tailwind.config.js`, inside `theme.extend.keyframes`, add three new entries
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add tailwind.config.js
|
git add tailwind.config.js
|
||||||
@@ -1619,7 +1619,7 @@ git commit -m "feat(frontend): add shimmer, scan, row-flash keyframes"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `src/components/ui/skeleton.tsx`
|
- Create: `src/components/ui/skeleton.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
`src/components/ui/skeleton.tsx`:
|
`src/components/ui/skeleton.tsx`:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1679,12 +1679,12 @@ export function Skeleton({ className, variant = "row" }: SkeletonProps) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build**
|
- [x] **Step 2: Verify build**
|
||||||
|
|
||||||
Run: `npm run build`
|
Run: `npm run build`
|
||||||
Expected: passes.
|
Expected: passes.
|
||||||
|
|
||||||
- [ ] **Step 3: Commit**
|
- [x] **Step 3: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add src/components/ui/skeleton.tsx
|
git add src/components/ui/skeleton.tsx
|
||||||
@@ -1698,7 +1698,7 @@ git commit -m "feat(frontend): add Skeleton UI primitive (hairline + scanline-sh
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `src/components/ui/empty-state.tsx`
|
- Create: `src/components/ui/empty-state.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
`src/components/ui/empty-state.tsx`:
|
`src/components/ui/empty-state.tsx`:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1726,7 +1726,7 @@ export function EmptyState({ eyebrow, message }: EmptyStateProps) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -1741,7 +1741,7 @@ git commit -m "feat(frontend): add EmptyState primitive (instrument-label eyebro
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `src/components/ui/error-state.tsx`
|
- Create: `src/components/ui/error-state.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
`src/components/ui/error-state.tsx`:
|
`src/components/ui/error-state.tsx`:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1776,7 +1776,7 @@ export function ErrorState({ error, onRetry }: ErrorStateProps) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -1791,7 +1791,7 @@ git commit -m "feat(frontend): add ErrorState primitive (destructive hairline +
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `src/components/ui/filter-chips.tsx`
|
- Create: `src/components/ui/filter-chips.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
`src/components/ui/filter-chips.tsx`:
|
`src/components/ui/filter-chips.tsx`:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1847,7 +1847,7 @@ export function FilterChips({
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -1862,7 +1862,7 @@ git commit -m "feat(frontend): add FilterChips primitive (read-only pill row)"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `src/components/ui/pagination.tsx`
|
- Create: `src/components/ui/pagination.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
`src/components/ui/pagination.tsx`:
|
`src/components/ui/pagination.tsx`:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -1951,7 +1951,7 @@ export function Pagination({ page, pageSize, total, onChange }: PaginationProps)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -1966,7 +1966,7 @@ git commit -m "feat(frontend): add Pagination primitive (nav-active echo, num pa
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/components/Layout.tsx`
|
- Modify: `src/components/Layout.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Update `Layout.tsx`**
|
- [x] **Step 1: Update `Layout.tsx`**
|
||||||
|
|
||||||
Replace `src/components/Layout.tsx` with:
|
Replace `src/components/Layout.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -2000,7 +2000,7 @@ export function Layout() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -2016,7 +2016,7 @@ git commit -m "feat(frontend): add 1px scan-line refetch indicator to Layout"
|
|||||||
- Modify: `src/lib/api.ts`
|
- Modify: `src/lib/api.ts`
|
||||||
- Create: `src/lib/api.test.ts` (extend with 3 tests)
|
- Create: `src/lib/api.test.ts` (extend with 3 tests)
|
||||||
|
|
||||||
- [ ] **Step 1: Add GET methods + types**
|
- [x] **Step 1: Add GET methods + types**
|
||||||
|
|
||||||
In `src/lib/api.ts`, before the `export const api = {` line, add:
|
In `src/lib/api.ts`, before the `export const api = {` line, add:
|
||||||
```ts
|
```ts
|
||||||
@@ -2174,7 +2174,7 @@ export const api = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Add 3 unit tests in `src/lib/api.test.ts`**
|
- [x] **Step 2: Add 3 unit tests in `src/lib/api.test.ts`**
|
||||||
|
|
||||||
Create `src/lib/api.test.ts`:
|
Create `src/lib/api.test.ts`:
|
||||||
```ts
|
```ts
|
||||||
@@ -2233,12 +2233,12 @@ describe("api GET helpers", () => {
|
|||||||
|
|
||||||
> If `vitest` is not already configured, add `"test": "vitest run"` to `package.json` `scripts` and `vitest` to devDependencies. Run `npm install -D vitest` if needed.
|
> If `vitest` is not already configured, add `"test": "vitest run"` to `package.json` `scripts` and `vitest` to devDependencies. Run `npm install -D vitest` if needed.
|
||||||
|
|
||||||
- [ ] **Step 3: Run the tests**
|
- [x] **Step 3: Run the tests**
|
||||||
|
|
||||||
Run: `npm test -- src/lib/api.test.ts`
|
Run: `npm test -- src/lib/api.test.ts`
|
||||||
Expected: 3 tests pass.
|
Expected: 3 tests pass.
|
||||||
|
|
||||||
- [ ] **Step 4: Commit**
|
- [x] **Step 4: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add src/lib/api.ts src/lib/api.test.ts package.json package-lock.json
|
git add src/lib/api.ts src/lib/api.test.ts package.json package-lock.json
|
||||||
@@ -2257,7 +2257,7 @@ git commit -m "feat(frontend): add listBatches/getBatch/listClaims/listRemittanc
|
|||||||
- Create: `src/hooks/useActivity.ts`
|
- Create: `src/hooks/useActivity.ts`
|
||||||
- Create: `src/hooks/useParse.ts`
|
- Create: `src/hooks/useParse.ts`
|
||||||
|
|
||||||
- [ ] **Step 1: `useBatches.ts`**
|
- [x] **Step 1: `useBatches.ts`**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
@@ -2272,7 +2272,7 @@ export function useBatches() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: `useClaims.ts`** (with fallback to zustand when `!api.isConfigured`)
|
- [x] **Step 2: `useClaims.ts`** (with fallback to zustand when `!api.isConfigured`)
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
@@ -2327,7 +2327,7 @@ export function useClaims(params: ListClaimsParams) {
|
|||||||
export { EMPTY as EMPTY_CLAIMS };
|
export { EMPTY as EMPTY_CLAIMS };
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 3: `useRemittances.ts`**
|
- [x] **Step 3: `useRemittances.ts`**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
@@ -2367,7 +2367,7 @@ export function useRemittances(params: ListRemittancesParams) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4: `useProviders.ts`**
|
- [x] **Step 4: `useProviders.ts`**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
@@ -2400,7 +2400,7 @@ export function useProviders(params: ListProvidersParams = {}) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 5: `useActivity.ts`**
|
- [x] **Step 5: `useActivity.ts`**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
@@ -2434,7 +2434,7 @@ export function useActivity(params: ListActivityParams = {}) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 6: `useParse.ts`**
|
- [x] **Step 6: `useParse.ts`**
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
@@ -2458,7 +2458,7 @@ export function useParse(kind: "837p" | "835") {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 7: Verify build + commit**
|
- [x] **Step 7: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -2473,7 +2473,7 @@ git commit -m "feat(frontend): add 6 query/mutation hooks (batches, claims, remi
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/pages/Claims.tsx`
|
- Modify: `src/pages/Claims.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `src/pages/Claims.tsx` with:
|
Replace `src/pages/Claims.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -2779,7 +2779,7 @@ export function Claims() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -2794,7 +2794,7 @@ git commit -m "feat(frontend): refactor Claims page to useClaims + skeleton/empt
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/pages/Remittances.tsx`
|
- Modify: `src/pages/Remittances.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `src/pages/Remittances.tsx` with:
|
Replace `src/pages/Remittances.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -2945,7 +2945,7 @@ export function Remittances() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -2960,7 +2960,7 @@ git commit -m "feat(frontend): refactor Remittances page to useRemittances + UX
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/pages/Providers.tsx`
|
- Modify: `src/pages/Providers.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `src/pages/Providers.tsx` with:
|
Replace `src/pages/Providers.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -3068,7 +3068,7 @@ export function Providers() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -3083,7 +3083,7 @@ git commit -m "feat(frontend): refactor Providers page to useProviders + UX patt
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/pages/ActivityLog.tsx`
|
- Modify: `src/pages/ActivityLog.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `src/pages/ActivityLog.tsx` with:
|
Replace `src/pages/ActivityLog.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -3136,7 +3136,7 @@ export function ActivityLog() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -3151,7 +3151,7 @@ git commit -m "feat(frontend): refactor ActivityLog page to useActivity + UX pat
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `src/pages/Upload.tsx`
|
- Modify: `src/pages/Upload.tsx`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `src/pages/Upload.tsx` with:
|
Replace `src/pages/Upload.tsx` with:
|
||||||
```tsx
|
```tsx
|
||||||
@@ -3592,7 +3592,7 @@ export function Upload() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Verify build + commit**
|
- [x] **Step 2: Verify build + commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -3604,17 +3604,17 @@ git commit -m "feat(frontend): refactor Upload page to use useParse mutation"
|
|||||||
|
|
||||||
### Task 27: Run frontend smoke (build + dev server check)
|
### Task 27: Run frontend smoke (build + dev server check)
|
||||||
|
|
||||||
- [ ] **Step 1: Build**
|
- [x] **Step 1: Build**
|
||||||
|
|
||||||
Run: `npm run build`
|
Run: `npm run build`
|
||||||
Expected: passes (no TS errors, no unused-import warnings).
|
Expected: passes (no TS errors, no unused-import warnings).
|
||||||
|
|
||||||
- [ ] **Step 2: Type-check**
|
- [x] **Step 2: Type-check**
|
||||||
|
|
||||||
Run: `npm run typecheck`
|
Run: `npm run typecheck`
|
||||||
Expected: passes.
|
Expected: passes.
|
||||||
|
|
||||||
- [ ] **Step 3: Commit any fixups (likely none)**
|
- [x] **Step 3: Commit any fixups (likely none)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git status # should be clean
|
git status # should be clean
|
||||||
@@ -3629,7 +3629,7 @@ git status # should be clean
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `docs/reference/837p.md`
|
- Create: `docs/reference/837p.md`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# 837P — Professional Claims (005010X222A1)
|
# 837P — Professional Claims (005010X222A1)
|
||||||
@@ -3699,7 +3699,7 @@ full walker.
|
|||||||
| `R300_subscriber_present` | error | `NM1*IL` (subscriber) present |
|
| `R300_subscriber_present` | error | `NM1*IL` (subscriber) present |
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add docs/reference/837p.md
|
git add docs/reference/837p.md
|
||||||
@@ -3713,7 +3713,7 @@ git commit -m "docs: add 837p reference note"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `docs/reference/835.md`
|
- Create: `docs/reference/835.md`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# 835 — Electronic Remittance Advice (005010X221A1)
|
# 835 — Electronic Remittance Advice (005010X221A1)
|
||||||
@@ -3791,7 +3791,7 @@ date of service is deferred to sub-project 2. Cyclone currently stores the
|
|||||||
835 output as-is.
|
835 output as-is.
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add docs/reference/835.md
|
git add docs/reference/835.md
|
||||||
@@ -3805,7 +3805,7 @@ git commit -m "docs: add 835 reference note"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `docs/reference/x12naming.md`
|
- Create: `docs/reference/x12naming.md`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# X12 naming conventions
|
# X12 naming conventions
|
||||||
@@ -3876,7 +3876,7 @@ rest of the file by those characters.
|
|||||||
- `^` — repetition separator
|
- `^` — repetition separator
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add docs/reference/x12naming.md
|
git add docs/reference/x12naming.md
|
||||||
@@ -3890,7 +3890,7 @@ git commit -m "docs: add x12 naming reference note"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Create: `docs/reference/co-medicaid.md`
|
- Create: `docs/reference/co-medicaid.md`
|
||||||
|
|
||||||
- [ ] **Step 1: Create the file**
|
- [x] **Step 1: Create the file**
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Colorado Medicaid — payer specifics
|
# Colorado Medicaid — payer specifics
|
||||||
@@ -3966,7 +3966,7 @@ The pattern is:
|
|||||||
4. Update this note + the 837p/835 notes with the new payer's specifics.
|
4. Update this note + the 837p/835 notes with the new payer's specifics.
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add docs/reference/co-medicaid.md
|
git add docs/reference/co-medicaid.md
|
||||||
@@ -3980,7 +3980,7 @@ git commit -m "docs: add CO Medicaid reference note"
|
|||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `README.md`
|
- Modify: `README.md`
|
||||||
|
|
||||||
- [ ] **Step 1: Replace the file**
|
- [x] **Step 1: Replace the file**
|
||||||
|
|
||||||
Replace `README.md` (root) with:
|
Replace `README.md` (root) with:
|
||||||
```markdown
|
```markdown
|
||||||
@@ -4103,7 +4103,7 @@ No license file yet; this is internal-use software. Add a `LICENSE` file
|
|||||||
when one is decided.
|
when one is decided.
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Commit**
|
- [x] **Step 2: Commit**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add README.md
|
git add README.md
|
||||||
@@ -4116,22 +4116,22 @@ git commit -m "docs: rewrite root README for sub-project 1"
|
|||||||
|
|
||||||
### Task 33: End-to-end smoke test (manual + documented)
|
### Task 33: End-to-end smoke test (manual + documented)
|
||||||
|
|
||||||
- [ ] **Step 1: Start the backend**
|
- [x] **Step 1: Start the backend**
|
||||||
|
|
||||||
Terminal 1: `cd backend && .venv/bin/python -m cyclone serve`
|
Terminal 1: `cd backend && .venv/bin/python -m cyclone serve`
|
||||||
Expected: log line "Uvicorn running on http://127.0.0.1:8000".
|
Expected: log line "Uvicorn running on http://127.0.0.1:8000".
|
||||||
|
|
||||||
- [ ] **Step 2: Confirm loopback-only**
|
- [x] **Step 2: Confirm loopback-only**
|
||||||
|
|
||||||
Terminal 2: `curl -s http://127.0.0.1:8000/api/health | jq .` → `{"status": "ok", "version": "0.1.0"}`.
|
Terminal 2: `curl -s http://127.0.0.1:8000/api/health | jq .` → `{"status": "ok", "version": "0.1.0"}`.
|
||||||
Then: `curl -s http://0.0.0.0:8000/api/health` → connection refused.
|
Then: `curl -s http://0.0.0.0:8000/api/health` → connection refused.
|
||||||
|
|
||||||
- [ ] **Step 3: Start the frontend**
|
- [x] **Step 3: Start the frontend**
|
||||||
|
|
||||||
Terminal 3: `npm run dev`
|
Terminal 3: `npm run dev`
|
||||||
Expected: "Local: http://localhost:5173".
|
Expected: "Local: http://localhost:5173".
|
||||||
|
|
||||||
- [ ] **Step 4: Drop a fixture file and verify live data flow**
|
- [x] **Step 4: Drop a fixture file and verify live data flow**
|
||||||
|
|
||||||
1. Open `http://localhost:5173/upload` in a browser.
|
1. Open `http://localhost:5173/upload` in a browser.
|
||||||
2. Drop `backend/tests/fixtures/co_medicaid_837p.txt` on the upload zone.
|
2. Drop `backend/tests/fixtures/co_medicaid_837p.txt` on the upload zone.
|
||||||
@@ -4143,18 +4143,18 @@ Expected: "Local: http://localhost:5173".
|
|||||||
8. Apply `Status: submitted` filter on `/claims`. Expect: the same 2 rows; the `FilterChips` row shows "Status: submitted ×".
|
8. Apply `Status: submitted` filter on `/claims`. Expect: the same 2 rows; the `FilterChips` row shows "Status: submitted ×".
|
||||||
9. Watch the top of `<main>` while navigating back to `/upload` and re-parsing — the 1px scan-line indicator should appear briefly.
|
9. Watch the top of `<main>` while navigating back to `/upload` and re-parsing — the 1px scan-line indicator should appear briefly.
|
||||||
|
|
||||||
- [ ] **Step 5: Verify NDJSON streaming**
|
- [x] **Step 5: Verify NDJSON streaming**
|
||||||
|
|
||||||
Terminal 2: `curl -s -N -H 'Accept: application/x-ndjson' http://127.0.0.1:8000/api/claims | head -5`
|
Terminal 2: `curl -s -N -H 'Accept: application/x-ndjson' http://127.0.0.1:8000/api/claims | head -5`
|
||||||
Expected: 2 lines of `{"type":"item",…}` + 1 line of `{"type":"summary",…}`.
|
Expected: 2 lines of `{"type":"item",…}` + 1 line of `{"type":"summary",…}`.
|
||||||
|
|
||||||
- [ ] **Step 6: Stop the backend and verify the UI reverts to the fallback**
|
- [x] **Step 6: Stop the backend and verify the UI reverts to the fallback**
|
||||||
|
|
||||||
Kill terminal 1 (`Ctrl+C`). Refresh the browser. Expect: the pages still
|
Kill terminal 1 (`Ctrl+C`). Refresh the browser. Expect: the pages still
|
||||||
render (using the zustand fallback via the existing `data` adapter), but
|
render (using the zustand fallback via the existing `data` adapter), but
|
||||||
the upload page shows "No backend configured".
|
the upload page shows "No backend configured".
|
||||||
|
|
||||||
- [ ] **Step 7: Final commit (likely none)**
|
- [x] **Step 7: Final commit (likely none)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git status # should be clean
|
git status # should be clean
|
||||||
|
|||||||
Reference in New Issue
Block a user