양도소득세 · git:20261020.970c216 · 2026-10-20 · sha256 2e60484eda2c074f

양도소득세 git:20261020.970c216A

Immutable. This exact content never changes and is served at /api/v1/blob/2e60484eda2c074f.

---
name: 양도소득세
description: 주택·토지·건물 양도건을 질문지로 사실부터 모으고, 공고 이력으로 조정대상지역을 판정해 1세대1주택 비과세·일시적 2주택·고가주택·다주택 중과(한시배제 포함)·단기·미등기·장기보유특별공제·기본공제·합산 비교·지방소득세를 계산한다. 결과에 근거 조문과 시행일, 국세청 파일설명서 코드값을 붙이고, 수식이 들어 있는 계산근거 엑셀을 만든다. 예정신고 정기분과 예정신고를 한 번도 하지 않은 확정신고 정기분은 신고인 정보를 따로 받아 신고서 PDF(별지 제84호서식 본지·부표1·부표3, 지방소득세 별지 제40호의11서식)까지 만든다. 출력 폴더에는 신고서 PDF 두 벌과 계산근거 엑셀만 남는다. 확정신고에는 예정신고 무신고가산세와 납부지연가산세를 국세와 지방소득세 모두 계산해 넣는다. 매매계약서·취득세 영수증·공사 세금계산서 같은 증빙 파일을 주면 먼저 읽어 원문과 대조한 값만 사실관계에 채우고 남은 문항만 묻는다. 고객이 직접 채우는 HTML 질문지도 들어 있다. 세율·공제율·기준금액·처분기한·가산세율은 법제처 원문과 대조한 규칙세트에서 읽고, 2025-01-01 양도분부터 매매와 경매로 양도한 건을 계산한다. "양도소득세", "양도세 계산", "양도세 얼마", "1세대1주택 비과세", "일시적 2주택", "고가주택", "장특공", "장기보유특별공제", "다주택 중과", "조정대상지역", "환산취득가액", "양도세 신고서", "양도세 예정신고", "양도세 확정신고", "예정신고 무신고 가산세", "계약서 올릴게", "매매계약서로 채워줘", "영수증 증빙", "경비 증빙"이 언급되면 트리거.
---

# 양도소득세

주택·토지·건물 양도건의 세액을 근거 조문과 함께 계산합니다. 예정신고 정기분과, 예정신고를 한 번도 하지 않은 확정신고 정기분은 신고서 PDF 까지 만듭니다. 매매와 경매(매각대금 완납일이 양도일)로 양도한 건이 대상입니다. 수용, 교환, 부담부증여, 기타 원인으로 양도한 건은 다루지 않습니다(`references/적용한계.md`). 조세특례제한법 감면은 계산하지 않습니다. 가산세는 예정신고를 한 번도 하지 않은 확정신고의 예정신고 무신고가산세와 납부지연가산세만 계산하고, 국세와 지방소득세에 모두 넣습니다.

사용자에게는 계약일, 잔금일, 등기접수일, 읍면동 주소, 세대가 가진 주택 목록 같은 원자료만 묻고, 조정대상지역 여부·보유햇수·세율은 묻지 않습니다. 판정과 계산은 엔진이 하고, 세율·공제율·기준금액·처분기한·신고기한·가산세율은 `rules/` 의 규칙세트에서 읽습니다. 코드에 남은 고정값은 `references/규칙세트_스키마.md` 에 적혀 있습니다. 값은 2025-01-01 양도분부터 있습니다.

출력 폴더에 남는 파일은 셋뿐입니다.

| 실행 | 출력 폴더에 남는 파일 |
|---|---|
| 계산(`scripts/run.py`, `yangdo_calculate`) | `양도소득세_계산근거.xlsx` |
| 신고서(`scripts/make_return.py`, `yangdo_forms`) | `양도소득세_신고서.pdf`, `지방소득세_신고서.pdf`, `양도소득세_계산근거.xlsx` |

상태, 합계, 판정, 확인사항, 경고, 질문, 다루지않음, 사람이 할 일은 화면 출력과 MCP 응답으로 나옵니다. 결과 JSON, 검토 문서, 질문 문서, 신고값 JSON, 확인 문서는 따로 쓰지 않습니다.

결과는 검토용 초안입니다. 신고 전 최종 판단은 세무 전문가가 합니다.

## 시험해 보기

스킬의 `tests/cases.py` 에 있는 합성 사례 A(서울 아파트 1세대1주택, 고가주택)로 한 번 돌려 봅니다. 스킬 폴더에서:

```bash
pip install -r requirements.txt
python tests/sample_inputs.py A sample
python scripts/run.py --사실관계 sample/a.json --출력 out
```

화면에 `산출세액 2,565,000원, 지방소득세 256,500원, 검산 통과` 와 자산별 판정이 나오고 `out/` 에 `양도소득세_계산근거.xlsx` 가 생깁니다. 설치 확인은 이 한 건이면 됩니다. `tests/` 의 전체 시험은 몇 분 걸려서 설치할 때는 돌리지 않습니다. 스킬 코드를 고친 사람이 `python -m pytest -q tests` 로 돌리고, GitHub 에 올리면 Actions 가 자동으로 돌립니다.

같은 사례로 신고서까지 만들어 봅니다. `sample/a_신고인.json` 은 `tests/filers.py` 의 합성 신고인입니다.

```bash
python scripts/make_return.py --사실관계 sample/a.json --신고인 sample/a_신고인.json --출력 out --오늘 2026-12-20
```

합성 신고인의 작성일(제출하는 날)이 2026-12-20 이라 `--오늘` 을 그 날로 줍니다. 작성일이 오늘보다 앞서면 종료코드 2 로 멈춥니다. 이 날짜는 기준정보 확인일보다 7일 넘게 뒤라 화면의 경고 절에 「기준정보 확인일 … 7일 넘게 지났다」가 나옵니다. 예시 날짜 때문에 나오는 경고이고 계산 결과는 달라지지 않습니다.

