restructure: AGENTS.md canonical + docs/guides with .claude/rules symlinks
Rename CLAUDE.md -> AGENTS.md (cross-vendor standard) with a relative CLAUDE.md symlink so Claude Code still loads it. Move each .claude/rules file into docs/guides/ (paths: frontmatter preserved) and replace the rules file with a relative symlink into the guide. Repoint the AGENTS.md index paragraph at docs/guides/ so non-Claude agents find the guides.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
---
|
||||
paths:
|
||||
- "image/app/audio_proxy.py"
|
||||
- "image/app/speech_models.py"
|
||||
- "image/app/deep_health.py"
|
||||
- "image/parakeet_patches/**"
|
||||
- "scripts/test-audio-with-speakers.sh"
|
||||
- "docs/AUDIO_API.md"
|
||||
---
|
||||
|
||||
# Audio / speech stack (Parakeet STT + Sortformer diarizer + Kokoro TTS on Spark 2)
|
||||
|
||||
## Changing the parakeet-asr container
|
||||
|
||||
- `image/parakeet_patches/` (`main.py`, `diarizer.py`) is an overlay copied into the `parakeet-asr` container by the "Reapply speech-model patches" dashboard action (`image/app/speech_models.py`). This is the **only** durable way to change that container — `docker exec` / pip changes inside it die on `docker rm`.
|
||||
- **Never install `cuda-python` in parakeet-asr** to "fix" the startup warning about CUDA graphs being disabled. The warning is harmless; enabling the graph path crashes real decode with illegal memory access on this GPU/CUDA-13 stack (GB10/sm_121). The slow path served 11k+ requests with zero failures — leave it alone.
|
||||
- Pin/constrain torch versions when pip-installing anything into NGC-based containers on the Sparks (ABI breaks otherwise); expect ARM64 wheel gaps and source builds (`--no-build-isolation` for torchaudio). Applies to `spark_embed` too.
|
||||
|
||||
## Testing audio endpoints
|
||||
|
||||
- Test with **real speech** (e.g. `say -o /tmp/t.wav --data-format=LEI16@16000 "<a couple of sentences>"`), not tones/silence — zero-token audio skips the decoder paths where crashes live.
|
||||
- Send audio requests to Spark 2 **sequentially** in tests/scripts. Parallel audio requests can race (cuFFT → 503), and the single GPU serializes them anyway.
|
||||
- End-to-end suite (hits the LIVE cluster):
|
||||
|
||||
```bash
|
||||
./scripts/test-audio-with-speakers.sh <audio-file> # from repo root
|
||||
```
|
||||
|
||||
`SPARK_CONTROL` defaults to `http://127.0.0.1:9999` (a running local dev server); point it at the installed package URL otherwise.
|
||||
|
||||
## API quirk
|
||||
|
||||
Spark Control's `/v1/models` lists *audio* models (STT model + Kokoro voices) by design — **not** the loaded LLM. Discover the LLM via `/api/status` (`vllm.current_model`).
|
||||
|
||||
Diarizer caps at 4 speakers (Sortformer `diar_sortformer_4spk-v1`).
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
paths:
|
||||
- "image/**"
|
||||
---
|
||||
|
||||
# FastAPI image (`image/`)
|
||||
|
||||
Standalone FastAPI app (Python ≥3.11; ships on `python:3.12-slim`; UI on port 9999; vanilla HTML/CSS/JS, no framework). Python has no configured linter/formatter — match the style of the file you're editing.
|
||||
|
||||
## Local dev (no StartOS)
|
||||
|
||||
```bash
|
||||
cd image
|
||||
python3 -m venv .venv && source .venv/bin/activate # one-time
|
||||
pip install -e .
|
||||
export SPARK1_HOST=<ip> SPARK1_USER=<user> SPARK2_HOST=<ip> SPARK2_USER=<user> SSH_KEY_PATH=<private-key>
|
||||
# Required outside the container — these default to paths under /data, which only exists in the image
|
||||
# (missing REDACTION_MAP_DB crashes startup; missing CONNECTIVITY_LOG 500s /api/status):
|
||||
export REDACTION_MAP_DB=/tmp/redaction_maps.db CONNECTIVITY_LOG=/tmp/connectivity.json
|
||||
uvicorn app.server:app --host 0.0.0.0 --port 9999 --reload
|
||||
```
|
||||
|
||||
Other env vars: `BIND_PORT`, `MODELS_YAML`, `SSH_DIR`, `SSH_KNOWN_HOSTS`, `MODELS_OVERRIDES`, `SERVICES_OVERRIDES`.
|
||||
|
||||
## Tests
|
||||
|
||||
No pytest harness — each suite is a standalone script run with the `image/.venv` interpreter (system python3 has no deps). See the redaction and audio rules for the suites themselves.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Pydantic request models go at **module scope**, never inside a `build_router()` body (FastAPI silently 422s otherwise).
|
||||
- New external-facing endpoints get documented in `docs/` (`AUDIO_API.md`, `EMBEDDINGS.md`, `REDACTION_GATEWAY.md`) and noted in release notes.
|
||||
|
||||
## Layout
|
||||
|
||||
- `image/app/server.py` — FastAPI entry; routers live in sibling modules (`audio_proxy.py`, `llm_proxy.py`, `embeddings_proxy.py`, `redaction_gateway.py`, `swap.py`, `health.py`, `deep_health.py`, `connectivity.py`, …).
|
||||
- `image/app/static/` — the dashboard UI.
|
||||
- `image/models.yaml` — vLLM model catalog bundled into the image.
|
||||
- `image/spark_embed/` — Dockerfile + app for the embeddings container; built ON a Spark (ARM64, NGC PyTorch base — see the audio/cluster rule for NGC torch-pinning caveats).
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
paths:
|
||||
- "image/app/redaction/**"
|
||||
- "image/app/redaction_gateway.py"
|
||||
- "docs/REDACTION_GATEWAY.md"
|
||||
---
|
||||
|
||||
# Redaction (`/scrub` + `/rehydrate`)
|
||||
|
||||
- `image/app/redaction/scrub.py` + `test_scrub_leak.py` are vendored **byte-for-byte** from the CRM repo (sha recorded in `redaction/__init__.py`). **Never edit them here** — change them in the CRM repo, re-vendor (`cp`), update the sha, re-run the leak test.
|
||||
- The gateway around the vendored scrubber is `image/app/redaction_gateway.py`. Its token-map store lives on `/data` (`REDACTION_MAP_DB`, default `/data/redaction_maps.db`) and fails closed if it can't open — set the env var when running outside the container.
|
||||
|
||||
## Test suites — both must pass before shipping ANY redaction change
|
||||
|
||||
```bash
|
||||
cd image
|
||||
.venv/bin/python -m app.redaction.test_gateway # /scrub + /rehydrate acceptance; offline, no cluster needed
|
||||
.venv/bin/python app/redaction/test_scrub_leak.py # vendored golden-file leak test; offline
|
||||
```
|
||||
|
||||
Keep the leak test green against the vendored `scrub.py` after any re-vendor.
|
||||
|
||||
Policy context: scrubbed text via `/scrub` is the **only** sanctioned path toward frontier/cloud models — see the whole-repo privacy rule in CLAUDE.md.
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
paths:
|
||||
- "package/**"
|
||||
---
|
||||
|
||||
# StartOS package (`package/`)
|
||||
|
||||
TypeScript wrapper that ships the Docker image as an s9pk. `@start9labs/start-sdk` pinned `1.3.3`, Node ≥22, bundled by `@vercel/ncc`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cd package
|
||||
npm i # one-time
|
||||
make x86 # typecheck + ncc bundle + docker build + pack → spark-control_x86_64.s9pk
|
||||
make install # sideload to the Start9 server; needs "host: http(s)://<server>.local" in ~/.startos/config.yaml
|
||||
npm run check # tsc --noEmit — run after any startos/ edit; make x86 also runs it
|
||||
npm run prettier # prettier --write startos (no semicolons, single quotes, trailing commas)
|
||||
```
|
||||
|
||||
`make aarch64` for ARM Start9 servers. `make install` picks the newest `*.s9pk` in `package/` and restarts the live spark-control service — get a go/no-go first.
|
||||
|
||||
## Versioning & release notes
|
||||
|
||||
- Version format is `X.Y.Z:N` (`:N` = revision). Bump in `package/startos/versions/v0_1_0.ts`; **replace** the release notes — never leave old notes behind under an extra key (any unknown key fails `tsc`).
|
||||
- New external-facing endpoints get noted in release notes for downstream app developers (Recap Relay, Ten31 Transcripts, CRM, Signal Engine consume these APIs).
|
||||
|
||||
## Layout
|
||||
|
||||
- `package/startos/` — manifest, interfaces, actions (`configureSparks`, `showPublicKey`), `versions/v0_1_0.ts` (current version string + release notes).
|
||||
- The "Reapply speech-model patches" action is **not** a StartOS action — it's a dashboard action implemented in `image/app/speech_models.py`.
|
||||
Reference in New Issue
Block a user