diff --git a/AGENTS.md b/AGENTS.md index d6e29c3..a9524de 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -79,8 +79,9 @@ sections/0N-/ # one .md per BOOK (chapter-level list items are merged int (f) EN-каталогами: полные записи не ведутся (WorldCat мёртв) — строка `EN refs` по данным isbnval/OL/ia; (g) ✅-карточка: РГБ обязателен + ≥1 второй каталог если sweep его трогал; (h) старое поле Status-формулировок: единая «маркер + одна фраза». - Migration of 219 legacy cards + linter `tools/check-md.py` — PLANNED (после секций 05–07 стартуют - на v3; legacy мигрируется скриптом ~80%). + **Migration DONE 2026-09-21** (219/219 cards, `tools/migrate_cards_v3.py`, linter + `tools/check-md.py` = 0 issues; Downloads tables rebuilt from MANIFESTs; sec04 #22 = ES section). + New cards (sec05+) start on v3. - **UNIFIED FORMAT — PENDING DISCUSSION (after cards):** SUMMARY (4 layouts), INDEX (3), MANIFEST (3), MISSING (4), dossiers (10+ header variants, «Round N» append logs). - **TODO (later, after 4 sections in order):** `tools/liart.py` — search for opac.liart.ru (РГБИ): diff --git a/sections/01-fundamentals/47-the-way-of-all-women.md b/sections/01-fundamentals/47-the-way-of-all-women.md index b35a12f..5911bdc 100644 --- a/sections/01-fundamentals/47-the-way-of-all-women.md +++ b/sections/01-fundamentals/47-the-way-of-all-women.md @@ -14,9 +14,8 @@ ## Editions — RU | RU title | Publisher | Year | Pages | Translator | ISBN | -| Пути женщин (= *The Way of All Women*; встреч. также «Путь всех женщин») | Клуб Касталия (М.) | 2023 | ? | ? | 978-5-52-116220-8 | |----------|-----------|------|-------|------------|------| -| (not searched yet) | | | | | | +| Пути женщин (= *The Way of All Women*; встреч. также «Путь всех женщин») | Клуб Касталия (М.) | 2023 | ? | ? | 978-5-52-116220-8 | ## Downloads diff --git a/tools/check-md.py b/tools/check-md.py index 3d4f2fe..0730397 100644 --- a/tools/check-md.py +++ b/tools/check-md.py @@ -2,7 +2,11 @@ """Lint book cards against CANON v3 (see AGENTS.md). Usage: python3 tools/check-md.py [section ...] (default: all) Exit code: 0 = clean, 1 = issues found.""" -import re, sys, os, glob +import re, sys, os, glob, importlib.util + +# single source of truth for MANIFEST parsing: the migration tool +_spec = importlib.util.spec_from_file_location("_mig", os.path.join(os.path.dirname(__file__), "migrate_cards_v3.py")) +_mig = importlib.util.module_from_spec(_spec); _spec.loader.exec_module(_mig) ALLOWED_SECTIONS = re.compile(r'^## (Editions — [A-Z]{2}|Downloads|Catalog records|Notes)$') BANNED_SECTIONS = ('## Russian editions', '## Libgen', '## RSL records', '## Verdict', @@ -61,14 +65,14 @@ def lint_card(path, manifest_files): if dm: rows = re.findall(r'^\|\s*(EN|RU\??|\?)\s*\|\s*([0-9]{2}-[a-zA-Z0-9\.\-]+)\s*\|', dm.group(1), re.M) disk = set(os.path.basename(f) for f in glob.glob(f"downloads/{sec_of(path)}/*")) - manifest = set(f for f in manifest_files.get(num, [])) + manifest = set(f for f, _, _ in manifest_files.get(num, [])) for lang, fname in rows: if fname not in disk: issues.append(f'Downloads file not on disk: {fname}') if manifest and fname not in manifest: issues.append(f'Downloads file not in MANIFEST: {fname}') - if manifest and set(f for _, f in rows) != manifest: - extra = manifest - set(f for _, f in rows) + if manifest and set(f for _, f in rows) != set(manifest): + extra = set(manifest) - set(f for _, f in rows) missing = set(f for _, f in rows) - manifest if extra: issues.append(f'MANIFEST files missing from card: {sorted(extra)}') if missing: issues.append(f'card files not in MANIFEST: {sorted(missing)}') @@ -99,19 +103,16 @@ def main(): secdir = f'sections/{sec}' if not os.path.isdir(secdir): continue - # manifest file sets - mfiles = {} - mp = f'downloads/{sec}/MANIFEST.md' - if os.path.exists(mp): - mt = open(mp).read() - for f in re.findall(r'([0-9]{2}-[a-zA-Z0-9\.\-]+\.(?:pdf|fb2|epub|doc|docx|chm|djvu|txt|zip|azw3))', mt): - mfiles.setdefault(f[:2], set()).add(f) + mfiles = _mig.parse_manifest_files(f'downloads/{sec}/MANIFEST.md') ncards = 0 for p in sorted(glob.glob(f'{secdir}/[0-9][0-9]-*.md')): ncards += 1 for i in lint_card(p, mfiles): total += 1 print(f'{p}: {i}') + if ncards == 0: + print(f'{sec}: 0 cards (skipped)') + continue for i in lint_index_status(secdir): total += 1 print(f'{secdir}/INDEX: {i}')