Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .claude/skills/asa-context/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
name: asa-context
description: Use this skill at the start of a session working on the ASA project (Ableton Sonic Analyzer) at ~/code/projects/asa, or when the user says "load asa context", "/asa-context", "warm up on asa", "what's the asa project about", or asks for an overview of ASA's mission, architecture, or quality invariants. Loads the canonical project docs and produces a structured summary the user can scan to confirm the assistant has the right context.
version: 0.1.0
---

# ASA Context Loader

## Purpose

Bring an agent (or a fresh session) up to speed on the Ableton Sonic Analyzer project in a single, sourced summary. ASA is opinionated — read the canonical docs in order, do not paraphrase from memory.

## When to use

- Start of any session where ASA work is the focus.
- User says "load context", "/asa-context", "warm up on asa", "give me the asa overview".
- An agent has been asked to make a non-trivial change to ASA and you want a sanity check that it has internalized the quality invariants before it writes code.

## Procedure

Read the following files in this exact order. Do not skip — each one builds on the prior.

1. `~/code/projects/asa/PURPOSE.md` — **highest authority.** Mission, target user, what good output looks like, the 6 quality invariants, decision framework. Read in full.
2. `~/code/projects/asa/AGENTS.md` — root agent-facing guide. Build commands, testing strategy, key modules.
3. `~/code/projects/asa/apps/backend/AGENTS.md` — backend-specific patterns and contracts.
4. `~/code/projects/asa/apps/ui/AGENTS.md` — frontend-specific patterns and contracts.
5. `~/code/projects/asa/CLAUDE.md` — Claude Code-specific guidance for working in this repo. (Some content overlaps with AGENTS.md — read for the parts that differ.)
6. `~/code/projects/asa/BACKLOG.md` — backport candidates from `sonic-architect-app`. Read **headings only** unless the user asks about a specific item.

If `~/code/projects/asa/docs/ARCHITECTURE_STRATEGY.md` exists, also read it — it records *why* the three-layer design is shaped the way it is, and is required reading before proposing structural changes.

## Output format

After reading, produce a structured summary in this exact shape. Keep it to 10–14 lines total so it's scannable.

```
**ASA Context Summary**

Mission: <one sentence from PURPOSE.md>

Architecture (three layers):
1. Measurement — <one phrase, name the engine>
2. Pitch/note translation — <one phrase, name the tools>
3. Interpretation — <one phrase, name the model>

Quality invariants (from PURPOSE.md, all six by name):
1. Measurement authority
2. Citation chain
3. Ableton specificity
4. Honest uncertainty
5. Reconstruction completeness
6. Intermediate accessibility

Working stack:
- Backend: <python version, key libs>
- Frontend: <framework + key deps>
- Ports: UI <port>, backend <port>

Notable in-flight or recently-touched:
- <bullet from BACKLOG.md or recent CHANGELOG, if obvious>
- <bullet>

Pointers (read these before changing the matching surface):
- apps/backend/prompts/phase2_system.txt — Phase 2 system prompt
- apps/backend/JSON_SCHEMA.md — Phase 1 schema
- docs/ARCHITECTURE_STRATEGY.md — structural decisions
```

## Quality bar for the summary

The summary is correct if:

1. **All six quality invariants are named** (by the labels above — "Measurement authority", etc.). Missing any one is a regression.
2. **The mission line is from PURPOSE.md**, not invented. Paraphrasing is fine; new claims are not.
3. **Three-layer architecture is named correctly** — Measurement / Pitch-note translation / Interpretation. Other orderings or names are wrong.
4. **Working stack mentions Python 3.11.x** (the version constraint is load-bearing — Essentia 2.1b6 wheels are 3.11-only on macOS arm64).
5. **Pointers list at least the three files above.**

If you cannot confirm a claim from a file you actually read in this session, say "not confirmed in loaded docs" instead of guessing.

## After the summary

Offer the user one of:
- "Tell me what you're working on and I'll pull in the relevant deeper docs."
- "Want me to read `docs/ARCHITECTURE_STRATEGY.md` or a specific `apps/*/AGENTS.md` more carefully before we start?"

Do not start coding until the user has confirmed direction.
139 changes: 139 additions & 0 deletions .claude/skills/asa-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
name: asa-dev
description: Use this skill when the user wants to start ASA's full development stack (frontend + backend together) and says "start asa", "run asa locally", "/asa-dev", "bring asa up", "spin up the dev server", or asks to launch ASA for local testing. Runs preflight checks (Python 3.11, venv, npm deps, ports 3100/8100 free, .env wiring) BEFORE invoking scripts/dev.sh, and routes specific failure modes to specific fixes instead of dumping cryptic stack traces.
version: 0.1.0
---

