diff --git a/AGENTS.md b/AGENTS.md index ea3a7af04c..e2a76755e2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ agents work efficiently. Documentation is structured in three levels under This gives you setup, architecture, code map, conventions, workflows, interfaces, gotchas, and security. 3. If a task needs more detail than L1 provides, follow links to L2 deep dives - in `docs/ai/L1/deep_dives/`. Load only the specific L2 file you need. + in `docs/ai/L1/L2/`. Load only the specific L2 file you need. ## Levels @@ -51,9 +51,9 @@ agents work efficiently. Documentation is structured in three levels under | update docs | code changed since last `last_reviewed` date | | test docs | verify docs give agents the right context | -For detailed procedures, read -[progressive-disclosure-standard.md](docs/progressive-disclosure-standard.md) -sections 6 (generate) and 7 (bootstrap). +For detailed procedures, read `progressive-disclosure-standard.md` +sections 6 (generate) and 7 (bootstrap) on the `docs/progressive-disclosure` +branch (the standard is not checked into main). ## Working Areas diff --git a/docs/ai/L1/01_setup.md b/docs/ai/L1/01_setup.md index 5df1744df4..0160b7eb57 100644 --- a/docs/ai/L1/01_setup.md +++ b/docs/ai/L1/01_setup.md @@ -67,6 +67,12 @@ docker exec -d ten_agent_dev bash -c \ task run > /tmp/task_run.log 2>&1" ``` +**Fresh worktree/checkout**: run `task install` FIRST (it includes the +python-deps step). Running `install_python_deps.sh` alone on a fresh tree +fails with `failed to build go app` because `ten_packages/system/` (including +`ten_runtime_go`) is only populated by the install. Step 1 above is for +refreshing deps after a container restart, when packages already exist. + Typical choices: - `voice-assistant` for standard vendor iteration and demo graphs - `voice-assistant-advanced` for generated multi-graph setups diff --git a/docs/ai/L1/05_workflows.md b/docs/ai/L1/05_workflows.md index 7f992c4c94..3d40d5a8fa 100644 --- a/docs/ai/L1/05_workflows.md +++ b/docs/ai/L1/05_workflows.md @@ -164,6 +164,10 @@ catches a miss. For an extension change under # 1. Format + static checks (CI: task check, task lint) sudo docker exec ten_agent_dev bash -c \ "cd /app && task format && task check && task lint" +# task lint / task lint-extension in-container ALWAYS exits non-zero with +# E0401 import-errors — the runtime imports only resolve in CI. Judge by +# comparing against a known CI-green extension (e.g. xai_asr_python shows +# the same E0401s); only warnings beyond that baseline are real findings. # 2. Standalone tests for the extension sudo docker exec ten_agent_dev bash -c \ diff --git a/docs/ai/L1/L2/extension_development.md b/docs/ai/L1/L2/extension_development.md index 0ff01250a3..767e02040a 100644 --- a/docs/ai/L1/L2/extension_development.md +++ b/docs/ai/L1/L2/extension_development.md @@ -694,6 +694,8 @@ There are **10 tests** (1 excluded by the default test runner): | `test_dump` | Audio dump files created correctly | | `test_metrics` | TTFW and TTLW metrics: positive, TTLW > TTFW | | `test_audio_timestamp` | start_ms and duration_ms accuracy | +| `test_same_session_finalize_reconnect` | Audio sent after finalize still transcribes (fresh session if the vendor closes) | +| `test_connection_status` | connection_status_changed events — **allowlist-gated** (see below) | | `test_long_duration_stream` | **Excluded by default test runner** — 5+ min stream without timeout | ### Critical Pass Criteria @@ -704,6 +706,29 @@ There are **10 tests** (1 excluded by the default test runner): - **Metrics**: TTFW > 0, TTLW > TTFW, both in milliseconds - **Audio format**: Accepts 16-bit PCM, 16kHz, mono, 320 bytes per frame +### Guarder Contract Gotchas (learned the hard way) + +- **Timestamps** (`test_audio_timestamp`): every final needs `duration_ms > 0`, + and consecutive finals must not overlap (`prev.start_ms + prev.duration_ms + <= next.start_ms`). If the vendor returns no per-segment timing, synthesize + contiguous timestamps from the audio timeline: start = end of the previous + segment, end = total user audio sent when the final arrives. +- **Invalid credentials must be NON-fatal** (`test_reconnection`): the test + feeds bad credentials and asserts every error in the window is non-fatal + (retry expected). Classify only HTTP 401/403 as immediately fatal; vendors + that reject bad keys another way (e.g. a websocket close code) must surface + a non-fatal error and let the reconnect manager escalate to FATAL at the + retry ceiling. Any fatal error inside the test window fails the test. +- **connection_status tests are allowlist-gated**: the guarder only asserts + `connection_status_changed` sequences for extensions listed in + `_EXTENSIONS_WITH_CONNECTION_STATUS` (in + `integration_tests/asr_guarder/tests/test_connection_status.py`); other + extensions skip these two tests — expect `N passed, 2 skipped`. +- **Capture the summary**: pipe guarder output to a log file + (`task asr-guarder-test ... > /tmp/guarder.log 2>&1; echo $?`) — piping to + `tail` reports the pipe's exit code, not pytest's, and the retry tracebacks + from `test_reconnection` push the summary line out of a short tail. + --- ## AudioFrame Creation Pattern