From b3df27d099c0d6601e77fb945e066aef118c6fc7 Mon Sep 17 00:00:00 2001 From: slitty-codes Date: Mon, 8 Jun 2026 03:20:04 +1200 Subject: [PATCH] docs: fix command accuracy in CLAUDE.md and AGENTS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix unittest slash-path form → dotted module form in apps/backend/AGENTS.md - Add UPDATE_PHASE1_GOLDEN re-baseline command to CLAUDE.md Tripwire #4 - Add first-time Playwright install line to CLAUDE.md frontend commands - Add record_artifact pointer to analysis_runtime.py entry in CLAUDE.md - Add --source/--output invocation to build_live12_catalogue.py entry - Reconcile Node version in apps/ui/AGENTS.md against package.json (no engines field) Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 7 ++++--- apps/backend/AGENTS.md | 4 ++-- apps/ui/AGENTS.md | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c8859091..38e309b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,6 +137,7 @@ npm run verify # lint + test:unit + build + test:smoke (ful npm run lint # TypeScript type-check only (no ESLint/Prettier) npm test # All Vitest tests (vitest.config.ts include: tests/**/*.test.ts) npm run test:unit # Vitest, restricted to tests/services/ (the unit subset) +npx playwright install chromium # first-time Playwright setup (run once from apps/ui/) npm run test:smoke # Playwright smoke suite (tests/smoke/, default config) npm run test:smoke:live-gemini # Playwright smoke against the real Gemini Files API (tests/smoke/upload-phase2-live-gemini.spec.ts) npm run test:e2e # Playwright full e2e suite (playwright.full.config.ts) @@ -186,7 +187,7 @@ Operational and one-shot scripts live in two places. They are not on the request 1. `dev.sh` — full-stack dev launcher (covered above). Covered by `apps/backend/tests/test_root_dev_script.py`. 2. `test-e2e.sh` / `test-e2e-integration.sh` — e2e harnesses (covered above). Covered by `apps/backend/tests/test_root_e2e_script.py`. 3. `calibrate_confidence.py` — threshold-sweep harness for the pitch / chord / sidechain detectors. Research-only. Its unit test lives in `scripts/tests/test_calibrate_confidence.py`. -4. `build_live12_catalogue.py` — regenerates `data/live12_catalogue.json` (the source-extracted Live 12 device/parameter catalogue) from the upstream `gluon/AbletonLive12_MIDIRemoteScripts` checkout. Static AST extraction; carries no proprietary code. Re-run when the upstream commit shifts or the schema bumps; the published `data/live12_catalogue.schema.json` validates the output. +4. `build_live12_catalogue.py` — regenerates `data/live12_catalogue.json` (the source-extracted Live 12 device/parameter catalogue) from the upstream `gluon/AbletonLive12_MIDIRemoteScripts` checkout. Static AST extraction; carries no proprietary code. Re-run when the upstream commit shifts or the schema bumps; the published `data/live12_catalogue.schema.json` validates the output. Invocation: `scripts/build_live12_catalogue.py --source /path/to/gluon/AbletonLive12_MIDIRemoteScripts --output data/live12_catalogue.json` (or set `SONIC_ANALYZER_LIVE12_SOURCE` env var to omit `--source`). `apps/backend/scripts/`: 1. `bootstrap.sh` — recreate the Python 3.11 venv (covered above). `dev.sh` here is a thin shim that `exec`s the repo-root `scripts/dev.sh` full-stack launcher. `bin/asa` script contracts (install, bootstrap, cleanup) are covered by `apps/backend/tests/test_bootstrap_scripts.py`. @@ -271,7 +272,7 @@ Artifact access goes through `artifact_storage.py` rather than direct disk paths 1. **`analyze.py`**: Pure DSP pipeline entry point. Runs as a subprocess invoked by `server.py`. Coordinates the split feature modules below. **Writes JSON to stdout, diagnostics to stderr** — this contract is load-bearing. 2. **`analyze_core.py`, `analyze_audio_io.py`, `analyze_detection.py`, `analyze_estimate.py`, `analyze_rhythm.py`, `analyze_segments.py`, `analyze_structure.py`, `analyze_transcription.py`, `analyze_fast.py`**: Feature modules. Loadouts: BPM/key/LUFS/stereo/spectral balance, rhythm/melody detail, segment boundaries, transcription. `analyze_fast.py` is the streamlined pipeline used by `--fast`. 3. **`server.py`**: FastAPI app and router composition. Routes are organized into `server_phase1.py`, `server_phase2.py`, `server_upload.py`, `server_samples.py`. Handles multipart uploads, invokes `analyze.py` (or worker), normalizes raw output into the `phase1` HTTP contract. -4. **`analysis_runtime.py`**: SQLite-backed run state and stage queue management. Run state in `.runtime/analysis_runs.sqlite3`; artifacts in `.runtime/artifacts/`. +4. **`analysis_runtime.py`**: SQLite-backed run state and stage queue management. Run state in `.runtime/analysis_runs.sqlite3`; artifacts in `.runtime/artifacts/`. New artifact-producing code calls `record_artifact` — do not write `.runtime/` paths directly (see also Tripwire #6 and `artifact_storage.py`). 5. **`worker.py`**: Dedicated worker-process entry point for hosted-style background stage execution. In `local` profile, work runs in-process; in `hosted` profile, this is the worker role. 6. **`runtime_profile.py`**: Switchboard for `local` vs `hosted` profile and `all` vs `api` vs `worker` process roles (env: `SONIC_ANALYZER_RUNTIME_PROFILE`, `SONIC_ANALYZER_PROCESS_ROLE`). 7. **`artifact_storage.py`**: Storage-service boundary. Today writes to local disk; the interface is designed so callers do not assume disk paths forever. @@ -394,7 +395,7 @@ Things that look like normal code changes but silently break the contract. Most 1. **`print(...)` in [analyze.py](apps/backend/analyze.py) without `file=sys.stderr`.** Stdout is the JSON contract. Any stray print corrupts it and the server reports a parse error with no useful trace. The existing code is consistent about this — match the pattern (`print(f"[warn] ...", file=sys.stderr)`). 2. **Calling `analyze.py` as a subprocess without `--yes`.** The CLI prompts for confirmation when stdin is a TTY. Subprocess invocations must pass `--yes` or hang waiting for input. `server.py` already does; new callers must too. 3. **Renaming a field on only one side.** Python emits *camelCase* JSON directly (`bpmConfidence`, not `bpm_confidence`) — there is no conversion layer. A rename in [analyze.py](apps/backend/analyze.py) without a matching update in [src/types.ts](apps/ui/src/types.ts) is undetectable by either type system; the field just disappears from the UI. -4. **Adding a top-level key without updating `EXPECTED_TOP_LEVEL_KEYS`.** [tests/test_analyze.py](apps/backend/tests/test_analyze.py) holds a snapshot of every root key. New fields require updating that set *and* [JSON_SCHEMA.md](apps/backend/JSON_SCHEMA.md). The same test enforces that `--fast` only populates `FAST_MODE_POPULATED_FIELDS`. A change to *measured values* (not just keys) can also trip the golden-snapshot regression gate in [tests/test_phase1_golden.py](apps/backend/tests/test_phase1_golden.py) (fixture `tests/fixtures/golden/phase1_default.json`) — re-baseline it deliberately, never blindly. +4. **Adding a top-level key without updating `EXPECTED_TOP_LEVEL_KEYS`.** [tests/test_analyze.py](apps/backend/tests/test_analyze.py) holds a snapshot of every root key. New fields require updating that set *and* [JSON_SCHEMA.md](apps/backend/JSON_SCHEMA.md). The same test enforces that `--fast` only populates `FAST_MODE_POPULATED_FIELDS`. A change to *measured values* (not just keys) can also trip the golden-snapshot regression gate in [tests/test_phase1_golden.py](apps/backend/tests/test_phase1_golden.py) (fixture `tests/fixtures/golden/phase1_default.json`) — re-baseline it deliberately, never blindly (from `apps/backend/`): `UPDATE_PHASE1_GOLDEN=1 ./venv/bin/python -m unittest tests.test_phase1_golden` 5. **Using `document` or `window` in `tests/services/`.** Vitest runs in `node`, not `jsdom`. Service-layer tests are pure logic; if you need DOM, it's a Playwright test in `tests/smoke/` instead. 6. **Hard-coding `Path(...)` for artifacts in new code.** Artifact access must go through [artifact_storage.py](apps/backend/artifact_storage.py). Direct paths work in `local` profile and break silently in `hosted`. 7. **Editing `apps/ui/.env` and expecting `dev.sh` to honor it.** `dev.sh` reads `apps/ui/.env` but *overrides* `VITE_API_BASE_URL` for the spawned UI process so stale `.env` files don't break the stack. To point the UI at a non-canonical backend, edit `dev.sh` or run the UI directly with the env var on the command line. diff --git a/apps/backend/AGENTS.md b/apps/backend/AGENTS.md index 5beed8d3..04f2f9d1 100644 --- a/apps/backend/AGENTS.md +++ b/apps/backend/AGENTS.md @@ -80,8 +80,8 @@ python3.11 -m venv venv - Run one test module: ```bash -./venv/bin/python -m unittest tests/test_server.py -./venv/bin/python -m unittest tests/test_analyze.py +./venv/bin/python -m unittest tests.test_server +./venv/bin/python -m unittest tests.test_analyze ``` - Run one test class: diff --git a/apps/ui/AGENTS.md b/apps/ui/AGENTS.md index f2ea6c56..a865d87d 100644 --- a/apps/ui/AGENTS.md +++ b/apps/ui/AGENTS.md @@ -18,7 +18,7 @@ ## Environment And Setup -- Use Node 20+. +- Use Node 20 (per CI; no `engines` constraint in `package.json`). - Install dependencies: `npm install` - Create a local env file when needed: `cp .env.example .env` - Key env vars: