Skip to content

[DONE] 정리 2단계 PR 3 — BOM 이 빌드 가이드 부품표나 회로도와 어긋나면 CI 가 빨개지는 검사 둘을 단다 - #28

Merged
patternflow-bot merged 3 commits into
devfrom
claude/ops-cleanup-2-pr3-uz91vn
Oct 15, 2026
Merged

patternflow-bot merged 3 commits into
devfrom
claude/ops-cleanup-2-pr3-uz91vn

Conversation

@patternflow-bot

@patternflow-bot patternflow-bot commented Oct 15, 2026 •

Copy link
Copy Markdown

ops / https://claude.ai/code/session_01KYL31rYvPyhizskqp57VqM

정리 2단계 계획서 표의 PR 3 이다. BOM 과 빌드 가이드의 부품표, BOM 과 회로도 PDF 를 맞춰 보는 드리프트 검사 둘을 넣었다. 머지하면 하드 규칙 2(BOM·가이드·회로도를 같이 맞춘다)를 사람이 기억하지 않아도 웹 CI 의 check:ci 가 본다.

좋아지는 것: 없음

할 일

  • 계획서(docs/investigations/2026-10-cleanup-step2-plan.md) 표의 PR 3 행과 소견 3·4, docs/rfc-cleanup.md §2.1·§2.4·§2.11, docs/voice.md 를 읽는다
  • 표가 PR 3 에 적은 세 파일만 고친다: web/scripts/drift/_bom.ts, web/scripts/drift/bom.ts, web/scripts/drift/bom-schematic.ts
  • npm run check:ci 전체, typecheck, lint, check:drift 를 돌린다
  • 일부러 어긋나게 고친 판(따로 만든 worktree, 버림)에서 두 검사가 빨개지는 것을 보인다
  • pdftotext 가 없을 때 skip, PF_DRIFT_STRICT=1 이면 실패하는 것을 보인다
  • git fetch --tags 뒤 npm run doc-map 을 돌리고 두 CSV 는 커밋하지 않는다
  • dev 를 merge 한다(그새 들어온 [DONE] 정리 2단계 PR 2 — GitHub 절대 주소 링크 118개가 닿는지 보는 검사를 단다 #26 과 겹침 없음)
  • Web CI build 초록

한 일

  • web/scripts/drift/_bom.ts: 두 검사가 같이 쓰는 BOM 읽기. BOM(경로), bom()(CSV 를 머리 줄 이름으로 읽은 행들. 따옴표 안의 쉼표·"" 를 RFC 4180 대로 푼다), designators(ref)(J1 은 하나, SW1-SW4 는 넷, 하이픈이든 en dash 든. -·—·U1 (sockets) 처럼 그 밖의 칸은 0개. 거꾸로 쓴 범위는 throw).
  • web/scripts/drift/bom.ts(check:bom): BUILD_GUIDE.md 1절의 표 둘과 BOM 을 비교한다.
    • 보드 위(category 가 pcb): 줄마다 「지정자: 수량 × MPN」. 가이드의 MPN 칸 끝 (Bourns) 같은 제조사는 뗀다. 부품 이름은 비교하지 않는다(소견 3: 「Rotary encoder w/ switch」와 「…with push switch」처럼 일부러 다르게 쓴다). 소켓 줄은 BOM 의 U1 (sockets) 도 가이드의 — 도 지정자가 없어서 「—」로 맞는다.
    • 보드 밖(off-board): 지정자도 MPN 도 없어서 차례로 짝짓는다. 가이드 줄의 부품 이름이 짝 BOM 줄의 단어를 모두 가지면 같은 줄이다(「Sacrificial USB cable (it gets cut)」 ⊇ 「USB cable (sacrificial)」). 수량의 하이픈과 en dash 는 같다(6-12 = 6–12).
    • 표는 제목(### On the board·### Off the board) 아래 첫 표를 읽고, 필요한 열이 없으면 무엇이 없는지 말하고 실패한다.
  • web/scripts/drift/bom-schematic.ts(check:bom-schematic): pdftotext -layout hardware/pcb/schematic.pdf - 의 글에서 지정자 접두어(U, SW, J, C 와 R, D, Q, L, F, USB)로 시작하는 토큰을 모아 BOM 의 지정자와 비교한다. 핀 이름(S1S3, IO4IO48)과 ESP32 는 접두어가 없어 빠진다. pdftotext 가 없으면(ENOENT) skip()(D2). 첫날부터 strict 다(D4, 소견 4).

바뀐 줄: 3 파일, +171 −0. 다른 파일은 건드리지 않았다(git diff --stat origin/dev).

증거

npm run check:ci (web/, 머지 전 HEAD c149f27): exit 0. vitest Test Files 35 passed (35), Tests 478 passed (478), 끝은:

── bom
on the board: same
  hardware/bom/bom_v3.9.csv (7): C11: 1 × 16PX1000MEFC10X12.5, J1: 1 × 61201621621, J3: 1 × TB002-500-02BE, J4: 1 × TB002-500-02BE, SW1-SW4: 4 × PEC11R-4220F-S0024, U1: 1 × ESP32-S3-DevKitC-1-N16R8, —: 2 × PPPC221LFBN-RC
  BUILD_GUIDE.md (7): C11: 1 × 16PX1000MEFC10X12.5, J1: 1 × 61201621621, J3: 1 × TB002-500-02BE, J4: 1 × TB002-500-02BE, SW1-SW4: 4 × PEC11R-4220F-S0024, U1: 1 × ESP32-S3-DevKitC-1-N16R8, —: 2 × PPPC221LFBN-RC
off the board, rows pair in order, and a guide row with every word of its BOM row's part takes that name
off the board: same
  hardware/bom/bom_v3.9.csv (4): 1 × LED matrix panel, 1 × USB cable (sacrificial), 1 × USB power bank, 6-12 × M4 screw
  BUILD_GUIDE.md (4): 1 × LED matrix panel, 1 × USB cable (sacrificial), 1 × USB power bank, 6-12 × M4 screw
── bom-schematic
designators: same
  hardware/bom/bom_v3.9.csv (9): C11, J1, J3, J4, SW1, SW2, SW3, SW4, U1
  hardware/pcb/schematic.pdf (9): C11, J1, J3, J4, SW1, SW2, SW3, SW4, U1
── features
...
passed   bom
passed   bom-schematic
passed   features
check:ci exit 0

dev(#26) 를 merge 한 뒤 HEAD 427437d: npm run typecheck exit 0, npx eslint scripts/drift/ scripts/doc-map.ts exit 0, npm run check:drift:

passed   bom
passed   bom-schematic
passed   features
passed   links-absolute
drift exit 0

npm run lint(전체): exit 0, ✖ 12 problems (0 errors, 12 warnings). 경고 12개는 모두 원래 있던 src/ 의 것이다.

Web CI build(HEAD 427437d): success. 러너 로그 끝은 passed bom, skipped bom-schematic(designators: skipped, pdftotext is not installed (poppler-utils)), passed features, passed links-absolute. 가정에 적은 대로 웹 CI 러너에는 poppler 가 없어서 회로도 비교는 k10 의 strict 워크플로에서 처음 돈다.

일부러 어긋나게 고친 판(따로 만든 worktree 에서, 고친 뒤 git checkout 으로 되돌리고 worktree 는 지움):

판 1, 가이드의 J4 수량 1→2, C11 MPN 끝 .5 지움, check:bom exit 1:

on the board: drift
  only in hardware/bom/bom_v3.9.csv: C11: 1 × 16PX1000MEFC10X12.5, J4: 1 × TB002-500-02BE
  only in BUILD_GUIDE.md: C11: 1 × 16PX1000MEFC10X12, J4: 2 × TB002-500-02BE
off the board: same
failed   bom

판 2, 가이드 보드 밖의 「Sacrificial USB cable」→「Sacrificial cable」, 나사 6–12→6–10, check:bom exit 1:

off the board: drift
  only in hardware/bom/bom_v3.9.csv: 1 × USB cable (sacrificial), 6-12 × M4 screw
  only in BUILD_GUIDE.md: 1 × Sacrificial cable (it gets cut), 6-10 × M4 screw
failed   bom

판 3, BOM 에 R1 줄을 더하고 C11 줄을 지움, check:bom-schematic exit 1 (양쪽 방향 다):

designators: drift
  hardware/bom/bom_v3.9.csv (9): J1, J3, J4, R1, SW1, SW2, SW3, SW4, U1
  hardware/pcb/schematic.pdf (9): C11, J1, J3, J4, SW1, SW2, SW3, SW4, U1
  only in hardware/bom/bom_v3.9.csv: R1
  only in hardware/pcb/schematic.pdf: C11
failed   bom-schematic

판 4, 가이드의 소켓 줄 —→U1: only in BUILD_GUIDE.md: U1: 2 × PPPC221LFBN-RC, failed bom, exit 1.

판 5, BOM 의 SW1-SW4→SW4-SW1: Error: SW4-SW1: a range keeps one prefix and counts up, failed bom-schematic, exit 1.

판 6, pdftotext 없는 PATH(node·git 만): designators: skipped, pdftotext is not installed (poppler-utils) / skipped bom-schematic exit 0. 같은 PATH 에 PF_DRIFT_STRICT=1: PF_DRIFT_STRICT=1, so a skip fails / failed bom-schematic exit 1.

git fetch --tags 뒤 npm run doc-map: 1070 links from 213 files, 0 do not resolve, 1366 Korean/English pairs. 지도 CSV 에 4줄이 더 생기는데 모두 docs/investigations/2026-10-cleanup-step5-plan.md 에서 나가거나 들어오는 줄이다(dev 에 이미 있는 #24). origin/dev 에서 같은 명령을 돌린 CSV 와 이 브랜치의 CSV 가 cmp 로 같다. 이 PR 이 바꾼 지도 줄은 없다. 두 CSV 는 git checkout 으로 되돌렸다.

docs/voice-banned.txt 의 말은 새 파일에 없다. em dash 는 가이드 칸의 값 — 을 그대로 적은 곳뿐이다.

실행법

cd web
npm ci
npm run check:bom
npm run check:bom-schematic     # pdftotext(poppler-utils)가 있어야 비교한다. 없으면 skip
PF_DRIFT_STRICT=1 npm run check:drift

가정

  • 보드 밖 줄은 계획서대로 차례로 짝짓는다. 가이드 표가 BOM 에서 나온다(하드 규칙 2)고 봐서 순서가 바뀌는 것도 드리프트로 본다.
  • 보드 위에서 「부품」은 MPN 으로 본다. 이름은 소견 3 대로 비교하지 않는다. 가이드 MPN 칸의 제조사(「Würth」 대 「Würth Elektronik」)도 비교하지 않는다.
  • 지정자인지는 ref 칸 전체가 X1 이나 X1-X4 꼴인지로 가린다. 그래서 U1 (sockets) 는 지정자가 없고, 회로도 쪽 BOM 지정자는 소견 4 의 아홉 개가 된다. 그 줄의 notes 를 읽어 가리지는 않는다.
  • 계획서의 접두어 목록에 USB 하나를 더했다. v3.0 보드의 USB-C 자리가 USB1 이었고, 그것이 회로도에 돌아오면 하드 규칙 6 의 일이라 BOM 에 없는 채로 보이면 빨개져야 한다고 봤다. 지금 PDF 에는 USB 로 시작하는 토큰이 없다.
  • PDF 쪽은 언급만 보므로 같은 지정자가 여러 번 나와도 하나로 센다. BOM 쪽은 중복까지 센다(두 줄이 같은 지정자를 쓰면 드리프트).
  • 웹 CI 의 check:ci 는 PF_DRIFT_STRICT 없이 돈다. 러너에 pdftotext 가 없으면 bom-schematic 은 skipped 로 지나간다(이 PR 의 CI 가 그랬다). strict 로 도는 것은 k10 의 drift.yml 몫이다(계획서 D2·D4).
  • CHANGELOG.md·docs/rfc-cleanup-progress.md·doc-map CSV 는 고치지 않았다(머리말·계획서대로). 넣을 줄은 아래 「Changelog」. 검사가 지키는 것이 하드웨어 규칙이라 ### Hardware 절에 둔다.
  • 라벨 cleanup·step-2 는 포크에 없어서 달지 않았다(D7).
  • 덧붙임: 회로도의 표제란은 Rev: 3.0 이다(patternflow.kicad_sch 의 (rev "3.0") 도 같다). 지정자는 v3.9 BOM 과 맞아서 이 검사의 드리프트는 아니다. hardware/ 는 이 PR 몫이 아니라 그대로 두었다.

for another k

  • k10: bom-schematic 이 CI 에서 strict 로 비교하려면 drift.yml 이 pdftotext 없을 때 poppler-utils 를 깔아야 한다(계획서 k10 그대로).
  • k2(머지됨)의 web/scripts/doc-map.ts: --check absolute 가 skip 일 때도 exit 0 으로 끝나서(process.exit(failed ? 1 : 0)) 러너가 passed links-absolute 로 찍는다. 이 PR 의 CI 로그에 links-absolute: skipped 바로 뒤 passed links-absolute 가 있다. skip 이면 exit 75(_lib.ts 의 SKIPPED)여야 러너가 skipped 로 읽는다. strict 일 때 1 로 끝나는 것은 맞다. k2 행 파일이라 이 PR 에서 고치지 않았다.
  • k13: doc-map CSV 를 다시 만들면 step 5 계획서([DONE] 정리 5단계를 PR 넷으로 나눈 계획서 — 기록 하나와 RFC 초안 둘을 셋이 같이 써도 파일이 안 겹친다 #24)의 4줄이 더해진다. 이 PR 의 줄은 아니다.

Changelog

Hardware

  • check:bom and check:bom-schematic hold the BOM to the build guide and the schematic. Hard rule 2 as two checks. A designator, an MPN or a quantity that hardware/bom/bom_v3.9.csv and the parts tables in section 1 of BUILD_GUIDE.md do not share turns check:ci red, and so does a designator that the BOM and hardware/pcb/schematic.pdf do not share. The schematic's designators come out of its text layer through pdftotext (poppler); where it is not installed the check skips, and under PF_DRIFT_STRICT=1 the skip fails. Part names on the board are not compared, since the guide words them its own way. Off the board, where there is no MPN, the rows pair in order and each guide row keeps every word of its BOM row's part.

Upstream

  • What: Add check:bom, the BOM against the two parts tables in section 1 of BUILD_GUIDE.md, and check:bom-schematic, the BOM designators against the text layer of hardware/pcb/schematic.pdf, with their shared BOM reader web/scripts/drift/_bom.ts.
  • Checks: npm run check:ci, npm run typecheck, npm run lint (0 errors) and npm run check:drift pass; edits to the guide or the BOM turn each check red; without pdftotext it skips, and fails under PF_DRIFT_STRICT=1.
  • Docs map: none

🤖 Generated with Claude Code

https://claude.ai/code/session_01KYL31rYvPyhizskqp57VqM

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYL31rYvPyhizskqp57VqM
The BOM against the build guide's two parts tables, and the BOM's
designators against the schematic PDF's text layer (pdftotext).
Cleanup step 2, PR 3 of docs/investigations/2026-10-cleanup-step2-plan.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYL31rYvPyhizskqp57VqM
@patternflow-bot patternflow-bot changed the title [WIP] Patternflow 정리 2단계 PR 3 [DONE] 정리 2단계 PR 3 — BOM 이 빌드 가이드 부품표나 회로도와 어긋나면 CI 가 빨개지는 검사 둘을 단다 Oct 15, 2026
@patternflow-bot
patternflow-bot marked this pull request as ready for review October 15, 2026 00:40
@patternflow-bot
patternflow-bot merged commit 1be94ec into dev Oct 15, 2026
1 check passed
@patternflow-bot
patternflow-bot deleted the claude/ops-cleanup-2-pr3-uz91vn branch October 15, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants