Skip to content

Кросс-прогонный вики-слой (фаза 5.7) + накопленная работа с 19.08 - #10

Merged
Socialpranker merged 10 commits into
mainfrom
feat/wiki-layer
Sep 1, 2026
Merged

Socialpranker merged 10 commits into
mainfrom
feat/wiki-layer

Conversation

@Socialpranker

Copy link
Copy Markdown
Owner

Два коммита, намеренно раздельных.

1. 8c6c0bd — накопленный дрейф с 19.08

Локальная копия не пушилась 11 дней. Фаза 6.9 (сборка HTML/PDF/DOCX), fetch-лестница с robots.txt и санитайзингом от prompt injection, постобработка роя, диета SKILL.md/workflow.md, счёт блоков отвязан от литерала в тестах. Написано в предыдущих сессиях, в этой не ревьюилось. Отдельным коммитом — чтобы не смешивать с п.2. На этом состоянии: 409 passed.

2. b00f443 — вики-слой и фаза 5.7

У скилла было два слоя из трёх — raw и skills; эволюционировало только знание «где искать», не «что выяснено».

Ключевое решение. Источники сливаются механически по каноническому URL/DOI. Утверждения не сливаются никогда — только рёбра с вердиктом в pairs.jsonl: ошибочное ребро чинится одной строкой, ошибочное слияние необратимо.

Защита от выдуманных противоречий стоит до модели, а не после. Префильтр требует общей сущности И сопоставимого слота; затем авто-вердикты закрывают всё, что не требует суждения — as_of разошлись > 180 дней → superseded, разные единицы → different-claim, разошёлся скоуп → different-claim. У устаревшей цены и другого региона нет пути в «конфликт», сколько бы модель ни была уверена. record отклоняет пачку при одностороннем конфликте.

Гейт. wiki_ingest идёт в finish-up на любой глубине и пишет квитанцию, которую требует validate_phases. Шаг, чей результат лежит вне папки прогона, без гейта тихо перестаёт выполняться.

Проверка

  • 445 passed, ruff и F821 чисто
  • негативные контроли парами с позитивными: молчащий префильтр прошёл бы одни негативные и выглядел зелёным
  • мутации: снят auto_verdict → упало 4 теста, снят префильтр → упало 3
  • живой прогон на 8 ресёрчах вскрыл 2 бага, которых тесты не видели (порядко-зависимая привязка сущностей; хвост Z11-заголовка в ключе) — оба закрыты регрессиями

Известный предел

На разрозненных темах слой тихий: 0 общих источников на 8 ресёрчах. Проверено контрольной группой — клон прогона против вики даёт пары, значит ноль настоящий, а не сломанный замер. Узкое место 5.7 — не логика пар, а заполненность refresh_targets.md §1: сущности несут 14 утверждений из 205. Рычаг — заполнять Z11, а не расширять извлечение на прозу.

…h-лестница, постобработка роя

Дрейф локальной копии, ни разу не пушенный с 19.08. Собран в отдельный
коммит, чтобы не смешиваться с вики-слоем, который идёт следующим.

- Фаза 6.9: сборка HTML/PDF/DOCX из одного источника (build_report.py,
  report_charts.py, mermaid_figures.py, references/report_export.md)
- fetch-лестница: fetch_source.py с robots.txt, санитайзингом от prompt
  injection и fetch_tier; references/fetch_ladder.md, fallback_routes.yaml
- постобработка роя: references/swarm_postprocess.md
- plan_template.md, диета SKILL.md и workflow.md, счёт блоков отвязан от
  литерала в тестах штамповщика

Написано в предыдущих сессиях, мной не ревьюилось. Проверка: 409 passed
на этом состоянии (test_fetch_source.py не собирается — в системном
python3 нет yaml).
У скилла было два слоя из трёх: raw (sources/NN.md, observations.jsonl) и
skills (channels.md/api_sources за гейтом promote_candidates). Между ними
не было ничего, поэтому накапливалось знание «где искать», но не «что
выяснено»: один источник в двух ресёрчах давал два файла со счётом с нуля,
claim из июня был невидим прогону в августе, а противоположные выводы двух
прогонов не замечал никто.

- runner/wiki.py: три реестра в ~/.claude/research/wiki/. Источники
  сливаются по каноническому URL/DOI (arxiv /abs, /pdf, /html, vN — одна
  страница). Утверждения не сливаются НИКОГДА: только рёбра с вердиктом в
  pairs.jsonl — ошибочное ребро чинится строкой, слияние необратимо.
