지식위키

FableLayer Procedure & Source Policy (조사 절차·공개안전 정책)

한 줄 요약

조사·검증 절차(procedure)와 소스 라이선스 분류(source policy)를 데이터로 선언하고, 위반을 fail-closed 게이트로 막는 컴포넌트다. 왜 배우나 - “잘했다”는 말 대신 측정 가능한 증거를, “써도 되나”는 직감 대신 보수적 규칙으로 강제해 작업의 안전선을 코드로 고정하기 위해서다.

그림

flowchart TD
    subgraph PROC["procedure.py - 절차 프로파일"]
        P1["ProcedureProfile<br/>4개 모듈"]
        P1 --> M1["verification grounding<br/>증거 없는 완료선언 금지"]
        P1 --> M2["investigation protocol<br/>범위/증거/결정 분리"]
        P1 --> M3["multi-pass review<br/>구조/안전/완전성 분리검사"]
        P1 --> M4["drift prevention<br/>원래 목표에 고정"]
        M1 & M2 & M3 & M4 --> RM["render_markdown()<br/>체크리스트 문서 출력"]
    end

    subgraph SRC["source_policy.py - 소스 정책"]
        S0["Source(name, url, license, classification, risk)"]
        S0 --> CL{"classify()"}
        CL -->|"is_leaked=True"| R1["reference-only / high"]
        CL -->|"license unknown"| R2["unverified / high"]
        CL -->|"MIT/Apache/BSD..."| R3["adapt / low"]
        CL -->|"그 외 식별가능"| R4["reference-only / medium"]
        R1 & R2 & R3 & R4 --> AUD{"audit(ledger)"}
        AUD -->|"위반 0건"| OK["GateResult passed=True"]
        AUD -->|"non-public을 copy/adapt<br/>또는 blocked 존재<br/>또는 미지 값"| NG["GateResult passed=False<br/>reasons 누적"]
    end

쉽게 풀기

이 컴포넌트는 두 개의 규칙집을 합쳐 놓은 것이다.

첫째, 절차(procedure)는 “일하는 자세 체크리스트”다. 호텔 청소부가 “침대 정리 - 욕실 소독 - 비품 보충”을 순서표로 들고 다니듯, AI 작업자도 4가지 묶음의 체크리스트를 들고 다닌다. (1) 완료라고 말하려면 명령어 출력이나 파일 경로 같은 증거를 붙여라, (2) 손대기 전에 기존 파일부터 살펴보고 왜 이 길을 골랐는지 적어라, (3) 만들기와 검사하기를 따로 나눠서 구조-안전-완전성 세 번 훑어라, (4) 길을 잃지 않게 처음 목표와 받아들임 기준을 계속 대조하라. 이 체크리스트는 사람이 읽도록 마크다운 문서로 뽑아낼 수 있다.

둘째, 소스 정책(source policy)은 “남의 자료 갖다 쓰기 안전등급표”다. 식당이 식재료를 받을 때 원산지와 유통기한을 확인하듯, 외부 코드/프롬프트를 받을 때 출처와 라이선스를 확인한다. 핵심은 “의심스러우면 막는다”(fail-closed)는 보수적 태도다.

  • 유출(non-public) 자료다 -> 통째로 복사 금지, 참고만(reference-only), 위험 high.
  • 라이선스를 모르겠다 -> 검증 전엔 못 쓴다(unverified), 위험 high.
  • MIT 같은 관대한 라이선스다 -> 변형해 써도 된다(adapt), 위험 low.
  • 라이선스는 알겠지만 관대하진 않다 -> 보수적으로 참고만(reference-only), 위험 medium.

마지막에 audit이 전체 목록(ledger)을 훑어, 유출 자료를 복사로 분류했거나 차단(blocked) 항목이 섞였거나 정의되지 않은 값이 나오면 “통과 실패”로 막아준다.

핵심 정리

영역핵심 객체/함수하는 일안전 장치
절차ProcedureProfile / render_markdown()4개 모듈 체크리스트를 묶고 문서로 출력모듈마다 purpose+checklist 고정
분류classify()유출/라이선스로 5종 분류 결정unknown은 unverified로 차단
위험classify_risk()분류값을 low/medium/high로 매핑미지 분류는 high로 보수 처리
감사audit()원장 전체 위반 검사위반 시 fail-closed (passed=False)

[!note]- 5가지 분류값과 위험 매핑 전체

  • 분류 CLASS = ("copy", "adapt", "reference-only", "blocked", "unverified")
  • 위험 _RISK = ("low", "medium", "high")
  • classify: is_leaked=True -> reference-only / unknown license -> unverified / permissive(mit·apache·bsd·isc·unlicense) -> adapt / 그 외 -> reference-only
  • classify_risk: leaked -> high / unverified -> high / reference-only -> medium / adapt -> low / blocked -> high / 미지 -> high
  • unknown 토큰: unknown, 불명확, 불명, 모호, none, n/a, na, tbd

[!note]- audit 가 fail 시키는 3가지 위반과 _is_leaked_like 판정

  • 위반1: non-public 성격 소스를 copy 또는 adapt로 분류 -> fail
  • 위반2: classification == “blocked” 가 빌드에 존재 -> fail
  • 위반3: CLASS/_RISK 에 없는 알 수 없는 값 -> fail (fail-closed)
  • _is_leaked_like: license에 “non-public”/“leaked” 포함, 또는 (classification==“reference-only” and risk==“high”)면 유출 성격으로 본다.
  • 기본 원장(default_ledger)은 ATTRIBUTION.md의 10개 소스(MIT 4개, unknown 4개, non-public 2개)를 데이터로 표현.

실제 예시

# fablelayer/source_policy.py  (분류 핵심 로직)
def classify(name: str, license: str, is_leaked: bool) -> str:
    if is_leaked:
        return "reference-only"       # non-public: 전문 포함 금지
    if _is_unknown_license(license):
        return "unverified"           # fail-closed: 검증 전 채택 금지
    if _is_permissive_license(license):
        return "adapt"                # MIT/Apache/BSD...
    return "reference-only"           # 그 외 식별 가능 -> 보수적
# fablelayer/source_policy.py  (원장 감사 = fail-closed 게이트)
def audit(ledger: tuple[Source, ...]) -> GateResult:
    reasons: tuple[str, ...] = ()
    for src in ledger:
        if src.classification not in CLASS:
            reasons = reasons + (f"{src.name}: invalid classification '{src.classification}'",)
            continue
        if src.risk not in _RISK:
            reasons = reasons + (f"{src.name}: invalid risk '{src.risk}'",)
        if _is_leaked_like(src) and src.classification in ("copy", "adapt"):
            reasons = reasons + (f"{src.name}: non-public source must not be copy/adapt ...",)
        if src.classification == "blocked":
            reasons = reasons + (f"{src.name}: blocked source present in build",)
    return GateResult(passed=len(reasons) == 0, reasons=reasons)
# fablelayer/procedure.py  (절차 프로파일 한 모듈 예)
ProcedureModule(
    name="verification grounding",
    purpose="Do not claim completion without measurable evidence.",
    checklist=(
        "Attach command output, file path, or source URL to every completion claim.",
        "Mark untested behavior as unverified.",
        "Prefer fail-closed gates over narrative confidence.",
    ),
)
# 사용 흐름 예시 (의사 코드)
# from fablelayer.source_policy import default_ledger, audit
result = audit(default_ledger())
assert result.passed is True   # 기본 원장은 정책을 위반하지 않도록 구성됨
# from fablelayer.procedure import default_profile
doc = default_profile().render_markdown()  # 절차 체크리스트를 .md 문서로

요약 & 셀프체크

3줄 요약:

  • procedure.py는 4개 모듈(검증근거·조사프로토콜·다중패스리뷰·드리프트방지)의 체크리스트를 데이터로 선언하고 마크다운으로 렌더한다.
  • source_policy.py는 유출 여부와 라이선스로 소스를 5종(copy/adapt/reference-only/blocked/unverified)으로 분류하고 위험등급을 매긴다.
  • audit()이 non-public을 copy/adapt로 분류했거나 blocked가 섞였거나 미지 값이 있으면 fail-closed로 막는다.

셀프체크:

  1. 라이선스가 “TBD”인 소스는 classify에서 어떤 분류가 되고, 그 이유(설계 의도)는 무엇인가?
  2. classification이 “reference-only”이고 risk가 “high”인 소스를 누군가 “adapt”로 바꾸면 audit은 어떻게 반응하는가? (_is_leaked_like 기준으로 설명)
  3. 절차의 “multi-pass review”가 만들기와 검사를 분리하는 이유를, 소스 정책의 fail-closed 태도와 연결해 설명하라.

연결

FL_개요 · _분석축_루브릭