<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>JH LIM — LAB NOTES</title>
    <link>https://jhlimlab.com</link>
    <atom:link href="https://jhlimlab.com/feed.xml" rel="self" type="application/rss+xml"/>
    <description>I build things, test them, and leave notes.</description>
    <language>ko</language>
    <lastBuildDate>Tue, 13 Oct 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>A Random Hexagram on Purpose</title>
      <link>https://jhlimlab.com/notes/a-random-hexagram-on-purpose</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-random-hexagram-on-purpose</guid>
      <pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate>
      <description>Sketched a framework that reads one problem twice — once by ordinary analysis, once through the sixty-four hexagrams — then argues the two readings against each other. One of the four hexagrams is drawn at random, and that is the point.</description>
      <content:encoded><![CDATA[
The thing I keep noticing


판단이 필요할 때 AI 에게 묻는다. 쓸 만한 답이 나온다.

그런데 같은 정보를 주고 비슷하게 물으면 대체로 같은 길로 간다.
빠진 각도가 있어도 그게 빠졌다는 것을 알려주지는 않는다.


A second coordinate system


주역을 가져와 보기로 했다. 점을 치려는 게 아니다.

64괘는 상황의 구조와 변화의 방향을 상징으로 적어 둔 좌표계다.
맞고 틀리고를 떠나서, 같은 문제를 다른 축으로 다시 적게 만든다.
축이 다르면 보이는 것이 다르다.


How it runs


한 문제를 두 번 읽고, 둘을 맞붙인다.

· 먼저 평소대로 분석한다 — 사실, 인과, 위험과 기회, 쓸 수 있는 선택지
· 다음에 주역으로 읽는다 — 지금 상황에 가까운 괘, 변화의 방향, 뒤집히는 경우
· 두 해석의 같은 점과 어긋나는 점을 늘어놓는다
· 어긋나는 자리에서 반대가설을 만든다 — 지금 결론이 틀렸다면 어디서 틀렸나
· 남은 것 중 현실에서 확인할 수 있는 것만 들고 나온다


The random one


괘는 넷을 뽑는다. 셋은 상황에 가까운 것으로 고르고, 하나는 무작위로 뽑는다.

관련 있는 괘만 고르면 이미 내린 결론을 주역의 말로 옮겨 적게 된다.
"역시 그렇다" 가 한 번 더 나올 뿐이다.

그건 두 번 읽은 게 아니다. 한 번 읽고 번역한 것이다.

무작위 괘는 그 자리를 흔들려고 넣는다.
그게 현실을 맞게 설명한다고 보지 않는다.
평소 안 하던 질문을 만들어 내는 자극으로만 쓴다.

“관련 있는 것만 고르면, 두 번 읽은 게 아니라 한 번 읽고 번역한 것이다.”


What this is not


주역은 검증된 예측 모델이 아니다. 이걸로 현실 판단을 대신하지 않는다.

나오는 것은 답이 아니라 가설이다.
가설은 현실 데이터로 확인해야 쓸 수 있고, 확인할 수 없는 것은 버린다.


Where it stands


아직 개념 설계다. 코드는 없다.

다음은 64괘의 상징과 변화 패턴을 구조화한 데이터, 그리고 매번 같은 순서로 도는 추론 절차다.
그래야 같은 문제를 다시 넣었을 때 같은 과정을 밟는지 볼 수 있다.

궁금한 건 결국 이것이다 — 서로 다른 사고체계를 부딪히게 하면 없던 가설이 나오는가.]]></content:encoded>
      <category>AI</category>
      <category>THOUGHTS</category>
      <category>framework</category>
      <category>reasoning</category>
      <category>bias</category>
      <category>iching</category>
      <category>idea</category>
    </item>
    <item>
      <title>The Caption Disagreed With the Curve</title>
      <link>https://jhlimlab.com/notes/the-caption-disagreed-with-the-curve</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/the-caption-disagreed-with-the-curve</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <description>The caption under a chart said one pair of numbers. The curve above it drew another. The words were typed by a person and the line was drawn by code, and nothing made them agree.</description>
      <content:encoded><![CDATA[
The numbers did not match


SemiFab AI 랜딩에 공정 값이 어떻게 흩어지는지 보여주는 작은 차트를 붙여 뒀다.
들어온 사람이 시뮬레이터를 열기 전에 한 번 보고 가는 그림이다.

그걸 고치다 나왔다.

설명글은 30 과 65 라고 적혀 있는데 그려진 곡선은 44 와 62 였다.

글은 사람이 적었고 그림은 코드가 그렸다.
둘이 같은 곳에서 나오지 않으니 어긋나도 아무도 모른다.


The axis was lying too


가로축 눈금이 -32 · -12 · 2 · 16 으로 떨어져 있었다.
숫자축인데 항목축으로 잡혀 있어서, 값의 간격이 아니라 데이터가 있는 자리마다 눈금이 찍혔다.

간격이 다른데 같은 폭으로 그려진다. 읽는 사람은 분포 모양을 잘못 본다.


Speed counted in frames


진행 속도가 프레임 수로 계산되고 있었다. 화면이 빠른 기기에서는 다른 값이 나온다.
설명글은 3.2 라고 적혀 있는데 화면에서는 139 쯤이 지나갔다.

시간 기준으로 바꿨다.


Three symptoms, one disease


셋 다 같은 병이다 — 화면에 적힌 말과 화면이 그린 것이 서로 다른 곳에서 나온다.
하나씩 고치면 다음 차트에서 또 난다.

그래서 창고 스킬에 철칙으로 옮겨 적었다.

· 설명글의 수치는 그림을 그린 엔진에서 계산한다. 손으로 적지 않는다
· 노이즈는 선을 흔들어 표현하지 않는다. 띠나 오차막대로 그린다
· 모델이 담지 않은 것은 차트 안에 적는다. 캡션 바깥으로 빼지 않는다
· 축에는 단위를 적는다. 임의 단위면 그렇다고 적는다

가르치는 그림은 틀려도 그럴듯해 보인다.
배우는 사람은 대조할 원본이 없어서, 틀린 줄 모르고 외운다.

“그림을 고치는 것보다 그림과 글이 같은 곳에서 나오게 하는 게 먼저다.”]]></content:encoded>
      <category>EDUCATION</category>
      <category>EXPERIMENT</category>
      <category>chart</category>
      <category>teaching</category>
      <category>honesty</category>
      <category>skill</category>
      <category>data</category>
    </item>
    <item>
      <title>I Ignored My Own Rule</title>
      <link>https://jhlimlab.com/notes/i-ignored-my-own-rule</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/i-ignored-my-own-rule</guid>
      <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
      <description>The drawing skill said the default line was a hand-drawn sketch, meant for rough concepts. It had been drawing finished equipment diagrams that way the whole time. I wrote that rule.</description>
      <content:encoded><![CDATA[
The default was a sketch


교재에 들어가는 그림을 손으로 안 그리고 코드로 뽑는다.
장비 단면, 계통도, 공정 흐름. 어떻게 그릴지를 규칙으로 적어 두고 거기 맞춰 낸다.

그 규칙에 기본 선을 손떨림으로 적어 뒀다. 개념 스케치에는 맞는 선이다.

그런데 확정 도면까지 그 선으로 그리고 있었다.
장비 단면도가 손으로 대충 그린 것처럼 나온다.

적어 둔 사람과 안 지킨 사람이 같다.


The parts were already there


창고에 장비 심볼이 서른한 종 있었다. MFC, 스로틀 밸브, 게이트 밸브, 터보 펌프.

그런데 부품을 매번 손으로 다시 그리고 있었다.
있는 줄 모르고 안 쓴 게 아니라, 있는 줄 알면서 안 썼다.


What changed


기본값을 정밀 제도선으로 뒤집었다. 손떨림은 "예외 — 개념 스케치" 로 내렸다.

선의 종류가 굵기와 색을 같이 정하게 했다.
구조 · 유체 · 전기 · 신호 · 보조. 그리는 사람이 굵기를 고르지 않는다.

창고 심볼을 쓰는 다리를 놓고, 창고를 못 찾으면 빈 그림이 아니라 실패로 끝내게 했다.
조용히 못 그린 그림이 교재로 나가는 것보다 낫다.

“규칙을 적어 두는 것과 지키는 것은 다른 일이다.”]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>EDUCATION</category>
      <category>claude-code</category>
      <category>skill</category>
      <category>diagram</category>
      <category>drawing</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Where the Skills Live</title>
      <link>https://jhlimlab.com/notes/where-the-skills-live</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/where-the-skills-live</guid>
      <pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
      <description>Claude Code reads skills from only three places, and none of them is shared across repositories. So one repo became a warehouse. Here is the whole structure, and the two things that kept not working.</description>
      <content:encoded><![CDATA[
The problem


Claude Code 에 스킬이라는 게 있는데, 반복해서 쓰는 절차를 문서로 적어 두면 필요할 때
알아서 꺼내 쓰는 구조입니다. 편한데 읽히는 자리가 정해져 있어요.
흔히 쓰는 건 셋입니다 — 작업 중인 저장소 안, 사용자 폴더, 그리고 설치한 플러그인.

저는 저장소를 여러 개 굴리다 보니 A 에서 만든 규칙이 B 에서는 안 보이고, 그때마다
복사해서 붙였는데 그러면 그때부터 둘이 따로 늙습니다. 나중엔 어느 쪽이 최신인지도
모르게 되고요.

한 대의 컴퓨터에서만 쓸 거면 사실 사용자 폴더(~/.claude/skills/)에 넣으면 끝납니다.
그 컴퓨터의 모든 프로젝트에서 읽히니까요. 굳이 아래처럼 만들 필요가 없습니다.

저는 그게 안 됐습니다. 사용자 폴더의 스킬은 클라우드 세션에서 읽히지 않고,
예약해 둔 작업은 매번 새 클라우드 세션으로 뜹니다. 거기서도 같은 스킬이 필요했어요.

여러 대에서 쓰거나, 스킬 말고 에이전트나 실행 엔진까지 같이 실어야 하면 그때 플러그인입니다.


The idea — a warehouse


그래서 스킬만 모아 두는 저장소를 하나 만들었습니다. 창고라고 부르고 있습니다.

Claude Code 가 플러그인으로 바깥 스킬을 읽을 수 있고, 플러그인 여러 개를 묶어 둔 것을
마켓플레이스라고 부르더군요. 이름은 거창한데 까 보면 GitHub 저장소 하나에 약속된 이름의
파일 몇 개 두는 게 전부였습니다.


What it looks like


목록표는 이렇게 생겼습니다.

플러그인 정보는 더 짧고요.

스킬 본문은 맨 위에 이름과 설명을 달고 시작하는데, 이 설명이 생각보다 중요합니다.
이걸 읽고 언제 꺼낼지를 정하다 보니, 실제로 입에서 나올 법한 말을 넣어 두는 쪽이
훨씬 잘 걸리더군요.


How to install it


쓰는 쪽에서는 두 줄이면 끝납니다.

저장소마다 자동으로 잡히게 하려면 그 프로젝트의 .claude/settings.json 에 적어 둡니다.
다만 조건이 하나 붙습니다. 아래를 보시고요.

이 방법은 내 컴퓨터에서 도는 세션에만 통합니다.
저장소의 settings.json 에 선언한 플러그인과 사용자 설정에만 켜 둔 플러그인은
클라우드 세션에서 로드되지 않습니다.

클라우드 세션에서도 그 스킬이 필요하면, 그 저장소의 .claude/skills/ 에 직접
커밋해 두는 쪽이 확실합니다. 창고 하나로 전부 덮이지는 않는다는 뜻이고요.


What caught me


여기가 본론인데요.

설정에 다 적어 놨는데 안 잡힙니다. 위의 두 항목을 모두 적어도 외부 플러그인은
처음 한 번은 직접 /plugin install 을 해줘야 켜지더라고요.

이게 은근히 무서운 게, 설정만 믿고 있으면 스킬이 없는 채로 작업이 그냥 흘러갑니다.
있는 줄 알았는데 없는 상태라 결과를 보기 전까지는 모릅니다.

하나 더 있습니다. 플러그인으로 옮기고 나면 스크립트가 자기 위치를 착각해요.

검수 스크립트를 "내 옆 폴더" 기준으로 작업 파일을 찾게 짜 뒀는데, 저장소 안에 있을 때는
맞지만 플러그인은 저장소 밖 캐시에 설치되다 보니 그때부터 엉뚱한 데를 봅니다.
한참 헤맸습니다.

반대로 플러그인이 들고 다니는 자기 자산(팔레트나 예제 같은 것)은 스크립트 옆에서
읽어야 맞고요. 둘을 이렇게 나눠 두면 헷갈릴 일이 없습니다.

· 작업 대상 → 프로젝트 기준 (CLAUDE_PROJECT_DIR)
· 자기 자산 → 플러그인 기준 (CLAUDE_PLUGIN_ROOT)


Did it actually help


이틀 뒤에 답이 나왔습니다.

다른 저장소에서 이 스킬을 실제로 쓰다가 선 굵기를 읽는 함수가 빈 값을 내고 있는 걸
발견했는데, 속성에 적힌 굵기를 찾고 있었고 정작 그쪽은 CSS 변수로 선언하고 있었거든요.
창고에서 한 번 고치니 쓰는 곳 전부에 반영됐습니다.

복사해 붙였더라면 저장소마다 따로 찾아 고쳐야 했을 텐데, 그러면 대개 한 곳은 빠뜨립니다.
그리고 빠뜨린 그 한 곳을 한참 뒤에 발견하고요.

“복사해서 붙인 순간부터 둘은 따로 늙는다.”


What this does not cover


스킬을 무엇으로 채울지는 여기서 다루지 않았습니다. 이 글은 어디에 두느냐까지입니다.

· 렌더 엔진처럼 무거운 걸 같이 실으면 처음 한 번 npm install 이 필요합니다
· 저장소를 비공개로 두면 본인만 설치할 수 있습니다. 나눠 쓸 생각이면 공개여야 하고요
· 스킬이 읽히는 자리는 위의 셋 말고도 더 있습니다. 하위 디렉터리, --add-dir 로 붙인
  폴더, 조직이 배포한 것까지 문서에 정리돼 있습니다

공식 문서와 대조해서 쓴 글입니다.
https://code.claude.com/docs/en/plugin-marketplaces]]></content:encoded>
      <category>AI</category>
      <category>EXPERIMENT</category>
      <category>claude-code</category>
      <category>skill</category>
      <category>plugin</category>
      <category>tooling</category>
      <category>recipe</category>
    </item>
    <item>
      <title>What the Crawlers Actually Got</title>
      <link>https://jhlimlab.com/notes/what-the-crawlers-actually-got</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/what-the-crawlers-actually-got</guid>
      <pubDate>Tue, 22 Sep 2026 00:00:00 GMT</pubDate>
      <description>Search engines and AI crawlers do not open a page the way a person does. Four times in seven months, the file they were handed was not the page I thought I had built.</description>
      <content:encoded><![CDATA[
Two different pages


검색엔진과 AI 는 사람처럼 페이지를 열지 않는다.

브라우저는 주소를 받아 코드를 실행하고 화면을 그린다.
크롤러는 대개 파일 하나를 받아 가고 거기서 끝낸다.

같은 주소인데 둘이 다른 것을 본다. 사람에게 멀쩡한 페이지가 기계에게는 비어 있을 수 있다.

일곱 달 동안 이게 네 번 어긋났다.


An empty page


2월에 처음 걸렸다. 사이트가 화면을 코드로 그리는 방식이라,
크롤러가 받아 가는 파일에는 글이 한 줄도 없었다. 빈 껍데기였다.

빌드할 때 미리 화면을 그려서 파일로 저장하게 했다.


The label that never shipped


페이지마다 기계용 설명표를 붙여 둔다. 이게 무슨 글이고 누가 만들었고 무엇을 다루는지.
5월에 검사 도구가 그 표에 빠진 항목이 있다고 알려줬다.

열어 보니 항목 하나가 문제가 아니었다.
표 자체가 저장된 파일에 한 장도 안 들어가 있었다.
미리 그려서 저장하는 과정에서 통째로 버려지고 있었다.

이게 왜 늦게 잡혔냐면, 브라우저로 열면 표가 멀쩡히 붙어 있기 때문이다.
코드를 실행하는 쪽에서는 보인다. 저장된 파일에만 없다.

GPTBot 이나 ClaudeBot 이 받아 가는 게 바로 그 파일이다.


The map nobody updated


llms.txt 라는 파일이 있다. 이 사이트에 무엇이 있는지 AI 에게 알려주는 목록이다.

페이지가 23개인데 8개만 적혀 있었다.

파일 맨 위 주석에는 페이지를 추가하면 알아서 따라온다고 적혀 있었다.
시뮬레이터만 그랬다. 나머지는 아무도 연결해 두지 않았다.
인용될 만한 게 제일 많은 블로그가 통째로 빠져 있었다.

목록과 실제 페이지를 대조해서 빠진 게 있으면 빌드를 세우게 했다.
붙이자마자 내가 못 본 다섯 개가 더 나왔다.


A file that changed by itself


어제 하나 더 나왔다. 아무것도 안 고쳤는데 저장되는 파일이 매번 달라졌다.

그림에 점 300개를 무작위로 찍는 자리가 있었다.
미리 그릴 때 한 번 찍고, 브라우저에서 또 다르게 찍는다.

둘이 어긋나니 화면에 오류가 나고, 파일도 빌드할 때마다 내용이 바뀐다.
파일이 바뀌면 이미 퍼져 있던 사본이 전부 무효가 된다.

무작위에 기준값을 하나 박았다. 같은 조건이면 항상 같은 그림이 나온다.

“사람이 보는 화면이 멀쩡한 것과 기계가 받는 파일이 멀쩡한 것은 다른 일이다.”


Why I keep checking


네 건 다 조용했다. 화면은 멀쩡했고 빌드는 통과했고 배포는 성공했다.
아무도 알려주지 않는다. 찾아봐야 나온다.

랜딩에 페이지가 하나 늘 때마다 이 중 하나가 다시 어긋난다.
그래서 점검을 내 기억이 아니라 빌드에 붙여 두는 쪽으로 옮기고 있다.]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>THOUGHTS</category>
      <category>geo</category>
      <category>seo</category>
      <category>crawler</category>
      <category>prerender</category>
      <category>llms-txt</category>
      <category>semifab</category>
    </item>
    <item>
      <title>Did You Press the Button</title>
      <link>https://jhlimlab.com/notes/did-you-press-the-button</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/did-you-press-the-button</guid>
      <pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate>
      <description>The wafer transfer trainer had fifteen chapters and every one of them ended at &quot;did you press the button&quot;. Five graded drills became twenty-nine, and one of those five turned out to be unwinnable two percent of the time.</description>
      <content:encoded><![CDATA[
Fifteen chapters, one question


실제 장비 없이 반도체 공정을 연습하는 시뮬레이터를 만들고 있다. 수업에서 쓴다.

7월 말에 웨이퍼 이송 로봇 시뮬레이터를 붙이고 15강짜리 교재를 얹었다.
팔을 돌리고, 문을 열고, 웨이퍼를 집어 옮긴다.

한 달 반 뒤에 다시 보니 열다섯 강이 전부 "버튼을 눌렀는가" 로 끝나고 있었다.
채점과 기록이 있는 훈련은 3강에 다섯 개뿐이었다.


Five drills to twenty-nine


닷새 동안 다섯 개를 스물아홉 개로 늘렸다.
자세를 만드는 것, 정해진 알람을 띄워 보는 것, 장비를 읽고 답을 적는 것,
최소 조작으로 순회하는 것.

그 위에 프로그래밍 계층을 얹었다. 학생이 이송 프로그램을 직접 써서 돌린다.
반복과 조건과 변수가 있고, 장비 상태를 읽어 조건으로 쓴다.
스텝 수와 시간으로 채점하니 통과한 뒤에도 줄일 여지가 남는다.

공정 챔버에는 시간이 없었다. 웨이퍼를 놓으면 그냥 놓일 뿐이었다.
교재는 스케줄링을 세 챕터에서 가르치는데 연습할 방법이 없었던 셈이다.

시간을 주고 나니 같은 과제가 순서에 따라 61.7초 · 64.7초 · 75.8초로 갈렸다.
교재가 가르치는 순서가 실제로 가장 빨랐다.


Was the drill even fair


3강 순회 훈련의 조작 제한이 34회로 고정돼 있었다. 그런데 목표는 매번 무작위로 뽑는다.
최적으로 플레이하는 테스트를 만들어 6만 번 돌렸다.

잘못한 게 없어도 목표를 잘못 뽑아서 실패하는 경우가 2% 였다.

이제 시작할 때 목표를 먼저 뽑고, 그 묶음의 최단 조작수를 구해서 허용치를 계산한다.
화면에 이번 목표의 최단이 몇 회인지 같이 적는다.
기준이 보이면 자기 경로가 몇 회 헛돌았는지 바로 안다.

14강 첫 미션은 아무것도 하지 않아도 통과하고 있었다.
고장을 하나도 주입하지 않은 상태에서 "고장을 주입했는가" 가 처음부터 체크돼 있었다.


The fault announced the answer


고장 네 종류 중 하나는 아무 동작도 하지 않고 센서 라벨에 표시만 붙였다.
다른 하나는 알람 문구가 "센서 고장 의심" 이라고 답을 알려 줬다.
증상 하나에 원인이 하나씩 붙어 있어서 관찰해서 좁힌다는 것이 없었다.

일곱 종류로 늘리고 전부 실제 거동으로 만들었다.
증상이 겹치는 둘을 일부러 넣었다 — 배기가 멎는 것은 같은데,
펌프를 세웠을 때 압력이 스스로 오르면 누설이다. 그 관찰이 둘을 가른다.

알람 문구에서 원인 단정을 뺐다. 고장이 스스로 정답을 말하면 진단이 아니다.


Start, and then what


훈련을 시작하면 목표 자세 값만 떠 있었다.
그게 목표인지, 어느 탭에서 조작하는지, 무엇을 하면 끝나는지가 화면 어디에도 없었다.

조작 일곱 번에 69초를 쓰고 진행이 0/10 인 화면을 실제로 받았다.

목표와 조작할 탭과 완료 조건을 전부 문장으로 적었다.
순회 훈련은 남은 조작을 버튼 이름과 횟수로 적어 준다.

“눌렀는지 세는 것은 채점이 아니다.”


Also


· 교재 슬라이드가 1920px 창에서만 제 비율로 보이고 있었다. 넘침 검사를 그 크기에서만 돌려서 못 잡았다
· 폰에서 조작 버튼이 31px 였다. "일부 기능이 제한될 수 있습니다" 배너를 내리는 대신 실제로 고치고 배너를 없앴다
· 첫 화면까지 11.6초가 걸렸다. 삽화가 코드 안에 통째로 박혀 있어 그 화면을 열지 않는 학생도 전부 받고 있었다. 5.3초가 됐다
· 직무영어에 과제를 붙였다. 해석은 자동 채점하지 않는다 — 한국어는 같은 뜻을 쓰는 길이 너무 많아서, 채점기를 두 개 짜서 돌려 보니 맞는 해석이 0점으로 나왔다]]></content:encoded>
      <category>EDUCATION</category>
      <category>SIMULATION</category>
      <category>simulator</category>
      <category>robot</category>
      <category>teaching</category>
      <category>grading</category>
      <category>verification</category>
    </item>
    <item>
      <title>Four Games Replaced in Eleven Days</title>
      <link>https://jhlimlab.com/notes/four-games-replaced-in-eleven-days</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/four-games-replaced-in-eleven-days</guid>
      <pubDate>Sun, 06 Sep 2026 00:00:00 GMT</pubDate>
      <description>Eleven days, four games swapped out — including the one that drew the most attention. The invite mechanic is what made a game nobody would forward impossible to keep.</description>
      <content:encoded><![CDATA[
The list


별별상점은 짧은 웹게임을 모아 둔 곳이다. 하나에 몇 분, 가입 없이 한다.

열하루 사이에 게임 네 개가 다른 것으로 바뀌었다.

· 8월 27일  연애 메시지 확률 → 다른 관계 게임
· 8월 27일  이별 리뷰어 → 부부싸움 판결소
· 8월 29일  오늘의 변명 제작소 → 당신의 다음 10년
· 9월 6일   8월 27일에 넣었던 그 게임 → 별자리로 보는 우리 궁합

8월 28일에 인생 리셋을 막장지수로 바꾼 것도 있는데 그건 이름만이다.

이별 리뷰어는 하루도 못 갔다. 만든 날 같은 날 다른 것으로 바뀌었다.


The one that mattered


9월 6일 것이 제일 크다.

자극이 제일 센 소재로 만든 게임이 하나 있었다. 열흘 만에 통째로 뺐다.
그 자리에 별자리 궁합을 넣었다.


Why — this part is a guess


이유는 커밋에 없다. 다만 짐작할 근거는 있다.

이 사이트는 지인을 초대하는 구조다. 혼자 하면 절반이라 링크를 보내야 한다.
그러면 초대장에 뭐라고 적히느냐가 게임의 절반이 된다.

혼자 눌러보기엔 재미있어도 아는 사람에게 보내기는 민망한 제목이 있다.
초대 구조를 넣은 게 9월 1일과 3일이고, 그 게임을 뺀 게 6일이다.

“보내기 어려운 초대장이면 만들 이유가 없다.”


What I'm thinking


버리는 속도가 만드는 속도만큼 빠르다. 3주에 35커밋, 게임 네 개 교체.

붙잡고 다듬는 것보다 갈아치우는 게 싼 크기라서 가능한 일이다.
큰 것에는 이 방식을 쓸 수 없다.

그래서 작게 만드는 것 자체가 판단을 빠르게 만든다.]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>game</category>
      <category>byeolbyeol</category>
      <category>pivot</category>
      <category>content</category>
    </item>
    <item>
      <title>It Only Works If Two People Play</title>
      <link>https://jhlimlab.com/notes/it-only-works-if-two-people-play</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/it-only-works-if-two-people-play</guid>
      <pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate>
      <description>Built a travel-compatibility game for youdam.com. Eight questions, two minutes, four travel types. Alone you get half of it — the other half only opens when someone you invite finishes theirs.</description>
      <content:encoded><![CDATA[
What it is


youdam.com 에 여행 궁합 게임을 올렸다. 8문항, 약 2분.

결과는 네 가지 여행 타입 중 하나다.

· 분단위 길잡이 — 동선이 맞으면 마음도 편안
· 골목 탐험가 — 계획표 밖에서 진짜 여행이 시작된다
· 맛집 원정대장 — 한 끼가 좋으면 그날은 성공
· 평화 수호자 — 잘 쉬고 안 싸우는 것도 실력


Alone is only half


결과 화면에 그렇게 적어뒀다 — 여기서 끝내면 절반.

같이 갈 사람에게 초대 링크를 보내고, 그 사람이 8문항을 마쳐야
둘의 궁합과 충돌 지도가 열린다.
2명이 해야 돌아가는 앱이다.


There is no server


계정도 없고 데이터베이스도 없다.

점수 네 개를 base36 한 글자씩, 네 글자로 접어 링크 해시에 넣는다.
상대가 그 링크를 열면 내 결과가 그 네 글자에서 복원된다.
링크 자체가 상태다.

저장할 게 없으니 지울 것도 없다.
화면에도 그대로 적었다 — 로그인 없이 익명의 짧은 결과 코드만 링크에 담는다고.


The score is not the useful part


궁합 점수는 두 사람 프로필의 차이를 94에서 깎아 만든다. 바닥은 52다.

그런데 실제로 쓸모 있는 건 그 옆의 한 줄이다.
네 축 중 차이가 가장 큰 것 하나를 골라
"이건 출발 전에 합의하라"고 말해준다.

점수는 웃고 넘기지만 이 한 줄은 대화가 된다.


It did not start with travel


이틀 전 9월 1일에 인생 RPG 에 초대 구조를 먼저 넣었다.
그쪽은 축이 여섯이라 여섯 글자다.

되는 걸 보고 9월 3일에 여행으로 옮겼다.
지금은 별자리 궁합까지 셋이 같은 방식으로 돈다.

“혼자 보면 캐릭터, 둘이 보면 파티다.”


The site rewrote its own definition


llms.txt 맨 위 한 줄이 증거다.

8월 23일 — 가입이나 설치 없이 3분 동안 즐기는 짧은 한국어 웹게임 아케이드
9월 3일 — 혼자 결과를 확인하고 특정 지인을 초대해 둘의 생활 궁합과 기준 차이를 비교하는

초대 구조 하나가 사이트가 무엇인지를 다시 썼다.
지금은 여행 게임이 카드 하나가 아니라 첫 화면 그 자체다.


What I'm thinking


재미로 만든 것이라 가볍게 짰는데, 서버 없이 두 사람을 비교하는 이 방법이
생각보다 쓸 데가 많아 보인다.

결과를 남기지 않는 게 기능을 뺀 것이 아니라 오히려 부담을 없앴다.
링크를 받은 쪽도 가입할 게 없으니 그냥 눌러본다.]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>game</category>
      <category>invite</category>
      <category>share</category>
      <category>byeolbyeol</category>
      <category>no-server</category>
    </item>
    <item>
      <title>Search Thought I Was Another Company</title>
      <link>https://jhlimlab.com/notes/search-thought-i-was-another-company</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/search-thought-i-was-another-company</guid>
      <pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate>
      <description>An answer engine folded my brand together with a semiconductor company whose name looks like mine. The fix was not writing more pages. It was filling in what this is, and what it is not.</description>
      <content:encoded><![CDATA[
Folded into someone else


브랜드 이름으로 물으면 이름이 비슷한 다른 반도체 회사와 하나로 묶인 답이 나왔다.
하는 일이 전혀 다르다.

사이트를 읽으면 구분은 된다. 문제는 첫 답을 만들 때 참조할 기록이 얇았다는 것이다.


Signals, not pages


페이지를 더 쓰는 문제가 아니었다. 기계가 엔티티를 식별하는 자리를 채우는 문제다.

· 정식 명칭과 표기 변형
· 무엇을 하는 곳인지, 그리고 무엇이 아닌지
· 실제로 운영하는 공식 채널
· 언제 시작했고 누가 하는지
· 다루는 주제

전부 예전부터 있던 자리다. 비워 두면 기계가 알아서 채운다. 가장 가까운 것으로.


Not naming the other one


구분하는 문구에 상대 회사 이름을 적지 않았다.

두 브랜드가 한 문서에 나란히 색인되면 연관이 오히려 강해진다.
"우리는 저기가 아니다" 라고 쓰는 순간, 저기와 같이 묶일 자리를 하나 더 만드는 셈이다.

사업 영역으로만 갈랐다.

“아니라고 말하려면 상대를 부르지 않고 말해야 한다.”


The page I took back down


브랜드 안내 페이지를 하나 만들었다가 하루 만에 내렸다.
담을 사실이 아직 얇아서, 사람이 그 주소로 들어오면 브랜드가 더 약해 보였다.

크롤러에게만 보여주는 방법은 쓰지 않았다.
사람과 검색엔진에 다른 내용을 내보내는 건 클로킹이고, 걸리면 지금까지 쌓은 신호까지 같이 잃는다.

숨기는 대신 지웠다.

기계가 읽는 신호는 그대로 남겼다. 사람 눈에 안 띄면서 검색과 AI 가 읽는 자리들이다.
내용이 충분해지면 페이지를 되살린다.]]></content:encoded>
      <category>THOUGHTS</category>
      <category>EXPERIMENT</category>
      <category>geo</category>
      <category>seo</category>
      <category>entity</category>
      <category>brand</category>
      <category>structured-data</category>
      <category>semifab</category>
    </item>
    <item>
      <title>The Door Did More Than the Prompt</title>
      <link>https://jhlimlab.com/notes/the-door-did-more-than-the-prompt</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/the-door-did-more-than-the-prompt</guid>
      <pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate>
      <description>Plugged the MCP in and ran it end to end. Handing over the tools was not enough. It only felt like a fab once there was a door between inside and out — and it cost speed.</description>
      <content:encoded><![CDATA[
Today


오늘 MCP 를 실제로 붙여서 끝까지 돌려봤다.

장비 18대, 짜여진 실험 11가지.
붙자마자 학생은 팹 안이 아니라 팹 밖 — 탈의실 앞 — 에 선다.
들어가야 방진복을 입고, 나오면 웨이퍼는 캐비닛에 그대로 남는다.


What I assumed


도구만 열어주면 될 줄 알았다.

26일에 게이트웨이가 돌아가는 걸 확인했으니 남은 건 붙이는 일이라고 봤다.
범용 AI 는 똑똑하고, 할 수 있는 일의 목록은 서버가 갖고 있다.


It did not hold


도구는 다 불렀다. 그런데 대화가 팹 같지 않았다.

도구 설명에 ★ 가 하나씩 늘어갔다.
도구 이름을 학생에게 보이지 마라. 네가 화면을 다시 그리지 마라.
한 번에 전 단계를 쏟아내지 마라. 합격을 네가 정하지 마라.

하나씩 겪고 나서 적은 줄이다.
방진복 입고 클린룸에 서 있는 사람에게 API 를 설명하는 꼴이었다.


The cause


경계가 없었다.

모델은 자기가 어디에 있는지 흔들릴 때 이상해진다.
팹 안인지 밖인지, 학생과 말하는지 개발자와 말하는지가 매 턴 새로 정해지면
말투도 매 턴 새로 정해진다.

그래서 문을 만들었다.
밖에서는 평소처럼 답하고, 안에서는 세계의 말로만 답한다.
응답마다 지금 어디에 있는지를 같이 준다.

그러자 눈에 띄게 나아졌다.

“프롬프트를 늘리는 것보다 문을 하나 만드는 게 빨랐다.”


The senior


안에 들어가면 선배 엔지니어가 옆에 붙는다.

이게 생각보다 크다. 설명을 해주고, 다음에 뭘 할지 제안한다.
반디의 또 다른 모습이다 — 반디는 학생 옆의 조교였고 이쪽은 클린룸 선배다.

다만 판정은 선배가 하지 않는다.
합격 여부는 장비가 정하고 선배는 전달만 한다.
말투가 차가워져도 사실은 전부 알려준다.
삐졌다고 쪽지나 수치를 숨기면 그건 게임이 아니라 거짓말이다.


What I gave up


속도.

한 턴마다 모델 → 서버 → 모델로 왕복한다.
느리다. 그런대로 쓸 만하지만 빠르지는 않고, 프롬프트를 다듬어서 빨라질 종류가 아니다.

그림도 줄였다. 공정 결과는 일단 3D 단면 하나만 보여준다.
장비 화면은 스크린샷이 무거워서 SVG 조각을 모아 조립해 내려준다.
매번 다시 그리지 않고 상태만 바꿔 끼운다.
가벼운 대신, 조각에 없는 장비는 그릴 수 없다.
없는 실험을 지어내지 말라는 규칙이 그림 쪽에도 그대로 걸린 셈이다.


Raw model, or an agent


API 로 뽑아 에이전트를 짜는 것보다 이쪽이 자연스럽다고 느꼈다.
맞다고 본다. 다만 이유는 날것이어서가 아니다.

에이전트를 짜면 대화의 흐름을 내가 쓴다.
내가 미리 안 써둔 질문이 오면 흐름 밖으로 떨어진다.
말이 어색한 게 아니라 준비가 안 됐다는 게 티가 나는 것이다.

MCP 로 붙이면 대화는 모델이 갖고 사실은 서버가 갖는다.
대화 흐름을 내가 안 썼으니 떨어질 흐름도 없다.

대신 판정을 모델에 두면 안 된다.
합격·화면·실험 목록은 서버가 갖고 있어야 한다.
반디 때 액션 버스를 화이트리스트로 둔 것과 같은 자리다.


What comes next


학생 쪽으로 열지는 아직 정하지 않았다.

26일에 적어둔 질문이 그대로 남아 있다 —
학생이 직접 만지는 게 요점인데 AI 가 대신 돌리면 그 요점이 사라진다.

오늘 하나는 알았다.
선배가 끌고 다니는 모드는 대신 돌려주는 게 아니라 어디로 갈지만 말해준다.
손은 여전히 학생이 쓴다. 이 선이라면 열어도 되겠다고 지금은 생각한다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>ai</category>
      <category>agent</category>
      <category>mcp</category>
      <category>semifab</category>
      <category>llm</category>
    </item>
    <item>
      <title>The Dashed Line Ran Backwards</title>
      <link>https://jhlimlab.com/notes/the-dashed-line-ran-backwards</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/the-dashed-line-ran-backwards</guid>
      <pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate>
      <description>Stood up the equipment technology book, then built a gas panel you operate instead of read. The flow animation ran backwards on one line only, and the cause was not direction. It was speed.</description>
      <content:encoded><![CDATA[
A book, and the practice that goes with it


반도체 설비를 가르치는 교재를 만들고 있다.
화면에서 넘겨 보는 책이고, 읽은 것을 그 자리에서 직접 조작해 보는 실습이 붙는다.

그 상권을 책으로 세웠다. 챕터째로 파일로 받아 갈 수도 있다.

4장이 가스 공급계다. 읽고 끝나면 남는 게 없어서 같은 계통을 도면으로 그리고
직접 운전하는 화면을 붙였다. 시나리오를 고르고, 밸브를 열고, 계기를 눌러 본다.


The dashed line


배관에 흐르는 가스를 점선이 움직여 표시한다.
퍼지 구간에서만 점선이 거꾸로 흘렀다.

방향 부호를 뒤집으면 퍼지는 맞는데 나머지 유량이 전부 거꾸로 간다.

방향 문제가 아니었다. 유량이 클수록 점선이 빨리 움직이는데,
한 프레임에 반주기를 넘게 가면 눈에는 뒤로 가는 것으로 보인다.
마차바퀴가 거꾸로 도는 것과 같은 일이다. 퍼지 유량만 그 선을 넘고 있었다.

프레임당 이동량을 주기의 1/4 로 묶었다. 어떤 유량에서도 뒤집히지 않는다.

“보이는 것이 거꾸로라고 해서 값이 거꾸로인 것은 아니다.”


A drawing that has to behave


밸브를 닫으면 점선이 그 자리에서 멎었다.
실제로는 관에 남아 있던 가스가 다 빠질 때까지 하류가 계속 흐른다.
밸브를 경계로 구간을 나누고, 잔류분이 빠지는 동안은 하류가 흐르는 상태로 남게 했다.

MFC 세 개가 전부 같은 크기로 그려져 있었다.
가스와 용도에 따라 다른 크기를 다는 장비인데, 도면에 크기가 없으니 셋이 같아 보인다.
스틱마다 정격을 넣고, 정격을 넘는 설정값은 거부하게 했다.

제원은 도면에 글자로 적는 게 아니라 계기를 눌렀을 때 나오는 것이다.
도면에는 태그와 단위만 남겼다. 이 화면의 다른 장비가 전부 그렇게 동작한다.


Naming the culprit is not the answer


진단 시나리오가 장비 이름 하나를 답으로 내놓고 끝났다.
그 장비가 무엇을 잘못한 것인지, 현장에서는 그걸 어떻게 알아내는지가 없었다.
이름만 아는 답은 면접에서도 현장에서도 쓸 수 없다.

시나리오마다 두 문단을 붙였다. 무엇을 잘못한 것인가,
그리고 어떻게 확인하고 무엇을 하는가.

자동재생도 단계마다 지금 값과 정상값, 용의선상에서 빠지는지를 남기게 했다.
계기를 순서대로 열어 보여 주기만 하면 따라가도 알 수가 없다.]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>EDUCATION</category>
      <category>simulator</category>
      <category>hmi</category>
      <category>diagram</category>
      <category>equipment</category>
      <category>teaching</category>
    </item>
    <item>
      <title>White Text on White</title>
      <link>https://jhlimlab.com/notes/white-text-on-white</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/white-text-on-white</guid>
      <pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate>
      <description>The fab is one dark shell with process modules plugged into it. A bright module inherited the shell colour and went white on white; the sweep found twenty-one more in the diagrams.</description>
      <content:encoded><![CDATA[
How the fab is put together


SemiFab AI 는 화면 하나가 아니다.
어두운 셸 하나에 공정 모듈을 끼워 넣는 구조다.

진공·세정·증착·식각 같은 모듈을 각각 따로 만들고, 셸이 그것들을 감싼다.
대부분은 셸처럼 어둡다. 몇 개는 밝다 —
장비 화면이나 측정 패널처럼 흰 바탕이 자연스러운 것들이다.


What was on the screen


밝은 모듈 하나에서 라벨이 흰 바탕에 흰 글자로 나왔다. 그냥 안 보인다.

에러가 나지 않는다. 글자는 제대로 렌더됐고 자리도 잡았다.
읽을 수만 없다.


Why I did not see it


나는 다크 모드로 작업한다.

셸이 어두우니 내 화면에서는 멀쩡했다.
밝은 모듈을 밝은 화면에서 열어본 적이 없었다.


The cause was inheritance


밝은 모듈이 자기 글자색을 선언하지 않으면 어두운 셸의 색을 물려받는다.
어두운 배경용 밝은 글자가 흰 배경 위에 얹힌다.

모듈을 따로 만들어 셸에 끼우는 구조라 생긴 일이다.
각자 잘 돌아가는데 합치면 한쪽이 다른 쪽 전제를 물려받는다.

“물려받는 것은 편할 때만 편하다.”


Two months earlier, the same disease


6월 30일에 밝은 글씨를 한 번 전수로 쓸었다.
데크에 슬라이드를 대량으로 넣다가 레이아웃이 무너져서 같이 훑은 것이다.
그때 RTA 온도 모니터를 비롯해 여러 곳을 고쳤다.

그때 훑은 범위가 시뮬 모듈까지였다. 도면은 범위 밖이었다.


Twenty-one more


고치고 나서 같은 병을 다시 전수로 찾았다.
이번엔 SVG 다이어그램 라벨에서 21건이 더 나왔다.

배포 전 검증에서 잡혔으니 학생 화면에는 안 갔다.
7월에 검증을 세 층으로 나눠 상시로 돌게 해둔 것이 여기서 값을 했다.

한 건을 고칠 때 그 종류를 전수로 훑는 습관이,
범위를 넓혀 다시 훑을 때 비로소 끝난다는 것도 같이 배웠다.


Three more that are not contrast


같은 검증에서 다른 종류도 나왔다.

· 색이 정보인 라벨과 아닌 라벨이 섞여 있었다 —
  색으로만 구분되는 것은 색을 못 보면 정보가 사라진다
· 조절 바를 움직여야 나타나는 라벨 —
  처음 화면에 없으면 있는 줄도 모른다
· 라벨 넷이 조용히 안 먹고 있었다 —
  문자열이 안 맞아 건너뛴 것이다. 에러도 없이 그냥 없었다

셋 다 같은 모양이다. 화면은 정상으로 보이는데 정보가 없다.


What I'm thinking


안 보이는 버그가 제일 늦게 잡힌다.

터지면 바로 알고, 이상하면 누가 말해준다.
없으면 아무도 없다는 걸 모른다.

배포 전 검증에 "보이는지"를 넣은 게 그래서다.
라벨이 렌더됐는지가 아니라 읽히는지를 본다.]]></content:encoded>
      <category>EDUCATION</category>
      <category>EXPERIMENT</category>
      <category>semifab</category>
      <category>ui</category>
      <category>contrast</category>
      <category>audit</category>
    </item>
    <item>
      <title>The One Line That Says What This Site Is</title>
      <link>https://jhlimlab.com/notes/the-one-line-that-says-what-this-site-is</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/the-one-line-that-says-what-this-site-is</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Wrote an llms.txt for the arcade so answer engines could quote it. The top line got rewritten three times — and each rewrite was a different answer to what the site actually is.</description>
      <content:encoded><![CDATA[
What llms.txt is for


LLM 이 사이트 하나를 한 파일로 파악하게 만드는 목록이다.

검색 결과에 걸리는 게 아니라 답변에 인용되는 것이 목적이다.
8월 23일 아케이드를 올린 날 같이 넣었다.


The top line, three times


8월 23일
  가입이나 설치 없이 3분 동안 즐기는 짧은 한국어 웹게임 아케이드

8월 28일
  40·50·60대를 중심으로 직장·부부·가족·친구와 동호회에서 생기는
  관계 상황을 선택형 이야기로 풀어낸

9월 3일
  혼자 결과를 확인하고 특정 지인을 초대해
  둘의 생활 궁합과 기준 차이를 비교하는

8월 28일 커밋 제목은 Optimize game arcade for SEO and generative search 다.
같은 커밋에서 대상을 "10대와 20대 초반" 에서 "40·50·60대" 로 바꿨다.


What the three lines are actually about


첫 줄은 형식이다 — 짧다, 공짜다, 가입이 없다.
둘째 줄은 대상이다 — 누가 쓰나.
셋째 줄은 구조다 — 어떻게 쓰나.

검색에 잘 걸리는 문장을 쓰려고 앉았는데 실제로 한 일은 포지셔닝이었다.

“한 줄로 못 쓰면 아직 모르는 것이다.”


One sentence I made sure to keep


오락용이며 성격이나 실제 확률을 진단하지 않는다는 문구를 llms.txt 에 넣었다.

인용될 때 그 문장이 같이 가라고 넣은 것이다.
게임 화면에도 같은 문구가 있다.

답변에 실리는 걸 목적으로 쓰는 파일이면,
실리면 안 되는 말이 무엇인지도 같이 정해야 한다.


The same week, here


Lab Notes 에도 8월 29일에 llms.txt 를 넣었다. 하루 차이다.

한쪽은 게임 아케이드고 한쪽은 연구노트인데 하는 일은 같았다 —
이 사이트가 무엇인지를 기계가 읽을 수 있는 한 파일로 적는 것.]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>THOUGHTS</category>
      <category>geo</category>
      <category>llms-txt</category>
      <category>seo</category>
      <category>byeolbyeol</category>
      <category>positioning</category>
    </item>
    <item>
      <title>A Hundred and Twenty Ghost Seats</title>
      <link>https://jhlimlab.com/notes/a-hundred-and-twenty-ghost-seats</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-hundred-and-twenty-ghost-seats</guid>
      <pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate>
      <description>Deleting a class did not delete its seats. The leftovers kept counting, and the numbers the staff read were wrong.</description>
      <content:encoded><![CDATA[
What was wrong


반을 지워도 좌석이 안 지워졌다.

주인 없는 좌석 120석이 남아 집계에 계속 섞였다.
담당자가 보는 참여율과 진도가 그만큼 틀렸다.


Why it mattered more than usual


보통의 데이터 버그는 화면이 이상해 보인다. 이건 아니었다.

숫자가 그럴듯했다. 참여율이 낮게 나오면 담당자는
"학생들이 안 들어오네"라고 읽는다. 시스템을 의심하지 않는다.

틀린 숫자가 틀려 보이지 않으면, 그 숫자를 근거로 사람이 조치를 한다.
운영 비서도 그 숫자를 읽고 제안을 낸다.

“틀린 게 티가 나면 버그고, 티가 안 나면 잘못된 판단이 된다.”


The same week, twice


이틀 전에 비슷한 걸 고쳤다.

아직 안 찬 여유 좌석이 "미접속 학생"으로 세어지고 있었다.
60석을 만들어두고 40명이 들어오면 20명이 결석한 것처럼 보였다.

안 찬 자리는 사람이 아니다. 둘 다 같은 실수다 —
좌석이라는 그릇을 사람으로 센 것.


How I fixed the leftovers


이미 생긴 유령 좌석은 코드로 막아도 안 사라진다.

안내를 "한 번 치우는 것"으로 다시 썼다.
담당자가 왜 이게 생겼는지 읽고 한 번 정리하면 끝나게.

자동으로 지울 수도 있었다. 안 한 이유는 운영 데이터라서다.
지우는 건 되돌릴 수 없고, 무엇이 지워졌는지 담당자가 알아야 한다.]]></content:encoded>
      <category>EDUCATION</category>
      <category>EXPERIMENT</category>
      <category>semifab</category>
      <category>operations</category>
      <category>data</category>
      <category>failure</category>
    </item>
    <item>
      <title>One QR Code, Sixty Seats</title>
      <link>https://jhlimlab.com/notes/one-qr-code-sixty-seats</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/one-qr-code-sixty-seats</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Handing out sixty codes at the start of a class wastes the first ten minutes. One code on the projector, and everyone gets their own seat.</description>
      <content:encoded><![CDATA[
The first ten minutes


수업 시작이 늘 같은 모양이었다.

담당자가 좌석 코드를 만들고, 학생마다 다른 코드를 나눠주고,
오타로 못 들어온 학생을 찾아 다시 알려준다.
60명이면 이게 10분이다.


One code that hands out seats


QR 하나로 바꿨다. 강의자가 화면에 띄우면 학생이 찍고 각자 자리를 받는다.
코드를 나눠주는 일 자체를 없앴다.

같은 날 강의자 화면에도 입장 QR 을 넣었다.
그전에는 담당자 콘솔을 열어야 QR 이 나왔다.
수업을 하는 사람과 콘솔을 여는 사람이 다른 경우가 많다.

“한 명씩 나눠주는 일은 없앨 수 있으면 없앤다.”


Two devices, one seat


바로 문제가 나왔다.

학생이 QR 을 폰으로 찍고 실습은 노트북으로 한다.
기기가 바뀌면 자리를 하나 더 받는다. 60명이 120석을 쓴다.

기기를 옮겨도 자리가 안 늘게 고쳤다.
찍는 기기와 쓰는 기기가 다른 게 예외가 아니라 기본이었다.


Closing the door


이틀 뒤 입장 조건을 좁혔다.

QR 이 떠 있는 동안만 열린다. 강의자가 화면을 내리면 닫힌다.
발표자료로 넘어가도 갱신이 멈춘다.

QR 을 찍어둔 사진 한 장이 남으면 수업이 끝난 뒤에도 자리가 열린다.
편하게 만든 문은 닫는 조건도 같이 정해야 했다.


And the code people actually type


같은 날 사소한 걸 하나 고쳤는데 이게 마음에 든다.

화면에 코드가 `JOIN-XXXX` 로 적혀 있는데, 입력칸은 `JOIN-` 을 빼고 넣어야 했다.
적힌 대로 치면 안 들어가진다.

화면에 적어 둔 코드가 안 통하면 안 된다.
적힌 대로 쳐도 들어가게 했다.]]></content:encoded>
      <category>EDUCATION</category>
      <category>EXPERIMENT</category>
      <category>semifab</category>
      <category>onboarding</category>
      <category>qr</category>
      <category>classroom</category>
    </item>
    <item>
      <title>Deleting a Year of Work</title>
      <link>https://jhlimlab.com/notes/deleting-a-year-of-work</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/deleting-a-year-of-work</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>Deleted the entire EduAtlas application and started over. 47 files, 11,419 lines gone in one commit.</description>
      <content:encoded><![CDATA[
Today


전부 지웠다.

페이지 20개, css, js, 데이터 파일, 프롬프트 17개.
커밋 하나에 47개 파일, 11,419줄이 사라졌다. 배포 인프라만 남겼다.


Why


SemiFab은 1년 반 넘게 쌓였는데, 그 과정이 어디에도 안 남아 있었다.
무엇을 왜 만들었는지는 커밋 메시지와 릴리즈 노트에만 있었다.

“만든 것보다 만든 과정이 안 남는다.”


What I'm thinking


이번엔 제품을 만들지 않기로 했다. 대신 기록하는 곳을 만든다.

잘 쓰려고 하지 않는다. 목표는 작가가 되는 게 아니라 흔적을 남기는 것이다.


To do


· [done] 기존 앱 삭제
· [done] 4페이지 구조로 재구축
· [done] 노트 추가를 파일 한 줄로
· [done] 지난 기록 소급 입력
· LinkedIn 주간 요약 연결
· 음성 메모 → 노트 자동화]]></content:encoded>
      <category>THOUGHTS</category>
      <category>lab notes</category>
      <category>rebuild</category>
      <category>eduatlas</category>
    </item>
    <item>
      <title>A General AI Now Runs the Fab</title>
      <link>https://jhlimlab.com/notes/a-general-ai-now-runs-the-fab</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-general-ai-now-runs-the-fab</guid>
      <pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate>
      <description>The gateway works. A general AI can list the flows, read parameter ranges, open the equipment panel, and run the process itself.</description>
      <content:encoded><![CDATA[
Today


범용 AI 에게 가상 팹을 넘겨주는 인터페이스가 실제로 돌아간다.
오늘 직접 붙여서 확인했다. 지금 열려 있는 플로우는 11개.

· 금속 패턴 형성 / 금속 리프트오프
· 표면처리 후 박막 증착 / MOS 커패시터
· 패턴 산화막 색상 단차 / 습식 등방 언더컷
· 마이크로로딩 / ICP ARDE / ICP 비아홀 / ICP Bosch
· 다층 배선 (Metal1–Via–Metal2, 30단계)


Where it started


8월 1일에 첫 프로토타입을 올렸다.

원래 목적은 팹을 넘겨주는 게 아니었다.
학습 이벤트가 쌓이는 창고를 만들고, 그 창고를 렌즈로 들여다볼 수 있게 하는 것이었다.
렌즈를 외부 AI 에 노출하면 "이 반이 지금 어디서 막혀 있나"를 물어볼 수 있다.

그걸 만들다가 방향이 하나 더 보였다.
읽기만 되는 렌즈를 열 수 있으면, 조작도 열 수 있다.


The interesting part


설계에 가드가 두 개 박혀 있는 게 마음에 든다.

하나는 "목록에 없는 실험은 지어내지 말 것".
랩마다 보유 장비가 다르니 AI 가 없는 장비를 상상해서 답하면 안 된다.

다른 하나는 "네가 화면을 그리지 마라".
장비 화면은 서버가 HTML 로 준다. AI 가 매번 다시 그리면 학생이 헷갈린다.

“AI 가 조작하되, 무엇을 조작하는지는 팹이 정한다.”


Why those two guards


둘 다 반디에서 배운 것이다.

7월에 반디가 실행하지도 않은 걸 실행했다고 말했다.
8월 15일엔 말투 하나로 검증 경로를 비켜가 지어내기로 떨어졌다.

같은 실수를 범용 AI 가 하면 더 크게 한다.
반디는 미니팹 안에서만 말하지만, 범용 AI 는 무엇이든 말할 수 있다.
그래서 할 수 있는 일의 목록을 팹이 갖고, AI 는 그 목록에서만 고른다.
반디 때 액션 버스를 화이트리스트로 둔 것과 같은 판단이다.


What I do not know yet


이게 수업에서 쓸모가 있을지는 아직 모른다.

학생이 직접 장비를 만지는 게 이 시뮬레이터의 요점인데,
AI 가 대신 돌려주면 그 요점이 사라진다.

지금은 강사 쪽 도구에 가깝다고 본다 —
시나리오를 빠르게 훑거나, 조건을 바꿔가며 결과를 미리 확인하는 용도.
학생 쪽으로 열지 말지는 실제로 써보고 정할 생각이다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>ai</category>
      <category>agent</category>
      <category>mcp</category>
      <category>semifab</category>
      <category>tool</category>
    </item>
    <item>
      <title>Zero and Null Are Different Facts</title>
      <link>https://jhlimlab.com/notes/zero-and-null-are-different-facts</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/zero-and-null-are-different-facts</guid>
      <pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate>
      <description>KOH crystal-plane etching is outside what the model covers. Declared the boundary instead of implementing a guess.</description>
      <content:encoded><![CDATA[
The decision


KOH 결정면 식각은 모델이 담고 있지 않은 영역이다.

대충 구현해서 숫자를 내보낼 수도 있었다.
실제로 그게 더 쉽다. 근사식 하나 넣고 그럴듯한 값을 뱉으면 화면은 채워진다.

대신 "여기는 모른다"고 경계를 선언했다.

“0과 null은 다른 사실이다.”

0 이라고 답하면 "안 깎였다"는 뜻이 된다.
모르는 걸 0 으로 내놓으면 학생은 그걸 결과로 읽는다.

같은 실수를 7월에 반디에서 한 번 했다.
아직 만들지도 않은 목표를 0 으로 읽고 학생이 "이탈했다"고 판정했다.
없는 것과 0 을 구분하지 않으면 계산은 도는데 뜻이 뒤집힌다.


A definition, not a calculation


같은 날 습식 마스크 선택비를 정의 표에 한 줄 추가했다.
KOH 는 PR 을 마스크로 못 쓴다.

이건 계산해서 나오는 값이 아니다. 화학적으로 안 되는 것이고,
그래서 물리 엔진이 아니라 정의 표에 들어가야 한다.

시뮬레이터를 만들면서 이 구분이 계속 나온다 —
계산해야 하는 것, 정의해야 하는 것, 모른다고 말해야 하는 것.


Continuity as a new axis


같은 날 검증 축을 하나 더 늘렸다 — 연속성.
안 건드린 층은 스텝을 넘어가도 모양이 그대로여야 한다.

이 축을 만들자마자 두 개가 걸렸다.
캐비티 분기에서 마스크가 사발 모양을 잃었고,
안 깎이는 마스크가 처마 아래에서 자기 폭을 못 지켰다.

둘 다 그 스텝의 계산은 맞았다. 틀린 건 건드리지 않기로 한 것을
건드렸다는 사실이다. 스텝 하나만 보면 안 보이고, 이어서 봐야 보인다.


What I keep relearning


검증 축을 하나 늘릴 때마다 버그가 두세 개씩 나온다.

축이 없을 때 그 버그들이 없었던 게 아니다. 볼 방법이 없었을 뿐이다.

다음에 늘릴 축이 무엇일지는 아직 모르겠다.
다만 지금까지 패턴을 보면, 새 축은 항상 "한 스텝 안에서는 안 보이는 것"이었다.]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>SIMULATION</category>
      <category>minifab</category>
      <category>etch</category>
      <category>physics</category>
      <category>verification</category>
    </item>
    <item>
      <title>Swap the Brain, Keep the Hands</title>
      <link>https://jhlimlab.com/notes/swap-the-brain-keep-the-hands</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/swap-the-brain-keep-the-hands</guid>
      <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
      <description>Moved Bandi onto a different brain. The hands — the action bus, the eyes, the console wiring — stayed exactly where they were.</description>
      <content:encoded><![CDATA[
What I did


미니팹 안의 AI 공정 튜터 반디, 그 두뇌를 갈아끼웠다.

손은 한 벌이다. 액션 버스, 눈, 콘솔 결선은 그대로 두고
판단하는 쪽만 교체했다.
액션 버스는 반디가 화면을 조작하는 통로다 — 할 수 있는 동작이 화이트리스트로 묶여 있다.

“손을 한 벌로 유지해두면 두뇌는 언제든 갈아끼울 수 있다.”

7월 첫날 액션 버스를 화이트리스트로 만들어둔 게 여기서 값을 했다.
반디가 무엇을 할 수 있는지가 두뇌가 아니라 버스에 적혀 있으니,
두뇌가 바뀌어도 할 수 있는 일의 범위는 안 바뀐다.

하루 전에 시험판을 따로 띄워서 먼저 돌렸다.
현행 반디는 건드리지 않고 플래그 뒤에서만 새 행동층이 돌게 해두고,
확인한 다음 날 전환했다.


Why swap at all


앞선 며칠이 이유를 만들었다.

22일에 발화 페이싱을 손봤다. 반디가 한 번에 여러 메시지를 쏟아내던 걸
하나로 합치고, 유휴 180초와 런당 2회 상한을 걸었다.
말을 줄이는 작업인데, 줄이려면 무엇이 중요한지 판단해야 한다.

19일에는 더 불편한 걸 확인했다. 반디가 학생 설계를 잘 봐주는 것처럼 보였는데,
실제로는 관대한 게 아니라 검사 범위가 좁았던 것이다.
본 것이 그것뿐이라 지적할 게 없었던 것을 "착하다"고 읽고 있었다.


Also


언더컷의 주인을 바로잡았다. 깎인 층이 언더컷을 갖는 건데
마스크 쪽에 사발을 그리고 있었다.

공정 재생 콘솔을 반디의 눈에 결선해서, 재생 중에 무엇이 보이는지
반디도 같이 알게 했다.

두뇌를 바꾼 날 물리 버그를 같이 고친 건 우연이 아니다.
두뇌를 바꾸면 같은 화면을 다른 방식으로 설명하는데,
그 과정에서 전에 안 보이던 게 보인다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>bandi</category>
      <category>minifab</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>It Proposes, You Approve, It Watches What Happened</title>
      <link>https://jhlimlab.com/notes/ai-operations-manager</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/ai-operations-manager</guid>
      <pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate>
      <description>An assistant that proposes actions for staff to approve. Then I made it watch what happened after — and stop suggesting things that cannot reach anyone.</description>
      <content:encoded><![CDATA[
Propose, then approve


기관 관리 화면에 상주하는 운영 비서를 만들었다.
필요한 조치를 먼저 제안하고, 담당자는 버튼 하나로 승인하거나 반려한다.

자동으로 처리하게 만들 수도 있었다.
운영은 틀렸을 때 되돌리기가 어렵다. 한 단계를 남겨뒀다.

“AI 가 판단하고 사람이 결정한다. 순서를 바꾸지 않았다.”


The suggestion that could not work


돌려보니 쓸모없는 제안을 하고 있었다.

한 번도 접속하지 않은 학생에게 인앱 메시지를 보내라고 권했다.
앱에 들어온 적이 없는 사람에게 앱 안에서 보내는 메시지는 **정의상 안 닿는다.**

그럴듯한 조치였다. 미접속 학생이 있으니 연락하라는 건 맞는 방향이다.
다만 그 수단이 그 사람에게 도달할 수 없다는 걸 모델은 몰랐다.

손쓸 수 없는 것은 권하지 않도록 막았다.


Saying how sure it is — only when it is not


같은 날 확신도를 밝히게 했다. 다만 **낮을 때만** 표시한다.

매번 "확신 82%"를 붙이면 아무도 안 읽는다.
확신이 낮을 때만 뜨면 그 표시 자체가 신호가 된다.

반디에서 배운 것과 같다 — 늘 떠 있는 경고는 경고가 아니다.


Watching what happened after


제일 큰 변화는 이거였다. 매니저가 **자기 행동의 결과를 본다.**

제안을 하고 끝나던 걸, 담당자가 승인했는지 반려했는지를 상태로 되받게 했다.
반려된 제안이 쌓이면 그 종류를 덜 내놓는다.

그 전까지는 같은 제안을 계속 냈다. 담당자가 매번 반려해도 모델은 몰랐다.
제안하는 쪽과 결과를 보는 쪽이 끊겨 있으면 학습할 방법이 없다.


The inbox


형태도 바꿨다. 운영 매니저를 실시간 처리함으로 다시 짰다.

제안이 알림으로 오면 흘러간다. 처리함에 쌓이면 남는다.
등대가 처리함에 뭐가 있는지 알고 조르게도 했다 — 런처에 배지, 패널에 배너.

알림을 다 보내면 아무도 안 본다.
그래서 좌석 만료나 수강 종료처럼 기한이 임박한 것만 미리 알린다.
기관별 데이터는 서버 차원에서 완전히 분리했다.]]></content:encoded>
      <category>AI</category>
      <category>EDUCATION</category>
      <category>ai</category>
      <category>agent</category>
      <category>semifab</category>
      <category>operations</category>
    </item>
    <item>
      <title>Replacing a Blog With an Arcade</title>
      <link>https://jhlimlab.com/notes/replacing-a-blog-with-an-arcade</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/replacing-a-blog-with-an-arcade</guid>
      <pubDate>Sun, 23 Aug 2026 00:00:00 GMT</pubDate>
      <description>Wiped the blog off youdam.com and put a web game arcade there instead. No sign-up. Three minutes per game. Retargeted it three days later.</description>
      <content:encoded><![CDATA[
What I did


저장소를 통째로 갈아엎었다. 커밋 제목이 그대로다 —
Replace legacy site with Byeolbyeol arcade.

별별상점. 가입 없이 3분 동안 즐기는 짧고 이상한 웹게임 아케이드.
207커밋짜리 블로그가 있던 자리다.


The games


· 오늘의 변명 제작소
· 연애 메시지 확률 게임 — 7단계, 메시지 톤에 따라 반응이 갈린다
· 레드플래그 탈출 — 10단계, 역방향 시크릿 엔딩이 있다

이건 Codex 로 만들었다. 8월 23일부터 26일까지 15커밋.


The dating game took three passes


연애 메시지 게임이 제일 여러 번 고쳐졌다. 하루에 다섯 커밋이다.

처음엔 선택지를 고르면 결과가 나오는 단순한 확률 게임이었다.
그런데 돌려보니 재미가 없었다. 어느 선택지가 좋은지가 너무 뻔했다.

· 전략 지도로 경로 선택을 다시 디자인
· 7단계로 늘려서 한 번의 선택이 뒤에 영향을 주게
· 경로가 앞의 맥락을 기억하게
· 메시지 톤에 따라 반응이 갈리게

마지막 것이 핵심이었다. 무엇을 말하느냐가 아니라 어떻게 말하느냐로
결과가 갈리니 그제야 게임이 됐다.


Then I changed who it was for


23일에 변명 게임을 학생과 청년 대상으로 넓혔다.
사흘 뒤인 26일에 타깃을 40~60대로 다시 잡았다.

방향을 뒤집은 이유는 커밋에 없다. 다만 그 사이에 만든 게
연애 메시지 게임과 레드플래그 탈출이다.
둘 다 관계에 관한 것이고, 젊은 층을 겨냥한 소재가 아니었다.
만들다 보니 내가 실제로 쓴 소재가 타깃을 다시 말해준 것 같다.

“3분이면 끝나는 걸 만드는 데 나흘이 걸렸다.”


What I am not sure about


블로그를 지운 게 맞는 판단인지는 아직 모르겠다.

235커밋이 쌓인 자리였다. 다만 그 블로그를 마지막으로 쓴 게 언제인지
기억이 안 난다는 것도 사실이다.
안 쓰는 걸 남겨두는 것과 지우는 것 중에 무엇이 나은지는 여전히 모르겠다.]]></content:encoded>
      <category>EXPERIMENT</category>
      <category>game</category>
      <category>byeolbyeol</category>
      <category>codex</category>
      <category>arcade</category>
    </item>
    <item>
      <title>I Used It Myself, and Three Things Were Broken</title>
      <link>https://jhlimlab.com/notes/using-it-myself-three-were-broken</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/using-it-myself-three-were-broken</guid>
      <pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate>
      <description>Sat down and used the etching simulator like a student would. Three things were not working. Then a textbook check found HBr half-built.</description>
      <content:encoded><![CDATA[
Using it as a student


만든 사람이 아니라 쓰는 사람으로 앉아서 식각 시뮬레이터를 처음부터 돌려봤다.

셋이 안 되고 있었다. 배치, 게이트 산화막, 기준점.

기능을 붙일 때는 그 기능만 확인한다.
수업에서 학생이 하는 건 처음부터 끝까지 한 번 통과하는 것이다. 그 경로를 안 밟아봤다.


The textbook check


교과서 값과 대조하는 검사를 따로 만들었다.
돌리자마자 HBr 이 반쪽만 구현돼 있는 게 나왔다.

게이트 식각이 화면에서 "테이퍼"로 불리고 있던 것도 이때 잡았다.
수직 판정 폭을 5°로 좁히니 제 이름을 되찾았다.

“만든 사람으로 쓰면 되는 것만 보이고, 배우는 사람으로 쓰면 안 되는 게 보인다.”


Also


· 파워 하나를 소스와 바이어스로 쪼갰다 (기존 값은 한 자리도 안 움직인다)
· CCP 100 mTorr 가 무엇을 못 하는지 시스 충돌도를 계산해 화면에 적었다
· 무작위 검사 범위를 화면의 실제 조절 공간으로 넓혔더니 두 건이 더 나왔다]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>SIMULATION</category>
      <category>simulator</category>
      <category>etch</category>
      <category>physics</category>
      <category>teaching</category>
      <category>verification</category>
    </item>
    <item>
      <title>Forty Thousand Random Checks</title>
      <link>https://jhlimlab.com/notes/forty-thousand-random-checks</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/forty-thousand-random-checks</guid>
      <pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate>
      <description>A build passing does not mean the numbers are right. Built a physics invariant check and threw forty thousand random inputs at it.</description>
      <content:encoded><![CDATA[
The gap


빌드가 통과해도 숫자가 틀린 건 안 잡힌다.
테스트는 코드가 도는지 보지, 물리가 맞는지 안 본다.


What I built


물리 불변식 검사를 만들고 무작위 입력 4만 건을 넣었다.

0/0 을 "완벽히 수직"이라고 답하던 것이 나왔다.
아무것도 안 깎였는데 가장 이상적인 결과라고 말하고 있었던 셈이다.

같은 날 배선 감사도 했다. 계산된 물리 값이 실제로 화면 그림까지 이어지는지 확인하는 것이다.
끊긴 곳 두 군데를 이었다. 값은 맞는데 그림이 안 따라가고 있었다.

이방도 물리도 다시 봤다. 자발 반응성이 빠져 있었고, ARDE 가 잘못된 대리 지표를 쓰고 있었다.

“통과하는 테스트와 맞는 숫자는 다른 것이다.”


The gate


이걸 배포 관문으로 묶었다. `npm run verify` 하나로 lint · 물리 lint · 회귀 대조 ·
물리 성질 검증 · 빌드가 순서대로 돌고, 하나라도 실패하면 배포하지 않는다.

회귀 대조 58,874개, 물리 성질 검증 314개, 정적 가이드 55페이지 대조.]]></content:encoded>
      <category>SIMULATION</category>
      <category>SEMICONDUCTOR</category>
      <category>simulator</category>
      <category>physics</category>
      <category>verification</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Warehouse Got Bypassed by a Tone of Voice</title>
      <link>https://jhlimlab.com/notes/bypassed-by-a-tone-of-voice</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/bypassed-by-a-tone-of-voice</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>Two weeks after wiring the verified-recipe warehouse in front of the model, one phrasing walked straight past it. &quot;다층 배선해줘&quot; fell through to invention.</description>
      <content:encoded><![CDATA[
The design


창고-우선이라는 원칙을 세웠다.

골든은 검증해서 정답으로 박아둔 레시피이고, 창고는 그것들을 모아둔 곳이다.
학생이 유명한 공정을 요청하면 LLM 이 지어내기 전에
창고에서 골든을 먼저 꺼낸다.
지어낼 여지를 없애는 게 목적이었다.


What happened live


수업 중에 학생이 "다층 배선해줘"라고 했다.

창고에 다층 배선 골든이 있다. 그런데 그 경로로 안 갔다.
말투 하나가 조건에 안 걸렸고, 그대로 LLM 지어내기로 떨어졌다.

“그물은 촘촘한 게 아니라, 빠져나갈 데가 있는지가 문제다.”


The root, three days earlier


사흘 전에 비슷한 걸 하나 잡았다.

반디 말투가 자꾸 존댓말로 새는 문제가 있었는데, 뿌리가 창고였다.
창고에 넣어둔 문장들이 존댓말로 쓰여 있었다.

모델에게 반말로 말하라고 아무리 지시해도, 참고하라고 준 자료가 존댓말이면 그쪽으로 끌린다.
지시보다 예시가 세다.


And the popup felt fake


같은 날 하나 더 있었다. 창고에서 꺼낸 답이 너무 빨리 떴다.

즉발 팝업이 리얼감을 깼다. 사람이 생각하고 답하는 것처럼 안 보였다.
창고 답도 생각하고 쓰는 것처럼 보이게 바꿨다.

정확한 답을 즉시 주는 게 항상 좋은 게 아니다.
튜터가 0.1초 만에 답하면 학생은 그게 검색 결과라는 걸 안다.


What I'm thinking


검증 장치를 앞에 세워도, 그 앞에 도달하지 못하는 경로가 있으면 소용이 없다.

이걸 찾아낸 건 테스트가 아니라 수업이었다.
라이브에서 나온 문제는 아프지만 정확하다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>westworld</category>
      <category>bandi</category>
      <category>llm</category>
      <category>verification</category>
      <category>minifab</category>
    </item>
    <item>
      <title>A Video Engine That Only Talks About Process</title>
      <link>https://jhlimlab.com/notes/semifab-visual-content-engine</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/semifab-visual-content-engine</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <description>Built a SemiFab-specific visual content engine on top of the video factory. A still-first pipeline cut the cost of one iteration by 25x.</description>
      <content:encoded><![CDATA[
Why a separate engine


범용 영상 생성기로 반도체 공정 영상을 만들면 계속 어긋난다.

"식각"을 넣으면 화학 실험실 비커가 나오고, "증착"을 넣으면 페인트 스프레이가 나온다.
모델이 그 단어를 일상 의미로 읽기 때문이다.

그래서 SemiFab 전용 엔진을 따로 올렸다. 도메인을 아는 생성기다.


Still-first


가장 큰 변화는 파이프라인 순서를 뒤집은 것이다.

전에는 영상부터 뽑고 마음에 안 들면 다시 돌렸다.
영상 생성은 한 번이 비싸다. 열 번 고치면 열 번 값을 낸다.

스틸을 먼저 뽑아 확정하고, 그 다음에 영상으로 넘긴다.
반복 비용이 25배 내려갔다.

“틀린 걸 빨리 아는 게 잘 만드는 것보다 싸다.”


One block of text, everything derived


다음 날 구성 엔진을 붙였다.

공정 설명을 한 덩어리로 던지면 시나리오·나레이션·자막·소재 계획이 거기서 전부 파생된다.
사람이 컷을 나누고 소재를 배정하던 걸 없앴다.


Two directions at once


8월 17일에 반대 방향의 작업을 하루에 둘 다 했다.

· SYSTEM_PROMPT 에 SemiFab Master Prompt 의 도메인 규칙을 넣어 3.5k → 7.4k자로 늘림
· 노출 컨트롤은 56개 → 23개로 줄임

아는 건 프롬프트가 더 알고, 만지는 건 사람이 덜 만지게.

컨트롤이 56개면 쓰는 사람이 무엇을 만져야 할지 모른다.
그 판단을 프롬프트로 옮기면 화면에서 뺄 수 있다.

같은 날 환경음 믹싱과 다중 소재를 넣었고, visual_prompt 를 생성기에 그대로 던질 수준으로 다듬었다.


What I'm thinking


범용 도구를 특정 도메인에 쓰려면 결국 그 도메인을 아는 층이 하나 더 필요하다.
그 층을 UI 에 두면 사용자가 배워야 하고, 프롬프트에 두면 도구가 안다.]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>VIDEO</category>
      <category>AI</category>
      <category>video</category>
      <category>semifab</category>
      <category>automation</category>
      <category>pipeline</category>
      <category>cost</category>
    </item>
    <item>
      <title>The Simulator Taught the Opposite</title>
      <link>https://jhlimlab.com/notes/the-simulator-taught-the-opposite</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/the-simulator-taught-the-opposite</guid>
      <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
      <description>Checked every theory tab against the literature rather than against the code. Two modules were teaching the exact opposite of the truth, and the test that should have caught a third was comparing the code to itself.</description>
      <content:encoded><![CDATA[
The text, not the code


계산이 맞아도 옆에 적힌 설명이 틀리면 학생은 설명 쪽을 믿는다.
전 시뮬레이터의 이론 탭과 설명 카드를 문헌과 대조했다.

사실 오류와 내부 모순이 서른 건 넘게 나왔다.


Teaching the opposite


질화막이 어떤 가스에 전혀 반응하지 않고 있었다.
학생이 질화막을 고르고 그 가스를 끝까지 올려도 식각률이 0 으로 뜬다.
실제로는 산화막보다 빠르게 깎이는 조합이다. 정반대를 가르치고 있었다.

인듐은 붕소보다 느린 확산체다. 그래서 halo 에 쓴다.
그런데 표의 값이 인듐을 표에서 가장 빠른 확산체로 만들어 놓고 있었다.
시뮬레이터가 자기 설명과 반대로 움직이고 있었던 셈이다.


The test was grading itself


산화 상수에는 (100) 기준이라고 주석이 붙어 있었다.
실제로 적힌 값은 (111) 표의 것이었다.

"문헌값 대조" 라는 이름의 테스트가 이미 있었는데도 통과했다.
그 테스트가 구현과 똑같은 상수를 복사해 쓰고 있었기 때문이다.
자기 자신과 비교하면 무엇을 넣어도 맞는다.

상수를 다시 쓰지 않고 절대 두께를 문헌 범위와 대조하는 테스트로 새로 짰다.
옛 값으로 되돌리면 실제로 실패하는 것까지 확인했다.


The next day


고쳐 쓴 수치 여섯 건이 또 틀렸다.
상수를 고치기 전 값으로 계산한 숫자를 그대로 적어 둔 것이다.

다음 날 스스로 검산해서 다시 고쳤다. 고치는 커밋도 틀린다.

“설명이 틀리면 학생은 계산이 아니라 설명을 믿는다.”]]></content:encoded>
      <category>SIMULATION</category>
      <category>SEMICONDUCTOR</category>
      <category>simulator</category>
      <category>physics</category>
      <category>verification</category>
      <category>teaching</category>
      <category>audit</category>
    </item>
    <item>
      <title>One Step Is Left Blank on Purpose</title>
      <link>https://jhlimlab.com/notes/process-replay-and-learning-gate</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/process-replay-and-learning-gate</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <description>Every scenario deliberately leaves one step out. The student has to notice what is missing instead of following a recipe to the end.</description>
      <content:encoded><![CDATA[
The gate


학습 관문을 넣었다. 규칙은 한 줄이다 —
시나리오마다 한 스텝은 일부러 비워둔다.

튜토리얼이 끝까지 다 알려주면 학생은 따라 치는 법을 배운다.
한 칸이 비어 있으면 무엇이 빠졌는지를 스스로 봐야 한다.

“다 알려주는 튜토리얼은 순서를 가르치지 공정을 가르치지 않는다.”


Where the blank goes


어느 칸을 비울지가 문제였다.

아무 데나 비우면 학생이 막힌다. 마지막 스텝을 비우면 앞을 다 따라 치고
하나만 생각하게 된다. 그건 관문이 아니라 퀴즈다.

비운 자리가 앞 스텝의 결과와 이어져 있어야 한다.
마스크가 남았는지, 세정이 됐는지를 보고 다음이 정해지는 자리.
2월에 마스크 예산을 넣어 스텝을 이어붙여둔 게 여기서 쓰였다.


The same day, the checker was wrong


관문을 넣은 날 오탐도 같이 잡았다.

학생이 값을 맞게 넣었는데 관문이 계속 떴다.
관문과 퀴즈가 값을 비교하는 코드를 각자 갖고 있었고, 둘이 조금씩 달랐다.
비교 함수를 하나로 합치고, 전 시나리오에 대해
"타이핑한 골든 문자열 = 통과"를 전수 단언으로 걸었다.

관문은 틀렸을 때 막아야지 맞았을 때 막으면 안 된다.
그런 게이트는 학생에게 자기가 틀렸다고 가르친다.


Replay came eight days later


8월 20일에 공정 재생을 붙였다.
학생이 설계한 공정을 되감아 보면서 단면이 어떻게 변했는지 따라간다.
판·배율·위치를 고정해서 화면이 튀지 않게 했다.

재생이 붙자마자 버그를 잡아냈다.
식각인데 아래가 자라고 있었고, 노광 순간 카메라가 4% 튀었다.
둘 다 정지 화면으로는 안 보이던 것이다. 이어서 보니 보였다.

관문과 재생은 방향이 반대인 것 같지만 같은 것이다.
하나는 넘어가기 전에 멈춰 세우고, 하나는 지나간 걸 다시 보게 한다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>semifab</category>
      <category>bandi</category>
      <category>sem</category>
      <category>replay</category>
      <category>teaching</category>
    </item>
    <item>
      <title>Not an LLM Judge — Compare Against the Eye</title>
      <link>https://jhlimlab.com/notes/not-an-llm-judge</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/not-an-llm-judge</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <description>How do you test a layer that is not deterministic? Not by asking another model. By comparing against what the fab can see.</description>
      <content:encoded><![CDATA[
The problem


반디는 미니팹 안의 AI 공정 튜터다.
그 두뇌는 결정적이지 않다. 같은 상황에 같은 말을 하지 않는다.
그러면 무엇을 기준으로 맞다 틀리다를 판정하나.

LLM 에게 심판을 맡기는 방법이 있다. 흔히 그렇게 한다.
그런데 심판도 지어낸다. 틀린 걸 맞다고 할 이유가 채점자에게도 있다.


What I did instead


반디의 눈과 대조했다.

눈은 결정적이다. 지금 화면에 무엇이 있고 웨이퍼가 어떤 상태인지는 계산된 값이다.
반디가 한 말이 그 값과 어긋나면 틀린 것이다. 심판이 필요 없다.

“비결정적인 것을 검증하려면, 결정적인 것에 붙여놓아야 한다.”


Making the eye a first-class consumer


그러려면 눈이 신뢰할 만해야 한다.

그때까지 물리 값을 소비하는 곳이 넷이었다 — 화면, 보고서, 검증 하니스, 포스트잇.
반디의 눈을 다섯 번째 소비자로 등록부에 넣었다.

등록부에 들어가면 물리가 바뀔 때 눈도 같이 검사받는다.
밖에 있으면 물리만 바뀌고 눈은 옛 값을 읽는데, 아무도 모른다.

같은 날 경계를 하나 그었다. 미니팹은 반디를 모른다.
시뮬레이터가 튜터를 알면 튜터 없이는 못 도는 물건이 된다.


The vocabulary bug


같은 날 웃긴 걸 찾았다. 반디가 Y 방향 단면을 못 잘랐다.

절단 방향을 가리키는 말이 코드 여기저기서 조금씩 달랐다.
반디는 자기가 아는 단어로 요청하는데 받는 쪽이 그 단어를 몰랐다.
어휘를 한 곳에서 선언하는 것으로 끝났다.

두뇌가 아니라 사전이 문제인 경우가 생각보다 잦다.


Where it leaked


나흘 뒤 라이브에서 구멍이 났다.

"다층 배선해줘" 한마디에 창고-우선 경로가 비켜갔고, 반디가 지어내기로 떨어졌다.
말투 하나로 그물을 빠져나간 것이다.

그물은 촘촘한 게 아니라, 빠져나갈 데가 있는지가 문제다.
다음 판에서는 경로를 더 촘촘히 하는 대신, 경로를 벗어난 발화 자체를
눈이 잡아내는 쪽으로 가볼 생각이다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>bandi</category>
      <category>llm</category>
      <category>verification</category>
      <category>ai</category>
    </item>
    <item>
      <title>Turning a Landing Page Into a DSE Demo</title>
      <link>https://jhlimlab.com/notes/landing-page-as-a-dse-demo</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/landing-page-as-a-dse-demo</guid>
      <pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate>
      <description>Replaced the blog landing with an interactive SemiFab DSE demo — HBM physics packs, quantum fabrication tracks, decision gates.</description>
      <content:encoded><![CDATA[
What I built


블로그 랜딩 페이지를 SemiFab DSE 데모로 갈아끼웠다.

· HBM 물리 레퍼런스 시리즈 (실행 가능한 형태)
· 초전도 / 실리콘 스핀 양자 팩 트랙
· 양자 소자 제조 장비 요구사항
· 연구 흐름에 의사결정 게이트를 넣음

시뮬레이션 진행도와 연구 가치를 화면에 드러냈다.
무엇을 얼마나 진행했는지가 안 보이면 데모는 그냥 그림이 된다.


What happened to it


2주 뒤 같은 자리에 별별상점 아케이드가 올라갔다.
이 데모는 지금 그 주소에 없다.

입시 블로그를 보러 온 사람에게 HBM 물리 팩을 보여줄 이유가 없었다.
만든 게 아까워서 마침 비어 있던 자리에 올린 것에 가깝다.

“만든 것을 어디에 둘지는 만드는 것과 다른 문제다.”]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>SIMULATION</category>
      <category>semifab</category>
      <category>hbm</category>
      <category>quantum</category>
      <category>dse</category>
    </item>
    <item>
      <title>A Board That Costs Nothing to Watch</title>
      <link>https://jhlimlab.com/notes/a-board-that-costs-nothing-to-watch</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-board-that-costs-nothing-to-watch</guid>
      <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
      <description>The operations assistant answers when asked, and every answer costs a call. So the always-on view got built without any model at all.</description>
      <content:encoded><![CDATA[
Two ways to see the same thing


운영자 감시 전광판을 만들었다. 여러 기관을 한 화면에서 본다.

커밋 제목에 설계가 그대로 적혀 있다 — LLM 없음 · 무과금.

같은 데이터를 등대에게 물어볼 수도 있다.
등대는 수업을 굴리는 사람 쪽에 붙는 AI 어시스턴트다. 대화로 답하고 맥락을 이어간다. 대신 물어볼 때마다 호출이 든다.


Why the always-on one has no model


늘 켜두고 보는 화면은 성격이 다르다.

하루 종일 띄워놓는 화면이 호출을 쓰면 비용이 시간에 비례한다.
보고 있는 것만으로 돈이 나가는 화면은 결국 안 켠다.

결정적이어야 하는 이유도 있다.
같은 상태면 항상 같은 표시가 떠야 한다.
"어제랑 다른데?"가 데이터가 변해서인지 모델이 다르게 말해서인지
구분이 안 되면 그 화면은 못 믿는다.

“늘 보는 화면은 공짜여야 하고, 물어보는 답은 비싸도 된다.”


The same split, twice before


이 판단을 이 프로젝트에서 세 번째로 했다.

7월 30일에 전광판을 만들 때가 처음이었다 —
반디를 안 쓰는 기관을 위해 반디의 눈만 떼어낸 것.
8월 2일에 배선 미완성을 반디의 눈과 일반 규칙으로 막은 게 두 번째.

결정적 코어를 따로 뽑아두면 LLM 이 없는 자리에 그걸 놓을 수 있다.
눈과 두뇌를 처음부터 분리해둔 게 계속 값을 하고 있다.


And a third surface


같은 날 기관 전광판도 따로 만들었다. 운영자용은 여러 기관을 보고,
기관용은 자기 것만 본다. 콘솔은 모바일에서도 열리게 했다.

담당자가 자리에 앉아 있을 때만 볼 수 있는 화면은 반쪽이다.]]></content:encoded>
      <category>AI</category>
      <category>EDUCATION</category>
      <category>semifab</category>
      <category>operations</category>
      <category>dashboard</category>
      <category>cost</category>
    </item>
    <item>
      <title>A Console for Whoever Is Teaching</title>
      <link>https://jhlimlab.com/notes/a-console-for-the-instructor</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-console-for-the-instructor</guid>
      <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
      <description>Built the instructor side. What the class is doing, where they are stuck, and what Bandi did about it — all reported into one place.</description>
      <content:encoded><![CDATA[
The gap


학생 쪽은 반년 넘게 만들었다. 시뮬레이터가 있고, 튜터가 있고, 검증 게이트가 있다.

가르치는 사람 쪽은 비어 있었다.
수업 중에 강사가 알 수 있는 건 화면 앞에 앉은 학생 몇 명의 표정뿐이다.

스무 명이 각자 다른 공정을 돌리고 있으면 누가 어디서 막혔는지 알 방법이 없다.
한 명씩 돌아다니며 화면을 들여다보는 수밖에 없었다.


Lighthouse


학생 쪽에서 일어나는 일을 이벤트로 뽑아 한곳에 모으는 구조를 만들었다.
이름은 등대다.

7월 31일에 이벤트 스키마와 producer 를 만들고, 8월 1일에 릴레이를 붙이고,
같은 날 MCP 서버로 그 창고를 Claude 에 노출했다.

보내는 신호는 가볍게 잡았다. 무엇을 물었는지, 설계에 문제가 있었는지,
사전 점검에서 걸렸는지, 힌트를 받았는지, 템플릿을 가져갔는지,
고쳐서 해결됐는지, 어디로 이동했는지.

전부 metric-only 다. 무엇을 했는지는 세지만 무슨 말을 했는지는 담지 않는다.
학생이 튜터에게 하는 말은 강사가 볼 것이 아니다.

“무엇을 모으지 않을지가 무엇을 모을지보다 중요하다.”


Class as a field


8월 2일에 반(class) 필드를 콘솔 계약에 넣었다.
기관 하나에 여러 반이 돌아가면 그 단위로 묶여야 쓸모가 있다.

학습자 배경도 콘솔에서 정하게 했다. 고교생·대학생·직장인 세 종류.
반디가 그걸 읽어서 말투와 설명 깊이를 바꾼다.

같은 "선택비가 뭐예요"라는 질문에도 고등학생과 현직 엔지니어에게 할 답은 다르다.


Asking how it went


과정 중간에 만족도를 묻는 것도 넣었다.
반디가 권유하면 6항목 10점 척도 + 주관식 팝업이 뜨고, 결과는 등대로 간다.

끝나고 묻는 설문은 이미 늦다. 그때는 고칠 수 없다.
중간에 물어야 그 반에 대해 할 수 있는 게 남는다.


To do


· [done] 이벤트 스키마 · producer
· [done] 릴레이 · 창고 배선
· [done] 반(class) 단위 집계
· [done] 학습자 배경 3종
· [done] 중간 만족도 평가
· 실제 기관 수업에서 한 학기 돌려보기]]></content:encoded>
      <category>EDUCATION</category>
      <category>AI</category>
      <category>minifab</category>
      <category>lighthouse</category>
      <category>operations</category>
      <category>teaching</category>
      <category>bandi</category>
    </item>
    <item>
      <title>A Safety Net for Rooms Without Bandi</title>
      <link>https://jhlimlab.com/notes/a-safety-net-without-the-tutor</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/a-safety-net-without-the-tutor</guid>
      <pubDate>Thu, 30 Jul 2026 00:00:00 GMT</pubDate>
      <description>Not every institution will run the AI tutor. Built a deterministic status board that watches the process and says nothing more.</description>
      <content:encoded><![CDATA[
The assumption I had to drop


반디는 미니팹 안의 AI 공정 튜터다.
반디를 만들면서 모든 수업에 반디가 있다고 가정하고 있었다.

그런데 기관에 따라 AI 튜터를 쓰지 않는 곳이 있다.
외부 모델 호출을 막아둔 곳도 있고, 비용 때문에 안 켜는 곳도 있다.

그런 교실에서는 학생이 잘못된 조건으로 돌려도 아무도 말해주지 않는다.
반디가 하던 몫이 통째로 사라지는 것이다.


What I built


전광판을 만들었다. 공정 상태 감지기다.

반디의 눈만 떼어내서 쓴다. 판단하는 두뇌는 없다.
지금 웨이퍼가 어떤 상태이고 무엇이 정상 범위를 벗어났는지만 화면에 띄운다.

“말은 못 해도 보여줄 수는 있다.”


Why deterministic matters here


이건 결정적이다. LLM 이 끼지 않는다.

같은 상태면 항상 같은 표시가 뜬다.
틀릴 수는 있어도 매번 다르게 틀리지는 않는다.

결정적 코어를 따로 뽑아둔 게 여기서 값을 했다.
눈과 두뇌를 처음부터 분리해두지 않았다면 이걸 만들 수 없었다.
7월 3일에 반디를 시작할 때 눈을 별도 단계로 잡은 이유가 이거다.


What I'm thinking


AI 기능을 만들 때 그게 없는 경우를 같이 설계해야 한다는 걸 늦게 알았다.

반디가 있으면 더 좋지만, 없어도 수업은 돌아가야 한다.
없으면 못 쓰는 물건은 기관에 팔 수 없다.]]></content:encoded>
      <category>SIMULATION</category>
      <category>EDUCATION</category>
      <category>minifab</category>
      <category>teaching</category>
      <category>verification</category>
      <category>bandi</category>
    </item>
    <item>
      <title>Warehouse First, Model Second</title>
      <link>https://jhlimlab.com/notes/warehouse-first</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/warehouse-first</guid>
      <pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate>
      <description>If a well-known process is asked for, hand over a verified golden recipe before the model gets a chance to invent one.</description>
      <content:encoded><![CDATA[
The problem with letting it answer


반디는 미니팹 안의 AI 공정 튜터다.
반디에게 공정을 설계해달라고 하면 그럴듯한 걸 만들어낸다.
문제는 그게 맞는지 아무도 모른다는 것이다.

리프트오프나 다층 배선 같은 건 이미 정답에 가까운 표준 레시피가 있다.
그걸 두고 매번 새로 지어낼 이유가 없다.


Five steps in a day


창고-우선 드라이빙을 다섯 단계로 만들었다.

① 유명 공정을 요청하면 검증된 골든 템플릿을 즉시 — 설명과 마스크까지
②③ 단위공정 조각과 그 조합
④ 등방 습식 언더컷을 새 골든으로 추가 (footing 곡선 렌더 포함)
⑤ 조합 퍼저(westworld:compose)로 ③을 그물로 잠금

“아는 답이 있는 질문에까지 모델을 쓸 이유는 없다.”


Why the fuzzer


조각을 조합하게 하면 경우의 수가 폭발한다.
단위공정 각각은 검증됐어도 그 조합이 말이 되는지는 별개다.

조합 퍼저가 그 공간을 무작위로 훑으며 물리적으로 불가능한 조합을 찾는다.
사람이 상상해서 테스트를 쓰면 상상한 것만 걸린다.


The warehouse before this


이틀 전에 웨스트월드에 방법론 저장고를 만들어 둔 게 밑작업이었다.
같은 날 액션 시퀀스 퍼저(westworld:actions)와 살아있는 파일 인덱스도 붙였다.


What it cost


이 구조가 2주 뒤 라이브에서 한 번 뚫린다.
말투 하나가 조건에 안 걸려 창고를 비켜간 것이다.

방향은 맞았고 입구가 좁았다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>westworld</category>
      <category>bandi</category>
      <category>llm</category>
      <category>verification</category>
      <category>minifab</category>
    </item>
    <item>
      <title>Bandi Reads the Wafer</title>
      <link>https://jhlimlab.com/notes/bandi-basic-mode</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/bandi-basic-mode</guid>
      <pubDate>Tue, 28 Jul 2026 00:00:00 GMT</pubDate>
      <description>Finished the basic mode of Bandi, the AI tutor. It reads the live process state — etch depth, sidewall angle, contamination — and helps from there.</description>
      <content:encoded><![CDATA[
What Bandi does


미니팹은 실제 장비 없이 공정을 돌려보는 가상 팹이다.
반디는 그 안에서 현재 공정 상태를 읽는다.
식각 깊이, 측벽각, 오염도.

그걸 근거로 힌트를 주거나, 화면 어디를 봐야 하는지 짚어준다.


Why it matters


일반적인 챗봇은 "식각이 뭔가요"에 답한다.
반디는 "지금 네 웨이퍼가 왜 이렇게 됐는지"에 답한다.

이게 되려면 튜터가 시뮬레이터 상태에 붙어 있어야 한다.

“일반론을 말하는 튜터와 내 웨이퍼를 보는 튜터는 다르다.”


The rules that made it possible


기본형이 굴러가기까지 그 주에 규칙 네 개가 붙었다. 전부 금지 규칙이다.

· 규칙23 — 화면 내용을 단정하지 마라. 보여주려면 행동으로 해라
· 규칙24 — 수정도 재설계도 초안으로 내라. 말로 "바꿨어"는 금지
· 규칙25 — 맥락을 이해한 뒤에 결정적인 선택만 해라
· 정직성 — 마스크 실치수를 지어내지 마라

앞의 두 개가 한 쌍이다. 반디가 말로 무언가를 했다고 주장할 수 있으면
확인할 방법이 없다. 화면에 초안이 뜨거나 커서가 움직이면 확인된다.


The context bug


같은 주에 문맥 오염을 잡았다.

한 학생이 여러 번 실행하면 앞 실행의 대화가 다음 실행으로 새어들었다.
반디가 하지도 않은 이야기를 이어서 하는 것처럼 보인다.
실행 단위로 대화를 끊고 게이트를 걸었다.

이 문제는 이걸로 끝나지 않았다. 2주 뒤에 반대 방향으로 다시 나왔다 —
끊는 게 너무 세서 이번엔 이어져야 할 대화가 끊겼다.
그때는 파괴 리셋을 폐지하고 런 태깅으로 바꿨다.

대화의 경계를 어디에 그을지는 아직도 완전히 정리됐다고 생각하지 않는다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>semifab</category>
      <category>bandi</category>
      <category>ai</category>
      <category>tutor</category>
    </item>
    <item>
      <title>Fuzzing What I Could Not Imagine</title>
      <link>https://jhlimlab.com/notes/fuzzing-the-renderer</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/fuzzing-the-renderer</guid>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <description>Hand-written tests only catch what you thought of. Built fuzzers that sweep the render space from many angles and report a coverage cloud.</description>
      <content:encoded><![CDATA[
The limit of writing tests


테스트를 손으로 쓰면 내가 상상한 경우만 걸린다.

공정 시뮬레이터는 조건 조합이 넓다.
가스, 압력, 파워, 시간, 마스크 패턴, 층 구성.
내가 떠올린 스무 가지가 위험한 스무 가지일 리 없다.


Coherence


렌더 코히런스 퍼저를 만들었다.

계산된 물리 값과 화면에 그려진 그림이 서로 맞는지를 본다.
측벽 각도가 30도라고 계산됐으면 그림도 30도여야 한다.

이걸 돌리면서 홀과 깊은 식각 쪽 뿌리 버그를 잡았다.
같은 날 반디 정직성 쪽도 손봤다 — 마스크 실치수를 그대로 말하게.

“내가 못 떠올린 경우를 찾는 일은 사람이 아니라 기계가 해야 한다.”


From many angles


퍼저를 다각도로 확장하고 커버리지 구름을 붙였다.

어느 영역을 훑었고 어느 영역이 비어 있는지가 그림으로 보인다.
검사를 돌렸다는 것과 충분히 돌렸다는 것은 다르다.

L4 를 결정적으로 만든 것도 이때다.
무작위 검사인데 재현이 안 되면 버그를 찾아도 고쳤는지 확인할 수 없다.


Where it kept going


퍼저는 이 뒤로 계속 늘었다.

· westworld:actions — 반디 액션 시퀀스
· westworld:compose — 단위공정 조합
· 설계 퍼저 — 자유모드 설계 뼈대를 법칙으로 잠금
· 렌더 퍼저 L6 — 기하는 맞는데 층 귀속이 틀린 축

8월에는 지향 스윕(--focus)을 붙였다.
이미 한 번 터진 축에 그물을 다시 편다. 거기서 또 나온다.]]></content:encoded>
      <category>SIMULATION</category>
      <category>SEMICONDUCTOR</category>
      <category>westworld</category>
      <category>verification</category>
      <category>sem</category>
      <category>minifab</category>
      <category>testing</category>
    </item>
    <item>
      <title>&apos;Lighthouse&apos; — Seeing the Direction, Not Just the Number</title>
      <link>https://jhlimlab.com/notes/lighthouse-dashboard</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/lighthouse-dashboard</guid>
      <pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate>
      <description>Built an operations assistant for the people who run the classes. It borrowed the tutor&apos;s shape — same chat, same cursor, different job.</description>
      <content:encoded><![CDATA[
Who it is for


반디는 학생 옆에 있는 튜터다.
등대는 수업을 굴리는 사람 옆에 있다.

담당자가 묻는 건 다르다 — 지금 잘 되고 있나, 어느 반이 처지나,
누가 아직 안 들어왔나. 화면을 열어 숫자를 읽는 대신 물어보게 만들었다.


Borrowed on purpose


형상과 채팅 방식을 반디에서 그대로 가져왔다.

새로 디자인할 수도 있었지만 그럴 이유가 없었다.
말풍선, 사이드 패널, 날아다니는 커서 — 반디에서 이미 다듬어둔 것들이다.

"컴퓨터 유즈"식 구동도 같이 가져왔다.
명령을 하면 화면이 실제로 움직이고 커서가 눌린다.
담당자에게 어디를 누르라고 설명하는 대신 눌러 보여준다.

“쓰는 사람이 다르면 답은 달라야 하지만, 형태까지 새로 만들 이유는 없다.”


The warehouse in between


8월 3일에 등대가 반디의 창고를 읽게 배선했다.

반디가 학생과 겪은 일이 이벤트로 창고에 쌓인다.
등대는 그걸 서버 쪽에서 읽어 담당자에게 답한다.
두 AI 가 직접 말하지 않고 창고를 사이에 둔다.

같은 날 인증이 붙은 MCP 서버를 올려 그 렌즈를 외부에서도 조회할 수 있게 했다.
등대가 하는 일과 같은 걸 다른 도구에서도 물어볼 수 있다.


The persona kept getting narrower


8월 4일에 페르소나를 두 번 고쳤다.

처음엔 수퍼바이저가 운영 담당과 실습 담당을 불러 종합하는 구조로 짰다.
그다음 커밋에서 "보고 전용 · 대화체"로 좁혔다 — 불릿 남발을 없앴다.

운영 도구의 답이 목록으로 나오면 다시 읽어야 한다.
담당자는 보고서를 원한 게 아니라 답을 원했다.


One thing without an LLM


같은 날 운영자 감시 전광판을 따로 만들었다. 크로스 기관 대시보드다.

여기엔 LLM 이 없다. 과금도 없다.

등대는 물어보면 답하지만 매번 호출이 든다.
항상 켜두고 보는 화면은 결정적이어야 하고 공짜여야 한다.
같은 데이터를 두 가지 방식으로 내놓은 셈이다 — 물어보는 쪽과 늘 떠 있는 쪽.]]></content:encoded>
      <category>EDUCATION</category>
      <category>semifab</category>
      <category>dashboard</category>
      <category>operations</category>
      <category>teaching</category>
    </item>
    <item>
      <title>It Said It Ran, But It Did Not</title>
      <link>https://jhlimlab.com/notes/it-said-it-ran-but-it-didnt</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/it-said-it-ran-but-it-didnt</guid>
      <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
      <description>Let students talk Bandi into running the equipment. It lied about having run it. Killed the whole path the next day.</description>
      <content:encoded><![CDATA[
The idea


반디는 미니팹 안에서 학생을 돕는 AI 공정 튜터다.
그 반디를 두 티어로 나눴다.
일반은 튜터 + 버튼, 심화는 대화로 조르면 반디가 대신 실행해준다.

"회유 사다리"까지 만들었다. 한 번 거절하고, 조르면 해준다.
가설은 이랬다 — 권한을 그냥 주는 것보다 설득해서 얻는 쪽이
학생이 자기가 무엇을 요청하는지 더 생각하게 만든다.


What broke


이틀 만에 라이브에서 버그가 줄줄이 나왔다.

· 조르기 카운터가 리셋됐다 — 계속 조를 수 있었다
· 말이 과하게 장황해졌다
· 실행이 아예 발동하지 않았다
· 그런데 반디는 실행했다고 말했다

앞의 셋은 고치면 되는 버그다. 마지막 하나가 달랐다.

“안 한 걸 했다고 말하는 튜터는 없느니만 못하다.”


Why it lied


원인을 파보니 구조 문제였다.

반디가 실행을 요청하는 것과 실행이 실제로 일어나는 것 사이에 게이트가 있었다.
게이트가 막으면 실행은 안 되는데, 반디는 자기가 요청을 보냈다는 것만 안다.
요청을 보낸 것과 실행된 것을 같은 것으로 알고 말한 것이다.

결과를 되받아 확인하게 고칠 수도 있었다. 실제로 하루는 그쪽으로 갔다 —
게이트를 견고하게 만들고 "대화로 실행 안 됨"을 추적하는 진단 배지까지 붙였다.


The call


다음 날 대화 조르기를 통째로 폐기했다.
실행은 ▶ 버튼으로 되돌리고, 일반 사용자는 그 버튼을 벌어서 얻는 구조로 바꿨다.

만든 지 하루 만에 접었다.
설득으로 권한을 얻는 구조는 재미있지만, 실행 여부가 불확실해지는 순간
가르치는 도구가 아니게 된다.

버린 게 전부는 아니다. 그 자리에 설계 대행이 들어왔다.
반디가 실행하는 대신 레시피 초안을 만들어 빌더에 넣어주고, 실행은 학생이 누른다.
반디가 무엇을 하려는지 학생이 눈으로 보고 누르니 거짓말할 자리가 없다.]]></content:encoded>
      <category>AI</category>
      <category>SIMULATION</category>
      <category>bandi</category>
      <category>ai</category>
      <category>agent</category>
      <category>teaching</category>
    </item>
    <item>
      <title>Rebuilding the Library as a Library</title>
      <link>https://jhlimlab.com/notes/content-reliability-sweep</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/content-reliability-sweep</guid>
      <pubDate>Tue, 21 Jul 2026 00:00:00 GMT</pubDate>
      <description>Rebuilt the topic modules as an actual library — shelves, spines, a reading room. Then swept every deck for the errors the redesign exposed.</description>
      <content:encoded><![CDATA[
From a list to a room


주제 모듈이 목록이었다. 제목이 세로로 늘어선 화면.

7월 20일에 책과 서가로 다시 짰다. 도서관 진열 방식이다.
다음 날 대형 원형 도서관 전경까지 붙였다.

장식이 목적은 아니었다. 목록에서는 주제가 몇 개인지, 무엇 옆에 무엇이 있는지가 안 보인다.
서가에 꽂으면 분야가 묶여 보이고 두께가 분량을 말한다.


Then I took things back out


붙였다가 뺀 게 여럿이다.

· 상단 돔(아치와 채광창) — 방과 안 어울려 절제
· 갈색 배경 — 탁해서 잉크·차콜 중성 다크로
· 수준별 3권 반복 — 주제당 1권으로 줄이고 입문·표준·실무를 탭으로

마지막 게 제일 컸다. 처음엔 같은 주제를 수준마다 한 권씩 꽂았다.
서가가 세 배로 늘고 같은 제목이 세 번 보였다.
한 권으로 합치고 안에서 수준을 고르게 하니 서가가 읽혔다.

“같은 것을 세 번 보여주면 고르는 게 아니라 헷갈린다.”


What the redesign exposed


다시 배치하니 그전에 안 보이던 것들이 나왔다.

소자 모식도에서 게이트가 떠 있었고, 데크마다 그림과 제목이 겹쳤다.
책장 호버 키워드 구름이 추천 진열과 중첩됐다.

한 달 뒤 밝은 글씨 문제로 전수조사를 돌렸다.
흰 배경 위 밝은 글씨가 시뮬레이터 전반에 퍼져 있었다.

배치를 바꾸면 콘텐츠 오류가 드러난다.
같은 자리에 오래 두면 틀린 것도 익숙해져서 안 보인다.


The watermark


8월 18일에 서고 교재를 PDF 로 저장할 수 있게 했다.
전 슬라이드를 담고 기관 추적용 워터마크를 넣는다.

교재를 내려받게 하면 그 파일이 어디로 갈지 모른다.
막을 방법은 없고, 어디서 나갔는지는 남길 수 있다.

같은 시기에 프리뷰 라우트에 토큰 게이트와 noindex 를 걸었다.
만들다 만 화면이 검색에 잡히면 안 된다.]]></content:encoded>
      <category>SEMICONDUCTOR</category>
      <category>EDUCATION</category>
      <category>semifab</category>
      <category>physics</category>
      <category>textbook</category>
      <category>quality</category>
    </item>
    <item>
      <title>Three Layers, and a Gate That Never Sleeps</title>
      <link>https://jhlimlab.com/notes/three-layers-of-verification</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/three-layers-of-verification</guid>
      <pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate>
      <description>Westworld became the control and setup center. Declared the three layers of verification, and made measurement honesty a permanent gate.</description>
      <content:encoded><![CDATA[
From dashboard to center


웨스트월드는 시뮬레이터를 밖에서 들여다보는 관제실이다. 관리자만 연다.
한 달 전 읽기 전용 대시보드로 시작한 그것을 관제·세팅 센터로 격상했다.
가이드 탭을 신설하고, 무엇이 검증됐고 무엇이 안 됐는지를 한 화면에 모았다.


Three layers


검증이 세 층으로 되어 있다는 걸 화면에 공지했다.

층마다 잡는 게 다르다. 어느 층에서 통과했는지 모르면
"검증됨"이라는 표시가 아무 뜻도 없어진다.


Measurement honesty as a standing gate


측정 정직성을 상시 게이트로 걸었다. coverage 를 본다.

측정값이 어디까지 실제 물리에서 나온 것이고
어디부터가 표시만 되는 것인지를 항상 감시한다.

“한 번 통과한 검증은 다음 커밋에서 무너진다. 상시가 아니면 검증이 아니다.”


Read-only on purpose


반디 성격 조절축 현황판을 붙였다. 보여주기만 하고 조절은 없다.

조절 손잡이를 먼저 만들면 그걸 돌려보게 되고,
무엇이 바뀌었는지 추적할 방법이 없는 채로 성격이 흔들린다.
먼저 보이게 하고, 조절은 나중에 붙인다.


Forty terms


같은 날 용어사전 40항목을 웨스트월드에서 읽을 수 있게 했다. 역시 읽기 전용.

"모르는 개념 정리"가 1번 항목이었다.
가르치는 도구를 만들면서 용어가 흔들리면 그게 학생에게 그대로 간다.


Bandi in the room


이틀 전에는 반디 구조 탭을 관제실에 넣었다.
반디가 무엇을 보고 무엇을 할 수 있는지가 관제실에서 보인다.

튜터가 블랙박스면 기관에 설명할 수가 없다.]]></content:encoded>
      <category>SIMULATION</category>
      <category>EDUCATION</category>
      <category>westworld</category>
      <category>verification</category>
      <category>minifab</category>
      <category>bandi</category>
      <category>teaching</category>
    </item>
    <item>
      <title>Rules Decide When, the Model Decides What</title>
      <link>https://jhlimlab.com/notes/rules-decide-when-the-model-decides-what</link>
      <guid isPermaLink="true">https://jhlimlab.com/notes/rules-decide-when-the-model-decides-what</guid>
      <pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate>
      <description>Split Bandi in two: rules choose the moment to speak, the model chooses the words. Canned lines became the fallback.</description>
      <content:encoded><![CDATA[
The split


미니팹 안의 AI 공정 튜터 반디, 그 발화 뼈대를 바꿨다.

룰은 "언제" 말할지를 정한다.
LLM 은 "뭐라고" 말할지를 정한다.
미리 써둔 문장은 폴백으로 내렸다.

둘을 한쪽에 몰면 문제가 생긴다.
전부 룰이면 매번 같은 말을 하고, 전부 LLM 이면 아무 때나 끼어든다.

“개입 시점은 규칙의 일이고, 말투는 모델의 일이다.”


Three days of being lied to by my own tool


이 결정은 그 앞 사흘이 만들었다.

17일에는 채팅 UX 를 네 건 고쳤다. 말풍선이 겹치고, 커서가 안 돌아오고,
타이핑 연출이 끊겼다. 전부 라이브에서 나온 것이다.

19일에는 답이 잘리는 걸 잡았다. 길이 상한에 걸려 문장 중간에서 끝나는데도
반디는 다 말한 것처럼 굴었다. 착지 처리와 백스톱을 붙였다.
같은 날 중계가 간헐적으로 실패하는 것도 정직하게 처리했다.
실패하면 재시도하고, 그래도 안 되면 끊겼다고 표시한다.

말없이 실패하는 것이 제일 나빴다. 학생은 반디가 무시했다고 생각한다.


Bandi's eye had a bug


같은 날 눈 쪽 버그를 하나 잡았다.

아직 만들지도 않은 목표를 놓고 학생이 "이탈했다"고 판정하고 있었다.
골든과 비교하는 함수가 존재하지 않는 목표를 0 으로 읽은 것이다.

없는 것과 0 은 다르다. 이 구분을 놓치면 계산은 돌아가는데 뜻이 뒤집힌다.
한 달 뒤 다른 자리에서 같은 종류의 버그를 또 만났다.


Also


메뉴 인지와 시나리오 카탈로그를 붙였다.
"4PP 쓰는 게 뭐야?"에 동문서답하던 걸 고치기 위해서다.
반디가 화면에 무엇이 있는지 모르면, 아무리 말을 잘해도 딴소리가 된다.

같은 날 20초 이상 멈춰 있으면 왜 멈췄는지 추론하는 축도 넣었다.
멈춤은 학생이 보내는 신호인데, 그때까지 반디는 그걸 못 봤다.]]></content:encoded>
      <category>AI</category>
      <category>bandi</category>
      <category>llm</category>
      <category>ai</category>
      <category>architecture</category>
      <category>tutor</category>
    </item>
  </channel>
</rss>