- Фаза 5.7 (medium/deep), до синтеза: расхождение с прошлым ресёрчем
  обязано попасть в отчёт. Префильтр механический (общая сущность И
  совпавшая единица либо Jaccard >= 0.34); авто-вердикты закрывают до
  модели всё, что не требует суждения: as_of > 180 дней -> superseded,
  разные единицы -> different-claim, разошёлся скоуп -> different-claim.
  wiki_pair record отклоняет пачку при одностороннем конфликте: без
  второго as_of он неотличим от устаревшей цифры, без вторых корней — от
  одного источника, процитированного дважды.
- wiki_ingest в finish-up на ЛЮБОЙ глубине + квитанция, которую требует
  validate_phases: негейтованный шаг с результатом вне папки прогона
  тихо перестаёт выполняться.
- wiki_query в discover existing, wiki_lint на инварианты.

Тесты: негативные контроли идут ПАРАМИ с позитивными — молчащий префильтр
прошёл бы одни негативные и выглядел бы зелёным. Мутации: снят auto_verdict
-> упало 4 теста, снят префильтр -> упало 3.

Живой прогон на 8 ресёрчах вскрыл два бага, которых тесты не видели:
привязка сущностей была порядко-зависимой (сущность из 8-го прогона не
цеплялась к первым семи) и в ключ уезжал хвост Z11-заголовка
(«### Rosy — закрыт» -> rosy-закрыт, в тексте не встречается). Оба закрыты
регрессиями; покрытие 4 -> 14 утверждений.

Известный предел: на разрозненных темах слой тихий (0 общих источников на
8 ресёрчах — проверено контрольной группой, ноль настоящий). Узкое место —
не логика пар, а заполненность refresh_targets.md §1.

Проверка: 445 passed, ruff и F821 чисто.

Тесты стамповщика и валидатора фаз в этом коммите несут ещё несколько
строк fixture-правок предыдущих сессий — отделить их от правок под 5.7
построчно было дороже пользы.
Приехало с накопленным дрейфом и валило ruff в CI. Поведение то же.
…я ни разу

fetch_source.load_routes() импортирует yaml, тест зовёт её на уровне модуля.
Зависимость не была объявлена, pytest падал на сборке. protego рядом
прикручен ровно ради этого теста — PyYAML пропустили.
Тесты экспорта отчёта проверяют обработку ошибок build_report, до которой
доходишь только с установленным pandoc. Без него все пять умирали на
«pandoc не найден» — путь экспорта не проверялся в CI ни разу, проходил
только на машине автора.

5.7 добавлена в KNOWN_MISSING: оркестратор её не реализует, как 3.7/5.5/8.
…опускал

pandoc >=3.0 убрал role="doc-endnote" из <li> сноски. FOOTNOTE_ITEM требовал
закрывающую > сразу после id, поэтому на pandoc 2.x (apt в CI) не разбиралась
ни одна сноска.

Вторая половина бага важнее первой: items пуст -> moved == len(items) == 0 ->
проверка «сноска потерялась» проходит. Сборка отдавала ноль сносок как успех.

- регексп по lookahead на id="fnN", безразличен к прочим атрибутам и порядку
- FOOTNOTE_BACK вынесен и ловит backlink по классу, а не по позиции href
- sidenotes() отказывает, когда блок сносок найден, а разобрать из него нечего
- фикстура WRAPPED_PANDOC2 с точным выводом pandoc 2.9.2.1 + тест на отказ
…о <section>

Контейнер сносок меняет тег между версиями pandoc: 2.x и 3.10 дают
<section class="footnotes …">, 3.1.x (apt у ubuntu-latest) — <aside>.
Блок не находился, sidenotes возвращал 0 и это выглядело успехом.

Разбор теперь тег-агностичен, а случай «ссылки на сноски есть, блока нет»
роняет сборку вместо тихого нуля.
Гейт context_budget.py --ci падал по обеим границам:
SKILL.md 8640 > 7500 и always-floor 57837 > 57000. Перебор был
и до этой ветки — на origin/main SKILL.md уже весил 8078 > 7500,
просто CI не доходил до этого шага, падая на тестах выше.

Сначала ужат вики-слой, добавленный этой веткой: механика порогов
прескрина, правила record, обоснования — всё это есть в
references/wiki.md, в SKILL.md осталось только решение и указатель.
Затем сняты пересказы reference-файлов в других фазах и хвосты-
обоснования в «Что НЕ делать» — сами запреты, условия триангуляции,
гейты, блокеры и имена артефактов на месте.

SKILL.md 8640 → 7396 ток, always-floor 57837 → 56592 ток.
@Socialpranker
Socialpranker merged commit 885b3c3 into main Sep 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant