6개의 패턴. 수백 번의 설명. 그리고 실수는 반복됐다.

몇 달 동안 Drewgent에는 품질 패턴이 쌓여갔다. 점진제동, 포카요케, 자동정지+HITL, flaky vs systematic, 두눈 실증, FMEA — 대부분은 장애 대응에서 나왔고, 일부는 Karpathy 원칙에서, 나머지는 그냥 "또 당했네"에서 나왔다.

문제는 이 패턴들을 어디에 보관하느냐였다.

처음엔 시스템 프롬프트에 한 줄씩 넣었다. 그러다 3줄, 5줄, 10줄이 됐다. 프롬프트가 무거워질수록 모델이 패턴을 건너뛰는 빈도가 늘었다. AGENTS.md에도 넣어봤다 — 여전히 사람(과 에이전트)이 직접 읽어야 했다.

설명이 영원히 반복되는 구조는, 완전히 다른 접근이 필요했다.

What This Build Produced

  • patterns registry — 6개 패턴의 정본. frontmatter YAML 하나에 식별자, 레이어, maturity, 태그, 적용 내역을 모두 담았다
  • bridge-lint.sh — 79줄 bash. registry를 읽어서 변경된 파일의 provenance 태그를 검증한다
  • 3-tier enforcement model — Layer 0(구조적, 항상 ON) / Layer 1(원칙, wisdom) / Layer 2(프로세스, OFF by default)
  • patterns registry → lint → enforcement — config-driven 파이프라인. 패턴을 추가하면 lint가 자동으로 새로운 태그를 인식한다

Why Harness, Not System Prompt

시스템 프롬프트는 휘발된다. 모델이 바뀌면 패턴의 무게도 바뀐다. 한 줄이 큰 모델에선 잘 작동했는데 작은 모델에선 무시될 수도 있다.

파일은 휘발되지 않는다. patterns registry는 YAML frontmatter다. 에이전트가 읽을 수 있고, lint가 검증할 수 있고, git이 추적한다. 모델이 바뀌어도 registry는 그대로다.

설명 비용을 0으로 만드는 게 핵심이었다. 매번 “점진제동 원칙에 따라 4단계로 대응해”라고 말하는 대신, 파일에 provenance 태그 하나를 남기면 lint가 자동으로 검증한다. 태그는 공짜다. 설명은 공짜가 아니다.

Slice 1: Patterns Registry (frontmatter YAML)

manufacturing-bridge.md는 단순한 문서가 아니다. 머신 리더블한 패턴 레지스트리다. frontmatter에 patterns 배열로 식별자, 레이어, maturity, 태그를 정의한다.

patterns:
  - id: poka-yoke
    maturity: PROVEN
    layer: 0
  - id: andon
    maturity: PROVEN
    layer: 1
  - id: jidoka
    maturity: PROVEN
    layer: 1
  - id: spc
    maturity: PROVEN
    layer: 1
  - id: 3-hyun
    maturity: PROVEN
    layer: 1
  - id: fmea
    maturity: DRAFT
    layer: 2

이 YAML이 모든 것의 시작이다. bridge-lint.sh는 awk로 이 부분을 파싱해서 유효한 패턴 ID 목록을 만든다. 패턴을 추가하면 lint가 자동으로 새 ID를 인식한다. 패턴을 제거하면 lint가 해당 태그를 unknown으로 경고한다. registry가 곧 스키마다.

Slice 2: 3-Tier Enforcement Model

3개 레이어로 나눈 이유는 단순하다: overhead를 명시적으로 만들기 위해서.

Layer 0 — Structural (항상 ON, overhead 0)

OS나 파일시스템 레벨에서 원천 차단. watcher exclude로 vault 파일 접근 자체를 막고, chmod 600으로 읽기를 구조적으로 불가능하게 만든다. 에이전트의 판단이 필요 없다. 구조가 결정한다.

Layer 1 — Principles (항상 ON, wisdom)

system prompt에 박혀 있는 원칙들. 점진제동, 자동정지+HITL, flaky vs systematic 분류, 두눈 실증 — enforcement 없이 wisdom만으로 작동한다. 검증이 필요 없고, 위반해도 시스템이 멈추지 않는다. 하지만 반복 위반이 Layer 2로 escalation된다.

Layer 2 — Process (OFF by default, 명시적 호출)

FMEA와 bridge-lint가 여기 속한다. 기본적으로 꺼져 있다. 개인 실험/탐험 모드(DREWGENT_MODE=lab)에서는 침묵한다. 공개 레포나 협업 환경에서만 켠다. 프로세스는 유용하지만 피로도를 관리해야 하기 때문이다.

Slice 3: bridge-lint.sh — 79줄의 config-driven 검증기

가장 재미있는 부분이다. bridge-lint.sh는 패턴 레지스트리를 직접 읽는 린터다.

# 1. 패턴 ID 추출
REGISTRY_FILE="harness/patterns/manufacturing-bridge.md"
PATTERN_IDS=$(awk '/^patterns:/{f=1;next} f&&/^  - id:/{print $NF} ...' $REGISTRY_FILE)

# 2. 변경된 .md 파일 스캔
TAGS=$(grep -o 'manufacturing-bridge:[a-z0-9_-]*' "$file")

# 3. registry와 대조 → unknown 태그 경고
if ! echo "$VALID_IDS" | grep -qxF "$TAG_ID"; then
  echo "[WARN] unknown tag '$TAG'"
fi

79줄. awk+grep만으로 registry-driven lint를 구현했다. 핵심은 설계 결정의 추적 가능성이다.

모든 파일에 provenance 태그를 남기면 — 예를 들어 quality-pattern:andon — 누군가 "이 결정 왜 이렇게 했어?"라고 물었을 때, 문서를 뒤질 필요 없이 registry의 패턴 설명을 보여주면 된다. 태그 하나가 설계 근거 3문단을 대체한다.

Architecture

┌─────────────────────────────────────────────────────┐
│               manufacturing-bridge.md                │
│         (YAML frontmatter = patterns registry)       │
└──────────────────┬──────────────────────────────────┘
                   │ reads
                   ▼
┌─────────────────────────────────────────────────────┐
│                  bridge-lint.sh                      │
│     (awk parses registry → grep scans changed files  │
│      → cross-reference → WARNING or pass)            │
└──────────────────┬──────────────────────────────────┘
                   │ enforces
                   ▼
┌─────────────┬──────────────┬──────────────────────┐
│  Layer 0    │   Layer 1    │      Layer 2          │
│  Structural │  Principles  │     Process           │
│  항상 ON    │   항상 ON     │   OFF by default      │
│  poka-yoke  │  andon/jidoka│   FMEA / bridge-lint  │
│  overhead 0 │  spc/3-hyun  │   명시적 호출 필요    │
└─────────────┴──────────────┴──────────────────────┘

Key Design Decisions

결정 대안 선택 이유
YAML frontmatter registry JSON / 별도 DB git-friendly, 인간 가독, awk로 파싱 가능, 문서와 registry가 같은 파일
awk + grep lint Node.js / Python 스크립트 설치 0, 의존성 0, 79줄. lint에 복잡한 로직이 필요하지 않음
3-tier (Layer 0/1/2) flat rule list overhead를 명시화. Layer 2는 OFF by default로 피로도 관리
provenance 태그 자연어 설명 태그는 grep 가능, lint 검증 가능, git 추적 가능. 설명은 안 됨
pre-commit 미적용 자동 pre-commit hook Layer 2는 명시적 호출만. pre-commit은 개발 흐름을 방해

What I Learned

패턴은 모델보다 오래간다. 시스템 프롬프트는 모델 교체 때마다 바뀐다. 패턴 레지스트리는 git에 남아서 수년간 유지된다.

설명보다 태그가 싸다. 3문단짜리 패턴 설명을 system prompt에 넣는 대신, quality-pattern:andon 태그 하나로 대체했다. 태그는 토큰을 거의 소모하지 않고, lint가 존재를 확인해주며, git blame이 도입 시점을 알려준다.

Layer 0이 가장 강력하다. OS/파일시스템 레벨의 구조적 차단은 에이전트의 compliance나 판단이 필요 없다. 구조가 결정한다. 이것이 가장 적은 비용으로 가장 큰 효과를 내는 지점이다.

레지스트리 하나가 lint, 문서, 정책을 동시에 만족한다. 패턴을 추가하면 자동으로 lint가 검증하고, 문서가 업데이트되고, 정책이 적용된다. 별도 동기화가 필요 없다. 그냥 YAML 한 줄이면 된다.

4개 파일, 329줄. 시스템 프롬프트에 100줄을 추가하는 대신, 79줄의 bash 하나로 같은 효과를 냈다. 모든 enforcement는 구조에, 판단은 사람에게.

코드는 harness/patterns/manufacturing-bridge.mdscripts/bridge-lint.sh에서 볼 수 있다.

Thanks for reading. 다음 BUILD LOG는 GraphRCA의 entity extraction 파이프라인에 대한 이야기다.