+
+## Quick Start
+
+### 1) Setup
+```bash
+python run.py setup
+```
+
+What setup does:
+- creates/uses `.venv` (unless `--no-venv`)
+- installs dependencies
+- builds retrieval DB
+
+If you want to be able to use the LLM option, run setup with this command. It will download the flan-t5 model (~300MB):
+```bash
+python run.py setup --with-llm
+```
+
+### 2) Run Full Stack
+```bash
+python run.py fullstack
+```
+
+Endpoints:
+- API: `http://127.0.0.1:8000`
+- UI: `http://127.0.0.1:8501`
+
+### API Documentation
+When the API is running, interactive documentation is available at:
+- Swagger UI: http://localhost:8000/docs
+- ReDoc: http://localhost:8000/redoc
+
+## Run Commands
+
+```bash
+python run.py help
+python run.py api
+python run.py ui
+python run.py fullstack
+python run.py test
+python run.py test-matrix
+```
+
+`test-matrix` runs tox environments for available interpreters (`py310`, `py311`, `py312`).
+
+## Testing
+
+Single environment:
+```bash
+python run.py test
+```
+
+Multi-python matrix:
+```bash
+python run.py test-matrix
+```
+
+Direct:
+```bash
+python -m pytest -q
+tox
+```
+
+## CI (GitHub Actions)
+
+Workflow: `.github/workflows/ci.yml`
+
+Triggers:
+- push to:
+ - `main`
+ - `feature/customer-faq-assistant-cameron-d`
+- pull_request to:
+ - `main`
+ - `feature/customer-faq-assistant-cameron-d`
+- manual (`workflow_dispatch`)
+
+CI job:
+- Python matrix: 3.10 / 3.11 / 3.12
+- installs `requirements.txt`
+- runs `pytest -q`
+
+## API Overview
+
+- `GET /health`
+- `GET /db/status`
+- `POST /db/build`
+- `POST /ask`
+
+Example request:
+```json
+{
+ "question": "What can I do with the mobile app?",
+ "top_k": 3,
+ "generator": "mock"
+}
+```
+
+## Environment Variables
+
+- `RAG_MIN_SCORE` (minimum similarity score for retrieved documents. default: `0.25`)
+- `API_URL` (used by Streamlit UI; default `http://127.0.0.1:8000`)
+
+## Project Structure
+
+- `app/main.py` API routes
+- `app/retrieval.py` RAG retrieval/indexing logic
+- `app/generation.py` generator selection and LLM adapter
+- `app/rag_chain.py` LangChain prompt/chain
+- `ui/streamlit_app.py` UI
+- `SPECS/` authoritative feature specs
+- `tests/` test suite
+- `run.py` project entrypoint
+
+## Notes
+- Default mode is deterministic and intended for local testing/CI.
+- Optional `flan-t5` mode uses Google's Flan-T5-small (80M params) for local experimentation and requires model assets (~308MB download via `python run.py setup --with-llm`).
+- Project uses CPU-only PyTorch for faster setup and smaller footprint (~200MB vs ~2.5GB). GPU acceleration is unnecessary for the small models used in this project.
\ No newline at end of file
diff --git a/SPECS/ask-endpoint-validation.md b/SPECS/ask-endpoint-validation.md
new file mode 100644
index 00000000..836ba1a2
--- /dev/null
+++ b/SPECS/ask-endpoint-validation.md
@@ -0,0 +1,44 @@
+# Feature Spec: Ask Endpoint Validation
+
+## Goal
+- Enforce strict, predictable request validation for `POST /ask` so API behavior is safe and testable.
+
+## Scope
+- In:
+ - Validate request body fields `question` and `top_k`.
+ - Return consistent 400 errors for invalid input.
+- Out:
+ - Retrieval ranking behavior.
+ - Answer generation quality.
+
+## Requirements
+- Endpoint:
+ - `POST /ask`
+- Request schema:
+ - `question` is required string with length `5..300`.
+ - `top_k` is optional integer with default `3` and valid range `1..5`.
+ - `generator` is optional string with allowed values `mock` or `flan-t5`.
+- Validation failures MUST return HTTP 400.
+- Validation failures include:
+ - Missing `question`.
+ - `question` length below 5.
+ - `question` length above 300.
+ - `top_k` below 1.
+ - `top_k` above 5.
+ - `generator` not in allowed values.
+- Error responses MUST be JSON and machine-parseable.
+- Error responses MUST include a top-level `detail` field suitable for user-facing validation feedback.
+- Validation MUST run before retrieval or generation logic executes.
+- If DB is not built, endpoint MUST return `503` with actionable guidance to build DB first.
+
+## Related Specifications
+- `ask-response-contract.md` - Defines success response schema for valid requests
+- `retrieval-pipeline.md` - Processes validated requests
+
+## Acceptance Criteria
+- [x] Missing `question` returns `400`. (test_validation.py::test_ask_missing_question_returns_400)
+- [x] `question` shorter than 5 characters returns `400`. (test_validation.py::test_ask_question_too_short_returns_400)
+- [x] `question` longer than 300 characters returns `400`. (test_validation.py::test_ask_question_too_long_returns_400)
+- [x] `top_k = 0` returns `400`. (test_validation.py::test_ask_top_k_zero_returns_400)
+- [x] `top_k > 5` returns `400`. (test_validation.py::test_ask_top_k_above_range_returns_400)
+- [x] Omitted `top_k` is accepted and treated as `3`. (test_validation.py::test_ask_omitted_top_k_uses_default)
diff --git a/SPECS/ask-response-contract.md b/SPECS/ask-response-contract.md
new file mode 100644
index 00000000..ca970d74
--- /dev/null
+++ b/SPECS/ask-response-contract.md
@@ -0,0 +1,46 @@
+# Feature Spec: Ask Response Contract
+
+## Goal
+- Guarantee a stable JSON response contract from `POST /ask` across success and fallback paths.
+
+## Scope
+- In:
+ - Response schema for status `200`.
+ - Source object field contract.
+ - Retrieval metadata contract.
+- Out:
+ - HTTP error schema details outside `POST /ask` success response.
+
+## Requirements
+- `POST /ask` successful response MUST include keys:
+ - `answer`
+ - `sources`
+ - `retrieval`
+- `answer` MUST be a non-empty string.
+- `sources` MUST be an array (possibly empty).
+- Each `sources` item MUST include:
+ - `id` (non-empty string)
+ - `title` (non-empty string)
+ - `snippet` (non-empty string)
+ - `score` (number)
+- `retrieval` MUST include:
+ - `top_k` (integer)
+ - `matched` (integer)
+- Contract MUST remain stable for:
+ - Matched retrieval response.
+ - Fallback response (no sources).
+- In fallback response:
+ - `sources` MUST equal `[]`.
+ - `retrieval.matched` MUST equal `0`.
+
+## Related Specifications
+- `ask-endpoint-validation.md` - Defines request validation before response generation
+- `retrieval-pipeline.md` - Provides source data for response
+- `generation-mock.md` - Generates answer content for response
+
+## Acceptance Criteria
+- [x] Contract test validates required top-level keys exist on every 200 response. (test_contract.py::test_ask_response_contract_contains_required_top_level_keys)
+- [x] Contract test validates source item field presence and scalar types. (test_contract.py::test_ask_response_sources_have_required_fields_when_present)
+- [x] Contract test validates `answer`, `id`, `title`, and `snippet` are non-empty strings. (test_contract.py::test_ask_response_sources_have_required_fields_when_present)
+- [x] Fallback path preserves full schema and uses empty `sources`. (test_contract.py::test_ask_fallback_keeps_stable_schema)
+- [x] Retrieval metadata fields are always present and consistent with payload. (test_contract.py::test_ask_response_retrieval_metadata_has_required_fields)
diff --git a/SPECS/docker-optional.md b/SPECS/docker-optional.md
new file mode 100644
index 00000000..da1b7734
--- /dev/null
+++ b/SPECS/docker-optional.md
@@ -0,0 +1,35 @@
+# Feature Spec: Optional Docker Runtime
+
+## Goal
+- Provide an optional containerized workflow for running the Customer FAQ Assistant with consistent local environments.
+
+## Scope
+- In:
+ - Optional `Dockerfile` for the API runtime.
+ - Optional `docker-compose.yml` for API + Streamlit UI orchestration.
+ - Clear commands for building and running containers locally.
+ - Non-blocking usage that does not replace the default local workflow.
+- Out:
+ - Mandatory Docker dependency for development or test execution.
+ - Production-grade orchestration, autoscaling, or cloud deployment.
+
+## Requirements
+- Docker support MUST be optional and MUST NOT be required to run tests locally.
+- Default reviewer workflow MUST remain:
+ - local Python setup
+ - local `pytest` execution
+- If implemented, Docker artifacts MUST include:
+ - `Dockerfile` for API service
+ - `docker-compose.yml` for API and UI services
+- Container configuration MUST avoid embedding secrets or credentials.
+- Docker workflow MUST expose default local ports for API and Streamlit UI.
+- Documentation MUST state:
+ - Docker is optional
+ - Local non-Docker setup is fully supported
+ - How to build and run Docker services
+
+## Acceptance Criteria
+- [x] Project runs locally without Docker and all required tests execute.
+- [x] API can be built and started via Docker. (Dockerfile, docker-compose.yml::api)
+- [x] Optional compose workflow can start API and UI together. (docker-compose.yml, run.py::cmd_docker_fullstack)
+- [x] Documentation clearly separates optional Docker commands from default local workflow. (README.md)
diff --git a/SPECS/entrypoint-cli.md b/SPECS/entrypoint-cli.md
new file mode 100644
index 00000000..33b834f7
--- /dev/null
+++ b/SPECS/entrypoint-cli.md
@@ -0,0 +1,60 @@
+# Feature Spec: Entrypoint CLI (run.py)
+
+## Goal
+- Provide a single cross-platform entry point for setup, running services, and tests.
+
+## Scope
+- In:
+ - A `run.py` script that manages setup, API, UI, and test commands.
+ - Cross-platform support for macOS, Linux, and Windows.
+ - Clear help output with available commands.
+- Out:
+ - Full environment management beyond project dependencies.
+ - Complex process supervision or daemonization.
+
+## Requirements
+- `run.py` MUST support these commands:
+ - `setup`: Install dependencies.
+ - `setup --with-llm`: Install dependencies and download LLM assets.
+ - `api`: Run the FastAPI backend.
+ - `ui`: Run the Streamlit UI.
+ - `fullstack`: Run API and UI concurrently.
+ - `test`: Run pytest.
+ - `test-matrix`: Run tox-based multi-Python test matrix.
+ - `help`: Show available commands and examples.
+- `run.py` SHOULD support optional Docker helper commands:
+ - `docker-build`: Build container images.
+ - `docker-api`: Run API container.
+ - `docker-fullstack`: Run API and UI containers together.
+ - `docker-down`: Stop/remove running Docker Compose services.
+- `run.py` MUST be cross-platform and use `sys.executable` for subprocess calls.
+- `run.py` MUST default to creating and using a local `.venv` for setup.
+- `run.py` MUST support a `--no-venv` option to install into the current environment instead.
+- `run.py setup` MUST detect and prefer a supported Python interpreter for virtual environment creation.
+- Supported interpreter range for full project setup MUST be:
+ - `>=3.10`
+ - `<3.13`
+- `run.py setup` SHOULD prefer `3.12`, then `3.11`, then `3.10`, before fallback.
+- `run.py setup` MUST support overriding interpreter selection via `--python