화면에 `신고서 PDF 두 벌(양도소득세_신고서.pdf, 지방소득세_신고서.pdf)을 만들었다 (종료코드 0)` 이 나오고 `out/` 에는 신고서 PDF 두 벌과 `양도소득세_계산근거.xlsx` 만 있습니다.

## 0. 기준정보

기준정보(규칙세트, 고시 이력, 코드표, 공휴일 표)는 `rules/` 에 있고 운영자가 만듭니다. 사용자 작업에서는 고치지 않습니다.

계산 결과의 `기준정보` 에 판 id 와 확인일이 나옵니다. 확인일이 7일 넘게 지났으면 경고에 그 사실이 나옵니다. 그대로 보고합니다.

## 1. 사실 모으기

### 증빙 파일이 있으면 먼저 읽는다

사용자가 매매계약서, 취득세 영수증, 공사 세금계산서 같은 파일(PDF, 사진, 워드, 엑셀, 텍스트)이나 그 폴더를 주면 문항을 묻기 전에 증빙부터 읽습니다. 사용자가 같은 금액과 날짜를 두 번 말하지 않아도 됩니다. 증빙이 없으면 아래 문항 절차로 바로 갑니다.

1. `yangdo_evidence_inventory` 로 폴더의 문서 목록(id D01...)을 만든다. 글자층이 없는 PDF, 사진, 한글(HWP) 파일은 목록의 안내를 그대로 사용자에게 알린다
2. 문서를 읽고 값을 `증빙추출.json` 으로 적는다. 값마다 문서 id, 쪽, 문서에 적힌 그대로의 발췌, 확신(확실 또는 불확실)을 붙인다. 계약서 한 장에서 날짜·금액뿐 아니라 자산 종류(P02), 양도·취득 원인(P03, A15), 소재지(A01, 읍면동까지), 주택 형태(A04), 용도변경 특약 없음(A13), 매수인이 대신 내는 세액 없음(A14)도 읽는다. 법무사 영수증이 있으면 등기(A07)를 「예」로 적는다(엔진이 제안으로만 올린다). 경비 목록(M08~M11)은 서류마다 따로 적고 엔진이 이어 붙인다. 형식과 서류별 문항은 `references/증빙추출.md`
3. `yangdo_evidence_apply` 로 넣는다. 글자층 문서에서 발췌와 값이 원문과 맞고 확실한 값만 사실관계에 들어간다. 나머지는 `증빙_확인표.md` 와 응답의 `확인필요`, `충돌` 에 온다. 응답의 `가정` 은 흔한 값을 가정한 문항(M02 산 사람은 타인, M04 계약서 금액이 실제 금액과 같음), `생략` 은 묻지 않는 선택 문항(잔금일을 알면 A12 양도 등기접수일)이다
4. **확인표 하나**를 사용자에게 보여 준다. 아래 네 묶음을 한 표(또는 묶음마다 한 줄 제목을 단 한 표)로 보이고, 「맞으면 맞다고, 다른 줄만 고쳐 주세요」로 한 번에 답을 받는다
   - 증빙에서 넣은 값(`넣은값`): 값과 출처 문서. 특약에 조항이 없어 넣은 값(A13, A14)은 그렇다고 적는다
   - 확인이 필요한 값(`확인필요`): 제안 값과 사유. A07 처럼 정황만 있는 값은 「제안」으로 적는다
   - 가정한 값(`가정`): 「가정」이라고 분명히 적는다. 확인 없이 넣지 않는다
   - 묻지 않는 문항(`생략`): 안내 문장을 그대로 적는다. 사용자가 그 값을 알려 주면 넣는다
5. 사용자가 맞다고 한 확인필요 값과 가정 값을 `yangdo_answer` 로 넣는다. 고친 줄은 고친 값으로 넣는다. 사실관계의 값과 다른 값(충돌)은 어느 쪽이 맞는지 사용자가 정한다
6. 남은 문항을 아래 「문항으로 모으기」의 묶음 방식으로 묻는다

지킬 것: 문서에 없는 값은 적지 않는다. 성명, 주민등록번호, 전화번호, 계좌번호, 주소(읍면동까지만 소재지로)는 옮기지 않는다. 증빙의 진위와 경비 인정 요건(자본적지출 여부, 증빙 적격성)은 보지 않고 계산 결과의 확인사항을 따른다. 스캔본과 사진에서 읽은 값은 전부 사용자 확인을 거친다.

증빙 단계의 `증빙_목록.json`, `증빙_확인표.md`, `증빙_결과.json` 은 사용자가 정한 증빙 작업 폴더에 씁니다. 신고서 출력 폴더와 다른 폴더를 씁니다.

MCP 가 없으면 `python scripts/evidence.py inventory <폴더> --출력 <폴더>` 와 `python scripts/evidence.py apply --사실관계 facts.json --추출 증빙추출.json --목록 증빙_목록.json --출력 <폴더>` 로 같은 일을 합니다.

### 문항으로 모으기

로컬 MCP `yangdo` 가 등록돼 있으면 그것을 씁니다. 등록은 한 번만 합니다.

```bash
claude mcp add yangdo -- python <스킬 경로>/scripts/mcp_server.py
```

| 도구 | 하는 일 |
|---|---|
| `yangdo_next_questions` | 사실관계에 비어 있는 것 중 다음에 물을 문항을 돌려준다. 문항마다 `섹션`, `섹션이름`, 흔한 값의 `가정` 이 붙는다. `생략` 에는 묻지 않는 선택 문항과 그 안내가 온다. 인자는 `facts_path`(파일 경로)나 `facts`(JSON 객체) 중 하나, `limit`(한 번에 받을 문항 수, 기본 1. 묶어 물을 때는 10 안팎). `forms`(서식 단계 문항도 낸다)는 계산용 문항을 모을 때는 쓰지 않는다 |
| `yangdo_answer` | 문항 답을 사실관계에 넣는다. 인자는 `facts_path` 나 `facts`, `question`(문항 id), `value`(답), 자산이나 주택마다 묻는 문항이면 `asset`(자산 id), `house`(주택 id). `value` 에 문자열 「모름」을 주면 모름으로 기록한다. `facts_path` 를 주면 그 파일을 고쳐 쓰고, `facts` 를 주면 고친 사실관계를 `사실관계` 로 돌려준다 |
| `yangdo_calculate` | 판정, 세액, 근거, 파일설명서 코드를 응답으로 낸다. 인자는 `facts_path` 나 `facts`, `today`(YYYY-MM-DD, 비우면 한국 시간 오늘), `out_dir`. `out_dir` 를 주면 그 폴더에 이 스킬이 쓰는 이름의 이전 파일을 지우고 `양도소득세_계산근거.xlsx` 만 쓴다 |
| `yangdo_forms` | 계산에 이어 신고인 정보 검사, 신고값, 서식 검산, 신고서 PDF 두 벌까지 한다. 출력 폴더에는 신고서 PDF 두 벌과 계산근거 엑셀만 남는다. 인자는 `facts_path` 나 `facts`, `filer_path`(신고인 JSON 파일 경로, 필수), `out_dir`(필수), `today` |
| `regulated_area` | 기준일에 조정대상지역·투기과열지구·투기지역인지 공고 이력으로 판정한다. 필수 인자 `sido`(시도), `sigungu`(시군구), `as_of`(기준일), 선택 인자 `eupmyeondong`(읍면동), `in_district`(지구해당) |
| `ruleset_info` | 기준정보 판 id, 확인일, 시행예정 개정, 계류 개정 |

`facts` 와 `facts_path` 는 하나만 줍니다. 둘 다 주거나 둘 다 빼면 오류입니다. `yangdo_answer` 에 `facts_path` 를 주려면 그 파일이 먼저 있어야 합니다.

인자 이름은 영문입니다. Claude 클라이언트가 영문·숫자·`_`·`.`·`-` 가 아닌 인자 이름을 가진 도구를 목록에서 빼기 때문입니다. 옛 한글 이름(`오늘`, `문항`, `값`, `자산`, `주택`, `서식`, `시도`, `시군구`, `읍면동`, `기준일`, `지구해당`)으로 불러도 받습니다. 결과의 키와 사실관계의 키는 한글 그대로입니다. 도구가 받지 않는 인자를 주면 오류로 답합니다(예: `out_dir` 를 `outdir` 로 잘못 적은 경우). 오류 문장에는 인자 이름만 나옵니다. 도구가 예상하지 못한 오류로 실패하면 응답에는 오류의 종류만 나오고, 자세한 위치는 서버의 표준오류에 남습니다.

새 사건은 `{"자산": [{"id": "A"}]}` 로 시작합니다. 양도한 자산마다 id 를 하나씩 정해 넣습니다. `{}` 로 시작하면 자산과 상관없는 문항(P01, P05)만 묻습니다. 문항이 자산을 만들지 않으므로 계산하면 「양도한 자산이 하나도 없습니다」(P02) 질문이 나옵니다. `facts` 로 쓸 때는 돌려받은 `사실관계` 를 다음 호출에 그대로 넘깁니다.

`yangdo_next_questions` 로 문항을 받아 사용자에게 묻고 `yangdo_answer` 로 넣습니다. `다음` 이 빌 때까지 되풀이한 뒤 `yangdo_calculate` 를 부릅니다.

문항은 섹션끼리 묶어 묻습니다. `limit` 를 10 안팎으로 주고, 받은 문항 가운데 첫 문항과 `섹션` 이 같은 것을 한 메시지에 번호를 붙여 묻습니다(예: 세대 묶음 H01 배우자, H03 세대원, H04 세대가 가진 집, H06 입주권·분양권). 사용자가 한 번에 답하면 문항마다 `yangdo_answer` 로 넣고 다시 받습니다. 앞 답에 따라 나오는 문항(H01 이 아니오일 때의 H02 등)은 다음 호출에 나옵니다. 한 섹션의 문항이 하나뿐이면 다음 섹션 문항과 합쳐 물어도 됩니다. 사용자가 하나씩 묻기를 원할 때만 `limit` 1 로 하나씩 묻습니다.

MCP 가 없으면 같은 일을 스크립트로 합니다. `{skill}` 은 스킬 폴더 경로로 바꿔 읽습니다. 새 사건은 위와 같이 `{"자산": [{"id": "A"}]}` 를 담은 파일을 먼저 만듭니다.

```bash
# 다음 문항
python -c "import sys,json; sys.path.insert(0, r'{skill}'); from yangdo import questions as Q; r=Q.next_questions(json.load(open(r'<facts.json>', encoding='utf-8')), limit=10); print(json.dumps({k: r[k] for k in ('다음', '남은', '생략')}, ensure_ascii=False, indent=1))"

# 답 넣기(자산이나 주택마다 묻는 문항은 자산=, 주택= 를 함께 준다)
python -c "import sys,json; sys.path.insert(0, r'{skill}'); from yangdo import questions as Q; p=r'<facts.json>'; f=Q.answer(json.load(open(p, encoding='utf-8')), '<문항id>', <값>, 자산='<자산id>'); json.dump(f, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)"
```

문항을 물을 때 지킬 것:

