Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions .github/workflows/analyze-second-book-d1.4a.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Analyze second book D1.4a

on:
push:
branches:
- docs/second-book-evidence-d1.4a
paths:
- .github/workflows/analyze-second-book-d1.4a.yml
workflow_dispatch:

permissions:
contents: read

jobs:
analyze:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install PDF tools
run: sudo apt-get update && sudo apt-get install -y poppler-utils

- name: Analyze retained second-book PDF
shell: bash
run: |
set -euo pipefail
PDF="_archive/source-files/Unlocking-Your-Dream-Student-Ma.pdf"
OUT="artifacts/d1.4a"
mkdir -p "$OUT"

test -f "$PDF"
stat --printf='bytes=%s\n' "$PDF" | tee "$OUT/file-identity.txt"
sha256sum "$PDF" | tee -a "$OUT/file-identity.txt"
file "$PDF" | tee -a "$OUT/file-identity.txt"
pdfinfo "$PDF" | tee "$OUT/pdfinfo.txt"
pdftotext -layout "$PDF" "$OUT/extracted.txt"

python3 - <<'PY'
from pathlib import Path
import json
import re
import statistics

text_path = Path('artifacts/d1.4a/extracted.txt')
text = text_path.read_text(encoding='utf-8', errors='replace')
pages = text.split('\f')
if pages and not pages[-1].strip():
pages.pop()
counts = [len(page.strip()) for page in pages]
word_counts = [len(re.findall(r"\b\w+\b", page, flags=re.UNICODE)) for page in pages]
substantial = sum(count >= 80 for count in counts)
ratio = substantial / len(counts) if counts else 0
headings = []
seen = set()
for page_number, page in enumerate(pages, start=1):
for raw in page.splitlines():
line = re.sub(r'\s+', ' ', raw).strip()
if not 3 <= len(line) <= 90:
continue
if line.isupper() or re.match(r"^[A-Z][A-Za-z'’&:\- ]{3,}$", line):
key = line.casefold()
if key not in seen:
seen.add(key)
headings.append({'page': page_number, 'text': line})
if len(headings) >= 100:
break
if len(headings) >= 100:
break

result = {
'page_count_from_text': len(pages),
'pages_with_substantial_text': substantial,
'searchable_page_ratio': round(ratio, 4),
'total_characters': sum(counts),
'total_words': sum(word_counts),
'median_nonempty_page_characters': statistics.median([c for c in counts if c > 0]) if any(counts) else 0,
'technical_conclusion': (
'direct-text-extraction-viable' if ratio >= 0.85
else 'hybrid-text-and-ocr-likely' if ratio >= 0.35
else 'ocr-first-likely'
),
'first_20_page_character_counts': counts[:20],
'heading_candidates': headings,
'samples': [
{'page': i + 1, 'text': re.sub(r'\s+', ' ', pages[i]).strip()[:1200]}
for i in sorted(set([0, 1, 2, 3, 4, len(pages)//2, max(0, len(pages)-2), max(0, len(pages)-1)]))
if 0 <= i < len(pages)
],
}
Path('artifacts/d1.4a/extractability.json').write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding='utf-8')
print(json.dumps(result, ensure_ascii=False, indent=2))
PY

git log --follow --date=iso-strict --format='%H%x09%aI%x09%s' -- "$PDF" | tee "$OUT/git-history.txt"
git log --all --name-status --date=iso-strict --format='commit %H %aI %s' -- '*Unlocking*' '*Dream-Student*' | tee "$OUT/path-history.txt"

- name: Upload diagnostics
uses: actions/upload-artifact@v4
with:
name: udream-d1-4a-second-book-diagnostics
path: artifacts/d1.4a
retention-days: 30
107 changes: 64 additions & 43 deletions WORK_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,78 @@

| Поле | Текущее значение |
|---|---|
| Состояние | **READY** — незавершённой активной задачи нет |
| Рабочая ветка | `main` |
| Открытый Pull Request | нет |
| Состояние | **IN_PROGRESS** — начат D1.4a second-book evidence and extraction contract |
| Рабочая ветка | `docs/second-book-evidence-d1.4a` |
| Открытый Pull Request | ещё не открыт |
| Стабильный функциональный релиз | `v23.8.0` |
| Документационный/architecture baseline | `23.8.11` — D1.4 two-book architecture завершён |
| Последнее завершённое изменение | PR #31, squash merge `897f89a325c9997f9046455a6df7336e82d2c7d8` |
| Закрытая задача | Issue #30 — D1.4 completed |
| Следующая утверждённая работа | second-book evidence and dataset preparation |

## Завершённый этап D1.4

- создан `docs/TWO_BOOK_ARCHITECTURE.md`;
- создан machine-readable `docs/two-book-architecture.json`;
- добавлен permanent `scripts/validate-two-book-architecture.mjs`;
- GitHub Actions run №129 завершён успешно;
- текущий default остаётся `ru-current-v1`;
- второй сохранённый PDF классифицирован как retained evidence, но не готовый dataset;
- global identity определена как `(dataset_id, record_id)`;
- separate dataset switching выбран первым будущим functional mode;
- combined search определён как federated по отдельным indexes без destructive JSON merge;
- side-by-side comparison требует explicit reviewed relation map;
- определены visible provenance, dataset-aware URLs/history/sharing, atomic activation, cache isolation, fallback и rollback;
- factual uNews patchnote `23.8.11` и новый real PNG сохранены;
- существующие data files, runtime, PWA, package metadata, `versions/` и `_archive/` не изменены;
- Issue #30 закрыт как completed.
| Текущий baseline | `23.8.11`; следующий документационный кандидат будет определён после фактического diff |
| Актуальный `main` при старте | `20325ee0c3d60dbc90b88060dc26b201b6376e6f` |
| Активная задача | Issue #32 — D1.4a second-book evidence and extraction contract |
| Следующий точный шаг | собрать read-only identity, metadata и Git-history evidence для второго PDF, затем создать первый доказательный документ |

## Следующий точный шаг
## Цель

Подготовить проверяемую доказательную базу и безопасный extraction contract для второй сохранённой книги до создания нового logical dataset и до любой реализации selector, combined search или comparison UI.

## Планировалось

- проверить exact path, bytes, SHA-256 и PDF metadata второго сохранённого документа;
- восстановить Git history появления и переименований файла;
- проверить существующие упоминания названия, автора, edition и происхождения;
- разделить сведения на доказанные факты, разумные выводы и неизвестное;
- определить immutable raw-extraction output;
- определить provenance manifest contract;
- определить schema, local-ID и source-reference policy;
- определить validation gates перед регистрацией нового dataset;
- определить retention и rollback;
- не создавать и не изменять данные на этом этапе.

## Планируемые постоянные файлы

Следующую работу начинать только в новой отдельной ветке после создания Issue и обновления этого файла до `IN_PROGRESS`.
- `WORK_STATUS.md`;
- новый документ evidence/extraction contract под `docs/`;
- при необходимости machine-readable contract под `docs/`;
- при необходимости permanent validator под `scripts/`;
- синхронизация `ROADMAP.md`, `VERSION.md` и связанных документов;
- factual uNews patchnote и новое реальное изображение перед PR.

Цель следующего этапа — подготовить доказательства и безопасный extraction contract для второй книги до создания logical dataset:
## Критерии завершения

- доказательства и неизвестное разделены честно;
- second-book PDF identity и retained history зафиксированы;
- extraction output и manifest contracts определены;
- protected paths отсутствуют в diff;
- существующие data files не изменены;
- runtime, PWA, package metadata, `versions/` и `_archive/` не изменены;
- validators и GitHub Actions зелёные;
- PR объединён только после полного diff review;
- Issue #32 закрыт completed;
- `main/WORK_STATUS.md` возвращён в READY.

## Что уже сделано

- D1.4 завершён PR #31, squash merge `897f89a325c9997f9046455a6df7336e82d2c7d8`;
- Issue #30 закрыт completed;
- создан Issue #32 с точными границами D1.4a;
- создана отдельная ветка `docs/second-book-evidence-d1.4a` от актуального `main`;
- ранний handoff сохранён до начала исследования.

## Следующий точный шаг

1. зафиксировать точную identity/edition второй сохранённой работы настолько, насколько позволяют файлы и Git history;
2. отделить доказанные сведения, разумные выводы и неизвестное;
3. определить immutable raw-extraction output и provenance manifest;
4. определить schema, local ID policy, source references, hashes и validation gates;
5. не создавать registered dataset до появления фактического extraction output;
6. не менять `ru-current-v1`, runtime, PWA или существующие data files;
7. не реализовывать selector, combined search или comparison UI на этом этапе.
Read-only проверить `_archive/source-files/Unlocking-Your-Dream-Student-Ma.pdf`: exact bytes, SHA-256, PDF metadata, Git history и все maintained references. Затем создать первый доказательный черновик без изменения PDF, данных или runtime.

## Главные запреты

- не менять и не удалять существующие data files;
- не считать наличие PDF готовым dataset;
- не выполнять destructive merge книг;
- не назначать одинаковые numeric IDs между книгами без evidence;
- не менять runtime, PWA, Service Worker, package metadata, `versions/` или `_archive/`;
- не начинать user-facing selector до готовности и регистрации второй базы;
- не запускать AI-assisted translation experiment до отдельного утверждённого этапа;
- не добавлять API keys или секреты.
- не изменять существующие `data/` файлы;
- не изменять или удалять PDF и `_archive/`;
- не создавать registered second-book dataset без фактического extraction output;
- не добавлять selector, combined search или comparison UI;
- не назначать одинаковые numeric IDs между книгами;
- не менять runtime, PWA, Service Worker, package metadata или `versions/`;
- не запускать AI-assisted translation;
- не добавлять API keys;
- не заявлять source URL, edition или permissions без сохранённого evidence.

## Источник истины

Реальные GitHub-факты — `main`, открытые Pull Request, commits, Actions и Issues — имеют приоритет над памятью ИИ, старыми чатами и локальными незапушенными изменениями.
Реальные GitHub-факты — `main`, текущая ветка, commits, Pull Request, Actions и Issues — имеют приоритет над памятью ИИ, старыми чатами и локальными незапушенными изменениями.
Loading