Files

3.3 KiB

Personas — Milestone v0.2 (MVP)


active:

  • name: backend-engineer
  • name: data-engineer
  • name: frontend-engineer
  • name: ci-lead-developer phase_specific:
  • name: security-engineer phases: [2] reason: "v0.2 is the MVP: FastAPI backend + engine + adapters + trust loop (backend/data domains activate), the frontend consumes the OpenAPI-generated client in P3 (frontend stays active for the binding swap + P4 E2E), and the trust loop in P2 needs a phase-specific security-engineer for secrets handling and liveness verification. Lead-developer coordinates."

Roster

backend-engineer

  • Domain: backend
  • Active: true
  • Phase-specific: false
  • Frameworks: fastapi, pydantic v2, uv, uvicorn, sse-starlette, httpx, pytest, pytest-asyncio
  • Constraints: src-layout package researchx in backend/; all external I/O lives in adapters — engine imports no vendor SDKs (httpx only inside adapters); no blocking calls in async paths; durable state via atomic tmp+os.replace; never swallow CancelledError; API layer is transport only (no business logic); single uvicorn worker (single-user)
  • Territory: backend/**

data-engineer

  • Domain: data
  • Active: true
  • Phase-specific: false
  • Frameworks: pydantic v2 (schemas), pytest
  • Constraints: owns the pydantic schema contracts: dial schema (REQ-01), run state, evidence store models (stable passage IDs), citation ledger JSON schema (REQ-21); pure data + validation — no I/O in schema modules; every run persists resolved dial values (REQ-04)
  • Territory: backend/src/researchx/config/**, backend/src/researchx/evidence/**

frontend-engineer

  • Domain: frontend
  • Active: true
  • Phase-specific: false
  • Frameworks: next.js (App Router), react 19, typescript (strict), tailwind, vitest, openapi-fetch, openapi-typescript
  • Constraints: components never import the mock client or the generated client directly — only the ApiClient boundary does; RESEARCHX_API_MODE=mock|live selects the binding, mock default; no secrets or env keys in the frontend (NEXT_PUBLIC_API_BASE_URL only); zero component rewrites in the P3 swap (REQ-54/REQ-26)
  • Territory: frontend/**

security-engineer (phase-specific: P2)

  • Domain: security
  • Active: false (P2 shipped — removed per phase-specific policy)
  • Phase-specific: true
  • Frameworks: httpx, pytest, STRIDE analysis
  • Constraints: secrets resolve from env-file scopes only (OLLAMA_API_KEY, TAVILY_API_KEY, GITEA_TOKEN via .ciagent/.env.secrets) — never shell env, never logged, never in git; liveness verification and trust-loop code must not leak keys in errors or traces; SSRF guard for fetched URLs (private-address refusal); authority tiering must not phone home
  • Territory: backend/src/researchx/trust/**, backend/src/researchx/adapters/secrets*/**
  • Removal: deactivate after P2 ships

ci-lead-developer

  • Domain: coordination
  • Active: true
  • Phase-specific: false
  • Frameworks: ciagent workflows, git discipline
  • Constraints: enforce persona territories; adapter/engine boundary review (I/O only in adapters); commit discipline with ---ci--- blocks; phase-boundary file updates only (no .ciagent/ writes during task execution); gates green before every ship
  • Territory: .ciagent/**, repo root config files (README, VERSIONING, .gitignore)