- 문항마다 `질문` 을 그대로 읽어 줍니다. `도움말`, `증빙서류`, `안내` 가 있으면 함께 전합니다. 묶어 물을 때는 문항마다 번호를 붙이고, 사용자가 번호로 답하게 합니다.
- `가정` 이 있는 문항은 「보통은 <가정 문구>입니다. 맞나요?」 꼴로 묻습니다. 사용자가 맞다고 해야 가정 값을 넣습니다. 답이 없으면 넣지 않습니다.
- `생략` 에 오는 문항은 묻지 않습니다. 안내 문장을 한 번 전하고, 사용자가 그 값을 먼저 말하면 `yangdo_answer` 로 넣습니다. A12(양도 등기접수일)는 잔금일을 알면 묻지 않습니다. 양도일은 잔금일이고, 잔금 전에 사는 사람 앞으로 등기가 접수됐을 때만 접수일이 양도일입니다(소득세법 제98조, 시행령 제162조①2호). 잔금일을 모르면 A12 를 묻습니다(같은 조 ①1호).
- 모르겠다고 하면 `모를때확인처` 를 알려 줍니다. 끝내 모르면 값에 「모름」을 넣습니다. 엔진이 추정하지 않고 확인사항이나 질문으로 돌려줍니다.
- 답 형식은 `답형식` 을 따릅니다. 날짜는 `YYYY-MM-DD`, 금액은 원 단위 정수, 예/아니오는 `true`/`false` 로 답합니다. 선택은 `선택지` 의 코드값 하나, 복수선택은 코드값의 목록(하나만 골라도 목록)입니다. 키가 여럿인 문항은 `{"마지막 키 이름": 값}` 으로 답합니다.
- 사실관계 JSON 에 성명, 주민등록번호, 주소 문자열, 전화번호, 계좌를 넣지 않습니다. 넣으면 엔진이 거부합니다. 소재지는 `{"시도": ..., "시군구": ..., "읍면동": ...}` 로 나눠 적습니다. 2026-07-01 에 통합된 광주광역시와 전라남도의 주소는 옛 시도 이름으로 적어도 되고 전남광주통합특별시로 적어도 됩니다. 서식에 필요한 인적사항은 `신고인.json` 으로 따로 받습니다(3절).
- 양도 원인(P03)이 수용, 교환, 부담부증여, 기타면 나머지 문항을 묻지 말고 바로 알립니다. 취득 원인(A15)이 상속, 증여, 부담부증여, 조합원, 기타일 때도 같습니다. `yangdo_next_questions` 는 이때도 문항을 돌려주지만 따르지 말고, 계산해서 나오는 다루지않음 결과를 알립니다.
- 양도 원인이 경매면 잔금일 문항(A11)에 매수인이 매각대금을 다 낸 날을 받습니다. 사실관계에 `양도.대금완납일` 로 넣어도 되고, 둘 다 있으면 대금완납일을 씁니다.

고객이 직접 채울 때는 `질문지/양도소득세_질문지.html` 을 보냅니다. 브라우저에서 여는 파일 하나이고 서버와 외부 전송이 없습니다. 근거 링크만 law.go.kr 로 열립니다.

- 고객이 「답변 내려받기」로 받은 `양도소득세_답변.json` 이 사실관계 JSON 입니다. 이 파일을 `facts_path` 로 주고 `yangdo_next_questions` 로 남은 문항을 이어서 묻습니다.
- 앞 답으로 계산해 봐야 물을지 정해지는 문항에는 「회계사가 확인합니다」 표시가 붙습니다. 고객이 화면 위의 「회계사가 확인하는 항목 숨기기」를 켜고 비워 둔 문항은 대화에서 다시 묻습니다.
- 성명, 주민등록번호, 전화번호, 계좌와 양수인 같은 서식 단계 문항은 HTML 에 없습니다. 3절의 `신고인.json` 으로 받습니다.
- 문항 정의는 대화와 HTML 이 `질문지/문항.json` 하나를 같이 씁니다. 문항을 고치면 `python scripts/make_questionnaire_html.py` 로 HTML 을 다시 만듭니다.

엔진은 사실관계 입력도 검사합니다. 인적사항이나 주소 문자열이 있으면 오류 문장을 내고 멈춥니다. 정수가 아닌 금액, 음수 금액, 형식이 틀린 날짜와 거주기간, 양도일보다 늦은 취득일은 해당 문항을 질문으로 돌려줍니다. 날짜는 `YYYY-MM-DD` 글자만 받으므로 `20261115` 처럼 붙여 쓴 날짜도 형식이 틀린 날짜입니다. 자산 `id` 는 글자 그대로 세대 주택목록의 `자산id` 와 같아야 하고 겹치면 안 됩니다.

자료형도 문항 정의의 `답형식` 대로 검사합니다. 예/아니오 문항에 `"false"` 같은 글자를 넣거나 복수선택 문항에 목록 대신 글자를 넣으면, 그 값을 참이나 거짓으로 읽지 않고 해당 문항을 질문으로 돌려줍니다. 글자 하나를 목록으로 읽어 중과배제 사유가 생기는 일을 막는 검사입니다.

엔진이 반영하지 못하는 사실이 사실관계에 있으면 낮은 세액을 내지 않고 다루지않음으로 돌려줍니다. 같은 날 주택 여러 채 양도, 다가구 호실별 양도, 매수인이 부담한 양도소득세, 특수관계인에게 시가보다 낮게 양도 등이 해당하고, 전체 목록은 `references/적용한계.md` 에 있습니다.

## 2. 계산

```bash
python "{skill}/scripts/run.py" --사실관계 <facts.json> --출력 <폴더>
```

선택 인자는 `--오늘 YYYY-MM-DD`(기준정보가 7일 넘게 지났는지 가리는 데 쓰는 날짜), `--rules <폴더>`(다른 기준정보 폴더)입니다. 같은 출력 폴더에 다시 실행하면 이전 결과를 지우고 시작합니다. 이 스킬이 쓰는 이름의 파일(계산근거 엑셀, 3절의 신고서 PDF, 예전 판이 쓰던 결과 JSON·검토 문서·질문 문서·신고값 JSON·확인 문서)만 지웁니다. 계산을 다시 하면 옛 신고서가 새 계산 결과와 맞지 않기 때문입니다. 다른 파일은 그대로 둡니다.

결과는 화면에 나옵니다. 완료면 기준정보 판, 합계, 자산별 판정(1세대1주택, 비과세, 중과, 장기보유특별공제)과 세액, 확인사항, 경고가 나오고, 질문이면 묻는 문항과 모를 때 확인하는 곳, 다루지않는 항목이 나옵니다. MCP 의 `yangdo_calculate` 는 같은 내용을 응답의 `상태`, `합계`, `자산`, `질문`, `다루지않음`, `확인사항`, `경고`, `검산` 으로 돌려줍니다.

| 종료코드 | 뜻 | 다음 |
|---|---|---|
| 0 | 완료 | 화면(또는 응답)의 판정, 확인사항, 경고를 요약해 보고하고 계산근거 엑셀 경로를 알린다 |
| 1 | 검산 실패 | 화면의 「검산」 절에 실패 줄이 나온다. 그대로 보고하고 이 결과를 신고에 쓰지 말라고 알린다 |
| 2 | 질문 또는 다루지않음 | 화면의 「계산 전에 확인할 것」 문항을 사용자에게 묻는다. 다루지않음이면 그 사실을 알린다. 그 항목을 다룰 계획은 결과의 `계획` 값(계획 번호, `미정`, `없음`)과 `references/적용한계.md` 의 표로 확인한다. 문항 없이 오류 문장만 나왔으면 사실관계 파일 자체의 문제다(인적사항, 주소 문자열, 자산 id, 읽을 수 없는 파일, 맞지 않는 값 형식). 그 문장을 보고하고 파일을 고치게 한다 |
| 3 | 기준정보 오류 | 규칙세트, 코드표, 고시 파일이 기준정보 판과 다르거나 없다. 계산하지 않고 운영자에게 알린다 |
| 4 | 출력 파일 쓰기 실패 | 이전 엑셀을 엑셀이 열어 둔 경우가 많다. 파일을 닫고 같은 명령을 다시 실행하라고 알린다 |

출력 폴더의 `양도소득세_계산근거.xlsx`(종료코드 0, 1)는 수식이 들어 있는 계산근거입니다. 요약 시트에 계산 흐름이, 근거 시트에 근거 조문과 시행일이 있습니다. 수식을 다시 계산해 엔진 값과 대조합니다.

## 3. 신고서

계산이 끝난 건으로 신고서 PDF 를 만듭니다. 신고서를 만드는 건은 아래와 같습니다.

| 건 | 만드는 것 |
|---|---|
| 예정신고 정기분 | 신고서 PDF 두 벌 |
| 예정신고를 한 번도 하지 않은 확정신고 정기분 | 신고서 PDF 두 벌. 예정신고 무신고가산세와 납부지연가산세를 국세와 지방소득세에 계산해 넣는다 |
| 과세 자산과 전액 비과세 자산이 섞인 건 | 전액 비과세 자산은 넣지 않고 과세 자산만으로 만든다 |
| 전액 비과세 자산뿐인 건 | 만들지 않는다. 계산 결과만 내고 종료코드 2 |
| 가산세를 계산하지 못한 확정신고 | 만들지 않는다. 계산근거 엑셀만 참고용으로 내고 종료코드 2 |
| 기한후신고, 수정신고, 경정청구, 같은 해에 먼저 예정신고한 양도가 있는 건, 대리 신고 | 다루지 않는다 |

확정신고와 전액 비과세 자산의 처리는 아래 「확정신고와 가산세」, 「전액 비과세 자산」에 있습니다. 전체 목록과 까닭은 `references/적용한계.md` 에 있고, 세무 전문가 확인이 남은 해석도 그 문서 끝에 모았습니다.

### 신고인 정보 받기

인적사항은 사실관계에 넣지 않고 `신고인.json` 파일에 따로 적습니다. 스킬 폴더의 `신고인_양식.json` 을 복사해 사용자가 직접 채우게 합니다. 키마다 받는 형식은 양식의 `_설명` 에 있습니다. MCP 도구에는 이 파일의 경로만 주고, 내용을 대화에 옮기지 않습니다.

| 구역 | 적는 것 |
|---|---|
| `신고` | `구분`(예정 또는 확정), `작성일`(YYYY-MM-DD), `분납신청`(true 또는 false). `홈택스ID` 는 비워 둔다(서식에 칸이 없다) |
| `신고인` | 성명, 주민등록번호, 주소(시도, 시군구, 읍면동, 특수지, 번지, 호, 아파트명, 아파트동, 아파트호, 법정동코드), 전화, 전자메일, 내외국인, 거주구분, 거주지국, 국적 |
| `양수인` | 산 사람마다 자산 id, 구분, 내외국인, 번호, 성명, 전화, 지분. 사실관계의 매수인관계가 타인이 아니면 관계코드 |
| `자산` | 자산 id 마다 지번(특수지, 번지, 호), 아파트명, 아파트동, 아파트호, 법정동코드, 총면적, 취득상대방. 경매로 취득하거나 양도한 자산은 등기원인 |
| `환급계좌`, `세무대리인` | `null` 로 둔다. 세무대리인에 값이 있으면 대리 신고라 멈춘다 |

`작성일` 은 신고서를 제출하는 날입니다. 신고서의 작성일과 신고기한 판정에 씁니다. 아래 네 경우는 종료코드 2 로 멈춥니다. 신고기한을 지난 날짜(기한후신고), 확정신고인데 확정신고 기간(양도일이 속한 과세기간의 다음 연도 5월 1일부터 5월 31일까지, 소득세법 제110조①)보다 앞선 날짜, 실행하는 날(`--오늘`, MCP 는 `today`, 없으면 한국 시간 오늘)보다 앞선 날짜, 양도일보다 앞선 날짜입니다. 확정신고의 작성일은 확정신고 기간 안의 신고·납부 예정일로 적고, 신고인 파일을 미리 만들어 두었으면 제출할 날짜로 고쳐 다시 실행합니다. 번호와 전화는 하이픈 없이 숫자만 적습니다. 성명과 취득상대방은 한글 완성형(KS X 1001) 글자와 ASCII 글자만 받습니다. 한자와 「똠」 같은 확장 한글은 쓸 수 없습니다.

신고기한은 규칙세트 값으로 계산합니다. 예정신고는 양도일이 속하는 달의 말일부터 2개월, 확정신고는 다음 연도 5월 31일입니다. 기한이 토요일, 일요일, 공휴일, 대체공휴일, 노동절이면 그 다음의 첫 평일까지로 봅니다(국세기본법 제5조①). 공휴일은 `rules/공휴일.json` 표로 보고, 표에는 2025년, 2026년, 2027년이 있습니다. 표에 없는 해에 끝나는 기한은 토·일, 날짜가 고정된 공휴일, 노동절만 옮깁니다. 표의 확인일 뒤에 지정된 임시공휴일도 표에 없습니다. 이 두 경우는 실제 기한이 더 늦을 수 있는데 기한후신고로 보고 멈춥니다. 기한을 옮겼으면 건너뛴 날이, 기한이 끝나는 해가 표에 없으면 그 해의 연휴와 대체공휴일을 모른다는 문장이 다루지않음 문장과 확인사항에 나옵니다. 그대로 전합니다.

신고인 파일의 구역에 그 구역이 받지 않는 키(띄어 쓴 키 이름 등)가 있으면 읽지 않고 알림(화면 출력과 MCP 응답의 `알림`)에 키 이름만 적습니다. `_` 로 시작하는 설명용 키는 알리지 않습니다. 빠졌거나 하나로 정하지 못한 값은 질문 F01~F08 로 화면의 「신고인 정보 질문」 절과 응답의 `신고인질문` 에 나옵니다. 질문에는 항목 이름만 나오고 값은 나오지 않습니다. 사용자에게 물어 파일을 채운 뒤 다시 실행합니다.

| 문항 | 묻는 것 | 채우는 곳 |
|---|---|---|
| F01 | 신고인 본인 정보, 주소, 주소의 법정동코드 | `신고인` |
| F02 | 자산을 산 양수인, 지분 합, 타인이 아닌 양수인의 관계코드 | `양수인` |
| F03 | 분납 신청 여부 | `신고.분납신청` |
| F04 | 자산 지번, 법정동코드, 경매 자산의 등기원인 코드 | `자산` |
| F05 | 신고 구분과 작성일 | `신고` |
| F07 | 지급처 사업자번호와 지급일을 반드시 적는 지출(법무사비용, 중개수수료, 기타를 뺀 자본적지출 등)의 사업자번호와 지급일. 부표3 에 적는다 | 사실관계 필요경비 항목의 `사업자번호`, `지급일` |
| F08 | 실지거래가액으로 신고하는 자산의 매도인 성명이나 상호 | `자산[id].취득상대방` |

### 실행

```bash
python "{skill}/scripts/make_return.py" --사실관계 <facts.json> --신고인 <신고인.json> --출력 <폴더>
```

선택 인자는 `run.py` 와 같습니다(`--오늘`, `--rules`). MCP 로는 `yangdo_forms` 를 부릅니다. 이 도구는 `pymupdf` 가 있어야 하고, 없으면 설치 안내 오류를 냅니다. 계산 도구는 그대로 쓸 수 있습니다.

순서는 계산, 신고인 정보 검사, 신고값(메모리에만 둔다), 서식 검산, 신고서 PDF 입니다. 앞 단계가 막히면 뒤 단계는 하지 않습니다. 같은 출력 폴더에 다시 실행하면 이 스킬이 쓰는 이름의 이전 파일만 지우고 시작합니다.

결과는 화면에 「# 양도소득세 신고 확인」 글로 나옵니다. 요약 줄과 종료코드, 기준정보 판, 합계, 단계 표, 알림, 계산 질문, 신고인 정보 질문, 검산과 서식 검산 문장, 확인사항, 경고, 만든 파일, 사람이 할 일이 차례로 나오고 인적사항 값은 없습니다. MCP 의 `yangdo_forms` 응답에는 `상태`, `종료코드`, `요약`, `단계`, `기준정보`, `판`, `합계`, `가산세`, `파일`, `질문`, `신고인질문`, `다루지않음`, `검산`, `서식검산`, `확인사항`, `경고`, `알림`, `사람이할일` 이 들어 있습니다.

| 종료코드 | 뜻 | 다음 |
|---|---|---|
| 0 | 완료 | 확인사항과 사람이 할 일을 그대로 보고한다 |
| 1 | 서식 검산 실패 | 실패 문장을 보고하고 이 결과로 신고하지 말라고 알린다. 계산 검산 실패, 신고값이나 신고서 PDF 를 만들지 못한 경우, 예상하지 못한 오류로 멈춘 경우(만든 신고서 PDF 를 지우고, 지우지 못하면 그렇게 적는다)도 1 이다 |
| 2 | 질문 또는 다루지않음 | 계산 질문은 「계산 질문」 절(응답의 `질문`), 신고인 정보 질문(F01~F08)은 「신고인 정보 질문」 절(응답의 `신고인질문`)에 있다. 사용자에게 물어 사실관계나 `신고인.json` 을 채우고 다시 실행한다. 신고 범위가 아닌 건(기한후신고 등), 전액 비과세 자산뿐이라 과세 자산이 없는 건, 가산세를 계산하지 못한 확정신고, 읽을 수 없거나 형식이 틀린 입력 파일, 작성일이 오늘이나 양도일보다 앞선 신고인 파일도 2 다. 이때는 알림 문장을 그대로 보고한다 |
| 3 | 기준정보, 서식 원본 판(`forms/서식판.json`) 오류 | 운영자에게 알린다 |
| 4 | 출력 파일 쓰기 실패 | 출력 폴더의 파일을 연 프로그램을 닫고 다시 실행하라고 알린다. 저장이 끝나지 않은 신고서 PDF 가 남았으면 알림에 그 이름이 나온다. 그 파일은 다시 실행해 새로 만들기 전에는 신고에 쓰지 않는다. 지우지 못해 남은 파일은 알림에 이전 실행의 것으로 적힌다. 이때 화면 글은 표준오류로 나온다. MCP 도구는 이 경우를 오류 응답으로 돌려준다 |

`합계` 에는 `산출세액`, `지방소득세` 가 있고, 가산세를 넣은 확정신고면 `가산세`, `납부할세액`, `지방가산세`, `지방납부할세액` 이 더 있습니다(본지 합계 열과 지방소득세 신고서 합계 열 값입니다). 가산세를 넣은 확정신고의 요약 줄은 「산출세액 …원, 가산세 …원, 납부할 세액 …원, 지방소득세 산출세액 …원, 지방소득세 가산세 …원, 지방소득세 납부할 세액 …원」 꼴입니다. 가산세가 없는 건의 요약 줄은 「산출세액 …원, 지방소득세 …원」 그대로입니다.

### 출력 파일

