diff --git a/resources/data_cost_input_value/_manifest.json b/resources/data_cost_input_value/_manifest.json index 56945ecf..389c2456 100644 --- a/resources/data_cost_input_value/_manifest.json +++ b/resources/data_cost_input_value/_manifest.json @@ -13,8 +13,8 @@ "file": "coef_2026.json", "dataset_id": "coef", "effective_date": "2026-01-01", - "sha256": "0bc3fe981165e8d320b7c20f4535c545f2f54415427ac60205dac4a72dbb4f19", - "size_bytes": 29413 + "sha256": "daba170cd806374c92e086dec69f9559271c0317a7426e66e9dc841c2ca264bd", + "size_bytes": 31715 }, { "file": "fx_2026-08-14.json", diff --git a/resources/data_cost_input_value/coef_2026.json b/resources/data_cost_input_value/coef_2026.json index b2654f01..51cb6ef4 100644 --- a/resources/data_cost_input_value/coef_2026.json +++ b/resources/data_cost_input_value/coef_2026.json @@ -787,6 +787,7 @@ ] }, "surcharge_mat": { + "used_value_at": "resources/data_material_surcharge/material_surcharge_2026-01-01.json → rates_pct — ⚠ 코드가 읽어 쓰는 값은 저기다. 이 표는 원문 보관용이라 읽는 코드가 없다(두 벌이 아니다).", "unit": "percent", "representation": "full_source_tables", "duplicate_application_prohibited": true, @@ -1108,6 +1109,8 @@ "max": 1.45, "duplicate_group": "암괴나 호박돌이 섞인 점토", "duplicate_index": 1, + "duplicate_same_value": true, + "duplicate_reason": "원문 두 줄 · 값 같음 — 화면에는 한 줄로 보임. 원문은 그대로 둠(임의 보정 없음).", "selection": "pending" }, { @@ -1129,6 +1132,9 @@ "max": 1.45, "duplicate_group": "암괴나 호박돌이 섞인 점토", "duplicate_index": 2, + "duplicate_same_value": true, + "hidden_duplicate": true, + "duplicate_reason": "원문 두 줄 · 값 같음 — 화면에는 한 줄로 보임. 원문은 그대로 둠(임의 보정 없음).", "selection": "pending" } ] @@ -1210,6 +1216,8 @@ "max": 0.95, "duplicate_group": "암괴나 호박돌이 섞인 점토", "duplicate_index": 1, + "duplicate_same_value": true, + "duplicate_reason": "원문 두 줄 · 값 같음 — 화면에는 한 줄로 보임. 원문은 그대로 둠(임의 보정 없음).", "selection": "pending" }, { @@ -1231,6 +1239,9 @@ "max": 0.95, "duplicate_group": "암괴나 호박돌이 섞인 점토", "duplicate_index": 2, + "duplicate_same_value": true, + "hidden_duplicate": true, + "duplicate_reason": "원문 두 줄 · 값 같음 — 화면에는 한 줄로 보임. 원문은 그대로 둠(임의 보정 없음).", "selection": "pending" } ] diff --git a/resources/data_master_labels/labels_2026-01-01.json b/resources/data_master_labels/labels_2026-01-01.json index 4607da7e..d43c8ff1 100644 --- a/resources/data_master_labels/labels_2026-01-01.json +++ b/resources/data_master_labels/labels_2026-01-01.json @@ -2,14 +2,14 @@ "schema_version": "1.0", "dataset_id": "data_master_labels", "effective_date": "2026-01-01", - "generated_at": "2026-09-16T11:39:55+09:00", + "generated_at": "2026-09-16T13:00:09+09:00", "note": "마스터 자료의 **사람이 읽을 이름표**. 값이 아니라 이름만 담는다 — 여기를 고쳐도 계산은 안 바뀐다. Z01 마스터 관리 화면이 표·열 이름을 여기서 읽는다.", "policy": { "labels_only": "값·수식·단가를 담지 않는다. 마스터 파일은 손대지 않는다.", "no_invented_meaning": "뜻을 모르는 열은 name_ko 를 비우고 unknown 에 사유를 적는다. 지어내지 않는다.", "unit_is_label_only": "unit 은 이름표에서만 정한다. 자료에 없는 단위를 만들어 붙이지 않는다.", "counting_rule": "표 = 화면이 표로 그릴 마디(줄이 여럿인 마디). 값 묶음 = 표가 아닌 마디(설명·방침·한 값짜리 요율 따위).", - "brain_kind_table": "갈래는 2026-09-15 브레인 갈래 나눔표를 그대로 따른다(로직 17 · 기초값 9 · 부산물 4 · 씨앗 1).", + "brain_kind_table": "갈래는 2026-09-15 브레인 갈래 나눔표에서 출발한다(로직 17 · 기초값 9 · 부산물 4 · 씨앗 1). 2026-09-16 사용자 판정으로 `structure_unit_observed`·`revetment_sabang` 둘을 **참고 사례**로 옮겼다 — 한 현장 관찰값·교본 설명 섞임이라 기초데이터가 아니다(로직 15 · 참고 사례 2).", "out_of_31": "폴더 지문(_manifest.json) 셋은 브레인 31 밖이다. 부산물이 아니라 **지문** 갈래로 둔다 — 계산이 남긴 기록이 아니라 어느 판으로 셈했는지 못박는 표라 「정본 아님」 딱지가 안 맞는다(2026-09-15 브레인 ②).", "excluded": "강우 IDF 캐시(resources/data_rainfall_idf_cache, 96 파일)는 배수용이라 뺀다.", "merged_tables_rule": "`merged_tables` 는 **기초단가 다섯**(노임·자재·유가·제비율·기계)을 화면이 한 표씩으로 보이려고 여러 원본 표를 모은 자리다. ⚠ **값을 옮기지 않는다** — 열 이름·단위·숨김과 `editable`(고칠 수 있나)만 담는다. `editable: false` 는 다른 값에서 나온 계산값이라 사람이 못 고친다. 기계는 한 표로 안 모이므로 `machine_cost_chain` 이 사슬을 적는다 (2026-09-15 사용자 지시 · 브레인).", @@ -45,6 +45,10 @@ "name_ko": "지문", "summary": "어느 판으로 셈했는지 못박는 자리. 값도 규칙도 아니고 **판을 가리키는 표**다 — 고치지 않는다." }, + "reference": { + "name_ko": "참고 사례", + "summary": "한 현장·한 교본에서 본 값. ⚠ 표준이 아니다 — 근거로 보되 기초데이터처럼 갈아 끼우지 않는다." + }, "seed": { "name_ko": "씨앗", "summary": "앞으로 늘려 갈 첫 벌. 모양을 잡아 두려고 먼저 놓은 것이다." @@ -1090,11 +1094,11 @@ "merged_columns": 89, "files": 34, "tables": 91, - "columns": 456, - "value_groups": 173, + "columns": 462, + "value_groups": 175, "unknown": 0, "value_groups_by_kind": { - "doc": 107, + "doc": 109, "value": 66 } }, @@ -1484,6 +1488,24 @@ "name_ko": "채택 여부", "unit": "", "visible": true + }, + { + "key": "duplicate_same_value", + "name_ko": "값 같은 중복", + "unit": "", + "visible": true + }, + { + "key": "duplicate_reason", + "name_ko": "중복 사유", + "unit": "", + "visible": true + }, + { + "key": "hidden_duplicate", + "name_ko": "접힌 줄", + "unit": "", + "visible": false } ] }, @@ -1529,6 +1551,24 @@ "name_ko": "채택 여부", "unit": "", "visible": true + }, + { + "key": "duplicate_same_value", + "name_ko": "값 같은 중복", + "unit": "", + "visible": true + }, + { + "key": "duplicate_reason", + "name_ko": "중복 사유", + "unit": "", + "visible": true + }, + { + "key": "hidden_duplicate", + "name_ko": "접힌 줄", + "unit": "", + "visible": false } ] }, @@ -1665,6 +1705,12 @@ "name_ko": "값 단위", "summary": "할증은 %다.", "kind": "value" + }, + { + "key": "variables/surcharge_mat/used_value_at", + "name_ko": "쓰는 값이 있는 자리", + "summary": "이 표는 원문 보관용이라 읽는 코드가 없다. 값은 `material_surcharge` 의 `rates_pct` 를 읽는다.", + "kind": "doc" } ] }, @@ -1827,6 +1873,12 @@ "summary": "실무 집계에서 본 할증률. 참고이지 기본값이 아니다.", "kind": "value" }, + { + "key": "original_tables", + "name_ko": "원문 표가 실린 자리", + "summary": "같은 값이 `coef` 의 `surcharge_mat` 에도 있다. ⚠ 두 벌이 아니다 — 저쪽은 원문 보관이고 읽어 쓰는 정본은 여기다.", + "kind": "doc" + }, { "key": "policy", "name_ko": "방침", @@ -2562,9 +2614,9 @@ { "file_id": "revetment_sabang", "path": "resources/data_masonry/revetment_sabang_2026-01-01.json", - "name_ko": "기슭막이 치수(사방)", - "summary": "독립 기슭막이의 높이·계획비탈·둑마루 두께·뒷채움을 한 자리에 둔 벌.", - "kind": "logic", + "name_ko": "기슭막이 치수(사방) — 참고 사례", + "summary": "사방기술교본 값에 설명 글이 섞인 벌. ⚠ 기초데이터가 아니다 — 표준값처럼 쓰지 말고 근거로만 본다(2026-09-16 사용자 판정).", + "kind": "reference", "tables": [], "value_groups": [ { @@ -2596,9 +2648,9 @@ { "file_id": "structure_unit_observed", "path": "resources/data_structure_unit/structure_unit_observed_2026-01-01.json", - "name_ko": "구조물 관측 원단위", - "summary": "품셈에 표준 물량표가 없는 콘크리트 구조물을 실무 설계원본에서 뽑은 벌.", - "kind": "logic", + "name_ko": "구조물 관측 원단위 — 참고 사례", + "summary": "울진소광 **한 현장**을 관찰한 값이다. ⚠ 기초데이터가 아니다 — 규격이 다르면 안 맞고 표준도 아니다(2026-09-16 사용자 판정).", + "kind": "reference", "tables": [ { "key": "double_count_rules/rules", @@ -6320,6 +6372,16 @@ "unit": "", "visible": true }, + "duplicate_reason": { + "name_ko": "중복 사유", + "unit": "", + "visible": true + }, + "duplicate_same_value": { + "name_ko": "값 같은 중복", + "unit": "", + "visible": true + }, "duration_bracket": { "name_ko": "공사기간 구간", "unit": "", @@ -6470,6 +6532,11 @@ "unit": "", "visible": true }, + "hidden_duplicate": { + "name_ko": "접힌 줄", + "unit": "", + "visible": false + }, "hours_per_day": { "name_ko": "1일 근로시간", "unit": "시간", @@ -7479,6 +7546,10 @@ "name_ko": "값 단위", "summary": "할증은 %다." }, + "coef::variables/surcharge_mat/used_value_at": { + "name_ko": "쓰는 값이 있는 자리", + "summary": "이 표는 원문 보관용이라 읽는 코드가 없다. 값은 `material_surcharge` 의 `rates_pct` 를 읽는다." + }, "formwork_reuse::reuse_ratio_pct": { "name_ko": "사용횟수별 기준수량 비율", "summary": "품셈 12-4 — 일위대가 재료비에 걸린다. B08 이 곱하면 이중계상이다." @@ -7599,6 +7670,10 @@ "name_ko": "실무 관측", "summary": "실무 집계에서 본 할증률. 참고이지 기본값이 아니다." }, + "material_surcharge::original_tables": { + "name_ko": "원문 표가 실린 자리", + "summary": "같은 값이 `coef` 의 `surcharge_mat` 에도 있다. ⚠ 두 벌이 아니다 — 저쪽은 원문 보관이고 읽어 쓰는 정본은 여기다." + }, "oil::variables/oil_diesel": { "name_ko": "경유 단가", "summary": "전국평균 경유 값(원/L)." diff --git a/resources/data_material_surcharge/_manifest.json b/resources/data_material_surcharge/_manifest.json index 31b2bde7..a8192720 100644 --- a/resources/data_material_surcharge/_manifest.json +++ b/resources/data_material_surcharge/_manifest.json @@ -6,8 +6,8 @@ "files": [ { "file": "material_surcharge_2026-01-01.json", - "sha256": "30a1e11acb6f6bd52c72e0ff471c96f772917858306ea61f66ecbcb5df433c9f", - "size_bytes": 5087 + "sha256": "1394a39be22ac0eb7476e4bc2b81c1e23c365a4ad5b915befe85d3f0f99023d5", + "size_bytes": 5344 } ] } diff --git a/resources/data_material_surcharge/material_surcharge_2026-01-01.json b/resources/data_material_surcharge/material_surcharge_2026-01-01.json index 2e732b1e..03a971a1 100644 --- a/resources/data_material_surcharge/material_surcharge_2026-01-01.json +++ b/resources/data_material_surcharge/material_surcharge_2026-01-01.json @@ -1,6 +1,7 @@ { "schema_version": "1.0", "dataset_id": "material_surcharge", + "original_tables": "resources/data_cost_input_value/coef_2026.json → variables/surcharge_mat — 원문 표가 실린 자리. ⚠ 값이 겹치지만 이원화가 아니다: 저쪽은 원문 보관이고 읽어 쓰는 정본은 여기(rates_pct)다.", "effective_date": "2026-01-01", "source": { "primary": { diff --git a/resources/tester/test_master_labels_cover.py b/resources/tester/test_master_labels_cover.py index 8e5504f9..8f08bcd7 100644 --- a/resources/tester/test_master_labels_cover.py +++ b/resources/tester/test_master_labels_cover.py @@ -19,7 +19,9 @@ ROOT = Path(__file__).resolve().parents[2] LABELS_PATH = ROOT / "resources" / "data_master_labels" / "labels_2026-01-01.json" #: 브레인 갈래 나눔표(2026-09-15). 폴더 장부(_manifest)는 그 31 밖이라 따로 센다. -BRAIN_KIND_COUNTS = {"logic": 17, "base_value": 9, "byproduct": 4, "seed": 1} +#: 2026-09-16 사용자 판정 — `structure_unit_observed`(울진소광 한 현장 관찰값)와 +#: `revetment_sabang`(교본값에 설명 글 섞임)은 기초데이터가 아니라 **참고 사례**다. +BRAIN_KIND_COUNTS = {"logic": 15, "base_value": 9, "byproduct": 4, "seed": 1, "reference": 2} MANIFEST_PREFIX = "manifest_" META_KEYS = { diff --git a/resources/tester/test_z01_master_data.py b/resources/tester/test_z01_master_data.py index f7f00f68..3814a58e 100644 --- a/resources/tester/test_z01_master_data.py +++ b/resources/tester/test_z01_master_data.py @@ -49,7 +49,15 @@ def test_갈래는_이름표_차례_파일_34_강우_캐시는_없음(client: Te groups = _tree(client)["groups"] assert [g["key"] for g in groups] == [k for k in LABELS["kinds"]] counts = {g["key"]: len(g["files"]) for g in groups} - assert counts == {"logic": 17, "base_value": 9, "byproduct": 4, "fingerprint": 3, "seed": 1} + # 2026-09-16 사용자 판정 — 한 현장 관찰값·교본 설명 섞임 둘은 참고 사례로 옮겼다. + assert counts == { + "logic": 15, + "base_value": 9, + "byproduct": 4, + "reference": 2, + "fingerprint": 3, + "seed": 1, + } assert {g["key"]: g["label"] for g in groups}["base_value"] == "기초값" by_id = {f["file_id"]: f for f in LABELS["files"]} for f in (f for g in groups for f in g["files"]):