From 7053e4e06110b21f9c22c4859ddb0f04623595a2 Mon Sep 17 00:00:00 2001 From: Kisa Date: Sat, 20 Jun 2026 17:38:31 -0400 Subject: [PATCH] docs: add build spec, support manual, and shared current-state context Co-Authored-By: Claude Sonnet 4.6 --- context/current-state.md | 34 ++++ docs/build-spec-2026-06-20.md | 345 ++++++++++++++++++++++++++++++++++ docs/support-manual.md | 206 ++++++++++++++++++++ 3 files changed, 585 insertions(+) create mode 100644 context/current-state.md create mode 100644 docs/build-spec-2026-06-20.md create mode 100644 docs/support-manual.md diff --git a/context/current-state.md b/context/current-state.md new file mode 100644 index 0000000..02ee9ca --- /dev/null +++ b/context/current-state.md @@ -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 diff --git a/docs/build-spec-2026-06-20.md b/docs/build-spec-2026-06-20.md new file mode 100644 index 0000000..76eec38 --- /dev/null +++ b/docs/build-spec-2026-06-20.md @@ -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 +``` + +--- + +## 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 +``` diff --git a/docs/support-manual.md b/docs/support-manual.md new file mode 100644 index 0000000..93ff019 --- /dev/null +++ b/docs/support-manual.md @@ -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)