1. Shrnutí

Čas se neměří, odvozuje se. Nikdo neloguje hodiny. Nikdo nevyplňuje timesheets.

Člověk deklaruje kapacitu na období. Systém identifikuje work items, na nichž se prokazatelně podílel. Kapacita se ex post rozpadá poměrově mezi relevantní items podle Job Size a míry contribution.

Výsledkem je výkaz, který je vedlejším produktem dodávky, ne separátní administrativní aktivitou.

Model poskytuje dva komplementární pohledy na stejná data:

  • Per-person pohled: jak se kapacita člověka rozloží mezi jeho items → výkazy, timesheets
  • Per-item pohled: jak se práce na itemu rozloží mezi lidi → nákladová alokace, audit per deliverable

2. Terminologie

PojemDefiniceKonfigurace
IteraceDelivery cyklus. Stories se plánují, dodávají a uzavírají.1t (AI-native) / 2t (klasicky)
Planning IntervalPlánovací cyklus. Features se plánují, koordinují a vyhodnocují.5t (4+1 IP) / 10t (8+2 IP)
IP IteraceInnovation & Planning iterace na konci PI.Poslední iterace v PI
Job Size (JS)Relativní odhad velikosti work itemu. Modifikovaná Fibonacci podle WSJF (SAFe 6).1, 2, 3, 5, 8, 13, 20, 40, 100
WSJFPrioritizační skóre: (BV + TC + RR&OE) / JSPer úroveň nezávisle
CWContribution Weight — per-item normalizovaný podíl osoby na itemu (Σ napříč osobami = 1.0 na položce).0–1.0
Signal WeightVáha jednoho typu evidence signálu (commit_author, pr_reviewer, issue_comment), kterou agreguje detect_contributors.py. V configu pod klíčem signals.*.cw_heuristics.yaml
Contribution ScoreΣ vah fired signálů per (osoba, item). Vstup do per-item normalizace. V kódu jako contribution_score.Automaticky
Derived HoursOdvozené hodiny, výstup modelu.Po Iteration Close
Signal Weight → Contribution Score (Σ vah fired signálů) → CW (per-item normalizovaný podíl) → Derived Hours.

3. Architektura modelu

3.1 Tři oddělené vrstvy

VrstvaÚčelKde žije
Operational MetadataŽivá delivery dataGitHub Issues + Projects
Capacity RegistryKapacita lidi, role, FTEYAML / JSON v repo
Evidence & ReportingFrozen snapshoty, výkazy, podpisy/snapshots, /reports, /signed

3.2 Source of truth

GitHub JE source of truth pro: issue hierarchy, ownership, status, Job Size, WSJF inputs, review trail, delivery audit trail.

GitHub NENÍ source of truth pro: hodinovou kapacitu, FTE, derived hours, podpisové stavy. Tyto žijí v evidence vrstvě.

4. Hierarchie work items

Initiative (celý projekt, business case) └── Epic (strategický cíl, 6-9 měsíců) └── Feature (musí se vejít do Planning Intervalu) ├── Story (dodáváno v Iteraci) │ └── Task (technická práce, volitelné) └── Defect (oprava, na úrovni Story)
Initiative
Epic
Feature
Story
Defect
Task

Každá úroveň má vlastní nezávislý Job Size a WSJF. Feature WSJF se nepočítá ze Stories pod ní.

ÚroveňJob Size rozsahGitHub mapping
Initiative1–100 (mod. Fibonacci)Issue Type: Initiative
Epic1–100 (mod. Fibonacci)Issue Type: Epic
Feature1–100 (mod. Fibonacci)Issue Type: Feature
Story1–100 (mod. Fibonacci)Issue Type: Story
Defect1–100 (mod. Fibonacci)Issue Type: Defect
Task— (sub-Story checklist)Issue Type: Task
Modifikovaná Fibonacci škála (1, 2, 3, 5, 8, 13, 20, 40, 100) podle WSJF metodiky SAFe 6. Žádné fixní stropy per úroveň — granularita je odpovědnost týmu při refinementu. Při AI-asistované práci může být i Story s JS=20+ realisticky odpracovatelná v iteraci.
WSJF: (BV + TC + RR&OE) / JS BV = Business Value, TC = Time Criticality, RR&OE = Risk Reduction Počítá se per úroveň nezávisle.
BV — Business Value
TC — Time Criticality
RR&OE — Risk Reduction & Opportunity Enablement
JS — Job Size

5. Model: Evidence-Driven Proportional Allocation

5.1 Protokol plánování iterace

Než EDPA odvodí hodiny (ex-post), tým musí naplánovat iteraci (ex-ante). Plánování vyžaduje potvrzenou kapacitu jako vstup.

  1. Potvrdit kapacitu — Každý člen týmu potvrdí dostupnost. Jde o závazek, ne odhad. Externí spolupracovníci vyjednávají alokaci explicitně. Výsledek: availability: confirmed v people.yaml.
  2. Upravit kapacitu na iteraci (volitelné) — Jednorázové odchylky od baseline (PTO, přesčas, nábor) se zapisují jako per-iterace override do people: bloku iteračního YAML — command /edpa:capacity <iterace> --add --person <id> --hours …. Baseline capacity_per_iteration zůstává; engine použije override a vykáže capacity_baseline + capacity_override. Nastav před uzávěrkou (Stage 1 v /edpa:close-iteration).
  3. Vypočítat Planning CapacityPlanning_Capacity = Σ Capacity[P, I] × planning_factor. planning_factor je vlastnost týmu (konfigurováno per tým v people.yaml pod teams:). Výchozí: 0.8.
  4. Vybrat práci — Vytáhni stories z prioritizovaného backlogu (WSJF pořadí) dokud Σ JobSize nedosáhne historické velocity × planning_factor. Neplánuj na 100%.
  5. Buffer — Zbylých ~20% absorbuje support, maintenance, incidenty a neplánovanou práci. Pokud buffer položky generují evidenci, EDPA je alokuje normálně.
  6. Edge case — Pokud žádná neplánovaná práce nenastane, veškerá kapacita jde na plánované položky. Garance Σ = Capacity platí vždy.
Proč 80%? Plánování na 100% vynucuje jeden ze tří failure modes: nedodané stories, přetížení, nebo scope creep. Heuristika 80% je konzistentní se SAFe load factor, Scrum velocity-based planning a Kanban WIP limits. Různé týmy si mohou zvolit různé faktory podle svého support loadu a zralosti.

5.2 Vstupy

VstupZdrojPříklad
Capacity[P, I]Potvrzeno při Iteration Planning40h
RelevantItems[P, I]Automaticky z GitHub evidence (Story Done + Feature/Epic/Initiative gates)6 items přes 4 úrovně
JobSize[item]Custom field na issueMod. Fibonacci 1–100
cw[P, item]detect_contributors.py — additivní agregace + per-item normalizace0–1.0 (Σ na itemu = 1.0)

5.3 Evidence detection

GitHub signalSignal weightDetekce
Commit author4.00Commit s S-/F-/E-/I-XXX v branchi/zprávě
PR reviewer2.17Schválený PR review (vyjma self)
Issue / PR comment1.46Komentář (boti vyloučeni)
/contribute @osoba weight:XexplicitManuální additivní signál — váha X z direktivy
state_transition0Status přechod (person/at/from→to) — analytics + delivery lead-time, nepřispívá do CW
  • Signály se sčítají additivně do contribution_score per (osoba, item) — žádný „highest wins"
  • Per-item normalizace dává cw share: cw = contribution_score / Σ_persons contribution_score
  • /contribute je rovnocenný signál — nepřepisuje auto-detekci, jen přidává váhu
  • Default váhy nahoře jsou kalibrované Monte Carlo simulací (1000 syntetických scénářů)
Bez per-role korekcí. CW se počítá výhradně signálovou agregací a per-item normalizací (viz § 5.4 níže). Strategická-role bias se řeší kalibrací signálových vah proti ground truth — pokud BO/PM/Arch dostávají málo, kalibrátor zvedne issue_comment a pr_reviewer váhy. Detail v auto-calibration.md.

5.4 Výpočet — single source, sum-and-normalize

contribution_score[P, item] = Σ signal_weight × signal_fired(P, item) cw[P, item] = contribution_score[P, item] / Σpersons contribution_score[*, item] score[P, item] = JobSize[item] × cw[P, item] ratio[P, item] = score[P, item] / Σitems_of_P score DerivedHours[P, item] = ratio[P, item] × Capacity[P, I]
CW je per-item podíl (Σ napříč osobami = 1.0 na položce), ne absolutní role-coupled hodnota. Signály sčítají additivně, normalizují se per-item, engine konzumuje hotové cw.
Příklad: Kalkulátor. Plná specifikace: methodology.md § 5.4.

5.5 Matematické garance (dvě)

1. Per-item: Σpersons cw[*, item] = 1.0 2. Per-person: Σitems DerivedHours[P, *] = Capacity[P, I] Obě platí strukturálně — z konstrukce sum-and-normalize aggregation a ratio normalizace per osobu napříč iteračními položkami. Engine je při běhu validuje a snapshot odmítne zapsat při porušení.

5.6 Co engine kredituje per typ položky

EDPA pracuje se 6 typy issues (S-, F-, E-, I-, D-, T-). Ne všechny se ale zahrnují do výpočtu hodin stejně:

TypDetekce evidenceEngine kreditujeIteration filter
Story (S-)anoano, jen status==Doneexact match (PI-2026-1.1)
Feature (F-)anoano, Done + gate transitionsPI match (PI-2026-1.x)
Epic (E-)anoano, Done + gate transitionsalways (cross-PI)
Initiative (I-)anoano, Done + gate transitionsalways (cross-PI)
Defect (D-)anoano, jen status==Donealways (cross-PI) — záměrně
Task (T-)anone — engine tasks/ neprocházín/a
Defect cross-PI je záměrné. Defekt se nemusí stihnout opravit v iteraci, ve které byl založen — může přetéct i přes hranici PI. Engine ho proto kredituje vždy v iteraci, kdy přejde do Done, bez filtru na původ. To zachycuje skutečnou délku trvání defektu jako evidenci.
Task není deliverable v EDPA modelu. Tasks jsou míněny jako sub-Story breakdown (checklist na issue), ne samostatná položka pro výpočet hodin. Pokud tým commit referencuje T-XXX, evidence se sice detekuje, ale engine pro tu práci nezíská žádný score — práce by se měla připojit k parent Story.

6. Dual-view CW: dvě otázky, jeden dataset

CW = 0.25 pro reviewera může znamenat dvě věci. Jsou to dvě různé otázky — model řeší obě ze stejných dat:

Per-person normalizace

Otázka: Jak se kapacita člověka P rozloží mezi jeho items?

DerivedHours[P, item] = (Score[P, item] / Σ Score[P, *]) × Capacity[P, I] Garance: Σ DerivedHours[P, *] = Capacity

Výstup: výkaz per osoba pro OP TAK

Per-item normalizace

Otázka: Jak se práce na itemu X rozloží mezi lidi?

ItemShare[P, item] = DerivedHours[P, item] / Σ DerivedHours[*, item] Garance: Σ podilu na itemu = 100 %

Výstup: nákladová karta per deliverable

PohledOtázkaVýstupGarance
Per-personKolik hodin P strávil na čem?Výkaz, OP TAKΣ = kapacita
Per-itemKolik lidí a hodin stál item X?Nákladová alokaceΣ podilu = 100%

7. Konfigurace kadence

Varianta A: Klasická (2/10)
CyklusDélka1.0 FTE0.50.25
Iterace2 týdny80h40h20h
PI10 týdnů400h200h100h
Varianta B: AI-Native (1/5)
CyklusDélka1.0 FTE0.50.25
Iterace1 týden40h20h10h
PI5 týdnů200h100h50h
Doporučení: začít na A. Po prvním PI vyhodnotit přechod na B na základě velocity a lead time dat.

8. Učící smyčka

Velocity tracking
Story_Velocity = Σ JS uzavřených Stories / iterace Feature_Velocity = Σ JS uzavřených Features / PI Accuracy = Actual / Planned × 100 %
Kalibrace
  • CW: Po 2–3 iteracích vyhodnotit heuristiku. Rekalibrace signálových vah optimizérem /edpa:calibrate (Monte Carlo + coordinate descent, syntetický korpus).
  • Job Size: Referenční Story “3” ≠ Feature “3”. Per úroveň nezávisle.
  • AI: Vykazuješ čas na dodání, ne minuty kódu. AI → velocity, ne výkaz.

9. Implementace v GitHub

9.1 Native Issue Types & custom fields

EDPA je local-first: engine čte lokální git evidence a backlog YAML, GitHub vrstva je volitelná. Pokud tým GitHub používá, Issue Types jsou nativní funkce GitHubu na úrovni organizace (ne labels, ne custom fields). Spravují se přes issue_types.py setup --org <org>. Filtrování: type:Epic, type:Story atd.

Issue TypePopis
InitiativeBusiness case, investiční záměr
EpicStrategický cíl, 6-9 měsíců
FeatureMusí se vejít do Planning Intervalu
StoryDodáváno v iteraci
DefectDefekt v existující funkcionalitě
TaskTechnická práce
Enabler je label klasifikace (Business vs Enabler), ne Issue Type. Epic může mít label „Enabler“ pro označení Enabler Epicu (SAFe).
Custom fieldTypHodnoty
Job SizeNumberMod. Fibonacci 1–100
BV / TC / RR&OENumberMod. Fibonacci 1–100
WSJF ScoreNumberAuto (Action)
Planning IntervalIteration5 nebo 10 týdnů
IterationIteration1 nebo 2 týdny
TeamSingle selectTýmové hodnoty
Primary OwnerAssigneeAccountable owner
Co nedržet jako GitHub field: Capacity, Derived Hours, FTE, podpisový stav → patří do evidence vrstvy.

9.2 Engine běží lokálně, GitHub vrstva je volitelná

V2 nemá pipeline GitHub Actions. Engine, výpočet WSJF, iteration/PI close i velocity běží lokálně přes /edpa:close-iteration a MCP nástroje. Atribuci řeší post-commit hook (local_evidence.py) — pro každý commit s referencí na EDPA item emituje commit_author, funguje i offline a na GitLab/Forgejo. Hooky se registrují do .git/hooks/, nebo — pokud projekt používá lefthook — přes vytištěný snippet do lefthook.yml.

VrstvaKde běžíFunkce
Engine + výpočetLokálně (/edpa:close-iteration)Score, DerivedHours, snapshot + výkazy (MD/JSON/XLSX) + per-item
AtribuceLokální post-commit hookcommit_author z git historie pro každý item-referencující commit
VelocityLokálně (MCP edpa_flow_metrics)Velocity a flow metriky z lokálních dat
Contribution sync (volitelné)GitHub Action — --with-ciedpa-contribution-sync.yml: po merge PR dopíše pr_reviewer + issue_comment z PR vlákna do evidence[]
Kdy nasadit --with-ci: jen když máte signály, které nežijí v git historii (PR reviews, komentáře) a chcete je započítat. Single-dev / review-light / off-GitHub týmy workflow přeskočí — local evidence stačí.

9.3 Timestamp pole

Každý backlog item nese tři timestamp pole (zapisuje engine při přechodech stavů; pokud tým používá GitHub, naplní se z issue):

PoleZdrojVyužití
created_atVznik položkyCycle time start, item age
updated_atPoslední změna položkyFreshness, řazení
closed_atPřechod do DoneCycle time end, throughput
Tato pole jsou vstupem pro flow metriky (§ 9.4). Žádný obousměrný sync ani řešení konfliktů — jediný zdroj pravdy je lokální YAML v repu.

9.4 Flow Metrics MCP tool

MCP tool edpa_flow_metrics poskytuje analytiku toku práce na základě timestamp polí:

MetrikaVýpočetVyužití
Cycle Timeclosed_at - created_atJak dlouho trvá dodání položky
ThroughputPočet uzavřených položek / iteracePrediktabilita, kapacitní plánování
Item Agenow - created_at (otevřené)Detekce stagnujících položek

9.5 Branch naming & DoR

feature/S-200-omop-parser defect/D-215-upload-validation feature/F-102-anon-engine

CI check blokuje PR bez reference na issue (S-XXX, F-XXX, E-XXX). DoR: Issue Type, Parent, Job Size, BV+TC+RR&OE, Owner.

9b. ID kolize a renumbering (multi-developer setup)

EDPA alokuje ID lokálně (žádný centrální koordinátor) — pokud dva vývojáři současně vytvoří backlog item ze stejného počátečního stavu mainu, oba dostanou stejné ID (např. oba S-5). Kolize se projeví až při merge druhého PR.

4 vrstvy obrany detekují kolizi co nejdřív + poloautomatický recovery tool:

VrstvaKdyToolCo dělá
5 local git commit validate_ids.py --staged (pre-commit hook) Blokuje commit pokud staged backlog má ID nekonzistence (filename ≢ id, missing fields, duplicity)
6 local git push validate_ids.py --pre-push (pre-push hook) Fetch origin, porovná lokálně přidané ID proti origin/main. Pokud ID už existuje na mainu → push BLOKOVÁN
7 PR open/sync (server-side) .github/workflows/edpa-collision-check.yml Spustí renumber_collisions.py --check. Při kolizi: comment na PR s instrukcemi + fail check (PR's merge button disabled)
Recovery po conflictu renumber_collisions.py --apply Přejmenuje lokální file (S-5.md → S-6.md), přepíše id:, updatuje parent: reference v dependent items, bumpne counter

Standardní recovery flow

git fetch origin python3 .edpa/engine/scripts/renumber_collisions.py --apply # Detected 1 collision: S-5 → S-6 git add . && git commit -m "renumber(S-5→S-6): collision with main" git merge origin/main # resolve id_counters.yaml conflict (vezmi MAX hodnotu) git push

Setup pro nový projekt (jednou):

python3 .edpa/engine/scripts/project_setup.py --with-hooks cp .edpa/engine/templates/github-workflows/edpa-collision-check.yml \ .github/workflows/

Plný guide s rozhodovacím stromem a běžnými typy kolizí (single / multi / parent-chain / cascading): docs/dev-collisions.md.

10. Výkazy a audit

10.1 Pipeline

/.edpa/snapshots/ iteration-PI-2026-1.3.json ← frozen snapshot /.edpa/reports/ iteration-PI-2026-1.3/ vykaz-urbanek.md ← čitelný výkaz vykaz-urbanek.json ← strojová data summary.xlsx ← souhrnný Excel item-costs.xlsx ← per-item pohled /signed/ PI-2026-1.3-urbanek.pdf ← BankID podepsaný

10.2 Freeze rule

Po Iteration Close: snapshot je frozen. Evidence se nepřepisuje in-place. Každá oprava je nová revize. Zásadní pro auditní obhajobu.

10.3 Auditni princip

Průkaznost stojí na 5 pilírich:

  1. Lokální git delivery evidence (commit_author, yaml_edit, gate_events, story_activity)
  2. Capacity registry (YAML)
  3. Frozen snapshot (reprodukovatelný vstup)
  4. Reprodukovatelný výpočet (Score = JS × CW; CW = additivní agregace + per-item normalizace)
  5. Podepsaný výstup (BankID, zákon 21/2020 Sb.)

11. Předpoklady a rizika

Předpoklady
  • Všechny items se uzavírají (nedodané se přesouvají)
  • Kapacita potvrzena při Iteration Planning
  • Branch naming dodržen (CI check)
  • Job Size konzistentní per úroveň
  • CW se kalibruje po prvních iteracích
Rizika
RizikoMitigace
Auditor neuznáMetodika + snapshoty + BankID
CW neodpovidaOverride + kalibrace
Commit bez S-/F-/E-XXXCI check blokuje PR
PM/Arch bez commituComments + /contribute
0 items pro osobuProcesní eskalace

12. Srovnání s alternativami

Fixed Split

Předem definované koše (např. 60% Dev, 20% Arch, 20% QA). Hodiny se rozdělují fixně podle role, nezávisle na skutečném příspěvku. Jednoduché, ale nepřesné.

EDPA v2.11.1

Evidence-Driven Proportional Allocation. Hodiny se odvozují automaticky z lokální git evidence (commity, yaml edits, status přechody, in-flight Story aktivita); GitHub Projects + Actions jsou volitelný doplněk. Matematická garance: Σ = Capacity.

Ruční timesheets

Každý člen týmu ručně vyplňuje hodiny. Subjektivní, administrativně náročné, nemá per-item pohled, neauditovatelné bez doplňkové evidence.

VlastnostFixed SplitEDPA v2.11.1Ruční timesheets
Fixované košeAnoNeNe
Prázdné úrovněProblémNeexistujíN/A
Per-person pohledAnoAno (primární)Ano
Per-item pohledNeAno (dual-view)Ne
Cross-funkčníOmezenáPlnáPlná
AutomatizaceStředníVysokáŽádná
Mat. garanceSložitějšíNativněNe

13. Implementační plán

FázeČasObsah
Den 11h/edpa:setup — vendoring enginu do .edpa/engine/, config (edpa.yaml, people.yaml), seed backlogu
Den 1 (volitelné)30 min--with-hooks (git hooky), --with-ci (contribution-sync workflow), --with-rules
Iterace 11–2tPilotní provoz, první výkazy z /edpa:close-iteration
Kalibrace10 min/edpa:calibrate — rekalibrace signálových vah po prvních iteracích
Retro PI 11 denKadence, CW accuracy, velocity, dual-view validace