| 파일 | 언제 | 내용 |
|---|---|---|
| `양도소득세_계산근거.xlsx` | 계산 완료 | 2절과 같다 |
| `양도소득세_신고서.pdf`, `지방소득세_신고서.pdf` | 서식 검산 통과 | 별지 제84호서식(본지, 부표1, 부표3)과 지방세 별지 제40호의11서식. 인적사항이 들어 있다. 란 대응은 `references/신고서식.md` |

신고값(서식 란별 값)은 메모리에서만 쓰고 파일로 남기지 않습니다. 중간 파일은 출력 폴더에 남지 않습니다.

### 확정신고와 가산세

확정신고의 신고서는 그 해에 예정신고한 양도가 없을 때만 만듭니다. 예정신고한 양도가 하나라도 있으면 기신고분을 합산해야 하는 신고라 다루지 않습니다. 작성일은 확정신고 기간(다음 연도 5월 1일부터 5월 31일까지) 안이어야 하고, 기간 전이면 종료코드 2 로 멈춥니다. 가산세를 작성일(납부일)까지의 일수로 계산하기 때문입니다. 허가 전에 대금을 청산한 토지거래허가구역 토지는 허가일이 양도일과 다른 해에 속하면 확정신고 기간이 허가일 다음 연도 5월입니다(소득세법 제110조① 괄호). 그 토지의 확정신고서는 만들지 않습니다.

| 항목 | 처리 |
|---|---|
| 국세 가산세 | 예정신고 무신고가산세와 납부지연가산세를 계산해 신고서 ⑯ 가산세와 ⑱ 납부할 세액에 넣는다. 가산세율은 규칙세트에서 읽는다 |
| 지방소득세 가산세 | 무신고가산세와 납부지연가산세를 지방소득세 신고서 ⑬ 가산세와 ⑮ 납부할 총세액에 넣는다. 두 가지를 가정한 값이다. 지방소득세 예정신고기한은 소득세법이 정한 예정신고기한(토요일·일요일·공휴일이라 옮기기 전)에 2개월을 더한 날로 보았다. 무신고가산세는 세액 합계에 가산세율을 곱해 원 미만을 버린 뒤 건별로 나누고, 납부지연가산세는 건마다 원 미만을 버렸다. 위택스 화면이 계산한 가산세와 다르면 위택스 값을 따른다 |
| 무신고가산세의 감면 | 국세와 지방소득세 모두 감면 없이 계산한다. 예정신고분을 확정신고기한까지 기한 후 신고로 내면 100분의 50 을 감면하는 규정이 있지만, 이 스킬은 확정신고서를 만들므로 적용하지 않는다. 지방세기본법의 감면 규정은 확정신고기한까지 과세표준 신고를 한 경우라고 정하지만, 문구가 같은 규정(2025-12-31 까지의 국세기본법 감면 규정)을 과세관청이 달리 본 예가 있어 적용하지 않았다. 감면이 적용될 때의 금액이 확인사항과 「알림」에 나온다 |
| 납부일 | 작성일에 국세와 지방소득세를 내는 것으로 보고 납부지연가산세를 계산한다. 다른 날 내면 신고인 파일의 작성일을 그 날로 바꿔 다시 만든다 |
| 같은 달에 양도한 자산 | 한 건으로 합산해 예정신고 세액을 계산한다. 양도일마다 따로 신고한 것으로 본 금액이 확인사항에 함께 나온다 |
| 분납 | 분납 한도는 가산세를 뺀 세액으로 계산한다. 분납을 신청하면 분납할 세액에 납부지연가산세가 더 붙을 수 있다는 확인사항이 나온다 |
| 부정행위로 신고하지 않은 경우 | 부정행위로 신고하지 않은 경우의 가산세율은 적용하지 않는다. 일반 무신고가산세율로 계산했다는 확인사항이 나온다 |
| 가산세를 계산하지 못한 건 | 허가일 값이 없는 토지거래허가구역 토지, 같은 달에 양도한 자산의 세율이 다르고 합산 비교세액이 세율별 세액의 합보다 큰 경우다. 신고서를 만들지 않고 종료코드 2 로 끝난다. 가산세를 더한 신고는 세무 전문가와 한다 |

작성일이 지방소득세 예정신고기한 이전이면 지방소득세 가산세가 없다는 한 줄만 나옵니다(확정신고 기간이 5월이라 이 스킬의 확정신고에서는 보통 나오지 않습니다). 감면 없이 계산했다는 알림은 그대로 보고하고, 기한 후 신고로 내는 방법과 비교하라는 「사람이 할 일」도 함께 전합니다.

### 전액 비과세 자산

엔진이 전액 비과세로 판정한 자산은 신고서에 넣지 않습니다.

- 과세 자산과 섞인 건은 과세 자산만 신고합니다. 「알림」에 넣지 않은 자산의 id 와 「비과세 요건을 과세관청이 달리 보면 그 자산은 신고하지 않은 것이 된다」는 문장이 나옵니다. 그대로 보고하고, 비과세 요건 증빙을 보관하라는 「사람이 할 일」도 함께 전합니다. 넣지 않은 자산의 양수인과 지번은 묻지 않습니다.
- 전액 비과세 자산뿐인 건은 신고서를 만들 과세 자산이 없어 종료코드 2 로 끝납니다. 계산 결과만 나옵니다. 비과세 판정은 세무 전문가와 확인합니다.

### 사람이 할 일

종료코드 0 일 때 화면 글 끝과 응답의 `사람이할일` 에 아래 순서가 나옵니다. 그대로 전합니다. 건에 따라 줄이 더 붙습니다.

1. 신고서 PDF 두 벌을 계약서·증빙과 대조해 검토한다. 신고 전 최종 판단은 세무 전문가가 한다.
2. 홈택스에 사람이 로그인해 `양도소득세_신고서.pdf` 의 값으로 양도소득세를 신고하고 접수증을 보관한다. 에이전트는 로그인하거나 제출하지 않는다.
3. 취득가액과 필요경비를 보이는 증빙(매매계약서, 영수증, 세금계산서 등)을 보관한다. 신고할 때 함께 낼 서류는 세무 전문가와 확인한다.
4. 위택스에서 지방소득세(양도소득분)를 따로 신고한다. 값은 `지방소득세_신고서.pdf` 에 있다.
5. 신고기한 안에 국세와 지방소득세를 납부한다.

