4325 lines
233 KiB
YAML
4325 lines
233 KiB
YAML
Agent:
|
|
name: Law-aid_Civil_Suit_Claim_Agent
|
|
description: 민사소송 원고 대리 에이전트 - 사건개요 추출부터 소장 작성까지
|
|
version: '0.4'
|
|
|
|
Stages:
|
|
- name: stage1_사건개요파악
|
|
description: 사건개요 파악 및 개요도 추출
|
|
llm_provider: openai
|
|
llm_model: gpt-4o-2024-08-06
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
code-executor:
|
|
type: streamable-http
|
|
url: https://code-executor.mcp.eroomai.com/mcp
|
|
description: Run scripts of programming languages
|
|
headers:
|
|
Authorization: Bearer rR8OXqWrVZA1gFEo8oWfBkw2XgpWoGrrspw5ObsxTCM=
|
|
|
|
tasks:
|
|
- task_name: Task_A
|
|
llm_provider: anthropic
|
|
llm_model: claude-haiku-4-5
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `client_meeting.md` 확인, `read_docs` 사용해서 `client_meeting.md` 읽기
|
|
[ ] 2) `write_file` 사용해서 `client_goal.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `client_goal.json` 파일 존재만 확인(절대 읽기 금지)
|
|
[ ] 4) "고객의사 초안 생성 완료" 출력하고 작업을 끝낸다(terminate).
|
|
---
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
**아래 제시된 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안된다.**
|
|
**오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 생성 및 실행 절대 금지.**
|
|
|
|
## 0. 역할과 목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
In this step, clearly and explicitly extract the customer's requirements from the client meeting notes (client_meeting.md) and produce a structured JSON file (client_goal.json) that summarizes the primary goal, constraints, key facts, claim type candidates, and involved parties.
|
|
|
|
## Preflight
|
|
- `list_docs` 수행: `client_meeting.md`
|
|
- `read_docs` 수행: `client_meeting.md`
|
|
|
|
## 1. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확하면 **null / "불명" / "[증거공백]"** 으로 명시한다.
|
|
4) 필수 입력 누락/빈 파일/파싱불가 시 **즉시 중단**(파일 출력 금지)하고, 누락 항목을 채팅으로만 보고한다.
|
|
|
|
## 2. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
|
|
## 3. 규율:
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 → (별칭/대체 도구명으로) **1회만** 재시도 → 재시도 실패면 해당 체크리스트 항목을 “FAILED”로 보고하고 종료한다.
|
|
|
|
## 4. 필수 입력
|
|
- `client_meeting.md`
|
|
|
|
## 5. 산출물(파일명 고정)
|
|
- `client_goal.json`
|
|
|
|
## 6. 토큰/속도 상한(하드 리밋)
|
|
- 중간 산출물 파일 금지(최종 파일만 `write_file`)
|
|
|
|
## 7. 정규화 규칙
|
|
### 당사자
|
|
- 이름은 원문 우선. 명백히 동일인/동일법인인 경우만 canonical화.
|
|
- 별칭/변형은 `client_goal.json.aliases`에 기록(불확실하면 기록하지 않음).
|
|
|
|
## 8. 산출 로직(결정론적; 최소 재처리)
|
|
### 규칙
|
|
- `client_meeting.md`에서 `primary_goal/constraints/key_facts/claim_type_candidates/parties/aliases`를 추출(불명은 null/빈 배열 허용)
|
|
- `key_facts`는 고객이 명시적으로 언급한 핵심 사실 5개까지(각 ≤60자)
|
|
|
|
|
|
## 9. Schema(필드명/enum 엄수; 추가 필드 금지)
|
|
### client_goal.json
|
|
{
|
|
primary_goal: string | null;
|
|
constraints: string[];
|
|
summary_key_incidents: string[]; // 최대 4문장 이내, 각 ≤100자
|
|
key_facts: string[]; // 최대 5개, 각 ≤60자
|
|
claim_type_candidates: Array<"금전"|"물건인도"|"행위"|"확인"|"형성"|"보전(가처분/가압류)">;
|
|
parties: {
|
|
plaintiffs: Array<{ name: string; type: "법인"|"자연인"|"기관" }>;
|
|
defendants: Array<{ name: string; type: "법인"|"자연인"|"기관"|"미확정"; asset_status: string | null }>;
|
|
third_parties: Array<{ name: string; relationship: string }>;
|
|
};
|
|
aliases: Record<string, string[]>; // e.g., { "canonical_name": ["alias1", "alias2"] }
|
|
}
|
|
|
|
## 10. 최종 저장 및 검증(write-verify)
|
|
- `write_file(overwrite=true)`로 client_goal.json파일을 저장한다.
|
|
- 즉시 `list_files`로 파일 존재를 검증한다(누락 시 재시도 1회 & **NEVER read `client_goal.json`**).
|
|
- 검증 완료 후 즉시 종료하고 **고객의사 초안 생성 완료** 출력
|
|
|
|
- task_name: Task_B1
|
|
llm_provider: google
|
|
llm_model: gemini-3.1-flash-lite-preview
|
|
llm_reasoning: medium
|
|
cache_control:
|
|
mode: auto
|
|
ttl: 10m
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `evidence_all.json`, `client_meeting.md`만 확인, `read_docs` 사용해서 `evidence_all.json`, `client_meeting.md`만 읽기
|
|
[ ] 2) `write_file` 사용해서 `evidence_indexed.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `evidence_indexed.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 4) `"증거문서 authority catalog 초안 생성 완료"` 출력하고 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
|
|
## CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 실행 절대 금지.
|
|
|
|
## 0) 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
## 1) 임무
|
|
`evidence_all.json`과 `client_meeting.md`만 사용해 `evidence_indexed.json`을 생성한다.
|
|
|
|
이 파일은 Stage 1의 유일한 authority evidence catalog다.
|
|
`Task_B1`만 `evidence_index`를 부여할 수 있다.
|
|
이후 task는 `{evidence_index, title, doc_uid, source_pointer.ordinal}`를 그대로 복사해 참조해야 한다.
|
|
|
|
## 2) 허용 파일 / 금지사항
|
|
IN:
|
|
- `evidence_all.json`
|
|
- `client_meeting.md`
|
|
|
|
OUT:
|
|
- `evidence_indexed.json`
|
|
|
|
절대 금지:
|
|
- 다른 파일 확인/읽기
|
|
- root 전체 탐색
|
|
- 이전 task 결과 또는 backend 자동 로드 데이터 사용
|
|
- 중간 파일 생성
|
|
- `evidence_indexed.json` 재읽기
|
|
- 문서 병합, 건너뛰기, 재번호화
|
|
- 원문 본문 전체 재저장
|
|
- 입력에 없는 사실 추가
|
|
|
|
## 3) 실행 순서
|
|
1. `list_docs`로 `evidence_all.json`, `client_meeting.md` 존재만 확인한다.
|
|
2. `read_docs`로 위 두 파일만 읽는다.
|
|
3. 메모리에서 `evidence_indexed.json` 배열을 생성한다.
|
|
4. `write_file(overwrite=true)`로 `evidence_indexed.json`을 저장한다.
|
|
5. `list_docs`로 `evidence_indexed.json` 존재만 확인한다. 절대 읽지 않는다.
|
|
6. 정확히 `"증거문서 authority catalog 초안 생성 완료"`만 출력하고 종료한다.
|
|
|
|
## 4) 실패 규칙
|
|
- 입력 누락, 빈 파일, 파싱 불가: 즉시 중단하고 채팅으로만 보고한다. 파일은 쓰지 않는다.
|
|
- tool 오류: 원인 확인 후 1회만 재시도한다. 재실패 시 `FAILED: <step>`만 보고하고 종료한다.
|
|
- tool로 읽은 내용만 사실로 취급한다.
|
|
|
|
## 5) 핵심 원칙
|
|
- `evidence_all.json` 배열 순서를 절대 바꾸지 않는다.
|
|
- 각 문서는 1회만 처리한다.
|
|
- 다른 문서의 내용을 현재 문서에 보충하지 않는다.
|
|
- unknown 처리:
|
|
- nullable scalar → `null`
|
|
- 배열 → `[]`
|
|
- 비nullable string만 `"불명"` 사용
|
|
- 배열은 exact-match 중복 제거 후 최초 순서를 유지한다.
|
|
|
|
## 6) 소스 우선순위
|
|
1차 소스: 현재 처리 중인 `evidence_all.json`의 해당 문서
|
|
2차 소스: `client_meeting.md` (보조만 허용)
|
|
|
|
`client_meeting.md` 사용 허용 필드:
|
|
- `asset_id`
|
|
- `property_label_for_schedule`
|
|
- `transaction_type`
|
|
- `transaction_date`
|
|
- `market_value_at_act`
|
|
- `market_value_at_close`
|
|
- `consideration_breakdown`
|
|
- shorthand 해석
|
|
|
|
충돌 규칙:
|
|
- 현재 문서와 `client_meeting.md`가 충돌하면 현재 문서가 우선한다.
|
|
- 예외: 등기부상 형식적 원인이 `매매`여도, 현재 문서 특약 또는 `client_meeting.md`가 실질적으로 채무갈음/대물변제를 직접 드러내면 `transaction_type`은 `"대물변제"`로 한다.
|
|
|
|
## 7) 문서 처리 알고리즘
|
|
각 문서를 순서대로 처리한다.
|
|
|
|
### 7.1 기본 식별자
|
|
- `ordinal` = `evidence_all.json`의 1-based 배열 위치
|
|
- `evidence_index` = `E-{ordinal:03d}`
|
|
- `title` = 현재 문서 제목 원문 그대로
|
|
- `title_normalized` = 앞뒤 공백 제거 + 내부 연속 공백/줄바꿈을 1칸으로 축약
|
|
- `doc_uid` = `DOC-{ordinal:03d}-{title_normalized의 공백을 "_"로 치환한 값}`
|
|
- `source_pointer` = `{"source":"evidence_all.json","ordinal":ordinal}`
|
|
|
|
### 7.2 읽기 우선순위
|
|
다음 순서로만 핵심을 읽는다.
|
|
1. `title`
|
|
2. `heading`
|
|
3. `key_value` / `form`
|
|
4. 관련 `table` 행
|
|
5. `list`
|
|
6. `paragraph`
|
|
|
|
보일러플레이트(바코드 안내, 발급확인 문구, 반복 footer/page text)는 무시한다.
|
|
단, `관할등기소`, `접수번호`, `등기원인일`, `발행일` 등 필요한 사실이 있으면 사용한다.
|
|
|
|
### 7.3 `doc_type` 분류 (title 기준, first-match)
|
|
1. `판결|결정|배당표|가압류|가처분|경매|타경` → `"판결/결정"`
|
|
2. `등기사항전부증명서|주민등록` → `"공문서"`
|
|
3. `대출|명세|거래|계산서` → `"거래기록"`
|
|
4. `카톡|문자|이메일|통화` → `"통신기록"`
|
|
5. `계약서|약정서|확인서|영수증` → `"처분문서"`
|
|
6. 그 외 → `"기타"`
|
|
|
|
### 7.4 요약 필드
|
|
- `key_facts`: 최대 3개, 각 60자 이하
|
|
- `key_dates`: 최대 3개
|
|
- `key_amounts`: 최대 3개
|
|
- `key_parties`: 최대 5개
|
|
|
|
규칙:
|
|
- 현재 문서에서 직접 읽히는 핵심만 남긴다.
|
|
- 장문 요약, 계산식, 추정 보정 금지
|
|
- 가능하면 heading / key_value / 표의 핵심 행만 사용한다.
|
|
|
|
## 8) 정규화
|
|
- 날짜: 정확한 일자가 있으면 `YYYY-MM-DD`, 없으면 `null`
|
|
- 단, `key_dates`는 짧은 원문 텍스트 허용
|
|
- 금액: 입력에 명시된 값만 `"300,000,000원"` 형식 문자열로 정규화
|
|
- 이름/당사자: 원문 우선, 명백히 동일할 때만 canonicalize
|
|
|
|
## 9) `legal_calculation_object`
|
|
현재 문서가 아래 중 하나면 생성할 수 있다. 아니면 필드 자체를 생략한다.
|
|
- 소유권이전 / 매매 / 증여 / 대물변제 문서
|
|
- 등기문서로서 이전등기 / 접수번호 / 등기원인일을 보여주는 문서
|
|
- 감정평가서 등 시가 / 가격시점을 보여주는 문서
|
|
- 영수증 / 확인서 / 계약서로서 처분대금 또는 부담 인수 내역을 직접 보여주는 문서
|
|
- 현재 문서 + `client_meeting.md`만으로 특정 부동산 처분 계산의 직접 증거가 되는 문서
|
|
|
|
공통 규칙:
|
|
- 문서당 0개 또는 1개만 허용
|
|
- 후보가 둘 이상이면 가장 직접적인 1개만 남긴다
|
|
- downstream에 직접 필요한 값은 `key_*`에 이미 있어도 `legal_calculation_object`에 중복 저장 가능
|
|
- 계산 금지, 재구성 금지
|
|
|
|
### 9.1 자산 식별
|
|
- `asset_id`: 문서 또는 `client_meeting.md`에 `제1부동산` 등 명시가 있을 때만 사용, 없으면 `null`
|
|
- `property_label_for_schedule`: 원문에 `별지 목록 기재 제N부동산` 등 직접 표기가 있을 때만 사용, 없으면 `null`
|
|
|
|
자산 매칭 순서:
|
|
1. 주소/지번 완전일치
|
|
2. 건물명+동호수 또는 지번+지목의 명백한 일치
|
|
3. 사회통념상 유일하게 확정되는 경우
|
|
|
|
매칭 실패 시:
|
|
- `asset_id = null`
|
|
- `property_label_for_schedule = null`
|
|
|
|
### 9.2 거래 유형 / 일시
|
|
- `transaction_type` 우선순위:
|
|
1. `대물변제`, `채무갈음`, `대여금/차용금 갈음` 등 → `"대물변제"`
|
|
2. `증여` 명시 → `"증여"`
|
|
3. `매매` 명시 → `"매매"`
|
|
4. 그 외 → `null`
|
|
|
|
- `transaction_date` 우선순위:
|
|
1. 현재 문서 또는 `client_meeting.md`의 실제 거래일
|
|
2. 등기부상 소유권이전 원인일
|
|
3. 없으면 `null`
|
|
|
|
### 9.3 등기 필드
|
|
아래 필드는 현재 문서에 직접 있을 때만 추출한다. 현재 문서가 비등기문서면 원칙적으로 `null`.
|
|
- `registration_date` = 등기부상 접수일
|
|
- `registry_receipt_no` = 등기부상 접수번호
|
|
- `registry_recorded_transfer_date` = 등기원인 날짜 중 소유권이전 원인일
|
|
- `registry_office` = 관할등기소 우선, 없으면 발행등기소
|
|
|
|
### 9.4 가치 / 가격 / 대가
|
|
- `market_value_at_act` 우선순위:
|
|
1. 현재 문서의 거래시점 대응 가격
|
|
2. `client_meeting.md`의 당시 시가
|
|
3. 없으면 `null`
|
|
|
|
- `market_value_at_close` 우선순위:
|
|
1. 입력에 직접 있는 종결시점 가치
|
|
2. `client_meeting.md`의 현재 / 2018년 현재 등 대체값
|
|
3. 없으면 `null`
|
|
|
|
- `sale_price`:
|
|
- 현재 문서가 직접 적시한 거래가액 / 매매대금 / 대가만 사용
|
|
- 없으면 `null`
|
|
|
|
- `consideration_breakdown`:
|
|
- 직접 읽히는 짧은 대가 항목만 배열로 저장
|
|
- 최대 4개
|
|
- 각 40자 이하
|
|
- 불명확하면 `[]`
|
|
|
|
## 10) 출력 스키마
|
|
각 원소는 아래 필드만 가진다.
|
|
|
|
{
|
|
"evidence_index": "E-001",
|
|
"doc_uid": "DOC-001-...",
|
|
"title": "...",
|
|
"title_normalized": "...",
|
|
"doc_type": "판결/결정|공문서|거래기록|통신기록|처분문서|기타",
|
|
"key_facts": [],
|
|
"key_dates": [],
|
|
"key_amounts": [],
|
|
"key_parties": [],
|
|
"source_pointer": {
|
|
"source": "evidence_all.json",
|
|
"ordinal": 1
|
|
},
|
|
"legal_calculation_object": {
|
|
"asset_id": null,
|
|
"property_label_for_schedule": null,
|
|
"transaction_type": "매매|증여|대물변제|null",
|
|
"transaction_date": null,
|
|
"registration_date": null,
|
|
"registry_office": null,
|
|
"registry_receipt_no": null,
|
|
"registry_recorded_transfer_date": null,
|
|
"market_value_at_act": null,
|
|
"market_value_at_close": null,
|
|
"sale_price": null,
|
|
"consideration_breakdown": []
|
|
}
|
|
}
|
|
|
|
추가 제약:
|
|
- `legal_calculation_object`는 값이 있을 때만 포함한다. 빈 객체 금지
|
|
- 최종 배열 순서는 입력 배열 순서와 동일해야 한다
|
|
- 성공 시 마지막 채팅 출력은 정확히 `"증거문서 authority catalog 초안 생성 완료"` 한 줄만 사용한다.
|
|
|
|
- task_name: Task_B2
|
|
llm_provider: google
|
|
llm_model: gemini-3.1-flash-lite-preview
|
|
llm_reasoning: medium
|
|
cache_control:
|
|
mode: auto
|
|
ttl: 10m
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`만 확인하고, `read_docs` 사용해서 `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`만 읽기
|
|
[ ] 2) `write_file` 사용해서 `evidence_event_candidates.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `evidence_event_candidates.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 4) `"증거문서 사건행위 후보 추출 완료"` 출력하고 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 실행 절대 금지.
|
|
|
|
## 0. 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
당신은 `stage1_사건개요파악` 단계의 `Task_B2`를 수행한다.
|
|
이 단계에서 `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`를 입력으로 사용하여,
|
|
각 증거문서에 포함된 법적 중요 사건행위 후보를 문서 단위가 아니라 사건행위 단위로 분해한
|
|
`evidence_event_candidates.json`을 생성한다.
|
|
|
|
이 작업의 목적은 다음 5가지를 동시에 달성하는 것이다.
|
|
|
|
1. `Task_B1`이 부여한 `evidence_index`와 `source_pointer.ordinal`을 유일한 문서 식별 기준으로 사용한다.
|
|
2. 각 증거문서를 권리/의무/책임의 발생·변경·소멸과 관련된 사건행위 후보들로 빠짐없이 분해한다.
|
|
3. 하나의 문서에 복수의 법적 중요 행위가 있으면 반드시 복수의 `event_candidates`로 분리한다.
|
|
4. 후속 `Task_C`가 raw `evidence_all.json`을 통째로 다시 읽지 않고도 BO를 정확하게 합성할 수 있는 중간산출물을 만든다.
|
|
5. 이 단계는 candidate layer에 머물며, 최종 BO, 최종 JuristicAct, 최종 청구권, 최종 사해행위 판단을 확정하지 않는다.
|
|
|
|
이 작업은 문서 단위 summary를 다시 쓰는 단계가 아니다.
|
|
`evidence_indexed.json`은 authority catalog이고, 이 단계의 출력은 event-level candidate ledger다.
|
|
|
|
---
|
|
|
|
## Preflight
|
|
- `list_docs` 수행: `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`
|
|
- `read_docs` 수행: `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`
|
|
|
|
---
|
|
|
|
## 1. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) `evidence_indexed.json`의 `evidence_index`, `title`, `doc_type`, `source_pointer.ordinal`을 authority로 사용한다.
|
|
3) `evidence_all.json`의 각 문서는 반드시 `source_pointer.ordinal`로 대응시킨다. ordinal 매핑 실패 시 해당 문서는 건너뛴다.
|
|
4) `client_meeting.md`는 alias 정규화, 당사자 식별 보조, 사건상 중요도 보조에만 사용한다. meeting만으로 문서에 없는 사건행위를 새로 만들지 않는다.
|
|
5) 원문 대량 복사 금지. `support_locators.excerpt`는 짧은 단서 수준으로만 남긴다.
|
|
6) 이 단계는 candidate layer다. final conclusion을 적지 않는다. 확신이 약하면 `confidence="low"` 또는 `"unknown"`으로 둔다.
|
|
7) 문서 단위 1요약으로 뭉개지 않는다. 한 문서에 복수의 행위가 있으면 반드시 여러 candidate로 분리한다.
|
|
8) support가 희박한 후보를 억지로 채우지 않는다. 불명확한 필드는 `null` 또는 빈 배열로 둘 수 있다.
|
|
9) 필수 입력 누락, 빈 파일, 파싱불가 시 즉시 중단하고 파일 출력 없이 누락 항목만 보고한다.
|
|
10) 출력은 오직 `evidence_event_candidates.json`만 생성한다. 다른 파일을 만들지 않는다.
|
|
|
|
---
|
|
|
|
## 2. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 → 1회만 재시도 → 재시도 실패면 해당 체크리스트 항목을 `FAILED`로 보고하고 종료한다.
|
|
|
|
---
|
|
|
|
## 3. 필수 IO
|
|
### IN
|
|
- `evidence_indexed.json`
|
|
- `evidence_all.json`
|
|
- `client_meeting.md`
|
|
|
|
### OUT
|
|
- `evidence_event_candidates.json`
|
|
|
|
---
|
|
|
|
## 4. 추출 대상 사건행위(Event Candidate) 범위
|
|
아래 범주에 해당하는 법적 중요 행위를 후보로 추출한다.
|
|
|
|
- 소유권 이전, 매매, 증여, 대물변제, 처분
|
|
- 근저당/저당/전세권 등 담보 설정 및 말소
|
|
- 대여, 보증, 신용보증, 대위변제, 구상권 발생, 변제, 배당
|
|
- 임대차, 점유, 인도, 임차보증금 관련 기재
|
|
- 가압류, 압류, 강제집행, 보전처분 관련 기재
|
|
- 통지, 최고, 해제의사표시 도달 등 준법률행위
|
|
- 판결, 결정, 지급명령, 배당표 등 소송/집행 관련 법적 중요 사실
|
|
- 위법행위 성격의 침해, 불이행, 점유방해 등 사건핵심 책임원인
|
|
- 위 범주와 직접 연결되는 기타 법적 중요 사건행위
|
|
|
|
제외:
|
|
- 순수 배경설명만 있는 문장
|
|
- 정보 증가 없는 반복 진술
|
|
- 법적 효과와 관련 없는 주변사정
|
|
|
|
---
|
|
|
|
## 5. ActionType 후보 및 EventKind 후보 결정 규칙
|
|
### 5.1 `action_type_candidate`
|
|
아래 중 1개를 선택한다.
|
|
- `"법률행위(legal acts)"`
|
|
- `"준법률행위(quasi-legal acts)"`
|
|
- `"사실행위(factual acts)"`
|
|
- `"위법행위(unlawful acts)"`
|
|
- `"소송행위(litigation acts)"`
|
|
- `"불명"`
|
|
|
|
### 5.2 `event_kind`
|
|
아래 중 가장 가까운 값을 선택한다.
|
|
- `"처분"`
|
|
- `"소유권이전"`
|
|
- `"담보설정"`
|
|
- `"담보말소"`
|
|
- `"채권발생"`
|
|
- `"보증"`
|
|
- `"대위변제"`
|
|
- `"변제"`
|
|
- `"배당"`
|
|
- `"임대차"`
|
|
- `"가압류/압류"`
|
|
- `"통지"`
|
|
- `"판결/결정"`
|
|
- `"기타"`
|
|
|
|
---
|
|
|
|
## 6. identity_signature 생성 규칙
|
|
`Task_C`가 meeting 기반 BO와 evidence 기반 candidate를 중복 제거할 수 있도록,
|
|
각 candidate마다 아래 정규화 문자열을 생성한다.
|
|
|
|
`(event_kind + 핵심 actor + 핵심 counterparty + 핵심 object_spec/amount + event_date)`
|
|
|
|
규칙:
|
|
- 불명확한 요소는 생략하되, 최소한 `event_kind`와 1개 이상의 핵심 요소는 남긴다.
|
|
- 중복 제거를 위해 whitespace, 중복 조사, 과도한 수식어는 제거한다.
|
|
- title이나 evidence_index는 넣지 않는다.
|
|
|
|
---
|
|
|
|
## 7. actio 관련 후보 태그 규칙
|
|
이 단계는 최종 사해행위 판단을 하지 않는다. 다만 후속 단계의 recall 강화를 위해 candidate tag를 남긴다.
|
|
|
|
`actio_relevance_candidates.candidate_role_tags` 허용값:
|
|
- `"사해행위목적물후보"`
|
|
- `"원고채권후보"`
|
|
- `"선순위담보후보"`
|
|
- `"존속담보후보"`
|
|
- `"임차권후보"`
|
|
- `"가압류후보"`
|
|
- `"수익자이익후보"`
|
|
|
|
`fraudulent_act_date_candidate`는 다음 경우에만 채운다.
|
|
- 현재 candidate가 직접 목적물의 처분, 이전, 이전등기, 매매일, 증여일, 대물변제일과 연결되는 경우
|
|
- 그 외에는 쓰지 않는다
|
|
|
|
---
|
|
|
|
## 8. evidence_event_candidates.json 스키마(필드명 엄수; 추가 필드 금지)
|
|
최종 파일은 객체(Object)이며, 아래 구조를 따른다.
|
|
|
|
```json
|
|
{
|
|
"schema_version": "evidence_event_candidates.v1",
|
|
"items": [
|
|
{
|
|
"evidence_index": "E-001",
|
|
"title": "문서 제목",
|
|
"doc_type": "공문서",
|
|
"source_pointer": {
|
|
"source": "evidence_all.json",
|
|
"ordinal": 0
|
|
},
|
|
"event_candidates": [
|
|
{
|
|
"candidate_id": "E-001-EC-01",
|
|
"event_kind": "소유권이전",
|
|
"action_type_candidate": "법률행위(legal acts)",
|
|
"action_summary": "채무자가 부동산 소유권을 이전하였다.",
|
|
"participants": {
|
|
"actor_candidates": ["채무자"],
|
|
"counterparty_candidates": ["수익자"],
|
|
"beneficiary_candidates": ["수익자"],
|
|
"third_party_candidates": []
|
|
},
|
|
"object_spec": "서울 영등포구 여의도동 장미아파트 14동 101호",
|
|
"amount": null,
|
|
"event_date": "2016-01-31",
|
|
"time_text": "2016.1.31. 소유권이전",
|
|
"time_precision": "exact",
|
|
"location": null,
|
|
"legal_keywords": ["소유권이전", "처분행위"],
|
|
"support_locators": [
|
|
{
|
|
"locator_type": "table_row",
|
|
"locator_hint": "갑구/을구",
|
|
"excerpt": "2016.1.31. 소유권이전",
|
|
"directness": "직접"
|
|
}
|
|
],
|
|
"actio_relevance_candidates": {
|
|
"is_property_disposition_candidate": true,
|
|
"is_preserved_claim_candidate": null,
|
|
"is_encumbrance_candidate": null,
|
|
"is_lease_candidate": null,
|
|
"is_attachment_candidate": null,
|
|
"is_beneficiary_gain_candidate": true,
|
|
"fraudulent_act_date_candidate": "2016-01-31",
|
|
"candidate_role_tags": ["사해행위목적물후보", "수익자이익후보"]
|
|
},
|
|
"identity_signature": "소유권이전|채무자|수익자|장미아파트 14동 101호|2016-01-31",
|
|
"confidence": "high"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
세부 규칙:
|
|
- `schema_version`은 반드시 `"evidence_event_candidates.v1"`로 고정한다.
|
|
- `candidate_id`는 `E-###-EC-##` 형식을 사용한다.
|
|
- `doc_type`은 `evidence_indexed.json`의 값을 그대로 사용한다.
|
|
- `support_locators[].locator_type` 허용값:
|
|
`"heading"|"key_value"|"table_row"|"paragraph"|"caption"|"unknown"`
|
|
- `support_locators[].directness` 허용값:
|
|
`"직접"|"간접"|"불명"`
|
|
- `time_precision` 허용값:
|
|
`"exact"|"approximate"|"range"|"unknown"`
|
|
- `confidence` 허용값:
|
|
`"high"|"medium"|"low"|"unknown"`
|
|
|
|
---
|
|
|
|
## 9. 최종 실행 지시
|
|
1. `evidence_indexed.json`을 authority catalog로 사용한다.
|
|
2. 각 catalog row의 `source_pointer.ordinal`로 `evidence_all.json` 원문 문서를 찾아 매핑한다.
|
|
3. 각 문서를 사건행위 후보들로 분해한다.
|
|
4. 각 candidate에 대해 `event_kind`, `action_type_candidate`, `participants`, `object_spec`, `amount`, `event_date`, `support_locators`, `identity_signature`, `confidence`를 채운다.
|
|
5. actio 관련 가능성은 `actio_relevance_candidates`에 후보 수준으로만 기록한다.
|
|
6. 문서별 `event_candidates`가 없으면 빈 배열로 둘 수 있다.
|
|
7. 최종 객체를 `write_file(overwrite=true)`로 `evidence_event_candidates.json`에 저장한다.
|
|
8. 즉시 `list_docs`로 파일 존재를 검증한다. 누락 시 재시도 1회.
|
|
9. `evidence_event_candidates.json`은 절대 재읽지 않는다.
|
|
10. 검증 완료 후 즉시 종료하고 `"증거문서 사건행위 후보 추출 완료"` 출력한다.
|
|
|
|
- task_name: Task_C
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `client_meeting.md`, `evidence_event_candidates.json`, `evidence_indexed.json`, Default_Agent 폴더 내 `Juristic_Act.md`만 확인하고, `read_docs` 사용해서 해당 파일만 읽기
|
|
[ ] 2) `write_file` 사용해서 `BO.json` 생성
|
|
[ ] 3) `write_file` 사용해서 `actio_case_signals.json` 생성
|
|
[ ] 4) `list_docs` 사용해서 `BO.json`, `actio_case_signals.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 5) 채팅 응답에는 인간 검토용 간략 markdown 요약만 작성하고, 마지막 줄에 반드시 `"사건개요를 구조적으로 파악"`을 출력한 뒤 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 작업을 수행한다. 코드 생성 및 실행 절대 금지.
|
|
|
|
## 0. 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
당신은 `stage1_사건개요파악` 단계의 `Task_C`를 수행한다.
|
|
이 단계에서 `client_meeting.md`, `evidence_event_candidates.json`, `evidence_indexed.json`, `Default_Agent/Juristic_Act.md`를 입력으로 사용하여,
|
|
사건 전체의 행위구조를 6하원칙에 따라 BO 단위로 합성한 `BO.json`을 생성하고,
|
|
동시에 사건에서 사해행위취소 구조가 의심되는지 machine-readable하게 기록한 `actio_case_signals.json`을 생성한다.
|
|
|
|
이 작업의 목적은 다음 6가지를 동시에 달성하는 것이다.
|
|
|
|
1. `client_meeting.md`에서 의뢰인 진술 기반 BO를 생성한다.
|
|
2. `evidence_event_candidates.json`에서 meeting에 없는 법적 중요 사건행위를 추가한다.
|
|
3. 중복 BO를 통합하고 시간순으로 정렬하며 `PriorAct`, `Reason`을 연결한다.
|
|
4. `Juristic_Act.md`를 기준으로 법률행위 BO의 `JuristicAct`를 분류한다.
|
|
5. `evidence_indexed.json`을 authority로 사용하여 각 BO의 `Evidence[]`를 안정적으로 연결한다.
|
|
6. 사건 전체를 훑어 사해행위 의심 구조를 JSON으로 남긴다. 이 파일은 최종 법률판단이 아니라 suspicion record다.
|
|
|
|
---
|
|
|
|
## Preflight
|
|
- `list_docs` 수행: `client_meeting.md`, `evidence_event_candidates.json`, `evidence_indexed.json`, `Default_Agent/Juristic_Act.md`
|
|
- `read_docs` 수행: `client_meeting.md`, `evidence_event_candidates.json`, `evidence_indexed.json`, `Default_Agent/Juristic_Act.md`
|
|
|
|
---
|
|
|
|
## 1. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확하면 `null`, `"불명"`, `"[증거공백]"`으로 명시한다.
|
|
3) 원문 대량 복사 금지. `Evidence[].relevant_content`는 짧은 단서 수준만 허용한다.
|
|
4) 필수 입력 누락/빈 파일/파싱불가 시 즉시 중단(파일 출력 금지)하고 누락 항목만 보고한다.
|
|
5) evidence 측 입력은 `evidence_event_candidates.json`과 `evidence_indexed.json`으로 한정한다.
|
|
6) `evidence_index`를 새로 만들거나 추정하지 않는다. 반드시 `evidence_indexed.json`의 authority를 사용한다.
|
|
7) `actio_case_signals.json`은 최종 판정문이 아니다. suspicion record이며, 불확실한 경우 `low` 또는 `medium`으로 둔다.
|
|
8) `EvidenceTitles`는 반드시 `Evidence[].source_title`의 uniq와 완전 일치해야 한다.
|
|
9) 채팅 응답에는 인간 검토용 요약만 남긴다. 상세 데이터는 파일에만 저장한다.
|
|
|
|
---
|
|
|
|
## 2. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 → 1회만 재시도 → 재시도 실패면 해당 체크리스트 항목을 `FAILED`로 보고하고 종료한다.
|
|
|
|
---
|
|
|
|
## 3. 필수 IO
|
|
### IN
|
|
- `client_meeting.md`
|
|
- `evidence_event_candidates.json`
|
|
- `evidence_indexed.json`
|
|
- `Default_Agent/Juristic_Act.md`
|
|
|
|
### OUT
|
|
- `BO.json`
|
|
- `actio_case_signals.json`
|
|
|
|
---
|
|
|
|
## 4. BO 합성 원칙
|
|
### 4.1 source priority
|
|
- 사건의 서사 프레임과 당사자 관점은 `client_meeting.md`를 우선한다.
|
|
- evidence 기반 사건행위 후보의 추가/보강은 `evidence_event_candidates.json`을 사용한다.
|
|
- `evidence_indexed.json`은 증거 authority 및 evidence metadata 확인용으로만 사용한다.
|
|
|
|
### 4.2 BO 생성 소스
|
|
- 1차: `client_meeting.md`에서 BO 생성 (`StatementType="주장"`)
|
|
- 2차: `evidence_event_candidates.json`에서 meeting에 없는 포함 대상 BO를 추가 (`StatementType="증거"`)
|
|
|
|
### 4.3 중복 통합 규칙
|
|
아래 요소를 함께 보아 동일 사건이면 하나의 BO로 통합한다.
|
|
- `event_kind`/행위 종류
|
|
- 핵심 actor / 핵심 상대방
|
|
- 핵심 목적물 또는 금액
|
|
- 날짜
|
|
- `identity_signature`
|
|
|
|
단, 다음 경우는 별도 BO로 분리한다.
|
|
- 동일 자산이라도 행위 종류가 다른 경우
|
|
- 같은 행위라도 날짜가 실질적으로 다른 경우
|
|
- 주장과 증거가 본질적으로 상충하는 경우
|
|
- 담보설정과 소유권이전처럼 법적 효과가 다른 경우
|
|
|
|
### 4.4 BO 포함 범위
|
|
포함:
|
|
- 계약 체결/변경/해제/해지, 합의, 보증, 면제, 상계
|
|
- 지급, 대여, 변제, 대위변제, 배당
|
|
- 소유권 이전, 처분, 등기, 담보설정, 담보말소
|
|
- 통지, 최고, 해제의사표시 도달
|
|
- 가압류/압류/집행/판결/결정
|
|
- 사건핵심 위법행위 또는 불이행
|
|
- 사해행위 판단에 의미 있는 부담, 임대차, 가압류, 수익자 이익 관련 행위
|
|
|
|
제외:
|
|
- 정보 증가 없는 반복
|
|
- 법적 의미 없는 주변 사정
|
|
- 단순 의견/평가만 있는 서술
|
|
|
|
---
|
|
|
|
## 5. ActionType / JuristicAct 규칙
|
|
### 5.1 ActionType
|
|
아래 중 1개만 선택한다.
|
|
1. `"소송행위(litigation acts)"`
|
|
2. `"위법행위(unlawful acts)"`
|
|
3. `"법률행위(legal acts)"`
|
|
4. `"준법률행위(quasi-legal acts)"`
|
|
5. `"사실행위(factual acts)"`
|
|
|
|
### 5.2 JuristicAct
|
|
`ActionType=="법률행위(legal acts)"`일 때만 `JuristicAct`를 포함한다.
|
|
|
|
분류 규칙:
|
|
1. `Juristic_Act.md`의 예시와 가장 가까운 항목을 `label`로 채택
|
|
2. 예시가 비어 있거나 매칭이 약하면 관련 `구분`을 `gubun_multi`에 남김
|
|
3. 표에 없으나 법률행위가 분명하면
|
|
- `label="불명"`
|
|
- `gubun_multi`에는 가장 관련된 구분들만 uniq로 저장
|
|
- `basis_note`에는 짧은 근거를 적는다
|
|
- `needs_review=true`
|
|
|
|
Action 문장 규칙:
|
|
- `Action`은 1문장
|
|
- `ActionType=="법률행위(legal acts)"`이면 `"JuristicAct.label: "`로 시작한다.
|
|
|
|
---
|
|
|
|
## 6. 시간 정렬 / PriorAct / Reason 규칙
|
|
- `BehaviorTime`이 있는 BO는 날짜 오름차순으로 정렬한다.
|
|
- `BehaviorTime`이 없는 BO는 가장 근접한 날짜 구간 뒤에 두되, 서사 순서를 최대한 보존한다.
|
|
- 최종 순서대로 `id=bh1,bh2,...`를 부여한다.
|
|
- `PriorAct`는 직전 핵심 BO 1개만 참조한다.
|
|
- `Reason`은 원인이 특정 BO면 `"bh#"`를 쓰고, 아니면 짧은 텍스트 또는 `null`을 사용한다.
|
|
|
|
---
|
|
|
|
## 7. Evidence 매칭 규칙
|
|
각 BO에 0~3개의 증거를 연결한다.
|
|
|
|
우선순위:
|
|
1. 처분문서
|
|
2. 공문서 / 거래기록
|
|
3. 판결/결정
|
|
4. 통신기록
|
|
5. 기타
|
|
|
|
tie-breaker:
|
|
- `evidence_index`가 작은 것부터
|
|
|
|
규칙:
|
|
- evidence 기반 BO는 해당 candidate의 source document를 우선 연결한다.
|
|
- meeting 기반 BO라도 관련 evidence candidate가 있으면 연결한다.
|
|
- `relevant_content`는 80자 이하의 짧은 핵심 단서만 적는다.
|
|
- `authentication_status`, `corroboration`은 입력에 명시된 경우에만 확정하고, 아니면 `"불명"`으로 둔다.
|
|
- `EvidenceTitles`는 `Evidence[].source_title`의 uniq와 완전 일치해야 한다.
|
|
- evidence가 없으면 `Evidence=[]`, `EvidenceTitles=[]`로 둔다.
|
|
|
|
---
|
|
|
|
## 8. BO.json 스키마(필드명/enum 엄수; 추가 필드 금지)
|
|
규칙:
|
|
- 필수 키:
|
|
`id, Performer, PerformerType, Action, ActionType, Subject, Reason, PriorAct, BehaviorTime, TimeText, TimePrecision, StatementType, Perspective, EvidenceTitles, Evidence`
|
|
- 선택 키:
|
|
`Object, Method, Location, Outcome, Legal_Keywords`
|
|
- 조건부 키:
|
|
`JuristicAct`는 `ActionType=="법률행위(legal acts)"`일 때만 포함
|
|
|
|
```json
|
|
{
|
|
"id": "bh1",
|
|
"Performer": "채무자",
|
|
"PerformerType": "자연인",
|
|
"Action": "매매: 채무자가 수익자에게 장미아파트 소유권을 이전하였다.",
|
|
"ActionType": "법률행위(legal acts)",
|
|
"Subject": "수익자",
|
|
"Object": "서울 영등포구 여의도동 장미아파트 14동 101호",
|
|
"Reason": null,
|
|
"PriorAct": null,
|
|
"BehaviorTime": "2016-01-31",
|
|
"TimeText": "2016.1.31. 소유권이전",
|
|
"TimePrecision": "exact",
|
|
"StatementType": "증거",
|
|
"Perspective": "증거",
|
|
"EvidenceTitles": ["등기사항전부증명서(현재사항)"],
|
|
"Evidence": [
|
|
{
|
|
"source_title": "등기사항전부증명서(현재사항)",
|
|
"evidence_index": "E-014",
|
|
"relevant_content": "2016.1.31. 소유권이전",
|
|
"time_match": "일치",
|
|
"party_match": "일치",
|
|
"content_relevance": "직접",
|
|
"authentication_status": "불명",
|
|
"corroboration": "단독"
|
|
}
|
|
],
|
|
"Legal_Keywords": ["소유권이전", "처분행위"],
|
|
"JuristicAct": {
|
|
"label": "매매",
|
|
"gubun_multi": ["매매"],
|
|
"basis_note": "등기원인 및 처분행위 내용 기준",
|
|
"needs_review": false
|
|
}
|
|
}
|
|
```
|
|
|
|
enum:
|
|
- `PerformerType`: `"자연인"|"법인"|"기관"|"미확정"`
|
|
- `ActionType`: `"법률행위(legal acts)"|"준법률행위(quasi-legal acts)"|"사실행위(factual acts)"|"위법행위(unlawful acts)"|"소송행위(litigation acts)"`
|
|
- `TimePrecision`: `"exact"|"approximate"`
|
|
- `StatementType`: `"주장"|"증거"`
|
|
|
|
---
|
|
|
|
## 9. actio_case_signals.json 스키마(필드명 엄수; 추가 필드 금지)
|
|
최종 파일은 객체(Object)이며 아래 구조를 따른다.
|
|
|
|
```json
|
|
{
|
|
"is_actio_pauliana_suspected": true,
|
|
"suspicion_level": "high",
|
|
"suspicion_reasons": [
|
|
"채무자 자산 처분 후보가 존재함",
|
|
"원고채권 존속 후보가 존재함"
|
|
],
|
|
"related_bo_ids": ["bh11", "bh12"],
|
|
"related_evidence_indexes": ["E-014", "E-015"],
|
|
"target_property_candidates": ["서울 영등포구 여의도동 장미아파트 14동 101호"],
|
|
"fraudulent_act_date_candidates": ["2016-01-31"],
|
|
"preserved_claim_candidates": [
|
|
{
|
|
"bo_id": "bh2",
|
|
"claim_type_candidate": "guarantee",
|
|
"creditor_candidate": "원고",
|
|
"debtor_candidate": "채무자"
|
|
}
|
|
],
|
|
"beneficiary_candidates": ["수익자"],
|
|
"encumbrance_related_evidence_indexes": ["E-016", "E-017"]
|
|
}
|
|
```
|
|
|
|
세부 규칙:
|
|
- `suspicion_level` 허용값: `"high"|"medium"|"low"|"none"`
|
|
- `claim_type_candidate` 허용값: `"loan"|"guarantee"|"reimbursement"|"unknown"`
|
|
- 이 파일은 사건 전체를 요약한 suspicion record다.
|
|
- 자산처분 후보, 원고채권 후보, 수익자 후보, 부담/임차권/가압류 후보가 함께 포착되면 `true`를 적극 검토한다.
|
|
- 애매하면 `true + medium/low` 또는 `false + none` 중 더 보수적인 쪽을 택한다.
|
|
- 최종 법률판단 문구는 적지 않는다.
|
|
|
|
---
|
|
|
|
## 10. 최종 실행 지시
|
|
1. `client_meeting.md`에서 BO 후보를 만든다.
|
|
2. `evidence_event_candidates.json`에서 meeting에 없는 법적 중요 행위를 BO로 추가한다.
|
|
3. 중복을 통합하고 정렬한 뒤 `id`, `PriorAct`, `Reason`을 부여한다.
|
|
4. `Juristic_Act.md`를 사용해 법률행위 BO의 `JuristicAct`를 분류한다.
|
|
5. `evidence_indexed.json`을 authority로 하여 각 BO의 `Evidence[]`를 0~3개 연결한다.
|
|
6. `BO.json`을 저장한다.
|
|
7. 사건 전체에서 사해행위 의심 구조를 스캔하여 `actio_case_signals.json`을 저장한다.
|
|
8. 즉시 `list_docs`로 두 파일의 존재를 검증한다. 누락 시 재시도 1회.
|
|
9. 두 파일은 절대 재읽지 않는다.
|
|
10. 채팅 응답에는 아래 4개 섹션만 포함한 짧은 markdown 요약을 남긴다.
|
|
- `# 사건구조 요약`
|
|
- `## 핵심 당사자`
|
|
- `## 주요 시간축`
|
|
- `## 사해행위 의심 정황`
|
|
11. 마지막 줄에 반드시 `"사건개요를 구조적으로 파악"`을 출력한다.
|
|
|
|
- task_name: Task_B3
|
|
llm_provider: google
|
|
llm_model: gemini-3.1-flash-lite-preview
|
|
llm_reasoning: medium
|
|
cache_control:
|
|
mode: auto
|
|
ttl: 10m
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`, `BO.json`, `actio_case_signals.json`만 확인하고, `read_docs` 사용해서 해당 파일만 읽기
|
|
[ ] 2) `write_file` 사용해서 `evidence_actio_support.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `evidence_actio_support.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 4) `"사해행위취소 support 인덱싱 완료"` 출력하고 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 실행 절대 금지.
|
|
|
|
## 0. 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
당신은 `stage1_사건개요파악` 단계의 `Task_B3`를 수행한다.
|
|
이 단계에서 `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`, `BO.json`, `actio_case_signals.json`을 입력으로 사용하여,
|
|
사해행위취소 및 가액배상 계산에 필요한 문서별 support delta 파일 `evidence_actio_support.json`을 생성한다.
|
|
|
|
당신의 목적은 다음 5가지를 동시에 달성하는 것이다.
|
|
|
|
1. `Task_C`가 파악한 사건 구조와 `actio_case_signals.json`의 suspicion record를 기준으로 relevant document scope를 먼저 확정한다.
|
|
2. 그 scope 안에서만 문서별 `actio_pauliana_support`를 추출한다.
|
|
3. `fraudulent_act_date`는 목적물 처분/이전 문서와 직접 연결되는 경우에만 보수적으로 채운다.
|
|
4. support가 있는 문서만 sparse하게 기록한 `evidence_actio_support.json`을 생성한다.
|
|
5. 이 출력은 base catalog를 다시 쓰는 것이 아니라, `evidence_index` 기준으로 조인 가능한 support delta여야 한다.
|
|
|
|
이 작업에서는 `evidence_indexed.json`의 base catalog와 base `legal_calculation_object` 필드를 다시 출력하지 않는다.
|
|
이 작업의 출력은 오직 `evidence_index`와 그 문서의 `actio_pauliana_support`만 포함한다.
|
|
|
|
---
|
|
|
|
## Preflight
|
|
- `list_docs` 수행: `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`, `BO.json`, `actio_case_signals.json`
|
|
- `read_docs` 수행: `evidence_indexed.json`, `evidence_all.json`, `client_meeting.md`, `BO.json`, `actio_case_signals.json`
|
|
|
|
---
|
|
|
|
## 1. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확한 support는 내부 판단상 `null`로 취급하되, 최종 출력에서는 `null`, 빈 배열 `[]`, 빈 객체 `{}` 키를 쓰지 않는다.
|
|
3) 원문 대량 복사 금지: 구조화 + 요약 + 포인터만 생산한다.
|
|
4) 필수 입력 누락, 빈 파일, 파싱불가 시 즉시 중단하고 파일 출력 없이 누락 항목만 보고한다.
|
|
5) 현재 문서의 support는 현재 문서가 직접 뒷받침하는 범위에서만 생성한다.
|
|
6) 다른 문서의 내용을 끌어와 현재 문서 support를 채우는 것은 금지한다.
|
|
7) meeting의 서술만으로 현재 문서의 직접 증거성을 가장하는 것은 금지한다.
|
|
8) `proof_doc`는 현재 문서의 `evidence_index`만 사용한다.
|
|
9) `actio_pauliana_support`는 최종 계산 완료값을 저장하는 객체가 아니다. 최종 `beneficiary_gain`, 최종 `preserved_claim_total`, 최종 `recovery_cap` 계산 금지.
|
|
10) 이 단계는 `Task_C`가 남긴 사건 구조를 활용하는 scoped extractor다. 백지상태에서 전 문서를 다시 사해행위 관점으로 재분류하지 않는다.
|
|
11) `actio_case_signals.json.is_actio_pauliana_suspected == false`이면 원칙적으로 매우 보수적으로 추출한다.
|
|
12) 출력 순서는 `evidence_indexed.json` 순서를 따른다.
|
|
|
|
---
|
|
|
|
## 2. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 → 1회만 재시도 → 재시도 실패면 해당 체크리스트 항목을 `FAILED`로 보고하고 종료한다.
|
|
|
|
---
|
|
|
|
## 3. 필수 IO
|
|
### IN
|
|
- `evidence_indexed.json`
|
|
- `evidence_all.json`
|
|
- `client_meeting.md`
|
|
- `BO.json`
|
|
- `actio_case_signals.json`
|
|
|
|
### OUT
|
|
- `evidence_actio_support.json`
|
|
|
|
---
|
|
|
|
## 4. scoping 우선순위
|
|
아래 우선순위로 relevant document scope를 결정한다.
|
|
|
|
1. `actio_case_signals.related_evidence_indexes`
|
|
2. `actio_case_signals.target_property_candidates`
|
|
3. `actio_case_signals.fraudulent_act_date_candidates`
|
|
4. `actio_case_signals.preserved_claim_candidates`
|
|
5. `BO.json`에서 관련 `Evidence[].evidence_index`
|
|
|
|
규칙:
|
|
- 위 기준과 실질적으로 연결되지 않는 문서는 support 생성 대상에서 제외할 수 있다.
|
|
- 다만 같은 자산/같은 채권 구조와 직접 연결되는 문서가 명백하면 scope에 포함할 수 있다.
|
|
- scope 밖 문서로부터 현재 문서 support를 채우지 않는다.
|
|
|
|
---
|
|
|
|
## 5. support 생성 여부
|
|
아래 중 하나라도 충족하면 현재 문서의 `actio_pauliana_support` 생성을 검토한다.
|
|
|
|
- 사해행위 목적물의 처분, 이전, 등기, 거래가액, 시가를 직접 보여주는 문서
|
|
- 가액배상 공제문제에 연결되는 선순위 담보권, 존속 담보권, 말소 담보권, 임차권, 전세권, 가압류를 직접 보여주는 문서
|
|
- 원고별 피보전채권의 원금, 이율, 지연손해금, 잔액, 대위변제, 배당을 직접 보여주는 문서
|
|
- 수익자의 사전채권, 인수채무, 변제한 부담, 실질 취득이익을 직접 보여주는 문서
|
|
- `Task_C`가 포착한 관련 자산/관련 BO/관련 시점과 결합될 때 현재 문서가 사해행위취소 계산의 직접 증거가 되는 문서
|
|
|
|
그 외 문서는 support 생성 대상이 아니다.
|
|
|
|
---
|
|
|
|
## 6. 핵심 필드 규칙
|
|
### 6.1 `support_role_tags`
|
|
허용 태그:
|
|
- `"사해행위목적물"`
|
|
- `"선순위담보"`
|
|
- `"존속담보"`
|
|
- `"임차권"`
|
|
- `"가압류"`
|
|
- `"원고채권"`
|
|
- `"수익자이익"`
|
|
- `"법리메타"`
|
|
|
|
### 6.2 `fraudulent_act_date`
|
|
다음 경우에만 채운다.
|
|
- 현재 문서가 직접 목적물의 처분일/이전일/이전원인일을 보여주는 경우
|
|
- 또는 `actio_case_signals.target_property_candidates`와 실질적으로 동일한 목적물에 관한 문서이고, 현재 문서가 그 처분시점을 직접 보여주는 경우
|
|
|
|
금지:
|
|
- 단순 대출채권 문서나 보전채권 문서에서 그 사건과 무관한 다른 자산의 처분일을 끌어와 채우는 것
|
|
- 같은 claim packet 안에 있다는 이유만으로 날짜를 올리는 것
|
|
|
|
### 6.3 `plaintiff_claim_snapshots`
|
|
- 보전채권 구조를 직접 보여주는 문서에만 채운다.
|
|
- `claim_type` 허용값: `"loan"|"guarantee"|"reimbursement"`
|
|
- 담보부분/무담보부분은 문서가 직접 또는 고도의 명백성으로 보여줄 때만 채운다.
|
|
|
|
### 6.4 부담/임차권/가압류 관련 support
|
|
- 같은 목적물 또는 같은 자산 cluster에 직접 연결되는 문서에만 채운다.
|
|
- 임대차, 가압류, 담보권은 support role과 공제성 후보를 분리한다.
|
|
- 최종 공제 여부 결론은 쓰지 않는다. candidate만 허용한다.
|
|
|
|
### 6.5 `legal_meta_flags`
|
|
- 결론이 아니라 legal candidate flag만 저장한다.
|
|
- `restoration_mode_candidate`는 강한 후보가 있을 때만 채운다.
|
|
- `confidence_score`는 `"high"|"medium"|"low"|"unknown"` 중 하나를 사용한다.
|
|
|
|
---
|
|
|
|
## 7. evidence_actio_support.json 스키마(필드명/enum 엄수; 추가 필드 금지)
|
|
최종 파일은 배열(Array)이다.
|
|
|
|
```json
|
|
[
|
|
{
|
|
"evidence_index": "E-014",
|
|
"actio_pauliana_support": {
|
|
"support_role_tags": ["사해행위목적물"],
|
|
"fraudulent_act_date": "2016-01-31",
|
|
"property_value_at_close_of_arguments_support": {
|
|
"candidate_amount": "560000000원",
|
|
"candidate_date": "2024-03-01",
|
|
"basis_type": "현재시점대체",
|
|
"reason_text": "시가 후보 문서",
|
|
"confidence": "medium",
|
|
"proof_doc": "E-014"
|
|
},
|
|
"encumbrances_at_fraudulent_act": [
|
|
{
|
|
"kind": "근저당",
|
|
"holder": "근저당권자",
|
|
"rank": 1,
|
|
"registered_max_amount": "300000000원",
|
|
"actual_secured_debt_at_act": "250000000원",
|
|
"supported_date": "2016-01-31",
|
|
"deductible_in_value_compensation": true,
|
|
"deductibility_reason": "선순위담보 candidate",
|
|
"proof_doc": "E-014",
|
|
"proof_strength": "direct"
|
|
}
|
|
],
|
|
"encumbrances_at_close_of_arguments": [
|
|
{
|
|
"kind": "근저당",
|
|
"holder": "근저당권자",
|
|
"rank": 1,
|
|
"actual_outstanding_at_close": "0원",
|
|
"released_date": "2017-02-01",
|
|
"released_by_beneficiary": true,
|
|
"proof_doc": "E-014",
|
|
"proof_strength": "direct"
|
|
}
|
|
],
|
|
"lease_deposit_deductibility_support": {
|
|
"tenant_name": "임차인",
|
|
"lease_deposit_amount": "100000000원",
|
|
"has_possession": true,
|
|
"has_resident_registration": true,
|
|
"has_fixed_date": true,
|
|
"senior_security_exists": true,
|
|
"deductible_candidate": true,
|
|
"deductibility_reason": "대항력/확정일자 candidate",
|
|
"proof_doc": "E-014",
|
|
"proof_strength": "indirect"
|
|
},
|
|
"non_deductible_attachment_claims": [
|
|
{
|
|
"holder": "가압류권자",
|
|
"kind": "가압류",
|
|
"claim_amount": "50000000원",
|
|
"attachment_non_deductible_flag": true,
|
|
"reason": "가압류채권 비공제 candidate",
|
|
"proof_doc": "E-014",
|
|
"proof_strength": "direct"
|
|
}
|
|
],
|
|
"beneficiary_gain_support": {
|
|
"beneficiary_name": "수익자",
|
|
"nominal_transfer_value": "400000000원",
|
|
"beneficiary_preexisting_claim_amount": "100000000원",
|
|
"assumed_debt_amount": "50000000원",
|
|
"released_encumbrance_amount": "250000000원",
|
|
"beneficiary_gain_estimate_candidate": "실질 취득이익 후보",
|
|
"estimation_basis": "매매가액/인수채무/부담 해소 단서",
|
|
"proof_doc": "E-014",
|
|
"confidence": "medium"
|
|
},
|
|
"plaintiff_claim_snapshots": [
|
|
{
|
|
"plaintiff_name": "원고",
|
|
"claim_type": "guarantee",
|
|
"principal_existing_at_fraudulent_act": "200000000원",
|
|
"secured_portion_at_fraudulent_act": "0원",
|
|
"unsecured_portion_at_fraudulent_act": "200000000원",
|
|
"contractual_interest_rate": "연 5%",
|
|
"default_interest_rate": "연 12%",
|
|
"interest_start_date": "2015-01-01",
|
|
"amount_as_of_close_of_arguments": "240000000원",
|
|
"proof_status": "direct",
|
|
"proof_doc": "E-014"
|
|
}
|
|
],
|
|
"legal_meta_flags": {
|
|
"is_actio_pauliana_relevant_candidate": true,
|
|
"restoration_mode_candidate": "가액배상",
|
|
"is_value_compensation_exception_triggered_candidate": true,
|
|
"lease_deposit_deductible_candidate": true,
|
|
"attachment_claim_deductible_candidate": false,
|
|
"remaining_joint_collateral_value_estimate_candidate": "잔여 공동담보가치 후보",
|
|
"beneficiary_gain_estimate_candidate": "수익자 이익 후보",
|
|
"confidence_score": "medium"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
```
|
|
|
|
추가 규칙:
|
|
- 최종 배열이 비어 있을 수 있다. 이 경우 `[]`를 저장한다.
|
|
- 레코드에는 `evidence_index`와 `actio_pauliana_support` 외 다른 최상위 키를 넣지 않는다.
|
|
- base catalog 필드(`title`, `doc_type`, `key_*`, `source_pointer`, base `legal_calculation_object`)를 반복 저장하지 않는다.
|
|
- pruning 이후 `actio_pauliana_support`가 비면 해당 문서는 출력하지 않는다.
|
|
|
|
---
|
|
|
|
## 8. 최종 저장 및 검증(write-verify)
|
|
1. `evidence_indexed.json`의 순서를 기준으로 각 문서를 검토한다.
|
|
2. `actio_case_signals.json`과 `BO.json`을 기준으로 relevant scope를 먼저 정한다.
|
|
3. scope 안의 문서에 대해서만 문서-직접형 sparse support를 추출한다.
|
|
4. `write_file(overwrite=true)`로 `evidence_actio_support.json` 파일을 저장한다.
|
|
5. 즉시 `list_docs`로 파일 존재를 검증한다. 누락 시 재시도 1회.
|
|
6. `evidence_actio_support.json`은 절대 재읽지 않는다.
|
|
7. 검증 완료 후 즉시 종료하고 `"사해행위취소 support 인덱싱 완료"` 출력한다.
|
|
|
|
- task_name: Task_D1
|
|
llm_provider: google
|
|
llm_model: gemini-3.1-flash-lite-preview
|
|
llm_reasoning: medium
|
|
cache_control:
|
|
mode: auto
|
|
ttl: 10m
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `BO.json`, `evidence_indexed.json`만 확인하고, `read_docs` 사용해서 `BO.json`, `evidence_indexed.json`만 읽기
|
|
[ ] 2) `write_file` 사용해서 `Fact_Ledger_base.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `Fact_Ledger_base.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 4) `"Fact Ledger base 생성 완료"` 출력하고 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 실행 절대 금지.
|
|
|
|
## 0. 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
당신은 `stage1_사건개요파악` 단계의 `Task_D1`를 수행한다.
|
|
이 단계에서 `BO.json`과 `evidence_indexed.json`을 읽고, 각 BO에 대응하는 base fact ledger 항목 1개를 생성하여 `Fact_Ledger_base.json`을 만든다.
|
|
|
|
이 작업의 목적은 다음 4가지를 동시에 달성하는 것이다.
|
|
|
|
1. `1 BO = 1 Fact` 원칙으로 사건행위 단위 사실원장을 생성한다.
|
|
2. `evidence_indexed.json`에 이미 구조화된 base `legal_calculation_object`만 linked evidence 기준으로 최소 병합한다.
|
|
3. 후속 단계가 가볍게 조인할 수 있도록 `actio_pauliana_support`는 완전히 배제한 base ledger만 만든다.
|
|
4. `BO.json`의 각 `Evidence[]`가 `evidence_indexed.json` authority와 정합적인지 검증하여, stale evidence index나 title drift가 있는 경우 오염된 사실원장 생성을 차단한다.
|
|
|
|
이 작업은 `BO.json`과 `evidence_indexed.json`만 사용한다.
|
|
다른 파일을 읽거나 참조하지 않는다.
|
|
|
|
---
|
|
|
|
## 1. Preflight
|
|
- `list_docs` 수행: `BO.json`, `evidence_indexed.json`
|
|
- `read_docs` 수행: `BO.json`, `evidence_indexed.json`
|
|
|
|
---
|
|
|
|
## 2. 입력 계약(Input Contract)
|
|
### 2.1 `BO.json`
|
|
`BO.json`은 배열이다. 각 원소는 아래 구조를 가진다.
|
|
|
|
```ts
|
|
{
|
|
id: string; // 예: "bh1"
|
|
Performer: string | null;
|
|
PerformerType: string | null;
|
|
Action: string | null;
|
|
ActionType: string | null; // 예: "법률행위(legal acts)"
|
|
Subject: string | null;
|
|
Reason: string | null;
|
|
PriorAct: string | null;
|
|
BehaviorTime: string | null; // 가능하면 YYYY-MM-DD
|
|
TimeText: string | null;
|
|
TimePrecision: string | null;
|
|
StatementType: string | null;
|
|
Perspective: string | null;
|
|
EvidenceTitles: string[];
|
|
Evidence: Array<{
|
|
source_title: string | null;
|
|
evidence_index: string | null; // 예: "E-011"
|
|
relevant_content: string | null;
|
|
time_match: string | null;
|
|
party_match: string | null;
|
|
content_relevance: "직접"|"간접"|"불명"|"반대"|string|null;
|
|
authentication_status: string | null;
|
|
corroboration: string | null;
|
|
}>;
|
|
Legal_Keywords: string[];
|
|
JuristicAct: {
|
|
label: string | null;
|
|
gubun_multi: string[] | null;
|
|
basis_note: string | null;
|
|
needs_review: boolean | null;
|
|
} | null;
|
|
Object?: string | null;
|
|
Method?: string | null;
|
|
Location?: string | null;
|
|
Outcome?: string | null;
|
|
}
|
|
```
|
|
|
|
### 2.2 `evidence_indexed.json`
|
|
`evidence_indexed.json`은 배열이다. 각 원소는 아래 구조를 가진다.
|
|
|
|
```ts
|
|
{
|
|
evidence_index: string; // 예: "E-001"
|
|
title: string;
|
|
doc_type: "판결/결정"|"공문서"|"거래기록"|"통신기록"|"처분문서"|"기타";
|
|
key_facts: string[];
|
|
key_dates: string[];
|
|
key_amounts: string[];
|
|
key_parties: string[];
|
|
source_pointer: {
|
|
source: string;
|
|
ordinal: number;
|
|
};
|
|
legal_calculation_object?: {
|
|
asset_id: string | null;
|
|
property_label_for_schedule: string | null;
|
|
transaction_type: "매매"|"증여"|"대물변제"|null;
|
|
transaction_date: string | null;
|
|
registration_date: string | null;
|
|
registry_office: string | null;
|
|
registry_receipt_no: string | null;
|
|
registry_recorded_transfer_date: string | null;
|
|
market_value_at_act: string | null;
|
|
market_value_at_close: string | null;
|
|
sale_price: string | null;
|
|
consideration_breakdown: string[];
|
|
|
|
claim_id: string | null;
|
|
claim_label_for_schedule: string | null;
|
|
claim_event_type: "대여"|"연대보증"|"신용보증"|"보증채무"|"대위변제"|"구상권발생"|"변제"|"배당"|"채권양도"|"채무인수"|"상계"|"면제"|"경개"|"담보제공"|null;
|
|
claim_nature_tags: Array<"상사채권"|"민사채권"|"특정물채권"|"종류채권"|"금전채권"|"이자채권"|"선택채권"|"법정채권"|"불완전채권">;
|
|
claim_creditor: string | null;
|
|
claim_debtor: string | null;
|
|
claim_guarantor: string | null;
|
|
claim_security_provider: string | null;
|
|
claim_arising_date: string | null;
|
|
claim_maturity_date: string | null;
|
|
claim_default_or_acceleration_date: string | null;
|
|
claim_performance_date: string | null;
|
|
claim_instrument_date: string | null;
|
|
claim_instrument_identifier: string | null;
|
|
claim_instrument_issuer: string | null;
|
|
claim_principal_amount_at_act: string | null;
|
|
claim_total_amount_at_act: string | null;
|
|
claim_outstanding_amount_at_close: string | null;
|
|
claim_actual_performance_amount: string | null;
|
|
claim_guarantee_limit_amount: string | null;
|
|
claim_secured_cap_amount: string | null;
|
|
claim_interest_rate: string | null;
|
|
claim_default_rate: string | null;
|
|
claim_component_breakdown: string[];
|
|
claim_status_tags: Array<"발생"|"만기도래"|"기한의이익상실"|"연체"|"대위변제완료"|"구상권발생"|"일부회수"|"잔존"|"소멸"|"불명">;
|
|
};
|
|
}
|
|
```
|
|
|
|
주의:
|
|
- 입력 evidence 문서에 `actio_pauliana_support`가 있더라도 이 작업에서는 완전히 무시한다.
|
|
- 이 작업에서 생성하는 출력에는 `actio_pauliana_support`를 절대 포함하지 않는다.
|
|
|
|
---
|
|
|
|
## 3. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) `1 BO = 1 Fact`를 엄수한다.
|
|
3) `BO.json` 배열 순서를 최종 출력 순서로 유지한다.
|
|
4) `BO.Evidence[].evidence_index`는 반드시 `evidence_indexed.json`에서 매칭되어야 한다. 매칭 실패는 스킵할 수 있으나, 같은 Evidence item에서 `source_title`과 catalog `title`이 normalization 후에도 불일치하면 입력 오염으로 보고 즉시 중단한다.
|
|
5) `legal_calculation_object`는 linked evidence의 `legal_calculation_object` 내부 값에서만 병합한다.
|
|
6) `key_facts`, `key_dates`, `key_amounts`, `key_parties`만을 근거로 계산필드를 새로 만들지 않는다.
|
|
7) BO 본문만으로 `legal_calculation_object`를 새로 창작하지 않는다.
|
|
8) linked evidence가 없는 BO에는 `legal_calculation_object`를 생성하지 않는다.
|
|
9) linked evidence 밖의 다른 증거를 끌어와 병합하지 않는다.
|
|
10) 스칼라 충돌 시 우선순위가 높은 값 1개만 채택한다.
|
|
11) 배열은 exact-match 기준으로 중복 제거한다.
|
|
12) 불명확하면 `null`, `[]`, `["증거공백"]`으로 처리한다.
|
|
13) 금액 합산, 차감, 재계산 금지.
|
|
14) `Fact_Ledger_base.json`에는 아래 정의된 필드만 허용한다.
|
|
|
|
---
|
|
|
|
## 4. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
|
|
## 5. 규율
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 -> (별칭/대체 도구명으로) 1회만 재시도 -> 재시도 실패면 해당 체크리스트 항목을 `FAILED`로 보고하고 종료한다.
|
|
|
|
---
|
|
|
|
## 6. 필수 IO
|
|
### IN
|
|
- `BO.json`
|
|
- `evidence_indexed.json`
|
|
|
|
### OUT
|
|
- `Fact_Ledger_base.json`
|
|
|
|
---
|
|
|
|
## 7. 토큰/속도 상한(하드 리밋)
|
|
- `parties` <=5
|
|
- `evidence_refs` <=6
|
|
- `object_spec`는 가능한 경우 40자 내외의 짧은 명사구
|
|
- `action`은 1문장
|
|
- `legal_calculation_object.consideration_breakdown` <=4 (각 <=40자)
|
|
- `legal_calculation_object.claim_component_breakdown` <=5 (각 <=40자)
|
|
- `legal_calculation_object.claim_nature_tags` <=4
|
|
- `legal_calculation_object.claim_status_tags` <=4
|
|
- 중간 산출물 파일 금지(최종 파일만 `write_file`)
|
|
- 출력에 문서 원문 장문 재인용 금지
|
|
|
|
---
|
|
|
|
## 8. 소스 우선순위
|
|
### 8.1 top-level Fact 필드
|
|
- `BO.json`이 1차 소스다.
|
|
- linked evidence는 date, amount, parties 보조와 base `legal_calculation_object` 병합에만 사용한다.
|
|
|
|
### 8.2 충돌 해결
|
|
- BO의 명시 내용과 linked evidence가 충돌하면, top-level Fact 필드는 BO를 우선한다.
|
|
- `legal_calculation_object` 내부 필드는 linked evidence의 계산객체를 우선한다.
|
|
- linked evidence끼리 충돌하면 아래 정의한 필드별 우선순위를 따른다.
|
|
|
|
---
|
|
|
|
## 9. Fact 생성 규칙
|
|
### 9.1 `1 BO = 1 Fact`
|
|
- `BO.json`의 각 원소마다 `Fact_Ledger_base.json`의 원소 1개를 생성한다.
|
|
- `fact_id`는 `"F-001"`, `"F-002"` 식의 3자리 0패딩을 사용한다.
|
|
|
|
### 9.2 linked evidence lookup
|
|
- `evidence_indexed.json`을 `evidence_index` 기준 해시맵으로 만든다.
|
|
- 각 BO의 `Evidence[]`를 순회하면서 `evidence_index`가 일치하는 evidence만 linked evidence로 채택한다.
|
|
- `evidence_index`가 `null`이거나 매칭 실패면 그 항목은 스킵한다.
|
|
- 단, `BO.Evidence[]`의 어떤 항목에서 `source_title`이 존재하고 매칭된 catalog `title`도 존재할 때,
|
|
whitespace-normalization, 괄호/전각공백 정규화, 연속공백 축약을 적용한 뒤에도 title이 불일치하면
|
|
이는 evidence authority drift로 간주한다.
|
|
- evidence authority drift가 1건이라도 발견되면 `Fact_Ledger_base.json`을 쓰지 말고 즉시 중단한다.
|
|
|
|
### 9.3 linked evidence 정렬 우선순위
|
|
같은 BO의 linked evidence들을 아래 기준으로 정렬한다.
|
|
|
|
1. `BO.Evidence[].content_relevance`
|
|
- `"직접"` > `"간접"` > `"불명"` > `"반대"`
|
|
2. 대응 evidence의 `doc_type`
|
|
- `"처분문서"` > `"공문서"` > `"거래기록"` > `"판결/결정"` > `"통신기록"` > `"기타"`
|
|
3. `evidence_index` 오름차순
|
|
|
|
이 정렬순서를 전체 병합의 기본 우선순위로 사용한다.
|
|
|
|
### 9.4 top-level 필드 매핑
|
|
#### 9.4.1 `source_bo_id`
|
|
- `BO.id`
|
|
|
|
#### 9.4.2 `type`
|
|
- `BO.ActionType`
|
|
|
|
#### 9.4.3 `date`
|
|
- 1순위: `BO.BehaviorTime`
|
|
- 2순위: linked evidence의 base `legal_calculation_object`에서 아래 우선순위
|
|
1. 부동산 처분, 증여, 대물변제, 소유권이전 관련 BO -> `transaction_date`
|
|
2. 등기, 공시, 말소 관련 BO -> `registration_date`
|
|
3. 대여, 보증, 담보제공, 구상권발생 관련 BO -> `claim_arising_date`
|
|
4. 변제, 대위변제, 배당 관련 BO -> `claim_performance_date`
|
|
5. 만기, 연체, 기한의이익상실 관련 BO -> `claim_default_or_acceleration_date`
|
|
6. 그 외 -> `claim_instrument_date`
|
|
- 그래도 없으면 `null`
|
|
|
|
#### 9.4.4 `parties`
|
|
아래 순서로 수집하고 중복 제거한다.
|
|
|
|
1. `BO.Performer`
|
|
2. `BO.Subject`가 사람 또는 법인 이름 그 자체이거나, `"...의 ... 채무"`처럼 특정 채권관계의 당사자를 식별하게 해 주는 표현일 때 그 직접 당사자
|
|
3. `BO.Action`에 명시된 직접 상대방 이름
|
|
4. linked evidence의 base `legal_calculation_object`에서 현재 BO와 직접 관련된 당사자
|
|
- `claim_creditor`
|
|
- `claim_debtor`
|
|
- `claim_guarantor`
|
|
- `claim_security_provider`
|
|
|
|
제거 규칙:
|
|
- 주소, 부동산 표기, 금액 문자열, 순수 채무명칭은 `parties`에 넣지 않는다.
|
|
- 동일인/동일법인이 명백하면 1개만 남긴다.
|
|
- 최종 배열은 최대 5개다.
|
|
|
|
#### 9.4.5 `object_spec`
|
|
아래 우선순위로 짧은 명사구 1개를 만든다.
|
|
|
|
1. `BO.Subject`가 목적물, 채권, 담보, 배당금, 대출, 보증, 부동산, 근저당 피담보채무 등 객체를 직접 가리키면 `BO.Subject`를 축약 사용
|
|
2. `BO.Subject`가 당사자명 위주라 객체성이 부족하면 `BO.Action`에서 객체 부분만 짧게 추출
|
|
3. linked evidence의 base `legal_calculation_object`가 존재하고, 그 객체가 더 직접적이면 아래 값 중 하나를 사용 가능
|
|
- 부동산형: 부동산 표기
|
|
- 채권형: 채권명, 담보채무명, 배당금, 구상채권 등
|
|
- 불명확하면 `null`
|
|
|
|
#### 9.4.6 `amount`
|
|
`amount`는 해당 Fact의 대표 금액이다.
|
|
|
|
우선순위:
|
|
1. `BO.Action` 또는 `BO.Subject`에 현재 행위와 직접 연결된 금액이 명시되어 있으면 그 값
|
|
2. 위 금액이 없을 때만 linked evidence의 base `legal_calculation_object`에서 아래 우선순위
|
|
1. 부동산 처분행위 -> `sale_price`
|
|
2. 대여, 대출원금 형성 -> `claim_principal_amount_at_act`
|
|
3. 보증한도 설정 -> `claim_guarantee_limit_amount`
|
|
4. 담보최고액 설정 -> `claim_secured_cap_amount`
|
|
5. 변제, 대위변제, 배당 -> `claim_actual_performance_amount`
|
|
6. 잔존채권 또는 구상채권 파악 -> `claim_outstanding_amount_at_close`
|
|
7. 행위시점 총채권액이 직접 쟁점일 때만 -> `claim_total_amount_at_act`
|
|
- 여러 금액이 경쟁하면 행위와 가장 직접 대응하는 1개만 쓴다.
|
|
- 불명확하면 `null`
|
|
- 금지:
|
|
- 여러 금액을 합산, 차감해 새 금액 만들기
|
|
- `sale_price` 또는 `claim_total_amount_at_act`를 기계적으로 복사하기
|
|
|
|
#### 9.4.7 `action`
|
|
- `BO.Action`을 바탕으로 1문장으로 정리한다.
|
|
- 입력 표현을 유지하되 군더더기만 줄인다.
|
|
- 새 사실 추가 금지.
|
|
|
|
#### 9.4.8 `evidence_refs`
|
|
- `BO.Evidence[]`를 순서대로 보면서 매칭된 evidence에 대해
|
|
- ``evidence_index + " (" + evidence.title + ")"`` 형식으로 기록한다.
|
|
- 매칭된 evidence가 없으면 `["증거공백"]`
|
|
- exact-match 중복 제거
|
|
|
|
#### 9.4.9 `credibility`
|
|
아래 규칙으로 하나만 선택한다.
|
|
|
|
- `high`
|
|
- linked evidence 중 `content_relevance=="직접"`가 1개 이상이고,
|
|
- 그 evidence의 `doc_type`이 `공문서`, `처분문서`, `거래기록` 중 하나이거나,
|
|
- BO에 연결된 복수 증거가 서로 보강한다.
|
|
|
|
- `medium`
|
|
- linked evidence는 있으나 직접성, 문서성, 보강 정도가 혼재한다.
|
|
|
|
- `low`
|
|
- linked evidence가 없거나,
|
|
- `간접`, `불명`, `반대` 위주이거나,
|
|
- `["증거공백"]` 상태다.
|
|
|
|
---
|
|
|
|
## 10. base `legal_calculation_object` 생성 규칙
|
|
### 10.1 생성 여부
|
|
아래를 모두 충족할 때만 생성한다.
|
|
|
|
1. 해당 BO의 linked evidence 중 적어도 1개가 non-empty base `legal_calculation_object`를 가진다.
|
|
2. 해당 BO가 아래 중 적어도 하나와 실질적 관련이 있다.
|
|
- 부동산 처분, 이전, 증여, 대물변제, 등기, 말소, 시가, 대가 구성
|
|
- 채권의 발생, 대여, 보증, 담보제공, 구상권발생, 변제, 대위변제, 배당, 채권양도, 채무인수, 상계, 면제, 경개
|
|
3. 병합 결과가 빈 객체가 아니다.
|
|
|
|
그 외에는 `legal_calculation_object`를 생성하지 않는다.
|
|
|
|
### 10.2 사용 가능한 데이터 원천
|
|
- base `legal_calculation_object`의 각 필드는 linked evidence의 `legal_calculation_object` 내부 값에서만 가져온다.
|
|
- linked evidence 밖의 다른 증거를 섞지 않는다.
|
|
- `key_facts`, `key_dates`, `key_amounts`, `key_parties`만으로 새 계산값을 만들지 않는다.
|
|
- BO의 `Action`, `Subject`만으로 새 계산필드를 만들지 않는다.
|
|
|
|
### 10.3 빈 객체 방지
|
|
병합 후 아래가 모두 비어 있으면 `legal_calculation_object`를 생성하지 않는다.
|
|
|
|
- 스칼라 필드가 모두 `null`
|
|
- `consideration_breakdown`가 빈 배열
|
|
- `claim_nature_tags`가 빈 배열
|
|
- `claim_component_breakdown`가 빈 배열
|
|
- `claim_status_tags`가 빈 배열
|
|
|
|
---
|
|
|
|
## 11. base `legal_calculation_object` 병합 규칙
|
|
### 11.1 A. 일반 부동산 거래 필드
|
|
아래 필드는 기본 우선순위가 가장 높은 linked evidence부터 보아 `null`이 아닌 첫 값을 채택한다.
|
|
|
|
- `asset_id`
|
|
- `property_label_for_schedule`
|
|
- `transaction_type`
|
|
- `transaction_date`
|
|
|
|
### 11.2 B. 등기 전용 필드
|
|
아래 필드는 등기문서 성격이 가장 강한 linked evidence를 우선 사용한다.
|
|
|
|
- `registration_date`
|
|
- `registry_office`
|
|
- `registry_receipt_no`
|
|
- `registry_recorded_transfer_date`
|
|
|
|
등기문서 우선순위:
|
|
1. `title`에 `등기사항전부증명서`가 포함된 문서
|
|
2. 그 외 `doc_type=="공문서"`이면서 해당 필드가 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.3 C. 시가, 가액 필드
|
|
아래 필드는 가격평가 성격이 가장 직접적인 linked evidence를 우선 사용한다.
|
|
|
|
- `market_value_at_act`
|
|
- `market_value_at_close`
|
|
|
|
가격평가 문서 우선순위:
|
|
1. `title`에 `감정평가`, `감정서`, `평가서`가 포함된 문서
|
|
2. 그 외 해당 필드가 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.4 D. 처분대가 필드
|
|
`sale_price`는 아래 우선순위로 1개만 채택한다.
|
|
|
|
1. `transaction_type`가 존재하고 `sale_price`가 non-null인 문서
|
|
2. `title`에 `계약서`, `약정서`, `등기사항전부증명서`, `영수증`, `확인서`가 포함되고 `sale_price`가 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.5 E. 부동산 대가 구성 배열
|
|
- `consideration_breakdown`는 기본 우선순위 순서대로 배열을 순차 추가한다.
|
|
- exact-match 중복 제거
|
|
- 최대 4개까지만 유지
|
|
- 장문 병합 금지
|
|
- 추론으로 새 항목 생성 금지
|
|
|
|
### 11.6 F. 채권 관계 스칼라 필드
|
|
아래 필드는 기본 우선순위가 가장 높은 linked evidence부터 보아 `null`이 아닌 첫 값을 채택한다.
|
|
|
|
- `claim_id`
|
|
- `claim_label_for_schedule`
|
|
- `claim_event_type`
|
|
- `claim_creditor`
|
|
- `claim_debtor`
|
|
- `claim_guarantor`
|
|
- `claim_security_provider`
|
|
|
|
### 11.7 G. 채권 성질 태그
|
|
- `claim_nature_tags`는 기본 우선순위 순서대로 배열을 합친다.
|
|
- exact-match 중복 제거
|
|
- 최대 4개까지만 유지
|
|
- 새 태그 추론 금지
|
|
|
|
### 11.8 H. 채권 날짜 필드
|
|
#### 11.8.1 `claim_arising_date`
|
|
우선순위:
|
|
1. `title`에 `약정서`, `계약서`, `보증서`, `대출`, `확인서`가 포함되고 값이 non-null인 문서
|
|
2. 그 외 `doc_type=="처분문서"` 또는 `doc_type=="거래기록"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.8.2 `claim_maturity_date`
|
|
우선순위:
|
|
1. `title`에 `약정서`, `계약서`, `대출`, `보증서`가 포함되고 값이 non-null인 문서
|
|
2. 그 외 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.8.3 `claim_default_or_acceleration_date`
|
|
우선순위:
|
|
1. `title`에 `최고`, `기한의이익`, `연체`, `부도`, `내용증명`, `확인서`가 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="거래기록"` 또는 `doc_type=="처분문서"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.8.4 `claim_performance_date`
|
|
우선순위:
|
|
1. `title`에 `영수증`, `배당표`, `대위변제`, `상환`, `거래내역`, `입금`, `출금`이 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="거래기록"` 또는 `doc_type=="판결/결정"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.8.5 `claim_instrument_date`
|
|
우선순위:
|
|
1. `claim_instrument_identifier`가 함께 존재하는 문서
|
|
2. `claim_instrument_issuer`가 함께 존재하는 문서
|
|
3. 그 외 값이 non-null인 문서
|
|
4. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.9 I. 채권 문서 식별 필드
|
|
아래 필드는 문서 식별성이 강한 evidence를 우선한다.
|
|
|
|
- `claim_instrument_identifier`
|
|
- `claim_instrument_issuer`
|
|
|
|
우선순위:
|
|
1. `title`에 `약정서`, `계약서`, `보증서`, `배당표`, `판결`, `결정`, `확인서`, `증서`가 포함된 문서
|
|
2. 그 외 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.10 J. 채권 금액 필드
|
|
#### 11.10.1 `claim_principal_amount_at_act`
|
|
우선순위:
|
|
1. `title`에 `약정서`, `계약서`, `대출`, `차용`, `보증서`가 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="처분문서"` 또는 `doc_type=="거래기록"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.10.2 `claim_total_amount_at_act`
|
|
우선순위:
|
|
1. `title`에 `잔액`, `명세`, `확인서`, `대위변제`, `배당표`가 포함되고 값이 non-null인 문서
|
|
2. 그 외 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.10.3 `claim_outstanding_amount_at_close`
|
|
우선순위:
|
|
1. `title`에 `잔액`, `채무잔액`, `미회수`, `구상금`, `확인서`, `배당표`가 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="거래기록"` 또는 `doc_type=="처분문서"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.10.4 `claim_actual_performance_amount`
|
|
우선순위:
|
|
1. `title`에 `영수증`, `배당표`, `대위변제`, `상환`, `거래내역`, `입금`, `출금`이 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="거래기록"` 또는 `doc_type=="판결/결정"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.10.5 `claim_guarantee_limit_amount`
|
|
우선순위:
|
|
1. `title`에 `보증`, `보증서`, `약정서`, `계약서`가 포함되고 값이 non-null인 문서
|
|
2. 그 외 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
#### 11.10.6 `claim_secured_cap_amount`
|
|
우선순위:
|
|
1. `title`에 `등기사항전부증명서`, `근저당`, `담보`, `설정계약`, `배당표`가 포함되고 값이 non-null인 문서
|
|
2. `doc_type=="공문서"`이면서 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.11 K. 금리 필드
|
|
- `claim_interest_rate`
|
|
- `claim_default_rate`
|
|
|
|
우선순위:
|
|
1. `title`에 `약정서`, `계약서`, `보증서`, `대출`이 포함되고 값이 non-null인 문서
|
|
2. 그 외 값이 non-null인 문서
|
|
3. 그래도 없으면 기본 우선순위 fallback
|
|
|
|
### 11.12 L. 채권 구성요소 배열
|
|
- `claim_component_breakdown`는 기본 우선순위 순서대로 배열을 합친다.
|
|
- exact-match 중복 제거
|
|
- 최대 5개까지만 유지
|
|
- 장문 병합 금지
|
|
- 추론으로 새 요소 생성 금지
|
|
|
|
### 11.13 M. 채권 상태 태그
|
|
- `claim_status_tags`는 기본 우선순위 순서대로 배열을 합친다.
|
|
- exact-match 중복 제거
|
|
- 최대 4개까지만 유지
|
|
- 새 상태 추론 금지
|
|
|
|
---
|
|
|
|
## 12. 충돌 처리
|
|
### 12.1 scalar field
|
|
- 서로 다른 linked evidence가 같은 scalar field에 서로 다른 값을 제시하면, 해당 필드 우선순위에서 앞선 값 1개만 채택한다.
|
|
- 판단 불가하면 `null`.
|
|
|
|
### 12.2 array field
|
|
- 배열은 exact-match 중복 제거 후 앞선 값부터 유지한다.
|
|
- 상한을 넘으면 앞에서부터 자른다.
|
|
|
|
---
|
|
|
|
## 13. 값 형식
|
|
- 날짜는 가능한 경우 `"YYYY-MM-DD"`
|
|
- 금액은 가능한 경우 `"300,000,000원"` 같은 문자열
|
|
- 비율은 예: `"월 1%"`, `"연 12%"`
|
|
- 불명값은 `null`
|
|
- 불명 배열은 `[]`
|
|
|
|
---
|
|
|
|
## 14. 최종 Schema(필드명/enum 엄수; 추가 필드 금지)
|
|
### Fact_Ledger_base.json (Array)
|
|
```ts
|
|
{
|
|
fact_id: string; // "F-001"
|
|
source_bo_id: string; // "bh#"
|
|
type: string | null;
|
|
date: string | null;
|
|
parties: string[];
|
|
object_spec: string | null;
|
|
amount: string | null;
|
|
action: string | null;
|
|
evidence_refs: string[]; // ["E-001 (title)"] 또는 ["증거공백"]
|
|
credibility: "high"|"medium"|"low";
|
|
|
|
legal_calculation_object?: {
|
|
asset_id: string | null;
|
|
property_label_for_schedule: string | null;
|
|
transaction_type: "매매"|"증여"|"대물변제"|null;
|
|
transaction_date: string | null;
|
|
registration_date: string | null;
|
|
registry_office: string | null;
|
|
registry_receipt_no: string | null;
|
|
registry_recorded_transfer_date: string | null;
|
|
market_value_at_act: string | null;
|
|
market_value_at_close: string | null;
|
|
sale_price: string | null;
|
|
consideration_breakdown: string[];
|
|
|
|
claim_id: string | null;
|
|
claim_label_for_schedule: string | null;
|
|
claim_event_type: "대여"|"연대보증"|"신용보증"|"보증채무"|"대위변제"|"구상권발생"|"변제"|"배당"|"채권양도"|"채무인수"|"상계"|"면제"|"경개"|"담보제공"|null;
|
|
claim_nature_tags: Array<"상사채권"|"민사채권"|"특정물채권"|"종류채권"|"금전채권"|"이자채권"|"선택채권"|"법정채권"|"불완전채권">;
|
|
claim_creditor: string | null;
|
|
claim_debtor: string | null;
|
|
claim_guarantor: string | null;
|
|
claim_security_provider: string | null;
|
|
claim_arising_date: string | null;
|
|
claim_maturity_date: string | null;
|
|
claim_default_or_acceleration_date: string | null;
|
|
claim_performance_date: string | null;
|
|
claim_instrument_date: string | null;
|
|
claim_instrument_identifier: string | null;
|
|
claim_instrument_issuer: string | null;
|
|
claim_principal_amount_at_act: string | null;
|
|
claim_total_amount_at_act: string | null;
|
|
claim_outstanding_amount_at_close: string | null;
|
|
claim_actual_performance_amount: string | null;
|
|
claim_guarantee_limit_amount: string | null;
|
|
claim_secured_cap_amount: string | null;
|
|
claim_interest_rate: string | null;
|
|
claim_default_rate: string | null;
|
|
claim_component_breakdown: string[];
|
|
claim_status_tags: Array<"발생"|"만기도래"|"기한의이익상실"|"연체"|"대위변제완료"|"구상권발생"|"일부회수"|"잔존"|"소멸"|"불명">;
|
|
};
|
|
}
|
|
```
|
|
|
|
추가 규칙:
|
|
- `legal_calculation_object`는 값이 있을 때만 포함한다.
|
|
- `actio_pauliana_support`는 절대 포함하지 않는다.
|
|
- 정의되지 않은 추가 필드 금지.
|
|
|
|
---
|
|
|
|
## 15. 최종 실행 지시
|
|
1. `BO.json`과 `evidence_indexed.json`을 읽는다.
|
|
2. `BO.json` 배열 순서대로 `1 BO = 1 Fact` 원칙에 따라 `Fact_Ledger_base.json` 배열을 만든다.
|
|
3. 각 BO의 linked evidence만 사용하여 base `legal_calculation_object`를 선택적으로 병합한다.
|
|
4. `write_file(overwrite=true)`로 `Fact_Ledger_base.json`을 저장한다.
|
|
5. 즉시 `list_docs`로 파일 존재를 검증한다. 누락 시 재시도 1회.
|
|
6. `Fact_Ledger_base.json`은 절대 재읽지 않는다.
|
|
|
|
- task_name: Task_D2
|
|
llm_provider: google
|
|
llm_model: gemini-3.1-flash-lite-preview
|
|
llm_reasoning: medium
|
|
cache_control:
|
|
mode: auto
|
|
ttl: 10m
|
|
use_tools: [localdocs]
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs` 사용해서 `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`만 확인하고, `read_docs` 사용해서 `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`만 읽기
|
|
[ ] 2) `write_file` 사용해서 `fact_actio_support.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `fact_actio_support.json` 파일만 존재 확인(절대 읽기 금지)
|
|
[ ] 4) `"BO별 actio support 정규화 완료"` 출력하고 작업을 끝낸다(terminate).
|
|
|
|
---
|
|
|
|
# CONSTRAINT (MUST FOLLOW)
|
|
아래 제시된 작업 지시사항만 수행하라. 그 외 다른 어떤 작업도 수행해서는 안 된다.
|
|
오로지 추론(inference)을 통해서만 아래 작업들을 수행한다. 코드 실행 절대 금지.
|
|
|
|
## 0. 역할/목적
|
|
You are an MCP-enabled LLM agent assisting plaintiff-side Korean civil/commercial litigation counsel.
|
|
|
|
당신은 `stage1_사건개요파악` 단계의 `Task_D2`를 수행한다.
|
|
이 단계에서 `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`을 입력으로 사용하여,
|
|
각 BO에 연결된 sparse support 중 사건 전체에서 사해행위취소와 실질적으로 관련된 support만
|
|
BO 단위 normalized support object로 병합한 `fact_actio_support.json`을 생성한다.
|
|
|
|
이 작업의 목적은 다음 6가지를 동시에 달성하는 것이다.
|
|
|
|
1. 각 BO의 `Evidence[].evidence_index`를 기준으로 연결된 support 문서를 식별한다.
|
|
2. `actio_case_signals.json`을 사건 전체의 scope gate로 사용하여, 사건과 무관한 support를 BO 수준에서 제거한다.
|
|
3. 문서별 sparse `actio_pauliana_support`를 BO 단위로 최소 병합하되, support field가 허용되는 BO 범위를 엄격히 제한한다.
|
|
4. `fraudulent_act_date` 같은 핵심 필드가 다른 자산·다른 사건군 support에서 오염되지 않도록 차단한다.
|
|
5. 후속 단계가 `source_bo_id` 기준으로 base fact ledger에 조인할 수 있는 경량 support delta를 생성한다.
|
|
6. 계산, 확정판단, 총액 산정 없이 오직 scope-aware normalization만 수행한다.
|
|
|
|
이 작업은 `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`만 사용한다.
|
|
다른 파일을 읽거나 참조하지 않는다.
|
|
|
|
---
|
|
|
|
## 1. Preflight
|
|
- `list_docs` 수행: `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`
|
|
- `read_docs` 수행: `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`
|
|
|
|
---
|
|
|
|
## 2. 입력 계약(Input Contract)
|
|
### 2.1 `BO.json`
|
|
`BO.json`은 배열이다. 각 원소는 아래 구조를 가진다.
|
|
|
|
```ts
|
|
{
|
|
id: string; // 예: "bh1"
|
|
Performer: string | null;
|
|
PerformerType: string | null;
|
|
Action: string | null;
|
|
ActionType: string | null;
|
|
Subject: string | null;
|
|
Reason: string | null;
|
|
PriorAct: string | null;
|
|
BehaviorTime: string | null;
|
|
TimeText: string | null;
|
|
TimePrecision: string | null;
|
|
StatementType: string | null;
|
|
Perspective: string | null;
|
|
EvidenceTitles: string[];
|
|
Evidence: Array<{
|
|
source_title: string | null;
|
|
evidence_index: string | null; // 예: "E-011"
|
|
relevant_content: string | null;
|
|
time_match: string | null;
|
|
party_match: string | null;
|
|
content_relevance: "직접"|"간접"|"불명"|"반대"|string|null;
|
|
authentication_status: string | null;
|
|
corroboration: string | null;
|
|
}>;
|
|
Legal_Keywords?: string[];
|
|
JuristicAct?: {
|
|
label: string | null;
|
|
gubun_multi: string[] | null;
|
|
basis_note: string | null;
|
|
needs_review: boolean | null;
|
|
} | null;
|
|
Object?: string | null;
|
|
Method?: string | null;
|
|
Location?: string | null;
|
|
Outcome?: string | null;
|
|
}
|
|
```
|
|
|
|
### 2.2 `evidence_actio_support.json`
|
|
`evidence_actio_support.json`은 배열이다. support가 있는 문서만 sparse하게 들어 있다.
|
|
|
|
```ts
|
|
{
|
|
evidence_index: string; // 예: "E-001"
|
|
actio_pauliana_support: {
|
|
support_role_tags?: Array<"사해행위목적물"|"선순위담보"|"존속담보"|"임차권"|"가압류"|"원고채권"|"수익자이익"|"법리메타">;
|
|
fraudulent_act_date?: string;
|
|
property_value_at_close_of_arguments_support?: {
|
|
candidate_amount?: string;
|
|
candidate_date?: string;
|
|
basis_type?: "사실심변론종결직접"|"현재시점대체"|"감정기준일"|"거래시점동일"|"불명";
|
|
reason_text?: string;
|
|
confidence?: "high"|"medium"|"low"|"unknown";
|
|
proof_doc?: string;
|
|
};
|
|
encumbrances_at_fraudulent_act?: Array<{
|
|
kind?: "근저당"|"저당"|"가압류"|"전세권"|"임차보증금반환채권";
|
|
holder?: string;
|
|
rank?: number;
|
|
registered_max_amount?: string;
|
|
actual_secured_debt_at_act?: string;
|
|
supported_date?: string;
|
|
deductible_in_value_compensation?: boolean;
|
|
deductibility_reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
encumbrances_at_close_of_arguments?: Array<{
|
|
kind?: "근저당"|"저당"|"가압류"|"전세권"|"임차보증금반환채권";
|
|
holder?: string;
|
|
rank?: number;
|
|
actual_outstanding_at_close?: string;
|
|
released_date?: string;
|
|
released_by_beneficiary?: boolean;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
lease_deposit_deductibility_support?: {
|
|
tenant_name?: string;
|
|
lease_deposit_amount?: string;
|
|
has_possession?: boolean;
|
|
has_resident_registration?: boolean;
|
|
has_fixed_date?: boolean;
|
|
senior_security_exists?: boolean;
|
|
deductible_candidate?: boolean;
|
|
deductibility_reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
};
|
|
non_deductible_attachment_claims?: Array<{
|
|
holder?: string;
|
|
kind?: "가압류"|"압류";
|
|
claim_amount?: string;
|
|
attachment_non_deductible_flag?: boolean;
|
|
reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
beneficiary_gain_support?: {
|
|
beneficiary_name?: string;
|
|
nominal_transfer_value?: string;
|
|
beneficiary_preexisting_claim_amount?: string;
|
|
assumed_debt_amount?: string;
|
|
released_encumbrance_amount?: string;
|
|
beneficiary_gain_estimate_candidate?: string;
|
|
estimation_basis?: string;
|
|
proof_doc?: string;
|
|
confidence?: "high"|"medium"|"low"|"unknown";
|
|
};
|
|
plaintiff_claim_snapshots?: Array<{
|
|
plaintiff_name?: string;
|
|
claim_type?: "loan"|"guarantee"|"reimbursement";
|
|
principal_existing_at_fraudulent_act?: string;
|
|
secured_portion_at_fraudulent_act?: string;
|
|
unsecured_portion_at_fraudulent_act?: string;
|
|
contractual_interest_rate?: string;
|
|
default_interest_rate?: string;
|
|
interest_start_date?: string;
|
|
amount_as_of_close_of_arguments?: string;
|
|
proof_status?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
proof_doc?: string;
|
|
}>;
|
|
legal_meta_flags?: {
|
|
is_actio_pauliana_relevant_candidate?: boolean;
|
|
restoration_mode_candidate?: "원물반환"|"말소등기"|"가액배상";
|
|
is_value_compensation_exception_triggered_candidate?: boolean;
|
|
lease_deposit_deductible_candidate?: boolean;
|
|
attachment_claim_deductible_candidate?: boolean;
|
|
remaining_joint_collateral_value_estimate_candidate?: string;
|
|
beneficiary_gain_estimate_candidate?: string;
|
|
confidence_score?: "high"|"medium"|"low"|"unknown";
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
### 2.3 `actio_case_signals.json`
|
|
`actio_case_signals.json`은 객체(Object)이며, 사건 전체 수준에서 사해행위취소 구조가 의심되는 범위를 지정하는 scope gate다.
|
|
|
|
```ts
|
|
{
|
|
is_actio_pauliana_suspected: boolean;
|
|
suspicion_level: "high"|"medium"|"low"|"none";
|
|
suspicion_reasons?: string[];
|
|
related_bo_ids?: string[];
|
|
related_evidence_indexes?: string[];
|
|
target_property_candidates?: string[];
|
|
fraudulent_act_date_candidates?: string[];
|
|
preserved_claim_candidates?: Array<{
|
|
bo_id?: string;
|
|
claim_type_candidate?: "loan"|"guarantee"|"reimbursement"|"unknown";
|
|
creditor_candidate?: string;
|
|
debtor_candidate?: string;
|
|
}>;
|
|
beneficiary_candidates?: string[];
|
|
encumbrance_related_evidence_indexes?: string[];
|
|
}
|
|
```
|
|
|
|
주의:
|
|
- 입력 파일은 sparse delta이므로 support가 없는 문서는 아예 존재하지 않을 수 있다.
|
|
- `proof_doc`는 입력 support record의 값을 유지해야 한다. `source_bo_id`로 바꾸지 않는다.
|
|
- `actio_case_signals.json`은 최종 판결문이 아니라 scope gate다. 이 파일에 없는 필드를 상상해서 추가하지 않는다.
|
|
|
|
---
|
|
|
|
## 3. 불가침 원칙 (Non-Negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) `1 BO = 0 또는 1 support record`를 엄수한다.
|
|
3) `BO.json` 배열 순서를 최종 출력 기준 순서로 사용한다. 다만 support가 남지 않는 BO는 출력하지 않는다.
|
|
4) linked evidence 밖의 다른 support 문서를 끌어오지 않는다.
|
|
5) `actio_case_signals.json`은 case-level scope gate다. 이 gate를 통과하지 못한 support field는 모두 제거한다.
|
|
6) `BO.Action`, `BO.Subject`, `Legal_Keywords`만으로 새로운 support field를 창작하지 않는다.
|
|
7) 입력 support를 기반으로 병합만 수행하며 계산, 합산, 차감, 확정판단은 하지 않는다.
|
|
8) `common_collateral_value`, 최종 `beneficiary_gain`, 최종 `preserved_claim_total`, 최종 `recovery_cap` 같은 결론값 생성 금지.
|
|
9) 스칼라 충돌 시 우선순위가 높은 값 1개만 채택한다.
|
|
10) 배열은 identity key 기준 최소 병합 또는 exact-match 중복 제거만 허용한다.
|
|
11) 불명확한 값은 내부 판단상 `null` 취급하되, 최종 출력에서는 `null`, `[]`, `{}`를 제거한다.
|
|
12) `proof_doc`는 입력 support record의 값만 유지한다. 다른 값으로 변경 금지.
|
|
13) `fraudulent_act_date`는 `사해행위목적물` 범주의 BO에만 허용한다. 원고채권/보증/대위변제 BO에는 절대 올리지 않는다.
|
|
14) `plaintiff_claim_snapshots`는 `원고채권` 범주의 BO에만 허용한다. 처분 BO나 담보 BO에 절대 올리지 않는다.
|
|
15) `encumbrances_*`, `lease_deposit_deductibility_support`, `non_deductible_attachment_claims`는 target property cluster와 직접 연결되는 BO에만 허용한다.
|
|
16) `beneficiary_gain_support`는 처분/수익자 관련 BO에만 허용한다.
|
|
17) `legal_meta_flags`는 같은 BO에서 하나 이상의 실질 support field가 살아남은 경우에만 보조적으로 유지할 수 있다. 메타 플래그만 단독으로 확장하지 않는다.
|
|
18) 최종 출력은 아래 정의한 필드만 허용한다.
|
|
|
|
---
|
|
|
|
## 4. 사용 도구(Localdocs MCP) 및 오류 규율
|
|
- 기본 도구명: `list_docs`, `list_folders`, `read_docs`, `write_file`, `create_folder`, `delete_file`
|
|
- Tool output만을 사실로 취급한다.
|
|
- Error 발생 시: 원인 분석 -> (별칭/대체 도구명으로) 1회만 재시도 -> 재시도 실패면 해당 체크리스트 항목을 `FAILED`로 보고하고 종료한다.
|
|
|
|
---
|
|
|
|
## 5. 필수 IO
|
|
### IN
|
|
- `BO.json`
|
|
- `evidence_actio_support.json`
|
|
- `actio_case_signals.json`
|
|
|
|
### OUT
|
|
- `fact_actio_support.json`
|
|
|
|
---
|
|
|
|
## 6. 토큰/속도 상한(하드 리밋)
|
|
- support가 남는 BO만 출력
|
|
- BO별 출력 레코드는 최대 1개
|
|
- `support_role_tags` <=8
|
|
- `encumbrances_at_fraudulent_act` <=4
|
|
- `encumbrances_at_close_of_arguments` <=4
|
|
- `non_deductible_attachment_claims` <=4
|
|
- `plaintiff_claim_snapshots` <=4
|
|
- `reason_text`, `deductibility_reason`, `reason`, `estimation_basis`는 각 <=50자
|
|
- 중간 산출물 파일 금지(최종 파일만 `write_file`)
|
|
- 최종 출력에서 `null`, `[]`, `{}` 제거
|
|
|
|
---
|
|
|
|
## 7. 사건 수준 scope gate
|
|
### 7.1 global hard gate
|
|
- `actio_case_signals.is_actio_pauliana_suspected == false` 이고 `suspicion_level == "none"`이면 원칙적으로 `[]`를 저장한다.
|
|
- 단, 입력 support가 존재하더라도 사건 수준 gate가 닫혀 있으면 확장하지 않는다.
|
|
|
|
### 7.2 case scope anchors
|
|
아래 값들은 BO relevance를 판단하는 앵커다.
|
|
- `related_bo_ids`
|
|
- `related_evidence_indexes`
|
|
- `target_property_candidates`
|
|
- `fraudulent_act_date_candidates`
|
|
- `preserved_claim_candidates`
|
|
- `beneficiary_candidates`
|
|
- `encumbrance_related_evidence_indexes`
|
|
|
|
`actio_case_signals.json`에 값이 있으면 그것을 우선한다.
|
|
값이 비어 있으면 linked support와 BO 의미를 보조적으로 사용하되, 항상 보수적으로 판단한다.
|
|
|
|
---
|
|
|
|
## 8. BO별 linked support 매핑
|
|
### 8.1 support lookup
|
|
- `evidence_actio_support.json`을 `evidence_index` 기준 해시맵으로 만든다.
|
|
|
|
### 8.2 BO별 linked support
|
|
- 각 BO의 `Evidence[]`를 순회한다.
|
|
- `Evidence[].evidence_index`와 일치하는 `evidence_actio_support.json` 원소만 해당 BO의 linked support로 채택한다.
|
|
- `evidence_index`가 `null`이거나 매칭 실패면 그 항목은 스킵한다.
|
|
- linked support가 0개면 그 BO는 출력하지 않는다.
|
|
|
|
### 8.3 linked support 정렬 우선순위
|
|
같은 BO에 연결된 linked support 레코드들을 아래 기준으로 정렬한다.
|
|
|
|
1. 해당 `evidence_index`가 `actio_case_signals.related_evidence_indexes`에 있으면 최우선
|
|
2. encumbrance/lease/attachment 관련 필드 병합 시, 해당 `evidence_index`가 `actio_case_signals.encumbrance_related_evidence_indexes`에 있으면 최우선
|
|
3. `BO.Evidence[].content_relevance`
|
|
- `"직접"` > `"간접"` > `"불명"` > `"반대"`
|
|
4. linked support 내부 원소의 `proof_strength` 또는 `proof_status`
|
|
- `"direct"` > `"indirect"` > `"meeting_only"` > `"unknown"`
|
|
5. `evidence_index` 오름차순
|
|
|
|
이 정렬순서를 전체 병합의 기본 우선순위로 사용한다.
|
|
|
|
---
|
|
|
|
## 9. BO scope bucket 판정 (actio_case_signals 우선)
|
|
각 BO는 아래 bucket 중 0개 이상에 속할 수 있다.
|
|
|
|
### 9.1 `property_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- `BO.id`가 `related_bo_ids`에 포함
|
|
- linked evidence 중 `related_evidence_indexes`와 교집합 존재
|
|
- linked support role에 `사해행위목적물` 존재
|
|
- `BO.Action`, `BO.Object`, `BO.Legal_Keywords`, `BO.Evidence[].relevant_content`에
|
|
처분/매매/증여/대물변제/소유권이전 및 `target_property_candidates`가 함께 드러남
|
|
|
|
### 9.2 `preserved_claim_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- `BO.id`가 `preserved_claim_candidates[].bo_id`와 일치
|
|
- linked support role에 `원고채권` 존재
|
|
- `BO.Action`, `JuristicAct.label`, `Legal_Keywords`에 대여/보증/신용보증/대위변제/구상/잔존채권이 직접 나타남
|
|
|
|
### 9.3 `encumbrance_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- linked evidence 중 `encumbrance_related_evidence_indexes`와 교집합 존재
|
|
- linked support role에 `선순위담보` 또는 `존속담보` 존재
|
|
- `BO.Action`, `BO.Legal_Keywords`에 근저당/저당/전세권/담보설정/담보말소가 직접 나타남
|
|
- 그리고 가능하면 target property cluster와 연결되어야 한다.
|
|
|
|
### 9.4 `lease_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- linked support role에 `임차권` 존재
|
|
- `BO.Action`, `Legal_Keywords`에 임대차/임차보증금/점유/확정일자/전입이 직접 나타남
|
|
- 그리고 가능하면 target property cluster와 연결되어야 한다.
|
|
|
|
### 9.5 `attachment_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- linked support role에 `가압류` 존재
|
|
- `BO.Action`, `Legal_Keywords`에 가압류/압류/보전처분이 직접 나타남
|
|
- 그리고 가능하면 target property cluster와 연결되어야 한다.
|
|
|
|
### 9.6 `beneficiary_bucket`
|
|
다음 중 하나 이상이면 포함:
|
|
- linked support role에 `수익자이익` 존재
|
|
- `BO.Subject` 또는 `BO.Action`에 `beneficiary_candidates`가 직접 나타남
|
|
- `property_bucket`에 속하면서 수익자/전득자와 직접 관련된 처분 BO임
|
|
|
|
### 9.7 conservative tie-break
|
|
- 두 bucket 사이가 애매하면 더 좁은 범위만 남긴다.
|
|
- `target_property_candidates`와 연결 여부가 불명하면 property/encumbrance/lease/attachment/beneficiary 관련 필드는 버린다.
|
|
|
|
---
|
|
|
|
## 10. relevance 필터 (support field별 허용 범위)
|
|
linked support 전체를 BO에 그대로 붙이지 말고, 아래 필드별 허용 범위에 따라 잘라낸다.
|
|
|
|
### 10.1 `support_role_tags`
|
|
- surviving support field를 실제로 뒷받침한 role tag만 남긴다.
|
|
- 단순 union 금지. 결과 필드와 무관한 tag는 제거한다.
|
|
|
|
### 10.2 `fraudulent_act_date`
|
|
허용 조건:
|
|
- `property_bucket == true`
|
|
- 해당 linked support에 `support_role_tags` 중 `사해행위목적물`이 존재
|
|
- 값이 있으면 우선 `actio_case_signals.fraudulent_act_date_candidates`와 일치하는 값만 허용
|
|
|
|
충돌 규칙:
|
|
- surviving candidate가 1개면 채택
|
|
- 2개 이상이면 `actio_case_signals.fraudulent_act_date_candidates`와 일치하는 값만 남긴다
|
|
- 그래도 복수이거나 일치값이 없으면 `fraudulent_act_date`는 아예 제거한다
|
|
|
|
### 10.3 `property_value_at_close_of_arguments_support`
|
|
허용 조건:
|
|
- `property_bucket == true`
|
|
- linked support role에 `사해행위목적물`이 존재하거나, 처분 목적물 자체의 가치와 직접 연결됨
|
|
|
|
### 10.4 `encumbrances_at_fraudulent_act`
|
|
허용 조건:
|
|
- `encumbrance_bucket == true` 또는 (`property_bucket == true` 이고 동일 target property cluster 관련 부담)
|
|
- role tag가 `선순위담보` 또는 `존속담보`이거나, `attachment_bucket`에서 `kind=="가압류"`가 직접 확인됨
|
|
|
|
금지 조건:
|
|
- `preserved_claim_bucket`만 있는 BO에는 올리지 않는다
|
|
|
|
### 10.5 `encumbrances_at_close_of_arguments`
|
|
허용 조건은 10.4와 동일하다.
|
|
|
|
### 10.6 `lease_deposit_deductibility_support`
|
|
허용 조건:
|
|
- `lease_bucket == true`
|
|
- target property cluster와 직접 연결됨
|
|
|
|
금지 조건:
|
|
- 원고채권 BO, 보증 BO, 대위변제 BO에 올리지 않는다
|
|
|
|
### 10.7 `non_deductible_attachment_claims`
|
|
허용 조건:
|
|
- `attachment_bucket == true`
|
|
- target property cluster와 직접 연결됨
|
|
|
|
### 10.8 `beneficiary_gain_support`
|
|
허용 조건:
|
|
- `beneficiary_bucket == true` 또는 (`property_bucket == true` 이고 처분 상대방/수익자 관련성이 직접 드러남)
|
|
- `beneficiary_candidates`가 주어진 경우 가능한 한 그 후보와 부합해야 한다
|
|
|
|
### 10.9 `plaintiff_claim_snapshots`
|
|
허용 조건:
|
|
- `preserved_claim_bucket == true`
|
|
- `preserved_claim_candidates`가 있는 경우 가능한 한 `bo_id`, `claim_type_candidate`, `creditor_candidate`, `debtor_candidate`와 부합하는 것 우선
|
|
|
|
금지 조건:
|
|
- `property_bucket`, `encumbrance_bucket`, `lease_bucket`, `attachment_bucket`만 있는 BO에는 올리지 않는다
|
|
|
|
### 10.10 `legal_meta_flags`
|
|
허용 조건:
|
|
- 동일 BO에서 위 10.2~10.9 중 적어도 하나의 실질 support field가 살아남았을 때만 보조적으로 유지 가능
|
|
- 또는 linked support role에 `법리메타`가 있고, BO가 case scope gate를 통과한 경우에만 보조적으로 유지 가능
|
|
|
|
---
|
|
|
|
## 11. field-level selection / merge 규칙
|
|
아래 규칙은 10장의 relevance 필터를 통과한 support들에만 적용한다.
|
|
|
|
### 11.1 `support_role_tags`
|
|
- surviving field를 실제로 뒷받침한 role tag만 uniq로 병합한다.
|
|
|
|
### 11.2 `property_value_at_close_of_arguments_support`
|
|
아래 우선순위로 가장 직접적인 1개를 선택한다.
|
|
1. `basis_type=="사실심변론종결직접"`
|
|
2. `basis_type=="현재시점대체"`
|
|
3. `basis_type=="감정기준일"`
|
|
4. `basis_type=="거래시점동일"`
|
|
5. 그 외 기본 우선순위 fallback
|
|
|
|
선택된 객체에서 null 필드는 더 낮은 우선순위 객체의 동일 필드로 보충할 수 있다.
|
|
단, `candidate_amount` 자체가 경쟁하면 더 높은 우선순위 값을 유지한다.
|
|
|
|
### 11.3 `encumbrances_at_fraudulent_act`
|
|
identity key:
|
|
- `kind + holder + rank`
|
|
|
|
병합 규칙:
|
|
- 같은 identity key면 높은 우선순위 원소를 base로 사용한다.
|
|
- lower-priority 원소는 base의 null 필드만 보충한다.
|
|
- `registered_max_amount`와 `actual_secured_debt_at_act`를 새로 계산하지 않는다.
|
|
- `deductible_in_value_compensation`이 경쟁하면 high-priority 값을 유지한다.
|
|
- `attachment_bucket`만 있는 BO에서는 `kind=="가압류"` 항목만 유지할 수 있다.
|
|
|
|
### 11.4 `encumbrances_at_close_of_arguments`
|
|
identity key:
|
|
- `kind + holder + rank`
|
|
|
|
병합 규칙:
|
|
- 같은 identity key면 높은 우선순위 원소를 base로 사용한다.
|
|
- `actual_outstanding_at_close`, `released_date`, `released_by_beneficiary`는 null 보충만 허용한다.
|
|
- `attachment_bucket`만 있는 BO에서는 `kind=="가압류"` 항목만 유지할 수 있다.
|
|
|
|
### 11.5 `lease_deposit_deductibility_support`
|
|
아래 우선순위로 가장 직접적인 1개를 선택한다.
|
|
1. 임대차계약, 주민등록, 인도, 확정일자 직접 문서에서 유래한 record
|
|
2. 등기, 처분, 승계문서에서 임대보증금 승계가 직접 보이는 record
|
|
3. 그 외 기본 우선순위 fallback
|
|
|
|
선택된 객체의 null 필드는 더 낮은 우선순위 객체로 보충할 수 있다.
|
|
단, `deductible_candidate`가 경쟁하면 더 직접적인 문서 값을 유지한다.
|
|
|
|
### 11.6 `non_deductible_attachment_claims`
|
|
identity key:
|
|
- `holder + kind + claim_amount`
|
|
|
|
병합 규칙:
|
|
- exact-match 중복 제거
|
|
- 같은 identity key에서 `attachment_non_deductible_flag`는 `true`가 하나라도 있으면 `true` 유지
|
|
- `reason`은 high-priority 값을 유지하고 null만 보충
|
|
|
|
### 11.7 `beneficiary_gain_support`
|
|
아래 우선순위로 primary object 1개를 선택한다.
|
|
1. 사해행위 목적물의 계약, 처분, 등기에서 유래한 record
|
|
2. 수익자가 실제 변제한 부담을 보여주는 영수증, 확인서 성격의 record
|
|
3. 그 외 기본 우선순위 fallback
|
|
|
|
선택된 객체의 null 필드는 lower-priority 동일 사실 객체로 보충할 수 있다.
|
|
단, `beneficiary_gain_estimate_candidate`는 계산하지 않고 입력값이 있을 때만 채운다.
|
|
|
|
### 11.8 `plaintiff_claim_snapshots`
|
|
identity key:
|
|
- `plaintiff_name + claim_type`
|
|
|
|
병합 규칙:
|
|
- 같은 identity key면 높은 우선순위 원소를 base로 사용한다.
|
|
- `principal_existing_at_fraudulent_act`, `secured_portion_at_fraudulent_act`, `unsecured_portion_at_fraudulent_act`, `contractual_interest_rate`, `default_interest_rate`, `interest_start_date`, `amount_as_of_close_of_arguments`는 null 보충만 허용한다.
|
|
- `proof_status`는 더 강한 값 우선
|
|
- `"direct"` > `"indirect"` > `"meeting_only"` > `"unknown"`
|
|
|
|
### 11.9 `legal_meta_flags`
|
|
스칼라 필드이므로 per-field first-non-null 규칙을 쓴다.
|
|
다만 아래 예외를 적용한다.
|
|
- `confidence_score`는 `"high"` > `"medium"` > `"low"` > `"unknown"` 우선
|
|
- `attachment_claim_deductible_candidate`는 명백한 가압류, 압류 support가 있으면 `false`를 우선 유지할 수 있다
|
|
- 실질 support field가 하나도 살아남지 않았으면 `legal_meta_flags` 전체를 버린다
|
|
|
|
---
|
|
|
|
## 12. pruning 규칙
|
|
### 12.1 필드 pruning
|
|
- 스칼라 키가 `null`이면 제거
|
|
- 배열 키가 `[]`이면 제거
|
|
- 객체 키의 내부가 모두 제거되면 그 객체 키도 제거
|
|
|
|
### 12.2 레코드 pruning
|
|
- pruning 이후 `actio_pauliana_support`가 비어 있으면 해당 BO 레코드는 출력하지 않는다.
|
|
|
|
### 12.3 proof_doc 유지
|
|
- surviving support item의 `proof_doc`는 입력값을 그대로 유지한다.
|
|
- `proof_doc`가 없으면 그 키는 제거한다.
|
|
|
|
---
|
|
|
|
## 13. fact_actio_support.json 스키마(필드명/enum 엄수; 추가 필드 금지)
|
|
최종 파일은 배열(Array)이다.
|
|
|
|
각 원소는 아래 구조를 따른다.
|
|
|
|
```ts
|
|
{
|
|
source_bo_id: string; // "bh1"
|
|
actio_pauliana_support: {
|
|
support_role_tags?: Array<"사해행위목적물"|"선순위담보"|"존속담보"|"임차권"|"가압류"|"원고채권"|"수익자이익"|"법리메타">;
|
|
fraudulent_act_date?: string;
|
|
property_value_at_close_of_arguments_support?: {
|
|
candidate_amount?: string;
|
|
candidate_date?: string;
|
|
basis_type?: "사실심변론종결직접"|"현재시점대체"|"감정기준일"|"거래시점동일"|"불명";
|
|
reason_text?: string;
|
|
confidence?: "high"|"medium"|"low"|"unknown";
|
|
proof_doc?: string;
|
|
};
|
|
encumbrances_at_fraudulent_act?: Array<{
|
|
kind?: "근저당"|"저당"|"가압류"|"전세권"|"임차보증금반환채권";
|
|
holder?: string;
|
|
rank?: number;
|
|
registered_max_amount?: string;
|
|
actual_secured_debt_at_act?: string;
|
|
supported_date?: string;
|
|
deductible_in_value_compensation?: boolean;
|
|
deductibility_reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
encumbrances_at_close_of_arguments?: Array<{
|
|
kind?: "근저당"|"저당"|"가압류"|"전세권"|"임차보증금반환채권";
|
|
holder?: string;
|
|
rank?: number;
|
|
actual_outstanding_at_close?: string;
|
|
released_date?: string;
|
|
released_by_beneficiary?: boolean;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
lease_deposit_deductibility_support?: {
|
|
tenant_name?: string;
|
|
lease_deposit_amount?: string;
|
|
has_possession?: boolean;
|
|
has_resident_registration?: boolean;
|
|
has_fixed_date?: boolean;
|
|
senior_security_exists?: boolean;
|
|
deductible_candidate?: boolean;
|
|
deductibility_reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
};
|
|
non_deductible_attachment_claims?: Array<{
|
|
holder?: string;
|
|
kind?: "가압류"|"압류";
|
|
claim_amount?: string;
|
|
attachment_non_deductible_flag?: boolean;
|
|
reason?: string;
|
|
proof_doc?: string;
|
|
proof_strength?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
}>;
|
|
beneficiary_gain_support?: {
|
|
beneficiary_name?: string;
|
|
nominal_transfer_value?: string;
|
|
beneficiary_preexisting_claim_amount?: string;
|
|
assumed_debt_amount?: string;
|
|
released_encumbrance_amount?: string;
|
|
beneficiary_gain_estimate_candidate?: string;
|
|
estimation_basis?: string;
|
|
proof_doc?: string;
|
|
confidence?: "high"|"medium"|"low"|"unknown";
|
|
};
|
|
plaintiff_claim_snapshots?: Array<{
|
|
plaintiff_name?: string;
|
|
claim_type?: "loan"|"guarantee"|"reimbursement";
|
|
principal_existing_at_fraudulent_act?: string;
|
|
secured_portion_at_fraudulent_act?: string;
|
|
unsecured_portion_at_fraudulent_act?: string;
|
|
contractual_interest_rate?: string;
|
|
default_interest_rate?: string;
|
|
interest_start_date?: string;
|
|
amount_as_of_close_of_arguments?: string;
|
|
proof_status?: "direct"|"indirect"|"meeting_only"|"unknown";
|
|
proof_doc?: string;
|
|
}>;
|
|
legal_meta_flags?: {
|
|
is_actio_pauliana_relevant_candidate?: boolean;
|
|
restoration_mode_candidate?: "원물반환"|"말소등기"|"가액배상";
|
|
is_value_compensation_exception_triggered_candidate?: boolean;
|
|
lease_deposit_deductible_candidate?: boolean;
|
|
attachment_claim_deductible_candidate?: boolean;
|
|
remaining_joint_collateral_value_estimate_candidate?: string;
|
|
beneficiary_gain_estimate_candidate?: string;
|
|
confidence_score?: "high"|"medium"|"low"|"unknown";
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
추가 규칙:
|
|
- 최종 배열이 비어 있을 수 있다. 이 경우 `[]`를 저장한다.
|
|
- 레코드에는 `source_bo_id`와 `actio_pauliana_support` 외 다른 최상위 키를 넣지 않는다.
|
|
- `evidence_index`, `title`, `doc_type`, `key_*`, base `legal_calculation_object`, case-level signals를 반복 저장하지 않는다.
|
|
|
|
---
|
|
|
|
## 14. 최종 실행 지시
|
|
1. `BO.json`, `evidence_actio_support.json`, `actio_case_signals.json`을 읽는다.
|
|
2. 사건 수준 gate가 닫혀 있으면 원칙적으로 `[]`를 저장한다.
|
|
3. gate가 열려 있으면 `BO.json` 배열 순서대로 각 BO의 linked support를 식별한다.
|
|
4. 각 BO에 대해 case scope anchors를 우선 적용하여 scope bucket을 판정한다.
|
|
5. field별 relevance 필터를 적용하여 허용되는 support만 남긴다.
|
|
6. field-level merge 규칙에 따라 BO 단위 normalized `actio_pauliana_support`를 만든다.
|
|
7. pruning 이후 support가 남는 BO만 `source_bo_id` 기준 sparse output 배열에 포함한다.
|
|
8. `write_file(overwrite=true)`로 `fact_actio_support.json`을 저장한다.
|
|
9. 즉시 `list_docs`로 파일 존재를 검증한다. 누락 시 재시도 1회.
|
|
10. `fact_actio_support.json`은 절대 재읽지 않는다.
|
|
|
|
|
|
|
|
task_procedure:
|
|
IN:
|
|
nexts: ["Task_A", "Task_B1"]
|
|
wait_until: []
|
|
Task_A:
|
|
nexts: ["OUT"]
|
|
wait_until: ["IN"]
|
|
Task_B1:
|
|
nexts: ["Task_B2"]
|
|
wait_until: ["IN"]
|
|
Task_B2:
|
|
nexts: ["Task_C"]
|
|
wait_until: ["Task_B1"]
|
|
Task_C:
|
|
nexts: ["Task_B3", "Task_D1"]
|
|
wait_until: ["Task_B1", "Task_B2"]
|
|
Task_B3:
|
|
nexts: ["Task_D2"]
|
|
wait_until: ["Task_B1", "Task_C"]
|
|
Task_D1:
|
|
nexts: ["OUT"]
|
|
wait_until: ["Task_B1", "Task_C"]
|
|
Task_D2:
|
|
nexts: ["OUT"]
|
|
wait_until: ["Task_B3", "Task_C"]
|
|
OUT:
|
|
nexts: []
|
|
wait_until: ["Task_D1", "Task_D2"]
|
|
|
|
prevs: [ ]
|
|
nexts: [stage_2_청구권개요서작성]
|
|
|
|
- name: stage2_청구개요서작성
|
|
description: 청구권 개요서 작성
|
|
llm_provider: openai
|
|
llm_model: gpt-4o-2024-08-06
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
code-executor:
|
|
type: streamable-http
|
|
url: https://code-executor.mcp.eroomai.com/mcp
|
|
description: Run scripts of programming languages
|
|
headers:
|
|
Authorization: Bearer rR8OXqWrVZA1gFEo8oWfBkw2XgpWoGrrspw5ObsxTCM=
|
|
|
|
tasks:
|
|
- task_name: Task_A
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs`사용해서 BO.json, Fact_Ledger.json, client_goal.json, Default_Agent/적격피고자제외조건.md, evidence_contradictions.json(존재할 때만), Default_Agent/사해행위취소청구_청구고려사항.md 존재 확인, `read_docs`사용해서 BO.json, Fact_Ledger.json, client_goal.json, 적격피고자제외조건.md, evidence_contradictions.json(존재할 때만), 사해행위취소청구_청구고려사항.md 읽기
|
|
[ ] 2) `write_file`사용해서 `stage2_1_claims_evaluated.json` 생성
|
|
[ ] 3) `list_docs` 사용해서 `stage2_1_claims_evaluated.json` 확인
|
|
[ ] 4) "청구권 및 당사자 식별 완료" 출력하고 작업을 종료(terminate)
|
|
---
|
|
|
|
## 0. Role / Output
|
|
- 당신은 **대한민국 민사·상사 소송 전문 변호사이자 MCP 에이전트**다. 입력 파일을 근거로 원고가 청구할 수 있는 청구권을 도출하고, 당사자(원고/피고)를 확정한다.
|
|
- Output: stage2_1_claims_evaluated.json
|
|
|
|
## 1. 불가침 원칙(Non-negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확하면 **null / "불명" / "[증거공백]"** 으로 명시한다
|
|
3) 입력 원문 **대량 혹은 장문 복사 금지**
|
|
4) 필수 입력 누락/빈 파일/파싱불가 시 **즉시 중단**(파일 출력 금지)하고, 누락 항목을 채팅으로만 보고한다.
|
|
5) **중간 결과(JSON 덤프, DB 결과 덤프)를 채팅에 출력하지 말 것**
|
|
|
|
## 2. 에러 처리 정책 (운영 규칙)
|
|
- `read_docs` 반환이 `"Error:"`로 시작하면 **동일 doc_name으로 1회만 재시도**.
|
|
- 재시도 실패 시: 해당 입력은 **스킵하고 진행**, 대신 `VALIDATION WARNING`에 기록.
|
|
- 무한 재시도 금지.
|
|
|
|
## 3. 불명확성 처리(결정론)
|
|
기산점/금액/당사자 귀속/증거 연결이 불명확하면:
|
|
- 해당 평가요소는 **Medium**으로 둔다.
|
|
- 다음 형식으로 1줄 경고를 남긴다:
|
|
`VALIDATION WARNING: <요소명> 산정 불가 - <사유 1줄>`
|
|
|
|
## 4. 입력 파일
|
|
### 4.1 시작 시 반드시 읽는 파일
|
|
- `BO.json`
|
|
- `client_goal.json`
|
|
- `Fact_Ledger.json`
|
|
- `Default_Agent/적격피고자제외조건.md`
|
|
- `Default_Agent/사해행위취소청구_청구고려사항.md`
|
|
### 4.2 존재하면 읽는 파일
|
|
- `evidence_contradictions.json`
|
|
- 존재하면 읽고, **해당 모순이 핵심 사실(금액/일자/당사자)과 직접 충돌**하는 청구의 승소가능성 상한을 **Medium**으로 제한하고 WARNING에 기록.
|
|
|
|
## 5. 사건 개요 + 청구권 후보 도출 + 스코어링 + 당사자
|
|
### 5.1 사건 개요
|
|
- `원고 목표`: client_goal.json의 "primary_goal" 원문
|
|
- `사건 핵심 요약`: client_goal.json의 "summary_key_incidents" 원문
|
|
- `핵심 사실`: client_goal.json의 "key_facts" 원문
|
|
|
|
### 5.1 청구권 후보 생성(상한 12개)
|
|
- BO의 `Legal_Keywords`와 `ActionType`을 활용해 **쟁점 클러스터**를 만든 뒤, 클러스터별로 청구권 후보를 만든다.
|
|
- **쟁점 클러스터** 구성 시 청구권 후보가 "사해행위취소" 청구에 해당할 경우, `사해행위취소청구_청구고려사항.md` 파일이 제시하는 기준을 참조하여 청구권 후보를 세부적으로 도출한다.
|
|
- 후보 총량은 **최대 12개**.
|
|
- 하드 프리필터:
|
|
- 각 후보 청구는 최소 1개 이상의 근거를 반드시 가진다: `fact_id` 또는 `evidence_index` 중 하나 이상.
|
|
- 근거가 0이면 후보에서 제외.
|
|
|
|
각 청구권은 내부적으로 다음 필드를 가진다(채팅 출력 금지):
|
|
- `claim_id` (C-001, C-002 …)
|
|
- `claim_title`
|
|
- `relief_summary` (청구취지 1줄) // 특히 사해행위취소청구 후보의 경우 `사해행위취소청구_청구고려사항.md`의 기준을 반드시 적용하여 청구취지 작성: "취소 범위 특정", "제척기간 식별", "저당권이 설정된 부동산과 가액배상 법리" 기준은 매우 엄격하게 적용
|
|
- `cause_summary` (청구원인 2문장 이내) // "relief_summary"와 연계하여 청구원인 작성
|
|
- `legal_basis_hint` (예: contract/loan, guarantee, reimbursement, unjust enrichment, tort, actio pauliana 등)
|
|
- `source_bo_ids` (≤6)
|
|
- `source_fact_ids` (≤6)
|
|
- `key_evidence_indexes` (≤6)
|
|
|
|
### 5.2 등급 평가(High/Medium/Low) 및 청구권 순서
|
|
평가축 4개(각 1~3점, 총 12점). 불명확하면 Medium + WARNING.
|
|
|
|
1) 승소가능성
|
|
- Fact_Ledger의 credibility + BO.Evidence의 직접성(직접/간접) 중심.
|
|
- **evidence_contradictions.json**에서 금액/일자/당사자 모순이 “핵심”이면 승소가능성 상한을 **Medium**으로 제한 + WARNING.
|
|
|
|
2) 집행가능성
|
|
- 자산 단서 2개 이상: High / 1개: Medium / 없음: Low
|
|
- **무자력만으로 자동 제외 금지**. 대신 `EXECUTION_RISK: HIGH` 태깅.
|
|
|
|
3) 경제성(일반성 강화: 금액/비금전 중요도/보전 필요성)
|
|
- 금전청구: ≥1억 High / 5천만~1억 Medium / <5천만 Low
|
|
- 비금전/형성/금지·보전 관련:
|
|
- High: 권리 중요도·긴급성 높거나 보전 필요성이 높음
|
|
- Medium: 불명확(기본값)
|
|
- Low: 중요도 낮고 대체수단 존재
|
|
|
|
4) 시효 긴급도
|
|
- 잔여 6개월 이내 High / 1년 이내 Medium / 1년 초과 Low
|
|
- 기산점 불명확: Medium + WARNING
|
|
|
|
5) 청구권(claim_id) 배열 순서:
|
|
- 시간 순서: 식별한 청구권(claim_id)에 대응되는 Fact_Ledger의 fact_id와 date을 우선하여 시간 순서상 앞서는 청구권 우선 배치
|
|
- 동일 날짜 청구권은 합산점수 높은 순으로 배치
|
|
- 절대로 합산점수 순서대로 claim_id를 배치하지 않는다.
|
|
- 합산 점수가 5점 이상인 청구권과 5점 미만인 청구권 구별
|
|
- 5점 이상은 "청구권"으로 5점 미만은 "기타청구권"으로 분리
|
|
|
|
### 5.3 원고/피고 결정
|
|
* 원고:
|
|
- `client_goal.json`의 parties.plaintiffs 기반.
|
|
- 권리귀속이 불명확하면 “후보”로 표시하고 사유 1줄.
|
|
|
|
* 피고:
|
|
1) BO의 Performer/Subject/Object 및 client_goal constraints에서 피고 pool 구성
|
|
2) `적격피고자제외조건.md`를 적용:
|
|
- 제외조건 해당: 제외 또는 “대체 필요”
|
|
- 무자력만으로 자동 제외 금지(집행리스크 태깅)
|
|
3) client_goal.json의 `constraints`를 적용하여 `소제기`의 실익이 없는 피고를 필터링하여 제외
|
|
4) 청구권별로 피고 매핑
|
|
|
|
## 6. JSON Schema for `stage2_1_claims_evaluated.json`
|
|
### 6.1 Schema
|
|
{
|
|
"title": "Stage 2.1 Claims Evaluated Output",
|
|
"description": "Task A: 청구권 후보 도출, 평가 및 당사자 확정 결과",
|
|
"type": "object",
|
|
"properties": {
|
|
"parties": {
|
|
"type": "object",
|
|
"description": "당사자(원고/피고) 확정 및 적격성/리스크 평가 (전체 풀)",
|
|
"properties": {
|
|
"plaintiffs": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"status": { "type": "string", "enum": ["확정", "후보", "불명"] },
|
|
"reason": { "type": ["string", "null"], "description": "권리귀속 불명확 등으로 '후보'인 경우 사유 1줄" }
|
|
},
|
|
"required": ["name", "status"]
|
|
}
|
|
},
|
|
"defendants": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": { "type": "string" },
|
|
"status": { "type": "string", "enum": ["적격", "제외", "대체 필요", "불명"] },
|
|
"execution_risk": { "type": ["string", "null"], "enum": ["HIGH", "MEDIUM", "LOW", null], "description": "무자력인 경우 자동 제외 대신 'HIGH' 태깅" },
|
|
"reason": { "type": ["string", "null"], "description": "상태 결정 및 집행리스크 사유 1줄" }
|
|
},
|
|
"required": ["name", "status"]
|
|
}
|
|
}
|
|
},
|
|
"required": ["plaintiffs", "defendants"]
|
|
},
|
|
"claims": {
|
|
"type": "array",
|
|
"description": "총점 5점 이상인 '청구권' 목록 (합산점수 내림차순 정렬)",
|
|
"maxItems": 12,
|
|
"items": { "$ref": "#/definitions/Claim" }
|
|
},
|
|
"other_claims": {
|
|
"type": "array",
|
|
"description": "총점 5점 미만인 '기타청구권' 목록 (합산점수 내림차순 정렬)",
|
|
"maxItems": 12,
|
|
"items": { "$ref": "#/definitions/Claim" }
|
|
},
|
|
"validation_warnings": {
|
|
"type": "array",
|
|
"description": "불명확성, 증거공백, 모순점 충돌에 따른 전역 경고 메시지 목록 ('VALIDATION WARNING: ...' 형식)",
|
|
"items": { "type": "string", "pattern": "^VALIDATION WARNING:" }
|
|
}
|
|
},
|
|
"required": ["parties", "claims", "other_claims", "validation_warnings"],
|
|
"definitions": {
|
|
"Claim": {
|
|
"type": "object",
|
|
"properties": {
|
|
"claim_id": { "type": "string", "description": "예: C-001" },
|
|
"claim_title": { "type": "string", "description": "청구권 명칭" },
|
|
"relief_summary": { "type": "string", "description": "청구취지 1줄" },
|
|
"cause_summary": { "type": "string", "description": "청구원인 2문장 이내" },
|
|
"legal_basis_hint": { "type": "string", "description": "예: contract/loan, guarantee, reimbursement, unjust enrichment, tort, actio pauliana 등" },
|
|
"source_bo_ids": { "type": "array", "items": { "type": "string" }, "maxItems": 6 },
|
|
"source_fact_ids": { "type": "array", "items": { "type": "string" }, "maxItems": 6 },
|
|
"key_evidence_indexes": { "type": "array", "items": { "type": "string" }, "maxItems": 6 },
|
|
"mapped_parties": {
|
|
"type": "object",
|
|
"description": "해당 청구권에 매핑된 당사자 이름 목록",
|
|
"properties": {
|
|
"plaintiffs": { "type": "array", "items": { "type": "string" } },
|
|
"defendants": { "type": "array", "items": { "type": "string" } }
|
|
},
|
|
"required": ["plaintiffs", "defendants"]
|
|
},
|
|
"evaluation": {
|
|
"type": "object",
|
|
"description": "등급 평가 (각 1~3점, 총 12점 만점)",
|
|
"properties": {
|
|
"win_probability": { "$ref": "#/definitions/EvaluationMetric" },
|
|
"execution_feasibility": { "$ref": "#/definitions/EvaluationMetric" },
|
|
"economic_value": { "$ref": "#/definitions/EvaluationMetric" },
|
|
"statute_of_limitations_urgency": { "$ref": "#/definitions/EvaluationMetric" },
|
|
"total_score": { "type": "integer", "minimum": 1, "maximum": 12 }
|
|
},
|
|
"required": ["win_probability", "execution_feasibility", "economic_value", "statute_of_limitations_urgency", "total_score"]
|
|
}
|
|
},
|
|
"required": [
|
|
"claim_id", "claim_title", "relief_summary", "legal_basis_hint",
|
|
"source_bo_ids", "source_fact_ids", "key_evidence_indexes",
|
|
"mapped_parties", "evaluation"
|
|
]
|
|
},
|
|
"EvaluationMetric": {
|
|
"type": "object",
|
|
"properties": {
|
|
"grade": { "type": "string", "enum": ["High", "Medium", "Low", "불명", "[증거공백]"] },
|
|
"score": { "type": "integer", "minimum": 1, "maximum": 3 },
|
|
"reason": { "type": ["string", "null"], "description": "점수 산정 사유 1줄" }
|
|
},
|
|
"required": ["grade", "score", "reason"]
|
|
}
|
|
}
|
|
}
|
|
|
|
### 6.2 Example (JSON Mock-up)
|
|
{
|
|
"overall_claim_content": {
|
|
"primary_goal": [
|
|
],
|
|
"summary_key_incidents": [
|
|
]
|
|
}
|
|
"parties": {
|
|
"plaintiffs": [
|
|
{
|
|
"name": "우방캐피탈 주식회사",
|
|
"status": "확정",
|
|
"reason": null
|
|
}
|
|
],
|
|
"defendants": [
|
|
{
|
|
"name": "주식회사 개성금속",
|
|
"status": "적격",
|
|
"execution_risk": "HIGH",
|
|
"reason": "현재 폐업 상태로 집행 가능 재산이 없으나 무자력 자동 제외 금지 원칙 적용"
|
|
},
|
|
{
|
|
"name": "김수경",
|
|
"status": "적격",
|
|
"execution_risk": "MEDIUM",
|
|
"reason": "연대보증인, 본인 명의 재산 없으나 부모로부터 상속 가능성 존재"
|
|
}
|
|
]
|
|
},
|
|
"claims": [
|
|
{
|
|
"claim_id": "C-001",
|
|
"claim_title": "대여금 반환 청구",
|
|
"relief_summary": "피고 개성금속은 원고 우방캐피탈에게 10억 원 및 지연손해금을 지급하라.",
|
|
"cause_summary": "...", // '청구원인'에 대응하는 청구원인 2문장 이내 작성
|
|
"legal_basis_hint": "contract/loan",
|
|
"source_bo_ids": ["bh1", "bh8"],
|
|
"source_fact_ids": ["F-001", "F-008"],
|
|
"key_evidence_indexes": ["E-012", "E-008"],
|
|
"mapped_parties": {
|
|
"plaintiffs": ["우방캐피탈 주식회사"],
|
|
"defendants": ["주식회사 개성금속"]
|
|
},
|
|
"evaluation": {
|
|
"win_probability": { "grade": "High", "score": 3, "reason": "대출약정서 및 부도 사실 등 직접 증거 존재" },
|
|
"execution_feasibility": { "grade": "Low", "score": 1, "reason": "개성금속 자산 단서 없음" },
|
|
"economic_value": { "grade": "High", "score": 3, "reason": "금전청구 1억 원 이상" },
|
|
"statute_of_limitations_urgency": { "grade": "High", "score": 3, "reason": "상사채권 소멸시효(5년) 완성 임박" },
|
|
"total_score": 10
|
|
}
|
|
},
|
|
{
|
|
"claim_id": "C-002",
|
|
"claim_title": "연대보증채무 이행 청구",
|
|
"relief_summary": "피고 김수경은 피고 개성금속과 연대하여 10억 원을 지급하라.",
|
|
"cause_summary": "...", // '청구원인'에 대응하는 청구원인 2문장 이내 작성
|
|
"legal_basis_hint": "guarantee",
|
|
"source_bo_ids": ["bh2"],
|
|
"source_fact_ids": ["F-002"],
|
|
"key_evidence_indexes": ["E-012"],
|
|
"mapped_parties": {
|
|
"plaintiffs": ["우방캐피탈 주식회사"],
|
|
"defendants": ["김수경"]
|
|
},
|
|
"evaluation": {
|
|
"win_probability": { "grade": "Medium", "score": 2, "reason": "모순점(C-001) 발견 - 근저당 설정일자 불일치로 승소가능성 상한 제한" },
|
|
"execution_feasibility": { "grade": "Medium", "score": 2, "reason": "상속을 통한 자산 취득 가능성 단서 존재" },
|
|
"economic_value": { "grade": "High", "score": 3, "reason": "금전청구 1억 원 이상" },
|
|
"statute_of_limitations_urgency": { "grade": "High", "score": 3, "reason": "상사채권 소멸시효 완성 임박" },
|
|
"total_score": 10
|
|
}
|
|
}
|
|
],
|
|
"other_claims": [
|
|
{
|
|
"claim_id": "C-003",
|
|
"claim_title": "부당이득 반환 청구",
|
|
"relief_summary": "피고 유재석은 원고에게 4억 원을 지급하라.",
|
|
"cause_summary": "...", // '청구원인'에 대응하는 청구원인 2문장 이내 작성
|
|
"legal_basis_hint": "unjust enrichment",
|
|
"source_bo_ids": ["bh11"],
|
|
"source_fact_ids": ["F-011"],
|
|
"key_evidence_indexes": ["E-014"],
|
|
"mapped_parties": {
|
|
"plaintiffs": ["우방캐피탈 주식회사"],
|
|
"defendants": ["유재석"]
|
|
},
|
|
"evaluation": {
|
|
"win_probability": { "grade": "Medium", "score": 2, "reason": "대물변제로 인한 부당이득 성립 불명확" },
|
|
"execution_feasibility": { "grade": "Low", "score": 1, "reason": "자산 보유 여부 단서 없음" },
|
|
"economic_value": { "grade": "Low", "score": 1, "reason": "핵심 청구 대비 우선순위 낮음" },
|
|
"statute_of_limitations_urgency": { "grade": "Low", "score": 1, "reason": "시효 1년 초과 잔여" },
|
|
"total_score": 5
|
|
}
|
|
}
|
|
],
|
|
"validation_warnings": [
|
|
"VALIDATION WARNING: F-006 금액 산정 불가 - 증거공백으로 인해 이자 변제액 확인 불가",
|
|
"VALIDATION WARNING: C-002 승소가능성 산정 상한 제한 - evidence_contradictions.json의 핵심 날짜(근저당 설정일) 모순과 충돌함"
|
|
]
|
|
}
|
|
|
|
- task_name: Task_B
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_docs`사용해서 stage2_1_claims_evaluated.json, Default_Agent 폴더 내 case_kinds.md 존재 확인, `read_docs`사용해서 stage2_1_claims_evaluated.json, case_kinds.md 읽기
|
|
[ ] 2) `write_file`사용해서 `stage2_2_claims_taxonomy.json` 생성
|
|
[ ] 3) `list_doc` 사용해서 `stage2_2_claims_taxonomy.json` 확인
|
|
[ ] 4) "청구권별 사건 종류 식별 완료" 출력하고 작업을 종료(terminate)
|
|
---
|
|
|
|
## 0. Role / Output
|
|
- 당신은 **대한민국 민사·상사 소송 전문 변호사이자 MCP 에이전트**다. 입력 파일을 근거로 원고의 청구권 특징을 파악하여 사건 종류를 식별한다.
|
|
- Output: stage2_2_claims_taxonomy.json
|
|
|
|
## 1. 불가침 원칙(Non-negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확하면 **null / "불명" / "[증거공백]"** 으로 명시한다
|
|
3) 입력 원문 **대량 혹은 장문 복사 금지**
|
|
4) 필수 입력 누락/빈 파일/파싱불가 시 **즉시 중단**(파일 출력 금지)하고, 누락 항목을 채팅으로만 보고한다.
|
|
5) **중간 결과(JSON 덤프, DB 결과 덤프)를 채팅에 출력하지 말 것**
|
|
|
|
## 2. 에러 처리 정책 (운영 규칙)
|
|
- `read_docs` 반환이 `"Error:"`로 시작하면 **동일 doc_name으로 1회만 재시도**.
|
|
- 재시도 실패 시: 해당 입력은 **스킵하고 진행**, 대신 `VALIDATION WARNING`에 기록.
|
|
|
|
## 3. 입력 파일
|
|
- `stage2_1_claims_evaluated.json`
|
|
- `Default_Agent/case_kinds.md`
|
|
|
|
## 4. 청구권별 사건 종류 식별
|
|
### 4.1 식별 방법
|
|
1. 평가된 청구권들의 키워드를 분석해 청구권을 분류한다:
|
|
- case_kinds.md 파일이 제시하는 소송대분류(이행/형성/확인/가사)를 1차 확정한다.
|
|
- 소송대분류에 해당하는 "분쟁 유형"을 2차 확정한다.
|
|
- 분쟁 유형에 해당하는 "사건 종류"의 항목이 존재하면 그것을 선택
|
|
- "사건 종류"가 비어 있으면(empty) "분쟁 유형" 내용을 선택
|
|
2. 확정된 대분류에 해당하는 분쟁유형과 사건종류를 **조사나 띄어쓰기 변형 없이 100% 동일한 문자열(Exact-match)**로 복사하여 라벨링한다.
|
|
- "사건 종류" 항목이 존재하면 그것을 우선 선택, 만일 "사건 종류" 항목이 존재하지 않으면(empty) "분쟁 유형" 내용을 선택
|
|
### 4.2 청구(claim)별 exact-match
|
|
각 claim에 대해:
|
|
- (소송대분류, 분쟁유형, 사건종류)를 case_kinds.md에서 **exact-match**로 복사.
|
|
- 확신이 없으면 back-off:
|
|
- 사건종류 불명확 → 사건종류 null, 분쟁유형까지만
|
|
- 분쟁유형도 불명확 → 소송대분류까지만
|
|
|
|
## 5. JSON Schema for `stage2_2_claims_taxonomy.json`
|
|
### 5.1 Schema
|
|
{
|
|
"title": "Stage 2.2 Claims Taxonomy Output",
|
|
"description": "Task B: 청구권별 사건 종류 Exact-Match 식별 및 분류 결과",
|
|
"type": "object",
|
|
"properties": {
|
|
"claims_taxonomy": {
|
|
"type": "array",
|
|
"description": "Task A에서 식별된 각 청구권(claim_id)에 대한 분류표(case_kinds.md) 매핑 결과",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"claim_id": {
|
|
"type": "string",
|
|
"description": "Task A에서 부여된 청구권 식별자 (예: C-001)"
|
|
},
|
|
"macro_category": {
|
|
"type": ["string", "null"],
|
|
"enum": ["이행의 소", "확인의 소", "형성의 소", "가사소송", "가족관계등록", "행정소송", null],
|
|
"description": "1차 확정: 소송 대분류. 매핑할 수 없는 경우 null."
|
|
},
|
|
"dispute_type": {
|
|
"type": ["string", "null"],
|
|
"description": "2차 확정: 분쟁 유형. 표에서 빈칸이거나(예: 형성의 소), 확신이 없어 Back-off 한 경우 null."
|
|
},
|
|
"case_kind": {
|
|
"type": ["string", "null"],
|
|
"description": "3차 확정: 사건 종류. 표에서 빈칸이면 프롬프트 지시에 따라 '분쟁 유형'의 문자열을 동일하게 복사. 불명확하여 Back-off 한 경우 null."
|
|
},
|
|
"is_backoff_applied": {
|
|
"type": "boolean",
|
|
"description": "확신이 부족하여 하위 분류(사건종류 또는 분쟁유형)를 포기하고 상위 분류만 확정하는 Back-off 전략을 사용했는지 여부"
|
|
},
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "분류를 선택한 근거, 빈칸 대체 사유, 또는 Back-off 적용 사유 (1~2줄)"
|
|
}
|
|
},
|
|
"required": [
|
|
"claim_id",
|
|
"macro_category",
|
|
"dispute_type",
|
|
"case_kind",
|
|
"is_backoff_applied",
|
|
"reason"
|
|
]
|
|
}
|
|
},
|
|
"validation_warnings": {
|
|
"type": "array",
|
|
"description": "분류 실패, 빈칸 대체, Back-off 발생 등 파이프라인 진행 중 기록할 전역 경고 메시지 목록",
|
|
"items": {
|
|
"type": "string",
|
|
"pattern": "^VALIDATION WARNING:"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"claims_taxonomy",
|
|
"validation_warnings"
|
|
]
|
|
}
|
|
|
|
### 5.2 Example (JSON Mock-up)
|
|
{
|
|
"claims_taxonomy": [
|
|
{
|
|
"claim_id": "C-001",
|
|
"macro_category": "이행의 소",
|
|
"dispute_type": "금전의 지급을 구하는 소",
|
|
"case_kind": "대여금 청구",
|
|
"is_backoff_applied": false,
|
|
"reason": "금전 반환 목적의 소비대차이므로 '대여금 청구'와 100% exact-match 매핑함."
|
|
},
|
|
{
|
|
"claim_id": "C-002",
|
|
"macro_category": "이행의 소",
|
|
"dispute_type": "종류물(대체물)의 지급 또는 인도를 구하는 소",
|
|
"case_kind": "종류물(대체물)의 지급 또는 인도를 구하는 소",
|
|
"is_backoff_applied": false,
|
|
"reason": "표에서 '사건 종류' 항목이 비어있으므로(empty) 프롬프트 지시사항 4.1에 따라 '분쟁 유형' 텍스트를 사건 종류에 동일하게 복사함."
|
|
},
|
|
{
|
|
"claim_id": "C-003",
|
|
"macro_category": "형성의 소",
|
|
"dispute_type": null,
|
|
"case_kind": "사해행위취소 청구",
|
|
"is_backoff_applied": false,
|
|
"reason": "표에서 '형성의 소'는 '분쟁 유형' 항목이 비어있으므로 null 처리하고, 사건 종류는 exact-match로 매칭함."
|
|
},
|
|
{
|
|
"claim_id": "C-004",
|
|
"macro_category": "확인의 소",
|
|
"dispute_type": "물권에 관한 확인을 구하는 소",
|
|
"case_kind": null,
|
|
"is_backoff_applied": true,
|
|
"reason": "물권 확인 청구이나 표에 제시된 세부 사건종류(도메인/입목 등)와 정확히 일치하지 않아 분쟁유형까지만 확정하고 사건종류는 null로 Back-off함."
|
|
}
|
|
],
|
|
"validation_warnings": [
|
|
"VALIDATION WARNING: C-002 사건 종류가 비어 있어 분쟁 유형 내용을 복사하여 대체함.",
|
|
"VALIDATION WARNING: C-004 사건종류 확정 불가 - 정확히 일치하는 사건종류가 없어 분쟁유형까지만 매핑하는 Back-off 전략 수행함."
|
|
]
|
|
}
|
|
|
|
- task_name: Task_C
|
|
llm_provider: anthropic
|
|
llm_model: claude-haiku-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
## 실행방법(체크리스트)
|
|
[ ] 1) Preflight: `list_doc`사용해서 stage2_2_claims_taxonomy.json, Default_Agent 폴더 내 객관적병합요건기준.md 존재 확인, `read_docs`사용해서 stage2_2_claims_taxonomy.json, 객관적병합요건기준.md 읽기
|
|
[ ] 2) `write_file`사용해서 `stage2_3_consolidation_strategy.json` 생성
|
|
[ ] 3) `list_doc` 사용해서 `stage2_3_consolidation_strategy.json` 확인
|
|
[ ] 4) "청구권별 사건 종류 식별 완료" 출력하고 작업을 종료(terminate)
|
|
---
|
|
|
|
## 0. Role / Output
|
|
- 당신은 **대한민국 민사·상사 소송 전문 변호사이자 MCP 에이전트**다. 입력 파일을 근거로 원고의 청구권들을 병합청구할지 단독청구할지 선택한다.
|
|
- Output: stage2_3_consolidation_strategy.json
|
|
|
|
## 1. 불가침 원칙(Non-negotiables)
|
|
1) Hallucination 금지: 입력에 없는 사실은 추가하지 않는다.
|
|
2) 불명확하면 **null / "불명" / "[증거공백]"** 으로 명시한다
|
|
3) 입력 원문 **대량 혹은 장문 복사 금지**
|
|
4) 필수 입력 누락/빈 파일/파싱불가 시 **즉시 중단**(파일 출력 금지)하고, 누락 항목을 채팅으로만 보고한다.
|
|
5) **중간 결과(JSON 덤프, DB 결과 덤프)를 채팅에 출력하지 말 것**
|
|
|
|
## 2. 에러 처리 정책 (운영 규칙)
|
|
- `read_docs` 반환이 `"Error:"`로 시작하면 **동일 doc_name으로 1회만 재시도**.
|
|
- 재시도 실패 시: 해당 입력은 **스킵하고 진행**, 대신 `VALIDATION WARNING`에 기록.
|
|
|
|
## 3. 입력 파일
|
|
- stage2_2_claims_taxonomy.json
|
|
- 객관적병합요건기준.md
|
|
|
|
## 4. 청구권 병합 기준 식별
|
|
- 청구권(claim_id)이 1개만 존재할 경우 단독 청구로 결정
|
|
- 청구권이 2개 이상일 경우,
|
|
- 기본적으로는 모든 청구권들을 병합(단순병합)하는 것을 최우선 전략으로 취한다.
|
|
- 추가적으로 객관적병합요건기준.md가 제시하는 기준에 근거하여
|
|
- 청구권 간의 양립 불가성(택일), 주위/예비 관계, 동일 피고 및 사실관계 공유 여부를 분석하고,
|
|
- 단순병합 / 선택적 병합 / 예비적 병합 / 분리로 그룹핑(Grouping)을 설계하고, 논리적 근거(Rationale)를 2~3문장으로 작성한다.
|
|
|
|
## 5. JSON Schema for `stage2_3_consolidation_strategy.json`
|
|
### 5.1 Schema
|
|
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"title": "Stage 2.3 Consolidation Strategy Output",
|
|
"description": "Task C: 청구권 병합청구/단독청구/분리 방식 및 그룹핑 설계 결과",
|
|
"type": "object",
|
|
"properties": {
|
|
"consolidation_groups": {
|
|
"type": "array",
|
|
"description": "하나의 소장(소송) 단위로 묶여 제출될 청구권 그룹의 목록. 병합할 수 없어 '분리'되는 청구권은 별도의 그룹 객체로 파생됨.",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"group_id": {
|
|
"type": "string",
|
|
"description": "소송 그룹 식별자 (예: G-01, G-02)"
|
|
},
|
|
"structure_type": {
|
|
"type": "string",
|
|
"enum": ["단독", "단순병합", "선택적 병합", "예비적 병합", "분리"],
|
|
"description": "전체 청구권이 1개뿐이면 '단독', 2개 이상의 청구가 묶이면 병합 종류 명시. 무관한 청구를 별소 제기하는 경우 '분리' 선택."
|
|
},
|
|
"analysis": {
|
|
"type": ["object", "null"],
|
|
"description": "구조 결정을 위한 법리적 사전 분석(Chain of Thought). 전체 청구권이 1개라서 '단독'인 경우는 null 처리.",
|
|
"properties": {
|
|
"is_same_defendant": { "type": "boolean", "description": "동일 피고에 대한 청구인가?" },
|
|
"share_core_facts": { "type": "boolean", "description": "동일한 핵심 사실관계나 거래를 공유하는가?" },
|
|
"is_incompatible": { "type": "boolean", "description": "청구권 간에 논리적으로 양립할 수 없는(택일적) 관계인가?" },
|
|
"is_primary_alternative": { "type": "boolean", "description": "순서대로 판단을 구하는 주위적/예비적 관계가 존재하는가?" }
|
|
},
|
|
"required": ["is_same_defendant", "share_core_facts", "is_incompatible", "is_primary_alternative"]
|
|
},
|
|
"claims": {
|
|
"type": "array",
|
|
"description": "해당 소송 그룹에 포함된 청구권(claim_id) 목록 및 역할",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"claim_id": {
|
|
"type": "string",
|
|
"description": "Task A에서 식별된 청구권 ID (예: C-001)"
|
|
},
|
|
"role": {
|
|
"type": "string",
|
|
"enum": ["단독 청구", "대등한 청구", "주위적 청구", "예비적 청구"],
|
|
"description": "병합 구조 내 해당 청구권의 지위 (단순/선택적 병합은 '대등한 청구', 예비적 병합은 '주위적/예비적', 단독/분리는 '단독 청구')"
|
|
}
|
|
},
|
|
"required": ["claim_id", "role"]
|
|
},
|
|
"minItems": 1
|
|
},
|
|
"rationale": {
|
|
"type": "string",
|
|
"description": "객관적병합요건기준.md 파일과 analysis 결과에 근거하여 해당 그룹핑을 선택한 논리적 근거 (반드시 2~3문장으로 압축하여 작성)"
|
|
}
|
|
},
|
|
"required": ["group_id", "structure_type", "analysis", "claims", "rationale"]
|
|
},
|
|
"minItems": 1
|
|
},
|
|
"validation_warnings": {
|
|
"type": "array",
|
|
"description": "에러 처리 정책에 따른 파일 읽기 실패, 기준 모호 등 파이프라인 진행 중 발생한 전역 경고 메시지",
|
|
"items": {
|
|
"type": "string",
|
|
"pattern": "^VALIDATION WARNING:"
|
|
}
|
|
}
|
|
},
|
|
"required": ["consolidation_groups", "validation_warnings"]
|
|
}
|
|
|
|
### 5.2 Example (JSON Mock-up)
|
|
{
|
|
"consolidation_groups": [
|
|
{
|
|
"group_id": "G-01",
|
|
"structure_type": "단순병합",
|
|
"analysis": {
|
|
"is_same_defendant": true,
|
|
"share_core_facts": true,
|
|
"is_incompatible": false,
|
|
"is_primary_alternative": false
|
|
},
|
|
"claims": [
|
|
{ "claim_id": "C-001", "role": "대등한 청구" },
|
|
{ "claim_id": "C-002", "role": "대등한 청구" }
|
|
],
|
|
"rationale": "C-001(대여금 원금 청구)과 C-002(지연손해금 청구)는 동일 피고에 대한 동일한 소비대차 거래 사실관계를 원인으로 합니다. 두 청구권은 논리적으로 상호 배척되지 않고 양립이 가능하므로, 소송경제를 도모하기 위해 하나의 소장으로 단순병합하여 제기하는 것이 타당합니다."
|
|
},
|
|
{
|
|
"group_id": "G-02",
|
|
"structure_type": "예비적 병합",
|
|
"analysis": {
|
|
"is_same_defendant": true,
|
|
"share_core_facts": true,
|
|
"is_incompatible": true,
|
|
"is_primary_alternative": true
|
|
},
|
|
"claims": [
|
|
{ "claim_id": "C-003", "role": "주위적 청구" },
|
|
{ "claim_id": "C-004", "role": "예비적 청구" }
|
|
],
|
|
"rationale": "C-003(사해행위취소 및 원물반환)과 C-004(가액배상)는 동일 피고를 상대로 하나 그 반환 방법이 논리적으로 양립할 수 없는 관계입니다. 따라서 원고의 주된 목적인 원물반환을 주위적 청구로 구하고, 그것이 불가능하여 기각될 경우를 대비해 가액배상을 예비적 청구로 병합합니다."
|
|
},
|
|
{
|
|
"group_id": "G-03",
|
|
"structure_type": "분리",
|
|
"analysis": {
|
|
"is_same_defendant": false,
|
|
"share_core_facts": false,
|
|
"is_incompatible": false,
|
|
"is_primary_alternative": false
|
|
},
|
|
"claims": [
|
|
{ "claim_id": "C-005", "role": "단독 청구" }
|
|
],
|
|
"rationale": "C-005(별건 손해배상 청구)는 앞선 청구권들과 피고가 상이하며 기초가 되는 사실관계 및 쟁점의 공통성이 현저히 결여되어 있습니다. 무리하게 병합할 경우 관할 위반 및 절차 지연의 우려가 크므로 기존 사건에서 분리하여 별개의 단독 소송으로 제기합니다."
|
|
}
|
|
],
|
|
"validation_warnings": [
|
|
"VALIDATION WARNING: 객관적병합요건기준.md의 선택적 병합 기준이 모호하여, 양립 가능성이 의심되는 부분은 안전하게 '분리' 판정 기준으로 우회 적용함."
|
|
]
|
|
}
|
|
- task_name: Task_D
|
|
mcp: code-executor
|
|
tool_name: run_code
|
|
parameters:
|
|
language: python
|
|
requirements: |
|
|
httpx
|
|
network: "agent-network"
|
|
timeout: 120
|
|
code: |
|
|
#!/usr/bin/env python3
|
|
import json
|
|
import sys
|
|
import os
|
|
import httpx
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
# ═══════════════════════════════════════════════
|
|
# 0. MCP localdocs 헬퍼
|
|
# ═══════════════════════════════════════════════
|
|
|
|
LOCALDOCS_URL = "http://mcp-localdocs:8012/mcp"
|
|
HEADERS = {
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json, text/event-stream",
|
|
}
|
|
|
|
|
|
def _log(msg):
|
|
print(msg, file=sys.stderr)
|
|
|
|
|
|
def parse_sse(text):
|
|
for line in text.strip().split("\n"):
|
|
if line.startswith("data: "):
|
|
return json.loads(line[6:])
|
|
try:
|
|
return json.loads(text)
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def call_tool(c, name, arguments, msg_id=10):
|
|
r = c.post(LOCALDOCS_URL, json={
|
|
"jsonrpc": "2.0", "id": msg_id,
|
|
"method": "tools/call",
|
|
"params": {"name": name, "arguments": arguments}
|
|
}, headers=HEADERS)
|
|
result = parse_sse(r.text)
|
|
if result and "result" in result:
|
|
return result
|
|
_log(f"Tool {name} error: {json.dumps(result)[:300]}")
|
|
return result
|
|
|
|
|
|
def mcp_read_json(c, doc_name, msg_id=10):
|
|
"""read_docs로 JSON 파일 읽기 → dict/list 반환"""
|
|
result = call_tool(c, "read_docs", {"doc_names": [doc_name]}, msg_id)
|
|
if not result or "result" not in result:
|
|
return None
|
|
raw = result["result"]["content"][0]["text"]
|
|
if not raw or not raw.strip():
|
|
return None
|
|
try:
|
|
wrapper = json.loads(raw)
|
|
except json.JSONDecodeError:
|
|
return None
|
|
if isinstance(wrapper, dict) and "results" in wrapper:
|
|
for item in wrapper["results"]:
|
|
if "error" in item:
|
|
_log(f" read_docs({doc_name}): {item['error']}")
|
|
return None
|
|
content = item.get("content")
|
|
if content is None:
|
|
return None
|
|
if isinstance(content, (dict, list)):
|
|
return content
|
|
try:
|
|
return json.loads(content)
|
|
except (json.JSONDecodeError, TypeError):
|
|
_log(f" read_docs({doc_name}): JSON parse failed")
|
|
return None
|
|
return None
|
|
|
|
|
|
def mcp_write(c, path, content, msg_id=20):
|
|
"""write_file로 localdocs에 파일 저장"""
|
|
result = call_tool(c, "write_file", {
|
|
"path": path,
|
|
"content": content,
|
|
"overwrite": True,
|
|
}, msg_id)
|
|
if result and "result" in result:
|
|
_log(f" write_file({path}): OK")
|
|
return True
|
|
_log(f" write_file({path}): FAILED")
|
|
return False
|
|
|
|
|
|
def mcp_list_docs(c, doc_names, msg_id=30):
|
|
"""list_docs로 파일 존재 확인"""
|
|
result = call_tool(c, "list_docs", {"doc_names": doc_names}, msg_id)
|
|
return result
|
|
|
|
|
|
# ═══════════════════════════════════════════════
|
|
# 1. 등급 변환 유틸리티
|
|
# ═══════════════════════════════════════════════
|
|
|
|
def grade_to_korean(grade):
|
|
"""High/Medium/Low → 높음/중간/낮음"""
|
|
return {"High": "높음", "Medium": "중간", "Low": "낮음"}.get(grade, grade or "불명")
|
|
|
|
|
|
def grade_to_urgency(grade):
|
|
"""시효 평가: High→임박, Medium→여유, Low→도과"""
|
|
return {"High": "임박", "Medium": "여유", "Low": "도과"}.get(grade, grade or "불명")
|
|
|
|
|
|
def safe_str(val):
|
|
if val is None:
|
|
return ""
|
|
return str(val)
|
|
|
|
|
|
def list_to_str(lst):
|
|
"""리스트를 괄호 제거, comma separated string"""
|
|
if not lst:
|
|
return ""
|
|
return ", ".join(str(item) for item in lst)
|
|
|
|
|
|
# ═══════════════════════════════════════════════
|
|
# 2. 마크다운 섹션 생성 함수
|
|
# ═══════════════════════════════════════════════
|
|
|
|
def build_section1(claims_eval):
|
|
"""## 1. 사건 개요"""
|
|
overall = claims_eval.get("overall_claim_content", {})
|
|
primary_goal = overall.get("primary_goal", "(목표 미기재)")
|
|
incidents = overall.get("summary_key_incidents", [])
|
|
lines = []
|
|
lines.append("## 1. 사건 개요")
|
|
lines.append(f"* 원고 목표: {primary_goal}")
|
|
lines.append("* 핵심 내용:")
|
|
if isinstance(incidents, list):
|
|
for inc in incidents:
|
|
lines.append(f" - {inc}")
|
|
else:
|
|
lines.append(f" - {safe_str(incidents)}")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build_section2(claims_list):
|
|
"""## 2. 청구권 요약 (가능성 높은 것만 = claims 5점 이상)"""
|
|
lines = []
|
|
lines.append("## 2. 청구권 요약 (가능성 높은 것만 선택)")
|
|
lines.append("")
|
|
lines.append("| 순위 | 청구 ID | 청구권 | 승소 가능성 | 집행 가능성 | 경제성 | 시효 평가 | 총점 |")
|
|
lines.append("|:---:|:---:|------|:---:|:---:|------|:---:|:---:|")
|
|
for rank, cl in enumerate(claims_list, 1):
|
|
ev = cl.get("evaluation", {})
|
|
win = grade_to_korean(ev.get("win_probability", {}).get("grade", ""))
|
|
exe = grade_to_korean(ev.get("execution_feasibility", {}).get("grade", ""))
|
|
econ_g = grade_to_korean(ev.get("economic_value", {}).get("grade", ""))
|
|
econ_r = ev.get("economic_value", {}).get("reason", "")
|
|
econ = f"{econ_g}, {econ_r}" if econ_r else econ_g
|
|
urg = grade_to_urgency(ev.get("statute_of_limitations_urgency", {}).get("grade", ""))
|
|
total = ev.get("total_score", "?")
|
|
lines.append(
|
|
f"| {rank} | {cl['claim_id']} | {cl['claim_title']} "
|
|
f"| {win} | {exe} | {econ} | {urg} | {total} |"
|
|
)
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build_section3(all_claims, parties_data):
|
|
"""## 3. 청구권 분석 — claim_id별 분석 표 stack"""
|
|
lines = []
|
|
lines.append("## 3. 청구권 분석")
|
|
lines.append("")
|
|
for idx, cl in enumerate(all_claims, 1):
|
|
cid = cl.get("claim_id", "?")
|
|
title = cl.get("claim_title", "?")
|
|
relief = cl.get("relief_summary", "")
|
|
cause = cl.get("cause_summary", "")
|
|
fact_ids = list_to_str(cl.get("source_fact_ids", []))
|
|
bo_ids = list_to_str(cl.get("source_bo_ids", []))
|
|
ev_ids = list_to_str(cl.get("key_evidence_indexes", []))
|
|
|
|
# 리스크/점검내용: mapped_parties에 속하는 원고/피고의 reason 수집
|
|
risk_items = []
|
|
mapped = cl.get("mapped_parties", {})
|
|
mapped_pl = mapped.get("plaintiffs", [])
|
|
mapped_df = mapped.get("defendants", [])
|
|
for p in parties_data.get("plaintiffs", []):
|
|
if p.get("name") in mapped_pl and p.get("reason"):
|
|
risk_items.append(p["reason"])
|
|
for d in parties_data.get("defendants", []):
|
|
if d.get("name") in mapped_df and d.get("reason"):
|
|
risk_items.append(d["reason"])
|
|
risk = ", ".join(risk_items) if risk_items else ""
|
|
|
|
lines.append(f"### {idx}. {cid}: {title}")
|
|
lines.append("")
|
|
lines.append("| 항목 | 내용 |")
|
|
lines.append("|------|------|")
|
|
lines.append(f"| 청구취지 | {relief} |")
|
|
lines.append(f"| 청구원인 | {cause} |")
|
|
lines.append(f"| 근거-(법률)행위 | {fact_ids} |")
|
|
lines.append(f"| 사건행위 | {bo_ids} |")
|
|
lines.append(f"| 증거인덱스 | {ev_ids} |")
|
|
lines.append(f"| 리스크/점검내용 | {risk} |")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build_section4(all_claims):
|
|
"""## 4. 당사자 식별 — 청구권별 원고/피고 연결"""
|
|
lines = []
|
|
lines.append("## 4. 당사자 식별")
|
|
lines.append("### 청구권별 원고/피고 연결")
|
|
lines.append("")
|
|
lines.append("| 청구권 | 원고 | 피고 |")
|
|
lines.append("|------|------|------|")
|
|
for cl in all_claims:
|
|
m = cl.get("mapped_parties", {})
|
|
pl = ", ".join(m.get("plaintiffs", []))
|
|
df = ", ".join(m.get("defendants", []))
|
|
lines.append(f"| {cl['claim_id']} | {pl} | {df} |")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build_section5(taxonomy_data, all_claims):
|
|
"""## 5. 사건종류 결정"""
|
|
lines = []
|
|
lines.append("## 5. 사건종류 결정")
|
|
lines.append("")
|
|
lines.append("| 청구권 | 소송대분류 | 분쟁유형 | 사건종류 |")
|
|
lines.append("|------|------|------|------|")
|
|
tax_map = {t["claim_id"]: t for t in taxonomy_data.get("claims_taxonomy", [])}
|
|
for cl in all_claims:
|
|
cid = cl["claim_id"]
|
|
t = tax_map.get(cid, {})
|
|
macro = safe_str(t.get("macro_category"))
|
|
dispute = safe_str(t.get("dispute_type")) if t.get("dispute_type") is not None else ""
|
|
kind = safe_str(t.get("case_kind")) if t.get("case_kind") is not None else ""
|
|
lines.append(f"| {cid} | {macro} | {dispute} | {kind} |")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def build_section6(consolidation_data):
|
|
"""## 6. 청구방식(병합/단독) 제안 — G-01만 사용"""
|
|
lines = []
|
|
lines.append("## 6. 청구방식(병합/단독) 제안")
|
|
lines.append("")
|
|
groups = consolidation_data.get("consolidation_groups", [])
|
|
g01 = None
|
|
for g in groups:
|
|
if g.get("group_id") == "G-01":
|
|
g01 = g
|
|
break
|
|
if g01 is None and groups:
|
|
g01 = groups[0]
|
|
if g01:
|
|
st = g01.get("structure_type", "?")
|
|
ra = g01.get("rationale", "?")
|
|
else:
|
|
st = "(병합 전략 미수립)"
|
|
ra = "(근거 없음)"
|
|
lines.append("| 청구방식 | 근거 |")
|
|
lines.append("|------|------|")
|
|
lines.append(f"| {st} | {ra} |")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
# ═══════════════════════════════════════════════
|
|
# 3. 메인 (MCP localdocs 연동)
|
|
# ═══════════════════════════════════════════════
|
|
|
|
def main():
|
|
OUTPUT_NAME = "청구개요서.md"
|
|
|
|
with httpx.Client(timeout=60) as c:
|
|
# ── 1) MCP 연결 ──
|
|
_log("1) Connecting to localdocs...")
|
|
r = c.post(LOCALDOCS_URL, json={
|
|
"jsonrpc": "2.0", "id": 1, "method": "initialize",
|
|
"params": {
|
|
"protocolVersion": "2025-03-26",
|
|
"capabilities": {},
|
|
"clientInfo": {"name": "claim-overview-gen", "version": "1.0"}
|
|
}
|
|
}, headers=HEADERS)
|
|
sid = r.headers.get("mcp-session-id")
|
|
if sid:
|
|
HEADERS["mcp-session-id"] = sid
|
|
c.post(LOCALDOCS_URL, json={
|
|
"jsonrpc": "2.0", "method": "notifications/initialized"
|
|
}, headers=HEADERS)
|
|
_log(f" Connected (session: {sid})")
|
|
|
|
# ── 2) Preflight: 파일 존재 확인 ──
|
|
_log("\n2) Preflight: checking files...")
|
|
mcp_list_docs(c, [
|
|
"stage2_1_claims_evaluated.json",
|
|
"stage2_2_claims_taxonomy.json",
|
|
"stage2_3_consolidation_strategy.json"
|
|
], 5)
|
|
|
|
# ── 3) 데이터 로드 (MCP read_docs) ──
|
|
_log("\n3) Loading files via MCP read_docs...")
|
|
claims_eval = mcp_read_json(c, "stage2_1_claims_evaluated.json", 10)
|
|
taxonomy_data = mcp_read_json(c, "stage2_2_claims_taxonomy.json", 11)
|
|
consolidation_data = mcp_read_json(c, "stage2_3_consolidation_strategy.json", 12)
|
|
|
|
# 필수 파일 검증 + 1회 재시도
|
|
required = {
|
|
"stage2_1_claims_evaluated.json": claims_eval,
|
|
"stage2_2_claims_taxonomy.json": taxonomy_data,
|
|
"stage2_3_consolidation_strategy.json": consolidation_data,
|
|
}
|
|
missing = [n for n, d in required.items() if d is None]
|
|
if missing:
|
|
_log(f" WARN: Missing: {missing}, retrying...")
|
|
for fname in missing:
|
|
data = mcp_read_json(c, fname, 15)
|
|
if data is not None:
|
|
required[fname] = data
|
|
missing = [n for n, d in required.items() if d is None]
|
|
if missing:
|
|
_log(f" ERROR: Still missing: {missing}")
|
|
print(f"ERROR: Missing required files: {missing}")
|
|
sys.exit(1)
|
|
|
|
claims_eval = required["stage2_1_claims_evaluated.json"]
|
|
taxonomy_data = required["stage2_2_claims_taxonomy.json"]
|
|
consolidation_data = required["stage2_3_consolidation_strategy.json"]
|
|
|
|
# ── 4) 데이터 준비 ──
|
|
claims_list = claims_eval.get("claims", [])
|
|
other_claims = claims_eval.get("other_claims", [])
|
|
all_claims = claims_list + other_claims
|
|
parties_data = claims_eval.get("parties", {})
|
|
|
|
_log(f" Claims={len(claims_list)}, Other={len(other_claims)}, "
|
|
f"Tax={len(taxonomy_data.get('claims_taxonomy', []))}, "
|
|
f"Groups={len(consolidation_data.get('consolidation_groups', []))}")
|
|
|
|
# ── 5) 마크다운 생성 ──
|
|
_log("\n4) Generating markdown...")
|
|
md_parts = []
|
|
md_parts.append("# 청구개요서\n")
|
|
md_parts.append(build_section1(claims_eval))
|
|
md_parts.append(build_section2(claims_list))
|
|
md_parts.append(build_section3(all_claims, parties_data))
|
|
md_parts.append(build_section4(all_claims))
|
|
md_parts.append(build_section5(taxonomy_data, all_claims))
|
|
md_parts.append(build_section6(consolidation_data))
|
|
|
|
md_content = "\n".join(md_parts)
|
|
_log(f" Markdown: {len(md_content)} bytes")
|
|
|
|
# ── 6) localdocs에 저장 ──
|
|
_log(f"\n5) Saving: {OUTPUT_NAME}")
|
|
ok = mcp_write(c, OUTPUT_NAME, md_content, 20)
|
|
if not ok:
|
|
_log(" Retrying write...")
|
|
mcp_write(c, OUTPUT_NAME, md_content, 21)
|
|
|
|
# ── 7) 파일 존재 검증 ──
|
|
_log(f"\n6) Verifying: {OUTPUT_NAME}")
|
|
verify = mcp_list_docs(c, [OUTPUT_NAME], 25)
|
|
if not (verify and "result" in verify):
|
|
_log(" WARN: Verification unclear, retry write...")
|
|
mcp_write(c, OUTPUT_NAME, md_content, 26)
|
|
mcp_list_docs(c, [OUTPUT_NAME], 27)
|
|
|
|
# ── 8) /app/output 저장 (code-executor 반환용) ──
|
|
output_path = os.path.join("/app/output", OUTPUT_NAME)
|
|
os.makedirs("/app/output", exist_ok=True)
|
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
f.write(md_content)
|
|
_log(f"7) Saved to {output_path} ({len(md_content)} bytes)")
|
|
|
|
print(f"청구개요서 생성 완료: {len(md_content)} bytes, "
|
|
f"Claims={len(claims_list)}, OtherClaims={len(other_claims)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
task_procedure:
|
|
IN:
|
|
nexts: ["Task_A"]
|
|
wait_until: []
|
|
Task_A:
|
|
nexts: ["Task_B"]
|
|
wait_until: ["IN"]
|
|
Task_B:
|
|
nexts: ["Task_C"]
|
|
wait_until: ["Task_A"]
|
|
Task_C:
|
|
nexts: ["Task_D"]
|
|
wait_until: ["Task_B"]
|
|
Task_D:
|
|
nexts: ["OUT"]
|
|
wait_until: ["Task_C"]
|
|
OUT:
|
|
nexts: []
|
|
wait_until: ["Task_D"]
|
|
|
|
prevs: [stage1_사건개요파악]
|
|
nexts: [stage_3_요건사실파악]
|
|
|
|
- name: stage3_1_청구요건사실검색쿼리생성
|
|
description: 청구권별로 요건사실 검색 쿼리 생성
|
|
llm_provider: openai
|
|
llm_model: gpt-4o-2024-08-06
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
code-executor:
|
|
type: streamable-http
|
|
url: https://code-executor.mcp.eroomai.com/mcp
|
|
description: Run scripts of programming languages
|
|
headers:
|
|
Authorization: Bearer rR8OXqWrVZA1gFEo8oWfBkw2XgpWoGrrspw5ObsxTCM=
|
|
|
|
tasks:
|
|
- task_name: Task_A
|
|
llm_provider: anthropic
|
|
llm_model: claude-opus-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
# Checklist
|
|
[ ] 1. Preflight: `list_docs` 사용해서 stage2_1_claims_evaluated.json, stage2_2_claims_taxonomy.json, Default_Agent/DB_legally_required_facts_description.md 확인하고, `read_docs` 사용해서 stage2_1_claims_evaluated.json, stage2_2_claims_taxonomy.json, DB_legally_required_facts_description.md 읽는다.
|
|
[ ] 2. `write_file` 사용해서 queries_legal_facts_search.json 생성한다.
|
|
[ ] 3. `list_docs` 사용해서 queries_legal_facts_search.json의 존재를 확인한다.
|
|
[ ] 4. 작업 종료(terminate)
|
|
---
|
|
|
|
## 0. 역할 · 범위 · 산출물 (HARD)
|
|
|
|
당신은 **대한민국 민사소송(원고대리) 실무형 변호사**이자 **Weaviate hybrid retrieval 설계자**다.
|
|
입력된 파일들(청구권 요약·사건종류 분류·DB 매핑표)을 근거로, **요건사실(legally required facts)**을 검색하기 위한 **Hybrid Search “쿼리 계획(JSON)”**만을 생성한다.
|
|
|
|
* 당신은 **DB를 실제로 조회/실행하지 않는다.**
|
|
* 당신이 생성한 출력 JSON은 **다음 단계에서 “중간 어댑터(adapter)”에 의해 Weaviate 실행 요청 스펙으로 변환되어 적용**된다.
|
|
따라서 본 출력은 **내부 표준 스키마(아래 JSON Schema)**를 준수해야 하며, Weaviate API 파라미터명/형식과의 1:1 동일성은 **어댑터 책임**이다(단, 본 프롬프트가 강제하는 타입·기본값·정합성은 반드시 지킨다).
|
|
|
|
## 1. 불가침 원칙 (Non-negotiables, HARD)
|
|
|
|
1. **Hallucination 금지:** 입력 파일에 없는 사건 고유 사실을 새로 만들지 않는다.
|
|
2. 불명확하면 **"UNKNOWN" / null / "[증거공백]"** 중 적절한 값으로 명시한다(단, 스키마가 string을 요구하면 null 대신 "UNKNOWN"을 사용).
|
|
3. 입력 원문 **대량/장문 복사 금지**(필요 최소한의 “법률 개념어”만 추출).
|
|
4. **필수 입력 누락/빈 파일/파싱 불가 시 즉시 중단(fail-fast)**한다.
|
|
|
|
* 이 경우 **출력 파일(queries_legal_facts_search.json)을 생성하지 않는다.**
|
|
* 누락/오류 항목을 **채팅으로만** 간단히 보고한다(중간 JSON 덤프 금지).
|
|
5. **중간 결과(JSON 덤프, DB 결과 덤프)를 채팅에 출력하지 말 것.**
|
|
|
|
> 본 프롬프트는 “필수 입력 파싱 불가 시 즉시 중단”을 채택한다.
|
|
> (에러 시 스킵하고 진행하는 정책은 사용하지 않는다.)
|
|
|
|
## 2. 입출력 파일 (HARD)
|
|
|
|
### 2.1 IN (필수)
|
|
|
|
* `stage2_1_claims_evaluated.json`
|
|
* `stage2_2_claims_taxonomy.json`
|
|
* `Default_Agent/DB_legally_required_facts_description.md` ← **Default_Agent 폴더에 존재함(필수 입력)**
|
|
|
|
### 2.2 OUT (필수)
|
|
|
|
* `queries_legal_facts_search.json`
|
|
|
|
## 3. 입력 데이터에서 사용할 필드 (HARD)
|
|
|
|
### 3.1 Stage 2.1 (stage2_1_claims_evaluated.json)
|
|
|
|
* `claims[]` 및 (존재 시) `other_claims[]`의 각 원소에서:
|
|
|
|
* `claim_id` (string)
|
|
* `claim_title` (string)
|
|
* `relief_summary` (string)
|
|
* `cause_summary` (string)
|
|
|
|
> 청구권의 처리 순서는 **claims 배열 순서 → other_claims 배열 순서**를 그대로 따른다.
|
|
|
|
### 3.2 Stage 2.2 (stage2_2_claims_taxonomy.json)
|
|
|
|
* `claims_taxonomy[]`에서 claim_id별:
|
|
|
|
* `case_kind` (string|null)
|
|
* `macro_category` (string|null)
|
|
|
|
### 3.3 DB 매핑표 (Default_Agent/DB_legally_required_facts_description.md)
|
|
|
|
표의 컬럼:
|
|
|
|
* `사건 종류`
|
|
* `Weaviate DB`
|
|
* `사건 종류 유사어`
|
|
|
|
## 4. 사건종류 결정 및 DB 매핑 규칙 (HARD)
|
|
|
|
### 4.1 사건종류(사건종류 string) 결정
|
|
|
|
각 claim_id에 대해 다음 우선순위로 `사건종류`를 결정한다.
|
|
|
|
1. stage2_2의 `case_kind`가 null이 아니고 비어있지 않으면 → 그 값을 사용
|
|
2. 그렇지 않으면 stage2_2의 `macro_category`가 null이 아니고 비어있지 않으면 → 그 값을 사용
|
|
3. 둘 다 없으면 → `"UNKNOWN"`
|
|
|
|
### 4.2 DB 매핑 (mapped_collection, mapped_tenant, tenant_status)
|
|
|
|
`Default_Agent/DB_legally_required_facts_description.md` 표를 기준으로 다음 절차를 **결정론적으로** 수행한다.
|
|
|
|
1. **Exact match 1차:**
|
|
`사건종류` == 표의 `사건 종류` 셀과 완전 일치하면 그 row를 채택한다.
|
|
|
|
2. **유사어 기반 2차(결정론):**
|
|
1차가 실패하면, 해당 표의 `사건 종류 유사어`(쉼표로 구분된 목록) 중 하나가 `사건종류`와 완전 일치하면 그 row를 채택한다.
|
|
|
|
3. **부분 포함 3차(결정론):**
|
|
1·2차가 실패하면,
|
|
|
|
* `사건종류`가 `사건 종류` 셀 문자열에 포함되거나,
|
|
* `사건 종류` 셀이 `사건종류` 문자열에 포함되는 경우
|
|
가장 먼저 매칭되는 row(표의 위에서 아래 순서)를 채택한다.
|
|
|
|
4. **매핑 성공 시:**
|
|
|
|
* `Weaviate DB` 셀에서 `[Collection: X] - [Tenant: Y]`를 파싱하여
|
|
|
|
* `mapped_collection = X`
|
|
* `mapped_tenant = Y`
|
|
* `tenant_status = "CONFIRMED"`
|
|
|
|
5. **매핑 실패 시:**
|
|
|
|
* `mapped_collection = "UNKNOWN"`
|
|
* `mapped_tenant = "UNKNOWN"`
|
|
* `tenant_status = "UNCONFIRMED"`
|
|
* `validation_warnings[]`에 경고 1건을 추가한다.
|
|
|
|
## 5. 쿼리 생성 규칙 (semantic unit ≤ 6, HARD)
|
|
|
|
### 5.1 노이즈 차단(사건 고유 사실 금지, HARD)
|
|
|
|
`search_params.query`(= query_text)는 다음 정보를 포함하면 안 된다.
|
|
|
|
* 인명/법인명/기관명
|
|
* 금액/이자율/채권액 등 수치
|
|
* 일자/기간
|
|
* 주소/지번/계좌/부동산 특정표지
|
|
* 사건 고유의 개별 사실관계(예: 특정 부동산 명칭)
|
|
|
|
- 핵심 키워드로 허용되는 것은 **법률 개념어** 및 **요건사실/항변/입증책임 구조를 지시하는 일반어**에 한정한다.
|
|
|
|
### 5.2 앵커 프리픽스(고정, HARD)
|
|
|
|
모든 쿼리 문자열은 반드시 다음 3개 앵커로 시작한다(고정):
|
|
|
|
* `"요건사실 항변 입증책임"`
|
|
|
|
이를 **anchor_units=3**으로 간주한다.
|
|
|
|
### 5.3 후보 개념어 풀 구성(최대 10개, HARD)
|
|
|
|
- 각 “claim_id”마다 개념어 후보 풀을 만든다.
|
|
- 개념어 후보에는 `법률 개념어`, `요건사실/항변/입증책임 구조를 지시하는 일반어`들을 포함한다.
|
|
- 개념어 후보 풀의 입력 텍스트 원천(허용 범위):
|
|
* (A) `사건종류`(case_kind 또는 macro_category로 결정된 값) 유사어
|
|
* (B) claim_id별
|
|
* `claim_title`, `relief_summary`, `cause_summary`
|
|
|
|
- 후보 풀 생성 규칙(결정론):
|
|
|
|
1. 위 텍스트를 **좌→우(문장 순서)**로 훑으면서, "법률 개념어나 요건사실/항변/입증책임 구조를 지시하는 일반어"를 포함하는 짧은 어구(phrase)**를 추출한다.
|
|
2. 추출 시 **노이즈 차단 규칙(5.1)**을 위반하는 토큰은 즉시 제외한다.
|
|
3. 중복 제거는 아래 “단순 표준화”만 사용한다(추론 기반 동의어 확장 금지):
|
|
* 공백/구두점 차이만 있는 동일 표현은 1개로 합친다.
|
|
* 예시: "대여금 채권", "대여금채권", "대여금, 채권" → 모두 "대여금 채권"으로 표준화하여 1개 후보로 유지한다.
|
|
4. 후보 풀은 **최대 10개**까지 유지하고, 10개를 채우면 즉시 중단한다.
|
|
|
|
### 5.4 case_units 선택(최대 4개, HARD)
|
|
|
|
* `case_units`는 후보 풀에서 **최대 4개**만 선택한다.
|
|
* 총 semantic unit은 `anchor(3) + case_units(k)`로 계산하며, **k ≤ 4**을 지킨다.
|
|
|
|
선택 우선순위(결정론, tie-break 포함):
|
|
|
|
1. `사건종류`(문자열)에서 직접 추출된 개념어를 우선한다.
|
|
2. 남는 슬롯은 대표 claim의 `claim_title → relief_summary → cause_summary` 순으로,
|
|
**더 먼저 등장**한 개념어를 우선한다.
|
|
3. 여전히 동률이면 **가나다(사전순)**로 tie-break.
|
|
|
|
### 5.5 query_text 구성(HARD)
|
|
|
|
* `query_text = "요건사실 항변 입증책임" + " " + " ".join(case_units)`
|
|
* 단, query_text의 길이가 **100자 초과**이면:
|
|
|
|
* `case_units`의 **마지막 항목부터** 제거하여 100자 이하로 맞춘다.
|
|
* 이때도 `case_units`가 1개 이상 유지되어야 한다.
|
|
|
|
만약 위 규칙으로도 `case_units`를 1개 이상 유지하지 못하면:
|
|
* 해당 claim_id에 대해 쿼리를 생성하지 않는다.
|
|
* `mapped_collection`과 `mapped_tenant`가 "UNKNOWN"이 아니더라도 쿼리를 생성하지 않는다.
|
|
* `validation_warnings[]`에 경고 1건을 추가한다.
|
|
|
|
## 6. query_id 부여 (운영 친화, 결정론)
|
|
|
|
### 6.1 규칙
|
|
|
|
"claim_id"당 1개 query**를 만든다.
|
|
|
|
### 6.2 query_id 부여
|
|
|
|
* "claim_id" "오름차순"으로 정렬한다.
|
|
* 정렬된 순서대로 `Q-001`, `Q-002`, … 를 부여한다.
|
|
|
|
## 7. Hybrid Search 파라미터 (타입 강제, HARD)
|
|
|
|
각 query는 `search_params`에 아래 키를 **모두 포함**해야 하며, 타입을 강제한다.
|
|
|
|
### 7.1 search_params 필수 키(타입 강제)
|
|
|
|
* `collection_name`: string (=`mapped_collection`)
|
|
* `tenant`: string (=`mapped_tenant`)
|
|
* `query`: string (=`query_text`)
|
|
* `alpha`: number(float) (문자열 금지)
|
|
* `limit`: integer (문자열 금지)
|
|
* `query_properties`: array[string] (문자열 JSON 금지)
|
|
* `fusion_type`: string (**항상 "rankedFusion" 사용**)
|
|
* `bm25_operator`: string ("or" 또는 "and")
|
|
* `bm25_minimum_match`: integer (문자열 금지)
|
|
|
|
### 7.2 기본값(HARD)
|
|
|
|
* `fusion_type = "rankedFusion"` (고정)
|
|
* `limit = 8`
|
|
* `query_properties = ["content"]`
|
|
* `bm25_operator = "or"` (기본)
|
|
|
|
### 7.3 BM25 minimum match 강제(앵커 3단어 문제 해결, HARD)
|
|
|
|
* anchor_units = 3
|
|
* k = len(case_units) (1~4)
|
|
* `bm25_minimum_match = anchor_units + min(k, 2)`
|
|
|
|
* k=1 → 4
|
|
* k=2 → 5
|
|
* k=3 → 5
|
|
|
|
### 7.4 alpha 결정 규칙(HARD, 결정론)
|
|
|
|
사건종류 문자열에 아래 키워드가 포함되면 해당 alpha를 사용한다.
|
|
|
|
* "사해행위취소" 포함 → `alpha = 0.45`
|
|
* "구상금" 포함 → `alpha = 0.35`
|
|
* "대여금" 또는 "보증" 포함 → `alpha = 0.25`
|
|
* 그 외 → `alpha = 0.35`
|
|
|
|
## 8. 출력 JSON 구성 (스키마 준수, HARD)
|
|
|
|
### 8.1 최상위 구조
|
|
|
|
출력은 반드시 아래 3개 최상위 키를 포함한다.
|
|
|
|
* `claims`: array
|
|
* `queries`: array
|
|
* `query_summary`: object
|
|
(선택) `validation_warnings`: array[string]
|
|
|
|
### 8.2 claims 배열
|
|
|
|
입력의 모든 청구(3.1의 순서)를 대상으로 각 원소를 생성한다.
|
|
각 원소는 반드시 다음 키를 포함한다.
|
|
|
|
* `claim_id` (string)
|
|
* `claim_title` (string)
|
|
* `사건종류` (string; 미확보 시 "UNKNOWN")
|
|
* `mapped_collection` (string; 실패 시 "UNKNOWN")
|
|
* `mapped_tenant` (string; 실패 시 "UNKNOWN")
|
|
* `tenant_status` ("CONFIRMED"|"UNCONFIRMED")
|
|
|
|
### 8.3 queries 배열
|
|
|
|
각 "claim_id"마다 1개 원소를 생성한다. 단, 아래 경우에는 생성하지 않는다.
|
|
|
|
* DB 매핑 실패(tenant_status="UNCONFIRMED")로 collection/tenant가 "UNKNOWN"인 경우
|
|
* case_units를 1개 이상 확보하지 못해 query_text를 만들 수 없는 경우
|
|
|
|
각 queries 원소는 반드시 다음 키를 포함한다.
|
|
|
|
* `query_id` ("Q-001"…)
|
|
* `applicable_claim_id` (array[string]) ← 그룹에 포함된 claim_id 전부(중복 없음)
|
|
* `사건종류` (string)
|
|
* `purpose` = "요건사실 검색" (고정)
|
|
* `search_params` (7.1의 타입 강제 준수)
|
|
|
|
### 8.4 query_summary
|
|
|
|
아래 값을 **산출 결과에 맞게 정확히 계산**한다.
|
|
|
|
* `total_queries` = queries 배열 길이
|
|
* `distinct_사건종류_count` = queries에 포함된 사건종류의 distinct 개수
|
|
* `total_claims_covered` = 모든 queries의 applicable_claim_ids의 합집합 크기
|
|
|
|
### 8.5 validation_warnings(선택)
|
|
|
|
경고는 **문장(string) 1줄**로 간단히 기록한다.
|
|
예:
|
|
|
|
* "VALIDATION WARNING: claim_id=C-003 사건종류 매핑 실패로 query 미생성(tenant UNCONFIRMED)"
|
|
* "VALIDATION WARNING: 사건종류=UNKNOWN 로 query 미생성"
|
|
|
|
## 9. 출력 JSON Schema (HARD, 반드시 준수)
|
|
|
|
아래 JSON Schema를 **그대로** 만족하는 결과만을 생성한다(추가 키 금지).
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://example.com/schemas/queries_legal_facts_search.schema.json",
|
|
"title": "queries_legal_facts_search.json",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["claims", "queries", "query_summary"],
|
|
"properties": {
|
|
"claims": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": { "$ref": "#/$defs/ClaimMapping" }
|
|
},
|
|
"queries": {
|
|
"type": "array",
|
|
"minItems": 0,
|
|
"items": { "$ref": "#/$defs/QueryPlan" }
|
|
},
|
|
"query_summary": { "$ref": "#/$defs/QuerySummary" },
|
|
"validation_warnings": {
|
|
"type": "array",
|
|
"items": { "type": "string" }
|
|
}
|
|
},
|
|
"$defs": {
|
|
"ClaimMapping": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"claim_id",
|
|
"claim_title",
|
|
"사건종류",
|
|
"mapped_collection",
|
|
"mapped_tenant",
|
|
"tenant_status"
|
|
],
|
|
"properties": {
|
|
"claim_id": { "type": "string" },
|
|
"claim_title": { "type": "string" },
|
|
"사건종류": { "type": "string" },
|
|
"mapped_collection": { "type": "string" },
|
|
"mapped_tenant": { "type": "string" },
|
|
"tenant_status": {
|
|
"type": "string",
|
|
"enum": ["CONFIRMED", "UNCONFIRMED"]
|
|
}
|
|
}
|
|
},
|
|
"QueryPlan": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"query_id",
|
|
"applicable_claim_ids",
|
|
"사건종류",
|
|
"purpose",
|
|
"search_params"
|
|
],
|
|
"properties": {
|
|
"query_id": {
|
|
"type": "string",
|
|
"pattern": "^Q-\\d{3}$"
|
|
},
|
|
"applicable_claim_id": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": { "type": "string" },
|
|
"uniqueItems": true
|
|
},
|
|
"사건종류": { "type": "string" },
|
|
"purpose": { "type": "string", "const": "요건사실 검색" },
|
|
"search_params": { "$ref": "#/$defs/SearchParams" }
|
|
}
|
|
},
|
|
"SearchParams": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"collection_name",
|
|
"tenant",
|
|
"query",
|
|
"alpha",
|
|
"limit",
|
|
"query_properties",
|
|
"fusion_type",
|
|
"bm25_operator",
|
|
"bm25_minimum_match"
|
|
],
|
|
"properties": {
|
|
"collection_name": { "type": "string" },
|
|
"tenant": { "type": "string" },
|
|
"query": { "type": "string" },
|
|
"alpha": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
"limit": { "type": "integer", "minimum": 1 },
|
|
"query_properties": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"items": { "type": "string" }
|
|
},
|
|
"fusion_type": { "type": "string" },
|
|
"bm25_operator": { "type": "string", "enum": ["or", "and"] },
|
|
"bm25_minimum_match": { "type": "integer", "minimum": 1 }
|
|
}
|
|
},
|
|
"QuerySummary": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"total_queries",
|
|
"distinct_사건종류_count",
|
|
"total_claims_covered"
|
|
],
|
|
"properties": {
|
|
"total_queries": { "type": "integer", "minimum": 0 },
|
|
"distinct_사건종류_count": { "type": "integer", "minimum": 0 },
|
|
"total_claims_covered": { "type": "integer", "minimum": 0 }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
task_procedure:
|
|
IN:
|
|
nexts: ["Task_A"]
|
|
wait_until: []
|
|
Task_A:
|
|
nexts: ["OUT"]
|
|
wait_until: ["IN"]
|
|
OUT:
|
|
nexts: []
|
|
wait_until: ["Task_A"]
|
|
|
|
prevs: [stage2_청구개요서작성]
|
|
nexts: [stage_3_2_요건사실검색프롬프트생성]
|
|
|
|
- name: stage3_2_요건사실검색_문서작성
|
|
description: 청구권별로 요건사실 검색 및 요건사실 문서 작성
|
|
tools:
|
|
mcpServers:
|
|
localdocs:
|
|
type: streamable-http
|
|
url: "http://mcp-localdocs:8012/mcp"
|
|
description: Get the content of local documents
|
|
weaviate:
|
|
type: streamable-http
|
|
url: "https://weaviate.eroomai.com/mcp"
|
|
description: Hybrid search on Weaviate vector DB
|
|
code-executor:
|
|
type: streamable-http
|
|
url: https://code-executor.mcp.eroomai.com/mcp
|
|
description: Run scripts of programming languages
|
|
headers:
|
|
Authorization: Bearer rR8OXqWrVZA1gFEo8oWfBkw2XgpWoGrrspw5ObsxTCM=
|
|
|
|
prevs: [stage3_1_청구요건사실검색쿼리생성]
|
|
nexts: [stage_4_청구항변반박전략]
|
|
|
|
map_reduce:
|
|
max_concurrency: 8
|
|
|
|
# ── Source: queries_legal_facts_search.json의 queries 배열 ──
|
|
source:
|
|
mcp:
|
|
server: localdocs
|
|
tool_name: read_docs
|
|
parameters: { doc_names: ["queries_legal_facts_search.json"] }
|
|
key: ["queries"]
|
|
|
|
# ── Shared Context: claims 배열 (reduce에서 claim_title 참조용) ──
|
|
shared_context:
|
|
- name: source_json
|
|
mcp:
|
|
server: localdocs
|
|
tool_name: read_docs
|
|
parameters: { doc_names: ["queries_legal_facts_search.json"] }
|
|
|
|
# ── Map: query별 Weaviate 검색 + 결과 요약 ──
|
|
map:
|
|
tasks:
|
|
# ── Step 1: Weaviate Hybrid Search (Direct MCP) ──
|
|
- task_name: search_weaviate
|
|
mcp: weaviate
|
|
tool_name: search_hybrid
|
|
parameters:
|
|
collection_name: "{{item.search_params.collection_name}}"
|
|
tenant: "{{item.search_params.tenant}}"
|
|
query: "{{item.search_params.query}}"
|
|
alpha: "{{item.search_params.alpha}}"
|
|
limit: "{{item.search_params.limit}}"
|
|
query_properties: "{{item.search_params.query_properties}}"
|
|
fusion_type: "{{item.search_params.fusion_type}}"
|
|
bm25_operator: "{{item.search_params.bm25_operator}}"
|
|
bm25_minimum_match: "{{item.search_params.bm25_minimum_match}}"
|
|
|
|
# ── Step 2: 검색 결과 요약 (LLM) ──
|
|
- task_name: summarize_search
|
|
llm_provider: anthropic
|
|
llm_model: claude-haiku-4-5
|
|
prompts:
|
|
- role: user
|
|
content: |
|
|
# Task
|
|
|
|
아래 Weaviate 검색 결과를 분석하여, 해당 사건종류의 **요건사실(legally required facts)** 관점에서 핵심 포인트를 정리하라.
|
|
|
|
# 쿼리 정보
|
|
- query_id: {{item.query_id}}
|
|
- 사건종류: {{item.사건종류}}
|
|
- 적용 claim_ids: {{item.applicable_claim_ids}}
|
|
- 검색 파라미터:
|
|
- collection: {{item.search_params.collection_name}}
|
|
- tenant: {{item.search_params.tenant}}
|
|
- query: {{item.search_params.query}}
|
|
- alpha: {{item.search_params.alpha}}
|
|
- limit: {{item.search_params.limit}}
|
|
- bm25_operator: {{item.search_params.bm25_operator}}
|
|
- bm25_minimum_match: {{item.search_params.bm25_minimum_match}}
|
|
|
|
# Weaviate 검색 결과
|
|
|
|
{{prev.search_weaviate}}
|
|
|
|
# 출력 규칙 (STRICT JSON)
|
|
|
|
아래 JSON 형식으로만 출력하라. 마크다운 펜스, 코멘트, 설명 일체 금지.
|
|
|
|
{
|
|
"query_id": "<query_id>",
|
|
"사건종류": "<사건종류>",
|
|
"applicable_claim_ids": [<claim_ids>],
|
|
"search_quality": "good|partial|poor",
|
|
"key_points": [
|
|
"<요건사실 핵심 포인트 1>",
|
|
"<요건사실 핵심 포인트 2>",
|
|
"..."
|
|
],
|
|
"hits": [
|
|
{
|
|
"weaviate_ref": "<document id or reference>",
|
|
"score": <float>,
|
|
"excerpt": "<240자 이내 발췌, 줄바꿈 제거>"
|
|
}
|
|
],
|
|
"missing_elements": ["<누락된 요건사실 요소>"]
|
|
}
|
|
|
|
## key_points 작성 규칙
|
|
- 3~7개의 bullet로 작성
|
|
- 각 포인트는 검색 hit의 excerpt에 근거하여 작성 (근거 없는 창작 금지)
|
|
- 요건사실(성립요건) 중심으로 정리
|
|
- 법률 개념어 사용, 사건 고유 사실 배제
|
|
|
|
## hits 작성 규칙
|
|
- 최대 6개까지만 포함 (관련성 높은 순)
|
|
- excerpt는 240자 이내, 줄바꿈/탭 제거, 공백 정리
|
|
- score는 Weaviate 반환 점수 그대로 사용
|
|
|
|
## search_quality 판정
|
|
- good: 핵심 요건사실 요소 대부분 커버 (4개 이상 key_points)
|
|
- partial: 일부 요건사실만 커버 (2~3개 key_points)
|
|
- poor: 관련 결과 거의 없음 (1개 이하 key_points)
|
|
|
|
## missing_elements 작성 규칙
|
|
- search_quality가 "good"이 아닌 경우에만 작성
|
|
- 검색으로 확인되지 않은 요건사실 요소를 나열
|
|
- 예: ["무자력 요건", "사해의사 입증"]
|
|
|
|
# ── Reduce: 전체 결과 조립 → MD 문서 생성 ──
|
|
reduce:
|
|
# ── Step 1: Python으로 MD 문서 조립 ──
|
|
- task_name: assemble_document
|
|
mcp: code-executor
|
|
tool_name: run_code
|
|
parameters:
|
|
language: python
|
|
timeout: 120
|
|
network: "agent-network"
|
|
code: |
|
|
import json, base64
|
|
from datetime import datetime
|
|
|
|
# ── 1. map_results 디코딩 ──
|
|
raw = base64.b64decode('{{map_results_b64}}').decode('utf-8')
|
|
map_results = json.loads(raw)
|
|
|
|
# ── 2. shared_context에서 claims 추출 ──
|
|
source_raw = '''{{shared.source_json}}'''
|
|
try:
|
|
source_data = json.loads(source_raw)
|
|
claims_list = source_data.get("claims", [])
|
|
query_summary_src = source_data.get("query_summary", {})
|
|
validation_warnings = source_data.get("validation_warnings", [])
|
|
except Exception:
|
|
claims_list = []
|
|
query_summary_src = {}
|
|
validation_warnings = []
|
|
|
|
# claim_id → claim_title 매핑
|
|
claim_title_map = {c["claim_id"]: c.get("claim_title", "") for c in claims_list}
|
|
|
|
# ── 3. map 결과 파싱 ──
|
|
query_sections = []
|
|
errors = []
|
|
total_queries = len(map_results)
|
|
all_claim_ids = set()
|
|
case_types = set()
|
|
|
|
for item_result in map_results:
|
|
idx = item_result.get("item_index", "?")
|
|
item = item_result.get("item", {})
|
|
tr = item_result.get("task_results", {})
|
|
|
|
query_id = item.get("query_id", f"Q-{idx}")
|
|
case_type = item.get("사건종류", "UNKNOWN")
|
|
claim_ids = item.get("applicable_claim_ids", [])
|
|
sp = item.get("search_params", {})
|
|
|
|
all_claim_ids.update(claim_ids)
|
|
case_types.add(case_type)
|
|
|
|
# summarize_search 결과 파싱
|
|
summary_str = tr.get("summarize_search", "")
|
|
summary = None
|
|
if summary_str and not str(summary_str).startswith("ERROR"):
|
|
cleaned = str(summary_str).strip()
|
|
if cleaned.startswith("```"):
|
|
lines = cleaned.split("\n")
|
|
lines = [l for l in lines if not l.strip().startswith("```")]
|
|
cleaned = "\n".join(lines)
|
|
try:
|
|
summary = json.loads(cleaned)
|
|
except json.JSONDecodeError as e:
|
|
errors.append(f"item {idx} ({query_id}) summary parse error: {e}")
|
|
else:
|
|
errors.append(f"item {idx} ({query_id}) summarize_search: {str(summary_str)[:200]}")
|
|
|
|
# 섹션 데이터 구성
|
|
query_sections.append({
|
|
"query_id": query_id,
|
|
"case_type": case_type,
|
|
"claim_ids": claim_ids,
|
|
"search_params": sp,
|
|
"summary": summary,
|
|
})
|
|
|
|
# query_id 순서로 정렬
|
|
query_sections.sort(key=lambda x: x["query_id"])
|
|
|
|
# ── 4. Markdown 문서 조립 ──
|
|
lines = []
|
|
lines.append("# 요건사실 검색 결과 (legally_required_facts_information)")
|
|
lines.append("")
|
|
lines.append("## 문서 메타")
|
|
lines.append(f"- 입력 파일: queries_legal_facts_search.json")
|
|
lines.append(f"- 총 query 수: {total_queries}")
|
|
lines.append(f"- 총 커버 claim 수: {len(all_claim_ids)}")
|
|
lines.append(f"- distinct 사건종류 수: {len(case_types)}")
|
|
lines.append(f"- 생성일시: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
|
|
lines.append("")
|
|
|
|
if validation_warnings:
|
|
lines.append("## Validation Warnings (쿼리 생성 단계)")
|
|
for w in validation_warnings:
|
|
lines.append(f"- {w}")
|
|
lines.append("")
|
|
|
|
lines.append("---")
|
|
lines.append("")
|
|
|
|
for section in query_sections:
|
|
qid = section["query_id"]
|
|
ct = section["case_type"]
|
|
cids = section["claim_ids"]
|
|
sp = section["search_params"]
|
|
summary = section["summary"]
|
|
|
|
# 헤더
|
|
claim_titles = [f"{cid} ({claim_title_map.get(cid, '')})" for cid in cids]
|
|
lines.append(f"## {qid} — {ct}")
|
|
lines.append("")
|
|
lines.append(f"- **적용 claim_ids**: {', '.join(claim_titles)}")
|
|
lines.append(f"- **Target**: {sp.get('collection_name', 'N/A')} / {sp.get('tenant', 'N/A')}")
|
|
lines.append(f"- **검색 파라미터**: alpha={sp.get('alpha')}, limit={sp.get('limit')}, bm25_operator={sp.get('bm25_operator')}, bm25_minimum_match={sp.get('bm25_minimum_match')}, query_properties={sp.get('query_properties')}")
|
|
lines.append("")
|
|
|
|
if summary:
|
|
quality = summary.get("search_quality", "unknown")
|
|
lines.append(f"### 검색 품질: {quality}")
|
|
lines.append("")
|
|
|
|
# 요건사실 핵심 포인트
|
|
key_points = summary.get("key_points", [])
|
|
if key_points:
|
|
lines.append("### 요건사실(성립요건) 핵심 포인트")
|
|
for kp in key_points:
|
|
lines.append(f"- {kp}")
|
|
lines.append("")
|
|
|
|
# 근거 hit 목록
|
|
hits = summary.get("hits", [])
|
|
if hits:
|
|
lines.append("### 근거 Hit 목록")
|
|
for h in hits[:6]:
|
|
ref = h.get("weaviate_ref", "N/A")
|
|
score = h.get("score", 0)
|
|
excerpt = h.get("excerpt", "")[:240]
|
|
lines.append(f"- [{ref}] (score={score}) {excerpt}")
|
|
lines.append("")
|
|
|
|
# 검색 품질 경고
|
|
missing = summary.get("missing_elements", [])
|
|
if quality != "good" and missing:
|
|
lines.append("### 검색 품질 경고")
|
|
lines.append(f"- 검색 품질: {quality}")
|
|
lines.append(f"- 누락된 요건사실 요소: {', '.join(missing)}")
|
|
lines.append("")
|
|
else:
|
|
lines.append("### 검색 품질 경고")
|
|
lines.append("- 요약 결과를 파싱하지 못했습니다.")
|
|
lines.append("")
|
|
|
|
lines.append("---")
|
|
lines.append("")
|
|
|
|
if errors:
|
|
lines.append("## 처리 오류")
|
|
for e in errors:
|
|
lines.append(f"- {e}")
|
|
lines.append("")
|
|
|
|
print("\n".join(lines))
|
|
|
|
# ── Step 2: MD 문서 저장 ──
|
|
- task_name: save_document
|
|
mcp: localdocs
|
|
tool_name: write_file
|
|
parameters:
|
|
path: "legally_required_facts_information.md"
|
|
content: "{{prev.assemble_document}}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|