# ASA Dev Launcher (Guarded)

## Purpose

`scripts/dev.sh` is the canonical entry point for the full ASA stack — it starts the backend on 8100, waits for the OpenAPI contract, and then launches the UI on 3100. The script already does some preflight, but new contributors (and AI agents) hit the same setup gaps repeatedly: missing venv, missing `node_modules`, occupied ports, stale `.env.local` files. This skill front-runs those checks so the failure mode is named, not mysterious.

## When to use

- The user wants ASA running and asks for it ("start asa", "/asa-dev", "bring up the dev environment").
- An AI agent has been asked to do work that requires a live ASA instance (e.g., smoke-testing a UI change end-to-end).
- After a fresh clone, or after `git pull` brought in dependency changes.

**Do NOT use** for: single-process invocations (`python analyze.py <file>`), running tests (use `asa-verify`), or background CI work.

## Procedure

### Step 1 — Locate the repo

Default to `~/code/projects/asa`. If the user is in a different working directory and clearly wants ASA, confirm before continuing.

### Step 2 — Run preflight checks in order

Stop at the first failure and route the user to the fix. Do NOT auto-fix — these checks gate real environmental decisions.

#### 2a. Python 3.11.x available

```bash
python3.11 --version 2>/dev/null || python3 --version
```

The Python version constraint is load-bearing — Essentia 2.1b6 wheels are only published for 3.11 on macOS arm64. If neither `python3.11` is on PATH nor `python3 --version` reports 3.11.x:

- **Fix:** Install Python 3.11.x (typically via `brew install python@3.11`).
- Do not attempt to run the backend with Python 3.12+ — `apps/backend/scripts/bootstrap.sh` will fail.

#### 2b. Backend venv exists

```bash
test -x ~/code/projects/asa/apps/backend/venv/bin/python && \
~/code/projects/asa/apps/backend/venv/bin/python --version
```

- If the venv is missing or the Python inside it is not 3.11.x:
**Fix:** Run `~/code/projects/asa/apps/backend/scripts/bootstrap.sh` (must be invoked from inside `apps/backend/`). Bootstrap is destructive (recreates the venv) — ask the user before running.

#### 2c. Frontend `node_modules` exists

```bash
test -d ~/code/projects/asa/apps/ui/node_modules && \
test -f ~/code/projects/asa/apps/ui/node_modules/.package-lock.json
```

- If missing or stale:
**Fix:** `npm --prefix ~/code/projects/asa/apps/ui install`. Ask before running (npm install can be slow).

#### 2d. Ports 3100 and 8100 are free

```bash
lsof -nP -iTCP:3100 -sTCP:LISTEN
lsof -nP -iTCP:8100 -sTCP:LISTEN
```

- If anything is listening on 3100, identify the process (name + PID).
- If anything is listening on 8100, same.
- **Two common cases:**
1. **A stale ASA backend or UI** from a previous run — kill with `kill <PID>` after confirming with the user.
2. **Something unrelated** (another dev server, a system service) — abort and let the user decide. Do not kill blindly.

The canonical ports are baked in: UI on 3100, backend on 8100 (or `SONIC_ANALYZER_PORT`). `scripts/dev.sh` fails loudly if they're occupied — better to surface that here with the process identified.

#### 2e. UI `.env` is sane

```bash
cat ~/code/projects/asa/apps/ui/.env 2>/dev/null
```

Check:
- File exists. If missing, copy from `.env.example` and proceed.
- `VITE_API_BASE_URL` is set. `scripts/dev.sh` overrides this for the spawned process to point at the local backend, but a stale file with a hosted URL can still confuse later builds. Surface the value to the user.
- `VITE_ENABLE_PHASE2_GEMINI` — if `true`, the user should know that Phase 2 calls will need `GEMINI_API_KEY` set in the backend environment. Mention it.

### Step 3 — Launch

If all preflight passes:

```bash
cd ~/code/projects/asa && ./scripts/dev.sh
```

This is a long-running foreground process. Run it in the foreground (NOT background) so the user sees the logs and can Ctrl-C it. Do not wrap it in `nohup` or `&`.

### Step 4 — Confirm it came up

The user will see `dev.sh`'s own output, including:
- Backend startup banner
- OpenAPI contract check passing
- UI startup (Vite reporting `Local: http://127.0.0.1:3100`)

If you're verifying from outside the terminal, wait 8–10 seconds and check:

```bash
curl -fsS http://127.0.0.1:8100/openapi.json | jq -r '.info.title'
# expected: Sonic Analyzer Local API
curl -fsS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3100
# expected: 200
```

## Failure modes — fast routing

