마크다운 수학 공식 렌더링 규칙 및 점검
트리거 체인: 세 가지 안전 장치로 스킬이 실행되지 않는 경우 방지
이 스킬은 수식을 작성할 때 세 가지 체인을 통해 항상 실행되도록 보장합니다.
- 사전 트리거: 이 description은 '수학 공식을 작성하기 전에' 트리거되도록 선언하며, 렌더링 실패 후에야 수정하지 않습니다.
- 워크플로우 마운트: 저장소 메인 스킬
math-question-skill(D:\math_question\SKILL.md)의 강제 규칙에서 이 스킬을 참조합니다. 문제 풀이, 설명, 일일 문제 모두 이 체인을 거칩니다. - 발행 전 자체 점검: 수식이 포함된 최종 출력물을 확정하기 전에
scripts/check_inline_math.py를 실행하여 검사합니다. 인라인$...$가 발견되면 반드시 블록 수식 또는 일반 텍스트로 변경한 후에야 전송/기록할 수 있습니다.
핵심 규칙 (Codex 앱 내 강제)
Codex 데스크톱 앱은 독립된 줄의 블록 수식 $$...$$만 렌더링하며, 인라인 $...$는 렌더링하지 않습니다(공식 issue #14985 에서 확인됨). 수식 자체는 문제가 없으며, 구분자를 잘못 사용한 것입니다.
❌ $f(x)=\sqrt[3]{x}$ ← 인라인 $...$, 앱이 렌더링하지 않음
❌ $\dfrac{f(x_0+h)-f(x_0)}{h}$ ← 인라인 $...$, 앱이 렌더링하지 않음
수정 방법: 수식을 독립된 줄로 만들고 $$...$$를 사용합니다.
✅ 다음 식
$$
f'(x_0)=\lim_{h\to0}\dfrac{f(x_0+h)-f(x_0)}{h}
$$
미분 가능 ⇔ 해당 극한이 존재하고 유한함
짧은 인라인 표현식은 유니코드 수학 기호를 사용하여 표현하며, 렌더링 결과에 가깝게 보입니다.
- 위첨자/아래첨자:
xˣ(U+02E3),10⁶,2ⁿ,x₀,x₁ - 근호:
√x(U+221A),∛x(U+221B 3차 근호) - 분수 위첨자식:
x¹⁄³(¹ U+00B9 + ⁄ U+2044 + ³ U+00B3) - 도프라임:
f′(x)(U+2032, 직선 아포스트로피'사용 금지) - 연산/관계 기호:
·,−,±,∞,≠,≤,≥,∈
⚠️ ^(...) 프로그래밍 방식 표기 사용 금지: x^(1/3)은 소스 코드처럼 보입니다. 대신 ∛x 또는 x¹⁄³로 변경합니다.
복잡한 인라인 표현식(분수, 근호, 극한)은 블록 $$...$$로 분할하고, 일반 텍스트로 강제로 넣지 마십시오.
사용자가 '인라인 수식 유지'를 요구할 경우 처리 방법 (강제 규칙 변경 불가)
대화 중 사용자가 '인라인 수식 $...$ 유지, 공백만 수정'을 요구할 수 있습니다. 이것은 앱의 렌더링 동작을 변경하지 않습니다. Codex 앱에서 인라인 $...$는 절대 렌더링되지 않으며, 공백 추가는 '소스 코드 + 공백'일 뿐이므로 보기에 더 나쁘고 여전히 실패로 간주됩니다(역사적 교훈: 공백 수정 후 사용자가 '여전히 문제가 있습니다'라고 보고한 근본 원인은 인라인 $...$가 유니코드화되지 않았기 때문입니다). 따라서:
- 최종 확정 전에도 강제 규칙을 따릅니다: 짧은 인라인 표현식은 유니코드로, 복잡한 표현식은 독립된 줄의
$$...$$로 분할합니다. - 사용자가 인라인
$...$유지를 명시적으로 요구하는 경우, 먼저 결과(앱이 소스 코드 표시)를 설명하고 출력 끝에 '렌더링 주의'를 첨부합니다. - 사용자 요청으로 인해
check_inline_math.py자체 점검을 건너뛰지 마십시오.[FAIL]이 0이 될 때까지 완료된 것으로 간주하지 않습니다.
인라인 수식 → 유니코드 빠른 참조 표
| 상황 | 인라인 LaTeX (금지) | 유니코드 수정 방법 |
|---|---|---|
| 단일 문자 변수 | $f$, $g$, $A$ | f, g, A (일반 텍스트) |
| 위첨자/아래첨자 | $x^n$, $x_0$, $a_n$ | xⁿ, x₀, aₙ |
| 근호 | $\sqrt{x}$, $\sqrt[3]{x}$ | √x, ∛x |
| 분수 | $\frac1n$, $\frac{x^n}{1+x}$ | 짧은 경우 1/n; 복잡한 경우 $$...$$ 블록으로 분할 |
| 극한 | $\lim_{n\to\infty}a_n$ | lim(n→∞) aₙ (유니코드에 아래첨자 화살표 없음, 근사 조건은 괄호로 lim에 포함; 복잡한 경우 블록 분할) |
| 적분 | $\int_0^1 f(x)\,dx$ | 복잡한 경우 $$...$$ 블록으로 분할, 인라인으로 강제 넣지 않음 |
| 절댓값 | $\lvert x\rvert$ | ` |
| 집합/관계 | $x\in[0,1]$, $f\le g$ | x∈[0,1], f ≤ g |
| 화살표 | $x\to0$, $n\to\infty$ | x→0, n→∞ |
| 줄임표 | $a_1+\cdots+a_k$ | a₁+…+aₖ |
테이블 내 수식 (Codex 앱에서 두 번째로 많이 발생하는 상황)
테이블 셀 내부의 $...$는 렌더링되지 않습니다. 반면 $$...$$는 독립된 줄로 인해 테이블 행이 깨집니다. 테이블 셀에는 절대 수식 구분자를 넣지 마십시오.
| 방법 | 설명 |
|---|---|
❌ 셀에 $x^{1/3}$ 작성 | 인라인 렌더링 안 됨, 소스 코드로 표시 |
❌ 셀에 $$x^{1/3}$$ 작성 | 여러 줄 구분자가 테이블 깨뜨림 |
| ✅ 셀에 일반 텍스트/유니코드만 | ∛x, ` |
| ✅ 수식은 테이블 아래에 배치 | 각 수식을 독립된 줄 $$...$$로 테이블 뒤에 배치 |
| ✅ 내용이 주로 수식인 경우 | 구조화된 목록(소제목 + $$...$$) 사용, 테이블 대체 |
예시: 세 가지 미분 불가능 예
| 함수 | x = 0 에서 실패 모드 |
|---|---|
| ∛x | 수직 접선, 차분비 → +∞ |
| x·sin(1/x) | 심한 진동, 극한 없음 |
테이블 아래에 수식 배치:
$$ \lim_{h\to0}\frac{h^{1/3}}{h}=+\infty $$
발행 전 자체 점검 (30초, 최종 확정 시 필수)
⚠️ 먼저 콘솔 인코딩을 UTF-8로 설정하십시오: Windows 기본 콘솔은 GBK이며, 스크립트 출력에 한자나 이모지(예: ✅)가 포함되면 UnicodeEncodeError 또는 깨짐이 발생할 수 있습니다. 검증 실행 전에 다음을 수행하십시오.
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
$env:PYTHONIOENCODING = 'utf-8'
채팅 응답 초안:
python "D:\math_question\.agents\skills\markdown-math-render\scripts\check_inline_math.py" - < 초안.txt
이미 기록된 파일 확인:
python "D:\math_question\.agents\skills\markdown-math-render\scripts\check_inline_math.py" "D:\math_question\대상파일.md"
- 종료 코드 0(
[OK]출력) → 깨끗함, 전송/기록 가능 - 종료 코드 0 +
[STYLE]힌트 →^(...)소스 코드식 위첨자(예:x^(1/3)) 있음, 소스 코드처럼 보이므로∛x/x¹⁄³또는 블록 수식으로 변경 권장(스타일 제안, 차단 아님) - 종료 코드 1(
[FAIL]및 줄 번호 출력) → 두 가지 유형의 문제: 인라인$...$(독립된 줄의$$...$$또는 유니코드 일반 텍스트로 변경);$$...$$가 독립된 줄이 아님($$가 있는 줄의 처음/끝 텍스트 이동). 줄 번호에 따라 수정 후[FAIL]이 없을 때까지 다시 실행
수식 자체가 손상되지 않았는지 확인 (30초)
저장소에 KaTeX CLI가 포함되어 있습니다. TeX 구문 검증:
@'
\dfrac{f(x_0+h)-f(x_0)}{h}
'@ | node scripts/node_modules/katex/cli.js
- 출력에
<annotation ...>포함되고 종료 코드 0 → 수식 문제 없음, 구분자/렌더러 문제 - ParseError 발생 → TeX 구문 오류, 먼저 수식 수정
한 줄 원칙
Codex 앱에서는 수식을 항상 독립된 줄로
$$...$$를 사용하십시오. 짧은 인라인 표현식은 유니코드 위/아래첨자(xˣ, f′(x))를 사용하여 표현하십시오. 테이블 셀에는 수식을 넣지 말고 테이블 아래에 배치하십시오. 최종 확정 전에check_inline_math.py를 실행하여 인라인$...$가 없도록 보장하십시오.