| 건 | 더 붙거나 바뀌는 줄 |
|---|---|
| 가산세가 있는 확정신고 | 1번 뒤에 예정신고분을 기한 후 신고로 내는 방법과 비교하라는 줄이 붙는다. 4번에 위택스 화면의 가산세와 다르면 위택스 값을 따른다는 문장이 붙는다(지방소득세 가산세가 있을 때). 5번은 작성일에 국세와 지방소득세를 납부하라는 줄로 바뀐다 |
| 전액 비과세 자산을 넣지 않은 건 | 3번 뒤에 그 자산의 비과세 요건 증빙을 보관하라는 줄이 붙는다 |
| 분납을 신청해 분납할 세액이 있는 건 | 납부 줄이 둘이다. 첫째는 작성일(예정신고는 신고기한 안)에 낼 금액으로, 국세는 납부할 세액에서 분납할 세액을 뺀 금액, 지방소득세는 납부할 세액 전액이다. 둘째는 분납할 세액과 그 납부 기한이다. 기한은 신고기한에서 2개월 뒤 날짜이고, 그날이 토요일·일요일·공휴일이면 다음 평일로 옮긴다(소득세법 제112조 「납부기한이 지난 후 2개월 이내」). 옮겼으면 건너뛴 날도 적는다. 이 날짜 계산은 이 스킬의 가정이라 「홈택스 분납 납부서에 적힌 기한을 따른다」를 붙인다. 지방소득세 분납은 안내하지 않는다 |
| 같은 해 다른 양도가 있다고 답한 건 | 맨 앞에 그 양도를 먼저 신고했는지 확인하라는 줄이 붙는다 |

지킬 것:

- 홈택스·위택스 로그인과 제출은 사람이 합니다. 에이전트는 로그인하지 않습니다.
- 지방소득세는 위택스에서 따로 신고합니다.
- 신고서 PDF 와 `신고인.json` 에는 인적사항이 있습니다. 내용을 대화나 보고에 옮기지 않습니다. 보고에는 화면 글과 도구 응답의 문장만 씁니다.
- 확정신고 가산세와 전액 비과세 자산에 관한 확인사항과 알림은 줄이지 않고 그대로 보고합니다(위 「확정신고와 가산세」, 「전액 비과세 자산」).

## 4. 보고할 때

- 결론 옆에 근거 조문과 시행일을 붙입니다. 계산근거 엑셀의 근거 시트에 있습니다.
- 합계는 세액 둘을 모두 보여 줍니다. 같은 세율 자산 합산 세액과 합산 비교세액 중 큰 값이 산출세액입니다(소득세법 제104조⑤). 자산이 하나면 합산 비교세액은 0 으로 나옵니다. 지방소득세도 같은 방식입니다. `yangdo_calculate` 결과의 `참고` 문장은 자산별 합과 산출세액이 다른 까닭을 적은 것이니 함께 전합니다.
- 확인사항을 전부 보고합니다. 조정대상지역 판정에 쓴 공고, 일시적 2주택 부칙, 한시배제, 추계 순서, 합산 비교는 특히 빠뜨리지 않습니다. 중과의 다른 주택 배제 사유(10호), 해외 출국 예외의 출국일 현재 1주택, 특수관계인 거래의 시가 비교, 전남광주통합특별시 시 지역의 집을 지방 저가주택으로 주택 수에서 뺐다는 확인사항도 같습니다. 「이 답은 이번 계산에 반영하지 않았다」 로 시작하는 확인사항(세대원 목록, 따로 산 세대원, 취득 상대방, 1990년 이전 취득 토지의 토지등급)은 사용자가 답한 사실을 계산에 쓰지 않았다는 뜻이므로 그대로 전합니다.
- 경고를 전부 보고합니다. 계류 중인 개정(2026 세제개편안 중과 완화)과 시행예정 개정이 여기에 나옵니다. 계류 목록(`ruleset_info` 의 `계류`)은 운영자가 기준정보를 갱신할 때 최신화 점검으로 맞춥니다. 정부가 낸 안과 국회를 통과한 안만 넣고, 의원 발의 법안은 넣지 않는 것이 기본입니다. 사용자가 목록에 없는 개정 소식을 물으면 `skills/법령검토/SKILL.md` 의 최신화 점검으로 따로 찾습니다.
- 「이 결과는 검토용입니다. 신고 전 최종 판단은 세무 전문가가 합니다」를 붙입니다.
- `references/적용한계.md` 에 걸리는 건이면 그 사실을 알립니다.

## 5. 법령을 더 찾아야 할 때

`skills/법령검토/SKILL.md` 순서를 따릅니다. TaxDoctor 를 1차로 쓰고 korean-law 로 대조합니다.

이 스킬의 규칙세트 값은 바꾸지 않습니다. 값이 틀렸다고 보이면 운영자에게 알립니다.

## 참고 문서

| 문서 | 내용 |
|---|---|
| `references/판정트리.md` | 판정 순서와 조문, 판정 뒤 계산 순서, 합산 |
| `references/증빙추출.md` | 증빙 파일을 읽어 사실관계를 채우는 순서, 증빙추출.json 형식, 서류별 문항, 원문 대조 판정 |
| `references/규칙세트_스키마.md` | `rules/` 파일 모양, 원문 대조 규칙, 공휴일 표, 기준정보 판 |
| `references/적용한계.md` | 계산하지 않고 다루지않음이나 확인사항으로 돌려주는 것, 신고서를 만들지 않는 건, 신고기한과 공휴일 표, 세무 전문가 확인이 남은 것 |
| `references/신고서식.md` | 신고값이 서식의 어느 란에 가는지, 서식 표기 변환, 서식 검산, 서식이 개정됐을 때 할 일 |
| `references/정답지.md` | 국세청 「양도소득세 신고서 작성 사례」와 대조한 기록, 확정신고 가산세 대조 |