Major additions: - Staged scanning modes (working tree, staged, committed) with git integration - Drift detection for baseline vs current state comparisons - Hosted API handlers for policy CRUD operations via StemeDB API - stemedb-ontology crate with domain definitions and medical extractors - Consumer health vertical UAT scenarios (GLP-1, gastroparesis, etc.) - Aphoria development skill documentation Code organization: - Split large files into focused modules to stay under 500-line limit - Extracted config tests, episteme helpers/drift/aliases, API helpers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
179 lines
4.0 KiB
Markdown
179 lines
4.0 KiB
Markdown
# UAT: Guidance Change Propagation ("What Changed Since?")
|
|
|
|
**Date:** YYYY-MM-DD
|
|
**Feature:** Incremental Change Tracking
|
|
**Status:** [ ] PASS / [ ] FAIL / [ ] BLOCKED
|
|
|
|
## Scenario
|
|
|
|
A downstream application queried StemeDB at time T1. Now at T2, they want to know: "What changed since my last query?"
|
|
|
|
This is critical for:
|
|
- Keeping derived data in sync
|
|
- Audit trails
|
|
- Real-time dashboards
|
|
|
|
## Acceptance Criteria
|
|
|
|
| Criterion | Expected | Met? |
|
|
|-----------|----------|------|
|
|
| Initial query at T1 | Returns baseline | [ ] |
|
|
| New assertion added | Stored with timestamp | [ ] |
|
|
| `since=T1` query | Returns only new assertion | [ ] |
|
|
| Changes array format | Includes operation type | [ ] |
|
|
| No false positives | Old assertions not returned | [ ] |
|
|
|
|
## Test Matrix
|
|
|
|
| Step | Action | Expected | Actual | Status |
|
|
|------|--------|----------|--------|--------|
|
|
| 1 | Query at T1 | Baseline returned | | [ ] |
|
|
| 2 | Add new assertion | Hash returned | | [ ] |
|
|
| 3 | Query with since=T1 | Only new assertion | | [ ] |
|
|
| 4 | Add another assertion | Hash returned | | [ ] |
|
|
| 5 | Query with since=T1 | Both new assertions | | [ ] |
|
|
| 6 | Query with since=T2 | Only most recent | | [ ] |
|
|
|
|
## Setup Commands
|
|
|
|
```bash
|
|
# Start StemeDB
|
|
cargo run --bin stemedb-api &
|
|
sleep 2
|
|
```
|
|
|
|
## Test Commands
|
|
|
|
### Step 1: Establish Baseline at T1
|
|
|
|
```bash
|
|
# Record the current timestamp
|
|
T1=$(date +%s)
|
|
|
|
# Create initial assertion
|
|
curl -X POST http://localhost:18180/v1/assertions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"subject": "Semaglutide",
|
|
"predicate": "approved_indications",
|
|
"object": {"Text": "Type 2 Diabetes"},
|
|
"confidence": 1.0,
|
|
"source_class": "Regulatory"
|
|
}'
|
|
|
|
# Query baseline
|
|
curl "http://localhost:18180/v1/query?subject=Semaglutide&predicate=approved_indications"
|
|
```
|
|
|
|
**Expected:** Returns Type 2 Diabetes assertion
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
### Step 2: Add New Assertion After T1
|
|
|
|
```bash
|
|
# Wait a moment to ensure different timestamp
|
|
sleep 1
|
|
|
|
# FDA approves new indication
|
|
curl -X POST http://localhost:18180/v1/assertions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"subject": "Semaglutide",
|
|
"predicate": "approved_indications",
|
|
"object": {"Text": "Chronic Weight Management"},
|
|
"confidence": 1.0,
|
|
"source_class": "Regulatory"
|
|
}'
|
|
```
|
|
|
|
**Expected:** Hash returned
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
### Step 3: Query with since=T1
|
|
|
|
```bash
|
|
curl "http://localhost:18180/v1/changes?subject=Semaglutide&since=$T1"
|
|
```
|
|
|
|
**Expected:**
|
|
```json
|
|
{
|
|
"changes": [
|
|
{
|
|
"operation": "insert",
|
|
"subject": "Semaglutide",
|
|
"predicate": "approved_indications",
|
|
"object": {"Text": "Chronic Weight Management"},
|
|
"timestamp": ...,
|
|
"hash": "..."
|
|
}
|
|
],
|
|
"query_timestamp": ...,
|
|
"since_timestamp": T1
|
|
}
|
|
```
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
### Step 4: Add Another Assertion
|
|
|
|
```bash
|
|
T2=$(date +%s)
|
|
sleep 1
|
|
|
|
# Third indication approved
|
|
curl -X POST http://localhost:18180/v1/assertions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"subject": "Semaglutide",
|
|
"predicate": "approved_indications",
|
|
"object": {"Text": "Cardiovascular Risk Reduction"},
|
|
"confidence": 1.0,
|
|
"source_class": "Regulatory"
|
|
}'
|
|
```
|
|
|
|
**Expected:** Hash returned
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
### Step 5: Query with since=T1 (All Changes)
|
|
|
|
```bash
|
|
curl "http://localhost:18180/v1/changes?subject=Semaglutide&since=$T1"
|
|
```
|
|
|
|
**Expected:** Returns BOTH new assertions (Weight Management AND Cardiovascular)
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
### Step 6: Query with since=T2 (Most Recent Only)
|
|
|
|
```bash
|
|
curl "http://localhost:18180/v1/changes?subject=Semaglutide&since=$T2"
|
|
```
|
|
|
|
**Expected:** Returns ONLY Cardiovascular Risk Reduction
|
|
**Actual:**
|
|
**Status:** [ ]
|
|
|
|
## Sign-Off Checklist
|
|
|
|
- [ ] Baseline query works
|
|
- [ ] New assertions timestamped correctly
|
|
- [ ] `since=` filter returns only newer assertions
|
|
- [ ] Changes include operation type
|
|
- [ ] Timestamp precision is sufficient (second or better)
|
|
|
|
## Notes
|
|
|
|
*The `/changes` endpoint is separate from `/query` to distinguish between "current state" and "what changed" semantics.*
|
|
|
|
---
|
|
|
|
**Tester:**
|
|
**Date:**
|
|
**Result:**
|