Brandýs-Boleslav
Začni psát pro vyhledávání...

Implementační plán — dopravní model /doprava (orchestrované workflow)

Implementační plán — dopravní model /doprava (orchestrované workflow)

Cíl: nástroj, kterým lze na zastupitelstvu i směrem k veřejnosti věrohodně ukázat, co udělá rozkopání konkrétní ulice s dopravou ve dvojměstí. Stavíme na stávajícím modelu v prohlížeči (MSA + BPR nad MapLibre); SUMO projekt slouží jen k závěrečnému ověření scénářů.

Model orchestrace

  • Orchestrátor (Fable): spouští workflow fází, kontroluje výsledky mezi fázemi, dělá kroky vyžadující prohlížeč nebo rozhodnutí (data z mapové aplikace ŘSD, vizuální kontrola UI, schválení kalibrace), navrhuje commity.
  • Sonnet: mechanické implementační úlohy s přesným zadáním — úpravy kódu podle specifikace, datové JSON soubory, dokumentace z dodaných podkladů.
  • Opus: úlohy vyžadující úsudek — ladění kalibrace, adversariální verifikace změn, návrh metodiky, práce se SUMO.
  • Každá fáze = jeden workflow (Workflow tool). Mezi fázemi orchestrátor čte výsledky a rozhoduje o pokračování. Implementační agenti běží paralelně jen tam, kde mají disjunktní soubory a předem daný kontrakt rozhraní.
  • Po každé fázi: node doprava/tools/test_model.mjs + ruční kontrola v prohlížeči (orchestrátor), commit až po schválení uživatelem.

Pořadí: fáze 0 → 1 jsou závazné (kalibrace potřebuje stabilní ID). Fáze 2–4 navazují volně, fáze 5 je volitelná (kdykoli po fázi 2).


Fáze 0 — Stabilní ID úseků

Uzavírky, sdílené URL i scénáře se dnes odkazují na pořadové číslo featury v sit.geojson; každá regenerace sítě je přečísluje a rozbije odkazy.

Kontrakt rozhraní (závazný pro oba agenty): každá featura dostane v properties stabilní klíč osm ve tvaru "<OSM way id>#<pořadí segmentu>"; JS používá osm, a pokud v datech chybí (síť ještě nepřegenerovaná), spadne zpět na číselné id. Neznámé klíče z URL se tiše přeskočí s upozorněním uživateli.

Úloha Agent Soubory
A. Klíč osm do generátoru sítě Sonnet tools/stahni_sit.py
B. Uzavírky + URL hash na stabilní klíče Sonnet js/app.js, js/graf.js, js/mapa.js
C. Adversariální review A+B, spuštění testu Opus čtení + test_model.mjs
D. Regenerace sítě (GitHub Actions doprava-osm-data.yml), kontrola odkazů orchestrátor

Hotovo, když: regenerace sítě nezneplatní uložené scénáře ani sdílené odkazy (test: uzavřít most, zkopírovat URL, přegenerovat síť, otevřít znovu).

export const meta = {
  name: 'doprava-faze0-stabilni-id',
  description: 'Stabilní ID úseků sítě: generátor + JS přechod na klíče osm',
  phases: [
    { title: 'Implementace', detail: 'dva sonnet agenti paralelně (disjunktní soubory)' },
    { title: 'Verifikace', detail: 'opus adversariální review + test' },
  ],
}
const DIR = '/Users/imac/Github/brandys-pirati/doprava'
const KONTRAKT = `KONTRAKT: každá featura v sit.geojson má v properties klíč "osm" = "<OSM way id>#<pořadí segmentu way>". JS preferuje "osm", fallback na číselné "id", neznámé klíče z URL tiše přeskočí a zobrazí upozornění. Piš česky komentáře i commit-ready kód, zachovej styl souborů.`

phase('Implementace')
const [py, js] = await parallel([
  () => agent(`${KONTRAKT}\nUprav ${DIR}/tools/stahni_sit.py: při dělení way na segmenty přidej do properties featury klíč "osm" (way id + '#' + index segmentu v rámci way). Nic jiného neměň. Vrať stručné shrnutí změn a případná rizika.`,
    { label: 'stahni_sit.py', model: 'sonnet', phase: 'Implementace' }),
  () => agent(`${KONTRAKT}\nUprav v ${DIR}/js soubory app.js, graf.js (a mapa.js jen pokud nutno): uzavírky (stav.zavrene), URL hash #u= a budoucí scénáře referencují stabilní klíč "osm" místo pořadového featId. Interně může zůstat mapování osm->featId vybudované při načtení sítě. Data sit.geojson zatím klíč "osm" NEobsahují — fallback na "id" musí fungovat. Vrať shrnutí změn.`,
    { label: 'js-stabilni-kluce', model: 'sonnet', phase: 'Implementace' }),
])

phase('Verifikace')
const verdikt = await agent(`Adversariálně zkontroluj čerstvé změny v ${DIR} (git diff): 1) dodržení kontraktu: ${KONTRAKT} 2) zpětná kompatibilita starých URL, 3) spusť node ${DIR}/tools/test_model.mjs a přilož výstup. Hledej, co je ROZBITÉ, ne co je hezké. Shrnutí změn implementátorů: PY: ${py} JS: ${js}`,
  { label: 'review', model: 'opus', phase: 'Verifikace',
    schema: { type: 'object', properties: { ok: { type: 'boolean' }, problemy: { type: 'array', items: { type: 'string' } }, testVystup: { type: 'string' } }, required: ['ok', 'problemy'] } })
return { py, js, verdikt }

Krok D po workflow (orchestrátor): gh workflow run doprava-osm-data.yml, po commitu nových dat ruční test odkazů.


Fáze 1 — Kalibrace na data ŘSD

Vstupní krok orchestrátoru (před workflow): z mapové aplikace sčítání (scitani.rsd.cz, předběžná data CSD 2025; křížově finální CSD 2020) vypsat profily v okolí — D10 (u exitů 8 a 14), II/610 (průtahy oběma městy), II/101, II/331, II/245 — a předat je workflow jako args (RPDI, podíl těžkých vozidel, poloha/název úseku). Mapová aplikace je JS bez API, tohle se agentům delegovat nedá.

Úloha Agent Výstup
A. data/kalibrace.json z podkladů + mapování na úseky modelu Sonnet kalibrace.json
B. GEH srovnávací tabulka do test_model.mjs Sonnet rozšířený test
C. Iterativní ladění zony.json (max 6 kol) Opus (smyčka) vyladěné parametry
D. Kontrola struktury poptávky proti ČSÚ dojížďce 2021 Opus zpráva
E. docs/kalibrace.md — tabulka model vs. měření Sonnet dokumentace
F. Schválení kalibrace orchestrátor + uživatel

Hotovo, když: GEH < 5 na ≥ 2/3 profilů, průtahy + most ±20 % vůči měření; tabulka zveřejněná v dokumentaci.

export const meta = {
  name: 'doprava-faze1-kalibrace',
  description: 'Kalibrace modelu na profily ŘSD (CSD 2025/2020), GEH tabulka, ladění zon',
  phases: [
    { title: 'Priprava', detail: 'kalibrace.json + GEH test (sonnet, paralelně)' },
    { title: 'Ladeni', detail: 'opus smyčka nad zony.json' },
    { title: 'Zaver', detail: 'ČSÚ kontrola + dokumentace' },
  ],
}
// args = { profily: [{ id, nazev, silnice, rok, rpdi, podilTezkych, popisPolohy }, ...] }
const DIR = '/Users/imac/Github/brandys-pirati/doprava'
if (!args || !Array.isArray(args.profily) || !args.profily.length) throw new Error('args.profily chybí — nejdřív vypsat profily z scitani.rsd.cz')

