This repository has been archived on 2026-09-12. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
praxis/.ciagent/REQUIREMENTS.md
T
Praxis CI f2a12f9fed docs(milestone): complete v0.4-operator-tier — v0.1.9 tagged, milestone release, merged to main
v0.4 (Operator Tier — Cohort Dashboard + Auth + Postgres) milestone complete.

Phases:
  ✓ P0  pre-execution (planning)        → v0.1.6
  ✓ P1  operator foundation (Postgres+auth+VC migration) → v0.1.7
  ✓ P2  cohort dashboard + aggregation   → v0.1.8
  ✓ P3  final review + ship              → v0.1.9 (= v0.4 milestone release)

Requirements covered (8/8):
  REQ-MT-01 (Postgres store), REQ-MT-02 (aggregation pipeline),
  REQ-AUTH-01 (operator auth), REQ-DASH-01 (cohort dashboard),
  REQ-NFR-AUTH-01 (auth NFRs), REQ-NFR-MT-01 (Postgres-in-LXC),
  REQ-NFR-DASH-01 (k-anonymity ≥10), REQ-NFR-DASH-02 (freshness ≤24h)

Grill MUSTs honored (6/6): G-008, G-011, G-027, G-031, G-038, G-041

Tests: 317 pytest pass, 36 skip (Postgres-requiring), 0 fail; 17/17 vitest pass
Review: APPROVE_WITH_NOTES (6/6 personas, 0 P0, 8 P1+ carry-forward)
Audit: HEALTHY (reconstruction PASS, 8/8 REQ, 6/6 grill)

---ci---
project: praxis
phase: 3
milestone: v0.4
status: complete
phase_role: final
milestone_complete: true
milestone_merged_to_main: true
tag: v0.1.9
requirements:
  covered: [REQ-MT-01, REQ-MT-02, REQ-AUTH-01, REQ-DASH-01, REQ-NFR-AUTH-01, REQ-NFR-MT-01, REQ-NFR-DASH-01, REQ-NFR-DASH-02]
  partial: []
---/ci---
2026-08-04 11:58:44 +00:00

277 lines
20 KiB
Markdown

# Praxis — Requirements
**Milestone:** v0.4 (Operator tier — cohort dashboard, auth, Postgres)
**Status:** phase 3 — final review (active milestone); P0-P2 complete — 8/8 v0.4 REQ covered (v0.1.6/v0.1.7/v0.1.8 tagged); v0.3 complete — released as v0.1.5 (13/13 v0.3 REQ covered)
Formal requirements with REQ-IDs. Scoped to the active milestone unless noted. v0.1/v0.2/v0.3 requirements (complete) are retained for reference with their final status. Later-milestone requirements are marked `deferred`.
## v0.4 Active Requirements
### Operator-Tier Postgres (v0.4 foundation)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-MT-01 | Operator-tier Postgres store — cohort aggregations, operator accounts, issued credentials, mastery-gate audit log. Separate from learner-local SQLite (D-007 preserved for learner surface). Migration path: SQLite stays for learner; Postgres added for operator. Postgres 16, persistent volume, internal Docker network only (D-040). | must | P1 | complete |
| REQ-MT-02 | Cohort aggregation pipeline — on-session-end hook + nightly reconciliation job writes k-anonymized aggregates to Postgres from learner sessions (D-045). No raw learner PII in Postgres. | must | P1 | complete |
### Operator Auth (v0.4)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-AUTH-01 | Operator-tier auth — session-based, single `operator` role in v0.4. Operator accounts in Postgres. Login endpoint + session cookie. Protects cohort dashboard + credential issuance. argon2id passwords, httpOnly+secure cookie, SameSite=Strict, 8h expiry, login rate-limited 5/min (D-041). | must | P1 | complete |
### Cohort Dashboard (v0.4)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-DASH-01 | Anonymized cohort view (practice, mastery progression, failure patterns) for training operators — k-anonymity ≥ 10, 7-day aggregation window (D-034). Operator UI (React) under `/operator/*`, served by same FastAPI server (`/api/operator/*` prefix), reuses v0.2 StaticFiles (D-044). No separate SPA build — same `client/dist`. | must | P2 | complete |
## v0.4 Non-Functional Requirements
| REQ-ID | Requirement | Target | Phase | Status |
|--------|-------------|--------|-------|--------|
| REQ-NFR-AUTH-01 | Operator auth — passwords hashed (argon2id), session cookie httpOnly + secure + SameSite=Strict, login rate-limited (5/min), 8h expiry | must | P1 | complete |
| REQ-NFR-MT-01 | Postgres-in-LXC — operator Postgres runs as a second Docker service in the existing LXC CT (D-040) without destabilizing the learner-facing praxis service. Internal Docker network only (not exposed to bridge). | must | P1 | complete |
| REQ-NFR-DASH-01 | Cohort dashboard k-anonymity ≥ 10 — any cohort view cell with < 10 learners is suppressed | must | P2 | complete |
| REQ-NFR-DASH-02 | Cohort dashboard freshness — aggregates ≤ 24h stale (nightly reconciliation + on-session-end hook per D-045) | must | P2 | complete |
## v0.4 Out of Scope (still deferred)
- REQ-PATH-01 (full multi-path launch) — v0.3 ships Customer Service path only, multi-path later
- REQ-DASH-02 (full operator-suite dashboard) — later milestone (v0.4 ships the foundational cohort view only)
- REQ-ASSIST-01..03 (Live Assist) — later milestone
- REQ-LOWBW-01..03 (WhatsApp/USSD/offline) — later milestone
- REQ-VOICE-05/06 (multi-language, persona switching) — later milestone
- Learner auth / multi-learner-per-device — operator auth is v0.4; learner auth later
- RBAC (multiple operator roles) — single `operator` role in v0.4; RBAC deferred
- Third-party credential issuers (university/agency) — v0.9 credentialing milestone
- Differential privacy — k-anonymity ≥ 10 is sufficient for v0.4 scale (D-034)
## Constraints (binding — carry forward from v0.1/v0.2/v0.3)
- C-1 Voice is primary interface; text is fallback only
- C-2 Must work on $100 Android phone over 2G/3G (relaxed for v0.1 Canada pilot)
- C-3 Cost ≤ $3/active learner/month (relaxed for v0.1 pilot)
- C-4 Audio-only in v1
- C-5 Open-weights LLM via Ollama catalog — `gemma4:cloud` + `deepseek-v4-flash:cloud`
- C-6 Domain safety guardrails + HITL + disclaimers for safety-sensitive domains
- C-7 Scenarios authored by domain experts + learning designers; AI generates variations only
- C-8 Latency budget < 600ms end-to-end (ASR → LLM → TTS) — mastery scoring + cohort aggregation must not be on the voice path
---
## v0.3 Requirements (complete — released as v0.1.5, retained for reference)
### Mastery & Assessment (v0.3 core)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-MAST-01 | Competency rubric per skill — a typed rubric model (criteria, 5-level scale, per-skill weights) authored as YAML, mapped to scenarios (D-036). At least one rubric for the Customer Service path in v0.3. | must | P1 | complete |
| REQ-MAST-02 | Mastery Score updated after each session — computed from rubric scores + varied-scenario-success gate (D-032: N=3 distinct scenarios, rubric mean ≥ 3.5/5.0). Score persisted per learner per path. Mastery gate opens when condition met. | must | P1 | complete |
| REQ-MAST-03 | Portable verifiable credentials on mastery — W3C VC Data Model 2.0, platform-issued Ed25519 signatures, status-list revocation (D-033). Issued when a mastery gate opens. Verifiable by third parties via a public verification endpoint. | must | P1 | complete |
| REQ-MAST-04 | No quizzes — assessment built into scenarios | principle | — | accepted |
### Scenario Engine (v0.3 extensions)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-SCEN-02 | Dynamic difficulty adjustment based on learner performance — IRT 1PL/Rasch, Bayesian θ update per session (D-035). Difficulty selection picks next scenario targeting ~50% expected success for current θ. | must | P1 | complete |
| REQ-SCEN-03 | Scenario library tagged by skill, difficulty, failure mode, rubric criteria — YAML directory + `scenarios/index.yaml` manifest (D-036). v0.3 ships ≥6 scenarios for the Customer Service path (one per week minimum). | must | P1 | complete |
| REQ-SCEN-04 | Expert-authored scenario format with AI-generated variations — extends D-018 YAML DSL with rubric mapping + `generated_from` backref for AI variations. Expert-authored = canonical; AI variations = same schema, flagged, reviewable. | must | P1 | complete |
### Skill Paths (v0.3)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-PATH-02 | Path structured as a job — 6-week structure per PRD §6.4, mastery-paced (D-037). Path = `paths/<slug>.yaml` defining weeks, each week = scenarios + a mastery gate. v0.3 ships the Customer Service path fully (6 weeks, ≥1 scenario/week). | must | P1 | complete |
## v0.3 Non-Functional Requirements (complete)
| REQ-ID | Requirement | Target | Phase | Status |
|--------|-------------|--------|-------|--------|
| REQ-NFR-MAST-01 | Rubric scoring determinism — same session + rubric → same score (no LLM non-determinism in the scoring path; LLM may assist rubric criterion extraction but final score is rule-based) | must | P1 | complete |
| REQ-NFR-MAST-02 | Mastery gate auditability — every gate-open event recorded with evidence (which 3 scenarios, rubric scores, timestamp) | must | P1 | complete |
| REQ-NFR-VC-01 | Verifiable credential tamper-evidence — Ed25519 signature, issuer key in operator-tier secrets (not committed), verification endpoint validates signature + status + interop test against external W3C verifier (grill Axis 3) | must | P1 | complete |
| REQ-NFR-VC-02 | Credential revocation latency — revoked credential must fail verification within 1 sync of the status list (next verify call — no cache) | must | P1 | complete |
| REQ-NFR-IRT-01 | IRT θ update latency — < 100ms (in-process, no LLM call) | must | P1 | complete |
## v0.3 Out of Scope (now activated in v0.4)
- ~~REQ-DASH-01 (cohort dashboard) — deferred to v0.4~~ → **activated in v0.4**
- ~~REQ-AUTH-01, REQ-MT-01, REQ-MT-02 (operator auth + Postgres) — deferred to v0.4~~ → **activated in v0.4**
- ~~REQ-NFR-DASH-01, REQ-NFR-DASH-02, REQ-NFR-AUTH-01, REQ-NFR-MT-01 — deferred to v0.4~~ → **activated in v0.4**
## v0.3 Out of Scope (still deferred)
- REQ-PATH-01 (full multi-path launch) — v0.3 ships Customer Service path only
- REQ-DASH-02 (full operator-suite dashboard) — later milestone
- REQ-ASSIST-01..03 (Live Assist) — later milestone
- REQ-LOWBW-01..03 (WhatsApp/USSD/offline) — later milestone
- REQ-VOICE-05/06 (multi-language, persona switching) — later milestone
- Third-party credential issuers (university/agency) — v0.9 credentialing milestone
- Learner auth / multi-learner-per-device — operator auth is v0.4; learner auth later
- Active failure injection (D-009) — evaluated in v0.3 RESEARCH (D-049), stays off
- Dynamic rubric weight re-weighting on branch outcome — static weights in v0.3, dynamic is a future feature (grill Axis 9)
---
## v0.2 Requirements (complete — retained for reference)
## Functional Requirements
### Voice Conversation Engine
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-VOICE-01 | Real-time streaming ASR accepting accented, noisy speech (Canadian English pilot) | must | P1 | complete |
| REQ-VOICE-02 | Streaming TTS with natural prosody, one voice persona (single voice for both mentor and role-play character per D-006) | must | P1 | complete |
| REQ-VOICE-03 | End-to-end voice round-trip < 600ms (ASR → LLM → TTS first audio) | must | P1 | complete |
| REQ-VOICE-04 | Interruptibility — learner can cut the AI off mid-sentence (abort-and-yield semantics per D-008) | must | P1 | complete |
| REQ-VOICE-05 | Multi-language support (10+ launch languages) | later | deferred | deferred |
| REQ-VOICE-06 | Persona switching — same AI becomes customer/colleague/patient/mentor | later | deferred | deferred |
### Scenario Engine
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-SCEN-01 | One branching Customer Service role-play scenario (Canada context): "Angry customer requesting refund on damaged product" with one branch point (escalate vs accept), defined success criteria, common mistakes, and a `failure_mode` field present but not actively provoked in v0.1 (per D-009, D-010) | must | P1 | complete |
| REQ-SCEN-02 | Dynamic difficulty adjustment based on learner performance | later | deferred | deferred |
| REQ-SCEN-03 | Scenario library tagged by skill, difficulty, failure mode | later | deferred | deferred |
| REQ-SCEN-04 | Expert-authored scenario format with AI-generated variations | later | deferred | deferred |
### Mastery & Assessment
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-MAST-01 | Competency rubric per skill | later | deferred | deferred |
| REQ-MAST-02 | Mastery Score updated after each session, requiring varied-scenario success | later | deferred | deferred |
| REQ-MAST-03 | Portable verifiable credentials on mastery | later | deferred | deferred |
| REQ-MAST-04 | No quizzes — assessment built into scenarios | principle | — | accepted |
### Skill Paths
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-PATH-01 | Launch paths: Customer Service, Retail Sales, Hospitality Front Desk, Home Health Aide, Basic English for Work, Auto-Rickshaw/Taxi | later | deferred | deferred |
| REQ-PATH-02 | Path structured as a job (6-week example structure per PRD §6.4) | later | deferred | deferred |
### Live Assist
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-ASSIST-01 | Hands-free voice companion invocable while working | later | deferred | deferred |
| REQ-ASSIST-02 | Context-aware (knows current scenario/skill) | later | deferred | deferred |
| REQ-ASSIST-03 | Guardrails: coaches, does not do the job; never lies to real customers | later | deferred | deferred |
### Low-Bandwidth Surfaces
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-LOWBW-01 | WhatsApp/SMS bot thin entry point (2-min voice-note scenarios) | later | deferred | deferred |
| REQ-LOWBW-02 | USSD fallback for feature phones | later | deferred | deferred |
| REQ-LOWBW-03 | Offline cache for pre-downloaded scenarios and voices | later | deferred | deferred |
### Employer / Program Dashboard
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-DASH-01 | Anonymized cohort view (practice, mastery progression, failure patterns) | later | deferred | deferred |
| REQ-DASH-02 | For training operators and SME HR, not individual learners | later | deferred | deferred |
### Learner State
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-STATE-01 | Single-learner session log with progress and session history (v0.1: local SQLite persistence, no auth, no multi-tenant per D-007) | must | P1 | complete |
### Coaching Debrief
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-DEBRIEF-01 | End-of-session single text+voice summary (not full multi-moment replay) per D-011 | must | P1 | complete |
### LLM Foundation
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-LLM-01 | Ollama-hosted `gemma4:cloud` model callable for edge/fast-path persona responses (via Ollama Cloud direct API per D-020) | must | P1 | complete |
| REQ-LLM-02 | Ollama-hosted `deepseek-v4-flash:cloud` model callable for complex coaching/debrief (no-think mode for latency per D-020) | must | P1 | complete |
| REQ-LLM-03 | Open-weights foundation enabling on-prem option for partners (model-call layer swappable per D-020) | principle | — | accepted |
### Orchestration & Pipeline (research-derived D-017)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-ORCH-01 | Pipecat server orchestrates ASR→LLM→TTS pipeline with Silero VAD + interruptibility (D-017) | must | P1 | complete |
| REQ-ORCH-02 | Pluggable guardrail layer with Customer Service ruleset (D-019): no legal/financial/medical advice, no real-company impersonation, stay-in-role, session-start disclaimer | must | P1 | complete |
### Scenario Format (research-derived D-018)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-SCEN-FMT-01 | YAML DSL scenario definition → Pydantic model → Pipecat Flows consumption (D-018); supports `failure_mode` field (D-009) | must | P1 | complete |
## Non-Functional Requirements
| REQ-ID | Requirement | Target | Phase | Status |
|--------|-------------|--------|-------|--------|
| REQ-NFR-LAT-01 | End-to-end voice round-trip latency | < 600ms | P1 | complete |
| REQ-NFR-COST-01 | Cost per active learner per month | ≤ $3 (target markets; no enforced ceiling in v0.1 Canada pilot per D-012, but architecture must not preclude it). Log actual per-session cost in v0.1. | P1 (logging only) | complete |
| REQ-NFR-SAFE-01 | Domain safety guardrails + disclaimers for safety-sensitive scenarios | baseline for v0.1 (Customer Service lower risk) | P1 | complete |
| REQ-NFR-BW-01 | Usable on 2G/3G bandwidth | target | later | deferred |
| REQ-NFR-DEVICE-01 | Usable on $100 Android phone | target | later | deferred |
| REQ-NFR-AUDIO-01 | Audio-only in v1 (no large video assets) | principle | — | accepted |
## Constraints (binding)
- C-1 Voice is primary interface; text is fallback only
- C-2 Must work on $100 Android phone over 2G/3G (relaxed for v0.1 Canada pilot)
- C-3 Cost ≤ $3/active learner/month (relaxed for v0.1 pilot)
- C-4 Audio-only in v1
- C-5 Open-weights LLM via Ollama catalog — `gemma4:cloud` + `deepseek-v4-flash:cloud`
- C-6 Domain safety guardrails + HITL + disclaimers for safety-sensitive domains
- C-7 Scenarios authored by domain experts + learning designers; AI generates variations only
- C-8 Latency budget < 600ms end-to-end
## Deployment (v0.2 — Proxmox LXC)
| REQ-ID | Requirement | Priority | Phase | Status |
|--------|-------------|----------|-------|--------|
| REQ-DEPLOY-01 | Multi-stage Dockerfile: Node stage builds `client/dist` via `npm run build`, Python stage runs the Pipecat server and serves `client/dist` via FastAPI StaticFiles (D-022, D-023) | must | P1 | complete |
| REQ-DEPLOY-02 | `docker-compose.yml` defining the praxis service with volume for SQLite DB (`praxis.db`), env injection, port mapping (8789), restart policy | must | P1 | complete |
| REQ-DEPLOY-03 | Port `scripts/proxmox/api.sh` from coreci verbatim (PVE REST helpers: pve_curl, pve_poll, pve_nextid, pve_get, pve_env, pve_lxc_env_args) | must | P1 | complete |
| REQ-DEPLOY-04 | Port `scripts/proxmox/lxc-clone.sh` adapted for praxis (hostname=praxis, port 8789, features=nesting=1 for Docker-in-LXC) | must | P1 | complete |
| REQ-DEPLOY-05 | Port `scripts/proxmox/lxc-config.sh` adapted: hookscript snippet, lxc.environment injects GITEA_TOKEN + DEEPGRAM_API_KEY + voice-service env vars (empty if unprovisioned), PRAXIS_PORT=8789 | must | P1 | complete |
| REQ-DEPLOY-06 | Port `scripts/proxmox/firstboot-hook.sh` adapted: host-builds Docker image (or loads pre-built), `pct exec` runs `docker compose up -d` inside the CT, health-checks `/health` :8789 | must | P1 | complete |
| REQ-DEPLOY-07 | Port `scripts/proxmox/health-check.sh` adapted for praxis: polls `http://<bridge-ip>:8789/health` (not coreci's `/healthz` :18080) | must | P1 | complete |
| REQ-DEPLOY-08 | Port `scripts/proxmox/{lxc-start,rollback,stage-snippet,timing}.sh` from coreci (adapted for praxis snippet name) | must | P1 | complete |
| REQ-DEPLOY-09 | Port `scripts/proxmox/lxc-deploy.sh` orchestrator: clone → config → start → health-check → rollback-on-failure, with idempotency (--recreate/--reconfigure) | must | P1 | complete |
| REQ-DEPLOY-10 | `scripts/install-service.sh` adapted: creates praxis user, data/log dirs, env file, systemd unit (`praxis.service`) that runs `docker compose up -d`, health-checks `/health` :8789 | must | P1 | complete |
| REQ-DEPLOY-11 | `scripts/proxmox/praxis.service` systemd unit running `docker compose up -d` with `Restart=on-failure` | must | P1 | complete |
| REQ-DEPLOY-12 | Secret wiring: extend `config.json` secrets.scopes with proxmox + voice scopes; source PROXMOX_* from `~/coreci/.ciagent/.env.secrets` | must | P1 | complete |
| REQ-DEPLOY-13 | FastAPI `server/__main__.py` mounts `client/dist` as StaticFiles at `/` (serving the React client from the same port as the API) | must | P1 | complete |
| REQ-DEPLOY-14 | `.env.example` updated with PROXMOX_* + deployment env vars (documented, not secret) | must | P1 | complete |
| REQ-DEPLOY-15 | E2E deploy verification: `scripts/proxmox/test/` bats tests (mirroring coreci's test structure) + health-check + smoke against live CT | must | P1 | complete |
| REQ-DEPLOY-16 | `.dockerignore` excluding `node_modules`, `.git`, `__pycache__`, `.pytest_cache`, `client/dist` (rebuilt in image), `.ciagent/.env*` (secrets) | must | P1 | complete |
## Non-Functional Requirements (v0.2)
| REQ-ID | Requirement | Target | Phase | Status |
|--------|-------------|--------|-------|--------|
| REQ-NFR-DEPLOY-01 | Deploy idempotency — re-running `lxc-deploy.sh` against a healthy CT is a no-op; unhealthy CT requires explicit `--recreate`/`--reconfigure` | must | P1 | complete |
| REQ-NFR-DEPLOY-02 | Deploy rollback — any stage failure (clone/config/start/health) triggers `rollback.sh` (stop + destroy the partial CT) | must | P1 | complete |
| REQ-NFR-DEPLOY-03 | First-boot install time | < 5 min (Docker image load + compose up + health) | P1 | deferred (live cluster required) |
| REQ-NFR-DEPLOY-04 | Secrets never committed to git (`.ciagent/.env*` in `.gitignore`, secrets injected via `lxc.environment` at runtime) | must | P1 | complete |
## Out of Scope (v0.1)
- Mastery scoring, competency rubrics, verifiable credentials
- Multi-language (launch: Canadian English only)
- Employer dashboard
- Live Assist mode
- WhatsApp/SMS/USSD surfaces
- Drill Mode, Review Mode
- Scenario authoring marketplace
- B2B SaaS
- Voice cloning of real individuals
- Early childhood education, medical procedures (permanent per PRD §11.6)