13 Commits
Author SHA1 Message Date
eomsangdonandClaude Opus 5 56343d8088 knowledge(품셈md): 도구 check · pages · status + 잠금 시험
- check: ① 수(갯수까지) ② 글자(공백 뗌) 양방향 대조 · 어긋난 자리를 쪽·줄로 출력 · 머리 기계검사 칸에 적음
- md 쪽은 머리 · 주석 · 그림 · 표 문법 · 제목·인용 표시 · 첨자 표시를 빼고, 막음표(\) 뒤 글자는 원문으로 셈
- 확정 파일은 통과할 때 확정지문(LF 로 센 sha256)을 한 번만 적음 — 있는 지문은 안 덮음
- pages: 쪽 그림 150dpi → tmp/pum_pages(git 밖) · status: 장별 상태 표
- test_pum_md_locked.py: 확정 파일 지문·①② 0 · 머리 칸 다 있음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
2026-09-19 01:27:15 +09:00
eomsangdonandClaude Opus 5 b8d76feccd knowledge(품셈md): 산림 빈 파일 196 — 장머리 13 · 절 183 (plan)
- 제4장 일곱(다른 창 시범분)은 건너뜀 → 산림 전체 장머리 14 · 절 189
- 절 이름·표지는 본문 머리 글자 그대로(번호 뒤 마침표) · 띄어쓰기는 쪽 그림의 글자 틈으로 되살림
- 도구: 장마다 0-00_장머리.md · 이미 있는 자리는 번호로 봐서 건너뜀(이 폴더·다른 창 브랜치)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
2026-09-19 01:23:13 +09:00
eomsangdon b956a18f86 Merge remote-tracking branches 'origin/sub_laptop_2' and 'origin/sub_laptop_3' into sub_laptop_1 2026-09-19 01:19:55 +09:00
eomsangdon 505b6efdb4 Merge remote-tracking branch 'origin/dev' into sub_laptop_1 2026-09-19 01:19:53 +09:00
eomsangdonandClaude Opus 5 1964797de2 knowledge(품셈md): 절별 md 도구 pum_md_tool.py — plan(차례 → 빈 파일)
- 산림 차례(PDF 3~12쪽)에서 장 14 · 절 189 · 쪽 범위 · 시작/끝 표지
- 절 머리는 번호로 찾음 — 차례 이름 오타 다섯(면벅·조림·우드그래풀·소형 운재) 때문
- 표지는 PDF 글자 그대로(번호 뒤 마침표 포함) · 띄어쓰기만 차례를 따름
- 다른 창 브랜치에 이미 있는 파일은 안 만듦(합칠 때 부딪힘 막음)
- 시험 test_pum_md_tool.py: 순수 함수 · 산림 차례 개수

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
2026-09-19 01:19:46 +09:00
eomsangdon dc5f584792 Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_4 2026-09-19 01:17:51 +09:00
eomsangdon 6c22b0bb78 Merge remote-tracking branch 'origin/sub_laptop_2' into sub_laptop_4 2026-09-19 01:17:25 +09:00
eomsangdonandClaude Opus 5 39b5cc3d65 knowledge(품셈md): 산림 4-6 벌목부 작업안전 보조 — 절·표지를 PDF 글자대로(마침표 포함) · [주] 항목마다 한 줄 · 글상자 넓은 띄움은 빈칸 하나
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0145cr1DMC5Ft8fouQSXtp69
2026-09-19 01:17:07 +09:00
eomsangdonandClaude Opus 5 ab4cf35e07 knowledge(품셈md): 산림 4-5 벌도 위험목 점검 — 절·표지를 PDF 글자대로(마침표 포함) · [주] 항목마다 한 줄
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0145cr1DMC5Ft8fouQSXtp69
2026-09-19 01:17:07 +09:00
eomsangdonandClaude Opus 5 4f3746d337 knowledge(품셈md): 산림 4-4 가지정리 작성
- PDF 62쪽(인쇄 50쪽) 그림과 한 줄씩 맞대어 받아씀 · 상태 검증대기
- 스스로 맞댐: 글자층 수 9 = md 수 9 · 글자 결손 0 · 더함 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
2026-09-19 01:15:33 +09:00
eomsangdonandClaude Opus 5 94dce3d71e knowledge(품셈md): 산림 4-3 위험목 베기 작성
- PDF 62쪽(인쇄 50쪽) 그림과 한 줄씩 맞대어 받아씀 · 상태 검증대기
- 스스로 맞댐: 글자층 수 69 = md 수 69 · 더한 글자는 두 단 머리 펼침(소요인력(인/본당)·소요시간(hr) 되풀이)뿐

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
2026-09-19 01:15:33 +09:00
eomsangdonandClaude Opus 5 d7abfa7431 knowledge(품셈md): 산림 4-6 벌목부 작업안전 보조 작성
- PDF 63쪽(인쇄 51) 그림과 한 줄씩 맞대 받아씀 · 제5장이 64쪽에서 시작해 넘어가는 쪽 없음 · 상태 검증대기
- 상자 안 붙임표는 원문 글자 「-」 그대로(옛 md 는 「–」 로 바뀌어 있었음)
- 스스로 맞대기: 글자층 수 14개·글자 결손 0 허구 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0145cr1DMC5Ft8fouQSXtp69
2026-09-19 01:15:31 +09:00
eomsangdonandClaude Opus 5 776c35f6b9 knowledge(품셈md): 산림 4-5 벌도 위험목 점검 작성
- PDF 63쪽(인쇄 51) 그림과 한 줄씩 맞대 받아씀 · 상태 검증대기
- 스스로 맞대기: 글자층 수 9개·글자 결손 0 허구 0

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0145cr1DMC5Ft8fouQSXtp69
2026-09-19 01:15:22 +09:00
203 changed files with 3579 additions and 0 deletions
@@ -0,0 +1,542 @@
# -*- coding: utf-8 -*-
"""품셈 PDF → 절별 md 도구 (규칙: `원가계산/_품셈md_작성규칙.md` · 2026-09-19).
판정 기준은 PDF 뿐 — 원가계산(B09)·공종 마스터·옛 md 는 보지 않음.
사용: python pum_md_tool.py plan <산림|건설> 차례에서 장·절 → 본문/ 빈 파일(머리만 · 상태 대기)
python pum_md_tool.py pages <산림|건설> [쪽범위] 쪽 그림 150dpi PNG → tmp/pum_pages/ (git 밖)
python pum_md_tool.py check <md 파일> ① 수 대조 ② 글자 대조 → 머리 「기계검사」 칸
python pum_md_tool.py status 장별 대기/작성중/검증대기/확정 표
절 경계 = 시작표지·끝표지 글자가 쪽 안에서 놓인 줄(좌표로 묶은 줄의 맨 앞).
좌표로 줄 묶기는 `resources/tester/test_const_pdf_coverage.py` 의 것을 그대로 씀(그 시험은 안 고침).
"""
from __future__ import annotations
import collections
import difflib
import hashlib
import re
import sys
from dataclasses import dataclass
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4] # 저장소 뿌리
sys.path.insert(0, str(ROOT))
from resources.tester.test_const_pdf_coverage import _NUM, _page_rows # noqa: E402
COST = ROOT / "resources/knowledge/original/원가계산"
#: 책마다 — PDF · 차례 쪽(PDF 쪽 번호) · 인쇄 1쪽이 놓인 PDF 쪽 · 머리 「문서」 칸 · 새 md 뿌리
BOOKS = {
"산림": {
"pdf": COST / "산림_표준품셈/첨부/(산림청고시 제2025-82호) 산림사업 표준품셈.pdf",
"toc": (3, 12),
"first_body": 13,
"doc": "산림사업 표준품셈(산림청고시 제2025-82호)",
"out": COST / "산림_표준품셈/본문",
},
}
HEAD_KEYS = (
"문서",
"",
"PDF쪽",
"인쇄쪽",
"시작표지",
"끝표지",
"상태",
"작성",
"검증",
"원천",
"기계검사",
"확정지문",
)
STATES = ("대기", "작성중", "검증대기", "확정")
_TOC_SKIP = {"", "내 용", "페이지", "- 목 차 -"}
_TOC_ID = re.compile(r"\d+장|\d+-\d+(?:-\d+)*|부록\d*")
_BAD_NAME = re.compile(r'[/:*?"<>|\\]')
_LEADER = re.compile(r"\s*[·․…]{3,}.*$")
#: 글자층이 없다고 볼 쪽 글자 수(쪽 번호만 남은 쪽)
_EMPTY_PAGE_CHARS = 20
@dataclass
class Entry:
"""차례 한 줄 — 장(`제1장`) · 절(`1-1`) · 항(`1-1-1`) · 부록."""
ident: str
name: str
page: int # 인쇄 쪽
def toc_entries(doc, first: int, last: int) -> list[Entry]:
"""차례 쪽(PDF first~last)의 줄 — 번호 줄 · 이름 줄(점선) · 쪽 줄이 차례로 옴."""
lines = [
line
for number in range(first - 1, last)
for line in doc[number].get_text().splitlines()
if line.strip() not in _TOC_SKIP
]
return parse_toc(lines)
def parse_toc(raw: list[str]) -> list[Entry]:
lines = [
t for t in (_LEADER.sub("", line).strip() for line in raw) if t
] # 점선 뗌(「부록 ····」)
out, i = [], 0
while i < len(lines):
if not _TOC_ID.fullmatch(lines[i]):
raise ValueError(f"차례 모양이 다름: {lines[i]!r}")
j, name = i + 1, []
while j < len(lines) and not lines[j].isdigit():
name.append(lines[j])
j += 1
if j == len(lines):
raise ValueError(f"차례 쪽 번호 없음: {lines[i]}")
out.append(Entry(lines[i], " ".join(name), int(lines[j])))
i = j + 1
return out
#: 가운뎃점 여러 벌 — 차례는 「보수․복구」(U+2024) · 본문은 「보수·복구」(U+00B7). 맞대기에서만 같게 봄.
_DOTS = str.maketrans({"": "·", "": "·", "": "·", "": "·"})
def key(text: str) -> str:
"""표지 맞대기 — 공백·대괄호를 떼고 번호 뒤 점을 뗌(`9-5. 발파암` = `9-5 발파암`)."""
tight = re.sub(r"[\s\[\]]", "", text).translate(_DOTS)
return re.sub(r"^(\d+(?:-\d+)*)\.", r"\1", tight)
def locate(doc, marker: str, first_pdf: int, slack: int = 3) -> tuple[int, int]:
"""표지가 줄 맨 앞에 놓인 (PDF 쪽, 그 쪽 안 줄 차례) — first_pdf 부터 slack 쪽 안에서 찾음."""
want = key(marker)
for number in range(first_pdf, min(first_pdf + slack, doc.page_count) + 1):
for index, row in enumerate(_page_rows(doc[number - 1])):
if key(row).startswith(want):
return number, index
raise ValueError(f"표지를 못 찾음: {marker} (PDF {first_pdf}~{first_pdf + slack})")
def heading_pattern(ident: str) -> re.Pattern:
"""본문 머리 줄 — **번호로** 찾음. 차례 이름에 오타가 있어서(「면벅」=면벽 · 「조림」=조립 …)."""
if ident.startswith(""):
return re.compile(r"^제\s*" + ident[1:-1] + r"\s*장(?!\d)")
if ident.startswith("부록"):
return re.compile(r"^\[?" + re.escape(ident) + r"\]?(?!\d)")
return re.compile(r"^" + re.escape(ident) + r"\.(?!\d)")
#: 글자 사이 빈칸으로 볼 틈(글자 크기 대비) — 본문 머리 실측: 빈칸 7.7pt · 붙은 글자 0.7pt(14pt 글꼴)
_GAP = 0.25
def visual_text(page, row: str) -> str:
"""쪽 그림대로 띄운 줄 — 글자층은 빈칸을 잃어서(「설계및수량」) 글자 사이 틈으로 되살림."""
want = re.sub(r"\s", "", row)
for block in page.get_text("rawdict")["blocks"]:
for line in block.get("lines", []):
chars = [c for span in line["spans"] for c in span["chars"]]
if re.sub(r"\s", "", "".join(c["c"] for c in chars)) != want:
continue
size = max(span["size"] for span in line["spans"])
out = ""
for prev, ch in zip([None, *chars], chars):
gap = ch["bbox"][0] - prev["bbox"][2] if prev else 0
if prev and not prev["c"].isspace() and gap > size * _GAP:
out += " "
out += ch["c"]
return " ".join(out.split())
return row
def find_heading(doc, ident: str, first_pdf: int, slack: int = 3) -> tuple[int, int, str]:
"""(PDF 쪽, 쪽 안 줄 차례, 머리 글자) — 머리 글자는 PDF 그대로(번호 뒤 마침표 포함) · 띄어쓰기는 쪽 그림대로."""
pattern = heading_pattern(ident)
for number in range(first_pdf, min(first_pdf + slack, doc.page_count) + 1):
for index, row in enumerate(_page_rows(doc[number - 1])):
if pattern.match(row.strip()):
return number, index, visual_text(doc[number - 1], row.strip())
raise ValueError(f"머리를 못 찾음: {ident} (PDF {first_pdf}~{first_pdf + slack})")
def name_of(ident: str, title: str) -> str:
"""머리 글자에서 번호를 뗀 이름(「9-5. 발파암」 → 「발파암」)."""
return title[heading_pattern(ident).match(title).end() :].strip()
def claimed_elsewhere(root: Path) -> set[str]:
"""다른 창 브랜치에 이미 있는 새 md 경로 — 만들면 합칠 때 같은 자리 두 벌로 부딪힘."""
import subprocess
rel = root.relative_to(ROOT).as_posix()
refs = subprocess.run(
["git", "-C", str(ROOT), "for-each-ref", "--format=%(refname)", "refs/remotes/origin"],
capture_output=True,
text=True,
check=True,
).stdout.split()
out: set[str] = set()
for ref in refs:
listed = subprocess.run(
[
"git",
"-C",
str(ROOT),
"-c",
"core.quotepath=off",
"ls-tree",
"-r",
"--name-only",
ref,
"--",
rel,
],
capture_output=True,
text=True,
encoding="utf-8",
)
out.update(line[len(rel) + 1 :] for line in listed.stdout.splitlines() if line)
return out # root 아래 상대 경로
def safe(text: str) -> str:
return _BAD_NAME.sub("", text).replace(" ", "_")
def _span(a: int, b: int) -> str:
return str(a) if a == b else f"{a}~{b}"
def head_text(values: dict[str, str]) -> str:
return (
"---\n" + "".join(f"{k}: {values.get(k, '')}".rstrip() + "\n" for k in HEAD_KEYS) + "---\n"
)
def read_head(path: Path) -> dict[str, str]:
lines = path.read_text(encoding="utf-8").splitlines()
if not lines or lines[0] != "---":
raise ValueError(f"머리 없음: {path}")
out = {}
for line in lines[1:]:
if line == "---":
return out
k, _, v = line.partition(":")
out[k.strip()] = v.strip()
raise ValueError(f"머리 끝 없음: {path}")
_SLOT = re.compile(r"제(\d+)장_[^/]*/(\d+-\d+)_")
def plan(book_name: str) -> list[Path]:
"""장마다 `0-00_장머리.md` + 절마다 빈 파일(머리만 · 상태 대기).
**이미 있는 자리는 안 건드림** — 이 폴더에 있거나 다른 창 브랜치에 있는 장·절(이름이 달라도 번호로 봄).
"""
import pymupdf
book = BOOKS[book_name]
out = book["out"]
offset = book["first_body"] - 1 # 인쇄 쪽 + offset = PDF 쪽
have = claimed_elsewhere(out) | {p.relative_to(out).as_posix() for p in out.rglob("*.md")}
taken = {f"{int(m[1])}/{m[2]}" for m in map(_SLOT.match, have) if m}
folders = {int(m[1]): rel.split("/")[0] for rel in have if (m := _SLOT.match(rel))}
written = []
with pymupdf.open(book["pdf"]) as doc:
entries = toc_entries(doc, *book["toc"])
# 경계가 되는 차례 줄 — 장 · 절 · 부록N(항은 절 안 · 머리 없는 「부록」 묶음 줄은 뺌)
bounds = [e for e in entries if e.ident != "부록" and e.ident.count("-") < 2]
chapter_no = None
for n, entry in enumerate(bounds):
if entry.ident.startswith("부록"):
continue
start_pdf, _, title = find_heading(doc, entry.ident, entry.page + offset)
following = bounds[n + 1] if n + 1 < len(bounds) else None
if following is None: # 문서 맨 끝 절
end_pdf, end_marker = doc.page_count, ""
else: # 장 마지막 절이면 다음 장 제목 · 부록 앞이면 부록 제목
next_pdf, at, end_marker = find_heading(
doc, following.ident, following.page + offset
)
end_pdf = max(next_pdf - 1 if at == 0 else next_pdf, start_pdf)
if entry.ident.startswith(""):
chapter_no = int(entry.ident[1:-1])
folders.setdefault(
chapter_no, f"{chapter_no:02d}장_{safe(name_of(entry.ident, title))}"
)
slot, file_name = "0-00", "0-00_장머리.md"
else:
major, minor = entry.ident.split("-")
slot = f"{major}-{int(minor):02d}"
file_name = f"{slot}_{safe(name_of(entry.ident, title))}.md"
if chapter_no is None or f"{chapter_no}/{slot}" in taken:
continue
empty = any(
len(re.sub(r"\s", "", doc[p - 1].get_text())) < _EMPTY_PAGE_CHARS
for p in range(start_pdf, end_pdf + 1)
)
path = out / folders[chapter_no] / file_name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
head_text(
{
"문서": book["doc"],
"": title,
"PDF쪽": _span(start_pdf, end_pdf),
"인쇄쪽": _span(start_pdf - offset, end_pdf - offset),
"시작표지": title,
"끝표지": end_marker,
"상태": "대기",
"원천": "그림" if empty else "글자층",
}
),
encoding="utf-8",
)
written.append(path)
return written
# ── check ──────────────────────────────────────────────────────────────
#: 쪽 번호 줄(「- 123 -」) — 절 글자에서 뺌
_PAGE_NO = re.compile(r"^-\s*\d+\s*-$")
#: md 문법 — 글자 대조·수 대조에서 뺌(원문 글자가 아님)
_COMMENT = re.compile(r"<!--.*?-->", re.S)
_IMAGE = re.compile(r"!\[[^\]]*\]\([^)]*\)")
_TABLE_RULE = re.compile(r"^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$")
#: 막음표 — 원문 글자가 md 문법으로 읽히지 않게 앞에 `\` 를 붙인 것(`\*` `\-` `\#` `\>` `\|` …)
_ESCAPED = re.compile(r"\\([\\`*_{}\[\]()#+\-.!|>~^])")
_HOLD = "\x00"
def book_of(path: Path) -> dict:
path = path.resolve()
for book in BOOKS.values():
if path.is_relative_to(book["out"].resolve()):
return book
raise ValueError(f"본문/ 아래 파일이 아님: {path}")
def split_head(text: str) -> tuple[str, str]:
"""(머리, 몸) — 머리는 첫 `---` 부터 다음 `---` 까지."""
lines = text.split("\n")
end = lines.index("---", 1)
return "\n".join(lines[: end + 1]), "\n".join(lines[end + 1 :])
def md_lines(body: str) -> list[tuple[int, str]]:
"""몸의 (줄 번호, 원문 글자) — 주석 · 그림 · 표 구분 줄 · md 문법 글자를 뺌. 줄 번호는 몸 기준 1부터."""
body = _COMMENT.sub(lambda m: "\n" * m.group(0).count("\n"), body)
out = []
for number, line in enumerate(body.split("\n"), start=1):
if _TABLE_RULE.match(line):
continue
line = _IMAGE.sub("", line).replace("<br>", " ")
held = _ESCAPED.findall(line) # 막음표 뒤 원문 글자는 아래 문법 떼기에서 지킴
line = _ESCAPED.sub(_HOLD, line)
line = re.sub(r"^\s*#+\s", "", line) # 제목
line = re.sub(r"^\s*(>\s*)+", "", line) # 인용
line = re.sub(r"[|^_]", " ", line) # 표 칸 · 첨자 표시(`10^-7` · `C_m`)
for ch in held:
line = line.replace(_HOLD, ch, 1)
out.append((number, line))
return out
def pdf_lines(doc, head: dict[str, str]) -> list[tuple[int, str]]:
"""그 절 PDF 글자층의 (PDF 쪽, 줄) — 시작표지 줄부터 끝표지 줄 앞까지 · 쪽 번호 줄 뺌."""
first, _, last = head["PDF쪽"].partition("~")
first, last = int(first), int(last or first)
start_page, start_row = locate(doc, head["시작표지"], first, slack=0)
end_page, end_row = last + 1, 0
if head["끝표지"] and head["끝표지"] != "":
try:
end_page, end_row = locate(doc, head["끝표지"], last, slack=1)
except ValueError:
pass
out = []
for number in range(start_page, min(end_page, doc.page_count) + 1):
for index, row in enumerate(_page_rows(doc[number - 1])):
if (number, index) < (start_page, start_row) or (number, index) >= (end_page, end_row):
continue
if not _PAGE_NO.match(row.strip()):
out.append((number, row))
return out
def _tight(lines: list[tuple[int, str]]) -> tuple[str, list[int]]:
"""공백 뗀 글자 줄 + 글자마다 어디서 왔나(쪽 또는 md 줄)."""
text, where = [], []
for at, line in lines:
for ch in re.sub(r"\s", "", line):
text.append(ch)
where.append(at)
return "".join(text), where
def _numbers(lines: list[tuple[int, str]]) -> tuple[collections.Counter, dict[str, list[int]]]:
counts, where = collections.Counter(), collections.defaultdict(list)
for at, line in lines:
for token in _NUM.findall(line):
counts[token] += 1
where[token].append(at)
return counts, where
def compare(pdf: list[tuple[int, str]], md: list[tuple[int, str]]) -> dict:
"""① 수(갯수까지) ② 글자(공백 뗌 · 갯수까지) — 양방향."""
pdf_n, pdf_at = _numbers(pdf)
md_n, md_at = _numbers(md)
pdf_t, pdf_where = _tight(pdf)
md_t, md_where = _tight(md)
missing_c = collections.Counter(pdf_t) - collections.Counter(md_t)
extra_c = collections.Counter(md_t) - collections.Counter(pdf_t)
spots = []
if missing_c or extra_c: # 자리 — 차례대로 맞대 어긋난 토막(갯수 차가 난 글자가 든 것만)
matcher = difflib.SequenceMatcher(None, pdf_t, md_t, autojunk=False)
for op, i1, i2, j1, j2 in matcher.get_opcodes():
gone, added = pdf_t[i1:i2], md_t[j1:j2]
if op == "equal" or not (set(gone) & set(missing_c) or set(added) & set(extra_c)):
continue
spots.append(
{
"pdf": pdf_where[min(i1, len(pdf_where) - 1)] if pdf_where else None,
"md": md_where[min(j1, len(md_where) - 1)] if md_where else None,
"context": pdf_t[max(0, i1 - 8) : i1],
"pdf_only": gone,
"md_only": added,
}
)
return {
"num_missing": {k: (v, pdf_at[k][:v]) for k, v in (pdf_n - md_n).items()},
"num_extra": {k: (v, md_at[k][:v]) for k, v in (md_n - pdf_n).items()},
"char_missing": missing_c,
"char_extra": extra_c,
"spots": spots,
}
def verdict(result: dict) -> str:
counts = (
sum(v for v, _ in result["num_missing"].values()),
sum(v for v, _ in result["num_extra"].values()),
sum(result["char_missing"].values()),
sum(result["char_extra"].values()),
)
word = "통과" if not any(counts) else "불통"
return (
f"{word} · ①수 결손 {counts[0]} 허구 {counts[1]} · ②글자 빠짐 {counts[2]} 더함 {counts[3]}"
)
def fingerprint(text: str) -> str:
"""확정지문 — 줄끝을 LF 로 고쳐 셈(git 이 CRLF 로 풀어도 같게) · 도구가 적는 두 칸(기계검사·확정지문)은 뺌."""
lines = text.replace("\r\n", "\n").split("\n")
kept = [ln for ln in lines if not ln.startswith(("기계검사:", "확정지문:"))]
return hashlib.sha256("\n".join(kept).encode("utf-8")).hexdigest()
def set_head(text: str, field: str, value: str) -> str:
head, body = split_head(text)
head = re.sub(rf"(?m)^{field}:.*$", f"{field}: {value}".rstrip(), head, count=1)
return head + "\n" + body
def check_file(path: Path) -> tuple[dict, str]:
"""(대조 결과, 한 줄 판정) — 파일은 안 고침."""
import pymupdf
_, body = split_head(path.read_text(encoding="utf-8").replace("\r\n", "\n"))
with pymupdf.open(book_of(path)["pdf"]) as doc:
result = compare(pdf_lines(doc, read_head(path)), md_lines(body))
return result, verdict(result)
def check(path: Path) -> int:
"""검사하고 머리 「기계검사」 칸에 적음 · 상태 `확정` 이고 통과인데 확정지문이 비었으면 지문도 적음.
⚠ 있는 확정지문은 안 고침 — 확정 뒤 바뀐 파일을 지문을 다시 적어 덮으면 시험이 못 잡음.
"""
result, line = check_file(path)
print(f"{path.name}: {line}")
for token, (count, at) in sorted(result["num_missing"].items()):
print(f" ① 결손 {token} ×{count} (PDF {', '.join(map(str, at))}쪽)")
for token, (count, at) in sorted(result["num_extra"].items()):
print(f" ① 허구 {token} ×{count} (md 몸 {', '.join(map(str, at))}줄)")
for spot in result["spots"][:40]:
print(
f" ② PDF {spot['pdf']}쪽 · md 몸 {spot['md']}줄 · …{spot['context']}"
f" [PDF만 「{spot['pdf_only']}」 · md만 「{spot['md_only']}」]"
)
text = set_head(path.read_text(encoding="utf-8").replace("\r\n", "\n"), "기계검사", line)
head = read_head(path)
if head.get("상태") == "확정" and line.startswith("통과") and not head.get("확정지문"):
text = set_head(text, "확정지문", fingerprint(text))
path.write_text(text, encoding="utf-8", newline="\n")
return 0 if line.startswith("통과") else 1
# ── pages · status ─────────────────────────────────────────────────────
PAGES_DIR = ROOT / "tmp/pum_pages"
def pages(book_name: str, span: str = "") -> list[Path]:
"""쪽 그림 150dpi PNG — `tmp/pum_pages/<책>/p0135.png`(git 밖)."""
import pymupdf
out = PAGES_DIR / book_name
out.mkdir(parents=True, exist_ok=True)
made = []
with pymupdf.open(BOOKS[book_name]["pdf"]) as doc:
first, _, last = (span or f"1~{doc.page_count}").replace("-", "~").partition("~")
for number in range(int(first), int(last or first) + 1):
path = out / f"p{number:04d}.png"
doc[number - 1].get_pixmap(dpi=150).save(path)
made.append(path)
return made
def status() -> str:
"""장별 상태 표(md) — 머리 「상태」 칸을 모음."""
rows = [
"| 책 | 장 | " + " | ".join(STATES) + " | 계 |",
"|---|---|" + "---|" * (len(STATES) + 1),
]
for name, book in BOOKS.items():
by_chapter: dict[str, collections.Counter] = {}
for path in sorted(book["out"].rglob("*.md")):
chapter = path.relative_to(book["out"]).parts[0]
by_chapter.setdefault(chapter, collections.Counter())[
read_head(path).get("상태", "")
] += 1
for chapter, counts in by_chapter.items():
cells = " | ".join(str(counts[s]) for s in STATES)
rows.append(f"| {name} | {chapter} | {cells} | {sum(counts.values())} |")
return "\n".join(rows)
def main(argv: list[str]) -> int:
command, args = (argv[0], argv[1:]) if argv else ("", [])
if command == "plan" and args:
print(f"새 파일 {len(plan(args[0]))}")
return 0
if command == "pages" and args:
made = pages(args[0], args[1] if len(args) > 1 else "")
print(f"쪽 그림 {len(made)}{PAGES_DIR / args[0]}")
return 0
if command == "check" and args:
return max(check(Path(a)) for a in args)
if command == "status":
print(status())
return 0
print(__doc__)
return 2
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제1장 적용기준
PDF쪽: 13
인쇄쪽: 1
시작표지: 제1장 적용기준
끝표지: 1-1. 일반사항
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-1. 일반사항
PDF쪽: 13~14
인쇄쪽: 1~2
시작표지: 1-1. 일반사항
끝표지: 1-2. 설계 및 수량
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-2. 설계 및 수량
PDF쪽: 14~27
인쇄쪽: 2~15
시작표지: 1-2. 설계 및 수량
끝표지: 1-3. 재료 및 노임의 할증
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-3. 재료 및 노임의 할증
PDF쪽: 27~29
인쇄쪽: 15~17
시작표지: 1-3. 재료 및 노임의 할증
끝표지: 1-4. 품의 할인․할증
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-4. 품의 할인․할증
PDF쪽: 29~36
인쇄쪽: 17~24
시작표지: 1-4. 품의 할인․할증
끝표지: 1-5. 목재 원목시가
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-5. 목재 원목시가
PDF쪽: 36
인쇄쪽: 24
시작표지: 1-5. 목재 원목시가
끝표지: 1-6. 원가 작성기준
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-6. 원가 작성기준
PDF쪽: 36~37
인쇄쪽: 24~25
시작표지: 1-6. 원가 작성기준
끝표지: 1-7. 기타사항
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 1-7. 기타사항
PDF쪽: 38~39
인쇄쪽: 26~27
시작표지: 1-7. 기타사항
끝표지: 제2장 소요재료 및 기계손료
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제2장 소요재료 및 기계손료
PDF쪽: 40
인쇄쪽: 28
시작표지: 제2장 소요재료 및 기계손료
끝표지: 2-1. 소요재료
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 2-1. 소요재료
PDF쪽: 40~47
인쇄쪽: 28~35
시작표지: 2-1. 소요재료
끝표지: 2-2. 기계손료
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 2-2. 기계손료
PDF쪽: 48~51
인쇄쪽: 36~39
시작표지: 2-2. 기계손료
끝표지: 제3장 작업장 관리
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제3장 작업장 관리
PDF쪽: 52
인쇄쪽: 40
시작표지: 제3장 작업장 관리
끝표지: 3-1. 경계표시
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-1. 경계표시
PDF쪽: 52
인쇄쪽: 40
시작표지: 3-1. 경계표시
끝표지: 3-2. 작업로 선정
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-2. 작업로 선정
PDF쪽: 52
인쇄쪽: 40
시작표지: 3-2. 작업로 선정
끝표지: 3-3. 작업로 설치
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-3. 작업로 설치
PDF쪽: 52~53
인쇄쪽: 40~41
시작표지: 3-3. 작업로 설치
끝표지: 3-4. 임산물 운반로 신설 및 보수·복구
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-4. 임산물 운반로 신설 및 보수·복구
PDF쪽: 53~55
인쇄쪽: 41~43
시작표지: 3-4. 임산물 운반로 신설 및 보수·복구
끝표지: 3-5. 예정지정리
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-5. 예정지정리
PDF쪽: 56~57
인쇄쪽: 44~45
시작표지: 3-5. 예정지정리
끝표지: 3-6. 산물 임내정리
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-6. 산물 임내정리
PDF쪽: 57
인쇄쪽: 45
시작표지: 3-6. 산물 임내정리
끝표지: 3-7. 재해산물 수집
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-7. 재해산물 수집
PDF쪽: 58
인쇄쪽: 46
시작표지: 3-7. 재해산물 수집
끝표지: 3-8. 드론 영상 촬영
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 3-8. 드론 영상 촬영
PDF쪽: 58
인쇄쪽: 46
시작표지: 3-8. 드론 영상 촬영
끝표지: 제4장 나무베기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,44 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 4-3 위험목 베기
PDF쪽: 62
인쇄쪽: 50
시작표지: 4-3 위험목 베기
끝표지: 4-4 가지정리
상태: 검증대기
작성: sub_laptop_3
검증:
원천: 글자층
기계검사:
확정지문:
---
## 4-3. 위험목 베기
| 가슴높이지름<br>(cm) | 소요인력(인/본당) › 특별인부 | 소요인력(인/본당) › 벌목부 | 소요인력(인/본당) › 보통인부 | 소요시간(hr) › 굴삭기<br>우드그랩 | 소요시간(hr) › 크레인 |
|---|---|---|---|---|---|
| 1620cm | 0.14 | 0.28 | 0.28 | 0.28 | 0.28 |
| 2230cm | 0.18 | 0.36 | 0.36 | 0.36 | 0.36 |
| 3240cm | 0.27 | 0.53 | 0.53 | 0.53 | 0.53 |
| 4250cm | 0.35 | 0.70 | 0.70 | 0.70 | 0.70 |
| 52cm이상 | 0.38 | 0.75 | 0.75 | 0.75 | 0.75 |
[주]① 본 품은 숲가꾸기 사업, 위험 해안가, 절벽지, 농경지‧주택지 주변 등 특수지역 위험목을 처리할 때와 소형윈치나 안전로프 등 벌목보조장치를 갖추고 나무베기 작업을 하여야 하는 경우에 적용한다.
② 가슴높이지름 16cm이상의 입목에 적용하며, 16cm 미만의 입목은 솎아베기 품 적용한다.
③ 장비 설치보조, 로프설치, 안전관리, 작업장관리 등을 포함하며 제거산물을 작동하여 안전한 장소에 쌓아놓거나 50m이내 거리까지 집재를 포함한다.
④ 숲가꾸기 위험목 제거 또는 인력작업 시에는 벌목부의 100%를 가산한다.
> 【소요인력 산출 예시】
> - 가슴높이지름 22~30cm, 20본 제거할 경우,
> : (벌목부) 0.36인×20본×2배=14.4인. (특별인부) 0.18×20본=3.6인, (보통인부) 0.36인×20본=7.2인
⑤ 장비는 굴착기 우드그랩은 0.2㎥, 크레인은 5톤 트럭탑재형 크레인을 적용, 현장 여건에 따라 장비의 규격을 조정 가능하다.
⑥ 산림병해충, 소나무재선충병 발생지역 내 장비 없이 인력으로만 위험목을 제거할 경우에는 보통인부의 100%를 가산한다.
> 【소요인력 산출 예시】
> - 가슴높이지름 22~30cm, 20본 제거할 경우,
> : (벌목부) 0.36인×20본=7.2인, (특별인부) 0.18×20본=3.6인, (보통인부) 0.36인×20본×2배=14.40인
@@ -0,0 +1,26 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 4-4 가지정리
PDF쪽: 62
인쇄쪽: 50
시작표지: 4-4 가지정리
끝표지: 4-5 벌도 위험목 점검
상태: 검증대기
작성: sub_laptop_3
검증:
원천: 글자층
기계검사:
확정지문:
---
## 4-4. 가지정리
(인/100㎡)
| 명칭 | 1종 | 2종 |
|---|---|---|
| 보통인부 | 0.42 | 0.71 |
[주] ① 1종 : 가지가 겹쳐 있어서 사람이 가지 사이를 걷는 것이 약간 곤란한 상태
② 2종 : 가지가 겹쳐 있어서 가지를 정리하지 않으면 사람이 걸을 수 없는 상태
@@ -0,0 +1,28 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 4-5. 벌도 위험목 점검
PDF쪽: 63
인쇄쪽: 51
시작표지: 4-5. 벌도 위험목 점검
끝표지: 4-6. 벌목부 작업안전 보조
상태: 검증대기
작성: sub_laptop_4
검증:
원천: 글자층
기계검사:
확정지문:
---
## 4-5. 벌도 위험목 점검
(인/ha)
| 소요인력(인) | 인력구분 |
|---|---|
| 0.13인 | 벌목부 |
[주]
① 본 품은 벌목작업 중 작업원이 위험목을 보다 빠르게 식별하고, 효과적으로 대처할 수 있도록 덩굴식물 피압목, 초두부 고사목, 수형이 불균형한 수목 등에 대해 작업 실행 전 숙련작업원이 선행 점검을 시행하고, 눈높이에 표식을 남겨 작업장 내 안전관리를 효과적으로 수행하고자 적용한다.
② 위험목의 벌도방향 결정 및 벌목작업은 벌목부 중에서도 숙련된 인원이 담당하므로, 위험여부의 판정 또한 벌목부가 현장을 확인하도록 한다.
③ 본 품은 작업자의 임내 가시거리를 15m로 기준할 때, 1ha당 총 330m의 보행 거리가 필요하며, 임내 보행 속도는 통상 2.5km/ha이므로 1ha당 0.132시간이 소요됨
<!-- 원문 그대로: 보행 속도 단위 「km/ha」 — 뒤의 시간 셈과 맞추면 「km/h」 로 보임 · 끝 마침표 없음도 원문 -->
@@ -0,0 +1,30 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 4-6. 벌목부 작업안전 보조
PDF쪽: 63
인쇄쪽: 51
시작표지: 4-6. 벌목부 작업안전 보조
끝표지: 제5장 식재 및 녹화
상태: 검증대기
작성: sub_laptop_4
검증:
원천: 글자층
기계검사:
확정지문:
---
## 4-6. 벌목부 작업안전 보조
| 소요인력(인) | 인력구분 |
|---|---|
| 1인 | 보통인부 |
[주]
① 본 품은 연료통의 전달, 기타 장구류의 전달 등 벌목작업 외 벌목부가 운반하여야 하는 노무를 보조하고, 작업자의 이동동선, 벌도목의 방향, 작업자를 지속적으로 관찰하여 안전한 벌목작업의 수행 및 보조를 위한 품이다.
② 벌목 시 벌목부 4인당 보통인부 1인을 추가하며 4인을 초과할 시 해당 인력에 대한 안전 벌목 보조를 추가하여야 한다.
> 【투입인원 산출】
>
> 벌목부 투입인원 3명 - 안전 벌목 보조 1명, 벌목부 투입인원 4명 - 안전 벌목 보조 1명
>
> 벌목부 투입인원 5명 - 안전 벌목 보조 2명, 벌목부 투입인원 6명 - 안전 벌목 보조 2명
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제5장 식재 및 녹화
PDF쪽: 64
인쇄쪽: 52
시작표지: 제5장 식재 및 녹화
끝표지: 5-1. 굴취작업
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-1. 굴취작업
PDF쪽: 64~66
인쇄쪽: 52~54
시작표지: 5-1. 굴취작업
끝표지: 5-2. 뿌리돌림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-2. 뿌리돌림
PDF쪽: 66
인쇄쪽: 54
시작표지: 5-2. 뿌리돌림
끝표지: 5-3. 식재작업
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-3. 식재작업
PDF쪽: 67~70
인쇄쪽: 55~58
시작표지: 5-3. 식재작업
끝표지: 5-4. 파종조림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-4. 파종조림
PDF쪽: 71
인쇄쪽: 59
시작표지: 5-4. 파종조림
끝표지: 5-5. 천연하종갱신
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-5. 천연하종갱신
PDF쪽: 71
인쇄쪽: 59
시작표지: 5-5. 천연하종갱신
끝표지: 5-6. 움싹갱신
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-6. 움싹갱신
PDF쪽: 71
인쇄쪽: 59
시작표지: 5-6. 움싹갱신
끝표지: 5-7. 생태보완조림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-7. 생태보완조림
PDF쪽: 72
인쇄쪽: 60
시작표지: 5-7. 생태보완조림
끝표지: 5-8. 큰나무 공익조림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-8. 큰나무 공익조림
PDF쪽: 72
인쇄쪽: 60
시작표지: 5-8. 큰나무 공익조림
끝표지: 5-9. 해안조림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-9. 해안조림
PDF쪽: 72~73
인쇄쪽: 60~61
시작표지: 5-9. 해안조림
끝표지: 5-10. 사방조림
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-10. 사방조림
PDF쪽: 73
인쇄쪽: 61
시작표지: 5-10. 사방조림
끝표지: 5-11. 사초심기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-11. 사초심기
PDF쪽: 73~74
인쇄쪽: 61~62
시작표지: 5-11. 사초심기
끝표지: 5-12. 떼붙임(재배잔디)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-12. 떼붙임(재배잔디)
PDF쪽: 74
인쇄쪽: 62
시작표지: 5-12. 떼붙임(재배잔디)
끝표지: 5-13. 떼심기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-13. 떼심기
PDF쪽: 74~75
인쇄쪽: 62~63
시작표지: 5-13. 떼심기
끝표지: 5-14. 새심기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-14. 새심기
PDF쪽: 75
인쇄쪽: 63
시작표지: 5-14. 새심기
끝표지: 5-15. 바자얽기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-15. 바자얽기
PDF쪽: 75~76
인쇄쪽: 63~64
시작표지: 5-15. 바자얽기
끝표지: 5-16. 선떼붙이기공
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-16. 선떼붙이기공
PDF쪽: 76
인쇄쪽: 64
시작표지: 5-16. 선떼붙이기공
끝표지: 5-17. 조공
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-17. 조공
PDF쪽: 77
인쇄쪽: 65
시작표지: 5-17. 조공
끝표지: 5-18. 씨뿌리기(줄)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-18. 씨뿌리기(줄)
PDF쪽: 77~78
인쇄쪽: 65~66
시작표지: 5-18. 씨뿌리기(줄)
끝표지: 5-19. 표토 절취 및 정지
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-19. 표토 절취 및 정지
PDF쪽: 78
인쇄쪽: 66
시작표지: 5-19. 표토 절취 및 정지
끝표지: 5-20. 표토관리
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-20. 표토관리
PDF쪽: 78
인쇄쪽: 66
시작표지: 5-20. 표토관리
끝표지: 5-21. 표토이식
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-21. 표토이식
PDF쪽: 79
인쇄쪽: 67
시작표지: 5-21. 표토이식
끝표지: 5-22. 평떼
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-22. 평떼
PDF쪽: 79~80
인쇄쪽: 67~68
시작표지: 5-22. 평떼
끝표지: 5-23. 줄떼
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-23. 줄떼
PDF쪽: 80
인쇄쪽: 68
시작표지: 5-23. 줄떼
끝표지: 5-24. 씨앗뿜어붙이기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-24. 씨앗뿜어붙이기
PDF쪽: 81~83
인쇄쪽: 69~71
시작표지: 5-24. 씨앗뿜어붙이기
끝표지: 5-25. 거적덮기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-25. 거적덮기
PDF쪽: 83
인쇄쪽: 71
시작표지: 5-25. 거적덮기
끝표지: 5-26. 흙갈이
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-26. 흙갈이
PDF쪽: 83~84
인쇄쪽: 71~72
시작표지: 5-26. 흙갈이
끝표지: 5-27. 식재면 관리
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-27. 식재면 관리
PDF쪽: 84
인쇄쪽: 72
시작표지: 5-27. 식재면 관리
끝표지: 5-28. 비탈덮기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-28. 비탈덮기
PDF쪽: 84~85
인쇄쪽: 72~73
시작표지: 5-28. 비탈덮기
끝표지: 5-29. 복사이식
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-29. 복사이식
PDF쪽: 85
인쇄쪽: 73
시작표지: 5-29. 복사이식
끝표지: 5-30. 표시봉설치
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-30. 표시봉설치
PDF쪽: 85
인쇄쪽: 73
시작표지: 5-30. 표시봉설치
끝표지: 5-31. 지주목설치
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-31. 지주목설치
PDF쪽: 86
인쇄쪽: 74
시작표지: 5-31. 지주목설치
끝표지: 5-32. 대절작업
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-32. 대절작업
PDF쪽: 86
인쇄쪽: 74
시작표지: 5-32. 대절작업
끝표지: 5-33. 묘목 가식작업
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-33. 묘목 가식작업
PDF쪽: 86
인쇄쪽: 74
시작표지: 5-33. 묘목 가식작업
끝표지: 5-34. 묘목 소운반
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 5-34. 묘목 소운반
PDF쪽: 86~88
인쇄쪽: 74~76
시작표지: 5-34. 묘목 소운반
끝표지: 제6장 생육보조
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제6장 생육보조
PDF쪽: 89
인쇄쪽: 77
시작표지: 제6장 생육보조
끝표지: 6-1. 비료주기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-1. 비료주기
PDF쪽: 89
인쇄쪽: 77
시작표지: 6-1. 비료주기
끝표지: 6-2. 풀베기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-2. 풀베기
PDF쪽: 89~90
인쇄쪽: 77~78
시작표지: 6-2. 풀베기
끝표지: 6-3. 맹아제거
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-3. 맹아제거
PDF쪽: 91
인쇄쪽: 79
시작표지: 6-3. 맹아제거
끝표지: 6-4. 덩굴제거
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-4. 덩굴제거
PDF쪽: 91~93
인쇄쪽: 79~81
시작표지: 6-4. 덩굴제거
끝표지: 6-5. 어린나무 가꾸기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-5. 어린나무 가꾸기
PDF쪽: 94
인쇄쪽: 82
시작표지: 6-5. 어린나무 가꾸기
끝표지: 6-6. 가지치기 및 수형교정
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-6. 가지치기 및 수형교정
PDF쪽: 95
인쇄쪽: 83
시작표지: 6-6. 가지치기 및 수형교정
끝표지: 6-7. 토양개량 및 치환
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-7. 토양개량 및 치환
PDF쪽: 95~96
인쇄쪽: 83~84
시작표지: 6-7. 토양개량 및 치환
끝표지: 6-8. 목재칩 포설
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 6-8. 목재칩 포설
PDF쪽: 96
인쇄쪽: 84
시작표지: 6-8. 목재칩 포설
끝표지: 제7장 집재 및 운재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 제7장 집재 및 운재
PDF쪽: 97
인쇄쪽: 85
시작표지: 제7장 집재 및 운재
끝표지: 7-1. 인력집재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-1. 인력집재
PDF쪽: 97~98
인쇄쪽: 85~86
시작표지: 7-1. 인력집재
끝표지: 7-2. 수라집재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-2. 수라집재
PDF쪽: 98
인쇄쪽: 86
시작표지: 7-2. 수라집재
끝표지: 7-3. 아키야윈치(임업용 윈치) 집재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-3. 아키야윈치(임업용 윈치) 집재
PDF쪽: 99
인쇄쪽: 87
시작표지: 7-3. 아키야윈치(임업용 윈치) 집재
끝표지: 7-4. 소형가선 집재(2드럼 윈치)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-4. 소형가선 집재(2드럼 윈치)
PDF쪽: 99~100
인쇄쪽: 87~88
시작표지: 7-4. 소형가선 집재(2드럼 윈치)
끝표지: 7-5. 트랙터부착형 집재(지면끌기)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-5. 트랙터부착형 집재(지면끌기)
PDF쪽: 100~101
인쇄쪽: 88~89
시작표지: 7-5. 트랙터부착형 집재(지면끌기)
끝표지: 7-6. 스윙야더 집재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-6. 스윙야더 집재
PDF쪽: 101
인쇄쪽: 89
시작표지: 7-6. 스윙야더 집재
끝표지: 7-7. HAM200 집재(춘천․스마트)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-7. HAM200 집재(춘천․스마트)
PDF쪽: 102~103
인쇄쪽: 90~91
시작표지: 7-7. HAM200 집재(춘천․스마트)
끝표지: 7-8. 타워야더(RME 300T)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-8. 타워야더(RME 300T)
PDF쪽: 103~104
인쇄쪽: 91~92
시작표지: 7-8. 타워야더(RME 300T)
끝표지: 7-9. 부착형 타워(K-301, HAM300) 집재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-9. 부착형 타워(K-301, HAM300) 집재
PDF쪽: 104~105
인쇄쪽: 92~93
시작표지: 7-9. 부착형 타워(K-301, HAM300) 집재
끝표지: 7-10. 굴착기 우드그랩 산지집재-병해충방제
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-10. 굴착기 우드그랩 산지집재-병해충방제
PDF쪽: 106
인쇄쪽: 94
시작표지: 7-10. 굴착기 우드그랩 산지집재-병해충방제
끝표지: 7-11. 동력상하차기(우드그래플) 집재-수확
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-11. 동력상하차기(우드그래플) 집재-수확
PDF쪽: 106~107
인쇄쪽: 94~95
시작표지: 7-11. 동력상하차기(우드그래플) 집재-수확
끝표지: 7-12. 동력상하차기(우드그래플) 집적
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-12. 동력상하차기(우드그래플) 집적
PDF쪽: 107~108
인쇄쪽: 95~96
시작표지: 7-12. 동력상하차기(우드그래플) 집적
끝표지: 7-13. 검척
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
: 7-13. 검척
PDF쪽: 108
인쇄쪽: 96
시작표지: 7-13. 검척
끝표지: 7-14. 원목 운반-수확
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 7-14. 원목 운반-수확
PDF쪽: 109
인쇄쪽: 97
시작표지: 7-14. 원목 운반-수확
끝표지: 7-15. 초소형 포워더 운재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 7-15. 초소형 포워더 운재
PDF쪽: 109~110
인쇄쪽: 97~98
시작표지: 7-15. 초소형 포워더 운재
끝표지: 7-16. 소형 포워더 운재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 7-16. 소형 포워더 운재
PDF쪽: 110
인쇄쪽: 98
시작표지: 7-16. 소형 포워더 운재
끝표지: 7-17. 소형트럭 운재
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 7-17. 소형트럭 운재
PDF쪽: 110
인쇄쪽: 98
시작표지: 7-17. 소형트럭 운재
끝표지: 7-18. 지조운반(포워더 활용)
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 7-18. 지조운반(포워더 활용)
PDF쪽: 111
인쇄쪽: 99
시작표지: 7-18. 지조운반(포워더 활용)
끝표지: 제8장 방제
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 제8장 방제
PDF쪽: 112
인쇄쪽: 100
시작표지: 제8장 방제
끝표지: 8-1. 나무주사
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-1. 나무주사
PDF쪽: 112
인쇄쪽: 100
시작표지: 8-1. 나무주사
끝표지: 8-2. 약제주입 기준
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-2. 약제주입 기준
PDF쪽: 113~123
인쇄쪽: 101~111
시작표지: 8-2. 약제주입 기준
끝표지: 8-3. 소각, 매몰, 훈증, 박피
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-3. 소각, 매몰, 훈증, 박피
PDF쪽: 124~125
인쇄쪽: 112~113
시작표지: 8-3. 소각, 매몰, 훈증, 박피
끝표지: 8-4. 끈끈이 롤 트랩
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-4. 끈끈이 롤 트랩
PDF쪽: 126
인쇄쪽: 114
시작표지: 8-4. 끈끈이 롤 트랩
끝표지: 8-5. 페르몬 유인트랩
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-5. 페르몬 유인트랩
PDF쪽: 126
인쇄쪽: 114
시작표지: 8-5. 페르몬 유인트랩
끝표지: 8-6. 약제살포
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-6. 약제살포
PDF쪽: 127~130
인쇄쪽: 115~118
시작표지: 8-6. 약제살포
끝표지: 8-7. 방제 실행 등록
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-7. 방제 실행 등록
PDF쪽: 131
인쇄쪽: 119
시작표지: 8-7. 방제 실행 등록
끝표지: 8-8. 훈증더미 제거
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-8. 훈증더미 제거
PDF쪽: 131
인쇄쪽: 119
시작표지: 8-8. 훈증더미 제거
끝표지: 8-9. 잔가지줍기
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-9. 잔가지줍기
PDF쪽: 132
인쇄쪽: 120
시작표지: 8-9. 잔가지줍기
끝표지: 8-10. 그물망 피복
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-10. 그물망 피복
PDF쪽: 132
인쇄쪽: 120
시작표지: 8-10. 그물망 피복
끝표지: 8-11. 이동식 임목 파쇄
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---
@@ -0,0 +1,14 @@
---
문서: 산림사업 표준품셈(산림청고시 제2025-82호)
절: 8-11. 이동식 임목 파쇄
PDF쪽: 132
인쇄쪽: 120
시작표지: 8-11. 이동식 임목 파쇄
끝표지: 제9장 토공
상태: 대기
작성:
검증:
원천: 글자층
기계검사:
확정지문:
---

Some files were not shown because too many files have changed in this diff Show More