phase('Priprava')
const [kal, geh] = await parallel([
  () => agent(`Vytvoř ${DIR}/data/kalibrace.json z těchto profilů ŘSD: ${JSON.stringify(args.profily)}. Ke každému profilu najdi v ${DIR}/data/sit.geojson odpovídající úsek (podle silnice a polohy) a doplň jeho stabilní klíč "osm". Špičkovou hodinovou intenzitu odvoď koeficientem 0.09 z RPDI (ulož koeficient do souboru, ať je změnitelný). Vrať JSON se seznamem profilů a jistotou mapování (vysoká/nízká) u každého.`,
    { label: 'kalibrace.json', model: 'sonnet', phase: 'Priprava' }),
  () => agent(`Rozšiř ${DIR}/tools/test_model.mjs: po výpočtu základního scénáře načti data/kalibrace.json (formát: profily s klíčem "osm" a špičkovou intenzitou) a vypiš tabulku model vs. měření včetně GEH statistiky (GEH = sqrt(2*(M-C)^2/(M+C)), M=model, C=měření, obojí voz/h) a souhrn: kolik profilů má GEH<5. Musí fungovat i bez kalibrace.json (přeskočí se). Vrať shrnutí.`,
    { label: 'geh-test', model: 'sonnet', phase: 'Priprava' }),
])

phase('Ladeni')
let stav = 'první kolo, zatím nic neladěno'
let vysledek = null
for (let kolo = 1; kolo <= 6; kolo++) {
  vysledek = await agent(`Ladíš kalibraci dopravního modelu v ${DIR}. Spusť node ${DIR}/tools/test_model.mjs, prostuduj GEH tabulku. Pokud kritérium (GEH<5 na >=2/3 profilů A průtahy+most do ±20 %) splněno, nic neměň a vrať hotovo=true. Jinak uprav ${DIR}/data/zony.json (váhy w podle reálných počtů obyvatel částí města — ověř webem, tripRate, tau, tauBrana, intenzity bran, matice pruchozi), spusť test znovu a vrať výsledek. Neměň kód modelu, jen parametry. Kontext z minulých kol: ${stav}`,
    { label: `ladeni-kolo-${kolo}`, model: 'opus', phase: 'Ladeni',
      schema: { type: 'object', properties: { hotovo: { type: 'boolean' }, gehOk: { type: 'integer' }, gehCelkem: { type: 'integer' }, zmeny: { type: 'string' }, tabulka: { type: 'string' } }, required: ['hotovo', 'zmeny', 'tabulka'] } })
  log(`Kolo ${kolo}: GEH ok ${vysledek.gehOk}/${vysledek.gehCelkem}`)
  if (vysledek.hotovo) break
  stav = `kolo ${kolo}: ${vysledek.zmeny}; tabulka: ${vysledek.tabulka}`
}

phase('Zaver')
const [csu, dokum] = await parallel([
  () => agent(`Ověř strukturu poptávky modelu ${DIR} proti veřejným datům ČSÚ o dojížďce (SLDB 2021): hlavní proudy Brandýs n. L.-Stará Boleslav <-> Praha, Čelákovice, Mladá Boleslav. Porovnej řádově s OD parami modelu (viz js/poptavka.js + data/zony.json). Vrať zprávu: sedí/nesedí a doporučené korekce.`,
    { label: 'csu-dojizdka', model: 'opus', phase: 'Zaver' }),
  () => agent(`Napiš ${DIR}/docs/kalibrace.md: metodika kalibrace (zdroje ŘSD CSD 2025 předběžná / CSD 2020, koeficient špičkové hodiny), finální srovnávací tabulka model vs. měření s GEH: ${JSON.stringify(vysledek)}, datum, omezení. Česky, věcně, bez marketingu.`,
    { label: 'kalibrace.md', model: 'sonnet', phase: 'Zaver' }),
])
return { kal, geh, ladeni: vysledek, csu, dokum }

Fáze 2 — Kurátorované scénáře jako obsah

Formát data/scenare.json (kontrakt): pole objektů { id, nazev, popis, stav: "planovano"|"probiha"|"hypoteticky", termin, odkaz, useky: [stabilní klíče "osm"] }.

Úloha Agent Soubory
A. Loader scénářů + karty + #s=<id> sdílení, odstranit zadrátované SCENARE Sonnet js/app.js, index.html, css/styl.css
B. Převod 3 stávajících scénářů do JSON + tlačítko „zkopírovat scénář” (export naklikaných uzavírek jako JSON blok) Sonnet data/scenare.json, js/app.js (jiná část)
C. Adversariální review + test Opus
D. Vizuální kontrola v prohlížeči orchestrátor

Pozn.: A a B sahají oba do app.js → běží sekvenčně (pipeline), B dostane shrnutí změn A.

Hotovo, když: nový výkop = jedna položka v JSON bez zásahu do JS; scénář jde sdílet odkazem #s=<id>.

export const meta = {
  name: 'doprava-faze2-scenare',
  description: 'Kurátorované scénáře uzavírek jako data/scenare.json + export tlačítko',
  phases: [{ title: 'Implementace', detail: 'sekvenčně (sdílený app.js)' }, { title: 'Verifikace' }],
}
const DIR = '/Users/imac/Github/brandys-pirati/doprava'
const FORMAT = `FORMÁT scenare.json: pole objektů { id, nazev, popis, stav: "planovano"|"probiha"|"hypoteticky", termin, odkaz, useky: [stabilní klíče "osm"] }. Česky, styl projektu.`

phase('Implementace')
const a = await agent(`${FORMAT}\nV ${DIR}: nahraď zadrátované pole SCENARE v js/app.js načítáním data/scenare.json; karty scénářů zobrazí termín a odkaz (úřední deska); sdílení scénáře přes hash #s=<id> (kombinovatelné s #u=). Vytvoř zatím prázdné/minimální data/scenare.json. Vrať shrnutí změn včetně názvů nových funkcí.`,
  { label: 'loader-scenaru', model: 'sonnet', phase: 'Implementace' })
const b = await agent(`${FORMAT}\nV ${DIR} (naváže na změny: ${a}): 1) převeď původní tři scénáře (most Maxe Švabinského, centrum Brandýsa, Boleslavská) do data/scenare.json — úseky dohledej v data/sit.geojson podle názvů ulic a polohy a použij jejich klíče "osm"; 2) přidej do panelu tlačítko „Zkopírovat scénář", které z aktuálně naklikaných uzavírek sestaví JSON blok ve formátu scénáře a zkopíruje do schránky. Vrať shrnutí.`,
  { label: 'export-a-data', model: 'sonnet', phase: 'Implementace' })

phase('Verifikace')
const verdikt = await agent(`Adversariálně zkontroluj git diff v ${DIR}: ${FORMAT} Ověř: staré URL #u= fungují, #s= načte scénář, prázdný/vadný scenare.json nerozbije aplikaci, export tlačítko generuje validní formát. Spusť node ${DIR}/tools/test_model.mjs. Změny: A: ${a} B: ${b}`,
  { label: 'review', model: 'opus', phase: 'Verifikace',
    schema: { type: 'object', properties: { ok: { type: 'boolean' }, problemy: { type: 'array', items: { type: 'string' } } }, required: ['ok', 'problemy'] } })
return { a, b, verdikt }

Fáze 3 — Metriky srozumitelné laikovi

Úloha Agent Soubory
A. data/mista.json — 6–8 referenčních bodů (Masarykovo nám., centrum St. Boleslavi, poliklinika, nájezd D10, Vrábí, sídliště západ, Zápská) s ověřenými souřadnicemi Sonnet data/mista.json
B. Panel „Typické cesty”: Dijkstra nad finálními časy hran před × po, zvýraznění nárůstů; scénář může určit relevantní dvojice Sonnet js/app.js, js/assignment.js (export), index.html, css
C. Review + kontrola věrohodnosti časů (srovnání s mapy.cz/Google) Opus

Hotovo, když: u aktivní uzavírky panel ukazuje „X → Y: A min → B min”.

export const meta = {
  name: 'doprava-faze3-metriky',
  description: 'Panel „Typické cesty" — doby jízdy mezi referenčními body před × po uzavírce',
  phases: [{ title: 'Implementace' }, { title: 'Verifikace' }],
}
const DIR = '/Users/imac/Github/brandys-pirati/doprava'

phase('Implementace')
const mista = await agent(`Vytvoř ${DIR}/data/mista.json: 6–8 referenčních bodů dvojměstí (Masarykovo náměstí, centrum Staré Boleslavi, poliklinika Brandýs, nájezd D10 exit 14, Vrábí, sídliště západ, Zápská průmyslová zóna) — id, název, lon/lat ověřené přes OSM/web, a seznam výchozích dvojic pro panel (např. sb-centrum -> br-namesti). Vrať obsah souboru.`,
  { label: 'mista.json', model: 'sonnet', phase: 'Implementace' })
const panel = await agent(`V ${DIR} přidej panel „Typické cesty": po každém přepočtu spočítej Dijkstrou nad finálními BPR časy (funkce v js/assignment.js — exportuj co chybí) doby jízdy pro dvojice z data/mista.json (obsah: ${mista}); body přichytávej na síť stejně jako zóny (viz najdiUzel v js/graf.js). Zobraz „X → Y: A min → B min" se zvýrazněním nárůstů; bez uzavírky jen aktuální časy. Scénář v scenare.json může volitelně mít pole "cesty" s preferovanými dvojicemi. Vrať shrnutí.`,
  { label: 'panel-cesty', model: 'sonnet', phase: 'Implementace' })

phase('Verifikace')
const verdikt = await agent(`Zkontroluj git diff v ${DIR} (panel Typické cesty). Kromě korektnosti kódu ověř VĚROHODNOST: spusť node ${DIR}/tools/test_model.mjs, spočti si ručně z dat pár dob jízdy a porovnej s realitou (web: mapy.cz / Google směry, volný provoz). Odchylka >50 % = problém. Změny: ${panel}`,
  { label: 'review-verohodnost', model: 'opus', phase: 'Verifikace',
    schema: { type: 'object', properties: { ok: { type: 'boolean' }, problemy: { type: 'array', items: { type: 'string' } }, srovnaniCasu: { type: 'string' } }, required: ['ok', 'problemy'] } })
return { mista, panel, verdikt }

Fáze 4 — Metodika a publikace

Úloha Agent Výstup
A. Stránka /doprava/metodika/: laická část + technická příloha (MSA, BPR, gravitační model, zdroje, kalibrační tabulka z fáze 1, omezení) Opus (návrh) → Sonnet (Jekyll stránka) metodika
B. Oponentní čtení metodiky („čím by ji napadl dopravní inženýr / politický oponent”) Opus posudek
C. Prolinkování z navigace webu a ze sekce /vykopy/ Sonnet šablony webu
D. Kontrola na mobilu + finální projití orchestrátor + uživatel

Hotovo, když: stránka je odkázaná z webu, obstojí proti oponentnímu posudku a je použitelná z telefonu.

export const meta = {
  name: 'doprava-faze4-metodika',
  description: 'Stránka metodiky, oponentní posudek, prolinkování z webu',
  phases: [{ title: 'Metodika' }, { title: 'Oponentura' }, { title: 'Publikace' }],
}
const DIR = '/Users/imac/Github/brandys-pirati'

phase('Metodika')
const navrh = await agent(`Navrhni obsah stránky metodiky dopravního modelu ${DIR}/doprava (přečti README.md, docs/kalibrace.md, js/assignment.js, js/poptavka.js). Dvě úrovně: 1) srozumitelně pro občana (co model umí/neumí, jak číst mapu), 2) technická příloha (MSA, BPR, gravitační model, zdroje ŘSD/ČSÚ/OSM, kalibrační tabulka, omezení — bez křižovatkových zdržení, orientační boční ulice). Česky. Vrať kompletní text v markdownu.`,
  { label: 'navrh-metodiky', model: 'opus', phase: 'Metodika' })

