160 lines
15 KiB
Python
160 lines
15 KiB
Python
#!/usr/bin/env python3
|
||
"""exp13 — ФИНАЛИЗАЦИЯ сида v2 (D30.5). Единый воспроизводимый трансформ v1 → v2,
|
||
СУПЕРСИДИТ exp12_glossary_v2.py (дефект провенанса/статусов из ревью D30.5):
|
||
• спорные термины → status:DRAFT (не approved!): 修炼/修行 (культивация), 人祖 (Первопредок),
|
||
род «гу»-зависимые (本命蛊 жизненный гу, 蛊虫 гу-червь), 花酒行者 (перезаписывал пожелание владельца);
|
||
• бесспорные правки/добавления (D30.5: 11 правок + 8 добавлений минус спорные) → approved;
|
||
• откат тихих промоушенов draft→approved (花酒行者, 本命蛊 остаются draft);
|
||
• обогащение мн.ч. (D24.4/полигон-№4): плюрал-формы в decl.forms счётных 元石/凡人/蛊师;
|
||
• gu-gender: НЕ флипаю молча (рекоменд. флагманов «мужской») — проектное решение владельца, в sign-off.
|
||
Вход: guzhenren-seed.yaml. Выход: guzhenren-seed-v2.yaml + diag/glossary_v2_signoff.md. ВНЕ git. НЕ в прод без подписи+resnapshot.
|
||
"""
|
||
from __future__ import annotations
|
||
import yaml
|
||
from pathlib import Path
|
||
|
||
BOOK = Path("/home/ubuntu/books/gu-zhenren")
|
||
SRC = BOOK / "guzhenren-seed.yaml"
|
||
OUT = BOOK / "guzhenren-seed-v2.yaml"
|
||
SIGNOFF = BOOK / "diag" / "glossary_v2_signoff.md"
|
||
|
||
DRAFT = "draft" # спорное — до подписи владельца
|
||
OK = "approved"
|
||
|
||
# src -> (new_dst, forms|None, status, contested_reason|None, rationale)
|
||
CHANGES = {
|
||
"空窍": ("апертура", ["апертуры", "апертуре", "апертуру", "апертурой", "апертуре"], OK, None,
|
||
"оба флагмана — топ-проблема: «врата» ломают грамматику («одни врата»); «апертура» = фан-вики жанра"),
|
||
"开窍": ("открытие апертуры", ["открытия апертуры", "открытию апертуры", "открытием апертуры", "открытии апертуры"], OK, None,
|
||
"согласовано с 空窍→апертура; 开窍大典 = обряд открытия апертуры"),
|
||
"真元": ("истинная ци", ["истинной ци", "истинной ци", "истинную ци", "истинной ци", "истинной ци"], OK, None,
|
||
"оба: НЕ «истинная энергия» (физикализм); ци — жанровая норма; отделить от 元气"),
|
||
"元海": ("море истинной ци", ["моря истинной ци", "морю истинной ци", "морем истинной ци", "море истинной ци"], OK, None,
|
||
"согласовано с 真元→истинная ци"),
|
||
"元石": ("изначальный камень", ["изначального камня", "изначальному камню", "изначальный камень", "изначальным камнем", "изначальном камне"], OK, None,
|
||
"«первокамень» → «двадцать первокамень» читается как «двадцать первый»; согласован с рядом 元"),
|
||
"古月山寨": ("селение Гуюэ", ["селения Гуюэ", "селению Гуюэ", "селением Гуюэ", "селении Гуюэ"], OK, None,
|
||
"«стан» = воинский лагерь; 山寨 здесь — укреплённое селение/деревня"),
|
||
"白家寨": ("селение Бай", ["селения Бай", "селению Бай", "селением Бай", "селении Бай"], OK, None, "согласовано"),
|
||
"熊家寨": ("селение Сюн", ["селения Сюн", "селению Сюн", "селением Сюн", "селении Сюн"], OK, None, "согласовано"),
|
||
# --- СПОРНЫЕ → DRAFT ---
|
||
"本命蛊": ("жизненный гу", ["жизненного гу", "жизненному гу", "жизненного гу", "жизненным гу", "жизненном гу"], DRAFT,
|
||
"род «гу» + выбор рендеринга", "оба: НЕ «гу Жизни» (читается как ВИД). СТАТУС, не вид. Согласование зависит от рода «гу»"),
|
||
"花酒行者": ("Странник Цветов и Вина", ["Странника Цветов и Вина", "Страннику Цветов и Вина", "Странника Цветов и Вина", "Странником Цветов и Вина", "Страннике Цветов и Вина"], DRAFT,
|
||
"перезаписывает пожелание владельца «Винный Странник»", "флагманы: сохранить 花 (=блуд; 采花大盗). Владелец предпочёл «Винный Странник» — за ним"),
|
||
"蛊虫": ("гу-червь", ["гу-червя", "гу-червю", "гу-червя", "гу-червём", "гу-черве"], DRAFT,
|
||
"род «гу»", "«гу-тварь» пейоративно; «гу-червь»/«гу». Согласование зависит от рода «гу»"),
|
||
}
|
||
|
||
# новые термины: dict(src,dst,type,forms|None,invariant,status,contested_reason|None,note)
|
||
ADDITIONS = [
|
||
dict(src="长生", dst="бессмертие", type="term", forms=["бессмертия", "бессмертию", "бессмертие", "бессмертием", "бессмертии"],
|
||
status=OK, contested=None, note="chángshēng; вечная жизнь/бессмертие — сквозная тема; НЕ «долголетие»"),
|
||
dict(src="族长", dst="глава клана", type="title", forms=["главы клана", "главе клана", "главу клана", "главой клана", "главе клана"],
|
||
status=OK, contested=None, note="zúzhǎng; глава клана — НАД старейшинами; черновик путал со «старейшиной». ⚠ консистентность род/клан — см. sign-off"),
|
||
dict(src="家老", dst="старейшина", type="title", forms=["старейшины", "старейшине", "старейшину", "старейшиной", "старейшине"],
|
||
status=OK, contested=None, note="jiālǎo; старейшина клана; развести с 族长"),
|
||
dict(src="困境", dst="Беды", type="term", forms=["Бед", "Бедам", "Беды", "Бедами", "Бедах"],
|
||
status=OK, contested=None, note="kùnjìng; стая зверей в легенде о Первопредке; имя стаи"),
|
||
dict(src="炼化", dst="очистить и подчинить", type="term", forms=[], invariant=True,
|
||
status=OK, contested=None, note="liànhuà; очистить-и-подчинить живого гу; НЕ «переплавить». Кратко «очистить»"),
|
||
# --- СПОРНЫЕ → DRAFT ---
|
||
dict(src="修炼", dst="культивация", type="term", forms=["культивации", "культивации", "культивацию", "культивацией", "культивации"],
|
||
status=DRAFT, contested="лит.альтернатива «совершенствование» (флагманы для издания)", note="xiūliàn; культивация/культивировать"),
|
||
dict(src="修行", dst="культивация", type="term", forms=["культивации", "культивации", "культивацию", "культивацией", "культивации"],
|
||
status=DRAFT, contested="как 修炼", note="xiūxíng; практика культивации; согласовано с 修炼"),
|
||
dict(src="人祖", dst="Первопредок", type="name", forms=["Первопредка", "Первопредку", "Первопредка", "Первопредком", "Первопредке"],
|
||
status=DRAFT, contested="альт-имя «Жэнь Цзу» (Палладица)", note="Rénzǔ; говорящее имя (Праотец человечества). НЕ «Рен Зу» (англ.релей-ошибка)"),
|
||
]
|
||
|
||
# обогащение мн.ч. (D24.4): src -> плюрал-формы (append к decl.forms), закрывает inflection_gap
|
||
PLURALS = {
|
||
"元石": ["изначальные камни", "изначальных камней", "изначальным камням", "изначальными камнями", "изначальных камнях"],
|
||
"凡人": ["смертные", "смертных", "смертным", "смертными"],
|
||
"蛊师": ["гу-мастеров", "гу-мастерам", "гу-мастерами", "гу-мастерах"],
|
||
}
|
||
|
||
GU_FLAG = ("РОД «гу»: сид держит НЕСКЛОНЯЕМЫЙ СРЕДНИЙ; оба флагмана рекомендуют МУЖСКОЙ («этот гу», как «жук»; "
|
||
"согласуется с «винный червь — он»). Меняет согласование во ВСЕХ гу-именах — НЕ флипаю молча. "
|
||
"Жизненный гу/гу-червь даны в мужском как рекомендация под status:draft. Решение — за владельцем.")
|
||
|
||
|
||
def main():
|
||
data = yaml.safe_load(SRC.read_text(encoding="utf-8"))
|
||
terms = data["terms"]
|
||
changed, added, plural_done, rollbacks = [], [], [], []
|
||
|
||
for t in terms:
|
||
s = t.get("src")
|
||
if s in CHANGES:
|
||
new_dst, forms, status, contested, rat = CHANGES[s]
|
||
old_dst, old_status = t.get("dst"), t.get("status")
|
||
t["dst"] = new_dst
|
||
if forms is not None:
|
||
t["decl"] = {"invariant": False, "forms": list(forms)}
|
||
t["status"] = status
|
||
tag = "DRAFT⚑" if status == DRAFT else "OK"
|
||
t["note"] = f"[v2:{tag}] {rat}. (было: «{old_dst}»). " + t.get("note", "")
|
||
changed.append((s, old_dst, new_dst, status, contested, rat))
|
||
if old_status == DRAFT and status == DRAFT and contested:
|
||
rollbacks.append((s, "оставлен draft (тихий промоушен НЕ применён)"))
|
||
if s in PLURALS:
|
||
forms = t.setdefault("decl", {}).setdefault("forms", [])
|
||
for f in PLURALS[s]:
|
||
if f not in forms:
|
||
forms.append(f)
|
||
t["note"] = t.get("note", "") + " [v2: +мн.ч. D24.4]"
|
||
plural_done.append((s, t["dst"], PLURALS[s]))
|
||
|
||
for a in ADDITIONS:
|
||
entry = {"src": a["src"], "dst": a["dst"], "type": a["type"],
|
||
"decl": {"invariant": a.get("invariant", False), "forms": list(a.get("forms", []))},
|
||
"since_ch": 0, "status": a["status"],
|
||
"note": f"[v2-NEW:{'DRAFT⚑' if a['status']==DRAFT else 'OK'}] {a['note']}"}
|
||
terms.append(entry)
|
||
added.append((a["src"], a["dst"], a["status"], a.get("contested"), a["note"]))
|
||
|
||
OUT.write_text(yaml.dump(data, allow_unicode=True, sort_keys=False, width=200), encoding="utf-8")
|
||
|
||
# --- sign-off table для владельца ---
|
||
contested_changes = [(s, o, n, c) for s, o, n, st, c, _ in changed if st == DRAFT]
|
||
contested_adds = [(s, d, c) for s, d, st, c, _ in added if st == DRAFT]
|
||
lg = ["# Глоссарий 蛊真人 — v2 · таблица на ПОДПИСЬ владельца (D30.5)", "",
|
||
f"Изменено: {len(changed)} · Добавлено: {len(added)} · Обогащено мн.ч.: {len(plural_done)} · Всего терминов: {len(terms)}",
|
||
"Провенанс: единый трансформ `eval/exp13_seed_v2.py` из v1-сида; рекомендации — консенсус флагманов "
|
||
"(GPT+Claude, diag/reading/ОЦЕНКА_ФЛАГМАНА.md) + пожелания владельца. **НЕ в прод без подписи + resnapshot.**",
|
||
"Статусы: **approved** = применяю (бесспорное); **draft⚑** = НЕ уходит в CONFIRMED-hard-constraints до твоей подписи (memory.go:419/473).", "",
|
||
"## A. Спорные — на решение (сейчас status:draft, инъектятся как ⟨проверить⟩)", "",
|
||
"| src | вариант в v2 | альтернатива / причина спора | твоё решение |", "|---|---|---|---|"]
|
||
for s, o, n, c in contested_changes:
|
||
lg.append(f"| {s} | **{n}** (было «{o}») | {c} | ☐ принять / ☐ альтернатива |")
|
||
for s, d, c in contested_adds:
|
||
lg.append(f"| {s} | **{d}** | {c} | ☐ принять / ☐ альтернатива |")
|
||
lg += ["", f"- **Род «гу»** (проектное, влияет на согласование всех гу-имён): {GU_FLAG}", ""]
|
||
lg += ["## B. Бесспорные — применены (status:approved)", "",
|
||
"| src | было | стало | почему |", "|---|---|---|---|"]
|
||
for s, o, n, st, c, rat in changed:
|
||
if st == OK:
|
||
lg.append(f"| {s} | {o} | **{n}** | {rat} |")
|
||
for s, d, st, c, note in added:
|
||
if st == OK:
|
||
lg.append(f"| {s} | — (новый) | **{d}** | {note} |")
|
||
lg += ["", "## C. Обогащение мн.ч. (D24.4/полигон-№4 — закрывает inflection_gap post-check)", "",
|
||
"| src | dst | добавленные формы |", "|---|---|---|"]
|
||
for s, d, forms in plural_done:
|
||
lg.append(f"| {s} | {d} | {', '.join(forms)} |")
|
||
lg += ["", "## D. Прочие открытые флаги сида (уже draft в v1, не трогаю без тебя)",
|
||
"- 花酒行者/Винный Странник, 甲乙丙丁/разряд А–Г, 蛊虫/гу-червь, 本命蛊/жизненный гу, 南疆/Наньцзян,",
|
||
" 一气金光虫/Золотосветный червь, 青丝蛊/гу Чёрных волос, 留影存声蛊 (длинное имя), 沈嬷嬷/матушка Шэнь.",
|
||
"- ⚠ Консистентность **род/клан**: 族长→«глава клана» (новый) vs 四代族长→«Четвёртый глава рода» (v1). Унифицировать? ☐ клан ☐ род"]
|
||
SIGNOFF.write_text("\n".join(lg), encoding="utf-8")
|
||
|
||
print(f"v2 seed → {OUT}")
|
||
print(f"sign-off → {SIGNOFF}")
|
||
print(f"изменено {len(changed)} (спорных→draft: {len(contested_changes)}), "
|
||
f"добавлено {len(added)} (спорных→draft: {len(contested_adds)}), мн.ч. {len(plural_done)}, всего {len(terms)}")
|
||
print("Спорные (draft):", [s for s, *_ in contested_changes] + [s for s, *_ in contested_adds])
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|