File size: 5,040 Bytes
b2e4883
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Contributing

## Code of conduct

Be kind. Accessibility-first means inclusive by default. See [the hackathon's CoC](https://musichackspace.org) for the baseline.

## Repo conventions

### Languages

- **TypeScript** for the web app (`apps/web/`)
- **Python 3.10+** for the audio service (`services/audio/`)
- **JSON** for pattern templates and onomatopoeia tables
- **YAML** for training data manifests

### Style

**TypeScript:**
- ESLint with `@typescript-eslint/recommended`
- Prettier for formatting
- No `any` unless absolutely necessary (and then comment why)
- Functional components, hooks, no class components
- Avoid `useEffect` for derived state β€” use `useMemo` or compute inline

**Python:**
- `ruff` for linting (replaces flake8, isort, etc.)
- `black` for formatting
- Type hints everywhere
- Pydantic for data models

### Naming

- Components: `PascalCase.tsx`
- Hooks: `useCamelCase.ts`
- Utilities: `camelCase.ts`
- Constants: `UPPER_SNAKE_CASE`
- Files match exports (one default export per file preferred)

### Git

**Commit format** (Conventional Commits):

```
<type>(<scope>): <description>

[optional body]

[optional footer]
```

Types:
- `feat` β€” new feature
- `fix` β€” bug fix
- `docs` β€” documentation only
- `style` β€” formatting, no code change
- `refactor` β€” code change that neither fixes a bug nor adds a feature
- `perf` β€” performance improvement
- `test` β€” adding or fixing tests
- `chore` β€” build, CI, tooling

Examples:
```
feat(parser): add onomatopoeia matcher with confidence scoring
fix(midi): correct GM drum map for china (should be 52, was 49)
docs(architecture): clarify Reaper integration is not a plugin
chore(ci): add axe-core to GitHub Actions
```

**Branch naming:**
- `feat/<short-description>`
- `fix/<short-description>`
- `docs/<short-description>`
- `chore/<short-description>`

Examples:
- `feat/voice-stt`
- `fix/midi-tempo-header`
- `docs/architecture-update`

### Pull requests

- One feature per PR
- PR description explains *what* and *why*
- Screenshots / screen recordings for UI changes
- Accessibility check included (NVDA test notes, axe-core results)
- All CI checks passing

### Accessibility requirements for every PR

If your PR touches the UI:

- [ ] Run axe-core locally (`npm run test:a11y`) β€” no AA violations
- [ ] Tab through the changed flow, verify focus order
- [ ] Test with NVDA (or document why you couldn't)
- [ ] All interactive elements have ARIA labels
- [ ] Color contrast meets WCAG AA (4.5:1 for normal text, 3:1 for large)
- [ ] No information conveyed by color alone

If your PR is docs-only or backend-only, skip these.

## Adding a new pattern template

1. Create `apps/web/data/patterns/<pattern-id>.json`
2. Follow the schema in [`03-data-model.md`](03-data-model.md#pattern-templates)
3. Test in the web app: `npm run dev`, load the pattern, generate MIDI, drag into Reaper
4. Verify the description reads naturally with a screenreader
5. Update the pattern list in [`03-data-model.md`](03-data-model.md#pattern-library--starting-list) if adding to the starting list

## Adding a new onomatopoeia

1. Edit `apps/web/data/onomatopoeia.json`
2. Add the entry with `patterns` (array of variants), `patternId`, and any defaults
3. Test the phonetic matcher: `npm run test:onomatopoeia`
4. Manually speak the variants, verify they map correctly

## Adding training data

1. Place audio in `data/training/oneshots/` or `data/training/loops/`
2. Preprocess: 44100 Hz mono, normalized to -14 LUFS
3. Add an entry to `data/training/manifest.yaml` with:
   - `id`, `path`, `category`, `tags`
   - `source`, `license`, `duration_seconds`
   - `bpm` (for loops only)
4. Run `python services/audio/training/preprocess.py` to regenerate the preprocessed versions
5. Verify the file plays correctly and the license is documented

## Accessibility testing protocol

Before opening a PR that touches UI:

1. **axe-core:** `npm run test:a11y` β€” must pass with no violations
2. **NVDA (Windows + Chrome/Firefox):**
   - Tab through the entire flow
   - Verify every state change is announced
   - Verify focus never disappears
   - Verify error states are announced
3. **VoiceOver (macOS + Safari):**
   - Repeat the NVDA flow
   - Especially test the grid navigation with VO + arrow keys
4. **Keyboard-only:**
   - Complete the entire demo flow without using the mouse
   - Verify every action has a keyboard equivalent
5. **High contrast:**
   - Enable Windows High Contrast Mode
   - Verify the UI is still usable
6. **200% zoom:**
   - Zoom the browser to 200%
   - Verify no content is cut off or unreachable

If any of these fail, the PR is not ready.

## Communication

- **Issues** β€” use GitHub Issues for bugs, feature requests, design questions
- **Discussions** β€” use GitHub Discussions for broader questions
- **Discord** β€” for real-time chat during the hackathon

## License

By contributing, you agree that your contributions will be licensed under the project's MIT license (code) or CC-BY (sample data where applicable).