Restore three rules the first prompt draft dropped and gate every battle-prompt rule by declared disposition
This commit is contained in:
parent
7f15323a8d
commit
824bd209eb
2 changed files with 142 additions and 4 deletions
|
|
@ -37,14 +37,22 @@
|
|||
исходного не стоит. Буквальность здесь не достоинство. Если выбор стоит между точной калькой и
|
||||
живой русской фразой — бери живую фразу.
|
||||
|
||||
ЧЕГО НЕЛЬЗЯ — четыре запрета, и они жёсткие:
|
||||
У этой свободы одна граница, и она важнее всего списка выше: ПОВТОР, СТОЯЩИЙ В ПАРАЛЛЕЛЬНЫХ
|
||||
ПОЗИЦИЯХ САМОГО ИСХОДНИКА, — авторский рефрен, а не бедность словаря. Такой повтор сохраняй и НЕ
|
||||
«разнообразь» лексику там, где автор повторяется намеренно.
|
||||
|
||||
ЧЕГО НЕЛЬЗЯ — пять запретов, и они жёсткие:
|
||||
1. Перевирать факт: участника действия, отрицание, число, ранг, меру, родство, кто кому что
|
||||
сказал. Полярность и адресат неприкосновенны.
|
||||
2. Терять смысловые ходы. Дробить и сливать можно; выбрасывать нельзя. Ничего не добавляй от себя
|
||||
как факт — связка и уточнение допустимы, новое событие нет.
|
||||
3. Менять канон. Имена, термины и реалии — строго в тех формах, что даны в глоссарии ниже,
|
||||
как факт — связка и уточнение допустимы, новое событие нет; сцены не пересочиняй.
|
||||
3. Переводить буквально жест, идиому и реалию. Это три места, где подстрочник врёт чаще всего:
|
||||
поклон — не «ударил головой»; идиому передавай смыслом, не сворачивая её в общее место и не
|
||||
калькируя дословно; реалию сперва пойми, а потом переводи — неверно понятая реалия остаётся
|
||||
ошибкой смысла, даже если фраза звучит гладко.
|
||||
4. Менять канон. Имена, термины и реалии — строго в тех формах, что даны в глоссарии ниже,
|
||||
склоняя по контексту. Своих вариантов не придумывай.
|
||||
4. Оставлять в выводе исходный язык, служебные преамбулы, комментарии, пояснения, заметки о
|
||||
5. Оставлять в выводе исходный язык, служебные преамбулы, комментарии, пояснения, заметки о
|
||||
решениях и markdown-заголовки.
|
||||
|
||||
РЕГИСТР — держи тот же градус, что в исходнике:
|
||||
|
|
|
|||
|
|
@ -150,6 +150,124 @@ def rol_msgs(p: str, src: str) -> list[dict]:
|
|||
return out
|
||||
|
||||
|
||||
# ── ГЕЙТ ПОКРЫТИЯ БОЕВЫХ ПРОМТОВ ─────────────────────────────────────────────────────────────
|
||||
# ⚠⚠ ЗАВЕДЁН ПО ЗАМЕЧАНИЮ ВЛАДЕЛЬЦА 20.08 («там же довольно много пропущено?»), И ЗАМЕЧАНИЕ БЫЛО
|
||||
# ВЕРНЫМ. Первая редакция нового промта молча потеряла три правила боевых промтов, и одно из них
|
||||
# потеряла ОПАСНО: «повтор в параллельных позициях исходника — авторский рефрен, сохраняй его» —
|
||||
# при том что новый промт прямо говорит «буквальность не достоинство», то есть толкает в обратную
|
||||
# сторону. Ещё два: «кальки жестов и идиом · неверно понятые реалии» и «не пересочиняй сцены».
|
||||
#
|
||||
# Обещание «я всё перенёс» проверяемо только механизмом, поэтому вот он. Каждое ПРАВИЛО боевых
|
||||
# промтов перечислено ниже характерной подстрокой, и у каждого объявлена ДИСПОЗИЦИЯ:
|
||||
# "промт" — правило стоит в ядре нового промта (проверяется вхождением ключевых слов);
|
||||
# "блок" — правило приезжает пар-блоком дословно (проверяется вхождением самой строки);
|
||||
# "снято" — правило снято СОЗНАТЕЛЬНО, с основанием прямо здесь.
|
||||
# Селфтест роняет замер, если хоть одна строка боевого промта не покрыта ни одной диспозицией:
|
||||
# правка боевого промта чужой зоной сломает мой гейт ГРОМКО, а не тихо изменит смысл арма.
|
||||
COVERAGE: tuple[tuple[str, str, str, str], ...] = (
|
||||
# (файл, характерная подстрока боевого правила, диспозиция, чем закрыто / основание)
|
||||
("translator", "Хонорифики:", "промт", "Хонорифики"),
|
||||
("translator", "Баланс форенизация", "промт", "форенизация/доместикация"),
|
||||
("translator", "Сноски:", "промт", "Сноски"),
|
||||
("translator", "ничего не пропускай", "промт", "выбрасывать нельзя"),
|
||||
("translator", "не добавляй от себя", "промт", "не добавляй от себя"),
|
||||
# ⚠ «смысл» — правило покрыто ПО СОДЕРЖАНИЮ другим, более полным местом промта, но не
|
||||
# дословно. Диспозиция заведена отдельно от «блок» намеренно: смешивать «перенесено буквой» и
|
||||
# «покрыто смыслом» значит потерять различие, на котором и погорела первая редакция.
|
||||
("translator", "НЕ копируй построчную разбивку", "смысл",
|
||||
"Один повествовательный ход оформляй ОДНИМ русским абзацем"),
|
||||
("translator", "избегай канцелярита", "промт", "канцелярита"),
|
||||
("translator", "Единицы и приёмы", "блок", "Единицы и приёмы"),
|
||||
("translator", "Выведи ТОЛЬКО перевод", "промт", "Выведи ТОЛЬКО перевод"),
|
||||
("editor", "искажения смысла", "промт", "Перевирать факт"),
|
||||
("editor", "неверно понятые реалии", "промт", "реалию сперва пойми"),
|
||||
("editor", "кальки жестов и идиом", "промт", "жест, идиому и реалию"),
|
||||
("editor", "а не подстрочником", "промт", "подстрочник врёт"),
|
||||
("editor", "лишние повторы", "промт", "разнообразь"),
|
||||
("editor", "авторский рефрен", "промт", "авторский рефрен"),
|
||||
("editor", "СТРОГО по приведённому глоссарию", "промт", "Менять канон"),
|
||||
("editor", "склоняя по контексту", "промт", "склоняя по контексту"),
|
||||
("editor", "не придумывай иных вариантов", "промт", "Своих вариантов не придумывай"),
|
||||
("editor", "естественные русские абзацы", "смысл",
|
||||
"Один повествовательный ход оформляй ОДНИМ русским абзацем"),
|
||||
("editor", "Реплики прямой речи", "смысл",
|
||||
"Каждую новую реплику начинай с нового абзаца через тире"),
|
||||
("editor", "Сохраняй ПОЛНОТУ", "промт", "Терять смысловые ходы"),
|
||||
("editor", "не пересочиняй сцены", "промт", "сцены не пересочиняй"),
|
||||
("editor", "ДИСКУРС-ПЕРЕВЁРСТКА", "блок", "ДИСКУРС-ПЕРЕВЁРСТКА"),
|
||||
# строки, которые приезжают ПАР-БЛОКАМИ дословно (их тело — данные пары, не наше)
|
||||
("translator", "МЕРЫ", "блок", "Единицы и приёмы"),
|
||||
("translator", "СТИХИ и названия классики", "блок", "Единицы и приёмы"),
|
||||
("translator", "Род и форму имён", "блок", "Единицы и приёмы"),
|
||||
("translator", "РАМОЧНЫЙ РАССКАЗ", "блок", "Единицы и приёмы"),
|
||||
("translator", "ФРАНЦУЗСКИЙ СЛОЙ", "блок", "Единицы и приёмы"),
|
||||
("translator", "РЕЧЕВЫЕ ПОРТРЕТЫ", "блок", "Единицы и приёмы"),
|
||||
("translator", "КАЛЬКИ en→ru", "блок", "Единицы и приёмы"),
|
||||
("translator", "ЗАГЛАВНЫЕ РЕАЛИИ", "блок", "Единицы и приёмы"),
|
||||
# у редактора СВОЯ сжатая копия единиц; в промт едет БОЛЕЕ ПОЛНАЯ версия переводчика
|
||||
("editor", "Единицы и приёмы", "смысл", "Единицы и приёмы"),
|
||||
("editor", "Молча определи смысловые ходы", "блок", "ДИСКУРС-ПЕРЕВЁРСТКА"),
|
||||
("editor", "Один повествовательный ход", "блок", "ДИСКУРС-ПЕРЕВЁРСТКА"),
|
||||
("editor", "Каждую новую реплику", "блок", "ДИСКУРС-ПЕРЕВЁРСТКА"),
|
||||
("editor", "Разрешено объединять и делить", "блок", "ДИСКУРС-ПЕРЕВЁРСТКА"),
|
||||
("editor", "Хонорифики:", "промт", "Хонорифики"),
|
||||
# ⚠ ЕДИНСТВЕННОЕ СОЗНАТЕЛЬНОЕ СНЯТИЕ, И ОНО ОБЪЯВЛЕНО ЗДЕСЬ, А НЕ УМОЛЧАНО. Боевой промт
|
||||
# переводчика требует «не сокращай»; решение владельца 16.08 («вольность не ошибка, живой
|
||||
# язык — приоритет») это правило отменяет, и новый промт прямо разрешает «сворачивать
|
||||
# описание». Полнота при этом охраняется НЕ запретом сокращать, а запретом терять смысловые
|
||||
# ХОДЫ — то есть на уровне содержания, а не числа слов.
|
||||
("translator", "не сокращай", "снято", "решение владельца 16.08: вольность не ошибка"),
|
||||
# Роль редактора-правщика однопроходке не передаётся по построению: чинить нечего.
|
||||
("editor", "Тебе даны ИСХОДНЫЙ текст и его черновой перевод", "снято", "черновика нет"),
|
||||
("editor", "Сверяй смысл черновика", "снято", "черновика нет"),
|
||||
("editor", "художественная редактура черновика", "снято", "черновика нет"),
|
||||
("editor", "Ты — литературный редактор", "снято", "роль задана заново: переводчик"),
|
||||
("editor", "Выведи ТОЛЬКО отредактированный", "снято", "своя строка вывода у переводчика"),
|
||||
("translator", "Ты — профессиональный литературный переводчик", "снято", "роль задана заново"),
|
||||
("translator", "Жанр книги:", "снято", "бриф перенесён своим блоком"),
|
||||
("editor", "Жанр книги:", "снято", "бриф перенесён своим блоком"),
|
||||
)
|
||||
_RULE_MARK = ("- ", "1.", "2.", "3.", "4.", "Ты —", "Жанр", "Твой мандат", "Выведи")
|
||||
|
||||
|
||||
def coverage_report(p: str) -> list[tuple[str, str, str]]:
|
||||
"""[(файл, строка боевого промта, вердикт)] — что покрыто, чем и что не покрыто вовсе."""
|
||||
cfg = PAIRS[p]
|
||||
cfg["wire"]()
|
||||
d = PR.PAIR_DIR[cfg["para"]().key]
|
||||
u = chosen(p)[0]
|
||||
sysall = "\n".join(x["content"] for x in rol_msgs(p, u["source"]) if x["role"] == "system")
|
||||
ub, rb = pair_blocks(p)
|
||||
out = []
|
||||
for fname in ("translator", "editor"):
|
||||
core, _f, _us = PR.load_template(d / f"{fname}.md")
|
||||
for ln in core.splitlines():
|
||||
s = ln.strip()
|
||||
if len(s) < 25 or not s.startswith(_RULE_MARK):
|
||||
continue
|
||||
hits = [c for c in COVERAGE if c[0] == fname and c[1] in s]
|
||||
if not hits:
|
||||
out.append((fname, s[:90], "⛔ НЕ ОБЪЯВЛЕНО НИ ОДНОЙ ДИСПОЗИЦИЕЙ"))
|
||||
continue
|
||||
for _f2, _sub, disp, what in hits:
|
||||
if disp == "снято":
|
||||
out.append((fname, s[:90], f"снято: {what}"))
|
||||
elif disp == "смысл":
|
||||
out.append((fname, s[:90], "покрыто смыслом"
|
||||
if what in sysall else f"⛔ «{what}» НЕТ в промте"))
|
||||
elif disp == "блок":
|
||||
# ⚠ Сверяется САМА СТРОКА боевого промта, а не начало блока: слабая проверка
|
||||
# («блок непустой») пропустила бы усечённый блок, из которого выпала половина
|
||||
# правил. Строка рендерится тем же брифом, иначе `{{venuti}}` не совпадёт.
|
||||
line = PR.render(s, getattr(PR, PR.PAIR_BRIEF[cfg["para"]().key]), "", "")
|
||||
out.append((fname, s[:90],
|
||||
"блок пары ДОСЛОВНО" if line in sysall else "⛔ строка НЕ доехала"))
|
||||
else:
|
||||
out.append((fname, s[:90],
|
||||
"в промте" if what in sysall else f"⛔ «{what}» НЕТ в промте"))
|
||||
return out
|
||||
|
||||
|
||||
def tag(p: str, arm: str, uid: str) -> str:
|
||||
return f"dv-{PAIRS[p]['letter']}-{arm.lower()}-{uid}"
|
||||
|
||||
|
|
@ -354,6 +472,13 @@ def cmd_selftest() -> int:
|
|||
ck(f"{p}: фаза заведена в кассе", cfg["phase"] in MONEY.CEILINGS)
|
||||
ck(f"{p}: две генерации несущей модели — РАЗНЫЕ теги",
|
||||
tag(p, "RN", u["uid"]) != tag(p, "RN2", u["uid"]))
|
||||
# ⚠ ГЕЙТ ПОКРЫТИЯ — главная проверка этого файла. Обещание «я перенёс всё из боевых
|
||||
# промтов» проверяемо только механизмом; замечание владельца 20.08 показало, что на слово
|
||||
# его брать нельзя.
|
||||
rep = coverage_report(p)
|
||||
miss = [r for r in rep if r[2].startswith("⛔")]
|
||||
ck(f"{p}: КАЖДОЕ правило боевых промтов имеет диспозицию и она исполнена",
|
||||
not miss, f"не покрыто {len(miss)} из {len(rep)}: " + " | ".join(r[1][:50] for r in miss[:3]))
|
||||
ck("пары не делят буквы тегов", len({v["letter"] for v in PAIRS.values()}) == len(PAIRS))
|
||||
ck("несущий контраст объявлен один", len(PRIMARY) == 2 and PRIMARY == ("RN", "ZP"))
|
||||
for a, (mo, _g) in ARMS.items():
|
||||
|
|
@ -379,6 +504,11 @@ if __name__ == "__main__":
|
|||
cmd_show(next((x for x in a[1:] if x in PAIRS), "zh"))
|
||||
elif a[0] == "--canon":
|
||||
canon()
|
||||
elif a[0] == "--coverage":
|
||||
for p in ([x for x in a[1:] if x in PAIRS] or list(PAIRS)):
|
||||
print(f"\n=== ПОКРЫТИЕ БОЕВЫХ ПРОМТОВ, пара {p} ===")
|
||||
for fname, line, verdict in coverage_report(p):
|
||||
print(f" [{verdict:32s}] {fname}: {line}")
|
||||
elif a[0] == "--buy":
|
||||
pr = [x for x in a[1:] if x in PAIRS] or list(PAIRS)
|
||||
ar = [x for x in a[1:] if x in ARMS] or list(ARMS)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue