Jedyna ingerencja w logikę viewera w tym repo, wydzielona do osobnego
commita zgodnie z ustaleniem.
Kolor węzła jest sterowany danymi ("background-color": "data(color)"),
więc odróżnienie kolorem załatwiła sama warstwa danych (poprzedni commit,
zero zmian w viewerze). Kształt już nie — cytoscape'owa tablica stylów
siedzi w viz.js. Dokładamy do niej DOKŁADNIE jedną regułę:
selector: 'node[type = "external"]'
shape: round-diamond, border-style: dotted, font-size: 10
To ta sama konwencja co istniejące reguły node[?stale] i
node[status = "deprecated"] — selektor po polu danych. Reguła jest
wstawiana przed node[?stale], czyli przed node:selected, więc
podświetlenie zaznaczenia nadal wygrywa.
Podmiana dzieje się w locie, na stringu wstawianym do viz.html; plik
viz.js w repo upstream pozostaje nietknięty. Jeśli upstream zmieni
kotwicę, gen_viz.py przerywa z błędem zamiast po cichu wygenerować
viewer bez reguły.
Zweryfikowane: viz.js w viz.html == upstream + ta jedna reguła (diff
bajtowy równy jej długości), viz.css nadal bajt w bajt, składnia
osadzonego JS-a sprawdzona node --check.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gen_viz.py wyciąga adresy z konceptów i dokłada je do window.BUNDLE jako
węzły typu "external" (teal #0d9488, odróżnialne od szarych konceptów)
z krawędzią koncept → link. Cztery niezależne źródła, każde wyłączalne
stałą SOURCES: md-link, bare-url, bare-domain, frontmatter.
Deduplikacja po znormalizowanym URL-u: bez fragmentu #, bez trailing
slash, schemat i host małymi literami. Odfiltrowane domeny techniczne:
github.com/GoogleCloudPlatform, localhost, 192.168.*, 100.*.
Klik w węzeł external otwiera URL w nowej karcie bez zmiany w viewerze:
pełny adres trafia do pola `resource`, które istniejący panel szczegółów
renderuje jako <a target="_blank" rel="noopener"> (viz.js:171-183). To
mniej inwazyjny wariant niż podpinanie się pod cy.on("tap", "node").
Uwaga: body konceptów nie zawiera dziś żadnego adresu http(s):// —
wszystkie adresy obiektów siedzą we frontmatterze (www:, gdzie_szukac:),
w body są tylko gołe domeny. Samo body + http/https dałoby 0 węzłów,
stąd źródła bare-domain i frontmatter.
Logika viewera nietknięta — viz.js i viz.css nadal bajt w bajt z
upstreamu. Bundle bez zmian: 0 zmodyfikowanych plików .md,
check_okf.py nadal zielony.
Wynik: 9 konceptów + 12 external, 23 krawędzie (9 + 14).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
check_okf.py — tylko stdlib, minimalny parser YAML wystarczający dla
frontmatterów w tym bundle'u. Sprawdza trzy warunki z §9:
- każdy nie-zarezerwowany .md ma parsowalny blok frontmattera YAML,
- każdy frontmatter ma niepuste pole `type`,
- pliki zarezerwowane bez frontmattera, poza root index.md, w którym
dozwolone jest wyłącznie okf_version (§11).
Wynik na frontmatterach zweryfikowany krzyżowo z PyYAML; walidator
przetestowany na 5 wstrzykniętych naruszeniach (każde wykryte).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Viewer jest samowystarczalny — bundle jest wpiekany do HTML jako
window.BUNDLE (nodes/edges/bodies), nie ma odczytu .md w runtime, więc
nie potrzeba manifestu ani konkretnej ścieżki serwowania. Źródłem danych
jest gen_viz.py, uruchamiany po zmianach w bundle'u.
Logika viewera (viz.js, viz.css, szkielet templates/viz.html) wstawiona
dosłownie z upstreamu — zweryfikowane bajt w bajt. gen_viz.py koryguje
wyłącznie zbieranie danych, w dwóch miejscach niezgodnych ze spec:
- _extract_links pomijał linki bundle-relative "/..." (generator.py:74),
czyli formę zalecaną w §5.1 — bundle zgodny ze spec dawał graf z 0
krawędzi. Sam viewer te linki rozumie (viz.js:297).
- _walk_concepts pomijał tylko index.md, więc zarezerwowany log.md
trafiał do grafu jako koncept typu "Unknown" (wbrew §3.1).
Wynik: 9 konceptów, 9 krawędzi (było 9 i 0).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- index.md: frontmatter zredukowany do samego okf_version (§6/§11),
body przepisane na listing sekcji w formacie §6.
- Nowy koncept wyjazd.md (type: Trip) przejmuje metadane wyjazdu
(nazwa/grupa/termin) oraz ranking ofert i najbliższe kroki z index.md.
- Każdy koncept dostał title/description/timestamp/tags (§4.1);
polskie pola zostawione bez zmian jako rozszerzenia.
- Wszystkie linki wewnątrz bundle'a na bundle-relative z / (§5.1).
- Nowe: oferty/index.md (§6) i log.md (§7).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>