docs: add build spec, support manual, and shared current-state context
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
42a79c6682
commit
7053e4e061
3 changed files with 585 additions and 0 deletions
34
context/current-state.md
Normal file
34
context/current-state.md
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
# current-state
|
||||||
|
|
||||||
|
ACTIVE: Build shared context + knowledge pipeline (Jun 20 design).
|
||||||
|
NEXT: Hand current-state.md + support-manual.md to Claude Code for build.
|
||||||
|
|
||||||
|
## Decisions (last 5)
|
||||||
|
|
||||||
|
- 2026-06-20 — current-state.md bridges Pi and Claude Code. Both read at start, both write at wrap-up.
|
||||||
|
- 2026-06-18 — SSA principle adopted: sparse, content-dependent, time-weighted retrieval.
|
||||||
|
- 2026-06-18 — TriLane Memory = permanent insight layer. research_insight category needed.
|
||||||
|
- 2026-06-18 — Graphify = monthly scan only. Not a daily driver.
|
||||||
|
- 2026-06-18 — Granola transcripts stay in Sessions workspace. Signal workspace = library. No mixing.
|
||||||
|
|
||||||
|
## Open Threads (max 5)
|
||||||
|
|
||||||
|
- Firecrawl key in .zshrc — needs pi restart from sourced shell
|
||||||
|
- 9 session summaries in Signal workspace — move to Sessions
|
||||||
|
- Insight Engine (Jul 4) — Railway deploy blocked on interactive auth
|
||||||
|
- labABLE Jun 26 call — deck built, needs review
|
||||||
|
- Clerk production — deferred, needs manual Google OAuth setup
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- signal-api: Railway (signal-api-production-91c2)
|
||||||
|
- signal-ui: Vercel (signal-ui-xi.vercel.app)
|
||||||
|
- Supabase: itmospnregdyiatbbdwl (JWT key)
|
||||||
|
- TriLane: localhost:8000 (signal/sessions/scale-software workspaces)
|
||||||
|
- Clerk: sandbox only
|
||||||
|
|
||||||
|
## Tip
|
||||||
|
|
||||||
|
TriLane Memory: 0 items. The permanent insight layer is empty. Every session brain should plant at least one.
|
||||||
|
|
||||||
|
## Updated: 2026-06-20 15:30 UTC
|
||||||
345
docs/build-spec-2026-06-20.md
Normal file
345
docs/build-spec-2026-06-20.md
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
# Build Spec: Shared Context + Knowledge Pipeline
|
||||||
|
|
||||||
|
**Date:** 2026-06-20
|
||||||
|
**Design session:** Pi (architecture)
|
||||||
|
**Build session(s):** Claude Code
|
||||||
|
**Verification:** Kisa reviews after each phase
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1 — Foundation (est. 1 session)
|
||||||
|
|
||||||
|
### 1.1 Add research_insight category to TriLane Memory
|
||||||
|
|
||||||
|
**Files to change:**
|
||||||
|
|
||||||
|
- [ ] `trilane/backend/app/models.py`
|
||||||
|
- Line ~79: Add `research_insight` to the allowed category values on `MemoryItem.category`
|
||||||
|
- Current: `category = Column(String(64), nullable=False) # decision, preference, open_loop, project_fact`
|
||||||
|
- Change comment to include `research_insight` or add enum validation
|
||||||
|
|
||||||
|
- [ ] `trilane/backend/app/schemas.py`
|
||||||
|
- Line ~65: Add `research_insight` to `MemoryItemOut` or `MemoryCreate` schema validation
|
||||||
|
- Ensure the field accepts the new category string
|
||||||
|
|
||||||
|
- [ ] Run DB migration (Alembic or manual)
|
||||||
|
- If using Alembic: `cd trilane && alembic revision --autogenerate -m "add research_insight category" && alembic upgrade head`
|
||||||
|
- If manual: `ALTER TABLE memory_items DROP CONSTRAINT IF EXISTS ...` or equivalent
|
||||||
|
- Verify migration ran: `curl http://localhost:8000/api/workspaces` — should still list all 3 workspaces
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -X POST http://localhost:8000/api/memory/16ee4620-4c81-48f9-bcd6-6c0a8fbbd71a \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"category": "research_insight", "content": "test", "salience": 1.0}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Should return 201 with memory item ID. Then delete the test item.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1.2 Plant the first real research_insight
|
||||||
|
|
||||||
|
- [ ] POST to TriLane Memory with the CGM→pharmacy insight
|
||||||
|
|
||||||
|
**Payload:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"workspace_id": "16ee4620-4c81-48f9-bcd6-6c0a8fbbd71a",
|
||||||
|
"category": "research_insight",
|
||||||
|
"content": "CGM is systematically moving to pharmacy channel. Payer rules in FL/CA/OH/NC have moved CGM to pharmacy-only. UHC MA requires Synapse Health enrollment. Humana MA has tied-routing rule. DMEPOS suppliers are being squeezed: paid less, held to stricter documentation requirements, pushed toward expensive TPA models. This trend Signal must track for supplier intelligence.",
|
||||||
|
"salience": 1.0,
|
||||||
|
"tags": ["cgm", "pharmacy", "payer_trend", "policy", "strategic"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
curl http://localhost:8000/api/memory/16ee4620-4c81-48f9-bcd6-6c0a8fbbd71a
|
||||||
|
```
|
||||||
|
|
||||||
|
Should show 1 item with category "research_insight" and content matching above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1.3 Move 9 leaked session summaries out of Signal workspace
|
||||||
|
|
||||||
|
- [ ] Identify all session summaries in Signal workspace (id: 16ee4620)
|
||||||
|
- Expected: 9 files from April/May 2026
|
||||||
|
- Filenames: `2026-04-24-session-summary*` through `2026-05-10-session-summary*`
|
||||||
|
- [ ] Find the TriLane API endpoint for moving/reassigning sources between workspaces
|
||||||
|
- If no move endpoint exists: DELETE from Signal, re-upload to Sessions workspace (id: 3446107c)
|
||||||
|
- If move endpoint exists: POST to move endpoint with source_id and target workspace_id
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
# Signal workspace should have 38 docs (was 47, minus 9 summaries)
|
||||||
|
curl http://localhost:8000/api/sources/16ee4620 | python3 -c "import json,sys; print(len(json.load(sys.stdin)))"
|
||||||
|
# Sessions workspace should have 88 docs (was 79, plus 9 summaries)
|
||||||
|
curl http://localhost:8000/api/sources/3446107c | python3 -c "import json,sys; print(len(json.load(sys.stdin)))"
|
||||||
|
```
|
||||||
|
|
||||||
|
No session summaries should appear in the Signal workspace source list.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2 — Session Brain Updates (est. 1 session)
|
||||||
|
|
||||||
|
### 2.1 Add current-state.md write to session brain
|
||||||
|
|
||||||
|
- [ ] Read `navaigate-session-brain/SKILL.md` to identify insertion point
|
||||||
|
- [ ] Add a substep between the current Step 3 (summary) and Step 4 (NotebookLM):
|
||||||
|
|
||||||
|
```
|
||||||
|
Step 3B — Write shared context file
|
||||||
|
- Update signal/context/current-state.md
|
||||||
|
- Set ACTIVE to what was accomplished
|
||||||
|
- Set NEXT to the next priority
|
||||||
|
- Add any new decisions (max 5, FIFO — oldest drops off)
|
||||||
|
- Update open threads
|
||||||
|
- Update stack state if anything changed
|
||||||
|
- Set timestamp to now
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
cat signal/context/current-state.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Should show the session's update after the next session brain run.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 Add insight extraction to session brain
|
||||||
|
|
||||||
|
- [ ] Add a second substep between Step 3 (or after Step 3B):
|
||||||
|
|
||||||
|
```
|
||||||
|
Step 3C — Extract research insights
|
||||||
|
- Did this session produce cross-document synthesis?
|
||||||
|
- If yes: POST a research_insight memory item to TriLane Signal workspace
|
||||||
|
- Content: one paragraph describing the insight
|
||||||
|
- Salience: 1.0 (permanent)
|
||||||
|
- Tags: relevant category tags
|
||||||
|
- If no new insight: skip this step
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
After the next session brain runs, TriLane Memory for Signal workspace should show
|
||||||
|
a new research_insight item (in addition to the CGM→pharmacy seed from Phase 1).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 — Startup Ritual (est. 30 min)
|
||||||
|
|
||||||
|
### 3.1 Update CLAUDE.md
|
||||||
|
|
||||||
|
- [ ] Read `signal/CLAUDE.md`
|
||||||
|
- [ ] Add near the top, after the project description:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Startup Ritual
|
||||||
|
|
||||||
|
At session start, in order:
|
||||||
|
1. Read signal/context/current-state.md to know the active priority
|
||||||
|
2. Check TriLane Memory for recent research_insights
|
||||||
|
3. Begin work
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
grep "current-state" signal/CLAUDE.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Should show the startup ritual section.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 Create startup instruction for Pi
|
||||||
|
|
||||||
|
- [ ] Add to `~/.pi/agent/AGENTS.md` or a startup prompt:
|
||||||
|
|
||||||
|
```
|
||||||
|
At session start:
|
||||||
|
Read signal/context/current-state.md
|
||||||
|
Check TriLane Memory for new research_insights
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
Pi reads current-state.md at session start.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 — Support Bot Foundation (est. 1 session)
|
||||||
|
|
||||||
|
### 4.1 Generate support-api-ref.json
|
||||||
|
|
||||||
|
- [ ] Write a Python script at `signal/scripts/gen-api-ref.py` that:
|
||||||
|
- Reads `python-backend/api/main.py`
|
||||||
|
- Parses FastAPI route decorators (@app.get, @app.post, etc.)
|
||||||
|
- Extracts route path, method, summary (from docstring first line)
|
||||||
|
- Extracts response model info
|
||||||
|
- Extracts error responses (from raise statements in the function body)
|
||||||
|
- Writes `signal/docs/support-api-ref.json`
|
||||||
|
|
||||||
|
**Expected output structure:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"generated": "2026-06-20",
|
||||||
|
"source": "python-backend/api/main.py",
|
||||||
|
"endpoints": [
|
||||||
|
{
|
||||||
|
"path": "/api/health",
|
||||||
|
"method": "GET",
|
||||||
|
"summary": "Health check endpoint",
|
||||||
|
"responses": [
|
||||||
|
{"code": 200, "description": "Service healthy"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/api/upload-csv",
|
||||||
|
"method": "POST",
|
||||||
|
"summary": "Upload and process a CSV file",
|
||||||
|
"parameters": [
|
||||||
|
{"name": "file", "in": "formData", "type": "file", "required": true}
|
||||||
|
],
|
||||||
|
"responses": [
|
||||||
|
{"code": 200, "description": "CSV processed successfully"},
|
||||||
|
{"code": 400, "description": "Invalid CSV format or missing columns"},
|
||||||
|
{"code": 401, "description": "Invalid or missing API key"},
|
||||||
|
{"code": 500, "description": "Server error processing CSV"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 signal/scripts/gen-api-ref.py
|
||||||
|
cat signal/docs/support-api-ref.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'{len(d[\"endpoints\"])} endpoints extracted')"
|
||||||
|
```
|
||||||
|
|
||||||
|
Should show all real API endpoints from the backend.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 Cross-reference support-manual.md with generated API ref
|
||||||
|
|
||||||
|
- [ ] Read both files and ensure:
|
||||||
|
- Error messages in the manual match actual error codes from the API ref
|
||||||
|
- Endpoint descriptions in the manual are consistent with the generated routes
|
||||||
|
- Any missing endpoints in the manual are added
|
||||||
|
- [ ] Add a note at the top of `support-manual.md` noting the generation timestamp
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
The error tables in `support-manual.md` should reference real endpoints in
|
||||||
|
`support-api-ref.json`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5 — Session Brain Nugget Format Update (est. 30 min)
|
||||||
|
|
||||||
|
### 5.1 Compact nugget format
|
||||||
|
|
||||||
|
- [ ] Edit `navaigate-session-brain/SKILL.md` Step 3 (Write Session Summary)
|
||||||
|
- [ ] Change the format from verbose markdown to compact nugget (~400 bytes):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Session Nugget — YYYY-MM-DD
|
||||||
|
N themes · N tools touched · N insights
|
||||||
|
|
||||||
|
### Completed
|
||||||
|
- [action 1]
|
||||||
|
- [action 2]
|
||||||
|
- [action 3]
|
||||||
|
|
||||||
|
### Insight
|
||||||
|
One sentence if cross-document synthesis happened. Omit if not.
|
||||||
|
|
||||||
|
### Next (Top 1)
|
||||||
|
1. [single most important next step]
|
||||||
|
|
||||||
|
### Cross-Refs
|
||||||
|
- Tool/Project links
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
After next session brain run, check the NotebookLM source to verify it's using
|
||||||
|
the compact format:
|
||||||
|
|
||||||
|
```
|
||||||
|
notebooklm source list --json
|
||||||
|
notebooklm source fulltext <source_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6 — Startup Automation (est. 30 min)
|
||||||
|
|
||||||
|
### 6.1 Verify the full cycle works end-to-end
|
||||||
|
|
||||||
|
- [ ] Simulate a Pi session:
|
||||||
|
1. Pi reads current-state.md
|
||||||
|
2. Pi does design work
|
||||||
|
3. Pi writes decisions to current-state.md
|
||||||
|
4. Pi posts insight to TriLane Memory (if applicable)
|
||||||
|
5. Pi runs session brain → pushes nugget
|
||||||
|
- [ ] Simulate a Claude Code session:
|
||||||
|
1. Claude Code reads current-state.md
|
||||||
|
2. Claude Code sees Pi's design decisions
|
||||||
|
3. Claude Code builds the change
|
||||||
|
4. Claude Code updates current-state.md
|
||||||
|
5. Claude Code runs session brain → pushes nugget
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
|
||||||
|
- current-state.md reflects the latest session
|
||||||
|
- TriLane Memory for Signal workspace has the planted insights
|
||||||
|
- NotebookLM Brain has nuggets from both sessions
|
||||||
|
- Barrier Log has any issues encountered (should be none for a clean build)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Completion Report Template
|
||||||
|
|
||||||
|
When all phases are complete, fill in:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Build Complete: Shared Context + Knowledge Pipeline
|
||||||
|
|
||||||
|
### Phase 1 (Foundation)
|
||||||
|
- [x] research_insight category added to TriLane Memory
|
||||||
|
- [x] CGM→pharmacy insight planted (salience 1.0)
|
||||||
|
- [x] 9 session summaries moved from Signal → Sessions workspace
|
||||||
|
|
||||||
|
### Phase 2 (Session Brain)
|
||||||
|
- [x] current-state.md write added to session brain
|
||||||
|
- [x] Insight extraction added to session brain
|
||||||
|
|
||||||
|
### Phase 3 (Startup Ritual)
|
||||||
|
- [x] CLAUDE.md updated with startup ritual
|
||||||
|
- [x] Pi AGENTS.md updated
|
||||||
|
|
||||||
|
### Phase 4 (Support Bot)
|
||||||
|
- [x] support-api-ref.json generated
|
||||||
|
- [x] Manual cross-referenced against generated ref
|
||||||
|
|
||||||
|
### Phase 5 (Nugget Format)
|
||||||
|
- [x] Session brain nugget format compacted to ~400 bytes
|
||||||
|
|
||||||
|
### Phase 6 (Verification)
|
||||||
|
- [x] Full cycle verified end-to-end
|
||||||
|
```
|
||||||
206
docs/support-manual.md
Normal file
206
docs/support-manual.md
Normal file
|
|
@ -0,0 +1,206 @@
|
||||||
|
# Signal Support Manual
|
||||||
|
|
||||||
|
Curated operations knowledge for the Signal CGM documentation readiness platform.
|
||||||
|
Support bot reads this + support-api-ref.json + Barrier Log for troubleshooting.
|
||||||
|
See signal/docs/support-api-ref.json for auto-generated API routes and error codes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CSV Import
|
||||||
|
|
||||||
|
Signal ingests order data from any DME order management CSV export.
|
||||||
|
|
||||||
|
### Required Columns
|
||||||
|
|
||||||
|
Column names are matched case-insensitively. At minimum, the CSV must contain
|
||||||
|
identifying and status fields. Signal evaluates each row against documentation
|
||||||
|
requirements and produces a status per patient.
|
||||||
|
|
||||||
|
| Column | Required | Purpose |
|
||||||
|
|--------|----------|---------|
|
||||||
|
| patient_name | Yes | Patient identifier |
|
||||||
|
| cgm_type | Yes | Device type for LCD rule matching |
|
||||||
|
| sw0_status | No | Signed written order status |
|
||||||
|
| qualifying_visit_date | No | Last qualifying visit date |
|
||||||
|
| pa_status | No | Prior authorization status |
|
||||||
|
| next_shipment_date | No | Expected resupply date |
|
||||||
|
| payer | No | Payer name for routing checks |
|
||||||
|
|
||||||
|
If a column is absent, Signal treats the requirement as "not evaluated" —
|
||||||
|
not a gap. This prevents false negatives when a supplier's export format
|
||||||
|
omits fields they don't track.
|
||||||
|
|
||||||
|
### Validation Rules
|
||||||
|
|
||||||
|
- Rows with empty patient_name are skipped
|
||||||
|
- Unknown cgm_type values log a warning and skip LCD matching
|
||||||
|
- Date columns must be ISO 8601 (YYYY-MM-DD) or a parseable US format
|
||||||
|
- Files over 10MB are rejected (supplier sends manageable subsets)
|
||||||
|
|
||||||
|
### Error Messages (common)
|
||||||
|
|
||||||
|
| Error | Cause | Fix |
|
||||||
|
|-------|-------|-----|
|
||||||
|
| "Missing required columns" | CSV missing patient_name or cgm_type | Check export template |
|
||||||
|
| "Upload failed — auth error" | API key missing or expired | Generate new key in Railway env |
|
||||||
|
| "Upload failed — CORS error" | Frontend domain not in allow list | Add domain to ALLOWED_ORIGINS_REGEX |
|
||||||
|
| "Upload failed — server error" | Backend crashed or timed out | Check Railway logs |
|
||||||
|
| "No parsable rows found" | All rows failed validation | Check column names in export |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
See `signal/docs/support-api-ref.json` for full auto-generated route listing.
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
- All endpoints require `X-API-Key` header matching the value in Railway env vars
|
||||||
|
- Clerk-authenticated endpoints use Bearer JWT tokens
|
||||||
|
- Dev keys are for sandbox only; rotate before any external user accesses the app
|
||||||
|
|
||||||
|
### Key Endpoints
|
||||||
|
|
||||||
|
| Endpoint | Method | Purpose |
|
||||||
|
|----------|--------|---------|
|
||||||
|
| /api/health | GET | Health check — returns {"status": "ok"} |
|
||||||
|
| /api/upload-csv | POST | Upload and process CSV file |
|
||||||
|
| /api/patients | GET | List all patients with status summary |
|
||||||
|
| /api/patients/{id} | GET | Single patient detail and cascade |
|
||||||
|
| /api/confirm-visit | POST | Record qualifying visit confirmation |
|
||||||
|
| /api/update-doc-status | POST | Update document status for a requirement |
|
||||||
|
| /api/export | GET | Download Signal Report as CSV |
|
||||||
|
|
||||||
|
### Common Response Codes
|
||||||
|
|
||||||
|
| Code | Meaning | Likely Cause |
|
||||||
|
|------|---------|--------------|
|
||||||
|
| 200 | Success | — |
|
||||||
|
| 400 | Bad request | Missing or malformed parameters |
|
||||||
|
| 401 | Unauthorized | Missing or invalid API key |
|
||||||
|
| 403 | Forbidden | Valid key, insufficient scope |
|
||||||
|
| 404 | Not found | Patient ID doesn't exist |
|
||||||
|
| 500 | Server error | Backend exception (check logs) |
|
||||||
|
| 503 | Service unavailable | Database connection issue or deployment cycling |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status Labels
|
||||||
|
|
||||||
|
Signal uses 4 UI tabs. The backend computes 8 internal flags that map to these.
|
||||||
|
|
||||||
|
### Internal Flags (backend)
|
||||||
|
|
||||||
|
| Flag | Meaning | Trigger |
|
||||||
|
|------|---------|---------|
|
||||||
|
| SUPPLY_LAPSED | Patient is past resuppy date | next_shipment_date passed |
|
||||||
|
| VISIT_REQUIRED | 6-month qualifying visit expired | qualifying_visit_date > 6 months ago |
|
||||||
|
| RENEWAL_CRITICAL | Prescription renewal due within 15 days | Calculated from renewal date |
|
||||||
|
| RENEWAL_ELEVATED | Renewal due within 30 days | |
|
||||||
|
| RENEWAL_SOON | Renewal due within 60 days | |
|
||||||
|
| RESUPPLY_READY | All requirements met, ready to ship | SWO on file + PA approved + visit current + no cascade gaps |
|
||||||
|
| ACTIVE | Patient is stable, no flags | Nothing due, no gaps |
|
||||||
|
| TRANSFER_PENDING | Incoming from another supplier | Set manually in CSV or UI |
|
||||||
|
|
||||||
|
### UI Tabs (frontend, mapped from internal flags)
|
||||||
|
|
||||||
|
| Tab | Internal Flags Included |
|
||||||
|
|-----|------------------------|
|
||||||
|
| At Risk | SUPPLY_LAPSED |
|
||||||
|
| Action Needed | VISIT_REQUIRED, RENEWAL_CRITICAL, RENEWAL_ELEVATED |
|
||||||
|
| Clear to Ship | RESUPPLY_READY (with no cascade items) |
|
||||||
|
| On Track | ACTIVE, RENEWAL_SOON, TRANSFER_PENDING, NO_RECENT_SHIPMENT |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation Requirements (Cascade)
|
||||||
|
|
||||||
|
Each patient has a cascade — a list of documentation actions needed to
|
||||||
|
reach Clear to Ship. Cascade items are only shown when their source column
|
||||||
|
was supplied in the CSV.
|
||||||
|
|
||||||
|
### Possible Cascade Items
|
||||||
|
|
||||||
|
| Item | Cause | Cleared By |
|
||||||
|
|------|-------|------------|
|
||||||
|
| Signed Written Order (SWO) | sw0_status is not "On File" | Update sw0_status or use "Confirm Visit" |
|
||||||
|
| Qualifying Visit | qualifying_visit_date missing or > 6 months | Schedule and confirm visit |
|
||||||
|
| Prior Authorization | pa_status is not "Approved" | Submit PA and update status in CSV |
|
||||||
|
| Prescription Renewal | renewal_date approaching or passed | Obtain new prescription |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Failures & Resolutions
|
||||||
|
|
||||||
|
Issues from the Barrier Log that appear most often. Full history at
|
||||||
|
`STTIL-Vault/Projects/Barrier-Log.md`.
|
||||||
|
|
||||||
|
### Uploads Fail Silently
|
||||||
|
|
||||||
|
**Symptoms:** CSV uploads return success but worklist stays empty or shows
|
||||||
|
wrong statuses. No error message shown to user.
|
||||||
|
|
||||||
|
**Root cause:** `api.js` had `catch { return null }` blocks swallowing all
|
||||||
|
errors. Fixed by re-throwing real errors and adding toast notifications.
|
||||||
|
|
||||||
|
**Status:** Fixed and deployed. If it recurs, check that:
|
||||||
|
|
||||||
|
1. The frontend is deployed from the fix branch (vercel --prod)
|
||||||
|
2. The backend is deployed from the matching fix (railway up --detach)
|
||||||
|
3. ALLOWED_ORIGINS_REGEX includes the domain
|
||||||
|
|
||||||
|
### Clear to Ship Never Goes Green
|
||||||
|
|
||||||
|
**Symptoms:** All patients show amber status, even resupply-ready ones.
|
||||||
|
Green count is permanently 0.
|
||||||
|
|
||||||
|
**Root cause:** The backend scored missing CSV columns as doc gaps. An
|
||||||
|
absent "sw0_status" column meant every patient had a "missing SWO" cascade
|
||||||
|
item. Green = "no cascade items" so green was unreachable.
|
||||||
|
|
||||||
|
**Fix:** Added "supplied" sentinel flags. An absent column is "not evaluated,"
|
||||||
|
not a gap. Green means "no known blocker from the data provided."
|
||||||
|
|
||||||
|
**Status:** Fixed and deployed. Verify by uploading a CSV with resupply-ready
|
||||||
|
patients — they should show green.
|
||||||
|
|
||||||
|
### CORS Errors on Vercel Deploy
|
||||||
|
|
||||||
|
**Symptoms:** Upload fails with browser CORS error on preview URLs.
|
||||||
|
|
||||||
|
**Root cause:** ALLOWED_ORIGINS was a fixed list. Vercel preview URLs
|
||||||
|
(project-xxxx.vercel.app) weren't included.
|
||||||
|
|
||||||
|
**Fix:** Changed to ALLOWED_ORIGINS_REGEX to accept *.vercel.app patterns.
|
||||||
|
|
||||||
|
### Status Count Mismatch (Stat Card vs Row Count)
|
||||||
|
|
||||||
|
**Symptoms:** The stat card shows a different green count than filtering
|
||||||
|
by "Clear to Ship" tab.
|
||||||
|
|
||||||
|
**Root cause:** Stat card counted RESUPPLY_READY. Tab counted
|
||||||
|
RESUPPLY_READY AND cascade empty. Cascade was never empty (see above).
|
||||||
|
|
||||||
|
**Fix:** Both now use the same logic: RESUPPLY_READY with no cascade gaps.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Issues (Active)
|
||||||
|
|
||||||
|
| Issue | Status | Workaround |
|
||||||
|
|-------|--------|------------|
|
||||||
|
| Clerk production migration deferred | Blocking real supplier login | Use sandbox keys for dev; manual Google OAuth setup needed |
|
||||||
|
| Gaboro demo API key in Railway env | Security risk before external access | Rotate before Robert Robinson pilot |
|
||||||
|
| granola-ingest portable path | Needs path update | Script works from full path; symlink/alias pending |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cross-References
|
||||||
|
|
||||||
|
- **State machine code:** python-backend/core/doc_state_machine.py
|
||||||
|
- **Cascade builder:** python-backend/core/doc_state_machine.py (_build_cascade)
|
||||||
|
- **Frontend status mapping:** signal-ui/src/components/WorklistTable.jsx
|
||||||
|
- **Upload handler:** signal-ui/src/lib/api.js
|
||||||
|
- **API auth:** python-backend/api/main.py (X-API-Key middleware)
|
||||||
|
- **Barrier Log (all resolved issues):** STTIL-Vault/Projects/Barrier-Log.md
|
||||||
|
- **TriLane research library:** Signal workspace (research docs, payer matrix, synthesis)
|
||||||
Loading…
Reference in a new issue