| Symptom | Likely cause | Fix |
|---|---|---|
| `python3.11: command not found` | Python 3.11 not installed | `brew install python@3.11` |
| `Missing required command: jq` (from dev.sh) | jq not installed | `brew install jq` |
| `Address already in use: 8100` | Stale backend | `lsof -nP -iTCP:8100 -sTCP:LISTEN` → `kill <PID>` |
| `ModuleNotFoundError: essentia` | Venv broken or wrong Python | `apps/backend/scripts/bootstrap.sh` (run from `apps/backend/`) |
| `Vite reports the wrong API URL` | Stale `apps/ui/.env` overriding | confirm what `dev.sh` is exporting; clear stale `.env` |
| UI 200s but `/api/analyze` 502s | Backend is up but errored | tail backend stderr; check `GEMINI_API_KEY` if Phase 2 was attempted |
| OpenAPI title is wrong | Someone changed `server.py` title | revert or update the contract probe expectations in `asa-verify` |

## Gotchas

- **`scripts/dev.sh` overrides `VITE_API_BASE_URL`** for the spawned UI process. A stale value in `apps/ui/.env` won't break the dev session but *will* break `npm run build` if used as-is. If the user reports "production-like behavior" surprises after `dev.sh`, check `.env`.
- **`SONIC_ANALYZER_PORT` is honored by `dev.sh`** but not by every script. If the user is on a non-default port, mention it explicitly in the report so they don't get confused later.
- **Bootstrap is destructive** — it recreates the venv from scratch. Always ask first.
- **AI agents in restricted shells:** if you cannot run interactive long-lived processes, run `dev.sh` in background mode and tell the user where to watch the logs — but explicitly note that interrupting it requires killing the PID.

## After launch

Do not start coding or testing immediately. Wait for the user to confirm:
- The UI is accessible at http://127.0.0.1:3100
- The backend is responsive at http://127.0.0.1:8100

If they want to verify with a real upload, point them at `apps/ui/tests/fixtures/` (if it exists) for a small sample file, or let them drop in their own.
132 changes: 132 additions & 0 deletions .claude/skills/asa-explain/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
name: asa-explain
description: Use this skill when the user asks what a Phase 1 measurement field in the ASA project means, hands you a dotted field path like "kickDetail.fundamentalHz" or "spectralBalance.subBass", says "/asa-explain <field>", or asks "what does crest factor mean in ASA", "where does this number come from", or "how should I interpret this measurement". Looks up the field in the canonical ASA schema docs and grounds it against Ableton Live 12 concepts via the Ableton Knowledge MCP.
version: 0.1.0
---

# ASA Measurement Field Explainer

## Purpose

Translate a Phase 1 measurement field into a producer-grounded answer: what it measures, what range to expect, why it matters for the reconstruction blueprint, and which Live 12 device(s) surface or shape it.

Inputs the user might hand you:
- A dotted path: `kickDetail.fundamentalHz`, `spectralBalance.subBass`, `sidechainDetail.pumpingStrength`
- A concept name: "crest factor", "the BPM agreement field", "spectral flatness"
- A measurement value in context: "ASA says my track has spectralCentroid 4200 Hz — what does that mean?"

## Procedure

### Step 1 — Normalize the request to a dotted path

If the user gives you a concept name, identify the matching field path. Common mappings:

- "crest factor" → `crestFactor` (root scalar)
- "BPM" → `bpm` + `bpmConfidence`; mention `bpmDoubletime` if half/double-time correction is relevant
- "key" → `key` + `keyConfidence`
- "stereo width" → `stereoDetail.stereoWidth`
- "spectral centroid" → `spectralDetail.spectralCentroidMean` (the post-normalization name — the field uses `Mean` suffix after server normalization; this is documented in the Phase 2 prompt as a common mistake to avoid)

If you cannot map the request to a known field, say so and ask the user to clarify before proceeding.

### Step 2 — Look up the field in the canonical schema

Read the relevant section(s) of `~/code/projects/asa/apps/backend/JSON_SCHEMA.md`. The doc is grep-friendly:

```bash
grep -n "^### \`<containerName>\`" apps/backend/JSON_SCHEMA.md
```

The file is organized as `## Section Name` → `### \`containerName\`` → bullet points per field. Section index includes:
- Core Metrics (root scalars: `bpm`, `key`, `lufsIntegrated`, `crestFactor`, etc.)
- Loudness & Dynamics (`lufsCurve`, `dynamicCharacter`, `textureCharacter`)
- Stereo (`stereoDetail`)
- Spectral Balance (`spectralBalance`, `spectralBalanceTimeSeries`, `spectralDetail`)
- Rhythm (`rhythmDetail`, `grooveDetail`, `beatsLoudness`, `rhythmTimeline`, `sidechainDetail`, `effectsDetail`)
- Melody (`melodyDetail`, `transcriptionDetail`)
- Pitch Detail (`pitchDetail`)
- Harmony (`chordDetail`, `segmentKey`)
- Synthesis Character (`synthesisCharacter`, `perceptual`, `essentiaFeatures`)
- Structure (`structure`, `arrangementDetail`, `segmentLoudness`, `segmentSpectral`, `segmentStereo`)

Capture: the field's definition, type/range, and any caveats the schema doc calls out.

### Step 3 — Confirm against the TypeScript type

Read the corresponding type definition. Phase 1 types live in `~/code/projects/asa/apps/ui/src/types/measurement.ts` (re-exported via `apps/ui/src/types/index.ts`). Confirm:
- The field name is spelled the same as in the schema.
- The optional/nullable status matches (the schema doc says "feature functions return `null` on failure" — this is real, downstream consumers must handle nulls).

If the schema doc and the TS type disagree, **flag the drift in your output**. This is a real bug class.

### Step 4 — Ground it in Ableton Live 12

Call `mcp__Ableton_Knowledge__search_live_manual` with a query oriented around the *Live device or concept* that this measurement informs, not the measurement name itself. Examples:

| Measurement | Good search query |
|---|---|
| `crestFactor` | "Compressor transient handling Glue Compressor attack" |
| `spectralBalance.subBass` | "EQ Eight low shelf sub bass band" |
| `sidechainDetail.pumpingStrength` | "sidechain compression Compressor external sidechain" |
| `kickDetail.fundamentalHz` | "Operator Drum Rack kick fundamental tuning" |
| `stereoDetail.stereoCorrelation` | "Utility width mono compatibility" |
| `melodyDetail.vibratoExtent` | "pitch modulation LFO vibrato in instruments" |

For root-level rhythm/timing fields (`bpm`, `key`, `timeSignature`), search for the Live concept that uses them — warp modes, time-signature handling, key signature.

If `search_live_manual` returns weak results, fall back to `mcp__Ableton_Knowledge__search_knowledge_base` for help-article-level context. Skip videos (`search_videos`) for this skill — the goal is a precise definition, not a tutorial.

### Step 5 — Compose the answer

Use this exact structure. Keep each section to 1–3 sentences.

```
**Field:** `<dotted.path>` (alias: <human name> if applicable)

**What it measures:**
<plain-English definition. If the schema gives units, include them.>

**Typical range / interpretation:**
<expected range; what "high" vs "low" means in practice.>

**Why it matters for the reconstruction blueprint:**
<which Phase 2 recommendations cite this, or which kind of decision it enables. Tie to the citation contract if relevant.>

**Related Live 12 device(s) / concept(s):**
<1–3 specific devices/parameters from the Ableton Knowledge MCP results, with exact spelling.>

**Sources:**
- `apps/backend/JSON_SCHEMA.md` § <section name>
- `apps/ui/src/types/measurement.ts` (line range)
- Live 12 manual: <article title from MCP result, with URL if returned>
```

### Step 6 — Flag drift, hedges, and gotchas

After the structured answer, surface:

1. **Documented gotchas** from `apps/backend/prompts/phase2_system.txt` lines 93–97 — if the user's path is one of the historically-typoed ones, name the correct spelling:
- `monoCompatible` is top-level, **not** `stereoDetail.monoCompatible`.
- Spectral mean fields use the `Mean` suffix after server normalization — use `spectralDetail.spectralCentroidMean`, **not** `spectralDetail.spectralCentroid`.
- Sidechain fields live under `sidechainDetail`, **not** `pumpingDetail`.
2. **Confidence pairing** — if the field has a sibling `<field>Confidence` (e.g., `bpm` ↔ `bpmConfidence`), say so and remind that low-confidence measurements must produce hedged recommendations (Quality Invariant #4).
3. **Drift between schema and type** — if you spotted any in Step 3.

## Quality bar

The answer is correct if:

1. The field path is one that actually appears in `apps/backend/JSON_SCHEMA.md` (or is explicitly called out as not present and renamed).
2. The Live 12 device/concept named comes from the MCP result, not from memory.
3. The "Sources" section cites real files and a real MCP-returned manual article.
4. Any documented gotcha that applies to this field is flagged.

Do not invent ranges. If the schema doesn't state a range, say so and offer a typical-music range as a separate, labeled annotation.

## After the answer

Offer one follow-up:
- "Want me to also explain a related field?" (suggest one based on the section the user's field lives in)
- "Want to see how this field is cited in `phase2Validator.ts` or `phase2_system.txt`?"

Don't volunteer a redesign or refactor unless asked — this skill is an explainer, not a code-changer.
Loading