Spaces:
Running
Running
Commit ·
cc678b9
0
Parent(s):
Deploy public Scribe-only CarePath Space
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .dockerignore +33 -0
- .env.ckey.example +35 -0
- .env.example +75 -0
- .env.local.example +31 -0
- .gitattributes +2 -0
- .github/workflows/ci.yml +147 -0
- .github/workflows/keepalive.yml +17 -0
- .gitignore +40 -0
- AGENTS.md +335 -0
- CLAUDE.md +6 -0
- Dockerfile +53 -0
- README.hf-space.md +21 -0
- README.md +21 -0
- UI-FIX-PLAN.md +154 -0
- data/medical_lexicon.json +215 -0
- docs/ARCHITECTURE.md +40 -0
- docs/CONTEXT_RULES.md +19 -0
- docs/FEATURE_INTAKE.md +51 -0
- docs/GLOSSARY.md +144 -0
- docs/HARNESS.md +65 -0
- docs/HARNESS_AUDIT.md +38 -0
- docs/HARNESS_BACKLOG.md +62 -0
- docs/HARNESS_COMPONENTS.md +167 -0
- docs/HARNESS_MATURITY.md +316 -0
- docs/IMPROVEMENT_PROTOCOL.md +57 -0
- docs/README.md +40 -0
- docs/TEST_MATRIX.md +17 -0
- docs/TOOL_REGISTRY.md +195 -0
- docs/TRACE_SPEC.md +204 -0
- docs/decisions/0001-harness-first-development.md +48 -0
- docs/decisions/0002-post-spec-product-lifecycle.md +54 -0
- docs/decisions/0003-generic-spec-intake-harness.md +58 -0
- docs/decisions/0004-sqlite-durable-layer.md +75 -0
- docs/decisions/0005-prebuilt-rust-harness-cli.md +91 -0
- docs/decisions/0006-phase-4-benchmark-triage.md +54 -0
- docs/decisions/0007-improvement-proposal-rules.md +60 -0
- docs/decisions/0008-carepath-harness-adoption.md +44 -0
- docs/decisions/0009-restructure-target-layout.md +56 -0
- docs/decisions/0010-shared-normalization-contract.md +31 -0
- docs/decisions/0011-canonical-medical-term-source.md +30 -0
- docs/decisions/0012-interpreter-runtime-hardening.md +29 -0
- docs/decisions/0013-gec-training-data-governance.md +30 -0
- docs/decisions/0014-gec-safety-weighted-regression-gate.md +31 -0
- docs/decisions/0015-soap-note-measurement-gate.md +31 -0
- docs/decisions/0016-scribe-training-ownership.md +35 -0
- docs/decisions/README.md +28 -0
- docs/deploy.md +150 -0
- docs/history/DEMO-SITE-PLAN.md +146 -0
- docs/history/JUDGE.md +99 -0
- docs/history/MERGE-PLAN.md +279 -0
.dockerignore
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.agents/
|
| 2 |
+
.claude/
|
| 3 |
+
.codex/
|
| 4 |
+
.git/
|
| 5 |
+
.pytest_cache/
|
| 6 |
+
.ruff_cache/
|
| 7 |
+
.mypy_cache/
|
| 8 |
+
.venv/
|
| 9 |
+
.venv_labeling/
|
| 10 |
+
__pycache__/
|
| 11 |
+
*.py[cod]
|
| 12 |
+
*.egg-info/
|
| 13 |
+
.env
|
| 14 |
+
.env.*
|
| 15 |
+
**/node_modules
|
| 16 |
+
**/dist
|
| 17 |
+
**/coverage
|
| 18 |
+
**/playwright-report
|
| 19 |
+
**/test-results
|
| 20 |
+
**/*.db
|
| 21 |
+
artifacts/
|
| 22 |
+
data/labeling/
|
| 23 |
+
models/
|
| 24 |
+
tmp/
|
| 25 |
+
*.wav
|
| 26 |
+
*.mp3
|
| 27 |
+
*.m4a
|
| 28 |
+
*.aac
|
| 29 |
+
*.flac
|
| 30 |
+
*.ogg
|
| 31 |
+
*.oga
|
| 32 |
+
*.opus
|
| 33 |
+
*.webm
|
.env.ckey.example
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath CKey runtime
|
| 2 |
+
APP_ENV=local
|
| 3 |
+
ASR_PROVIDER=gipformer
|
| 4 |
+
ALLOW_MOCK_ASR=false
|
| 5 |
+
|
| 6 |
+
# CKey uses the OpenAI-compatible chat/completions route.
|
| 7 |
+
# Get the key from the CKey AI API Console and keep .env out of source control.
|
| 8 |
+
LLM_PROVIDER=ckey
|
| 9 |
+
LLM_BASE_URL=https://api.xah.io/v1
|
| 10 |
+
LLM_MODEL=gpt-5.4
|
| 11 |
+
LLM_API_KEY=sk-YOUR_API_KEY
|
| 12 |
+
LLM_TIMEOUT_SECONDS=120
|
| 13 |
+
# Demo safety net: if CKey fails/times out, serve the deterministic offline
|
| 14 |
+
# generator instead of returning an error. Set to false to fail hard.
|
| 15 |
+
LLM_FALLBACK_OFFLINE=true
|
| 16 |
+
|
| 17 |
+
# Retrieval
|
| 18 |
+
MEDICAL_LEXICON_PATH=data/medical_lexicon.json
|
| 19 |
+
RETRIEVAL_TOP_K=5
|
| 20 |
+
|
| 21 |
+
# Gipformer ASR
|
| 22 |
+
GIPFORMER_QUANTIZE=int8
|
| 23 |
+
GIPFORMER_NUM_THREADS=4
|
| 24 |
+
GIPFORMER_DECODING_METHOD=modified_beam_search
|
| 25 |
+
GIPFORMER_CHUNK_SECONDS=20
|
| 26 |
+
|
| 27 |
+
# Abuse guard
|
| 28 |
+
TEAM_CODE=
|
| 29 |
+
SOAP_RATE_LIMIT_PER_IP_HOUR=3
|
| 30 |
+
SOAP_RATE_LIMIT_PER_IP_DAY=10
|
| 31 |
+
SOAP_RATE_LIMIT_GLOBAL_DAY=100
|
| 32 |
+
|
| 33 |
+
# --- Interpreter module (mock until its cloud track lands) ---
|
| 34 |
+
PROVIDER_MODE=mock
|
| 35 |
+
DATABASE_URL=sqlite:///./carepath.db
|
.env.example
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath unified runtime — one FastAPI service, two products.
|
| 2 |
+
# Defaults below are the keyless demo profile: the whole app must boot with no
|
| 3 |
+
# API keys (mock interpreter providers, mock ASR + offline LLM for the scriber).
|
| 4 |
+
# Ready-made profiles: .env.local.example (keyless demo), .env.ckey.example
|
| 5 |
+
# (real Gipformer ASR + CKey LLM).
|
| 6 |
+
|
| 7 |
+
# --- Scriber (scribe/carepath, routes /api/v1/*) ---
|
| 8 |
+
APP_ENV=local
|
| 9 |
+
ASR_PROVIDER=gipformer
|
| 10 |
+
GIPFORMER_QUANTIZE=int8
|
| 11 |
+
GIPFORMER_NUM_THREADS=4
|
| 12 |
+
GIPFORMER_DECODING_METHOD=modified_beam_search
|
| 13 |
+
GIPFORMER_CHUNK_SECONDS=20
|
| 14 |
+
# Long-audio segmentation: overlap (default) | vad | fixed.
|
| 15 |
+
# overlap = overlapping windows merged with seam de-duplication (no word loss
|
| 16 |
+
# at chunk boundaries; no extra model).
|
| 17 |
+
# vad = split on silence; requires GIPFORMER_VAD_MODEL (repo_id:filename or
|
| 18 |
+
# a local silero_vad.onnx path). Falls back to overlap if unavailable.
|
| 19 |
+
# fixed = legacy non-overlapping 20s windows.
|
| 20 |
+
GIPFORMER_SEGMENTATION=overlap
|
| 21 |
+
GIPFORMER_OVERLAP_SECONDS=2
|
| 22 |
+
GIPFORMER_MAX_SEGMENT_SECONDS=20
|
| 23 |
+
GIPFORMER_VAD_MODEL=
|
| 24 |
+
|
| 25 |
+
# Set LLM_PROVIDER=offline for a deterministic no-key fallback.
|
| 26 |
+
# Set LLM_PROVIDER=ckey for CKey OpenAI-compatible chat completions.
|
| 27 |
+
LLM_PROVIDER=offline
|
| 28 |
+
LLM_BASE_URL=https://api.openai.com/v1
|
| 29 |
+
LLM_MODEL=gpt-4.1-mini
|
| 30 |
+
LLM_API_KEY=
|
| 31 |
+
LLM_TIMEOUT_SECONDS=60
|
| 32 |
+
# If a network LLM provider fails, fall back to the offline generator so a
|
| 33 |
+
# request never errors out (recommended for live demos).
|
| 34 |
+
LLM_FALLBACK_OFFLINE=true
|
| 35 |
+
|
| 36 |
+
# Retrieval
|
| 37 |
+
MEDICAL_LEXICON_PATH=data/medical_lexicon.json
|
| 38 |
+
RETRIEVAL_TOP_K=5
|
| 39 |
+
# Backend: lexical (default) | semantic | hybrid. semantic/hybrid use the
|
| 40 |
+
# Vietnamese bi-encoder and need the optional sentence-transformers + pyvi deps.
|
| 41 |
+
RETRIEVAL_BACKEND=lexical
|
| 42 |
+
SEMANTIC_MODEL_NAME=bkai-foundation-models/vietnamese-bi-encoder
|
| 43 |
+
|
| 44 |
+
# Safety/demo
|
| 45 |
+
ALLOW_MOCK_ASR=false
|
| 46 |
+
TEAM_CODE=
|
| 47 |
+
SOAP_RATE_LIMIT_PER_IP_HOUR=3
|
| 48 |
+
SOAP_RATE_LIMIT_PER_IP_DAY=10
|
| 49 |
+
SOAP_RATE_LIMIT_GLOBAL_DAY=100
|
| 50 |
+
# Cross-origin frontends for both APIs. Clear this value for same-origin-only
|
| 51 |
+
# production; list every Vite development origin when developing against either API.
|
| 52 |
+
CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
| 53 |
+
|
| 54 |
+
# Public Vercel site used by the Interpreter's “Tất cả chức năng” link when
|
| 55 |
+
# its frontend is built into the Space image. Set as a Docker build arg.
|
| 56 |
+
VITE_PUBLIC_SITE_URL=https://carepath-omega.vercel.app
|
| 57 |
+
|
| 58 |
+
# --- Interpreter (interpreter/app, routes /api/* + /ws/*) ---
|
| 59 |
+
# PROVIDER_MODE=mock runs deterministic providers with zero keys (the demo
|
| 60 |
+
# profile). PROVIDER_MODE=cloud is a later track: it needs the two API keys
|
| 61 |
+
# below and a non-default ADMIN_TOKEN (startup refuses "change-me").
|
| 62 |
+
PROVIDER_MODE=mock
|
| 63 |
+
ANTHROPIC_API_KEY=
|
| 64 |
+
OPENAI_API_KEY=
|
| 65 |
+
ADMIN_TOKEN=change-me
|
| 66 |
+
CONFIDENCE_THRESHOLD=0.7
|
| 67 |
+
RETENTION_DAYS=30
|
| 68 |
+
MAX_TURN_AUDIO_BYTES=10485760
|
| 69 |
+
# sqlite is fine for the demo (ephemeral on HF Spaces); point at Postgres etc.
|
| 70 |
+
# for anything that must survive a container restart.
|
| 71 |
+
DATABASE_URL=sqlite:///./carepath.db
|
| 72 |
+
OPENAI_TRANSCRIBE_MODEL=gpt-4o-transcribe
|
| 73 |
+
CLAUDE_MT_MODEL=claude-sonnet-5
|
| 74 |
+
CLAUDE_REVIEWER_MODEL=claude-sonnet-5
|
| 75 |
+
PROVIDER_TIMEOUT_SECONDS=30
|
.env.local.example
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath local smoke/demo runtime
|
| 2 |
+
APP_ENV=local
|
| 3 |
+
ASR_PROVIDER=mock
|
| 4 |
+
ALLOW_MOCK_ASR=true
|
| 5 |
+
|
| 6 |
+
# Offline correction/SOAP fallback for local API contract testing.
|
| 7 |
+
LLM_PROVIDER=offline
|
| 8 |
+
LLM_BASE_URL=https://api.openai.com/v1
|
| 9 |
+
LLM_MODEL=gpt-4.1-mini
|
| 10 |
+
LLM_API_KEY=
|
| 11 |
+
LLM_TIMEOUT_SECONDS=60
|
| 12 |
+
|
| 13 |
+
# Retrieval
|
| 14 |
+
MEDICAL_LEXICON_PATH=data/medical_lexicon.json
|
| 15 |
+
RETRIEVAL_TOP_K=5
|
| 16 |
+
|
| 17 |
+
# Gipformer settings are ignored while ASR_PROVIDER=mock.
|
| 18 |
+
GIPFORMER_QUANTIZE=int8
|
| 19 |
+
GIPFORMER_NUM_THREADS=4
|
| 20 |
+
GIPFORMER_DECODING_METHOD=modified_beam_search
|
| 21 |
+
GIPFORMER_CHUNK_SECONDS=20
|
| 22 |
+
|
| 23 |
+
# Abuse guard
|
| 24 |
+
TEAM_CODE=
|
| 25 |
+
SOAP_RATE_LIMIT_PER_IP_HOUR=3
|
| 26 |
+
SOAP_RATE_LIMIT_PER_IP_DAY=10
|
| 27 |
+
SOAP_RATE_LIMIT_GLOBAL_DAY=100
|
| 28 |
+
|
| 29 |
+
# --- Interpreter module (mock providers, zero keys) ---
|
| 30 |
+
PROVIDER_MODE=mock
|
| 31 |
+
DATABASE_URL=sqlite:///./carepath.db
|
.gitattributes
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Playwright snapshots are byte-compared; never convert their line endings.
|
| 2 |
+
site/tests/**/*-snapshots/** -text
|
.github/workflows/ci.yml
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: CI
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
pull_request:
|
| 6 |
+
|
| 7 |
+
jobs:
|
| 8 |
+
unified-api:
|
| 9 |
+
runs-on: ubuntu-latest
|
| 10 |
+
steps:
|
| 11 |
+
- uses: actions/checkout@v4
|
| 12 |
+
- uses: actions/setup-python@v5
|
| 13 |
+
with:
|
| 14 |
+
python-version: "3.12"
|
| 15 |
+
- name: Install shared and API packages
|
| 16 |
+
run: python -m pip install -e ".[dev]" -e "./shared" -e "./interpreter[dev]"
|
| 17 |
+
- name: Scriber and combined-app tests
|
| 18 |
+
run: pytest
|
| 19 |
+
- name: Shared normalization characterization
|
| 20 |
+
run: python -m pytest shared/tests
|
| 21 |
+
- name: Regenerate term artifacts without drift
|
| 22 |
+
run: python scripts/build_term_artifacts.py && git diff --exit-code -- data/medical_lexicon.json interpreter/app/glossary/data/seed_glossary.csv
|
| 23 |
+
- name: Enforce serving/training import boundary
|
| 24 |
+
run: if rg -l 'from gec|import gec' scribe/carepath/; then exit 1; fi
|
| 25 |
+
- name: Scriber smoke test (mock ASR + offline LLM)
|
| 26 |
+
run: python scripts/smoke_backend.py
|
| 27 |
+
|
| 28 |
+
training-governance:
|
| 29 |
+
runs-on: ubuntu-latest
|
| 30 |
+
steps:
|
| 31 |
+
- uses: actions/checkout@v4
|
| 32 |
+
- uses: actions/setup-python@v5
|
| 33 |
+
with:
|
| 34 |
+
python-version: "3.12"
|
| 35 |
+
- name: Install CPU-only training proof dependencies
|
| 36 |
+
run: python -m pip install -e ".[dev]" -e "./shared"
|
| 37 |
+
- name: Test training governance and export smoke
|
| 38 |
+
run: python -m pytest scribe/training/tests
|
| 39 |
+
- name: Verify the committed frozen baseline report
|
| 40 |
+
run: python scribe/training/scripts/baseline_report.py
|
| 41 |
+
|
| 42 |
+
interpreter:
|
| 43 |
+
runs-on: ubuntu-latest
|
| 44 |
+
steps:
|
| 45 |
+
- uses: actions/checkout@v4
|
| 46 |
+
- uses: actions/setup-python@v5
|
| 47 |
+
with:
|
| 48 |
+
python-version: "3.12"
|
| 49 |
+
- name: Install shared and interpreter
|
| 50 |
+
run: python -m pip install -e "./shared" -e "./interpreter[dev]"
|
| 51 |
+
- name: Lint interpreter
|
| 52 |
+
working-directory: interpreter
|
| 53 |
+
run: ruff check .
|
| 54 |
+
- name: Test interpreter
|
| 55 |
+
working-directory: interpreter
|
| 56 |
+
run: pytest
|
| 57 |
+
- name: Eval regression
|
| 58 |
+
run: python interpreter/eval/run_eval.py --set interpreter/eval/fixtures/eval_starter.tsv --providers mock
|
| 59 |
+
|
| 60 |
+
frontend:
|
| 61 |
+
runs-on: ubuntu-latest
|
| 62 |
+
steps:
|
| 63 |
+
- uses: actions/checkout@v4
|
| 64 |
+
- uses: actions/setup-node@v4
|
| 65 |
+
with:
|
| 66 |
+
node-version: "22"
|
| 67 |
+
cache: npm
|
| 68 |
+
cache-dependency-path: interpreter/frontend/package-lock.json
|
| 69 |
+
- name: Install frontend
|
| 70 |
+
working-directory: interpreter/frontend
|
| 71 |
+
run: npm ci
|
| 72 |
+
- name: Lint frontend
|
| 73 |
+
working-directory: interpreter/frontend
|
| 74 |
+
run: npm run lint
|
| 75 |
+
- name: Test frontend
|
| 76 |
+
working-directory: interpreter/frontend
|
| 77 |
+
run: npm test
|
| 78 |
+
- name: Build frontend
|
| 79 |
+
working-directory: interpreter/frontend
|
| 80 |
+
run: npm run build
|
| 81 |
+
|
| 82 |
+
e2e:
|
| 83 |
+
runs-on: ubuntu-latest
|
| 84 |
+
needs: [interpreter, frontend]
|
| 85 |
+
env:
|
| 86 |
+
PROVIDER_MODE: mock
|
| 87 |
+
steps:
|
| 88 |
+
- uses: actions/checkout@v4
|
| 89 |
+
- uses: actions/setup-python@v5
|
| 90 |
+
with:
|
| 91 |
+
python-version: "3.12"
|
| 92 |
+
- uses: actions/setup-node@v4
|
| 93 |
+
with:
|
| 94 |
+
node-version: "22"
|
| 95 |
+
cache: npm
|
| 96 |
+
cache-dependency-path: interpreter/frontend/package-lock.json
|
| 97 |
+
- name: Install shared and interpreter
|
| 98 |
+
run: python -m pip install -e "./shared" -e "./interpreter[dev]"
|
| 99 |
+
- name: Install frontend
|
| 100 |
+
working-directory: interpreter/frontend
|
| 101 |
+
run: npm ci
|
| 102 |
+
- name: Install Playwright browser
|
| 103 |
+
working-directory: interpreter/frontend
|
| 104 |
+
run: npx playwright install --with-deps chromium
|
| 105 |
+
- name: Run Playwright e2e
|
| 106 |
+
working-directory: interpreter/frontend
|
| 107 |
+
run: npx playwright test
|
| 108 |
+
|
| 109 |
+
site:
|
| 110 |
+
runs-on: ubuntu-latest
|
| 111 |
+
steps:
|
| 112 |
+
- uses: actions/checkout@v4
|
| 113 |
+
- uses: actions/setup-node@v4
|
| 114 |
+
with:
|
| 115 |
+
node-version: "22"
|
| 116 |
+
cache: npm
|
| 117 |
+
cache-dependency-path: scribe/frontend/package-lock.json
|
| 118 |
+
- name: Install demo site
|
| 119 |
+
working-directory: scribe/frontend
|
| 120 |
+
run: npm ci
|
| 121 |
+
- name: Lint demo site
|
| 122 |
+
working-directory: scribe/frontend
|
| 123 |
+
run: npm run lint
|
| 124 |
+
- name: Test demo site
|
| 125 |
+
working-directory: scribe/frontend
|
| 126 |
+
run: npm test
|
| 127 |
+
- name: Test Vercel environment validation
|
| 128 |
+
working-directory: scribe/frontend
|
| 129 |
+
run: npm run test:deploy-env
|
| 130 |
+
- name: Build demo site
|
| 131 |
+
working-directory: scribe/frontend
|
| 132 |
+
run: npm run build
|
| 133 |
+
- name: Install Playwright browser
|
| 134 |
+
working-directory: scribe/frontend
|
| 135 |
+
run: npx playwright install --with-deps chromium
|
| 136 |
+
- name: Run demo site e2e
|
| 137 |
+
working-directory: scribe/frontend
|
| 138 |
+
run: npm run e2e
|
| 139 |
+
- name: Rebuild production demo site
|
| 140 |
+
working-directory: scribe/frontend
|
| 141 |
+
run: npm run build
|
| 142 |
+
- name: Audit demo site
|
| 143 |
+
working-directory: scribe/frontend
|
| 144 |
+
run: npm audit
|
| 145 |
+
- name: Run Lighthouse gates
|
| 146 |
+
working-directory: scribe/frontend
|
| 147 |
+
run: npm run lighthouse
|
.github/workflows/keepalive.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Keep HF Space Awake
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
schedule:
|
| 5 |
+
- cron: "0 */12 * * *"
|
| 6 |
+
workflow_dispatch:
|
| 7 |
+
|
| 8 |
+
jobs:
|
| 9 |
+
ping:
|
| 10 |
+
runs-on: ubuntu-latest
|
| 11 |
+
steps:
|
| 12 |
+
- name: Ping health endpoint
|
| 13 |
+
env:
|
| 14 |
+
SPACE_URL: ${{ vars.SPACE_URL }}
|
| 15 |
+
run: |
|
| 16 |
+
test -n "$SPACE_URL"
|
| 17 |
+
curl -fsS "${SPACE_URL%/}/api/v1/health"
|
.gitignore
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.env
|
| 2 |
+
.venv/
|
| 3 |
+
__pycache__/
|
| 4 |
+
*.py[cod]
|
| 5 |
+
*.egg-info/
|
| 6 |
+
.pytest_cache/
|
| 7 |
+
.ruff_cache/
|
| 8 |
+
.mypy_cache/
|
| 9 |
+
artifacts/
|
| 10 |
+
models/
|
| 11 |
+
tmp/
|
| 12 |
+
*.wav
|
| 13 |
+
*.mp3
|
| 14 |
+
*.m4a
|
| 15 |
+
*.aac
|
| 16 |
+
*.flac
|
| 17 |
+
*.ogg
|
| 18 |
+
*.oga
|
| 19 |
+
*.opus
|
| 20 |
+
*.webm
|
| 21 |
+
|
| 22 |
+
node_modules/
|
| 23 |
+
dist/
|
| 24 |
+
coverage/
|
| 25 |
+
*.tsbuildinfo
|
| 26 |
+
playwright-report/
|
| 27 |
+
test-results/
|
| 28 |
+
eval/reports/
|
| 29 |
+
interpreter/eval/reports/
|
| 30 |
+
|
| 31 |
+
*.db
|
| 32 |
+
*.sqlite
|
| 33 |
+
*.sqlite3
|
| 34 |
+
|
| 35 |
+
# Harness durable layer
|
| 36 |
+
harness.db
|
| 37 |
+
harness.db-wal
|
| 38 |
+
harness.db-shm
|
| 39 |
+
scripts/bin/harness-cli
|
| 40 |
+
scripts/bin/harness-cli.exe
|
AGENTS.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Agent instructions — CarePath unified
|
| 2 |
+
|
| 3 |
+
CarePath is one unified medical AI product with two clearly separated user-facing modules:
|
| 4 |
+
|
| 5 |
+
1. **Ghi chép bệnh án AI**
|
| 6 |
+
Internal/technical term: AI Scribe / scriber
|
| 7 |
+
Backend: `scribe/carepath`, `/api/v1/*`
|
| 8 |
+
Purpose: listen to a consultation and help generate structured clinical notes.
|
| 9 |
+
|
| 10 |
+
2. **Phiên dịch khám bệnh trực tiếp**
|
| 11 |
+
Internal/technical term: Medical Interpreter / interpreter
|
| 12 |
+
Backend: `interpreter/app`, `/api/*` + `/ws/*`
|
| 13 |
+
Purpose: live two-way interpretation between Vietnamese doctors and English-speaking patients.
|
| 14 |
+
|
| 15 |
+
The app is served by one FastAPI process plus two Vite frontends:
|
| 16 |
+
|
| 17 |
+
* `scribe/frontend/` at `/`
|
| 18 |
+
* `interpreter/frontend/` at `/phien-dich-y-khoa/` (`/console/` is a legacy redirect)
|
| 19 |
+
|
| 20 |
+
## Interpreter status
|
| 21 |
+
|
| 22 |
+
After restructure Phase 7, the Interpreter is on hold. Accept only bug fixes,
|
| 23 |
+
safety fixes, and required operational maintenance there; new product work is
|
| 24 |
+
focused on the Scribe training track unless the owner explicitly reopens it.
|
| 25 |
+
|
| 26 |
+
`docs/history/PLAN.md` and `docs/history/DEMO-SITE-PLAN.md` are historical build
|
| 27 |
+
plans for the interpreter and demo site. `docs/history/MERGE-PLAN.md` is the
|
| 28 |
+
executed unification plan, M.0–M.8 done, and `docs/history/JUDGE.md` is its
|
| 29 |
+
review protocol.
|
| 30 |
+
`docs/research.md` holds the interpreter safety background.
|
| 31 |
+
|
| 32 |
+
## Product UX contract
|
| 33 |
+
|
| 34 |
+
CarePath must be Vietnamese-first.
|
| 35 |
+
|
| 36 |
+
The target users may include Vietnamese doctors who are not comfortable with English medical software terms. Therefore, the UI must explain workflows by user intent, not by English product names.
|
| 37 |
+
|
| 38 |
+
### Primary user-facing labels
|
| 39 |
+
|
| 40 |
+
Use these as primary UI labels:
|
| 41 |
+
|
| 42 |
+
* `Ghi chép bệnh án AI`
|
| 43 |
+
* `Phiên dịch khám bệnh trực tiếp`
|
| 44 |
+
|
| 45 |
+
Use these as primary CTAs:
|
| 46 |
+
|
| 47 |
+
* `Bắt đầu ghi chép`
|
| 48 |
+
* `Bắt đầu phiên dịch`
|
| 49 |
+
|
| 50 |
+
Use this homepage framing:
|
| 51 |
+
|
| 52 |
+
```text
|
| 53 |
+
Bạn muốn hỗ trợ việc gì hôm nay?
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
### Secondary/internal labels
|
| 57 |
+
|
| 58 |
+
The following English terms may appear only as secondary helper text, developer labels, comments, docs, or internal route/component names:
|
| 59 |
+
|
| 60 |
+
* Scribe
|
| 61 |
+
* AI Scribe
|
| 62 |
+
* Interpreter
|
| 63 |
+
* Medical Interpreter
|
| 64 |
+
* Console
|
| 65 |
+
* Transcript
|
| 66 |
+
* Encounter
|
| 67 |
+
* Session
|
| 68 |
+
|
| 69 |
+
Do not use `Scribe` or `Interpreter` as primary labels on user-facing screens.
|
| 70 |
+
|
| 71 |
+
### Required distinction between the two modules
|
| 72 |
+
|
| 73 |
+
The landing page must make it obvious that these are two different workflows:
|
| 74 |
+
|
| 75 |
+
#### Ghi chép bệnh án AI
|
| 76 |
+
|
| 77 |
+
Explain as:
|
| 78 |
+
|
| 79 |
+
```text
|
| 80 |
+
AI nghe buổi khám và tạo ghi chú y khoa có cấu trúc.
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
Use when:
|
| 84 |
+
|
| 85 |
+
```text
|
| 86 |
+
Phù hợp khi bác sĩ muốn giảm thời gian nhập liệu sau khám.
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
Clarify that the doctor must review the output before use.
|
| 90 |
+
|
| 91 |
+
#### Phiên dịch khám bệnh trực tiếp
|
| 92 |
+
|
| 93 |
+
Explain as:
|
| 94 |
+
|
| 95 |
+
```text
|
| 96 |
+
Dịch hai chiều giữa bác sĩ tiếng Việt và bệnh nhân tiếng Anh trong lúc khám.
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
Use when:
|
| 100 |
+
|
| 101 |
+
```text
|
| 102 |
+
Phù hợp khi bác sĩ và bệnh nhân không cùng ngôn ngữ.
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
Clarify that the system translates only and must not provide medical advice.
|
| 106 |
+
|
| 107 |
+
### Every user-facing screen must answer
|
| 108 |
+
|
| 109 |
+
1. Tôi đang dùng chức năng nào?
|
| 110 |
+
2. Chức năng này giúp việc gì?
|
| 111 |
+
3. Tôi cần bấm gì tiếp theo?
|
| 112 |
+
4. Có rủi ro hoặc giới hạn nào bác sĩ cần biết không?
|
| 113 |
+
|
| 114 |
+
### Vietnamese copy rules
|
| 115 |
+
|
| 116 |
+
* Vietnamese text must be clear, short, and professional.
|
| 117 |
+
* Preserve Vietnamese diacritics.
|
| 118 |
+
* Keep text NFC-normalized.
|
| 119 |
+
* Avoid unnecessary English.
|
| 120 |
+
* Avoid startup/marketing buzzwords on clinical workflow screens.
|
| 121 |
+
* Prefer concrete action language over abstract product names.
|
| 122 |
+
|
| 123 |
+
Good:
|
| 124 |
+
|
| 125 |
+
```text
|
| 126 |
+
Ghi chép bệnh án AI
|
| 127 |
+
Phiên dịch khám bệnh trực tiếp
|
| 128 |
+
Bắt đầu ghi chép
|
| 129 |
+
Bắt đầu phiên dịch
|
| 130 |
+
Bác sĩ nói tiếng Việt, bệnh nhân nghe tiếng Anh
|
| 131 |
+
```
|
| 132 |
+
|
| 133 |
+
Avoid as primary UI:
|
| 134 |
+
|
| 135 |
+
```text
|
| 136 |
+
Scribe
|
| 137 |
+
Interpreter
|
| 138 |
+
Session
|
| 139 |
+
Encounter
|
| 140 |
+
Transcript
|
| 141 |
+
Start session
|
| 142 |
+
Launch interpreter
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
## Non-negotiable safety invariants
|
| 146 |
+
|
| 147 |
+
This file is the current safety contract. `docs/history/PLAN.md §2` preserves
|
| 148 |
+
the original MVP source for historical context.
|
| 149 |
+
|
| 150 |
+
1. Translate-only: never generate medical advice, diagnoses, or drug recommendations.
|
| 151 |
+
2. High/critical-risk turns are blocked from patient display and TTS until doctor confirms.
|
| 152 |
+
3. Low-confidence output is always visibly flagged, never silently delivered.
|
| 153 |
+
4. Raw audio is never persisted. Use memory-only processing. No audio columns, no temp files.
|
| 154 |
+
5. No mic capture before recorded consent.
|
| 155 |
+
6. On any pipeline or reviewer failure, fail closed: keep the turn blocked, show the doctor raw source and translation, offer escalation. Never fail open to the patient.
|
| 156 |
+
|
| 157 |
+
## Implementation workflow for agents
|
| 158 |
+
|
| 159 |
+
For UX or product-flow changes, do not implement immediately.
|
| 160 |
+
|
| 161 |
+
First produce or update a plan in `docs/ux-redesign-carepath.md` with:
|
| 162 |
+
|
| 163 |
+
1. Current UX problem
|
| 164 |
+
2. Proposed flow
|
| 165 |
+
3. Affected routes/pages/components
|
| 166 |
+
4. Vietnamese-first copy
|
| 167 |
+
5. Implementation stories
|
| 168 |
+
6. Dependencies between stories
|
| 169 |
+
7. Acceptance criteria
|
| 170 |
+
8. Validation commands
|
| 171 |
+
9. Risks and fallback behavior
|
| 172 |
+
|
| 173 |
+
Then implement one story at a time.
|
| 174 |
+
|
| 175 |
+
### Recommended story order for UX redesign
|
| 176 |
+
|
| 177 |
+
1. Update Vietnamese-first product naming and copy.
|
| 178 |
+
2. Redesign the landing page into two clear workflow cards.
|
| 179 |
+
3. Add or clarify separate entry routes for the two modules.
|
| 180 |
+
4. Add pre-start onboarding/explanation screens.
|
| 181 |
+
5. Improve empty/loading/error states in Vietnamese.
|
| 182 |
+
6. Run QA for mobile, accessibility, safety copy, and route regressions.
|
| 183 |
+
|
| 184 |
+
Do not combine homepage redesign, routing changes, and audio/backend logic changes in one large patch.
|
| 185 |
+
|
| 186 |
+
### Agent behavior
|
| 187 |
+
|
| 188 |
+
* Keep changes small and focused.
|
| 189 |
+
* Preserve existing working functionality.
|
| 190 |
+
* Do not rewrite backend, audio, risk, or websocket logic unless the current story explicitly requires it.
|
| 191 |
+
* Do not introduce new dependencies without documenting why.
|
| 192 |
+
* Prefer existing components and styling patterns.
|
| 193 |
+
* When changing user-facing Vietnamese text, check diacritics and consistency.
|
| 194 |
+
* When changing risk-engine behavior, update fixtures and evals.
|
| 195 |
+
* When changing product copy only, avoid touching medical logic.
|
| 196 |
+
|
| 197 |
+
## Commands
|
| 198 |
+
|
| 199 |
+
### Combined service
|
| 200 |
+
|
| 201 |
+
```bash
|
| 202 |
+
uvicorn carepath.main:app --app-dir scribe --reload
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
Requires:
|
| 206 |
+
|
| 207 |
+
```bash
|
| 208 |
+
pip install -e ".[dev]" -e "./shared" -e "./interpreter[dev]"
|
| 209 |
+
```
|
| 210 |
+
|
| 211 |
+
### Scriber and combined tests
|
| 212 |
+
|
| 213 |
+
```bash
|
| 214 |
+
pytest
|
| 215 |
+
python scripts/smoke_backend.py
|
| 216 |
+
python scripts/build_term_artifacts.py --check
|
| 217 |
+
```
|
| 218 |
+
|
| 219 |
+
### Interpreter backend alone
|
| 220 |
+
|
| 221 |
+
```bash
|
| 222 |
+
cd interpreter && uvicorn app.main:app --reload
|
| 223 |
+
pytest
|
| 224 |
+
```
|
| 225 |
+
|
| 226 |
+
### Console
|
| 227 |
+
|
| 228 |
+
```bash
|
| 229 |
+
cd interpreter/frontend && npm run dev
|
| 230 |
+
npm test
|
| 231 |
+
npx playwright test
|
| 232 |
+
```
|
| 233 |
+
|
| 234 |
+
### Demo site
|
| 235 |
+
|
| 236 |
+
```bash
|
| 237 |
+
cd scribe/frontend && npm run dev
|
| 238 |
+
npm test
|
| 239 |
+
npm run build
|
| 240 |
+
npm run e2e
|
| 241 |
+
```
|
| 242 |
+
|
| 243 |
+
`npm run build` is also the diacritics gate.
|
| 244 |
+
|
| 245 |
+
### Full mock-mode run
|
| 246 |
+
|
| 247 |
+
Set this in `.env`:
|
| 248 |
+
|
| 249 |
+
```bash
|
| 250 |
+
PROVIDER_MODE=mock
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
Mock mode must work with no API keys.
|
| 254 |
+
|
| 255 |
+
### Eval regression
|
| 256 |
+
|
| 257 |
+
```bash
|
| 258 |
+
python interpreter/eval/run_eval.py --set interpreter/eval/fixtures/eval_starter.tsv --providers mock
|
| 259 |
+
```
|
| 260 |
+
|
| 261 |
+
## Conventions
|
| 262 |
+
|
| 263 |
+
* Python 3.12.
|
| 264 |
+
* Python code must be ruff-formatted and type-hinted.
|
| 265 |
+
* Use pure functions for normalization and risk rules.
|
| 266 |
+
* TypeScript must be strict.
|
| 267 |
+
* Components should be small.
|
| 268 |
+
* Keep state minimal: context/zustand is allowed, Redux is not.
|
| 269 |
+
* `shared/carepath_shared/terms/medical_terms.json` is the canonical medical
|
| 270 |
+
term source. Regenerate `data/medical_lexicon.json` and
|
| 271 |
+
`interpreter/app/glossary/data/seed_glossary.csv` with
|
| 272 |
+
`python scripts/build_term_artifacts.py`; do not hand-edit generated artifacts.
|
| 273 |
+
* Risk lexicons under `interpreter/app/risk/lexicons/` remain separate
|
| 274 |
+
interpreter safety data. Clinicians edit data, not code.
|
| 275 |
+
* Every risk-engine behavior change updates `interpreter/eval/fixtures/risk_cases.jsonl`.
|
| 276 |
+
* The fixture run is the test.
|
| 277 |
+
* Zero misses on critical fixtures is a hard gate.
|
| 278 |
+
* Secrets only via env.
|
| 279 |
+
* `.env` is gitignored.
|
| 280 |
+
* `.env.example` must stay current.
|
| 281 |
+
* No new dependencies without noting why in the PR.
|
| 282 |
+
* Vietnamese text is data, not decoration: always NFC-normalized, diacritics preserved.
|
| 283 |
+
* Tests must include diacritic-stripped variants where matching allows it.
|
| 284 |
+
|
| 285 |
+
## Acceptance criteria for UX clarity changes
|
| 286 |
+
|
| 287 |
+
A UX clarity change is not done un less all of the following are true:
|
| 288 |
+
|
| 289 |
+
1. A Vietnamese doctor can understand the two workflows without knowing the words `Scribe` or `Interpreter`.
|
| 290 |
+
2. The landing page clearly separates:
|
| 291 |
+
|
| 292 |
+
* `Ghi chép bệnh án AI`
|
| 293 |
+
* `Phiên dịch khám bệnh trực tiếp`
|
| 294 |
+
3. Each workflow has a distinct CTA.
|
| 295 |
+
4. Each workflow explains when to use it.
|
| 296 |
+
5. English terms appear only as secondary helper text, not primary labels.
|
| 297 |
+
6. Mobile layout remains clear.
|
| 298 |
+
7. Existing core functionality still works.
|
| 299 |
+
8. Safety invariants remain unchanged.
|
| 300 |
+
9. Build and relevant tests pass.
|
| 301 |
+
|
| 302 |
+
<!-- HARNESS:START -->
|
| 303 |
+
## Harness workflow
|
| 304 |
+
|
| 305 |
+
This repository uses Repository Harness for durable task intake, proof, and
|
| 306 |
+
decision records. This block adds to the CarePath instructions above; it does
|
| 307 |
+
not replace them.
|
| 308 |
+
|
| 309 |
+
Priority, highest first:
|
| 310 |
+
|
| 311 |
+
1. The current user request and the safety and product rules in this file.
|
| 312 |
+
2. Current product contracts in `docs/product/`.
|
| 313 |
+
3. Selected story packets in `docs/stories/` and accepted decisions in
|
| 314 |
+
`docs/decisions/`.
|
| 315 |
+
4. Executable tests and the Harness proof matrix.
|
| 316 |
+
5. `docs/history/` as context only.
|
| 317 |
+
|
| 318 |
+
Before any task, read `README.md`, `docs/HARNESS.md`, and
|
| 319 |
+
`docs/FEATURE_INTAKE.md`; then run
|
| 320 |
+
`.\scripts\bin\harness-cli.exe query matrix` on Windows. Classify and record
|
| 321 |
+
the task as `tiny`, `normal`, or `high-risk` before changing code.
|
| 322 |
+
|
| 323 |
+
- Tiny work records an intake and runs the relevant quick proof.
|
| 324 |
+
- Normal work also updates one story packet and its proof record.
|
| 325 |
+
- High-risk work uses `docs/templates/high-risk-story/`, records a decision
|
| 326 |
+
when it changes architecture, data, safety, APIs, or validation, and waits
|
| 327 |
+
for human direction if its scope is ambiguous.
|
| 328 |
+
- A UX or product-flow task still must first update
|
| 329 |
+
`docs/ux-redesign-carepath.md`, then follow the Harness lane requirements.
|
| 330 |
+
- Before a step that could use an external tool, query the available provider:
|
| 331 |
+
`.\scripts\bin\harness-cli.exe query tools --capability <capability> --status present`.
|
| 332 |
+
A missing provider is a clean skip, never a reason to invent a dependency.
|
| 333 |
+
- Finish normal and high-risk work with a Harness trace that records the real
|
| 334 |
+
validation outcome and any friction. Do not claim proof that was not run.
|
| 335 |
+
<!-- HARNESS:END -->
|
CLAUDE.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath
|
| 2 |
+
|
| 3 |
+
@AGENTS.md
|
| 4 |
+
@docs/FEATURE_INTAKE.md
|
| 5 |
+
|
| 6 |
+
Use the Harness workflow in `AGENTS.md` before changing this repository.
|
Dockerfile
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# --- Stage 1: build the static frontends (demo site + interpreter console) ---
|
| 2 |
+
FROM node:22-slim AS frontends
|
| 3 |
+
|
| 4 |
+
WORKDIR /build
|
| 5 |
+
|
| 6 |
+
COPY scribe/frontend/package.json scribe/frontend/package-lock.json scribe/frontend/
|
| 7 |
+
RUN cd scribe/frontend && npm ci
|
| 8 |
+
COPY scribe/frontend scribe/frontend
|
| 9 |
+
# site build also runs the Vietnamese diacritics gate.
|
| 10 |
+
RUN cd scribe/frontend && npm run build
|
| 11 |
+
|
| 12 |
+
COPY interpreter/frontend/package.json interpreter/frontend/package-lock.json interpreter/frontend/
|
| 13 |
+
RUN cd interpreter/frontend && npm ci
|
| 14 |
+
COPY interpreter/frontend interpreter/frontend
|
| 15 |
+
# Production build uses base /phien-dich-y-khoa/ (see interpreter/frontend/vite.config.ts).
|
| 16 |
+
ARG VITE_PUBLIC_SITE_URL
|
| 17 |
+
ENV VITE_PUBLIC_SITE_URL=${VITE_PUBLIC_SITE_URL}
|
| 18 |
+
RUN cd interpreter/frontend && npm run build
|
| 19 |
+
|
| 20 |
+
# --- Stage 2: Python runtime serving both APIs and the built frontends ---
|
| 21 |
+
FROM python:3.12-slim
|
| 22 |
+
|
| 23 |
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
| 24 |
+
PYTHONUNBUFFERED=1 \
|
| 25 |
+
PIP_NO_CACHE_DIR=1 \
|
| 26 |
+
HF_HOME=/opt/hf-cache
|
| 27 |
+
|
| 28 |
+
WORKDIR /app
|
| 29 |
+
|
| 30 |
+
RUN apt-get update \
|
| 31 |
+
&& apt-get install -y --no-install-recommends ca-certificates libgomp1 libsndfile1 \
|
| 32 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 33 |
+
|
| 34 |
+
COPY pyproject.toml README.md ./
|
| 35 |
+
COPY shared ./shared
|
| 36 |
+
COPY scribe/carepath ./scribe/carepath
|
| 37 |
+
COPY interpreter ./interpreter
|
| 38 |
+
RUN python -m pip install --upgrade pip \
|
| 39 |
+
&& python -m pip install . ./shared ./interpreter
|
| 40 |
+
|
| 41 |
+
ARG GIPFORMER_QUANTIZE=int8
|
| 42 |
+
ENV GIPFORMER_QUANTIZE=${GIPFORMER_QUANTIZE}
|
| 43 |
+
RUN python -c "from carepath.services.asr import GipformerASR; from huggingface_hub import hf_hub_download; files = GipformerASR.onnx_files['${GIPFORMER_QUANTIZE}']; [hf_hub_download(repo_id=GipformerASR.repo_id, filename=name) for name in (*files.values(), 'tokens.txt')]"
|
| 44 |
+
|
| 45 |
+
COPY data ./data
|
| 46 |
+
COPY --from=frontends /build/scribe/frontend/dist ./scribe/frontend/dist
|
| 47 |
+
COPY --from=frontends /build/interpreter/frontend/dist ./interpreter/frontend/dist
|
| 48 |
+
ENV SITE_DIST_DIR=/app/scribe/frontend/dist \
|
| 49 |
+
CONSOLE_DIST_DIR=/app/interpreter/frontend/dist
|
| 50 |
+
|
| 51 |
+
EXPOSE 7860
|
| 52 |
+
|
| 53 |
+
CMD ["uvicorn", "carepath.main:app", "--app-dir", "scribe", "--host", "0.0.0.0", "--port", "7860"]
|
README.hf-space.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: CarePath
|
| 3 |
+
sdk: docker
|
| 4 |
+
app_port: 7860
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# CarePath Space
|
| 8 |
+
|
| 9 |
+
This Space runs the unified CarePath product from the root `Dockerfile`, which
|
| 10 |
+
builds `scribe/frontend/` and `interpreter/frontend/`:
|
| 11 |
+
demo site at `/`, Scribe tool at `/ghi-chep-lam-sang/`, scriber API at
|
| 12 |
+
`/api/v1/*`, and Interpreter API at `/api/*` + `/ws/*`. Interpreter browser
|
| 13 |
+
paths are disabled for public users while that module remains in development.
|
| 14 |
+
|
| 15 |
+
Required Space secrets (scriber; the interpreter runs keyless in mock mode):
|
| 16 |
+
|
| 17 |
+
- `LLM_PROVIDER=ckey`
|
| 18 |
+
- `LLM_API_KEY=<your CKey key>`
|
| 19 |
+
- `LLM_MODEL=gpt-5.4`
|
| 20 |
+
- `TEAM_CODE=<shared internal bypass code>`
|
| 21 |
+
- `APP_ENV=prod`
|
README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: CarePath
|
| 3 |
+
sdk: docker
|
| 4 |
+
app_port: 7860
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# CarePath Space
|
| 8 |
+
|
| 9 |
+
This Space runs the unified CarePath product from the root `Dockerfile`, which
|
| 10 |
+
builds `scribe/frontend/` and `interpreter/frontend/`:
|
| 11 |
+
demo site at `/`, Scribe tool at `/ghi-chep-lam-sang/`, scriber API at
|
| 12 |
+
`/api/v1/*`, and Interpreter API at `/api/*` + `/ws/*`. Interpreter browser
|
| 13 |
+
paths are disabled for public users while that module remains in development.
|
| 14 |
+
|
| 15 |
+
Required Space secrets (scriber; the interpreter runs keyless in mock mode):
|
| 16 |
+
|
| 17 |
+
- `LLM_PROVIDER=ckey`
|
| 18 |
+
- `LLM_API_KEY=<your CKey key>`
|
| 19 |
+
- `LLM_MODEL=gpt-5.4`
|
| 20 |
+
- `TEAM_CODE=<shared internal bypass code>`
|
| 21 |
+
- `APP_ENV=prod`
|
UI-FIX-PLAN.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# UI Fix Plan — carepath-omega.vercel.app (scribe/frontend/)
|
| 2 |
+
|
| 3 |
+
Plan authored by Fable 5 after reviewing the live deploy and source. Executor: Opus 4.8.
|
| 4 |
+
Scope: the Vite/React app in `scribe/frontend/` only. Do the fixes in order. Keep diffs minimal — no redesigns, no new dependencies.
|
| 5 |
+
|
| 6 |
+
## How findings were verified (and how you re-verify)
|
| 7 |
+
|
| 8 |
+
The live site was screenshotted and probed with the repo's own Playwright
|
| 9 |
+
(`scribe/frontend/node_modules/playwright-core`, headless Chromium) at 1440/1100/900/800/390px widths.
|
| 10 |
+
Re-run any probe the same way, e.g.:
|
| 11 |
+
|
| 12 |
+
```js
|
| 13 |
+
// node, from scribe/frontend/: require('playwright-core'), launch chromium,
|
| 14 |
+
// newPage({ viewport }), goto https://carepath-omega.vercel.app/ (or local `npm run preview`)
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
Verify locally against `npm run dev`/`preview` in `scribe/frontend/` — do not deploy to verify.
|
| 18 |
+
|
| 19 |
+
## Do NOT chase these (verified non-issues)
|
| 20 |
+
|
| 21 |
+
Full-page/element screenshots of this site produce artifacts because of the sticky nav and
|
| 22 |
+
GSAP scroll animations. Already confirmed fine:
|
| 23 |
+
|
| 24 |
+
- Hero "Audio → SOAP" strip overhanging its card (`.hero__route--scribe { right: -3% }`) is an
|
| 25 |
+
intentional accent. `document.scrollWidth - clientWidth === 0` at all tested widths — no
|
| 26 |
+
horizontal overflow anywhere.
|
| 27 |
+
- Grey band across the bottom of the safety bento in screenshots = GSAP scrub timeline
|
| 28 |
+
(`scribe/frontend/src/landing/useLandingMotion.ts:45-68`) caught mid-state. Renders correctly live.
|
| 29 |
+
- Scribe chapter body text is complete in source (`scribe/frontend/src/content/strings.ts:340`); the
|
| 30 |
+
"truncation" seen in captures was the sticky nav bar overlaying a line during scroll-stitching.
|
| 31 |
+
- Marquee is 48px tall and animates correctly; "clipped text" in captures is the same stitching
|
| 32 |
+
artifact.
|
| 33 |
+
|
| 34 |
+
---
|
| 35 |
+
|
| 36 |
+
## P0-1: Lead contact path is dead on production
|
| 37 |
+
|
| 38 |
+
**Symptom:** Footer "Liên hệ chương trình thí điểm" renders `href="mailto:"` (no recipient).
|
| 39 |
+
Submitting the pilot lead form opens a recipient-less mail draft and then shows the success-ish
|
| 40 |
+
"mail opened" status. The site's only conversion path silently goes nowhere.
|
| 41 |
+
|
| 42 |
+
**Root cause:** Neither `VITE_LEAD_ENDPOINT` nor `VITE_LEAD_EMAIL` is set in the Vercel project.
|
| 43 |
+
`submitLead()` falls through to `buildLeadMailto(payload, email = "")`
|
| 44 |
+
(`scribe/frontend/src/leads.ts:88-130`). The deploy gate `scribe/frontend/scripts/validate-deploy-env.mjs` only
|
| 45 |
+
validates `VITE_API_BASE` + `VITE_CONSOLE_URL`, so the build passed anyway
|
| 46 |
+
(`scribe/frontend/vercel.json` runs `npm run validate:deploy && npm run build`).
|
| 47 |
+
|
| 48 |
+
**Fix (all three parts):**
|
| 49 |
+
1. `scribe/frontend/scripts/validate-deploy-env.mjs`: require at least one lead channel — error if both
|
| 50 |
+
`VITE_LEAD_ENDPOINT` and `VITE_LEAD_EMAIL` are empty. Extend
|
| 51 |
+
`scribe/frontend/scripts/validate-deploy-env.test.mjs` accordingly (`npm run test:deploy-env`).
|
| 52 |
+
2. UI guard, belt-and-suspenders:
|
| 53 |
+
- `scribe/frontend/src/leads.ts` / `scribe/frontend/src/LeadForm.tsx`: if no endpoint and no email, `submitLead`
|
| 54 |
+
must not open `mailto:` and the form must show the existing error status (`labels.failed`
|
| 55 |
+
path) instead of "mail opened". Never report success for a no-op.
|
| 56 |
+
- `scribe/frontend/src/LandingPage.tsx:476-478`: don't render the footer mailto link when
|
| 57 |
+
`VITE_LEAD_EMAIL` is empty (render the text non-linked, or drop it).
|
| 58 |
+
- Existing tests mock `leadEmail`/`endpoint` props (`scribe/frontend/src/LeadForm.test.tsx`,
|
| 59 |
+
`scribe/frontend/src/leads.test.ts`) — add the empty-config case.
|
| 60 |
+
3. Tell the user to set `VITE_LEAD_EMAIL` (and optionally `VITE_LEAD_ENDPOINT`) in the Vercel
|
| 61 |
+
project settings — the value is a business decision; do not invent one. The code fix must be
|
| 62 |
+
correct with or without it.
|
| 63 |
+
|
| 64 |
+
**Accept when:** with no lead env vars, footer shows no dead link and form submit shows an error,
|
| 65 |
+
not success; `npm run test` and `npm run test:deploy-env` pass; with `VITE_LEAD_EMAIL` set the
|
| 66 |
+
mailto contains the recipient.
|
| 67 |
+
|
| 68 |
+
## P0-2: Mobile nav menu opens off-screen — links unusable on phones
|
| 69 |
+
|
| 70 |
+
**Symptom:** At 390×844, opening the hamburger shows a white panel whose link labels are
|
| 71 |
+
invisible. Measured panel box: `x = -108, width = 304` — a third of it (including all left-padded
|
| 72 |
+
label text) is past the left viewport edge. At 900px the panel floats detached mid-nav
|
| 73 |
+
(`x = 225`) under the centered button.
|
| 74 |
+
|
| 75 |
+
**Root cause:** `scribe/frontend/src/styles.css:2267-2277` — `.site-nav__menu > div` is
|
| 76 |
+
`position: absolute; right: 0` anchored to `.site-nav__menu` (`position: relative`, line 2248),
|
| 77 |
+
i.e. to the 2.6rem hamburger itself, which sits mid-nav between the brand and the VI/EN toggle.
|
| 78 |
+
The 19rem-wide panel extends leftward from there.
|
| 79 |
+
|
| 80 |
+
**Fix:** Anchor the panel to the nav bar, not the button. `.site-nav` is `position: sticky`
|
| 81 |
+
(styles.css:129-141) and therefore already a containing block for absolute descendants — the
|
| 82 |
+
smallest fix is to drop `position: relative` from `.site-nav__menu` (line 2248) and give the
|
| 83 |
+
panel a right offset matching the nav padding (`right: max(1.5rem, calc((100vw - var(--container)) / 2))`
|
| 84 |
+
at ≥761px; `1rem`-ish at ≤760px — mirror the nav's own padding values). Keep
|
| 85 |
+
`width: min(19rem, calc(100vw - 2rem))`.
|
| 86 |
+
|
| 87 |
+
**Accept when:** at 320, 390, 760, and 900px widths the open panel's bounding box is fully inside
|
| 88 |
+
the viewport, flush near the right edge below the bar, and every link label is visible.
|
| 89 |
+
|
| 90 |
+
## P0-3: Menu never closes after navigating
|
| 91 |
+
|
| 92 |
+
**Symptom:** Tap hamburger → tap "An toàn" → page scrolls to the section but the `<details>`
|
| 93 |
+
panel stays open, covering the content just navigated to. Verified: `.site-nav__menu[open]`
|
| 94 |
+
still present after link click.
|
| 95 |
+
|
| 96 |
+
**Root cause:** Native `<details>` doesn't close on child anchor clicks
|
| 97 |
+
(`scribe/frontend/src/LandingPage.tsx:60-63`).
|
| 98 |
+
|
| 99 |
+
**Fix:** In `LandingPage.tsx`, close the details when a menu link is clicked (e.g. `onClick` on
|
| 100 |
+
the wrapping div or each link that clears the `open` attribute via a ref). Keep it a few lines —
|
| 101 |
+
no state library, no outside-click handler unless it's free.
|
| 102 |
+
|
| 103 |
+
**Accept when:** tapping any menu link scrolls to the section AND the panel is closed.
|
| 104 |
+
|
| 105 |
+
## P1-1: Evidence section headline wraps 2 words × 6 lines on desktop
|
| 106 |
+
|
| 107 |
+
**Symptom:** At 1440px, "Xem cách mỗi sản phẩm giữ điểm cần duyệt ở đúng chỗ." renders 64px in a
|
| 108 |
+
379px-wide column → 6 cramped lines. Measured: `{w: 379, fs: 64px, lines: 6}`; still 4 lines at
|
| 109 |
+
1100px. Inside the carousel the slide `h3` (up to 2.6rem in a ~270px column,
|
| 110 |
+
`.evidence-slide` col `minmax(13rem, 0.65fr)`, styles.css:2062-2094) wraps ~5 lines the same way.
|
| 111 |
+
|
| 112 |
+
**Root cause:** `.evidence` grid gives the intro `minmax(16rem, 0.55fr)` of a 74rem container
|
| 113 |
+
minus up to 8rem gap (styles.css:2049-2056), while `.section-intro h2` uses the global
|
| 114 |
+
`clamp(2rem, 4.5vw, 4rem)` scale (styles.css:1615-1618) sized for full-width intros.
|
| 115 |
+
|
| 116 |
+
**Fix:** Scoped override, not a layout rework — e.g.
|
| 117 |
+
`.evidence .section-intro h2 { font-size: clamp(1.8rem, 2.2vw, 2.5rem); }` and similarly cap
|
| 118 |
+
`.evidence-slide__copy h3` (~`clamp(1.4rem, 1.8vw, 1.9rem)`). Alternatively rebalance the column
|
| 119 |
+
(`0.55fr → 0.75fr`) plus a smaller cap — pick whichever reads best live, but the acceptance bar
|
| 120 |
+
is below. Don't touch other sections' headings.
|
| 121 |
+
|
| 122 |
+
**Accept when:** at 1280–1600px the evidence h2 wraps ≤3 lines with ≥3 words per line, and each
|
| 123 |
+
slide h3 wraps ≤3 lines; ≤1023px layouts (already fine) unchanged.
|
| 124 |
+
|
| 125 |
+
## P2 (do only after P0/P1; each is a 1–2 line change)
|
| 126 |
+
|
| 127 |
+
- **Sticky nav dissolves into the page while scrolling.** `--nav-bg` ≈ page beige at 0.92 alpha
|
| 128 |
+
with only a hairline border (styles.css:129-141), so the floating VI/EN pill + hamburger appear
|
| 129 |
+
to sit directly on content text mid-scroll (most visible on mobile). Add a subtle
|
| 130 |
+
`box-shadow` (or slightly stronger bottom border) to `.site-nav` so the bar reads as a surface.
|
| 131 |
+
- **Marquee labels are 11.84px** (`.marquee__track span`, `font-size: 0.74rem`,
|
| 132 |
+
styles.css:780-791) — uppercase microtext below the 12px floor; bump to `0.78rem`.
|
| 133 |
+
- **Demo controls wrap ragged on mobile:** in `.demo__controls`
|
| 134 |
+
(`scribe/frontend/src/demo/DemoPlayer.tsx:251`, styles for it in styles.css) "Phát lại" wraps to an orphan
|
| 135 |
+
row at 390px. Make the wrap intentional (consistent gap; buttons full-width or evenly split at
|
| 136 |
+
≤760px — match `.product-chapter__actions`' existing pattern at styles.css:2429-2433).
|
| 137 |
+
|
| 138 |
+
## Verification (run all from `scribe/frontend/`)
|
| 139 |
+
|
| 140 |
+
1. `npm run lint`, `npm run test`, `npm run test:deploy-env` — all green.
|
| 141 |
+
2. `npm run build` — green WITH lead env vars; FAILS with a clear message when both lead vars are
|
| 142 |
+
missing (new validator rule). `npm run dev` for visual checks.
|
| 143 |
+
3. Playwright probe (as above) against local dev at 390 / 760 / 900 / 1440px:
|
| 144 |
+
menu panel fully in-viewport, closes on navigate; evidence h2 line counts within budget;
|
| 145 |
+
`scrollWidth === clientWidth` (no new horizontal overflow at any width).
|
| 146 |
+
4. Both languages (VI default, EN toggle) and `#/scribe` route still render — `App.test.tsx`,
|
| 147 |
+
`LandingPage.test.tsx`, `ScribeTool.test.tsx` cover regressions.
|
| 148 |
+
5. The build's `check-diacritics.mjs` runs inside `npm run build` — any copy you touch must keep
|
| 149 |
+
Vietnamese diacritics intact.
|
| 150 |
+
|
| 151 |
+
## Out of scope
|
| 152 |
+
|
| 153 |
+
Backend/`scribe/carepath`, the HF-space console (external `VITE_CONSOLE_URL` target), `interpreter/frontend/`
|
| 154 |
+
(separate app), content rewrites, redesigns, new sections, dependencies.
|
data/medical_lexicon.json
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"terms": [
|
| 3 |
+
{
|
| 4 |
+
"term": "SpO2",
|
| 5 |
+
"category": "vital_sign",
|
| 6 |
+
"vietnamese": "độ bão hòa oxy",
|
| 7 |
+
"aliases": ["spo2", "saturation", "oxy máu"]
|
| 8 |
+
},
|
| 9 |
+
{
|
| 10 |
+
"term": "ECG",
|
| 11 |
+
"category": "test",
|
| 12 |
+
"vietnamese": "điện tâm đồ",
|
| 13 |
+
"aliases": ["ekg", "electrocardiogram"]
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"term": "HbA1c",
|
| 17 |
+
"category": "biomarker",
|
| 18 |
+
"vietnamese": "đường huyết trung bình",
|
| 19 |
+
"aliases": ["hba1c", "a1c"]
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"term": "glucose",
|
| 23 |
+
"category": "biomarker",
|
| 24 |
+
"vietnamese": "đường huyết",
|
| 25 |
+
"aliases": ["blood sugar", "đường máu"]
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"term": "insulin",
|
| 29 |
+
"category": "medication",
|
| 30 |
+
"vietnamese": "insulin",
|
| 31 |
+
"aliases": ["in-su-lin"]
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"term": "metformin",
|
| 35 |
+
"category": "medication",
|
| 36 |
+
"vietnamese": "metformin",
|
| 37 |
+
"aliases": ["met for min", "mét-pho-min"]
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"term": "hypertension",
|
| 41 |
+
"category": "condition",
|
| 42 |
+
"vietnamese": "tăng huyết áp",
|
| 43 |
+
"aliases": ["cao huyết áp", "high blood pressure"]
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"term": "diabetes mellitus",
|
| 47 |
+
"category": "condition",
|
| 48 |
+
"vietnamese": "đái tháo đường",
|
| 49 |
+
"aliases": ["tiểu đường", "diabetes"]
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"term": "COPD",
|
| 53 |
+
"category": "condition",
|
| 54 |
+
"vietnamese": "bệnh phổi tắc nghẽn mạn tính",
|
| 55 |
+
"aliases": ["copd", "bệnh phổi tắc nghẽn"]
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"term": "asthma",
|
| 59 |
+
"category": "condition",
|
| 60 |
+
"vietnamese": "hen phế quản",
|
| 61 |
+
"aliases": ["hen suyễn"]
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"term": "BMI",
|
| 65 |
+
"category": "biometric",
|
| 66 |
+
"vietnamese": "chỉ số khối cơ thể",
|
| 67 |
+
"aliases": ["body mass index"]
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
"term": "creatinine",
|
| 71 |
+
"category": "biomarker",
|
| 72 |
+
"vietnamese": "creatinin",
|
| 73 |
+
"aliases": ["creatinin"]
|
| 74 |
+
},
|
| 75 |
+
{
|
| 76 |
+
"term": "eGFR",
|
| 77 |
+
"category": "biomarker",
|
| 78 |
+
"vietnamese": "mức lọc cầu thận ước tính",
|
| 79 |
+
"aliases": ["egfr", "gfr"]
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"term": "CRP",
|
| 83 |
+
"category": "biomarker",
|
| 84 |
+
"vietnamese": "protein phản ứng C",
|
| 85 |
+
"aliases": ["c reactive protein"]
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"term": "WBC",
|
| 89 |
+
"category": "biomarker",
|
| 90 |
+
"vietnamese": "bạch cầu",
|
| 91 |
+
"aliases": ["white blood cell", "leukocyte"]
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"term": "hemoglobin",
|
| 95 |
+
"category": "biomarker",
|
| 96 |
+
"vietnamese": "huyết sắc tố",
|
| 97 |
+
"aliases": ["hb"]
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"term": "platelet",
|
| 101 |
+
"category": "biomarker",
|
| 102 |
+
"vietnamese": "tiểu cầu",
|
| 103 |
+
"aliases": ["plt"]
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"term": "sodium",
|
| 107 |
+
"category": "biomarker",
|
| 108 |
+
"vietnamese": "natri",
|
| 109 |
+
"aliases": ["na", "na+"]
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"term": "potassium",
|
| 113 |
+
"category": "biomarker",
|
| 114 |
+
"vietnamese": "kali",
|
| 115 |
+
"aliases": ["k", "k+"]
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"term": "ALT",
|
| 119 |
+
"category": "biomarker",
|
| 120 |
+
"vietnamese": "men gan ALT",
|
| 121 |
+
"aliases": ["sgpt"]
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"term": "AST",
|
| 125 |
+
"category": "biomarker",
|
| 126 |
+
"vietnamese": "men gan AST",
|
| 127 |
+
"aliases": ["sgot"]
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"term": "ultrasound",
|
| 131 |
+
"category": "test",
|
| 132 |
+
"vietnamese": "siêu âm",
|
| 133 |
+
"aliases": ["sonography"]
|
| 134 |
+
},
|
| 135 |
+
{
|
| 136 |
+
"term": "X-ray",
|
| 137 |
+
"category": "test",
|
| 138 |
+
"vietnamese": "x-quang",
|
| 139 |
+
"aliases": ["xray", "x quang"]
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"term": "CT",
|
| 143 |
+
"category": "test",
|
| 144 |
+
"vietnamese": "chụp cắt lớp vi tính",
|
| 145 |
+
"aliases": ["ct scan", "computed tomography"]
|
| 146 |
+
},
|
| 147 |
+
{
|
| 148 |
+
"term": "MRI",
|
| 149 |
+
"category": "test",
|
| 150 |
+
"vietnamese": "chụp cộng hưởng từ",
|
| 151 |
+
"aliases": ["magnetic resonance imaging"]
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
"term": "pneumonia",
|
| 155 |
+
"category": "condition",
|
| 156 |
+
"vietnamese": "viêm phổi",
|
| 157 |
+
"aliases": ["lung infection"]
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"term": "tachycardia",
|
| 161 |
+
"category": "finding",
|
| 162 |
+
"vietnamese": "nhịp tim nhanh",
|
| 163 |
+
"aliases": ["tim nhanh"]
|
| 164 |
+
},
|
| 165 |
+
{
|
| 166 |
+
"term": "bradycardia",
|
| 167 |
+
"category": "finding",
|
| 168 |
+
"vietnamese": "nhịp tim chậm",
|
| 169 |
+
"aliases": ["tim chậm"]
|
| 170 |
+
},
|
| 171 |
+
{
|
| 172 |
+
"term": "systolic",
|
| 173 |
+
"category": "vital_sign",
|
| 174 |
+
"vietnamese": "huyết áp tâm thu",
|
| 175 |
+
"aliases": ["tâm thu"]
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"term": "diastolic",
|
| 179 |
+
"category": "vital_sign",
|
| 180 |
+
"vietnamese": "huyết áp tâm trương",
|
| 181 |
+
"aliases": ["tâm trương"]
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"term": "testosterone",
|
| 185 |
+
"category": "hormone",
|
| 186 |
+
"vietnamese": "testosterone",
|
| 187 |
+
"aliases": ["testosteron"]
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"term": "dihydrotestosterone",
|
| 191 |
+
"category": "hormone",
|
| 192 |
+
"vietnamese": "dihydrotestosterone",
|
| 193 |
+
"aliases": ["dht"]
|
| 194 |
+
},
|
| 195 |
+
{
|
| 196 |
+
"term": "Bartholin",
|
| 197 |
+
"category": "anatomy",
|
| 198 |
+
"vietnamese": "tuyến Bartholin",
|
| 199 |
+
"aliases": ["bartholins"]
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"term": "methionine",
|
| 203 |
+
"category": "biochemistry",
|
| 204 |
+
"vietnamese": "methionin",
|
| 205 |
+
"aliases": ["methionin"]
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"term": "glutathione",
|
| 209 |
+
"category": "biochemistry",
|
| 210 |
+
"vietnamese": "glutathion",
|
| 211 |
+
"aliases": ["glutathion"]
|
| 212 |
+
}
|
| 213 |
+
]
|
| 214 |
+
}
|
| 215 |
+
|
docs/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Architecture
|
| 2 |
+
|
| 3 |
+
CarePath is one FastAPI deployment with two separately named clinical workflows.
|
| 4 |
+
The combined entrypoint is `scribe/carepath/main.py`; it owns the Scribe API,
|
| 5 |
+
imports the Interpreter routers from `interpreter/app`, and mounts both built Vite
|
| 6 |
+
frontends after API routes.
|
| 7 |
+
|
| 8 |
+
## Product Boundaries
|
| 9 |
+
|
| 10 |
+
| Workflow | Backend boundary | Browser surface |
|
| 11 |
+
| --- | --- | --- |
|
| 12 |
+
| Ghi chép bệnh án AI | `scribe/carepath`, `/api/v1/*` | `scribe/frontend/` at `/`, including `/ghi-chep-lam-sang/` |
|
| 13 |
+
| Phiên dịch khám bệnh trực tiếp | `interpreter/app`, `/api/*` and `/ws/*` | `interpreter/frontend/` at `/phien-dich-y-khoa/` |
|
| 14 |
+
|
| 15 |
+
`/console/` redirects to the canonical interpreter path for compatibility. The
|
| 16 |
+
two API namespaces intentionally do not overlap.
|
| 17 |
+
|
| 18 |
+
`scribe/training/` is exclusively the Scribe's offline DARAG/GEC training and quality
|
| 19 |
+
track. It does not train or serve the Interpreter. `interpreter/eval/` is a
|
| 20 |
+
separate deterministic translation-safety harness that stays with the
|
| 21 |
+
Interpreter.
|
| 22 |
+
|
| 23 |
+
## Boundaries That Must Stay Explicit
|
| 24 |
+
|
| 25 |
+
- Scribe output is a clinician-reviewed draft; it does not replace clinical
|
| 26 |
+
judgment.
|
| 27 |
+
- Interpreter output is translation only. High or critical risk stays blocked
|
| 28 |
+
from patient display and TTS until clinician confirmation.
|
| 29 |
+
- Interpreter audio is memory-only: no raw-audio persistence, no microphone
|
| 30 |
+
capture before consent, and failures fail closed.
|
| 31 |
+
- Risk lexicons and glossary seeds are editable JSON/CSV data, not code.
|
| 32 |
+
- Providers, environment variables, HTTP/WebSocket payloads, uploaded files,
|
| 33 |
+
and database rows are trust boundaries and must be parsed before use.
|
| 34 |
+
|
| 35 |
+
## Delivery and Proof
|
| 36 |
+
|
| 37 |
+
The shared process serves built static assets in production; Vite dev servers
|
| 38 |
+
remain the development path. Existing Python, eval, frontend, browser, build,
|
| 39 |
+
and Lighthouse commands are the validation ladder. Do not add a second service,
|
| 40 |
+
state framework, or test runner unless a selected story proves the need.
|
docs/CONTEXT_RULES.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Context Rules
|
| 2 |
+
|
| 3 |
+
Read enough to preserve the selected contract, not the entire repository.
|
| 4 |
+
|
| 5 |
+
| Lane | Required context before implementation |
|
| 6 |
+
| --- | --- |
|
| 7 |
+
| Tiny | `AGENTS.md`, `docs/FEATURE_INTAKE.md`, matrix query, and exact files to change |
|
| 8 |
+
| Normal | Tiny context plus relevant product contract, story, validation command, and architecture when a boundary changes |
|
| 9 |
+
| High-risk | Normal context plus relevant decisions, high-risk template, safety/eval fixtures, and every affected module boundary |
|
| 10 |
+
|
| 11 |
+
Always read the current task's validation evidence before recording its trace.
|
| 12 |
+
For product or UX work, read the appropriate `docs/product/` contract; for UX
|
| 13 |
+
flows also read `docs/ux-redesign-carepath.md`. For risk, consent, TTS, audio,
|
| 14 |
+
or provider work, read `AGENTS.md` safety invariants and the affected tests and
|
| 15 |
+
fixtures before editing.
|
| 16 |
+
|
| 17 |
+
Stop reading unrelated history once the lane, contract, affected files, and
|
| 18 |
+
proof path are clear. Search targeted paths with `rg` rather than loading broad
|
| 19 |
+
archives.
|
docs/FEATURE_INTAKE.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Feature Intake
|
| 2 |
+
|
| 3 |
+
Every implementation request is classified before code changes. Record the
|
| 4 |
+
classification with `.\scripts\bin\harness-cli.exe intake`.
|
| 5 |
+
|
| 6 |
+
## Input Types
|
| 7 |
+
|
| 8 |
+
| Type | Use when | Typical artifact |
|
| 9 |
+
| --- | --- | --- |
|
| 10 |
+
| Change request | Bounded behavior, bug, copy, or UX refinement | Direct patch or story |
|
| 11 |
+
| New initiative | A new product area spanning multiple stories | Initiative note and stories |
|
| 12 |
+
| Maintenance request | Dependency, performance, delivery, or operational work | Story or decision |
|
| 13 |
+
| Harness improvement | Process, proof, template, or instruction work | Harness docs and trace |
|
| 14 |
+
|
| 15 |
+
## Lanes
|
| 16 |
+
|
| 17 |
+
### Tiny
|
| 18 |
+
|
| 19 |
+
Use for narrow docs, copy, or isolated maintenance with no safety, API, data,
|
| 20 |
+
or multi-module impact. Record intake, patch directly, and run the relevant
|
| 21 |
+
quick proof. A UX or product-flow change still updates
|
| 22 |
+
`docs/ux-redesign-carepath.md` first.
|
| 23 |
+
|
| 24 |
+
### Normal
|
| 25 |
+
|
| 26 |
+
Use for a bounded change to one product surface or shared implementation. Create
|
| 27 |
+
or update one story packet, define the validation, update proof flags, and
|
| 28 |
+
record a standard trace.
|
| 29 |
+
|
| 30 |
+
### High-Risk
|
| 31 |
+
|
| 32 |
+
Use `docs/templates/high-risk-story/` and record a durable decision when the
|
| 33 |
+
work changes safety behavior, architecture, data ownership, public API shape,
|
| 34 |
+
or validation policy. Ask the user before implementing when the direction is
|
| 35 |
+
ambiguous.
|
| 36 |
+
|
| 37 |
+
## CarePath Hard Gates
|
| 38 |
+
|
| 39 |
+
The following are always high-risk:
|
| 40 |
+
|
| 41 |
+
- Consent, microphone capture, raw-audio handling, retention, or privacy.
|
| 42 |
+
- Interpreter risk classification, confidence display, patient display, TTS,
|
| 43 |
+
escalation, or fail-closed behavior.
|
| 44 |
+
- Medical advice boundaries, provider behavior, credentials, or external
|
| 45 |
+
clinical data.
|
| 46 |
+
- Public API or WebSocket contract changes, database migrations, or changes
|
| 47 |
+
that span the Scribe and Interpreter modules.
|
| 48 |
+
- Removing or weakening existing safety or validation requirements.
|
| 49 |
+
|
| 50 |
+
Use the existing test and eval fixtures whenever a risk-engine rule changes;
|
| 51 |
+
zero misses on critical fixtures remains a hard gate.
|
docs/GLOSSARY.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Glossary
|
| 2 |
+
|
| 3 |
+
## Agent
|
| 4 |
+
|
| 5 |
+
An AI coding collaborator operating inside the repository.
|
| 6 |
+
|
| 7 |
+
## Harness
|
| 8 |
+
|
| 9 |
+
The repo-level operating system that tells humans and agents how to turn intent
|
| 10 |
+
into safe product changes.
|
| 11 |
+
|
| 12 |
+
## Product Contract
|
| 13 |
+
|
| 14 |
+
The current expected behavior of the product. Product docs plus executable tests
|
| 15 |
+
become the living contract once implementation exists.
|
| 16 |
+
|
| 17 |
+
## Story Packet
|
| 18 |
+
|
| 19 |
+
A story-sized work file or folder that describes the product contract, affected
|
| 20 |
+
docs, design notes, and validation expectations for a feature.
|
| 21 |
+
|
| 22 |
+
## Feature Intake
|
| 23 |
+
|
| 24 |
+
The classification step that turns a prompt into tiny, normal, or high-risk
|
| 25 |
+
work before implementation begins.
|
| 26 |
+
|
| 27 |
+
## Component Taxonomy
|
| 28 |
+
|
| 29 |
+
A map from Harness files and capabilities to the responsibilities they serve,
|
| 30 |
+
used to evaluate coverage, attribute failures, and identify missing harness
|
| 31 |
+
capabilities.
|
| 32 |
+
|
| 33 |
+
## Maturity Level
|
| 34 |
+
|
| 35 |
+
A verifiable stage in Harness capability, from H0 bare environment through H5
|
| 36 |
+
self-improving harness. Each level has required files, criteria, and benchmark
|
| 37 |
+
indicators.
|
| 38 |
+
|
| 39 |
+
## Trace Quality Tier
|
| 40 |
+
|
| 41 |
+
The expected depth of a task trace: minimal for tiny work, standard for normal
|
| 42 |
+
work, and detailed for high-risk work.
|
| 43 |
+
|
| 44 |
+
## Verification Gate
|
| 45 |
+
|
| 46 |
+
An advisory Harness check that runs or inspects mechanical proof before a task
|
| 47 |
+
is closed. In Phase 4, `story verify <id>` executes a story's `verify_command`,
|
| 48 |
+
`story verify-all` runs all configured story proof commands, and
|
| 49 |
+
`trace --story <id>` warns when that story's verification has not passed.
|
| 50 |
+
|
| 51 |
+
## Tool Registry
|
| 52 |
+
|
| 53 |
+
The compiled and registered tool manifest exposed by
|
| 54 |
+
`scripts/bin/harness-cli query tools`. It lets agents discover available
|
| 55 |
+
commands, arguments, responsibilities, and custom project tools.
|
| 56 |
+
|
| 57 |
+
## Intervention
|
| 58 |
+
|
| 59 |
+
A durable record of human, reviewer, CI, or agent feedback that corrected,
|
| 60 |
+
overrode, escalated, or approved work. Interventions are stored separately from
|
| 61 |
+
traces and feed improvement proposals.
|
| 62 |
+
|
| 63 |
+
## Context Score
|
| 64 |
+
|
| 65 |
+
The advisory result from `scripts/bin/harness-cli score-context <trace-id>`.
|
| 66 |
+
It compares a trace's recorded `files_read` against compiled context rules and
|
| 67 |
+
retrieval triggers.
|
| 68 |
+
|
| 69 |
+
## Entropy Score
|
| 70 |
+
|
| 71 |
+
The drift score printed by `scripts/bin/harness-cli audit`. Lower is better.
|
| 72 |
+
It counts stale or incomplete durable records such as orphaned stories,
|
| 73 |
+
unverified proof commands, missing backlog outcomes, and broken registered
|
| 74 |
+
tools.
|
| 75 |
+
|
| 76 |
+
## Improvement Proposal
|
| 77 |
+
|
| 78 |
+
A structured recommendation generated by `scripts/bin/harness-cli propose` from
|
| 79 |
+
repeated friction, intervention patterns, and audit findings. Proposals are
|
| 80 |
+
advisory unless committed to the backlog with `--commit`.
|
| 81 |
+
|
| 82 |
+
## Context Phase
|
| 83 |
+
|
| 84 |
+
A phase of an agent task that changes what context should be read, such as
|
| 85 |
+
intake, planning, implementation, validation, or trace recording.
|
| 86 |
+
|
| 87 |
+
## Retrieval Trigger
|
| 88 |
+
|
| 89 |
+
A condition that tells an agent to fetch additional context, such as touching a
|
| 90 |
+
database schema, changing a public contract, or discovering missing validation.
|
| 91 |
+
|
| 92 |
+
## Harness Delta
|
| 93 |
+
|
| 94 |
+
A documentation, template, validation, backlog, or decision update that makes
|
| 95 |
+
future agent work safer or easier.
|
| 96 |
+
|
| 97 |
+
## Backlog Outcome Loop
|
| 98 |
+
|
| 99 |
+
The feedback workflow for Harness improvements: record predicted impact when a
|
| 100 |
+
backlog item is created, then record actual measured outcome when the item is
|
| 101 |
+
closed so future agents can compare expectation with result.
|
| 102 |
+
|
| 103 |
+
## Durable Layer
|
| 104 |
+
|
| 105 |
+
The SQLite database and CLI (`scripts/bin/harness-cli`) that stores operational records
|
| 106 |
+
(intakes, stories, decisions, backlog items, traces) as structured, queryable
|
| 107 |
+
data. Policy docs describe how to work; the durable layer stores what happened.
|
| 108 |
+
|
| 109 |
+
## Product Delta
|
| 110 |
+
|
| 111 |
+
A product-facing change such as code, tests, API shape, data model, or product
|
| 112 |
+
documentation.
|
| 113 |
+
|
| 114 |
+
## Trace
|
| 115 |
+
|
| 116 |
+
A structured record of what an agent did during a task: actions taken, files
|
| 117 |
+
read, files changed, decisions made, errors encountered, outcome, and any
|
| 118 |
+
harness friction discovered.
|
| 119 |
+
|
| 120 |
+
## Tool Registry
|
| 121 |
+
|
| 122 |
+
The compiled and user-registered tool manifest exposed by
|
| 123 |
+
`scripts/bin/harness-cli query tools` and documented in `docs/TOOL_REGISTRY.md`.
|
| 124 |
+
|
| 125 |
+
## Intervention
|
| 126 |
+
|
| 127 |
+
A durable record of a human, reviewer, CI, or agent correction, override,
|
| 128 |
+
escalation, or approval that is separate from the normal task trace.
|
| 129 |
+
|
| 130 |
+
## Context Score
|
| 131 |
+
|
| 132 |
+
The advisory result from `scripts/bin/harness-cli score-context <trace-id>`,
|
| 133 |
+
which compares a trace's recorded reads against compiled context rules.
|
| 134 |
+
|
| 135 |
+
## Entropy Score
|
| 136 |
+
|
| 137 |
+
The drift score from `scripts/bin/harness-cli audit`. Lower scores mean fewer
|
| 138 |
+
orphaned, stale, unverified, outcome-missing, or broken-tool records.
|
| 139 |
+
|
| 140 |
+
## Improvement Proposal
|
| 141 |
+
|
| 142 |
+
A structured proposal generated by `scripts/bin/harness-cli propose` from
|
| 143 |
+
repeated friction, interventions, and audit drift. Proposals can be committed as
|
| 144 |
+
backlog items with `--commit`.
|
docs/HARNESS.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Harness
|
| 2 |
+
|
| 3 |
+
CarePath uses Repository Harness to turn a request into safe, reviewable work.
|
| 4 |
+
The application is what clinicians use; the Harness is the durable operating
|
| 5 |
+
layer for humans and coding agents.
|
| 6 |
+
|
| 7 |
+
## Sources of Truth
|
| 8 |
+
|
| 9 |
+
Apply sources in this order:
|
| 10 |
+
|
| 11 |
+
1. Current user instruction and the safety, Vietnamese-first, and UX rules in
|
| 12 |
+
`AGENTS.md`.
|
| 13 |
+
2. The current contracts in `docs/product/`.
|
| 14 |
+
3. The selected story packet in `docs/stories/` and accepted decisions in
|
| 15 |
+
`docs/decisions/`.
|
| 16 |
+
4. Executable tests and the proof matrix.
|
| 17 |
+
5. `docs/history/` and research as background, unless a current contract
|
| 18 |
+
explicitly incorporates them.
|
| 19 |
+
|
| 20 |
+
No Harness document may weaken a CarePath safety invariant. If sources conflict,
|
| 21 |
+
pause and ask the user rather than choosing a less-safe interpretation.
|
| 22 |
+
|
| 23 |
+
## Durable Layer
|
| 24 |
+
|
| 25 |
+
`scripts/bin/harness-cli.exe` manages the local, ignored `harness.db` using the
|
| 26 |
+
versioned migrations in `scripts/schema/`. Initialize it once per clone:
|
| 27 |
+
|
| 28 |
+
```powershell
|
| 29 |
+
.\scripts\bin\harness-cli.exe init
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
The database records intake classifications, story proof, decisions, traces,
|
| 33 |
+
and Harness friction. Markdown remains the reviewable product record; the
|
| 34 |
+
database records what happened locally.
|
| 35 |
+
|
| 36 |
+
## Task Loop
|
| 37 |
+
|
| 38 |
+
1. Read `AGENTS.md`, this file, `docs/FEATURE_INTAKE.md`, and the current
|
| 39 |
+
matrix.
|
| 40 |
+
2. Classify and record the request with `harness-cli.exe intake`.
|
| 41 |
+
3. Read only the affected product contract, stories, decisions, and code.
|
| 42 |
+
4. Define the proof before implementation.
|
| 43 |
+
5. Implement only the selected lane.
|
| 44 |
+
6. Update the product contract, story, and matrix when the change affects them.
|
| 45 |
+
7. Run the applicable existing checks and record their actual result.
|
| 46 |
+
8. Record a trace. Capture repeated missing context or proof as Harness
|
| 47 |
+
friction or a backlog item.
|
| 48 |
+
|
| 49 |
+
For UX or product-flow work, `AGENTS.md` additionally requires an updated
|
| 50 |
+
`docs/ux-redesign-carepath.md` before implementation. That requirement applies
|
| 51 |
+
even when intake classifies the edit as tiny.
|
| 52 |
+
|
| 53 |
+
## Tool Registry
|
| 54 |
+
|
| 55 |
+
The registry is optional. Before relying on an external tool, query it by
|
| 56 |
+
capability. If no present provider is registered, skip that optional step and
|
| 57 |
+
record the limitation only when it affects proof. Do not add a dependency or
|
| 58 |
+
tool registration merely to satisfy the Harness.
|
| 59 |
+
|
| 60 |
+
## Done
|
| 61 |
+
|
| 62 |
+
A task is done when its requested change is complete, relevant contracts and
|
| 63 |
+
proof records are current, the applicable checks have real results, and the
|
| 64 |
+
trace says what happened. A failed unrelated existing check is recorded as
|
| 65 |
+
failed proof; repairing it requires separate scope.
|
docs/HARNESS_AUDIT.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Harness Audit
|
| 2 |
+
|
| 3 |
+
`scripts/bin/harness-cli audit` detects drift in durable Harness state and
|
| 4 |
+
prints an entropy score. Lower is better.
|
| 5 |
+
|
| 6 |
+
## Checks
|
| 7 |
+
|
| 8 |
+
| Category | Meaning | Weight |
|
| 9 |
+
| --- | --- | --- |
|
| 10 |
+
| Orphaned stories | Planned or in-progress stories with no linked trace. | 10 |
|
| 11 |
+
| Unverified stories | Active or implemented stories with `verify_command` but no recorded verification result. Retired stories are historical records and are not counted. | 5 |
|
| 12 |
+
| Unverified decisions | Decisions with `verify_command` but no recorded verification result. | 5 |
|
| 13 |
+
| Open backlog without outcomes | Implemented backlog items with predicted impact but no actual outcome. | 2 |
|
| 14 |
+
| Stale stories | Unimplemented stories whose latest linked trace is more than 30 days old. | 3 |
|
| 15 |
+
| Broken tools | Registered tools whose command is not found on disk or `PATH`. | 8 |
|
| 16 |
+
|
| 17 |
+
## Score
|
| 18 |
+
|
| 19 |
+
```text
|
| 20 |
+
score = orphaned_stories * 10
|
| 21 |
+
+ unverified_stories * 5
|
| 22 |
+
+ unverified_decisions * 5
|
| 23 |
+
+ backlog_without_outcomes * 2
|
| 24 |
+
+ stale_stories * 3
|
| 25 |
+
+ broken_tools * 8
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
The score is capped at 100.
|
| 29 |
+
|
| 30 |
+
| Range | Interpretation |
|
| 31 |
+
| --- | --- |
|
| 32 |
+
| 0 | Perfect: records are traced, verified, and healthy. |
|
| 33 |
+
| 1-25 | Healthy: minor housekeeping remains. |
|
| 34 |
+
| 26-50 | Attention needed: drift is accumulating. |
|
| 35 |
+
| 51-100 | Action required: stale state undermines Harness value. |
|
| 36 |
+
|
| 37 |
+
Audit findings feed `scripts/bin/harness-cli propose`, which can turn repeated
|
| 38 |
+
drift into proposed backlog items.
|
docs/HARNESS_BACKLOG.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Harness Backlog
|
| 2 |
+
|
| 3 |
+
Use this file when an agent discovers a missing harness capability but should
|
| 4 |
+
not change the operating model immediately.
|
| 5 |
+
|
| 6 |
+
## Template
|
| 7 |
+
|
| 8 |
+
```md
|
| 9 |
+
## Missing Harness Capability
|
| 10 |
+
|
| 11 |
+
### Title
|
| 12 |
+
|
| 13 |
+
Short name.
|
| 14 |
+
|
| 15 |
+
### Discovered While
|
| 16 |
+
|
| 17 |
+
Task or story that exposed the gap.
|
| 18 |
+
|
| 19 |
+
### Current Pain
|
| 20 |
+
|
| 21 |
+
What was hard, repeated, ambiguous, or unsafe?
|
| 22 |
+
|
| 23 |
+
### Suggested Improvement
|
| 24 |
+
|
| 25 |
+
What should be added or changed?
|
| 26 |
+
|
| 27 |
+
### Risk
|
| 28 |
+
|
| 29 |
+
Tiny, normal, or high-risk.
|
| 30 |
+
|
| 31 |
+
CLI value: `--risk tiny`, `--risk normal`, or `--risk high-risk`.
|
| 32 |
+
|
| 33 |
+
### Status
|
| 34 |
+
|
| 35 |
+
proposed | accepted | implemented | rejected
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
## Items
|
| 39 |
+
|
| 40 |
+
## Future Interpreter Risk-Lexicon Consolidation
|
| 41 |
+
|
| 42 |
+
### Discovered While
|
| 43 |
+
|
| 44 |
+
CP-RES-006 term-store consolidation.
|
| 45 |
+
|
| 46 |
+
### Current Pain
|
| 47 |
+
|
| 48 |
+
The Interpreter safety lexicons are also clinician-editable data, but they
|
| 49 |
+
govern deterministic risk classification rather than medical-term retrieval.
|
| 50 |
+
|
| 51 |
+
### Suggested Improvement
|
| 52 |
+
|
| 53 |
+
Evaluate a separate, clinician-approved consolidation only with a safety-fixture
|
| 54 |
+
and evaluation policy change. Do not merge them into the general term source.
|
| 55 |
+
|
| 56 |
+
### Risk
|
| 57 |
+
|
| 58 |
+
high-risk.
|
| 59 |
+
|
| 60 |
+
### Status
|
| 61 |
+
|
| 62 |
+
proposed
|
docs/HARNESS_COMPONENTS.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Harness Components
|
| 2 |
+
|
| 3 |
+
This taxonomy maps the current `repository-harness` repository to two
|
| 4 |
+
component frameworks used by Phase 2 and updated by Phase 3 active
|
| 5 |
+
observability work:
|
| 6 |
+
|
| 7 |
+
- Runtime Substrate responsibilities: the 11 responsibility areas the harness
|
| 8 |
+
should cover.
|
| 9 |
+
- NexAU decomposition: the seven implementation surfaces that influence agent
|
| 10 |
+
behavior.
|
| 11 |
+
|
| 12 |
+
Status values:
|
| 13 |
+
|
| 14 |
+
- **Covered**: the repository has an explicit file, command, or record for this
|
| 15 |
+
responsibility.
|
| 16 |
+
- **Partial**: the repository has some support, but the support is incomplete,
|
| 17 |
+
manual, or not yet measured.
|
| 18 |
+
- **Missing**: no meaningful support exists yet.
|
| 19 |
+
|
| 20 |
+
## Responsibility Map
|
| 21 |
+
|
| 22 |
+
| # | Responsibility | Status | Harness Files | Evidence | Gap |
|
| 23 |
+
| --- | --- | --- | --- | --- | --- |
|
| 24 |
+
| 1 | Task specification | Covered | `AGENTS.md`, `docs/FEATURE_INTAKE.md`, `docs/templates/story.md`, `docs/templates/spec-intake.md`, `docs/templates/high-risk-story/*`, `docs/stories/*`, `intake` table, `story` table | Requests are classified by type and lane before implementation; normal and high-risk work have templates and durable story rows. | Keep story packets synchronized with future product docs. |
|
| 25 |
+
| 2 | Context selection | Covered | `AGENTS.md`, `docs/CONTEXT_RULES.md`, `docs/ARCHITECTURE.md`, `docs/decisions/*`, `docs/product/README.md`, `scripts/bin/harness-cli score-context` | Phase 2 adds phase-by-lane context rules and retrieval triggers; Phase 5 adds context scoring against recorded trace reads. | Future automation could enforce context selection instead of only measuring it. |
|
| 26 |
+
| 3 | Tool access | Covered | `scripts/bin/harness-cli`, `docs/TOOL_REGISTRY.md`, `tool` table, `crates/harness-cli/*`, `scripts/install-harness.sh`, `scripts/build-harness-cli-release.sh` | The Harness CLI exposes operational commands and a machine-readable tool manifest through `query tools`; external tools can be registered and removed. | Permission profiles and usage analytics remain future work. |
|
| 27 |
+
| 4 | Project memory | Covered | `docs/HARNESS.md`, `docs/decisions/*`, `docs/GLOSSARY.md`, `docs/HARNESS_BACKLOG.md`, `docs/stories/*`, `harness.db`, `decision`, `backlog`, and `trace` tables | Decisions, backlog, stories, and traces preserve durable knowledge across tasks. | Future work should add staleness checks and summarize old traces. |
|
| 28 |
+
| 5 | Task state | Covered | `scripts/bin/harness-cli query matrix`, `docs/TEST_MATRIX.md`, `intake` table, `story` table, `trace` table | Durable records track intake, story status, proof columns, and task traces. | Add lifecycle checks so in-progress stories cannot be forgotten. |
|
| 29 |
+
| 6 | Observability | Partial | `docs/TRACE_SPEC.md`, `trace` table, `scripts/bin/harness-cli trace`, `scripts/bin/harness-cli score-trace`, `scripts/bin/harness-cli query traces`, `scripts/bin/harness-cli query friction`, `docs/HARNESS_MATURITY.md` | Traces are auto-scored when recorded, can be rescored by command, and can be reviewed with friction context. | No dashboard or benchmark ingestion exists in this repo. |
|
| 30 |
+
| 7 | Failure attribution | Partial | `docs/HARNESS_COMPONENTS.md`, `docs/TRACE_SPEC.md`, `trace.errors`, `trace.harness_friction`, `docs/HARNESS_BACKLOG.md`, `backlog` table, `scripts/bin/harness-cli query friction` | Failures can be tied to files, components, friction, backlog proposals, and linked intake lane/type context. | No automated attribution from benchmark failures to harness components exists yet. |
|
| 31 |
+
| 8 | Verification | Covered | `docs/TEST_MATRIX.md`, `scripts/bin/harness-cli query matrix`, `scripts/bin/harness-cli story verify`, `scripts/bin/harness-cli story verify-all`, `scripts/bin/harness-cli trace`, `scripts/bin/harness-cli score-trace`, `story.verify_command`, `story.last_verified_result`, `.github/workflows/harness-cli-release.yml`, `docs/templates/validation-report.md` | Stories can store and run mechanical proof commands individually or in batch, traces warn when linked story verification has not passed, trace quality can be checked mechanically, and release workflow verifies Rust CLI releases. | Benchmark ingestion remains future work. |
|
| 32 |
+
| 9 | Permissions | Partial | `AGENTS.md`, `docs/HARNESS.md`, `docs/FEATURE_INTAKE.md`, `docs/ARCHITECTURE.md`, installer conflict handling in `scripts/install-harness.sh` | Policy describes when agents may update docs and when to ask before architecture or workflow changes. | Permissions are instruction-level only; no enforced policy layer or command allowlist exists. |
|
| 33 |
+
| 10 | Entropy auditing | Covered | `docs/HARNESS_BACKLOG.md`, `docs/HARNESS_AUDIT.md`, `docs/IMPROVEMENT_PROTOCOL.md`, `backlog` table, `trace.harness_friction`, `scripts/bin/harness-cli audit`, `scripts/bin/harness-cli propose`, `docs/HARNESS_MATURITY.md` | Growth rule captures friction, audit detects drift and entropy score, backlog items compare predicted impact to actual outcome, and proposal generation can create reviewable backlog items. | Automated repair remains future work. |
|
| 34 |
+
| 11 | Intervention recording | Covered | `intervention` table, `scripts/bin/harness-cli intervention add`, `scripts/bin/harness-cli query interventions`, `trace` table, `docs/decisions/*`, `docs/stories/*`, `docs/HARNESS.md` | Human, reviewer, CI, and agent interventions are separate durable records and can be filtered by trace, story, or type. | Capture is still manual and advisory. |
|
| 35 |
+
|
| 36 |
+
## NexAU Cross-Reference
|
| 37 |
+
|
| 38 |
+
| Component | Harness Equivalent | Status | Notes |
|
| 39 |
+
| --- | --- | --- | --- |
|
| 40 |
+
| System prompts | `AGENTS.md` plus Harness policy docs | Covered | `AGENTS.md` is the stable shim; `docs/HARNESS.md`, `docs/FEATURE_INTAKE.md`, and `docs/CONTEXT_RULES.md` carry evolving operating instructions. |
|
| 41 |
+
| Tool descriptions | `docs/TOOL_REGISTRY.md`, `scripts/README.md`, `docs/HARNESS.md`, `docs/TRACE_SPEC.md`, CLI help from `crates/harness-cli/src/interface.rs`, `scripts/bin/harness-cli query tools` | Covered | Commands are documented in a standalone registry and exposed as compiled plus registered tool manifest entries. |
|
| 42 |
+
| Tool implementations | `scripts/bin/harness-cli`, `crates/harness-cli/*`, `scripts/schema/001-init.sql`, `scripts/schema/002-story-verify.sql` | Covered | The Rust CLI is the primary durable-layer implementation and stable repo-local entrypoint. |
|
| 43 |
+
| Middleware | installer safety logic, feature intake workflow | Partial | The installer and intake process mediate work, but there is no runtime middleware enforcing policies. |
|
| 44 |
+
| Skills | `docs/templates/*`, `docs/FEATURE_INTAKE.md`, `docs/CONTEXT_RULES.md`, `docs/TRACE_SPEC.md` | Partial | Reusable procedures exist as markdown, not executable or installable agent skills. |
|
| 45 |
+
| Sub-agents | None in this repository | Missing | No delegated specialist agents or sub-agent protocols exist. |
|
| 46 |
+
| Long-term memory | `harness.db`, `docs/decisions/*`, `docs/stories/*`, `docs/HARNESS_BACKLOG.md`, `docs/GLOSSARY.md` | Covered | Durable records and markdown decisions preserve task history and project vocabulary. |
|
| 47 |
+
|
| 48 |
+
## File Inventory
|
| 49 |
+
|
| 50 |
+
Every tracked project file plus the Phase 2 input file is mapped to at least
|
| 51 |
+
one Runtime Substrate responsibility.
|
| 52 |
+
|
| 53 |
+
| File | Primary Responsibility | Secondary Responsibilities |
|
| 54 |
+
| --- | --- | --- |
|
| 55 |
+
| `.gitignore` | Tool access | Task state |
|
| 56 |
+
| `AGENTS.md` | Context selection | Task specification, permissions |
|
| 57 |
+
| `README.md` | Task specification | Project memory |
|
| 58 |
+
| `CONTRIBUTING.md` | Intervention recording | Project memory |
|
| 59 |
+
| `Cargo.toml` | Tool access | Verification |
|
| 60 |
+
| `Cargo.lock` | Tool access | Verification |
|
| 61 |
+
| `PHASE2.md` | Task specification | Observability, context selection |
|
| 62 |
+
| `PHASE3.md` | Task specification | Observability, verification, entropy auditing |
|
| 63 |
+
| `PHASE4.md` | Task specification | Verification, observability, task state |
|
| 64 |
+
| `PHASE5.md` | Task specification | Verification, entropy auditing, intervention recording |
|
| 65 |
+
| `crates/harness-cli/Cargo.toml` | Tool access | Verification |
|
| 66 |
+
| `crates/harness-cli/src/main.rs` | Tool access | Tool implementation |
|
| 67 |
+
| `crates/harness-cli/src/domain.rs` | Tool access | Task state, verification |
|
| 68 |
+
| `crates/harness-cli/src/application.rs` | Tool access | Task state |
|
| 69 |
+
| `crates/harness-cli/src/infrastructure.rs` | Tool access | Project memory, task state, observability |
|
| 70 |
+
| `crates/harness-cli/src/interface.rs` | Tool access | Context selection, verification |
|
| 71 |
+
| `docs/ARCHITECTURE.md` | Permissions | Context selection, task specification |
|
| 72 |
+
| `docs/FEATURE_INTAKE.md` | Task specification | Permissions, context selection |
|
| 73 |
+
| `docs/GLOSSARY.md` | Project memory | Context selection |
|
| 74 |
+
| `docs/HARNESS.md` | Task specification | Project memory, task state, permissions |
|
| 75 |
+
| `docs/HARNESS_BACKLOG.md` | Entropy auditing | Project memory, failure attribution |
|
| 76 |
+
| `docs/HARNESS_COMPONENTS.md` | Failure attribution | Observability, entropy auditing |
|
| 77 |
+
| `docs/HARNESS_MATURITY.md` | Entropy auditing | Observability, verification |
|
| 78 |
+
| `docs/HARNESS_AUDIT.md` | Entropy auditing | Verification, task state |
|
| 79 |
+
| `docs/IMPROVEMENT_PROTOCOL.md` | Entropy auditing | Failure attribution, permissions |
|
| 80 |
+
| `docs/CONTEXT_RULES.md` | Context selection | Permissions, task specification |
|
| 81 |
+
| `docs/TRACE_SPEC.md` | Observability | Failure attribution, intervention recording |
|
| 82 |
+
| `docs/TOOL_REGISTRY.md` | Tool access | Context selection, verification |
|
| 83 |
+
| `docs/README.md` | Project memory | Context selection |
|
| 84 |
+
| `docs/TEST_MATRIX.md` | Verification | Task state |
|
| 85 |
+
| `docs/decisions/0001-harness-first-development.md` | Project memory | Permissions |
|
| 86 |
+
| `docs/decisions/0002-post-spec-product-lifecycle.md` | Project memory | Task specification |
|
| 87 |
+
| `docs/decisions/0003-generic-spec-intake-harness.md` | Project memory | Task specification |
|
| 88 |
+
| `docs/decisions/0004-sqlite-durable-layer.md` | Project memory | Observability, task state |
|
| 89 |
+
| `docs/decisions/0005-prebuilt-rust-harness-cli.md` | Project memory | Tool access |
|
| 90 |
+
| `docs/decisions/0006-phase-4-benchmark-triage.md` | Project memory | Verification |
|
| 91 |
+
| `docs/decisions/0007-improvement-proposal-rules.md` | Project memory | Entropy auditing, permissions |
|
| 92 |
+
| `docs/decisions/README.md` | Project memory | Context selection |
|
| 93 |
+
| `docs/demo/README.md` | Task specification | Project memory |
|
| 94 |
+
| `docs/product/README.md` | Task specification | Project memory |
|
| 95 |
+
| `docs/review-fixes-1d30bf62-to-main.md` | Intervention recording | Failure attribution, verification |
|
| 96 |
+
| `docs/stories/README.md` | Task specification | Project memory |
|
| 97 |
+
| `docs/stories/US-001-install-harness.md` | Task specification | Verification, intervention recording |
|
| 98 |
+
| `docs/stories/US-008-trace-quality-scoring.md` | Task specification | Observability, verification |
|
| 99 |
+
| `docs/stories/US-009-enriched-friction-query.md` | Task specification | Failure attribution, observability |
|
| 100 |
+
| `docs/stories/US-011-backlog-outcome-workflow.md` | Task specification | Entropy auditing, project memory |
|
| 101 |
+
| `docs/stories/US-012-story-verify-command-field.md` | Task specification | Verification |
|
| 102 |
+
| `docs/stories/US-015-story-verify-command.md` | Task specification | Verification |
|
| 103 |
+
| `docs/stories/US-016-auto-trace-scoring-on-write.md` | Task specification | Observability, verification |
|
| 104 |
+
| `docs/stories/US-017-pre-close-verification-gate.md` | Task specification | Verification, permissions |
|
| 105 |
+
| `docs/stories/US-018-phase4-cli-ux-hardening.md` | Task specification | Tool access, verification |
|
| 106 |
+
| `docs/stories/US-019-machine-readable-tool-registry.md` | Task specification | Tool access |
|
| 107 |
+
| `docs/stories/US-020-batch-story-verification.md` | Task specification | Verification |
|
| 108 |
+
| `docs/stories/US-021-intervention-recording-schema.md` | Task specification | Intervention recording |
|
| 109 |
+
| `docs/stories/US-022-context-rule-measurement.md` | Task specification | Context selection |
|
| 110 |
+
| `docs/stories/US-023-drift-detection-entropy-score.md` | Task specification | Entropy auditing |
|
| 111 |
+
| `docs/stories/US-024-improvement-proposal-pipeline.md` | Task specification | Entropy auditing, permissions |
|
| 112 |
+
| `docs/stories/backlog.md` | Task specification | Project memory |
|
| 113 |
+
| `docs/stories/epics/README.md` | Task specification | Project memory |
|
| 114 |
+
| `docs/stories/epics/E01-durable-layer/US-002-rust-harness-cli/overview.md` | Task specification | Project memory |
|
| 115 |
+
| `docs/stories/epics/E01-durable-layer/US-002-rust-harness-cli/design.md` | Task specification | Tool access, permissions |
|
| 116 |
+
| `docs/stories/epics/E01-durable-layer/US-002-rust-harness-cli/execplan.md` | Task specification | Verification, task state |
|
| 117 |
+
| `docs/stories/epics/E01-durable-layer/US-002-rust-harness-cli/validation.md` | Verification | Intervention recording |
|
| 118 |
+
| `docs/stories/epics/E02-phase-2-observability-taxonomy/phase-2-progress.md` | Task state | Intervention recording |
|
| 119 |
+
| `docs/stories/epics/E03-phase-5-evolution-infrastructure/phase-5-progress.md` | Task state | Verification, entropy auditing |
|
| 120 |
+
| `docs/templates/decision.md` | Project memory | Task specification |
|
| 121 |
+
| `docs/templates/spec-intake.md` | Task specification | Context selection |
|
| 122 |
+
| `docs/templates/story.md` | Task specification | Verification |
|
| 123 |
+
| `docs/templates/validation-report.md` | Verification | Intervention recording |
|
| 124 |
+
| `docs/templates/high-risk-story/overview.md` | Task specification | Context selection |
|
| 125 |
+
| `docs/templates/high-risk-story/design.md` | Task specification | Permissions |
|
| 126 |
+
| `docs/templates/high-risk-story/execplan.md` | Task state | Verification |
|
| 127 |
+
| `docs/templates/high-risk-story/validation.md` | Verification | Failure attribution |
|
| 128 |
+
| `scripts/README.md` | Tool access | Context selection |
|
| 129 |
+
| `scripts/bin/harness-cli` | Tool access | Task state, observability |
|
| 130 |
+
| `scripts/bin/harness-cli` | Tool access | Task state, observability |
|
| 131 |
+
| `scripts/install-harness.sh` | Tool access | Permissions |
|
| 132 |
+
| `scripts/build-harness-cli-release.sh` | Verification | Tool access |
|
| 133 |
+
| `scripts/schema/001-init.sql` | Task state | Observability, project memory |
|
| 134 |
+
| `scripts/schema/002-story-verify.sql` | Verification | Task state, project memory |
|
| 135 |
+
| `scripts/schema/003-tool-registry.sql` | Tool access | Project memory |
|
| 136 |
+
| `scripts/schema/004-intervention.sql` | Intervention recording | Failure attribution |
|
| 137 |
+
| `.github/ISSUE_TEMPLATE/agent-failure-case.md` | Failure attribution | Entropy auditing |
|
| 138 |
+
| `.github/ISSUE_TEMPLATE/pattern-request.md` | Entropy auditing | Intervention recording |
|
| 139 |
+
| `.github/ISSUE_TEMPLATE/real-world-example.md` | Project memory | Intervention recording |
|
| 140 |
+
| `.github/workflows/harness-cli-release.yml` | Verification | Tool access |
|
| 141 |
+
|
| 142 |
+
## Coverage Summary
|
| 143 |
+
|
| 144 |
+
- Covered: 8/11 responsibilities.
|
| 145 |
+
- Partial: 3/11 responsibilities.
|
| 146 |
+
- Missing: 0/11 responsibilities.
|
| 147 |
+
|
| 148 |
+
Covered responsibilities:
|
| 149 |
+
|
| 150 |
+
- Task specification.
|
| 151 |
+
- Context selection.
|
| 152 |
+
- Tool access.
|
| 153 |
+
- Project memory.
|
| 154 |
+
- Task state.
|
| 155 |
+
- Verification.
|
| 156 |
+
- Entropy auditing.
|
| 157 |
+
- Intervention recording.
|
| 158 |
+
Partial responsibilities:
|
| 159 |
+
|
| 160 |
+
- Observability.
|
| 161 |
+
- Failure attribution.
|
| 162 |
+
- Permissions.
|
| 163 |
+
|
| 164 |
+
Phase 5 converts tool access, entropy auditing, and intervention recording into
|
| 165 |
+
covered responsibilities with a registry, drift audit, proposal loop, and
|
| 166 |
+
intervention schema. Later phases should focus on benchmark ingestion,
|
| 167 |
+
component-level attribution, permission enforcement, and tool usage analytics.
|
docs/HARNESS_MATURITY.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Harness Maturity Ladder
|
| 2 |
+
|
| 3 |
+
This ladder defines how `repository-harness` should progress from static
|
| 4 |
+
agent instructions to measurable harness improvement.
|
| 5 |
+
|
| 6 |
+
The levels are intentionally verifiable. A level is achieved only when its
|
| 7 |
+
criteria can be inspected in repository files, durable Harness records, or
|
| 8 |
+
benchmark output.
|
| 9 |
+
|
| 10 |
+
## Levels
|
| 11 |
+
|
| 12 |
+
### H0 - Bare Environment
|
| 13 |
+
|
| 14 |
+
The model operates with no repository harness. It receives a prompt and may
|
| 15 |
+
produce a patch, but the repo does not tell it how to classify, validate, or
|
| 16 |
+
record work.
|
| 17 |
+
|
| 18 |
+
Criteria:
|
| 19 |
+
|
| 20 |
+
- No `AGENTS.md` Harness block exists.
|
| 21 |
+
- No feature intake policy exists.
|
| 22 |
+
- No story, decision, validation, or trace artifact exists.
|
| 23 |
+
|
| 24 |
+
Required files:
|
| 25 |
+
|
| 26 |
+
- None.
|
| 27 |
+
|
| 28 |
+
Benchmark indicators:
|
| 29 |
+
|
| 30 |
+
- Functional score is the only meaningful metric.
|
| 31 |
+
- Harness compliance: 0%.
|
| 32 |
+
- Trace quality: 0/3.
|
| 33 |
+
|
| 34 |
+
Current status:
|
| 35 |
+
|
| 36 |
+
- Passed. This repository is beyond H0.
|
| 37 |
+
|
| 38 |
+
Activated responsibilities:
|
| 39 |
+
|
| 40 |
+
- None.
|
| 41 |
+
|
| 42 |
+
### H1 - Scaffolding And Policy
|
| 43 |
+
|
| 44 |
+
The repository contains static operating instructions, templates, risk lanes,
|
| 45 |
+
and source-of-truth rules. Agents can follow a documented workflow, but durable
|
| 46 |
+
state may still be manual or incomplete.
|
| 47 |
+
|
| 48 |
+
Criteria:
|
| 49 |
+
|
| 50 |
+
- `AGENTS.md` points agents to the Harness operating docs.
|
| 51 |
+
- `docs/HARNESS.md`, `docs/FEATURE_INTAKE.md`, and `docs/ARCHITECTURE.md`
|
| 52 |
+
exist.
|
| 53 |
+
- Story, decision, and validation templates exist under `docs/templates/`.
|
| 54 |
+
- `docs/TEST_MATRIX.md` defines proof columns and status meanings.
|
| 55 |
+
|
| 56 |
+
Required files:
|
| 57 |
+
|
| 58 |
+
- `AGENTS.md`
|
| 59 |
+
- `docs/HARNESS.md`
|
| 60 |
+
- `docs/FEATURE_INTAKE.md`
|
| 61 |
+
- `docs/ARCHITECTURE.md`
|
| 62 |
+
- `docs/TEST_MATRIX.md`
|
| 63 |
+
- `docs/templates/story.md`
|
| 64 |
+
- `docs/templates/decision.md`
|
| 65 |
+
- `docs/templates/validation-report.md`
|
| 66 |
+
|
| 67 |
+
Benchmark indicators:
|
| 68 |
+
|
| 69 |
+
- Harness compliance: 20-40%.
|
| 70 |
+
- Lane accuracy improves when agents read the intake policy.
|
| 71 |
+
- Trace quality remains low unless traces are separately requested.
|
| 72 |
+
|
| 73 |
+
Current status:
|
| 74 |
+
|
| 75 |
+
- Achieved. H1 files exist and are used by current Harness instructions.
|
| 76 |
+
|
| 77 |
+
Activated responsibilities:
|
| 78 |
+
|
| 79 |
+
- Task specification.
|
| 80 |
+
- Permissions.
|
| 81 |
+
- Project memory.
|
| 82 |
+
- Verification.
|
| 83 |
+
|
| 84 |
+
### H2 - Durable State And Observability
|
| 85 |
+
|
| 86 |
+
The repository has structured operational records and explicit observation
|
| 87 |
+
rules. Agents can record what happened, connect work to stories, and write
|
| 88 |
+
traces with predictable depth.
|
| 89 |
+
|
| 90 |
+
Criteria:
|
| 91 |
+
|
| 92 |
+
- `scripts/bin/harness-cli` can record intake, story, decision, backlog, and trace
|
| 93 |
+
data in `harness.db`.
|
| 94 |
+
- `scripts/schema/001-init.sql` defines durable tables for intake, story,
|
| 95 |
+
decision, backlog, and trace records.
|
| 96 |
+
- `docs/HARNESS_COMPONENTS.md` maps files and responsibilities.
|
| 97 |
+
- `docs/HARNESS_MATURITY.md` defines H0-H5 with measurable criteria.
|
| 98 |
+
- `docs/TRACE_SPEC.md` defines trace fields, quality tiers, and friction
|
| 99 |
+
capture.
|
| 100 |
+
- `docs/CONTEXT_RULES.md` defines phase-by-lane context rules.
|
| 101 |
+
- `AGENTS.md` and `docs/HARNESS.md` reference the Phase 2 operating docs.
|
| 102 |
+
|
| 103 |
+
Required files:
|
| 104 |
+
|
| 105 |
+
- `scripts/bin/harness-cli`
|
| 106 |
+
- `scripts/schema/001-init.sql`
|
| 107 |
+
- `docs/HARNESS_COMPONENTS.md`
|
| 108 |
+
- `docs/HARNESS_MATURITY.md`
|
| 109 |
+
- `docs/TRACE_SPEC.md`
|
| 110 |
+
- `docs/CONTEXT_RULES.md`
|
| 111 |
+
|
| 112 |
+
Benchmark indicators:
|
| 113 |
+
|
| 114 |
+
- Harness compliance: 75-90%.
|
| 115 |
+
- Trace quality: at least 2.0/3 on normal-lane tasks.
|
| 116 |
+
- Lane accuracy: 6/6 on the current benchmark suite.
|
| 117 |
+
- Friction captured: at least 4/6 benchmark tasks when friction exists.
|
| 118 |
+
|
| 119 |
+
Current status:
|
| 120 |
+
|
| 121 |
+
- Achieved. Durable state exists, and the Phase 2 docs define the
|
| 122 |
+
observability and context specification. Phase 3 active scoring builds on
|
| 123 |
+
this layer.
|
| 124 |
+
|
| 125 |
+
Activated responsibilities:
|
| 126 |
+
|
| 127 |
+
- Task state.
|
| 128 |
+
- Observability.
|
| 129 |
+
- Failure attribution.
|
| 130 |
+
- Context selection.
|
| 131 |
+
- Entropy auditing.
|
| 132 |
+
|
| 133 |
+
### H3 - Active Observability And Evolution
|
| 134 |
+
|
| 135 |
+
The harness can evaluate its own operational data and turn repeated failures
|
| 136 |
+
into prioritized improvements.
|
| 137 |
+
|
| 138 |
+
Criteria:
|
| 139 |
+
|
| 140 |
+
- Trace quality can be scored by a repeatable command or benchmark step.
|
| 141 |
+
- Harness friction can be grouped by component from `docs/HARNESS_COMPONENTS.md`.
|
| 142 |
+
- Backlog items include predicted impact and actual outcome after completion.
|
| 143 |
+
- Benchmark comparison output identifies which harness responsibility moved or
|
| 144 |
+
regressed.
|
| 145 |
+
|
| 146 |
+
Required files:
|
| 147 |
+
|
| 148 |
+
- H2 files.
|
| 149 |
+
- A benchmark protocol or report that references maturity levels.
|
| 150 |
+
- A documented trace quality scoring method.
|
| 151 |
+
- A documented friction-to-backlog review loop.
|
| 152 |
+
|
| 153 |
+
Benchmark indicators:
|
| 154 |
+
|
| 155 |
+
- Harness compliance: 85-95%.
|
| 156 |
+
- Trace quality: 2.3-2.7/3.
|
| 157 |
+
- Friction captured and classified by component for most failed or awkward
|
| 158 |
+
tasks.
|
| 159 |
+
- Regressions include an attributed harness component.
|
| 160 |
+
|
| 161 |
+
Current status:
|
| 162 |
+
|
| 163 |
+
- Partially achieved by Phase 3. `scripts/bin/harness-cli score-trace` scores trace
|
| 164 |
+
quality against tier rules, `query friction` includes linked intake context,
|
| 165 |
+
the `trace` command now prints that score at write time, and the backlog
|
| 166 |
+
outcome loop documents predicted impact versus actual outcome. Full H3 still
|
| 167 |
+
requires benchmark comparison output that attributes moved or regressed
|
| 168 |
+
responsibilities.
|
| 169 |
+
|
| 170 |
+
Activated responsibilities:
|
| 171 |
+
|
| 172 |
+
- Observability.
|
| 173 |
+
- Failure attribution.
|
| 174 |
+
- Entropy auditing.
|
| 175 |
+
- Intervention recording.
|
| 176 |
+
|
| 177 |
+
### H4 - Automated Verification
|
| 178 |
+
|
| 179 |
+
The harness can run or orchestrate proof checks consistently and can reject or
|
| 180 |
+
flag incomplete work before the final response.
|
| 181 |
+
|
| 182 |
+
Criteria:
|
| 183 |
+
|
| 184 |
+
- A documented verification command or protocol runs the expected checks for a
|
| 185 |
+
selected story and lane.
|
| 186 |
+
- Stories can store and execute a `verify_command`.
|
| 187 |
+
- Trace recording warns when a linked story has a verification command that has
|
| 188 |
+
not passed.
|
| 189 |
+
- Missing validation evidence is surfaced before a task is marked implemented.
|
| 190 |
+
|
| 191 |
+
Required files:
|
| 192 |
+
|
| 193 |
+
- H3 files.
|
| 194 |
+
- A verification protocol or command reference.
|
| 195 |
+
- Validation report examples tied to story proof columns.
|
| 196 |
+
- Story verification command documentation.
|
| 197 |
+
|
| 198 |
+
Benchmark indicators:
|
| 199 |
+
|
| 200 |
+
- Functional score remains stable.
|
| 201 |
+
- Harness compliance: at least 90%.
|
| 202 |
+
- Fewer false "done" claims in benchmark review.
|
| 203 |
+
- Missing proof is detected before merge or final response.
|
| 204 |
+
|
| 205 |
+
Current status:
|
| 206 |
+
|
| 207 |
+
- Achieved by Phase 5. `scripts/bin/harness-cli story verify <id>` runs
|
| 208 |
+
story-level proof commands, records pass/fail state, `trace --story` warns
|
| 209 |
+
before close when verification has not passed, and
|
| 210 |
+
`scripts/bin/harness-cli story verify-all` runs all configured story proof
|
| 211 |
+
commands in one pass. Proof-column automation remains a future enhancement,
|
| 212 |
+
but H4's required automated verification gate is now present.
|
| 213 |
+
|
| 214 |
+
Activated responsibilities:
|
| 215 |
+
|
| 216 |
+
- Verification.
|
| 217 |
+
- Task state.
|
| 218 |
+
- Permissions.
|
| 219 |
+
- Intervention recording.
|
| 220 |
+
|
| 221 |
+
### H5 - Self-Improving Harness
|
| 222 |
+
|
| 223 |
+
The harness can use traces, benchmark results, and backlog outcomes to propose
|
| 224 |
+
or apply safe improvements to itself.
|
| 225 |
+
|
| 226 |
+
Criteria:
|
| 227 |
+
|
| 228 |
+
- Repeated friction patterns are summarized into proposed harness changes.
|
| 229 |
+
- Proposed changes include predicted impact, risk, validation plan, and rollback
|
| 230 |
+
criteria.
|
| 231 |
+
- Completed changes compare predicted impact with actual benchmark or trace
|
| 232 |
+
outcomes.
|
| 233 |
+
- High-risk harness changes pause for human confirmation before changing source
|
| 234 |
+
hierarchy, architecture direction, or validation requirements.
|
| 235 |
+
|
| 236 |
+
Required files:
|
| 237 |
+
|
| 238 |
+
- H4 files.
|
| 239 |
+
- Self-improvement protocol.
|
| 240 |
+
- Historical improvement reports.
|
| 241 |
+
- Backlog outcome reviews.
|
| 242 |
+
|
| 243 |
+
Benchmark indicators:
|
| 244 |
+
|
| 245 |
+
- Harness compliance remains at least 90% across repeated benchmark runs.
|
| 246 |
+
- Trace quality remains at least 2.5/3.
|
| 247 |
+
- Improvements show measurable positive deltas or are explicitly reverted.
|
| 248 |
+
- Scope creep and validation weakening are caught by policy.
|
| 249 |
+
|
| 250 |
+
Current status:
|
| 251 |
+
|
| 252 |
+
- Partially achieved by Phase 5. `scripts/bin/harness-cli audit` detects
|
| 253 |
+
durable-state drift, `scripts/bin/harness-cli propose` generates structured
|
| 254 |
+
improvement proposals from friction, interventions, and audit results, and
|
| 255 |
+
`docs/IMPROVEMENT_PROTOCOL.md` defines the review loop. H5 is not fully
|
| 256 |
+
achieved until repeated benchmark outcomes prove proposed improvements create
|
| 257 |
+
measurable positive deltas or are explicitly reverted.
|
| 258 |
+
|
| 259 |
+
Activated responsibilities:
|
| 260 |
+
|
| 261 |
+
- Entropy auditing.
|
| 262 |
+
- Failure attribution.
|
| 263 |
+
- Intervention recording.
|
| 264 |
+
- Permissions.
|
| 265 |
+
|
| 266 |
+
## Current Assessment
|
| 267 |
+
|
| 268 |
+
| Level | Status | Evidence |
|
| 269 |
+
| --- | --- | --- |
|
| 270 |
+
| H0 | Passed | Harness docs, templates, and durable records exist. |
|
| 271 |
+
| H1 | Achieved | `AGENTS.md`, `docs/HARNESS.md`, `docs/FEATURE_INTAKE.md`, `docs/ARCHITECTURE.md`, `docs/templates/*`, and `docs/TEST_MATRIX.md` exist. |
|
| 272 |
+
| H2 | Achieved | `scripts/bin/harness-cli`, `scripts/schema/001-init.sql`, durable story records, `docs/HARNESS_COMPONENTS.md`, `docs/HARNESS_MATURITY.md`, `docs/TRACE_SPEC.md`, and `docs/CONTEXT_RULES.md` define the Phase 2 surface. |
|
| 273 |
+
| H3 | Partial | Phase 3 adds `scripts/bin/harness-cli score-trace`, enriched friction context, and the backlog outcome loop; Phase 4 auto-scores traces on write. Component-level benchmark attribution remains open. |
|
| 274 |
+
| H4 | Achieved | Phase 4 adds story-level `verify_command`, `story verify`, and trace-time verification warnings. Phase 5 adds `story verify-all` for batch story proof. |
|
| 275 |
+
| H5 | Partial | Phase 5 adds `audit`, `score-context`, `intervention add/query`, `propose`, `docs/HARNESS_AUDIT.md`, and `docs/IMPROVEMENT_PROTOCOL.md`; repeated benchmark outcome proof remains open. |
|
| 276 |
+
|
| 277 |
+
## Responsibility Activation
|
| 278 |
+
|
| 279 |
+
| Responsibility | H0 | H1 | H2 | H3 | H4 | H5 |
|
| 280 |
+
| --- | --- | --- | --- | --- | --- | --- |
|
| 281 |
+
| Task specification | Missing | Covered | Covered | Covered | Covered | Covered |
|
| 282 |
+
| Context selection | Missing | Partial | Covered | Covered | Covered | Covered |
|
| 283 |
+
| Tool access | Missing | Partial | Partial | Partial | Covered | Covered |
|
| 284 |
+
| Project memory | Missing | Covered | Covered | Covered | Covered | Covered |
|
| 285 |
+
| Task state | Missing | Partial | Covered | Covered | Covered | Covered |
|
| 286 |
+
| Observability | Missing | Missing | Partial | Covered | Covered | Covered |
|
| 287 |
+
| Failure attribution | Missing | Missing | Partial | Covered | Covered | Covered |
|
| 288 |
+
| Verification | Missing | Partial | Partial | Partial | Covered | Covered |
|
| 289 |
+
| Permissions | Missing | Partial | Partial | Partial | Covered | Covered |
|
| 290 |
+
| Entropy auditing | Missing | Missing | Partial | Covered | Covered | Covered |
|
| 291 |
+
| Intervention recording | Missing | Partial | Partial | Covered | Covered | Covered |
|
| 292 |
+
|
| 293 |
+
## Phase 3 Interpretation
|
| 294 |
+
|
| 295 |
+
Phase 3 starts the H2 to H3 transition. It claims active trace scoring and a
|
| 296 |
+
documented improvement feedback loop, but it does not claim full H3 because
|
| 297 |
+
benchmark comparison and component-level regression attribution are explicitly
|
| 298 |
+
outside this repository's Phase 3 scope.
|
| 299 |
+
|
| 300 |
+
## Phase 4 Interpretation
|
| 301 |
+
|
| 302 |
+
Phase 4 starts the H3 to H4 transition. It gives stories the same mechanical
|
| 303 |
+
verification pattern that decisions already had, records story verification
|
| 304 |
+
results in the durable layer, auto-scores traces when they are written, and
|
| 305 |
+
warns before close when a linked story's verification has not passed. It does
|
| 306 |
+
not claim full H4 because benchmark execution, batch verification, and automatic
|
| 307 |
+
proof-column updates remain separate work.
|
| 308 |
+
|
| 309 |
+
## Phase 5 Interpretation
|
| 310 |
+
|
| 311 |
+
Phase 5 completes H4 by adding batch story verification and starts H5 by adding
|
| 312 |
+
tool discovery, intervention records, context scoring, drift audit, and
|
| 313 |
+
deterministic proposal generation. The repository may claim H5 partial only
|
| 314 |
+
when those commands and docs are present and validated; it must not claim full
|
| 315 |
+
H5 until benchmark runs or trace outcomes prove the proposal loop improves the
|
| 316 |
+
harness over time.
|
docs/IMPROVEMENT_PROTOCOL.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Improvement Protocol
|
| 2 |
+
|
| 3 |
+
Phase 5 starts the self-improvement loop:
|
| 4 |
+
|
| 5 |
+
```text
|
| 6 |
+
friction + interventions + audit findings
|
| 7 |
+
-> harness-cli propose
|
| 8 |
+
-> proposed backlog item
|
| 9 |
+
-> human review
|
| 10 |
+
-> implementation with predicted impact
|
| 11 |
+
-> close with actual outcome
|
| 12 |
+
```
|
| 13 |
+
|
| 14 |
+
## Generate Proposals
|
| 15 |
+
|
| 16 |
+
```bash
|
| 17 |
+
scripts/bin/harness-cli propose
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
The command is rule-based. It looks for:
|
| 21 |
+
|
| 22 |
+
- repeated trace friction,
|
| 23 |
+
- repeated intervention patterns,
|
| 24 |
+
- non-zero audit categories.
|
| 25 |
+
|
| 26 |
+
Each proposal includes title, component, evidence, predicted impact, risk,
|
| 27 |
+
suggested action, validation plan, and confidence.
|
| 28 |
+
|
| 29 |
+
## Commit Proposals
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
scripts/bin/harness-cli propose --commit
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
Committed proposals become `proposed` backlog items. Humans review them with:
|
| 36 |
+
|
| 37 |
+
```bash
|
| 38 |
+
scripts/bin/harness-cli query backlog --open
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Review Rules
|
| 42 |
+
|
| 43 |
+
- Tiny proposals may be implemented directly when they only clarify docs.
|
| 44 |
+
- Normal proposals need a story packet or clear backlog acceptance.
|
| 45 |
+
- High-risk proposals need a durable decision record before changing source
|
| 46 |
+
hierarchy, architecture direction, validation requirements, or risk policy.
|
| 47 |
+
- Completed proposal work must close the backlog item with actual outcome
|
| 48 |
+
evidence.
|
| 49 |
+
|
| 50 |
+
## Validation
|
| 51 |
+
|
| 52 |
+
After implementation, compare the predicted impact with:
|
| 53 |
+
|
| 54 |
+
- `scripts/bin/harness-cli audit`,
|
| 55 |
+
- `scripts/bin/harness-cli query friction`,
|
| 56 |
+
- `scripts/bin/harness-cli query interventions`,
|
| 57 |
+
- benchmark trace quality and harness compliance when benchmark proof applies.
|
docs/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Documentation
|
| 2 |
+
|
| 3 |
+
Start every task with `AGENTS.md`. This index directs agents to the smallest
|
| 4 |
+
relevant context rather than every document in the repository.
|
| 5 |
+
|
| 6 |
+
## Current Product and Work
|
| 7 |
+
|
| 8 |
+
- `product/` — accepted contracts for CarePath, Ghi chép bệnh án AI, and Phiên
|
| 9 |
+
dịch khám bệnh trực tiếp.
|
| 10 |
+
- `ux-redesign-carepath.md` — current Vietnamese-first UX implementation
|
| 11 |
+
backlog; required before UX or product-flow implementation.
|
| 12 |
+
- `onboarding-ux-fix-tasks.md` — current visual onboarding execution backlog.
|
| 13 |
+
- `../UI-FIX-PLAN.md` — current public-site issue plan.
|
| 14 |
+
- `deploy.md` — Hugging Face Space deployment instructions.
|
| 15 |
+
|
| 16 |
+
## Harness: Read for Daily Work
|
| 17 |
+
|
| 18 |
+
- `HARNESS.md` — source hierarchy, task loop, and done definition.
|
| 19 |
+
- `FEATURE_INTAKE.md` — lane selection and CarePath hard gates.
|
| 20 |
+
- `ARCHITECTURE.md` — module and delivery boundaries.
|
| 21 |
+
- `CONTEXT_RULES.md` — minimum context by lane.
|
| 22 |
+
- `TEST_MATRIX.md` — behavior-to-proof baseline.
|
| 23 |
+
- `TRACE_SPEC.md` — durable completion evidence.
|
| 24 |
+
- `stories/`, `decisions/`, and `templates/` — selected work, settled
|
| 25 |
+
tradeoffs, and new-work starters.
|
| 26 |
+
|
| 27 |
+
## Harness: Read Only When Triggered
|
| 28 |
+
|
| 29 |
+
- `TOOL_REGISTRY.md` — registering or using optional external tools.
|
| 30 |
+
- `HARNESS_AUDIT.md`, `HARNESS_COMPONENTS.md`, and `HARNESS_MATURITY.md` —
|
| 31 |
+
audit, observability, maturity, or benchmark work.
|
| 32 |
+
- `HARNESS_BACKLOG.md` and `IMPROVEMENT_PROTOCOL.md` — repeated Harness
|
| 33 |
+
friction or process improvements.
|
| 34 |
+
- `GLOSSARY.md` — extending shared Harness terminology.
|
| 35 |
+
|
| 36 |
+
## Evidence and History
|
| 37 |
+
|
| 38 |
+
- `qa-evidence/` — versioned visual QA proof and its retention index.
|
| 39 |
+
- `history/` — preserved MVP, demo-site, unification, and review documents.
|
| 40 |
+
These are context only; do not reopen completed tickets as current work.
|
docs/TEST_MATRIX.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Test Matrix
|
| 2 |
+
|
| 3 |
+
This matrix maps the current CarePath baseline to proof. Status changes only
|
| 4 |
+
after the named evidence is actually run and recorded.
|
| 5 |
+
|
| 6 |
+
| Story | Contract | Unit | Integration | E2E | Platform | Status | Evidence |
|
| 7 |
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| 8 |
+
| CP-BASE-001 | Unified API and Ghi chép bệnh án AI remain available | yes | yes | no | no | implemented | 96 passed, 1 skipped; mock smoke passed (2026-07-12) |
|
| 9 |
+
| CP-BASE-002 | Interpreter remains translate-only and fail-closed | yes | yes | yes | no | implemented | Ruff; 109 passed, 1 skipped; mock eval 50/50; 4 browser tests passed (2026-07-12) |
|
| 10 |
+
| CP-BASE-003 | Public CarePath site remains Vietnamese-first and deployable | yes | no | yes | yes | implemented | 45 unit, 5 deploy-env, 7 browser tests; Lighthouse 100/100/100 (2026-07-12) |
|
| 11 |
+
| CP-BASE-004 | Interpreter console remains buildable and usable | yes | no | yes | no | implemented | lint; 38 unit; build; 4 browser tests passed (2026-07-12) |
|
| 12 |
+
| GEC-001 | Offline GEC training uses ViMedCSS and synthetic pairs without human-labeling tooling | no | yes | no | no | implemented | Ruff; 26 focused GEC tests; root 95 passed, 1 skipped (2026-07-12) |
|
| 13 |
+
| HARN-001 | Agent work follows durable CarePath intake and proof rules | no | yes | no | no | implemented | pinned merge install, CLI 0.1.11, init, matrix, audit, trace (2026-07-12) |
|
| 14 |
+
|
| 15 |
+
Proof labels mean the relevant layer has evidence for the baseline; they do not
|
| 16 |
+
claim every historical behavior was retested. Story packets define the exact
|
| 17 |
+
commands for future changes.
|
docs/TOOL_REGISTRY.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Tool Registry
|
| 2 |
+
|
| 3 |
+
The harness deals with two distinct kinds of "tool". Keep them separate.
|
| 4 |
+
|
| 5 |
+
| | Capability manifest (outbound) | Inbound tool registry |
|
| 6 |
+
| --- | --- | --- |
|
| 7 |
+
| Direction | harness offers it to the agent | a project equips it for the harness to use |
|
| 8 |
+
| Examples | the `harness-cli` subcommands below | gitnexus, c3, a linter, a deploy check |
|
| 9 |
+
| Presence | always compiled in | optional; may be absent on any machine |
|
| 10 |
+
| If missing | n/a (it is the harness) | clean skip; never blocks the main process |
|
| 11 |
+
|
| 12 |
+
This document describes both. The **inbound registry** is the extension base:
|
| 13 |
+
it is where the harness learns what extra capability is equipped, what purpose
|
| 14 |
+
it serves, and whether it is actually present right now, so a workflow step can
|
| 15 |
+
adapt to what is installed without the core ever depending on it.
|
| 16 |
+
|
| 17 |
+
## Inbound Registry: Register A Tool
|
| 18 |
+
|
| 19 |
+
```bash
|
| 20 |
+
scripts/bin/harness-cli tool register \
|
| 21 |
+
--name deploy-check \
|
| 22 |
+
--kind cli \
|
| 23 |
+
--capability deploy-verification \
|
| 24 |
+
--command ./scripts/deploy-check.sh \
|
| 25 |
+
--description "Verify deploy health before release" \
|
| 26 |
+
--responsibility Verification \
|
| 27 |
+
--args "env:enum:required:staging,production"
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
Fields specific to inbound tools:
|
| 31 |
+
|
| 32 |
+
- `--kind` — how the tool is reached and probed. One of `cli`, `binary`, `mcp`,
|
| 33 |
+
`skill`, `http`. Defaults to `cli`. The kind tells each agent runtime what it
|
| 34 |
+
can orchestrate (a non-Claude agent simply treats a `skill` it cannot run as
|
| 35 |
+
absent) and tells `tool check` which probe to use.
|
| 36 |
+
- `--capability` — the workflow purpose a step looks the tool up by. Free-text
|
| 37 |
+
but normalized to kebab-case, so `Impact Analysis`, `impact_analysis`, and
|
| 38 |
+
`impact-analysis` all register as `impact-analysis`. This is the only coupling
|
| 39 |
+
between a step and a tool; steps reference the capability, never the tool name.
|
| 40 |
+
- `--scan` — for `mcp`/`skill`/`http`, a declarative path or URL that
|
| 41 |
+
`tool check` resolves to decide presence (e.g. `.c3`, `~/.claude/skills/c3`,
|
| 42 |
+
`https://localhost:8080/health`). `cli`/`binary` are probed via their command.
|
| 43 |
+
|
| 44 |
+
`--force` is only needed for `cli`/`binary` whose command is intentionally
|
| 45 |
+
absent on the current machine. `mcp`/`skill`/`http` are not on `PATH` by nature,
|
| 46 |
+
so they register without `--force`; their presence is resolved later by
|
| 47 |
+
`tool check`.
|
| 48 |
+
|
| 49 |
+
Registering an MCP server or a Claude skill (examples):
|
| 50 |
+
|
| 51 |
+
```bash
|
| 52 |
+
scripts/bin/harness-cli tool register --name gitnexus --kind mcp \
|
| 53 |
+
--capability impact-analysis --scan ".gitnexus" --command "mcp:gitnexus" \
|
| 54 |
+
--description "Code-graph blast radius" --responsibility Verification
|
| 55 |
+
scripts/bin/harness-cli tool register --name c3 --kind skill \
|
| 56 |
+
--capability impact-analysis --scan ".c3" --command "skill:c3" \
|
| 57 |
+
--description "Component model and drift audit (Claude skill)" \
|
| 58 |
+
--responsibility Verification
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
Remove a tool with:
|
| 62 |
+
|
| 63 |
+
```bash
|
| 64 |
+
scripts/bin/harness-cli tool remove --name deploy-check
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
## Inbound Registry: Check Presence
|
| 68 |
+
|
| 69 |
+
Registration records intent. `tool check` reconciles intent with reality by
|
| 70 |
+
scanning each registered tool and persisting the verdict (`status` and
|
| 71 |
+
`checked_at`). Run it at intake start so status reflects current reality.
|
| 72 |
+
|
| 73 |
+
```bash
|
| 74 |
+
scripts/bin/harness-cli tool check # scan all registered tools
|
| 75 |
+
scripts/bin/harness-cli tool check --name c3 # scan one
|
| 76 |
+
scripts/bin/harness-cli tool check --json # machine-readable for agents
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
Probe per kind:
|
| 80 |
+
|
| 81 |
+
| Kind | Probe | `present` means |
|
| 82 |
+
| --- | --- | --- |
|
| 83 |
+
| `cli`, `binary` | command resolves on `PATH` or as a path | installed and runnable |
|
| 84 |
+
| `mcp`, `skill` | `scan_target` path resolves (`~` expands) | equipped/configured on disk |
|
| 85 |
+
| `http` | `scan_target` reachable over TCP (2s), else path | endpoint answers |
|
| 86 |
+
|
| 87 |
+
`tool check` always exits `0`: a missing extension is a fact to report, not a
|
| 88 |
+
CLI failure. A `cli`/`binary` is `present` when runnable. An `mcp`/`skill`/`http`
|
| 89 |
+
`present` means **equipped** (config/file resolves), not **live this session** —
|
| 90 |
+
the agent still confirms live usability at call time, since only the agent
|
| 91 |
+
runtime can see whether its MCP server is actually connected. With no
|
| 92 |
+
`scan_target`, the status is `unknown` and the agent must confirm.
|
| 93 |
+
|
| 94 |
+
## Inbound Registry: Look Up By Capability
|
| 95 |
+
|
| 96 |
+
A workflow step asks "what is present for this purpose?" rather than naming a
|
| 97 |
+
tool:
|
| 98 |
+
|
| 99 |
+
```bash
|
| 100 |
+
scripts/bin/harness-cli query tools --capability impact-analysis
|
| 101 |
+
scripts/bin/harness-cli query tools --capability impact-analysis --status present
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
The result is the set of providers. Multiple tools may provide one capability
|
| 105 |
+
(gitnexus and c3 both serve `impact-analysis` and are complementary), so a step
|
| 106 |
+
reads the set and degrades on how much of it is present.
|
| 107 |
+
|
| 108 |
+
### Degrade Ladder
|
| 109 |
+
|
| 110 |
+
The CLI reports facts (`status`); the agent applies policy. The generic rule,
|
| 111 |
+
keyed on the present-provider count for a capability:
|
| 112 |
+
|
| 113 |
+
| Providers present | Posture | Agent behavior |
|
| 114 |
+
| --- | --- | --- |
|
| 115 |
+
| none registered | Inactive | clean skip; note `capability X: inactive` in the trace. Not drift. |
|
| 116 |
+
| registered but none/some present | Degraded | run with what resolves; set the `Weak proof` flag; note the gap. |
|
| 117 |
+
| all present | Full | normal operation. |
|
| 118 |
+
|
| 119 |
+
A registered tool that scans as `missing` is a failed validity gate, not a skip.
|
| 120 |
+
A capability with no registered providers is simply inactive and is skipped
|
| 121 |
+
without penalty — this is what keeps the core seamless on a fresh install.
|
| 122 |
+
|
| 123 |
+
### Recommended Capability Vocabulary
|
| 124 |
+
|
| 125 |
+
Capability is open (no code change to add one), but a step and its providers
|
| 126 |
+
must agree on the exact string. Reuse these where they fit before coining a new
|
| 127 |
+
one; coin new ones in kebab-case:
|
| 128 |
+
|
| 129 |
+
```
|
| 130 |
+
impact-analysis · deploy-verification · coverage · security-scan
|
| 131 |
+
performance-benchmark · documentation-lookup
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
## Inspecting The Registry
|
| 135 |
+
|
| 136 |
+
```bash
|
| 137 |
+
scripts/bin/harness-cli query tools --summary
|
| 138 |
+
scripts/bin/harness-cli query tools --json
|
| 139 |
+
scripts/bin/harness-cli query tools --responsibility Verification
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
JSON records carry `kind`, `capability`, `scan_target`, `status`, and
|
| 143 |
+
`checked_at` alongside the existing fields, so any agent can read the registry
|
| 144 |
+
without parsing the human table.
|
| 145 |
+
|
| 146 |
+
## Compiled Harness Commands (Outbound Manifest)
|
| 147 |
+
|
| 148 |
+
| Command | Responsibility | Purpose | Arguments |
|
| 149 |
+
| --- | --- | --- | --- |
|
| 150 |
+
| `init` | Task state | Create the harness database. | none |
|
| 151 |
+
| `migrate` | Task state | Apply pending schema migrations. | none |
|
| 152 |
+
| `import brownfield` | Project memory | Seed durable records from markdown state. | none |
|
| 153 |
+
| `intake` | Task specification | Record a feature intake classification. | `--type`, `--summary`, `--lane` |
|
| 154 |
+
| `story add` | Task state | Create a durable story record. | `--id`, `--title`, `--lane`, optional `--verify` |
|
| 155 |
+
| `story update` | Task state | Update story status, proof flags, evidence, or verification command. | `--id`, optional proof/status fields |
|
| 156 |
+
| `story verify` | Verification | Run one story `verify_command` and record pass/fail. | story id |
|
| 157 |
+
| `story verify-all` | Verification | Run all configured story verification commands and skip stories without one. | none |
|
| 158 |
+
| `decision add` | Project memory | Create a durable decision record. | `--id`, `--title`, optional `--doc`, `--verify` |
|
| 159 |
+
| `decision verify` | Verification | Run one decision verification command. | decision id |
|
| 160 |
+
| `backlog add` | Entropy auditing | Record a harness improvement proposal. | `--title`, optional pain/suggestion/risk/predicted fields |
|
| 161 |
+
| `backlog close` | Entropy auditing | Close a backlog item with outcome evidence. | `--id`, optional `--status`, `--outcome` |
|
| 162 |
+
| `tool register` | Tool access | Register an external project tool. | `--name`, `--command`, `--description`, `--responsibility`, optional `--kind`, `--capability`, `--scan`, `--args`, `--force` |
|
| 163 |
+
| `tool check` | Tool access | Scan registered tools and persist present/missing/unknown status. | optional `--name`, `--json` |
|
| 164 |
+
| `tool remove` | Tool access | Remove a registered external tool. | `--name` |
|
| 165 |
+
| `intervention add` | Intervention recording | Record a human, reviewer, CI, or agent intervention. | `--type`, `--description`, `--source`, optional `--trace`, `--story`, `--impact` |
|
| 166 |
+
| `trace` | Observability | Record an agent execution trace and print trace quality. | `--summary`, optional trace fields |
|
| 167 |
+
| `score-trace` | Observability | Score trace detail against lane requirements. | optional `--id` |
|
| 168 |
+
| `score-context` | Context selection | Score trace reads against compiled context rules. | trace id |
|
| 169 |
+
| `audit` | Entropy auditing | Run drift checks and compute entropy score. | none |
|
| 170 |
+
| `propose` | Entropy auditing | Generate improvement proposals from friction, interventions, and audit findings. | optional `--commit` |
|
| 171 |
+
| `query matrix` | Task state | Show durable story proof matrix. | optional `--numeric` |
|
| 172 |
+
| `query backlog` | Entropy auditing | Show harness improvement backlog. | optional `--open`, `--closed` |
|
| 173 |
+
| `query decisions` | Project memory | Show durable decision records. | none |
|
| 174 |
+
| `query intakes` | Task specification | Show recent intake records. | none |
|
| 175 |
+
| `query traces` | Observability | Show recent trace records. | none |
|
| 176 |
+
| `query friction` | Failure attribution | Show traces with harness friction. | none |
|
| 177 |
+
| `query tools` | Tool access | Show compiled and registered tool entries. | optional `--json`, `--summary`, `--responsibility`, `--capability`, `--status` |
|
| 178 |
+
| `query interventions` | Intervention recording | Show intervention records. | optional `--trace`, `--story`, `--type` |
|
| 179 |
+
| `query stats` | Task state | Show durable record counts. | none |
|
| 180 |
+
| `query sql` | Tool access | Run arbitrary SQL against `harness.db`. | SQL text |
|
| 181 |
+
| `db changeset apply` | Task state | Apply one semantic changeset idempotently. | changeset path |
|
| 182 |
+
| `db rebuild` | Task state | Rebuild a fresh `harness.db` from semantic changesets. | `--from` changeset directory |
|
| 183 |
+
|
| 184 |
+
## Validation Rules
|
| 185 |
+
|
| 186 |
+
- Tool names must be unique among registered tools.
|
| 187 |
+
- Descriptions must be 10-200 characters.
|
| 188 |
+
- Responsibilities must match the Runtime Substrate responsibility list.
|
| 189 |
+
- `--kind` must be one of `cli`, `binary`, `mcp`, `skill`, `http`.
|
| 190 |
+
- `--capability` must be kebab-case (lowercase letters, digits, single hyphens);
|
| 191 |
+
spaces and underscores are normalized to hyphens.
|
| 192 |
+
- `--args` entries must use `name:type:required` or
|
| 193 |
+
`name:type:required:help`, with `required` or `optional` as the third field.
|
| 194 |
+
- For `cli`/`binary`, the command must exist as a path or on `PATH`, unless
|
| 195 |
+
`--force` is supplied. `mcp`/`skill`/`http` skip this check.
|
docs/TRACE_SPEC.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Trace Specification
|
| 2 |
+
|
| 3 |
+
The `trace` table records what happened during a Harness task. This document
|
| 4 |
+
defines the expected depth and format for each field so traces are useful for
|
| 5 |
+
review, benchmark scoring, failure attribution, and future harness evolution.
|
| 6 |
+
|
| 7 |
+
The current schema lives in `scripts/schema/001-init.sql` under the `trace`
|
| 8 |
+
table. The schema is not changed by Phase 2.
|
| 9 |
+
|
| 10 |
+
## Field Reference
|
| 11 |
+
|
| 12 |
+
| Field | Type | Required | Format | Example |
|
| 13 |
+
| --- | --- | --- | --- | --- |
|
| 14 |
+
| `id` | INTEGER | Automatic | SQLite autoincrement primary key. Do not set manually. | `42` |
|
| 15 |
+
| `created_at` | TEXT | Automatic | SQLite `datetime('now')`. Do not set manually. | `2026-05-27 09:24:37` |
|
| 16 |
+
| `task_summary` | TEXT | Yes | One sentence, at least 10 characters, naming the outcome or attempted outcome. | `Completed Phase 2 docs-only observability and taxonomy specification` |
|
| 17 |
+
| `intake_id` | INTEGER | Standard+ when an intake was recorded | Integer id from the related `intake` row. | `36` |
|
| 18 |
+
| `story_id` | TEXT | Standard+ when work maps to one story | Story id from the `story` table. Use the main story when one trace covers several; list the rest in `notes`. | `US-004` |
|
| 19 |
+
| `agent` | TEXT | Optional for minimal; Standard+ expected | Short agent/tool name. | `codex` |
|
| 20 |
+
| `actions_taken` | TEXT | Standard+ | JSON array text. With the current CLI, pass a comma-separated list and the CLI stores JSON text. | `["read PHASE2.md","drafted TRACE_SPEC.md","updated HARNESS.md"]` |
|
| 21 |
+
| `files_read` | TEXT | Standard+ | JSON array text of paths or command names. With the current CLI, pass a comma-separated list. | `["PHASE2.md","docs/HARNESS.md","scripts/bin/harness-cli query matrix"]` |
|
| 22 |
+
| `files_changed` | TEXT | Standard+ | JSON array text of changed file paths. With the current CLI, pass a comma-separated list; omit only when no files changed. | `["docs/TRACE_SPEC.md","docs/HARNESS.md"]` |
|
| 23 |
+
| `decisions_made` | TEXT | Detailed | JSON array text of decision strings. Include scope decisions, validation choices, and explicit non-goals. | `["Kept Phase 2 docs-only; installer propagation remains out of scope"]` |
|
| 24 |
+
| `errors` | TEXT | Standard+ if errors occurred; Detailed always | JSON array text of error or blocker strings. Until the CLI supports empty arrays directly, use `none` when a detailed trace needs explicit no-error evidence. | `["git diff --check failed before whitespace fix"]` |
|
| 25 |
+
| `outcome` | TEXT | Yes before final response | One of `completed`, `blocked`, `partial`, or `failed`. | `completed` |
|
| 26 |
+
| `duration_seconds` | INTEGER | Detailed when available | Positive integer estimate or measured duration. Leave null if unknown. | `1800` |
|
| 27 |
+
| `token_estimate` | INTEGER | Detailed when available | Positive integer estimate. Leave null if unknown. | `24000` |
|
| 28 |
+
| `harness_friction` | TEXT | Standard+ when friction exists; Detailed always | Free text naming what was hard, missing, ambiguous, or repeated. Use `none` only when the agent actively checked and found no friction. | `New Phase 2 docs are not in installer copy list; recorded as out-of-scope follow-up.` |
|
| 29 |
+
| `notes` | TEXT | Optional | Free text for review context that does not fit other fields. | `Trace covers US-003, US-004, US-005, and US-006.` |
|
| 30 |
+
|
| 31 |
+
## Quality Tiers
|
| 32 |
+
|
| 33 |
+
### Minimal (score: 1)
|
| 34 |
+
|
| 35 |
+
Minimum fields:
|
| 36 |
+
|
| 37 |
+
- `task_summary` is filled and at least 10 characters.
|
| 38 |
+
- `outcome` is filled before the final response.
|
| 39 |
+
|
| 40 |
+
Acceptable for:
|
| 41 |
+
|
| 42 |
+
- Tiny-lane tasks with no file changes or only low-risk copy/doc edits.
|
| 43 |
+
|
| 44 |
+
Not acceptable for:
|
| 45 |
+
|
| 46 |
+
- Normal or high-risk work.
|
| 47 |
+
- Any work that discovered friction, errors, or a missing validation path.
|
| 48 |
+
|
| 49 |
+
### Standard (score: 2)
|
| 50 |
+
|
| 51 |
+
Minimum fields:
|
| 52 |
+
|
| 53 |
+
- All Minimal fields.
|
| 54 |
+
- `intake_id` when an intake was recorded.
|
| 55 |
+
- `story_id` when the work maps cleanly to one story.
|
| 56 |
+
- `agent`.
|
| 57 |
+
- `actions_taken` as JSON array text.
|
| 58 |
+
- `files_read` as JSON array text.
|
| 59 |
+
- `files_changed` as JSON array text.
|
| 60 |
+
- At least one of `errors` or `harness_friction`.
|
| 61 |
+
|
| 62 |
+
Required for:
|
| 63 |
+
|
| 64 |
+
- Normal-lane tasks.
|
| 65 |
+
- Tiny tasks that changed Harness instructions, validation expectations, or
|
| 66 |
+
durable records.
|
| 67 |
+
|
| 68 |
+
Standard traces may leave `duration_seconds`, `token_estimate`, and
|
| 69 |
+
`decisions_made` empty when those details are not useful.
|
| 70 |
+
|
| 71 |
+
### Detailed (score: 3)
|
| 72 |
+
|
| 73 |
+
Minimum fields:
|
| 74 |
+
|
| 75 |
+
- All Standard fields.
|
| 76 |
+
- `decisions_made` as JSON array text.
|
| 77 |
+
- `errors` as JSON array text, using `none` with the current CLI when no
|
| 78 |
+
errors occurred.
|
| 79 |
+
- `harness_friction`, using `none` only after checking for friction.
|
| 80 |
+
- `duration_seconds` or a note explaining why duration is unavailable.
|
| 81 |
+
- `token_estimate` or a note explaining why token estimate is unavailable.
|
| 82 |
+
- `notes` when one trace covers multiple stories, multiple risk flags, or
|
| 83 |
+
skipped validation.
|
| 84 |
+
|
| 85 |
+
Required for:
|
| 86 |
+
|
| 87 |
+
- High-risk tasks.
|
| 88 |
+
- Changes touching architecture direction, source-of-truth hierarchy,
|
| 89 |
+
validation requirements, auth, authorization, data loss, audit/security, or
|
| 90 |
+
external provider behavior.
|
| 91 |
+
- Benchmark or release work where later review needs precise proof.
|
| 92 |
+
|
| 93 |
+
For high-risk work, `decisions_made` in the trace summarizes what was decided.
|
| 94 |
+
It does not replace a durable decision record. If the work changes behavior,
|
| 95 |
+
architecture, authorization, data ownership, API shape, or validation
|
| 96 |
+
requirements, add a `docs/decisions/NNNN-*.md` file and record it with
|
| 97 |
+
`scripts/bin/harness-cli decision add`.
|
| 98 |
+
|
| 99 |
+
## Lane Mapping
|
| 100 |
+
|
| 101 |
+
| Lane | Expected Tier | Minimum Trace Behavior |
|
| 102 |
+
| --- | --- | --- |
|
| 103 |
+
| Tiny | Minimal | Record summary and outcome; use Standard if friction or Harness docs changed. |
|
| 104 |
+
| Normal | Standard | Record intake, actions, files read, files changed, outcome, and friction/errors. |
|
| 105 |
+
| High-risk | Detailed | Record all fields or explicitly explain unavailable duration/token estimates. |
|
| 106 |
+
|
| 107 |
+
## Friction Capture Protocol
|
| 108 |
+
|
| 109 |
+
Populate `harness_friction` when any of these occur:
|
| 110 |
+
|
| 111 |
+
- The agent had to infer a missing rule or source of truth.
|
| 112 |
+
- Required validation was unclear, unavailable, or too expensive to run.
|
| 113 |
+
- A document, durable record, or story packet was stale or contradictory.
|
| 114 |
+
- The task revealed a repeated manual step that should become a template,
|
| 115 |
+
command, or checklist.
|
| 116 |
+
- A requested change was out of scope but likely important later.
|
| 117 |
+
- A benchmark or review failure could not be attributed to a component.
|
| 118 |
+
|
| 119 |
+
How to write friction:
|
| 120 |
+
|
| 121 |
+
- Name the concrete pain, not a vague mood.
|
| 122 |
+
- Include the missing capability or contradiction.
|
| 123 |
+
- If the friction should become work, also add or update a backlog item with
|
| 124 |
+
`scripts/bin/harness-cli backlog add`.
|
| 125 |
+
- If there was no friction, use `none` only for Detailed traces.
|
| 126 |
+
|
| 127 |
+
Good friction:
|
| 128 |
+
|
| 129 |
+
```text
|
| 130 |
+
New Phase 2 docs are not copied by scripts/install-harness.sh, but installer
|
| 131 |
+
propagation is out of scope for docs-only Phase 2.
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
Weak friction:
|
| 135 |
+
|
| 136 |
+
```text
|
| 137 |
+
docs confusing
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
## Examples
|
| 141 |
+
|
| 142 |
+
### Good Trace (Detailed)
|
| 143 |
+
|
| 144 |
+
```bash
|
| 145 |
+
scripts/bin/harness-cli trace \
|
| 146 |
+
--summary "Completed high-risk auth role migration with audit proof" \
|
| 147 |
+
--intake 51 \
|
| 148 |
+
--story US-014 \
|
| 149 |
+
--agent codex \
|
| 150 |
+
--outcome completed \
|
| 151 |
+
--duration 4200 \
|
| 152 |
+
--tokens 52000 \
|
| 153 |
+
--actions "read access-control docs,created migration,updated audit tests,ran integration suite" \
|
| 154 |
+
--read "docs/product/permissions.md,docs/decisions/0008-auth-boundary.md,src/auth/roles.ts" \
|
| 155 |
+
--changed "src/auth/roles.ts,src/audit/events.ts,tests/auth-roles.test.ts" \
|
| 156 |
+
--decisions "kept manager role scoped to workspace,recorded audit event on every role change" \
|
| 157 |
+
--errors "none" \
|
| 158 |
+
--friction "Existing permission docs did not define delegated admin; added backlog item for role glossary." \
|
| 159 |
+
--notes "Detailed trace required because the task touched authorization and audit behavior."
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
### Adequate Trace (Standard)
|
| 163 |
+
|
| 164 |
+
```bash
|
| 165 |
+
scripts/bin/harness-cli trace \
|
| 166 |
+
--summary "Added Phase 2 trace specification and Harness reference" \
|
| 167 |
+
--intake 36 \
|
| 168 |
+
--story US-004 \
|
| 169 |
+
--agent codex \
|
| 170 |
+
--outcome completed \
|
| 171 |
+
--actions "read PHASE2.md,drafted TRACE_SPEC.md,updated HARNESS.md,ran rg checks" \
|
| 172 |
+
--read "PHASE2.md,docs/HARNESS.md,scripts/schema/001-init.sql" \
|
| 173 |
+
--changed "docs/TRACE_SPEC.md,docs/HARNESS.md" \
|
| 174 |
+
--friction "none"
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
### Insufficient Trace
|
| 178 |
+
|
| 179 |
+
```bash
|
| 180 |
+
scripts/bin/harness-cli trace \
|
| 181 |
+
--summary "did phase 2" \
|
| 182 |
+
--outcome completed
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
Why this is insufficient for normal-lane Phase 2 work:
|
| 186 |
+
|
| 187 |
+
- It does not identify actions.
|
| 188 |
+
- It does not list files read or changed.
|
| 189 |
+
- It does not connect to intake or stories.
|
| 190 |
+
- It gives no friction or error signal.
|
| 191 |
+
|
| 192 |
+
## Review Checklist
|
| 193 |
+
|
| 194 |
+
Before the final response, check:
|
| 195 |
+
|
| 196 |
+
- The trace tier matches the lane.
|
| 197 |
+
- Review the score printed automatically by `scripts/bin/harness-cli trace`.
|
| 198 |
+
Use `scripts/bin/harness-cli score-trace --id N` when re-checking a specific
|
| 199 |
+
historical trace.
|
| 200 |
+
- `files_changed` matches the actual changed-file set at a useful level.
|
| 201 |
+
- `errors` names real blockers or is `none` for Detailed traces when the
|
| 202 |
+
current CLI is used.
|
| 203 |
+
- `harness_friction` either names a concrete issue or is intentionally `none`.
|
| 204 |
+
- Any friction that should become future work is recorded in the backlog.
|
docs/decisions/0001-harness-first-development.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0001 Harness-First Development
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-05
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The repository currently contains a product README and a large product
|
| 12 |
+
specification. There is no application implementation yet.
|
| 13 |
+
|
| 14 |
+
The project will likely involve human direction plus agent implementation over
|
| 15 |
+
many evolving stories. A single massive specification is not enough for safe
|
| 16 |
+
agent work because it becomes hard to locate current truth, risk, proof, and
|
| 17 |
+
change history.
|
| 18 |
+
|
| 19 |
+
## Decision
|
| 20 |
+
|
| 21 |
+
Create Harness v0 before scaffolding product code.
|
| 22 |
+
|
| 23 |
+
Harness v0 defines:
|
| 24 |
+
|
| 25 |
+
- Agent entrypoint.
|
| 26 |
+
- Product doc split.
|
| 27 |
+
- Feature intake and risk lanes.
|
| 28 |
+
- Story packet templates.
|
| 29 |
+
- Decision records.
|
| 30 |
+
- Test matrix.
|
| 31 |
+
- Harness backlog.
|
| 32 |
+
|
| 33 |
+
No application code, fake scripts, CI, or tests are created in this decision.
|
| 34 |
+
|
| 35 |
+
## Consequences
|
| 36 |
+
|
| 37 |
+
Positive:
|
| 38 |
+
|
| 39 |
+
- Agents have a clear operating model before implementation starts.
|
| 40 |
+
- Product truth can split away from the massive spec.
|
| 41 |
+
- Risky work has a slower lane before code changes.
|
| 42 |
+
- Harness growth becomes part of the work.
|
| 43 |
+
|
| 44 |
+
Tradeoffs:
|
| 45 |
+
|
| 46 |
+
- Some docs are placeholders until real stories exercise them.
|
| 47 |
+
- Validation commands are only contracts until implementation begins.
|
| 48 |
+
- The harness must stay small enough to revise from real friction.
|
docs/decisions/0002-post-spec-product-lifecycle.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0002 Seed Specification Product Lifecycle
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-05
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Superseded by `0003-generic-spec-intake-harness.md`
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Harness v0 originally assumed the repository would include one seed
|
| 12 |
+
specification file for the first product. This decision explained how agents
|
| 13 |
+
should decompose that initial specification into product docs, story packets,
|
| 14 |
+
implementation, and validation proof, then continue working after the seed was
|
| 15 |
+
exhausted.
|
| 16 |
+
|
| 17 |
+
That approach fit a single project but made the harness less reusable.
|
| 18 |
+
|
| 19 |
+
## Decision
|
| 20 |
+
|
| 21 |
+
Treat the initial specification as a seed and historical snapshot, not the
|
| 22 |
+
permanent living product plan.
|
| 23 |
+
|
| 24 |
+
After the initial specification has been exhausted, new work should enter
|
| 25 |
+
through the same harness loop as one of these input types:
|
| 26 |
+
|
| 27 |
+
- Change request.
|
| 28 |
+
- New initiative.
|
| 29 |
+
- Maintenance request.
|
| 30 |
+
- Harness improvement.
|
| 31 |
+
|
| 32 |
+
Product docs under `docs/product/`, story packets under `docs/stories/`,
|
| 33 |
+
validation evidence in `docs/TEST_MATRIX.md`, and decision records under
|
| 34 |
+
`docs/decisions/` become the living operating surface.
|
| 35 |
+
|
| 36 |
+
Large future product areas should be captured as scoped initiative notes instead
|
| 37 |
+
of appended to the seed specification or rewritten as a second monolithic spec.
|
| 38 |
+
|
| 39 |
+
## Consequences
|
| 40 |
+
|
| 41 |
+
Positive:
|
| 42 |
+
|
| 43 |
+
- The original specification remains stable as historical context.
|
| 44 |
+
- Product truth moves into smaller, current, maintainable files.
|
| 45 |
+
- Future work keeps using the same intake, story, proof, and harness-growth
|
| 46 |
+
loop.
|
| 47 |
+
- Large ideas can still be planned without creating another oversized spec.
|
| 48 |
+
|
| 49 |
+
Tradeoffs:
|
| 50 |
+
|
| 51 |
+
- The repository will eventually need an initiative template if large new
|
| 52 |
+
product areas become common.
|
| 53 |
+
- Agents must be careful to update product docs and tests rather than relying on
|
| 54 |
+
the seed specification after initial buildout.
|
docs/decisions/0003-generic-spec-intake-harness.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0003 Generic Spec Intake Harness
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-05
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Harness v0 originally shipped with a project-specific `SPEC.md`, product docs,
|
| 12 |
+
candidate epics, architecture assumptions, and validation examples. That made
|
| 13 |
+
the harness useful for the first project but too specific to reuse as the outer
|
| 14 |
+
shell for a new project.
|
| 15 |
+
|
| 16 |
+
The desired direction is a default harness that can wait for any user-provided
|
| 17 |
+
spec, derive product docs from that spec, and then continue with the same
|
| 18 |
+
intake, story, proof, and decision loop.
|
| 19 |
+
|
| 20 |
+
## Decision
|
| 21 |
+
|
| 22 |
+
Remove the tracked project-specific spec and pre-sliced product domains from
|
| 23 |
+
Harness v0.
|
| 24 |
+
|
| 25 |
+
The harness now starts with:
|
| 26 |
+
|
| 27 |
+
- No baked-in `SPEC.md`.
|
| 28 |
+
- Empty product docs except for intake guidance.
|
| 29 |
+
- Generic story and epic examples.
|
| 30 |
+
- Stack-neutral architecture discovery rules.
|
| 31 |
+
- Stack-neutral validation columns.
|
| 32 |
+
- A source hierarchy that treats a future user-provided spec as input material,
|
| 33 |
+
not permanent living truth.
|
| 34 |
+
|
| 35 |
+
## Alternatives Considered
|
| 36 |
+
|
| 37 |
+
1. Keep the original `SPEC.md` as an example. Rejected because examples can be
|
| 38 |
+
mistaken for current product truth.
|
| 39 |
+
2. Move the original product docs into an examples folder. Rejected for now
|
| 40 |
+
because the user asked for a clean default harness.
|
| 41 |
+
|
| 42 |
+
## Consequences
|
| 43 |
+
|
| 44 |
+
Positive:
|
| 45 |
+
|
| 46 |
+
- The repository is easier to reuse for any new project.
|
| 47 |
+
- Future specs can define their own product domains and stack.
|
| 48 |
+
- Agents are less likely to confuse template truth with product truth.
|
| 49 |
+
|
| 50 |
+
Tradeoffs:
|
| 51 |
+
|
| 52 |
+
- The harness has fewer concrete examples until the next spec is supplied.
|
| 53 |
+
- The first spec intake must create product docs and candidate epics before
|
| 54 |
+
implementation planning can be precise.
|
| 55 |
+
|
| 56 |
+
## Follow-Up
|
| 57 |
+
|
| 58 |
+
- Add a spec-intake template if repeated projects reveal a stable format.
|
docs/decisions/0004-sqlite-durable-layer.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0004 SQLite Durable Layer
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-22
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Harness v0 stores all operational data in markdown files: `TEST_MATRIX.md` rows,
|
| 12 |
+
`HARNESS_BACKLOG.md` items, decision records, and story status. This works for
|
| 13 |
+
human reading but creates friction for agents:
|
| 14 |
+
|
| 15 |
+
- Editing markdown tables is error-prone and hard to validate.
|
| 16 |
+
- There is no structured way to query past intakes, traces, or friction reports.
|
| 17 |
+
- The harness has no observability foundation for future evolution.
|
| 18 |
+
|
| 19 |
+
Recent research on harness engineering (arXiv:2604.25850, arXiv:2605.13357,
|
| 20 |
+
arXiv:2603.28052) identifies observability and structured traces as the
|
| 21 |
+
foundation for harness improvement. All three approaches require queryable
|
| 22 |
+
operational data, not prose documents.
|
| 23 |
+
|
| 24 |
+
## Decision
|
| 25 |
+
|
| 26 |
+
Add a SQLite database (`harness.db`) and a thin CLI (`scripts/bin/harness-cli`) as the
|
| 27 |
+
durable layer for operational harness data.
|
| 28 |
+
|
| 29 |
+
The database stores:
|
| 30 |
+
|
| 31 |
+
- **Intake records**: classification of incoming work.
|
| 32 |
+
- **Stories**: work packets and their validation proof status (replaces manual
|
| 33 |
+
`TEST_MATRIX.md` rows).
|
| 34 |
+
- **Decisions**: durable records with optional verification commands.
|
| 35 |
+
- **Backlog items**: harness improvement proposals with predicted and actual
|
| 36 |
+
impact.
|
| 37 |
+
- **Traces**: agent execution records including actions, files, errors, outcome,
|
| 38 |
+
and harness friction.
|
| 39 |
+
|
| 40 |
+
The schema is version-controlled under `scripts/schema/`. The database file is
|
| 41 |
+
`.gitignore`d because each project instance generates its own operational data.
|
| 42 |
+
|
| 43 |
+
Policy docs (`HARNESS.md`, `FEATURE_INTAKE.md`, `ARCHITECTURE.md`) remain as
|
| 44 |
+
human-readable references. The database stores what agents produce, not what
|
| 45 |
+
they should do.
|
| 46 |
+
|
| 47 |
+
## Alternatives Considered
|
| 48 |
+
|
| 49 |
+
1. Keep everything in markdown. Rejected because it prevents structured queries,
|
| 50 |
+
makes observability impossible, and forces agents to edit fragile tables.
|
| 51 |
+
2. Use JSON files. Rejected because concurrent writes are unsafe and queries
|
| 52 |
+
require custom tooling.
|
| 53 |
+
3. Use a full database server. Rejected because it adds deployment complexity
|
| 54 |
+
that does not match Harness v0 scope.
|
| 55 |
+
|
| 56 |
+
## Consequences
|
| 57 |
+
|
| 58 |
+
Positive:
|
| 59 |
+
|
| 60 |
+
- Agents record structured data instead of editing markdown tables.
|
| 61 |
+
- Intake, story, decision, backlog, and trace data is queryable.
|
| 62 |
+
- The harness has an observability foundation for future evolution.
|
| 63 |
+
- Schema migrations enable the durable layer to grow with the harness.
|
| 64 |
+
|
| 65 |
+
Tradeoffs:
|
| 66 |
+
|
| 67 |
+
- Requires `sqlite3` to be available in the environment.
|
| 68 |
+
- The database is not version-controlled, so each instance starts empty.
|
| 69 |
+
- Markdown docs and the database may drift if agents use one but not the other.
|
| 70 |
+
|
| 71 |
+
## Follow-Up
|
| 72 |
+
|
| 73 |
+
- Seed existing decisions (0001-0003) into the database during init.
|
| 74 |
+
- Add context engineering rules keyed by task type and risk lane.
|
| 75 |
+
- Add harness maturity ladder (H0-H4) once the durable layer proves useful.
|
docs/decisions/0005-prebuilt-rust-harness-cli.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0005 Prebuilt Rust Harness CLI
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-23
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted, amended 2026-05-31, amended 2026-06-09
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The durable layer started as a thin shell wrapper around SQLite. That wrapper
|
| 12 |
+
is now large enough to carry meaningful architecture risk: it mixes command
|
| 13 |
+
parsing, SQL construction, migrations, import behavior, query rendering, and
|
| 14 |
+
help text in one script.
|
| 15 |
+
|
| 16 |
+
The previous installer copied a shell wrapper into target repositories. That
|
| 17 |
+
kept Harness easy to install, but it also meant a Rust rewrite was not only an
|
| 18 |
+
implementation change. It changed the distribution contract for every project
|
| 19 |
+
that receives Harness.
|
| 20 |
+
|
| 21 |
+
## Decision
|
| 22 |
+
|
| 23 |
+
The future Rust implementation of the Harness CLI should be shipped as a
|
| 24 |
+
prebuilt binary downloaded by the installer.
|
| 25 |
+
|
| 26 |
+
The command path for users and agents is the installed Rust binary:
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
scripts/bin/harness-cli <command>
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
On Windows, the repository-local binary is installed as:
|
| 33 |
+
|
| 34 |
+
```powershell
|
| 35 |
+
.\scripts\bin\harness-cli.exe <command>
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
The installer should download, verify, and install the platform-specific Rust
|
| 39 |
+
binary directly at that path. There should be no shell wrapper command contract.
|
| 40 |
+
|
| 41 |
+
The Rust CLI should follow the existing architecture rules:
|
| 42 |
+
|
| 43 |
+
- Domain: harness records, statuses, lanes, and value types.
|
| 44 |
+
- Application: use cases for intake, stories, decisions, backlog, traces, and
|
| 45 |
+
queries.
|
| 46 |
+
- Infrastructure: SQLite repositories and schema migrations.
|
| 47 |
+
- Interface: command-line parsing, terminal output, and installer integration.
|
| 48 |
+
|
| 49 |
+
Release automation now follows the same distribution contract. After a PR is
|
| 50 |
+
merged to `main`, the post-merge maintenance workflow updates `CHANGELOG.md`.
|
| 51 |
+
When the merged PR changed the Rust CLI source, schema, Cargo metadata, or CLI
|
| 52 |
+
release packaging, it also bumps the CLI patch version, updates the installer
|
| 53 |
+
release tag pin, creates a `harness-cli-v*` tag, and invokes the reusable
|
| 54 |
+
Harness CLI release workflow for that tag.
|
| 55 |
+
|
| 56 |
+
## Alternatives Considered
|
| 57 |
+
|
| 58 |
+
1. Keep the shell CLI permanently. Rejected because the script has crossed from
|
| 59 |
+
a thin wrapper into a growing application surface with weak testability.
|
| 60 |
+
2. Copy Rust source into every target project and build locally. Rejected
|
| 61 |
+
because it makes Harness installation depend on a local Rust toolchain and
|
| 62 |
+
increases setup friction for projects that only need the harness.
|
| 63 |
+
3. Require users to install a global `harness` binary separately. Rejected
|
| 64 |
+
because Harness should remain repository-local for agents.
|
| 65 |
+
4. Download a prebuilt binary through the installer. Accepted because it keeps
|
| 66 |
+
target repos simple while allowing the CLI internals to become typed,
|
| 67 |
+
testable, and platform-aware.
|
| 68 |
+
|
| 69 |
+
## Consequences
|
| 70 |
+
|
| 71 |
+
Positive:
|
| 72 |
+
|
| 73 |
+
- The durable-layer CLI can move to typed command parsing and tested use cases.
|
| 74 |
+
- Target projects do not need a Rust toolchain just to use Harness.
|
| 75 |
+
- The `scripts/bin/harness-cli` command is the stable entrypoint for agents on
|
| 76 |
+
macOS/Linux; Windows uses the same repo-local path with the `.exe` suffix.
|
| 77 |
+
- Prebuilt releases can include a known SQLite linkage strategy.
|
| 78 |
+
|
| 79 |
+
Tradeoffs:
|
| 80 |
+
|
| 81 |
+
- The installer must learn platform detection and binary download behavior.
|
| 82 |
+
- Release artifacts need checksums or another integrity check.
|
| 83 |
+
- Unsupported platforms need a clear error path.
|
| 84 |
+
- The project needs a repeatable release process for supported platforms.
|
| 85 |
+
|
| 86 |
+
## Follow-Up
|
| 87 |
+
|
| 88 |
+
- Implement the migration through `US-002 Rust Harness CLI`.
|
| 89 |
+
- Remove the old shell wrapper from installed project payloads.
|
| 90 |
+
- Add checksum verification for downloaded binaries.
|
| 91 |
+
- Treat the Rust CLI as the primary durable-layer implementation.
|
docs/decisions/0006-phase-4-benchmark-triage.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0006 Phase 4 Benchmark Triage
|
| 2 |
+
|
| 3 |
+
Date: 2026-05-31
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The first Phase 4 benchmark re-run found that T4 authentication failed
|
| 12 |
+
`decision_recorded` even though the trace included decisions text. The same run
|
| 13 |
+
also showed command churn from agents trying `story update` proof flags with
|
| 14 |
+
`yes` and `no`, and trying to use `story verify` as if it accepted proof flags.
|
| 15 |
+
|
| 16 |
+
## Decision
|
| 17 |
+
|
| 18 |
+
Harness instructions and CLI help must distinguish durable records from trace
|
| 19 |
+
evidence and must show the current Rust CLI command shape at the point agents
|
| 20 |
+
need it:
|
| 21 |
+
|
| 22 |
+
- High-risk behavior changes require a markdown decision under
|
| 23 |
+
`docs/decisions/` and a durable `decision` row.
|
| 24 |
+
- Trace `--decisions` is evidence for trace quality, not the decision log.
|
| 25 |
+
- `story update` proof flags use `1` and `0`.
|
| 26 |
+
- `story verify <id>` only runs the configured `verify_command`; proof flags
|
| 27 |
+
stay on `story update`.
|
| 28 |
+
|
| 29 |
+
## Alternatives Considered
|
| 30 |
+
|
| 31 |
+
1. Rely on trace auto-scoring to catch the missing T4 decision. Rejected because
|
| 32 |
+
trace scoring can confirm detailed trace content but cannot prove a durable
|
| 33 |
+
decision record exists.
|
| 34 |
+
2. Change the CLI to accept `yes` and `no`. Deferred because v0.1.5 already has
|
| 35 |
+
a numeric command contract and the immediate benchmark issue is stale
|
| 36 |
+
guidance, not missing parser capability.
|
| 37 |
+
|
| 38 |
+
## Consequences
|
| 39 |
+
|
| 40 |
+
Positive:
|
| 41 |
+
|
| 42 |
+
- High-risk agents get explicit decision-log instructions before closing work.
|
| 43 |
+
- Command examples align with the Rust CLI v0.1.5 parser.
|
| 44 |
+
- `story verify` and `story update` have separate mental models in docs.
|
| 45 |
+
|
| 46 |
+
Tradeoffs:
|
| 47 |
+
|
| 48 |
+
- Docs now duplicate a few command examples so the common path is visible
|
| 49 |
+
without repeated help discovery.
|
| 50 |
+
|
| 51 |
+
## Follow-Up
|
| 52 |
+
|
| 53 |
+
- Re-run the Phase 4 benchmark and check whether T4 records a durable decision.
|
| 54 |
+
- Watch for remaining command churn around `story update` and `story verify`.
|
docs/decisions/0007-improvement-proposal-rules.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0007 Improvement Proposal Rules
|
| 2 |
+
|
| 3 |
+
Date: 2026-06-04
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Phase 5 adds `harness-cli propose`, which changes the harness evolution model.
|
| 12 |
+
The command must be useful without becoming an unchecked source of scope creep
|
| 13 |
+
or circular recommendations.
|
| 14 |
+
|
| 15 |
+
## Decision
|
| 16 |
+
|
| 17 |
+
Improvement proposals are advisory, rule-based, and evidence-backed. The command
|
| 18 |
+
may summarize repeated friction, repeated interventions, and audit drift. It may
|
| 19 |
+
create `proposed` backlog items only when `--commit` is supplied.
|
| 20 |
+
|
| 21 |
+
Every proposal must include:
|
| 22 |
+
|
| 23 |
+
- affected Harness component,
|
| 24 |
+
- concrete evidence,
|
| 25 |
+
- predicted impact,
|
| 26 |
+
- risk lane,
|
| 27 |
+
- suggested action,
|
| 28 |
+
- validation plan,
|
| 29 |
+
- confidence level.
|
| 30 |
+
|
| 31 |
+
High-risk proposal implementation still requires human review and a durable
|
| 32 |
+
decision record when it changes source hierarchy, architecture direction,
|
| 33 |
+
validation requirements, or risk policy.
|
| 34 |
+
|
| 35 |
+
## Alternatives Considered
|
| 36 |
+
|
| 37 |
+
1. Generate free-form LLM recommendations. Rejected because Phase 5 needs a
|
| 38 |
+
deterministic and auditable evolution role.
|
| 39 |
+
2. Automatically apply proposed changes. Rejected because the harness must not
|
| 40 |
+
rewrite its own policy without review.
|
| 41 |
+
3. Only report audit findings. Rejected because H5 requires proposed
|
| 42 |
+
improvements, not just drift detection.
|
| 43 |
+
|
| 44 |
+
## Consequences
|
| 45 |
+
|
| 46 |
+
Positive:
|
| 47 |
+
|
| 48 |
+
- Repeated operational patterns can become backlog items.
|
| 49 |
+
- Proposal output is explainable and testable.
|
| 50 |
+
- Human review remains the gate for risky harness changes.
|
| 51 |
+
|
| 52 |
+
Tradeoffs:
|
| 53 |
+
|
| 54 |
+
- Rule-based grouping can miss semantically similar phrasing.
|
| 55 |
+
- Audit-based proposals may be housekeeping rather than strategic evolution.
|
| 56 |
+
|
| 57 |
+
## Follow-Up
|
| 58 |
+
|
| 59 |
+
- Use benchmark runs and closed backlog outcomes to improve proposal quality in
|
| 60 |
+
later phases.
|
docs/decisions/0008-carepath-harness-adoption.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0008 CarePath Harness Adoption
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-12
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
CarePath has two clinical workflows, strict safety invariants, multiple test
|
| 12 |
+
surfaces, and historical plans. Future coding agents need a durable way to
|
| 13 |
+
classify work, preserve those boundaries, and record actual proof.
|
| 14 |
+
|
| 15 |
+
## Decision
|
| 16 |
+
|
| 17 |
+
Adopt Repository Harness from upstream commit `14e6f102a4a645562d046f7c693c61401261cac6`
|
| 18 |
+
with its pinned, checksum-verified Windows CLI v0.1.11. Keep `AGENTS.md` as the
|
| 19 |
+
highest repository-level safety and UX instruction, tailor the Harness to the
|
| 20 |
+
current CarePath contracts, and load the same instructions from `CLAUDE.md`.
|
| 21 |
+
|
| 22 |
+
## Alternatives Considered
|
| 23 |
+
|
| 24 |
+
1. Keep only historical plans and ad-hoc validation notes.
|
| 25 |
+
2. Adopt a documentation-only workflow without durable local records.
|
| 26 |
+
3. Replace the existing CarePath instructions with the generic upstream shim.
|
| 27 |
+
|
| 28 |
+
## Consequences
|
| 29 |
+
|
| 30 |
+
Positive:
|
| 31 |
+
|
| 32 |
+
- New work has explicit risk lanes, proof expectations, and durable traces.
|
| 33 |
+
- Codex and Claude Code share the same project contract.
|
| 34 |
+
- The Harness introduces no product dependencies or CI changes.
|
| 35 |
+
|
| 36 |
+
Tradeoffs:
|
| 37 |
+
|
| 38 |
+
- Agents must perform a small intake and trace step for future work.
|
| 39 |
+
- `harness.db` is local-only, so durable operational records are per clone.
|
| 40 |
+
|
| 41 |
+
## Follow-Up
|
| 42 |
+
|
| 43 |
+
- Upgrade the Harness only as a separately reviewed maintenance task.
|
| 44 |
+
- Register optional tools only when a recurring validation need proves one.
|
docs/decisions/0009-restructure-target-layout.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0009 CarePath Restructure Target Layout
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Superseded in part by 0016
|
| 8 |
+
|
| 9 |
+
> Location update (2026-07-13): the approved Scribe training boundary now
|
| 10 |
+
> resides at `scribe/training/`. The remaining Interpreter and shared-layout
|
| 11 |
+
> decisions in this record remain accepted.
|
| 12 |
+
|
| 13 |
+
## Context
|
| 14 |
+
|
| 15 |
+
CarePath serves two independent clinical workflows from one process, while the
|
| 16 |
+
repository currently places their runtime, frontends, tests, evaluation, and
|
| 17 |
+
training assets in mixed top-level locations. The approved restructure requires
|
| 18 |
+
a durable target layout without changing import names, routes, or safety
|
| 19 |
+
behavior.
|
| 20 |
+
|
| 21 |
+
## Decision
|
| 22 |
+
|
| 23 |
+
Move runtime ownership into `scribe/` and `interpreter/`, and reserve `shared/`
|
| 24 |
+
for the later shared package. Decision 0016 supersedes this record's original
|
| 25 |
+
top-level GEC-training location. Keep the import names `carepath` and `app`,
|
| 26 |
+
keep all public routes unchanged, and retain the root `pyproject.toml` as the
|
| 27 |
+
Scribe distribution. Move the interpreter evaluation harness with
|
| 28 |
+
`interpreter/`; it is not GEC training.
|
| 29 |
+
|
| 30 |
+
Each relocation phase must update path math, packaging, CI, Docker, deployment
|
| 31 |
+
documentation, and the affected product contracts, then pass its relevant
|
| 32 |
+
existing proof before the next phase begins.
|
| 33 |
+
|
| 34 |
+
## Alternatives Considered
|
| 35 |
+
|
| 36 |
+
1. Leave the current mixed top-level layout.
|
| 37 |
+
2. Rename both runtime imports to match their new directory names.
|
| 38 |
+
3. Create separate Python distributions before the relocations.
|
| 39 |
+
|
| 40 |
+
## Consequences
|
| 41 |
+
|
| 42 |
+
Positive:
|
| 43 |
+
|
| 44 |
+
- Runtime and training ownership are visible from the repository layout.
|
| 45 |
+
- Existing imports and public API routes remain stable.
|
| 46 |
+
- The risk-evaluation suite stays with the Interpreter that it validates.
|
| 47 |
+
|
| 48 |
+
Tradeoffs:
|
| 49 |
+
|
| 50 |
+
- Relative path calculations and deployment files must be audited after every move.
|
| 51 |
+
- The Vercel project root setting requires owner action when `scribe/frontend/` moves.
|
| 52 |
+
|
| 53 |
+
## Follow-Up
|
| 54 |
+
|
| 55 |
+
- Record a separate high-risk Harness intake and trace for every phase.
|
| 56 |
+
- Do not begin owner-led clinical-data collection without legal consent and data-handling approval.
|
docs/decisions/0010-shared-normalization-contract.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0010 Shared Normalization Contract
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Interpreter, Scribe scoring, training scoring, and both lexical retrievers
|
| 12 |
+
carried local normalization implementations. Their names overlapped, but their
|
| 13 |
+
contracts differed: the Interpreter normalizes units, Vietnamese number words,
|
| 14 |
+
and relative dates; scoring compares case-insensitively without semantic
|
| 15 |
+
conversion; lexical retrieval additionally folds diacritics and punctuation.
|
| 16 |
+
|
| 17 |
+
## Decision
|
| 18 |
+
|
| 19 |
+
Create the installable `shared/carepath_shared` package. Move the Interpreter
|
| 20 |
+
normalizer there unchanged as `normalize_text`, and make every former local
|
| 21 |
+
normalizer a direct import from this package. Keep the existing scoring and
|
| 22 |
+
retrieval semantics as the separately named `normalize_for_metrics` and
|
| 23 |
+
`normalize_for_match` functions, rather than silently changing metric scores or
|
| 24 |
+
term matching.
|
| 25 |
+
|
| 26 |
+
## Consequences
|
| 27 |
+
|
| 28 |
+
- Normalization algorithms have one owner and one characterization suite.
|
| 29 |
+
- Existing module import paths remain compatible.
|
| 30 |
+
- A future semantic consolidation must explicitly revise the characterization
|
| 31 |
+
suite and evaluation baseline; it is not part of this restructure.
|
docs/decisions/0011-canonical-medical-term-source.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0011 Canonical Medical-Term Source
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Scribe retrieval reads `data/medical_lexicon.json`; Interpreter safety glossary
|
| 12 |
+
seeding reads `interpreter/app/glossary/data/seed_glossary.csv`. Both are
|
| 13 |
+
clinician-editable medical terminology, but their serving schemas differ.
|
| 14 |
+
|
| 15 |
+
## Decision
|
| 16 |
+
|
| 17 |
+
`shared/carepath_shared/terms/medical_terms.json` is the only authored source.
|
| 18 |
+
Each row defines Vietnamese and English terms, kind, aliases, risk flags, and
|
| 19 |
+
target-specific rendering metadata. `scripts/build_term_artifacts.py` emits
|
| 20 |
+
both existing serving artifacts without changing either runtime reader.
|
| 21 |
+
|
| 22 |
+
Interpreter risk lexicons remain independent safety data and are explicitly
|
| 23 |
+
out of scope for this source.
|
| 24 |
+
|
| 25 |
+
## Consequences
|
| 26 |
+
|
| 27 |
+
- Serving paths and schemas stay stable.
|
| 28 |
+
- CI regenerates artifacts and rejects source/artifact drift.
|
| 29 |
+
- Any taxonomy or risk-flag meaning change now requires this decision's
|
| 30 |
+
characterization and safety proof to be revisited.
|
docs/decisions/0012-interpreter-runtime-hardening.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0012 Interpreter Runtime Hardening
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The Interpreter compared admin tokens directly, purged retained sessions only
|
| 12 |
+
at startup, and hard-coded development CORS origins. The combined FastAPI
|
| 13 |
+
service duplicated the standalone Interpreter startup path.
|
| 14 |
+
|
| 15 |
+
## Decision
|
| 16 |
+
|
| 17 |
+
Use `hmac.compare_digest` for the admin token. Give the Interpreter one shared
|
| 18 |
+
lifespan that seeds, purges on startup, runs a daily retention purge task, and
|
| 19 |
+
cancels it on shutdown; the combined service enters the same lifespan. Parse
|
| 20 |
+
CSV `CORS_ORIGINS` through Interpreter settings, with the existing two Vite
|
| 21 |
+
origins as the default.
|
| 22 |
+
|
| 23 |
+
## Consequences
|
| 24 |
+
|
| 25 |
+
- Admin authentication avoids an avoidable timing leak.
|
| 26 |
+
- Retention continues while a process stays up.
|
| 27 |
+
- Standalone and combined Interpreter startup cannot drift.
|
| 28 |
+
- Production operators configure allowed cross-origin development clients via
|
| 29 |
+
`.env`; same-origin deployment remains the default topology.
|
docs/decisions/0013-gec-training-data-governance.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0013 GEC Training Data Governance
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
GEC training previously accepted a dataset name and profile without a durable
|
| 12 |
+
record of its source, consent status, immutable version, or deterministic run
|
| 13 |
+
configuration. Clinical audio is sensitive personal data and cannot be sourced
|
| 14 |
+
or approved by an agent.
|
| 15 |
+
|
| 16 |
+
## Decision
|
| 17 |
+
|
| 18 |
+
Use versioned JSON run configs with fixed seeds and a dataset-manifest reference.
|
| 19 |
+
`run_pipeline.py` refuses every training stage until the referenced manifest has
|
| 20 |
+
owner-approved consent and a non-placeholder SHA-256. Add a text-only frozen
|
| 21 |
+
stratified evaluation fixture with a separate immutable hash; it contains no
|
| 22 |
+
patient audio or identifiers.
|
| 23 |
+
|
| 24 |
+
## Consequences
|
| 25 |
+
|
| 26 |
+
- The agent can validate pipeline governance without collecting clinical data.
|
| 27 |
+
- The owner must complete lawful sourcing, consent, de-identification, and hash
|
| 28 |
+
verification before a real training run.
|
| 29 |
+
- Evaluation categories make drug, dosage, laterality, negation, number, and
|
| 30 |
+
diacritic regressions visible independently.
|
docs/decisions/0014-gec-safety-weighted-regression-gate.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0014 GEC Safety-Weighted Regression Gate
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
Aggregate WER can improve while a correction damages a medication name or a
|
| 12 |
+
dosage. Those errors have a higher clinical cost than ordinary transcription
|
| 13 |
+
differences. The training pipeline also lacked a versioned committed baseline
|
| 14 |
+
that CI could validate without model or GPU dependencies.
|
| 15 |
+
|
| 16 |
+
## Decision
|
| 17 |
+
|
| 18 |
+
Commit a deterministic report for the hashed, text-only frozen GEC fixture.
|
| 19 |
+
Require its report to stay reproducible in CI. A trained adapter must pass the
|
| 20 |
+
existing aggregate gate and, before export, a frozen-fixture gate that rejects
|
| 21 |
+
any regression in `drug_name.term_recall` or
|
| 22 |
+
`dosage.number_unit_preservation` versus raw ASR.
|
| 23 |
+
|
| 24 |
+
## Consequences
|
| 25 |
+
|
| 26 |
+
- Overall WER alone can never approve an adapter that harms drug or dosage
|
| 27 |
+
preservation.
|
| 28 |
+
- CI remains CPU-only: it validates the 12-row fixture, committed report, and
|
| 29 |
+
a fake-adapter export/injected-generation smoke test.
|
| 30 |
+
- A real adapter run still needs the owner-approved training manifest and an
|
| 31 |
+
available GPU; this policy does not authorize data collection or training.
|
docs/decisions/0015-soap-note-measurement-gate.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0015 SOAP Note Measurement Gate
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The Scribe SOAP output uses a hosted clinical LLM with an offline fallback.
|
| 12 |
+
There is no legitimate basis to train or tune it from invented examples, and no
|
| 13 |
+
clinical rating protocol existed to distinguish missing content, hallucination,
|
| 14 |
+
and terminology errors.
|
| 15 |
+
|
| 16 |
+
## Decision
|
| 17 |
+
|
| 18 |
+
Before any SOAP fine-tuning decision, the owner must obtain at least 50
|
| 19 |
+
de-identified pilot notes rated by clinicians under the documented rubric.
|
| 20 |
+
The repository holds only a blank rating schema and a validator that accepts
|
| 21 |
+
anonymous rating metadata; it must never hold source audio, transcripts,
|
| 22 |
+
patient identifiers, or note text.
|
| 23 |
+
|
| 24 |
+
## Consequences
|
| 25 |
+
|
| 26 |
+
- The agent can make the measurement process reproducible without simulating
|
| 27 |
+
clinical evidence.
|
| 28 |
+
- A rating summary makes serious hallucinations and unsafe dispositions visible
|
| 29 |
+
to the owner before choosing training, retrieval, prompting, or no change.
|
| 30 |
+
- The clinical-data study, ratings, and any subsequent model decision remain
|
| 31 |
+
owner-led and require an approved environment.
|
docs/decisions/0016-scribe-training-ownership.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 0016 Scribe Training Ownership
|
| 2 |
+
|
| 3 |
+
Date: 2026-07-13
|
| 4 |
+
|
| 5 |
+
## Status
|
| 6 |
+
|
| 7 |
+
Accepted
|
| 8 |
+
|
| 9 |
+
## Context
|
| 10 |
+
|
| 11 |
+
The offline DARAG/GEC training code, fixtures, reports, notebooks, and scripts
|
| 12 |
+
already support the Scribe's Vietnamese clinical-note workflow. The top-level
|
| 13 |
+
`training/` directory obscures that ownership and risks being confused with the
|
| 14 |
+
Interpreter's safety evaluation harness at `interpreter/eval/`.
|
| 15 |
+
|
| 16 |
+
## Decision
|
| 17 |
+
|
| 18 |
+
Move the complete offline training boundary to `scribe/training/`. It contains
|
| 19 |
+
the GEC package, configs, fixtures, manifests, reports, notebooks, scripts,
|
| 20 |
+
tests, and SOAP measurement tooling. `interpreter/eval/` remains the
|
| 21 |
+
Interpreter's independent safety regression harness.
|
| 22 |
+
|
| 23 |
+
The Scribe serving package at `scribe/carepath/` must not import training code;
|
| 24 |
+
the production image copies only the Scribe runtime package, not
|
| 25 |
+
`scribe/training/`. Training keeps its standalone `gec.*` command-line import
|
| 26 |
+
boundary without adding a distribution or dependency.
|
| 27 |
+
|
| 28 |
+
This supersedes only the top-level training-location portion of decision 0009.
|
| 29 |
+
|
| 30 |
+
## Consequences
|
| 31 |
+
|
| 32 |
+
- Training commands and CI use `scribe/training/...` paths.
|
| 33 |
+
- Runtime packaging stays independent of offline model-development artifacts.
|
| 34 |
+
- The repository has a visibly separate Scribe training boundary and
|
| 35 |
+
Interpreter safety-evaluation boundary.
|
docs/decisions/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Decisions
|
| 2 |
+
|
| 3 |
+
Decision records explain why important product, architecture, or harness choices
|
| 4 |
+
were made.
|
| 5 |
+
|
| 6 |
+
Use `docs/templates/decision.md` when adding a new decision.
|
| 7 |
+
|
| 8 |
+
After adding or updating a markdown decision file, also add or refresh the
|
| 9 |
+
durable decision row:
|
| 10 |
+
|
| 11 |
+
```bash
|
| 12 |
+
scripts/bin/harness-cli decision add \
|
| 13 |
+
--id 0008-auth-boundary \
|
| 14 |
+
--title "Auth Boundary" \
|
| 15 |
+
--doc docs/decisions/0008-auth-boundary.md
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
Trace fields such as `--decisions` summarize task-level choices. They do not
|
| 19 |
+
count as the Harness decision log.
|
| 20 |
+
|
| 21 |
+
Add a decision when:
|
| 22 |
+
|
| 23 |
+
- A locked technical choice changes.
|
| 24 |
+
- A product rule changes meaningfully.
|
| 25 |
+
- A validation requirement is added, removed, or weakened.
|
| 26 |
+
- A high-risk feature chooses one design over another.
|
| 27 |
+
- Auth, authorization, data ownership, audit/security, or API behavior changes.
|
| 28 |
+
- The source-of-truth hierarchy changes.
|
docs/deploy.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Unified Deploy
|
| 2 |
+
|
| 3 |
+
Use `https://carepath-omega.vercel.app` as the public Scribe site. One Hugging
|
| 4 |
+
Face Space runs the Scribe tool at `/ghi-chep-lam-sang/`, the Scribe API at
|
| 5 |
+
`/api/v1/*`, and the retained Interpreter API at `/api/*` + `/ws/*`.
|
| 6 |
+
`/phien-dich-y-khoa/*` and `/console/*` are intentionally public 404s while
|
| 7 |
+
the Interpreter remains in development.
|
| 8 |
+
|
| 9 |
+
## Hugging Face Space
|
| 10 |
+
|
| 11 |
+
Reuse the existing Docker Space
|
| 12 |
+
[`tranth3truong/carepath-api`](https://huggingface.co/spaces/tranth3truong/carepath-api),
|
| 13 |
+
served at `https://tranth3truong-carepath-api.hf.space`. Deploy this unified
|
| 14 |
+
repository there; it retains the Interpreter API but does not serve the
|
| 15 |
+
unfinished Interpreter browser workflow.
|
| 16 |
+
|
| 17 |
+
1. Rebuild the existing `tranth3truong/carepath-api` Space with **Docker** as
|
| 18 |
+
the SDK. Create a replacement only if that Space is no longer available.
|
| 19 |
+
2. Copy `README.hf-space.md` to the Space as `README.md` so the Space has:
|
| 20 |
+
|
| 21 |
+
```yaml
|
| 22 |
+
---
|
| 23 |
+
title: CarePath
|
| 24 |
+
sdk: docker
|
| 25 |
+
app_port: 7860
|
| 26 |
+
---
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
3. Push this repo to the Space. The root `Dockerfile` builds `scribe/frontend/` and
|
| 30 |
+
`interpreter/frontend/` in a node stage (the site build enforces the Vietnamese
|
| 31 |
+
diacritics gate), installs both API packages, pre-downloads the Gipformer
|
| 32 |
+
int8 ONNX files, and starts Uvicorn on port `7860`.
|
| 33 |
+
Set the Docker build arg `VITE_PUBLIC_SITE_URL=https://carepath-omega.vercel.app`
|
| 34 |
+
so the Interpreter's “Tất cả chức năng” link returns to the public site
|
| 35 |
+
with the selected language.
|
| 36 |
+
4. Set these Space secrets:
|
| 37 |
+
|
| 38 |
+
```text
|
| 39 |
+
LLM_PROVIDER=ckey
|
| 40 |
+
LLM_API_KEY=<your CKey key>
|
| 41 |
+
LLM_MODEL=gpt-5.4
|
| 42 |
+
TEAM_CODE=<shared internal demo code>
|
| 43 |
+
SOAP_RATE_LIMIT_PER_IP_HOUR=3
|
| 44 |
+
SOAP_RATE_LIMIT_PER_IP_DAY=10
|
| 45 |
+
SOAP_RATE_LIMIT_GLOBAL_DAY=100
|
| 46 |
+
APP_ENV=prod
|
| 47 |
+
CORS_ORIGINS=https://carepath-omega.vercel.app
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
The interpreter module runs in mock mode by default and needs no secrets.
|
| 51 |
+
When its cloud track lands, it will additionally need `PROVIDER_MODE=cloud`,
|
| 52 |
+
`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and a non-default `ADMIN_TOKEN`
|
| 53 |
+
(startup refuses `change-me` in cloud mode).
|
| 54 |
+
|
| 55 |
+
The Vercel site uploads Scribe audio directly to the Space, so its exact origin
|
| 56 |
+
must be present in `CORS_ORIGINS`. Add local Vite origins as comma-separated
|
| 57 |
+
values only when testing local frontends against the deployed API.
|
| 58 |
+
|
| 59 |
+
Requests with header `X-Team-Code: <TEAM_CODE>` bypass the SOAP rate limits
|
| 60 |
+
for internal doctor-comparison runs. Limited requests return HTTP `429`,
|
| 61 |
+
`Retry-After`, and JSON body
|
| 62 |
+
`{"detail":{"message":"...","retry_after_seconds":3600}}` — the Scribe tool
|
| 63 |
+
surfaces that message to the user.
|
| 64 |
+
|
| 65 |
+
## Local Docker Check
|
| 66 |
+
|
| 67 |
+
```powershell
|
| 68 |
+
docker build -t carepath .
|
| 69 |
+
docker run --rm -p 7860:7860 `
|
| 70 |
+
-e LLM_PROVIDER=ckey `
|
| 71 |
+
-e "LLM_API_KEY=$env:LLM_API_KEY" `
|
| 72 |
+
-e LLM_MODEL=gpt-5.4 `
|
| 73 |
+
-e APP_ENV=prod `
|
| 74 |
+
carepath
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
Keyless variant (mock ASR + offline LLM + mock interpreter — must also work):
|
| 78 |
+
|
| 79 |
+
```powershell
|
| 80 |
+
docker run --rm -p 7860:7860 `
|
| 81 |
+
-e ASR_PROVIDER=mock -e ALLOW_MOCK_ASR=true -e LLM_PROVIDER=offline `
|
| 82 |
+
carepath
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
In another terminal:
|
| 86 |
+
|
| 87 |
+
```powershell
|
| 88 |
+
curl.exe http://127.0.0.1:7860/api/v1/health
|
| 89 |
+
curl.exe http://127.0.0.1:7860/api/health
|
| 90 |
+
curl.exe -o NUL -w "%{http_code}`n" http://127.0.0.1:7860/
|
| 91 |
+
curl.exe -o NUL -w "%{http_code}`n" http://127.0.0.1:7860/ghi-chep-lam-sang/
|
| 92 |
+
curl.exe -o NUL -w "%{http_code}`n" http://127.0.0.1:7860/phien-dich-y-khoa/
|
| 93 |
+
curl.exe -X POST http://127.0.0.1:7860/api/v1/soap-notes `
|
| 94 |
+
-F "audio=@C:\path\to\demo.wav" `
|
| 95 |
+
-F "encounter_context=Phòng khám nội tổng quát"
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
## Canonical Vercel site
|
| 99 |
+
|
| 100 |
+
The `scribe/frontend/` directory is the static marketing deployment at
|
| 101 |
+
`https://carepath-omega.vercel.app`:
|
| 102 |
+
|
| 103 |
+
1. In the Vercel project settings, change **Root Directory** from the removed
|
| 104 |
+
`apps/web-next` to `scribe/frontend` (framework/build/output come from
|
| 105 |
+
`scribe/frontend/vercel.json`).
|
| 106 |
+
2. Set these Vercel environment variables:
|
| 107 |
+
|
| 108 |
+
```text
|
| 109 |
+
VITE_API_BASE=https://tranth3truong-carepath-api.hf.space
|
| 110 |
+
VITE_CONSOLE_URL=https://tranth3truong-carepath-api.hf.space/phien-dich-y-khoa/
|
| 111 |
+
VITE_LEAD_ENDPOINT=<optional lead endpoint>
|
| 112 |
+
VITE_LEAD_EMAIL=<pilot contact email>
|
| 113 |
+
```
|
| 114 |
+
|
| 115 |
+
3. Confirm the Space contains the Vercel origin configured above. Do not add
|
| 116 |
+
Vercel API or WebSocket rewrites; the Space owns those routes.
|
| 117 |
+
|
| 118 |
+
The Vercel build runs `npm run validate:deploy` before compiling. It fails when
|
| 119 |
+
either URL is missing or invalid, does not use HTTPS, uses a different origin,
|
| 120 |
+
contains a query/fragment, or does not use the exact `/` and `/phien-dich-y-khoa/`
|
| 121 |
+
pathnames. Local
|
| 122 |
+
and combined-service builds still use same-origin fallbacks because the normal
|
| 123 |
+
`npm run build` does not run this deployment-only check.
|
| 124 |
+
|
| 125 |
+
The Interpreter backend stays on the Space because it needs the WebSocket API,
|
| 126 |
+
but its browser frontend is disabled. `VITE_CONSOLE_URL` remains a build-time
|
| 127 |
+
compatibility setting until the public-site validation is simplified. The pilot
|
| 128 |
+
form remains client-side unless `VITE_LEAD_ENDPOINT` is configured.
|
| 129 |
+
|
| 130 |
+
## Keep-Alive
|
| 131 |
+
|
| 132 |
+
The workflow in `.github/workflows/keepalive.yml` pings the Space every 12
|
| 133 |
+
hours. Set the GitHub repository variable:
|
| 134 |
+
|
| 135 |
+
```text
|
| 136 |
+
SPACE_URL=https://tranth3truong-carepath-api.hf.space
|
| 137 |
+
```
|
| 138 |
+
|
| 139 |
+
Then run **Actions > Keep HF Space Awake > Run workflow** once and confirm the
|
| 140 |
+
job succeeds.
|
| 141 |
+
|
| 142 |
+
## Final Smoke
|
| 143 |
+
|
| 144 |
+
1. Open the Space URL: the CarePath landing renders, Vietnamese by default.
|
| 145 |
+
2. Run the scripted interpreter simulation on the landing.
|
| 146 |
+
3. Open `/ghi-chep-lam-sang/`, upload a short clip, and verify the SOAP draft renders
|
| 147 |
+
with the review banner.
|
| 148 |
+
4. Confirm `/phien-dich-y-khoa/` and `/console/` return HTTP 404.
|
| 149 |
+
5. Confirm `GET /api/v1/health` reports `llm_provider: ckey` and
|
| 150 |
+
`asr_ready: true`, and `GET /api/health` reports `provider_mode: mock`.
|
docs/history/DEMO-SITE-PLAN.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Interpreter — Demo Website Plan
|
| 2 |
+
|
| 3 |
+
A public demo/marketing site for the product. Separate track from PLAN.md (the product);
|
| 4 |
+
do not touch `backend/` or `frontend/` for this work. Everything lives in a new `/site`
|
| 5 |
+
folder. Read [docs/research.md](docs/research.md) for the evidence base the copy draws on.
|
| 6 |
+
|
| 7 |
+
**Executor:** codex-5.5 (xhigh). Work tickets S.0 → S.7 in order, one commit per ticket,
|
| 8 |
+
same conventions as AGENTS.md. All copy that appears in Vietnamese MUST have full
|
| 9 |
+
diacritics — this is a hard rule (see AGENTS.md).
|
| 10 |
+
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
## 1. Purpose, audience, and the one metric
|
| 14 |
+
|
| 15 |
+
The site convinces **Vietnamese clinic owners and hospital administrators** (secondary:
|
| 16 |
+
pilot clinicians, investors) that CarePath is a safe, compliant way to run consultations
|
| 17 |
+
with English-speaking patients — and converts them into **pilot-program requests**.
|
| 18 |
+
One conversion goal: the "Đăng ký thí điểm" (Request a pilot) form. Everything on the
|
| 19 |
+
page exists to move a skeptical healthcare buyer toward that form.
|
| 20 |
+
|
| 21 |
+
Language: **Vietnamese default, English toggle** (persist choice in localStorage).
|
| 22 |
+
|
| 23 |
+
## 2. Architecture (decided)
|
| 24 |
+
|
| 25 |
+
- **Static site, no backend.** New `/site` folder: Vite + React 18 + TypeScript — same
|
| 26 |
+
stack and lint rules as `frontend/`, but an independent app (own package.json). Output
|
| 27 |
+
is plain static files deployable to any host (GitHub Pages/Netlify/nginx).
|
| 28 |
+
- **The interactive demo is a scripted, client-only simulation.** It replays canned
|
| 29 |
+
consultation turns that reproduce the real product UX (push-to-talk feel, bilingual
|
| 30 |
+
transcript, risk highlighting, read-back confirmation, escalation button). No real
|
| 31 |
+
ASR/MT calls, no API keys, no audio recording, no PHI — the browser never captures
|
| 32 |
+
the mic. Seed the scripts from `eval/fixtures/eval_starter.tsv` scenarios (they are
|
| 33 |
+
already clinically shaped and bilingual).
|
| 34 |
+
- **Lead capture without a server:** the pilot-request form POSTs to a configurable
|
| 35 |
+
`VITE_LEAD_ENDPOINT`; when unset, it falls back to a prefilled `mailto:` link. Mark
|
| 36 |
+
this as the single integration point. Store nothing in the browser beyond the form
|
| 37 |
+
draft.
|
| 38 |
+
- Simple i18n: one `strings.ts` dictionary module (`vi`/`en` keys), no i18n library.
|
| 39 |
+
- No analytics, no cookies, no tracking in MVP. A comment marks where a privacy-safe
|
| 40 |
+
counter could go later.
|
| 41 |
+
|
| 42 |
+
## 3. Honesty guardrails (non-negotiable)
|
| 43 |
+
|
| 44 |
+
The product's brand IS safety. The site models the same honesty the app enforces:
|
| 45 |
+
|
| 46 |
+
1. The demo is clearly labeled as a simulation: "Bản mô phỏng — không phải bản dịch
|
| 47 |
+
trực tiếp" visible while the demo plays.
|
| 48 |
+
2. Never claim autonomy or diagnosis. The tagline space says *translation-and-
|
| 49 |
+
verification aid with human-interpreter escalation* — mirror AGENTS.md invariant 1.
|
| 50 |
+
3. Banned patterns: fake urgency ("only 3 pilot slots left!"), fake scarcity, countdown
|
| 51 |
+
timers, guilt-trip copy ("No thanks, I prefer miscommunication"), pre-checked
|
| 52 |
+
marketing-consent boxes, hidden pricing.
|
| 53 |
+
4. Every statistic shown must come from docs/research.md and carry its citation in a
|
| 54 |
+
tooltip/footnote (e.g., 40–80% of verbal medical information is immediately
|
| 55 |
+
forgotten — Kessels 2003; up to 66% of MT'd discharge-instruction sets contained
|
| 56 |
+
an inaccuracy — BMJ Qual Saf 2025).
|
| 57 |
+
5. Loss-aversion and contrast framing must be factual (real costs, real risks), never
|
| 58 |
+
fabricated numbers. Pricing figures are placeholders marked `TODO-pricing` for the
|
| 59 |
+
founder to fill; do not invent prices presented as real.
|
| 60 |
+
|
| 61 |
+
## 4. Page architecture — each section wired to a persuasion principle
|
| 62 |
+
|
| 63 |
+
Single long-scroll landing page + the embedded demo. Section order is the persuasion
|
| 64 |
+
sequence; the six principles are design mechanics, not decoration:
|
| 65 |
+
|
| 66 |
+
| # | Section | Principle applied | Mechanic |
|
| 67 |
+
|---|---|---|---|
|
| 68 |
+
| 1 | **Hero** | Reciprocity | Value before any ask: headline + the live demo sits above the fold, playable immediately. No form, no email gate anywhere before section 7. CTA: "Xem demo 90 giây" scrolls into the demo. |
|
| 69 |
+
| 2 | **Interactive demo** | Smart defaults + Goal gradient + IKEA | See §5. Scenario pre-selected and pre-loaded (smart default: "Khám ngoại trú — kê đơn thuốc", the most relatable case). A 4-step progress rail starts with step 1 already checked: "✓ Kịch bản đã chọn" — the visitor begins at 25%, not zero. Customization panel (IKEA): clinic name, specialty, scenario choice — reflected live in the demo header ("Phòng khám Đa khoa An Bình — Demo"). |
|
| 70 |
+
| 3 | **The problem** | Loss aversion (ethical) | What clinics lose *today*: cited stats on miscommunication (research §Exec Summary), the cost/scarcity of qualified interpreters, compliance exposure. Frame: "Mỗi lượt khám không được phiên dịch đúng là một rủi ro bạn đang gánh" — protecting what they have (patients, reputation, license), not threatening to take features away. |
|
| 71 |
+
| 4 | **Safety by design** | Trust builder (no trick) | The product's differentiator. Render the real safety mechanics as cards: read-back confirmation, risk highlighting, low-confidence flagging, one-tap interpreter escalation, no-audio-storage privacy mode. Copy source: PLAN.md §2 invariants, translated for a non-technical buyer. |
|
| 72 |
+
| 5 | **How it works** | — | 3 illustrated steps (speak → verify → confirm), one line each. |
|
| 73 |
+
| 6 | **Cost framing** | Contrast effect (ethical) | Anchor with the true, cited costs of the status quo: full-time bilingual staff or per-visit professional interpreter rates, and the cost of a single adverse event. Then the pilot offer (placeholder `TODO-pricing`). The anchor numbers must be real and sourced — contrast through honest arithmetic, not a fake slashed price. |
|
| 74 |
+
| 7 | **Pilot CTA + form** | Reciprocity + IKEA + Loss aversion payoff | By now the visitor has used the demo and customized it. Form headline: "Giữ lại bản demo bạn vừa tạo" — submitting sends them their configured demo transcript (attach the transcript text into the form payload). Fields: name, clinic, role, email/Zalo, pre-filled message (smart default) summarizing their chosen scenario. ≤5 fields. |
|
| 75 |
+
| 8 | **Footer** | — | Compliance posture line (Decree 13/PDP-aware design, §1557-aligned positioning), AI-use honesty statement, contact. |
|
| 76 |
+
|
| 77 |
+
## 5. The interactive demo spec (the heart of the site)
|
| 78 |
+
|
| 79 |
+
A `DemoPlayer` component simulating one consultation:
|
| 80 |
+
|
| 81 |
+
- **Scenario scripts:** 3 scripted conversations (JSON in `site/src/demo/scenarios/`),
|
| 82 |
+
~8 turns each, adapted from eval fixtures: (a) prescription + dosage (default),
|
| 83 |
+
(b) allergy check with a negation moment, (c) chest-pain red flag → escalation.
|
| 84 |
+
Each turn: speaker, Vietnamese text, English text, risk tier, risk spans, and for
|
| 85 |
+
high/critical turns a read-back payload (entities: drug/dose/frequency/negation).
|
| 86 |
+
- **Playback:** turns appear one-by-one with a typing/speaking animation and a subtle
|
| 87 |
+
push-to-talk button pulse (autoplay ~4s per turn; controls: play/pause, next, replay).
|
| 88 |
+
Visitor can also click "Thử tự gõ" to type one custom line that gets echoed into the
|
| 89 |
+
transcript with a canned translation — participation, not real MT (label it).
|
| 90 |
+
- **The safety moment is the hero moment:** when the dosage/allergy turn arrives,
|
| 91 |
+
playback *stops*, the read-back confirmation card slides in (real product styling:
|
| 92 |
+
entity table, Confirm / Edit / Escalate), and the progress rail advances only when
|
| 93 |
+
the visitor clicks Confirm. In scenario (c), the red-flag turn triggers the
|
| 94 |
+
full-screen escalation banner exactly like the product.
|
| 95 |
+
- **Progress rail (goal gradient):** `✓ Kịch bản` → `Nghe hội thoại` → `Xác nhận
|
| 96 |
+
read-back` → `Nhận bản ghi`. Step 4 unlocks a "Tải bản ghi demo" button (downloads
|
| 97 |
+
the bilingual transcript as a formatted .txt/.html — the free cookie they keep).
|
| 98 |
+
- Visual fidelity: match the real product's transcript layout and risk badge colors
|
| 99 |
+
(lift the palette from `frontend/src/App.css`) so the demo IS the product, not a
|
| 100 |
+
cartoon of it.
|
| 101 |
+
|
| 102 |
+
## 6. Design direction
|
| 103 |
+
|
| 104 |
+
- Clinical-trust aesthetic: calm, spacious, high contrast; one accent color for risk/
|
| 105 |
+
CTA moments; light + dark theme. No stock-photo doctors, no purple-gradient AI slop,
|
| 106 |
+
no emoji in headings. Vietnamese typography checked with real diacritics at display
|
| 107 |
+
sizes (choose a font that renders Vietnamese well — e.g. Be Vietnam Pro, self-hosted).
|
| 108 |
+
- Responsive: the demo must work on a phone (clinic owners will open this from Zalo).
|
| 109 |
+
- Accessibility is part of the pitch: WCAG AA contrast, full keyboard path through the
|
| 110 |
+
demo, `prefers-reduced-motion` respected (no autoplay animation), semantic landmarks.
|
| 111 |
+
- Performance: static, self-hosted font subset, no external requests at runtime except
|
| 112 |
+
the lead endpoint on submit. Lighthouse ≥95 performance/accessibility/best-practices.
|
| 113 |
+
|
| 114 |
+
## 7. Tickets
|
| 115 |
+
|
| 116 |
+
- **S.0 Scaffold.** `/site` Vite React-TS app, eslint config copied from frontend,
|
| 117 |
+
`npm run dev/build/test`, README section. Commit this plan file with it.
|
| 118 |
+
*Accept:* `npm run build` outputs static files; CI-ready.
|
| 119 |
+
- **S.1 Demo engine.** Scenario JSON schema + 3 scripts + `DemoPlayer` with playback,
|
| 120 |
+
read-back stop, escalation moment, progress rail, transcript download. *Tests:*
|
| 121 |
+
vitest — playback advances, confirmation gates progress, download produces bilingual
|
| 122 |
+
content; scripts validated against the schema.
|
| 123 |
+
- **S.2 Page sections.** Sections 1, 3–6, 8 with bilingual copy (research-cited stats
|
| 124 |
+
with footnotes; `TODO-pricing` placeholders). *Accept:* full page renders in vi + en;
|
| 125 |
+
no diacritic-stripped Vietnamese anywhere (add a test that greps built output for
|
| 126 |
+
the corrected consent-style strings).
|
| 127 |
+
- **S.3 Persuasion wiring.** Smart-default scenario preselection, customization panel
|
| 128 |
+
(clinic name/specialty live in demo header), form pre-fill from demo state, "keep
|
| 129 |
+
your demo" transcript attach. *Tests:* customization propagates; form payload
|
| 130 |
+
contains scenario summary.
|
| 131 |
+
- **S.4 Language toggle.** `strings.ts`, vi default, persisted choice, `<html lang>`
|
| 132 |
+
switches. *Tests:* toggle flips all sections.
|
| 133 |
+
- **S.5 Lead form.** `VITE_LEAD_ENDPOINT` POST with mailto fallback, ≤5 fields, inline
|
| 134 |
+
validation, success state, zero persistence beyond the draft. *Tests:* endpoint mode
|
| 135 |
+
+ fallback mode.
|
| 136 |
+
- **S.6 A11y + e2e.** Keyboard-only Playwright run through the whole demo flow to form
|
| 137 |
+
success; reduced-motion snapshot; axe-core pass with no serious violations.
|
| 138 |
+
- **S.7 CI.** New `site` job: lint, test, build, run the S.6 e2e against `vite preview`.
|
| 139 |
+
*Accept:* CI green end to end.
|
| 140 |
+
|
| 141 |
+
## 8. Non-goals
|
| 142 |
+
|
| 143 |
+
No real translation calls, no account system, no CMS, no blog, no analytics, no A/B
|
| 144 |
+
testing framework, no multi-page router (one page + anchors), no video production
|
| 145 |
+
(the scripted demo replaces a demo video). Pricing numbers are founder input, not
|
| 146 |
+
codex's to invent.
|
docs/history/JUDGE.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# JUDGE.md — claude-fable-5 review protocol for the CarePath unification
|
| 2 |
+
|
| 3 |
+
**Who runs this:** claude-fable-5, in a fresh session, after codex finishes MERGE-PLAN.md.
|
| 4 |
+
**What is judged:** the `carepath-unified` branch, ticket commits M.0 → M.8.
|
| 5 |
+
**Baselines for comparison:** `origin/main` (scriber contract) and
|
| 6 |
+
`origin/carepath-interpreter-demo` (interpreter behavior + S.8 design).
|
| 7 |
+
|
| 8 |
+
Judge the work, not the plan. If MERGE-PLAN.md itself turns out to be wrong somewhere
|
| 9 |
+
and codex deviated for a good, documented reason, that is acceptable — say so explicitly
|
| 10 |
+
in the verdict instead of failing the ticket.
|
| 11 |
+
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
## 1. Hard gates — any failure ⇒ overall NEEDS WORK
|
| 15 |
+
|
| 16 |
+
Run every gate. Report each as PASS / FAIL with evidence (command output, file:line).
|
| 17 |
+
|
| 18 |
+
### G1. Everything green
|
| 19 |
+
|
| 20 |
+
Run the full Verify inventory (MERGE-PLAN.md §3) on a clean checkout of
|
| 21 |
+
`carepath-unified`:
|
| 22 |
+
|
| 23 |
+
```text
|
| 24 |
+
pip install -e ".[dev]" -e "./backend[dev]" # one Python 3.12 venv
|
| 25 |
+
pytest # root (scriber + combined-app test)
|
| 26 |
+
python scripts/smoke_backend.py
|
| 27 |
+
cd backend && ruff check . && pytest && cd ..
|
| 28 |
+
python eval/run_eval.py --set eval/fixtures/eval_starter.tsv --providers mock
|
| 29 |
+
cd frontend && npm ci && npm run lint && npm test && cd ..
|
| 30 |
+
cd site && npm ci && npm run lint && npm test && npm run build && cd ..
|
| 31 |
+
# e2e (needs built app / mock backend per ci.yml):
|
| 32 |
+
cd frontend && npm run e2e ; cd ../site && npm run e2e
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
### G2. Scriber API contract frozen
|
| 36 |
+
|
| 37 |
+
The deployed HF Space clients must not break:
|
| 38 |
+
|
| 39 |
+
```text
|
| 40 |
+
git diff origin/main carepath-unified -- apps/api/carepath/schemas.py
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
Schema diff must be empty (or provably additive-only). Then compare every `/api/v1/*`
|
| 44 |
+
route signature, status codes, and rate-limit/TEAM_CODE behavior in
|
| 45 |
+
`apps/api/carepath/main.py` against `origin/main` — changes must be additions
|
| 46 |
+
(interpreter routers, static mounts, lifespan additions), never modifications to
|
| 47 |
+
existing scriber behavior.
|
| 48 |
+
|
| 49 |
+
### G3. Safety invariants intact (AGENTS.md §2 / MERGE-PLAN.md §2)
|
| 50 |
+
|
| 51 |
+
Audit with greps + targeted reads on the merged tree:
|
| 52 |
+
|
| 53 |
+
1. **No raw-audio persistence** in the interpreter path: no audio columns in
|
| 54 |
+
`backend/app/crud.py` models, no `tempfile`/disk writes of turn audio in
|
| 55 |
+
`backend/app/session.py` or `api.py`. (The scriber's documented tempfile
|
| 56 |
+
normalization of *uploaded clips* on `origin/main` is pre-existing and allowed.)
|
| 57 |
+
2. **Consent before mic**: every `getUserMedia` call site in `frontend/` and `site/`
|
| 58 |
+
(including the new scribe view) is gated behind the consent flow.
|
| 59 |
+
3. **Risk blocking**: high/critical turns still blocked pre-confirmation — spot-check
|
| 60 |
+
`backend/app/session.py` + `frontend/src/components/InterpreterConsole.tsx` are
|
| 61 |
+
unchanged from the interpreter branch (or changed only for import/serving reasons).
|
| 62 |
+
4. **Fail-closed**: pipeline error paths in `backend/app/api.py` unchanged.
|
| 63 |
+
5. **No advice generation** introduced anywhere in new copy or code.
|
| 64 |
+
6. **Diacritics**: `site/` build gate ran; spot-check new Vietnamese copy (Scribe
|
| 65 |
+
section, error messages) for full diacritics.
|
| 66 |
+
|
| 67 |
+
### G4. Keyless boot
|
| 68 |
+
|
| 69 |
+
With **no** API keys in the environment (`PROVIDER_MODE=mock`, `ASR_PROVIDER=mock`,
|
| 70 |
+
`ALLOW_MOCK_ASR=true`, `LLM_PROVIDER=offline`): the combined uvicorn app boots and
|
| 71 |
+
serves `/api/health`, `/api/v1/health`, a mock `POST /api/v1/soap-notes`, a created
|
| 72 |
+
interpreter session + WebSocket handshake, and (if dists are built) `/` and `/console/`.
|
| 73 |
+
|
| 74 |
+
### G5. Retirement + hygiene
|
| 75 |
+
|
| 76 |
+
- `git ls-files apps/web apps/web-next` → empty.
|
| 77 |
+
- `grep -ri "carepath translate" site/src docs README.md` → empty.
|
| 78 |
+
- No secrets/keys anywhere in `git diff origin/main...carepath-unified`.
|
| 79 |
+
- Root `package-lock.json` orphan (if still present without a root `package.json`) —
|
| 80 |
+
flag for deletion.
|
| 81 |
+
- `.env.example` documents both products; defaults match the keyless demo profile.
|
| 82 |
+
|
| 83 |
+
## 2. Scored review — 1 (poor) to 5 (excellent) each
|
| 84 |
+
|
| 85 |
+
| Dimension | What 5 looks like |
|
| 86 |
+
|---|---|
|
| 87 |
+
| Brand/UI consistency | Landing, scribe view, and console read as one product on the S.8 design system; logo/name unified; no leftover Translate branding or old apps/web styling. |
|
| 88 |
+
| Code quality | Matches AGENTS.md conventions (ruff, TS strict, small components, data-not-code lexicons); no copy-paste from app.js left un-Reactified; no dead code. |
|
| 89 |
+
| Commit hygiene | Exactly one commit per ticket, M.0→M.8 in order, subjects match, bodies explain any deviation from the plan. |
|
| 90 |
+
| Minimalism | No unrequested abstractions, no new deps beyond plan, hash route not a router lib, mounts/env kept simple. |
|
| 91 |
+
|
| 92 |
+
## 3. Verdict format
|
| 93 |
+
|
| 94 |
+
1. **Per-ticket table**: ticket · commit sha · gates touched · PASS / NEEDS WORK · one-line note.
|
| 95 |
+
2. **Hard-gate table**: G1–G5 with evidence.
|
| 96 |
+
3. **Scores** with one sentence each.
|
| 97 |
+
4. **Overall: PASS or NEEDS WORK.** If NEEDS WORK: a numbered, codex-executable fix
|
| 98 |
+
list — each item states the file, the defect, the expected behavior, and which gate
|
| 99 |
+
it unblocks. No vague items.
|
docs/history/MERGE-PLAN.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CarePath Unification Plan — merge Scriber + Interpreter into one product
|
| 2 |
+
|
| 3 |
+
**Executor:** codex-5.6 terra (fallback: codex-5.5 xhigh). Work tickets M.0 → M.8 in
|
| 4 |
+
order, **one commit per ticket**, commit subject `M.x <imperative summary>`. Every
|
| 5 |
+
ticket ends green: run that ticket's Verify list before committing. If a Verify step
|
| 6 |
+
fails, fix it inside the same ticket — never commit red, never skip ahead.
|
| 7 |
+
|
| 8 |
+
**Judge:** after M.8, claude-fable-5 reviews the branch against `JUDGE.md`. Anything
|
| 9 |
+
that fails a hard gate there comes back as a fix list — save everyone a round trip by
|
| 10 |
+
running the gates yourself first.
|
| 11 |
+
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
## 1. What is being merged
|
| 15 |
+
|
| 16 |
+
The repo holds two products with **unrelated git histories**:
|
| 17 |
+
|
| 18 |
+
| | Scriber (`origin/main`) | Interpreter (`origin/carepath-interpreter-demo`) |
|
| 19 |
+
|---|---|---|
|
| 20 |
+
| Backend | `apps/api/carepath` FastAPI: `/api/v1/health`, `/api/v1/corrections`, `/api/v1/soap-notes` | `backend/app` FastAPI: `/api/*` REST + `/ws/sessions/{id}` WebSocket, risk engine, admin review |
|
| 21 |
+
| ASR / LLM | Gipformer ONNX (local, keyless) + ckey OpenAI-compatible LLM. **Deployed, working** (HF Space Docker) | OpenAI + Anthropic cloud providers (no keys) → **mock mode only** |
|
| 22 |
+
| Frontends | `apps/web` (static tool), `apps/web-next` (Next.js landing) | `frontend/` (interpreter console), `site/` (marketing demo site — the S.8 clinical redesign) |
|
| 23 |
+
|
| 24 |
+
Target: **one product, "CarePath"**, on branch `carepath-unified`:
|
| 25 |
+
|
| 26 |
+
1. **One FastAPI service** (single deploy): scriber routes stay at `/api/v1/*`,
|
| 27 |
+
interpreter routes at `/api/*` + `/ws/*`, one combined lifespan.
|
| 28 |
+
2. **Interpreter stays mock-only for now.** Do not touch the provider abstraction or
|
| 29 |
+
wire new providers. Real interpreter providers are a later, separate track.
|
| 30 |
+
3. **`site/` becomes the entire public face**, rebranded "CarePath Translate" →
|
| 31 |
+
"CarePath" with two modules: **Interpreter** and **Scribe**. The newer branch's
|
| 32 |
+
UI/UX (logos, design system) wins everywhere. `apps/web` and `apps/web-next` are
|
| 33 |
+
retired.
|
| 34 |
+
4. **Histories are preserved** via `git merge --allow-unrelated-histories`.
|
| 35 |
+
|
| 36 |
+
## 2. Non-negotiable invariants (inherited from AGENTS.md — full text there)
|
| 37 |
+
|
| 38 |
+
These apply to every ticket. The judge greps for regressions on each one.
|
| 39 |
+
|
| 40 |
+
1. Translate-only: never generate medical advice, diagnoses, or drug recommendations.
|
| 41 |
+
2. High/critical-risk turns stay blocked from patient display + TTS until doctor confirms.
|
| 42 |
+
3. Low-confidence output is always visibly flagged, never silently delivered.
|
| 43 |
+
4. Raw audio is never persisted by the interpreter — memory-only. No audio columns, no temp files.
|
| 44 |
+
5. No mic capture before recorded consent.
|
| 45 |
+
6. On pipeline/reviewer failure, fail closed — never fail open to the patient.
|
| 46 |
+
7. Vietnamese copy always carries full diacritics, NFC-normalized. `site/` build enforces this.
|
| 47 |
+
8. **The scriber API contract is frozen**: request/response schemas and routes under
|
| 48 |
+
`/api/v1/*` must be byte-for-byte compatible with `origin/main` (`carepath/schemas.py`
|
| 49 |
+
and the endpoint signatures in `carepath/main.py`). The deployed HF Space and its
|
| 50 |
+
clients must keep working.
|
| 51 |
+
9. Keyless boot is a hard requirement end-to-end: `PROVIDER_MODE=mock` +
|
| 52 |
+
`LLM_PROVIDER=offline` + `ASR_PROVIDER=mock`/`ALLOW_MOCK_ASR=true` must run the whole
|
| 53 |
+
combined product with zero API keys.
|
| 54 |
+
10. Secrets only via env. `.env` gitignored, `.env.example` stays current. No new
|
| 55 |
+
dependencies beyond those named in this plan without a written why in the commit body.
|
| 56 |
+
|
| 57 |
+
## 3. Verify command inventory
|
| 58 |
+
|
| 59 |
+
Used throughout the tickets (all verified to exist on their source branches):
|
| 60 |
+
|
| 61 |
+
```text
|
| 62 |
+
# scriber (repo root, Python 3.12 venv with: pip install -e ".[dev]")
|
| 63 |
+
pytest # root suite (tests/, pythonpath apps/api)
|
| 64 |
+
python scripts/smoke_backend.py # forces mock ASR + offline LLM internally
|
| 65 |
+
|
| 66 |
+
# interpreter backend (from backend/, same venv with: pip install -e ".[dev]")
|
| 67 |
+
ruff check .
|
| 68 |
+
pytest
|
| 69 |
+
|
| 70 |
+
# eval regression (repo root)
|
| 71 |
+
python eval/run_eval.py --set eval/fixtures/eval_starter.tsv --providers mock
|
| 72 |
+
|
| 73 |
+
# interpreter console (from frontend/)
|
| 74 |
+
npm ci && npm run lint && npm test && npm run e2e # e2e needs PROVIDER_MODE=mock backend
|
| 75 |
+
|
| 76 |
+
# demo site (from site/)
|
| 77 |
+
npm ci && npm run lint && npm test && npm run build # build runs check-diacritics.mjs
|
| 78 |
+
npm run e2e
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
---
|
| 82 |
+
|
| 83 |
+
## Tickets
|
| 84 |
+
|
| 85 |
+
### M.0 — Unify the histories
|
| 86 |
+
|
| 87 |
+
1. `git checkout -b carepath-unified origin/main`
|
| 88 |
+
2. `git merge --allow-unrelated-histories origin/carepath-interpreter-demo`
|
| 89 |
+
3. Exactly three paths collide — resolve as:
|
| 90 |
+
- `README.md`: temporary stub — unified title, one paragraph per product, links to
|
| 91 |
+
both quickstarts. Rewritten properly in M.8.
|
| 92 |
+
- `.gitignore`: union of both, deduplicated.
|
| 93 |
+
- `.env.example`: both files concatenated under `# --- Scriber (apps/api) ---` and
|
| 94 |
+
`# --- Interpreter (backend/) ---` section headers. Properly merged in M.2.
|
| 95 |
+
4. Nothing else changes in this ticket. No restructuring, no renames.
|
| 96 |
+
|
| 97 |
+
**Verify:** root `pytest` passes; `python scripts/smoke_backend.py` passes;
|
| 98 |
+
`cd backend && pytest` passes; `frontend/` and `site/` `npm test` pass.
|
| 99 |
+
|
| 100 |
+
### M.1 — One FastAPI service
|
| 101 |
+
|
| 102 |
+
Goal: a single uvicorn process serves both API surfaces.
|
| 103 |
+
|
| 104 |
+
1. Root `pyproject.toml`: no changes to the `carepath` package config. The interpreter
|
| 105 |
+
backend stays where it is and keeps its own `backend/pyproject.toml`; the combined
|
| 106 |
+
env simply installs both: `pip install -e ".[dev]" -e "./backend[dev]"`. Confirm the
|
| 107 |
+
resolver accepts both dependency sets on Python 3.12 (backend requires >=3.12).
|
| 108 |
+
2. Extend `apps/api/carepath/main.py`:
|
| 109 |
+
- `app.include_router(api_router)` and `app.include_router(ws_router)` from
|
| 110 |
+
`app.api` (the interpreter package is importable as `app` once installed). Register
|
| 111 |
+
routers **before** the `app.mount("/", StaticFiles(...))` call so routes win.
|
| 112 |
+
- Extend the existing lifespan: after scriber warmup, run the interpreter startup
|
| 113 |
+
sequence exactly as `backend/app/main.py` does today — `validate_runtime_settings()`,
|
| 114 |
+
`init_db()`, then in a DB session `seed_glossary(db)` and
|
| 115 |
+
`crud.purge_old_sessions(db, settings.retention_days)`.
|
| 116 |
+
- Do **not** add the interpreter's CORSMiddleware; the scriber's origin-guard +
|
| 117 |
+
CORS config governs the combined app.
|
| 118 |
+
3. Leave `backend/app/main.py` untouched — it remains the standalone dev/test app, and
|
| 119 |
+
the interpreter pytest suite keeps running against it unmodified.
|
| 120 |
+
4. Route collision check: scriber owns `/api/v1/*`; interpreter owns `/api/health`,
|
| 121 |
+
`/api/sessions*`, `/api/turns*`, `/api/admin/*`, `/ws/sessions/*`. `/api/health` and
|
| 122 |
+
`/api/v1/health` are distinct — keep both.
|
| 123 |
+
|
| 124 |
+
Watch-outs:
|
| 125 |
+
- WebSocket route through the combined app: verify `/ws/sessions/{id}` accepts a
|
| 126 |
+
connection (the interpreter e2e covers this in M.5's CI wiring; here a manual
|
| 127 |
+
`pytest`-style check or a small added test against the combined app is enough).
|
| 128 |
+
- The scriber origin-guard middleware only rejects when `CORS_ORIGINS` is set and the
|
| 129 |
+
Origin header mismatches — document in `.env.example` (M.2) that local Vite dev
|
| 130 |
+
origins (`http://localhost:5173`) must be listed when developing against it.
|
| 131 |
+
|
| 132 |
+
**Verify:** `uvicorn carepath.main:app --app-dir apps/api` boots keyless (env:
|
| 133 |
+
`PROVIDER_MODE=mock`, `ASR_PROVIDER=mock`, `ALLOW_MOCK_ASR=true`, `LLM_PROVIDER=offline`)
|
| 134 |
+
and answers `GET /api/v1/health` **and** `GET /api/health`; root `pytest`;
|
| 135 |
+
`python scripts/smoke_backend.py`; `cd backend && pytest`; add one combined-app test
|
| 136 |
+
(root `tests/test_combined_app.py`) asserting both health endpoints and a WebSocket
|
| 137 |
+
handshake on a created session — this test is the ticket's artifact.
|
| 138 |
+
|
| 139 |
+
### M.2 — Config and env unification
|
| 140 |
+
|
| 141 |
+
1. Rewrite `.env.example` as one documented file: shared section (nothing collides —
|
| 142 |
+
verified), scriber section (ASR_*, GIPFORMER_*, LLM_*, CORS_ORIGINS, TEAM_CODE,
|
| 143 |
+
SOAP_RATE_LIMIT_*), interpreter section (PROVIDER_MODE, ADMIN_TOKEN,
|
| 144 |
+
CONFIDENCE_THRESHOLD, RETENTION_DAYS, DATABASE_URL, MAX_TURN_AUDIO_BYTES, provider
|
| 145 |
+
models/keys marked "later track — mock mode needs none").
|
| 146 |
+
2. Defaults must produce a keyless boot: `PROVIDER_MODE=mock`, `LLM_PROVIDER=offline`
|
| 147 |
+
documented as the demo profile. Keep `.env.local.example` / `.env.ckey.example`
|
| 148 |
+
consistent or fold them in — fewest files wins, but don't break
|
| 149 |
+
`scripts/setup_local.ps1`, which copies `.env.local.example`.
|
| 150 |
+
3. sqlite `DATABASE_URL` default stays (ephemeral on HF Space is acceptable for the
|
| 151 |
+
mock demo; note this in the file).
|
| 152 |
+
|
| 153 |
+
**Verify:** fresh env from the new `.env.example` defaults boots the combined app
|
| 154 |
+
keyless; `python scripts/smoke_backend.py`; `cd backend && pytest`.
|
| 155 |
+
|
| 156 |
+
### M.3 — Rebrand `site/` to unified CarePath — **ALREADY DONE on the interpreter branch**
|
| 157 |
+
|
| 158 |
+
This ticket was executed by claude-fable-5 directly on `carepath-interpreter-demo`
|
| 159 |
+
before the merge (commit(s) touching `site/` after S.8): brand is now "CarePath"
|
| 160 |
+
(logo/favicon/titles/package `carepath-site`), the landing is a two-module story
|
| 161 |
+
(hero + module tiles + a `#scribe` chapter with a scripted `ScribeShowcase`
|
| 162 |
+
ASR→correction→SOAP walkthrough), and all tests/build/e2e are green.
|
| 163 |
+
|
| 164 |
+
**Your job in this ticket is verification only:** from `site/` run `npm run lint`,
|
| 165 |
+
`npm test`, `npm run build` (diacritics gate), `npm run e2e`; grep gate:
|
| 166 |
+
`grep -ri "carepath translate" site/src` returns nothing. Fix anything the merge broke;
|
| 167 |
+
otherwise commit nothing and move on.
|
| 168 |
+
|
| 169 |
+
### M.4 — Port the Scribe tool into `site/`, retire the old frontends
|
| 170 |
+
|
| 171 |
+
1. Rebuild the `apps/web/app` tool (record/upload audio → raw transcript → corrected
|
| 172 |
+
transcript → SOAP draft with retrieved terms) as a React view inside `site/`, using
|
| 173 |
+
the site's design system and `strings.ts` i18n.
|
| 174 |
+
2. Routing: `site/` has no router — add a **hash route** (`#/scribe`) with a small
|
| 175 |
+
`location.hash` switch in `App.tsx`. No router dependency, no server-side SPA
|
| 176 |
+
fallback needed. Note: the landing already has a `#scribe` **anchor** (the Scribe
|
| 177 |
+
overview chapter with the scripted `ScribeShowcase`) — keep it, and add a "Mở công
|
| 178 |
+
cụ Scribe / Open the Scribe tool" CTA inside that chapter linking to the `#/scribe`
|
| 179 |
+
tool route.
|
| 180 |
+
3. API calls (see `apps/web/app.js` on `origin/main` for the exact flow):
|
| 181 |
+
- `GET {base}/api/v1/health` for the status badge,
|
| 182 |
+
- `POST {base}/api/v1/soap-notes` (multipart file upload),
|
| 183 |
+
- base URL from `VITE_API_BASE`, defaulting to `""` (same-origin, matching M.5).
|
| 184 |
+
- Handle 400 (bad audio), 413/oversize, and 429 rate-limit responses with bilingual
|
| 185 |
+
messages; support an optional `X-Team-Code` header from a `VITE_TEAM_CODE` env or
|
| 186 |
+
input field (it bypasses the scriber's rate limit — never hardcode a value).
|
| 187 |
+
4. Mic/consent: the scribe records clinician dictation. Reuse the site's existing
|
| 188 |
+
consent-gate pattern before any `getUserMedia` call (invariant 5) — file upload
|
| 189 |
+
needs no consent gate.
|
| 190 |
+
5. Delete `apps/web/` and `apps/web-next/` entirely (git history preserves them).
|
| 191 |
+
Remove now-dead references: the `app.mount("/", StaticFiles(directory=WEB_DIR...))`
|
| 192 |
+
block keeps working until M.5 swaps the directory — if `WEB_DIR` points at the
|
| 193 |
+
deleted `apps/web`, make the mount conditional on the directory existing so the API
|
| 194 |
+
still boots; M.5 finishes the job.
|
| 195 |
+
|
| 196 |
+
**Verify:** `site/` lint + test + build + e2e green (add at least one e2e that walks
|
| 197 |
+
the scribe route against a mocked fetch or the local keyless API); combined app still
|
| 198 |
+
boots; `git ls-files apps/web apps/web-next` returns nothing.
|
| 199 |
+
|
| 200 |
+
### M.5 — Serve the frontends from the API
|
| 201 |
+
|
| 202 |
+
1. `frontend/` (interpreter console): set Vite `base: "/console/"`, make its API base
|
| 203 |
+
same-origin-relative in production (keep the localhost dev default working).
|
| 204 |
+
2. Combined app static serving, in this order after all routers:
|
| 205 |
+
- `app.mount("/console", StaticFiles(directory=<frontend/dist>, html=True))`
|
| 206 |
+
- `app.mount("/", StaticFiles(directory=<site/dist>, html=True))`
|
| 207 |
+
- Directories configurable via env (`SITE_DIST_DIR`, `CONSOLE_DIST_DIR`) with those
|
| 208 |
+
defaults; mounts are skipped with a logged warning when the dir is missing (dev
|
| 209 |
+
and CI run the Vite dev servers instead).
|
| 210 |
+
3. Landing links: Interpreter module CTA → `/console`, Scribe CTA → `#/scribe`.
|
| 211 |
+
4. WebSocket URL in the console must derive from `window.location` when served
|
| 212 |
+
same-origin (ws/wss scheme).
|
| 213 |
+
|
| 214 |
+
**Verify:** build both frontends, boot the combined app keyless, manually fetch `/`,
|
| 215 |
+
`/console/`, `/api/health`, `/api/v1/health`; `frontend/` mock-mode Playwright e2e
|
| 216 |
+
green; `site/` e2e green.
|
| 217 |
+
|
| 218 |
+
### M.6 — One CI workflow
|
| 219 |
+
|
| 220 |
+
Merge into a single `.github/workflows/ci.yml` (keep `keepalive.yml` as-is) with jobs:
|
| 221 |
+
|
| 222 |
+
1. `scriber`: Python 3.12, `pip install -e ".[dev]"`, root `pytest`,
|
| 223 |
+
`python scripts/smoke_backend.py`.
|
| 224 |
+
2. `interpreter-backend`: `pip install -e "./backend[dev]"`, `ruff check backend`,
|
| 225 |
+
backend `pytest`, eval regression run.
|
| 226 |
+
3. `combined-app`: install both packages, run the M.1 combined-app test + keyless boot
|
| 227 |
+
check.
|
| 228 |
+
4. `frontend`: existing lint + vitest job.
|
| 229 |
+
5. `site`: existing lint + vitest + build (diacritics) job.
|
| 230 |
+
6. `e2e`: existing Playwright jobs for `frontend/` (against `PROVIDER_MODE=mock`
|
| 231 |
+
backend) and `site/` — preserve their current setup from the interpreter branch's
|
| 232 |
+
ci.yml (S.7 wiring).
|
| 233 |
+
|
| 234 |
+
**Verify:** `git push` the branch and confirm all CI jobs green, or run each job's
|
| 235 |
+
commands locally in a clean venv/node_modules if CI isn't available to you.
|
| 236 |
+
|
| 237 |
+
### M.7 — Docker / deploy
|
| 238 |
+
|
| 239 |
+
1. Multi-stage `Dockerfile`:
|
| 240 |
+
- `node:22-slim` stage: `npm ci && npm run build` for `site/` and `frontend/`
|
| 241 |
+
(frontend built with `base=/console/`; site build runs the diacritics gate).
|
| 242 |
+
- Python stage (keep the existing base, env, Gipformer int8 pre-download exactly as
|
| 243 |
+
today): additionally `pip install ./backend`, copy the two dist folders, set
|
| 244 |
+
`SITE_DIST_DIR`/`CONSOLE_DIST_DIR`, same `CMD` (port 7860).
|
| 245 |
+
2. Update `docs/deploy.md` and `README.hf-space.md`: one Space serves the landing,
|
| 246 |
+
console, scribe, and both APIs; document the interpreter env vars (mock defaults, ADMIN_TOKEN
|
| 247 |
+
note: the combined app runs `validate_runtime_settings`, which only enforces
|
| 248 |
+
ADMIN_TOKEN when `PROVIDER_MODE=cloud`).
|
| 249 |
+
3. `apps/web-next` is gone — remove Vercel references from docs; note the old Vercel
|
| 250 |
+
project can be deleted.
|
| 251 |
+
|
| 252 |
+
**Verify:** `docker build .` succeeds; `docker run` with no API keys boots and serves
|
| 253 |
+
`/`, `/console/`, `/api/health`, `/api/v1/health`, and a mock `POST /api/v1/soap-notes`
|
| 254 |
+
(smoke-style WAV) — mirror what `scripts/check_goal5_deploy.ps1` checks where practical.
|
| 255 |
+
|
| 256 |
+
### M.8 — Docs
|
| 257 |
+
|
| 258 |
+
1. Rewrite `README.md` for the unified product: what CarePath is (two modules), local
|
| 259 |
+
quickstart (one venv, both packages, combined uvicorn command, both frontends),
|
| 260 |
+
keyless demo profile, test commands, deploy pointer.
|
| 261 |
+
2. Update `AGENTS.md`: unified command list, invariants unchanged, plan pointers —
|
| 262 |
+
`PLAN.md` and `DEMO-SITE-PLAN.md` marked historical (do not delete), `MERGE-PLAN.md`
|
| 263 |
+
marked done, `JUDGE.md` referenced as the review protocol.
|
| 264 |
+
3. Sweep for stale references: `grep -ri "web-next\|apps/web\b\|carepath translate"`
|
| 265 |
+
across docs and configs; fix stragglers.
|
| 266 |
+
|
| 267 |
+
**Verify:** every command in the new README executes as written on a clean checkout;
|
| 268 |
+
full Verify inventory from §3 green one last time.
|
| 269 |
+
|
| 270 |
+
---
|
| 271 |
+
|
| 272 |
+
## 4. Out of scope — do not do
|
| 273 |
+
|
| 274 |
+
- No real interpreter providers (no Gipformer-for-interpreter, no ckey MT/reviewer, no
|
| 275 |
+
new keys). Mock stays.
|
| 276 |
+
- No changes to the GEC training pipeline, notebooks, `scripts/gec/`, or eval datasets.
|
| 277 |
+
- No auth/multi-tenant, no analytics, no new runtime dependencies beyond what this plan
|
| 278 |
+
names (the hash route explicitly avoids react-router).
|
| 279 |
+
- No visual redesign of the S.8 system — extend it.
|