phase('Oponentura')
const oponentura = await agent(`Jsi kritický oponent (dopravní inženýr najatý protistranou). Najdi v této metodice všechna slabá místa, která by šla napadnout na zastupitelstvu, a navrhni, jak formulace zpevnit či doplnit: ${navrh}`,
  { label: 'oponent', model: 'opus', phase: 'Oponentura' })

phase('Publikace')
const stranka = await agent(`Vytvoř Jekyll stránku metodiky v repu ${DIR} (permalink /doprava/metodika/, zjisti konvence z existujících stránek, např. vykopy.md). Text: ${navrh}\nZapracuj doporučení oponenta: ${oponentura}\nPřidej odkazy: z aplikace /doprava (index.html, patička/panel) a ze sekce /vykopy/ na model i metodiku. Vrať seznam změněných souborů.`,
  { label: 'jekyll-stranka', model: 'sonnet', phase: 'Publikace' })
return { navrh, oponentura, stranka }

Krok D po workflow: orchestrátor projde web v prohlížeči (desktop + mobilní viewport), uživatel schválí publikaci.


Fáze 5 — Ověření mikrosimulací SUMO (volitelné)

Úloha Agent Poznámka
A. Oprava mechaniky uzavírek v sumo-brandys: hrany zakázat, duarouter přepočítá trasy (žádné mazání hran — vozidla se přesměrují, nezmizí) Opus /Users/imac/Github/sumo/sumo-brandys
B. Poptávka v SUMO ze stejných OD dat jako webový model (export ze zony.json + gravitační model) Opus férové srovnání
C. Běh 2–3 kurátorovaných scénářů (most, průtah) + srovnávací tabulka Sonnet (běhy) → Opus (interpretace) docs/validace-sumo.md

Hotovo, když: v metodice může stát „výsledky ověřeny nezávislou mikrosimulací SUMO” s odkazem na srovnání. Workflow skript vznikne až po fázi 2 (potřebuje finální formát scénářů) — úlohy A a B jsou na sobě nezávislé (parallel), C je pipeline přes scénáře.


Backlog (po základních fázích)

  • Z reverifikace fáze 2 (okrajové případy fallbacku konektorů, vědomě odloženo): obklíčení OBOU uzlů brány slepí odjezdový/příjezdový pás do jednoho uzlu; náhradní uzel se hledá přísněji (obousměrná dosažitelnost) než původní přichycení bran a při nenalezení tiše vrátí zónu beze změny; přesun konektoru může snížit vozKm/vozH i při neobslouzeno=0 (řádově −0,7 %, jen při zavírání přímo u modelové brány) — pojistka MEZ_NEOBSLOUZENO to nepokrývá. Dále pre-existující závod při rychlém tahání posuvníkem intenzity (základna se nespočítá, dopad ukáže +0).
  • Z reverifikace fáze 0 (vědomě odloženo): automatický test pořadí výpočtu základny v start() (logika s DOM, v Node se necvičí); assert klicUseku({osm}) === osm a test guardu duplicit v graf.js; kosmetika hashe #u=,, (nezobrazí hlášku, hash zůstane viset).
  • Křižovatkové penalizace (odbočení vlevo, semafory) — zvěrní centrum.
  • Vlastní sčítání dopravy na mostě a klíčových křižovatkách.
  • Částečné uzavírky (kyvadlový provoz = snížená kapacita, třetí stav úseku).
  • MHD vrstva (mhd/) — dopad uzavírek na autobusové linky.
  • Tisková verze mapy pro materiály na zastupitelstvo.

Provozní poznámky

  • Repo brandys-pirati (GitHub Pages, deploy z gitu). /doprava není do fáze 4 prolinkovaná — fáze 0–3 lze mergovat průběžně; fáze 4 je vědomý krok „jde to ven”.
  • Workflow skripty výše jsou připravené k přímému spuštění (Workflow tool); fáze 1 vyžaduje args.profily od orchestrátora (data ze scitani.rsd.cz).
  • Commity navrhuje orchestrátor po schválené verifikaci každé fáze.