Repository navigation
[DONE] 정리 4단계 PR 20 — 오디오 WebSocket 벡터가 가상 패널에서 돌고, check:audio-vectors 가 PR 마다 본다 - #85
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9se1jvH1i5Sc12oaN2xSW
Twelve vectors of docs/audio-ws-spec.md and three REST vectors of /api/audio, replayed against the virtual panel through a WebSocket sender Node 20 can run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9se1jvH1i5Sc12oaN2xSW
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M9se1jvH1i5Sc12oaN2xSW
patternflow-bot
marked this pull request as ready for review
October 15, 2026 16:08
This was referenced Oct 15, 2026
engmung
pushed a commit
to engmung/Patternflow
that referenced
this pull request
Oct 15, 2026
engmung
pushed a commit
to engmung/Patternflow
that referenced
this pull request
Oct 15, 2026
Patternflow-lab#11 Patternflow-lab#12 Patternflow-lab#13 Patternflow-lab#15 Patternflow-lab#17 Patternflow-lab#14 Patternflow-lab#16 Patternflow-lab#19 Patternflow-lab#20 Patternflow-lab#18 Patternflow-lab#21 Patternflow-lab#23 Patternflow-lab#24 Patternflow-lab#25 Patternflow-lab#26 Patternflow-lab#28 Patternflow-lab#29 Patternflow-lab#30 Patternflow-lab#27 Patternflow-lab#31 Patternflow-lab#32 Patternflow-lab#34 Patternflow-lab#35 Patternflow-lab#33 Patternflow-lab#36 Patternflow-lab#37 Patternflow-lab#38 Patternflow-lab#39 Patternflow-lab#40 Patternflow-lab#41 Patternflow-lab#42 Patternflow-lab#43 Patternflow-lab#46 Patternflow-lab#44 Patternflow-lab#47 Patternflow-lab#48 Patternflow-lab#49 Patternflow-lab#45 Patternflow-lab#50 Patternflow-lab#51 Patternflow-lab#52 Patternflow-lab#54 Patternflow-lab#57 Patternflow-lab#55 Patternflow-lab#53 Patternflow-lab#56 Patternflow-lab#59 Patternflow-lab#58 Patternflow-lab#60 Patternflow-lab#61 Patternflow-lab#62 Patternflow-lab#63 Patternflow-lab#64 Patternflow-lab#65 Patternflow-lab#66 Patternflow-lab#67 Patternflow-lab#68 Patternflow-lab#69 Patternflow-lab#70 Patternflow-lab#72 Patternflow-lab#73 Patternflow-lab#71 Patternflow-lab#75 Patternflow-lab#74 Patternflow-lab#77 Patternflow-lab#78 Patternflow-lab#76 Patternflow-lab#79 Patternflow-lab#80 Patternflow-lab#81 Patternflow-lab#82 Patternflow-lab#84 Patternflow-lab#83 Patternflow-lab#85 Patternflow-lab#86 Patternflow-lab#87 Patternflow-lab#88 Patternflow-lab#90 Patternflow-lab#91 Patternflow-lab#89 Patternflow-lab#92
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dev / https://claude.ai/code/session_01M9se1jvH1i5Sc12oaN2xSW
정리 4단계 계획서 표의 PR 20 이다. audio-ws-spec.md 의 문장 하나씩을 담은 벡터 열두 개를 docs/audio-ws-vectors/ 에, /api/audio 의 REST 벡터 셋을 docs/rest-api-vectors/ 에 두고, Node 20 에서 도는 WebSocket 보내는 쪽과 그것으로 벡터를 가상 패널에 돌리는 check:audio-vectors 를 더했다. 머지되면 CI 가 PR 마다 오디오 WebSocket 계약을 가상 패널에 돌려 보고, 스펙 문장이 바뀌면 그 문장을 옮긴 벡터가 빨개진다.
좋아지는 것: 없음
할 일
docs/contract-vectors.md,_vectors.ts, PR 19([DONE] 정리 4단계 PR 19 — 가상 패널이 오디오 WebSocket 으로 레인을 잡고 놓으며, /api/audio 로 AUD 스위치를 켜고 끈다 #84)의 「for another k」를 읽는다web/scripts/drift/_ws.ts: Node 20 에서 도는 WebSocket Sender, 벡터마다 소켓 하나web/scripts/drift/audio-vectors.ts:replay("docs/audio-ws-vectors", { ws })docs/audio-ws-vectors/: README 와 벡터 열둘docs/rest-api-vectors/audio-*.json셋DeviceSim규칙, REST 와 스펙 문장), 되돌림. 열다섯 벡터가 모두 한 번 이상 빨개졌다536bb0b에서 Drift checks(PF_DRIFT_STRICT=1,passed audio-vectors)와 Docs point at files that exist 가 success536bb0b에서 success78b4538,tools/virtual-panel/transports/midi.ts하나)가 들어왔다(58de9d8). 충돌 없음. typecheck, lint, check:drift, 링크, 잠금, 글투, audio·rest 벡터 다섯 번씩 다시 통과58de9d8의 CI: Drift checks(116526590493,PF_DRIFT_STRICT=1로passed audio-vectors), Docs point at files that exist(116526590119), Web CI(116526588679) 셋 다 success78b4538그대로라 merge 할 것이 없다한 일
_ws.ts는_vectors.ts에 넘기는wsSender 다. CI 의 Node 20 에는 WebSocket 클라이언트가 없어서node:http의 upgrade 위에 RFC 6455 를 보내는 쪽만큼 짰다(D2, 의존성 없음). 핸드셰이크 뒤Sec-WebSocket-Accept를 키와 맞춰 보고, 보내는 프레임은 다 마스크한다(PR 19: 마스크 없는 프레임은 1002 로 닫힌다). 벡터의ws는 프레임 하나의 글이고,{ "close": 1000 }은 그 코드의 close 프레임이다. 패널이 보낸 텍스트 프레임은heard에 넣는다. 스펙은 패널이 아무것도 보내지 않는다고 한다.settle()은 ping 을 보내고 pong 을 기다린다. 패널은 프레임을 받은 순서대로 읽으므로, pong 이 오면 그 앞에 보낸 메시지는 다 패널의 inbox 에 있다.setImmediate몇 번에 기대지 않는다. 2초 안에 답이 없으면 그 벡터가 「threw」로 빨개진다. close 도 패널의 close 프레임이 돌아올 때까지 기다린다.벡터는 스펙의 절로 이름을 나눈다. 패널은 프레임 끝에 받은 것을 읽어서 레인은 20 ms,
d=는 그다음 프레임에 패턴에 닿아 50 ms 를 준다.saysmessages-a-in a slot … (27행)a=0.25,0.5,0.75,1뒤a=0.8,-,-,0.2면lanes가[0.8,0.5,0.75,0.2], 400 ms 뒤-였던 둘만 놓인다.a=-0.5,0.25,-,-는 둘째 레인이 0.25, 셋째와 넷째는 그대로messages-kN(0..3) toF(clamped …) (28행)k=0,v=0.25,k=2,v=1.5,k=3,v=-2→lanes[0.25,_,1,0],laneActive[T,F,T,T]messages-dd=1,v=0.5→ 패턴이 받은 delta[0,24,0,0], 레인은 잡지 않는다.d=1,v=-0.25,d=3,v=-1뒤[0,12,0,-48]messages-off-nN… (30행)off=2→ 셋째만,off=0→ 첫째도 놓인다messages-offoff→ 넷 다 놓인다messages-unknownx=1,k=4,v=0.5,d=4,v=1,off=x,hello→ 레인 그대로, delta 0. 그다음k=1,v=0은 먹는다lanes-handd=는 둘째 레인을 놓지 않는다. 4760 ms 에 다시 보내도 첫 레인은 손의 것이고, 5060 ms 에 돌아온다lanes-busPOST /api/params?p1=700뒤 다시 보낸a=에도 첫 레인은 놓이고 버스가 잡는다lanes-closeaudioClients1, close 1000 뒤 넷 다 놓이고audioClients0release-500mscontract-vectors.md의 예시 그대로. 400 ms 엔[T,F,F,T], 600 ms 엔 넷 다 놓인다release-resendswitch-offon=0이면 잡힌 레인이 바로 놓이고audioRuntimefalse. 꺼진 동안a=와d=는 레인도 delta 도 없고 소켓은 열려 있다(audioClients1).on=1뒤k=가 먹는다REST 벡터 셋,
/api/audio다.rest-vectors.ts에는 WebSocket Sender 가 없어 소켓 없이 돈다.saysaudio-capscaps가["patterns","params","sleep","audio"],GET /api/audio는 JSON 200. 기본 빌드 쪽은 PR 7 의absent-*가 본다audio-getaudioRuntime(the switch) andaudioClients… (488행)audioRuntime은 boolean, 소켓이 없으니audioClients0audio-poston=0/1. Persisted in NVS; answers with the new state. (489행)on=0과 폼on=1의 답이{"ok":true,"audioRuntime":…}로 새 상태고, 다음 GET 도 같다README 는 이름 머리, 메시지를 적는 법, 20 ms 와 50 ms 의 까닭, 「normalized」를 읽은 법, 펌웨어와 다른 셋, 다시 돌리지 않는 것을 적는다(D11).
증거
로컬, web/:
깨뜨린 넷. 각각
git checkout으로 되돌렸고, 되돌린 뒤 passed.audio-ws.ts를 펌웨어처럼:a=의 칸이-로 시작하면 건너뛰고 나머지를 다음 칸으로 읽고(core_audio_ws.h:126),off=x를off=0으로(163),d=의 클릭을sim.nudge대신sim.turn으로(patternflow.ino:1333처럼 손으로 친다).audio-ws.ts의 버그 다섯:k=를 자르지 않고,d=의 배율을 반으로,off=N이 반대쪽 레인을 놓고off는 아무것도 놓지 않고, 꺼진 동안에도 메시지가 레인을 쓰고, 닫힌 소켓이 레인을 놓지 않는다.(벡터 ← 패널로 줄였다.)
messages-k는 이 판에서 통과했다.DeviceSim.setLane도 0..1 로 자르기 때문이다. 셋째 번에 그것까지 빼니 빨개졌다.deviceSim.ts(되돌림):setLane이 자르지 않고, 레인을 700 ms 에 놓고, 손이 4초만 잡고, 버스가 레인 위에 있지 않다.audio-ws.ts의k=자르기도 뺐다.GET /api/audio의audioClients에 1 을 더하고,POST가 바뀌기 전 상태로 답하고, caps 에서audio를 빼고,audio-ws-spec.md48행의 「five seconds」를 「three seconds」로.doc-map 의 새 줄은 넷이고 다 닿는다.
docs/audio-ws-vectors/README.md에서docs/audio-ws-spec.md,docs/contract-vectors.md,docs/rest-api-vectors/README.md,tools/virtual-panel/README.md로.GitHub, 이 PR:
536bb0b에서 「Drift checks / check」(job 116522245422) 로그에PF_DRIFT_STRICT=1로passed audio-vectors,passed rest-vectors,passed roadmap,check:human-lock: no locked words changed. CI 의 Node 는 20 이라_ws.ts가 그 위에서 돈 것이다. 「Docs point at files that exist / check」(116522241840)와 「Web CI / build」(116522242354)도 success.dev 의 PR 15 를 merge 한
58de9d8에서 로컬로 다시:panel.ts는transports/의 파일을 다 불러오므로, 이 실행은midi.ts가 불러와진 채로 돌았다. GitHub 에서도58de9d8의 「Drift checks / check」(116526590493) 로그에passed audio-vectors,passed rest-vectors,passed roadmap이 찍혔고, 「Docs point at files that exist」(116526590119)와 「Web CI / build」(116526588679)가 success 다.실행법
벡터 하나를 고쳐 보려면
docs/audio-ws-vectors/의 JSON 을 고치고 같은 명령을 돌린다.가정
docs/audio-ws-vectors/,docs/rest-api-vectors/audio-*.json,_ws.ts,audio-vectors.ts만 더했다.CHANGELOG.md,docs/rfc-cleanup-progress.md, doc-map CSV,web/package.json(PR 2 가check:audio-vectors를 이미 넣었다),contract-vectors.md,_vectors.ts,tools/virtual-panel/는 안 고쳤다. 라벨은 앞 PR 들처럼 달지 않았다.-칸이 있는a=, 잘리는k=,d=,off=N과off, 모르는 머리, 500 ms 뒤 놓이고 다시 보내면 남는 레인, 손이 5초 잡는 레인,audioRuntime이 꺼진 동안 무시되는 메시지)에 둘을 더했다. 버스가 레인 위라는 것(lanes-bus)과 소켓이 닫히면 레인을 놓는 것(lanes-close)이다. 둘 다 스펙의 문장이고 가상 패널이 이미 그렇게 한다.d=가 레인을 붙잡아 두지 않는 것(PR 19 의 다섯째 issue)은 기기에서 따로 보이지 않는다. 한 클릭 이상의d=는 아래 셋째 issue 대로 그 노브를 5초 잡아 버리고, 반 클릭이 안 되는d=에서만 드러난다.release-500ms만contract-vectors.md의 예시라POST /api/audio?on=1로 시작한다.rest-api.md382행이 48 detent 로 적는다(「48 detents cross a parameter's entire declared range」). 그래서messages-d는 0.5 를 24 클릭으로 본다. 값은 0.5, 0.25, 1 처럼 48 을 곱해 딱 떨어지는 것만 써서, 스펙이 말하지 않는 반올림에 기대지 않는다.{ "close": code }는contract-vectors.md의 표(「A message is the frame's text」)에 없는 꼴이다. 그 문서는 PR 3 의 파일이고_vectors.ts는 얼어 있어, Sender 와 이 폴더 README 에만 적었다. 소켓이 하나라 「last write wins」와 다른 소켓이 열린 채 하나가 닫히는 경우는 벡터가 없다(README).messages-a의a=-0.5,…단계는 첫 레인 값을"<number>"로만 본다. 스펙은a=의 범위 밖 값을 어떻게 하는지 말하지 않는다(k=만 「clamped」). 보는 것은 둘째 칸이 둘째 레인이고-칸이 손대지 않는다는 것이다.audio-post는 「Persisted in NVS」를 보지 않는다. 가상 패널에는 다시 켜는 일이 없다.firmware/와web/src/를 건드리지 않아build.sh all,check:ci,check:panels는 §2.1(1) 대상이 아니다. 계획서대로 typecheck 와 이 PR 의 check, 깨뜨린 실행을 적었다.Changelog
Tools
docs/audio-ws-vectors/holds twelve, each one sentence ofdocs/audio-ws-spec.mdand the messages that show a panel doing it, froma=with-slots to a lane a hand holds for five seconds. Three more indocs/rest-api-vectors/readGETandPOST /api/audio.npm run check:audio-vectorsinweb/replays them against the virtual panel built with theaudiofeature, through a WebSocket client that runs on Node 20, and CI runs it with the other drift checks.for an issue
D9. 벡터는 스펙을 따르고, 펌웨어는 셋에서 다르다.
messages-a.jsonstep 07, 08 ·audio-ws-spec.md27, "A literal-in a slot leaves that lane untouched" ·core_audio_ws.h:126이-로 시작하는 칸을 건너뛰고 나머지를 다음 칸으로 읽는다.a=-0.5,0.25,-,-는 둘째 레인에 0.5, 셋째에 0.25 를 둔다.messages-unknown.jsonstep 06, 08 ·audio-ws-spec.md30 과 33,off=N과 "Anything else is silently ignored" ·core_audio_ws.h:163이strtol로off=x를off=0으로 읽어 첫 레인을 놓는다.lanes-hand.jsonstep 04, 05 ·audio-ws-spec.md48, "A physical turn of an encoder takes that knob back" ·patternflow.ino:1333이 노브의 delta 면 무엇이든 5초 잡기를 건다. 12 클릭이 되는d=1,v=0.25가 둘째 레인을 놓는다. 질문 28 의 경우다.PR 19 가 적은 나머지 둘은 벡터가 없다. 마지막 클라이언트가 나갈 때만 레인을 놓는 것(
core_audio_ws.h:182)은 소켓이 둘 있어야 보이고,d=가 레인의 시간을 찍는 것(99)은 위 가정대로 기기에서 따로 보이지 않는다.for another k
AGENTS.md의audio-ws-spec.md옆에docs/audio-ws-vectors/, 명령에check:audio-vectors.docs/README.md의audio-ws-spec.md줄에audio-ws-vectors/를, pfst 줄처럼.docs/contract-vectors.md는 k22 의 목록에 없지만, 그 표의ws칸에{ "close": code }를 적을 자리다.Upstream
npm run typecheck,npm run lintandnpm run check:drift(audio-vectors and rest-vectors included) pass; firmware/ and web/src/ are untouched.🤖 Generated with Claude Code
https://claude.ai/code/session_01M9se1jvH1i5Sc12oaN2xSW