1. Summary

Time is not measured, it is derived. Nobody logs hours. Nobody fills out timesheets.

A person declares capacity for a period. The system identifies work items they demonstrably contributed to. Capacity is ex post proportionally split among relevant items based on Job Size and contribution level.

The result is a report that is a byproduct of delivery, not a separate administrative activity.

The model provides two complementary views of the same data:

  • Per-person view: how a person's capacity is distributed among their items → reports, timesheets
  • Per-item view: how work on an item is distributed among people → cost allocation, audit per deliverable

2. Terminology

TermDefinitionConfiguration
IterationDelivery cycle. Stories are planned, delivered, and closed.1w (AI-native) / 2w (classic)
Planning IntervalPlanning cycle. Features are planned, coordinated, and evaluated.5w (4+1 IP) / 10w (8+2 IP)
IP IterationInnovation & Planning iteration at the end of PI.Last iteration in PI
Job Size (JS)Relative size estimate of a work item. Modified Fibonacci.1, 2, 3, 5, 8, 13, 20
WSJFPrioritization score: (BV + TC + RR) / JSIndependent per level
CWContribution Weight — degree of a person's involvement on an item. Independent per person.0.15–1.0
Evidence ScoreRaw sum of activity signals from GitHub. Detection layer.Automatic
RSRelevance Signal — normalized signal derived from Evidence Score.Automatic
Derived HoursDerived hours, model output.After Iteration Close
Evidence Score is the detection layer → Relevance Signal is the mathematical input → Contribution Weight is the share → Derived Hours are the output.

3. Model architecture

3.1 Three separate layers

LayerPurposeWhere it lives
Operational MetadataLive delivery dataGitHub Issues + Projects
Capacity RegistryPeople capacity, roles, FTEYAML / JSON in repo
Evidence & ReportingFrozen snapshots, reports, signatures/snapshots, /reports, /signed

3.2 Source of truth

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

GitHub IS NOT source of truth for: hourly capacity, FTE, derived hours, signature states. These live in the evidence layer.

4. Work item hierarchy

Initiative (entire project, business case) └── Epic (strategic goal, 6-9 months) └── Feature (must fit within a Planning Interval) └── Story (delivered in an Iteration) └── Task (technical work, optional)
Initiative
Epic
Feature
Story
Task

Each level has its own independent Job Size and WSJF. Feature WSJF is not computed from Stories below it.

LevelJS maxGitHub mapping
Epic20Issue Type: Epic
Feature13Issue Type: Feature
Story (2/10)8Issue Type: Story
Story (1/5)5Issue Type: Story
TaskIssue Type: Task

Items above the limit are broken down. Granularity guardrails enforce reasonable granularity.

WSJF: (BV + TC + RR) / JS BV = Business Value, TC = Time Criticality, RR = Risk Reduction Computed per level independently.
BV — Business Value
TC — Time Criticality
RR — Risk Reduction
JS — Job Size

5. Model: Evidence-Driven Proportional Allocation

5.1 Iteration Planning Protocol

Before EDPA derives hours (ex-post), the team must plan the iteration (ex-ante). Planning requires confirmed capacity as input.

  1. Confirm Capacity — Each team member confirms availability. This is a commitment, not an estimate. External collaborators negotiate allocation explicitly. Result: availability: confirmed in capacity.yaml.
  2. Calculate Planning CapacityPlanning_Capacity = Σ Capacity[P, I] × planning_factor. The planning_factor is a team-level property (configured per team in capacity.yaml under teams:). Default: 0.8.
  3. Select Work — Pull stories from the prioritized backlog (WSJF order) until Σ JobSize approaches historical velocity × planning_factor. Do not plan to 100%.
  4. Buffer — The remaining ~20% absorbs support, maintenance, incidents, and unplanned work. If buffer items generate evidence, EDPA allocates them normally.
  5. Edge case — If no unplanned work occurs, all capacity goes to planned items. The guarantee Σ = Capacity holds regardless.
Why 80%? Planning to 100% forces one of three failure modes: undelivered stories, overwork, or scope creep. The 80% heuristic aligns with SAFe load factor, Scrum velocity-based planning, and Kanban WIP limits. Different teams may choose different factors based on their support load and maturity.

5.2 Inputs

InputSourceExample
Capacity[P, I]Confirmed at Iteration Planning40h
RelevantItems[P, I]Automatic from GitHub evidence6 items across 3 levels
JobSize[item]Custom field on issueFibonacci 1–20
CW[P, item]From evidence / manual override0.15–1.0
RS[P, item]Normalized from Evidence Score0.25–1.0

5.3 Evidence detection

GitHub signalEvidence ScoreTypical CW
Issue assignee+41.0 (owner)
Explicit /contribute command+3explicit
PR author referencing item+20.6 (key)
Commit author with ref in message+10.25 (reviewer)
PR reviewer+10.25 (reviewer)
Issue / PR comment+0.50.15 (consulted)
  • Threshold: Evidence Score ≥ 1.0
  • Heuristic: strongest signal → default CW
  • Override: /contribute @person weight:0.6
  • Commit count is not converted to time
  • Per-role corrections validated by Monte Carlo simulation (1,000 scenarios)
Monte Carlo CW calibration
RoleOriginal CWCalibrated CWBias
Business Owner1.01.15+0.15
Product Manager0.60.65+0.05
Architect0.60.65+0.05
Developer1.01.00.00

5.4 Calculation — two variants

Audit variant (Full): Score[P, item] = JobSize[item] × CW[P, item] × RS[P, item] DerivedHours[P, item] = (Score[P, item] / ΣScores[P, I]) × Capacity[P, I]
Operational variant (Simple): Score[P, item] = JobSize[item] × CW[P, item] DerivedHours[P, item] = (Score[P, item] / ΣScores[P, I]) × Capacity[P, I]
Recommendation: start with the operational variant. Keep Evidence Score and RS in the snapshot for audit defense.

5.5 Mathematical guarantee

Σ DerivedHours[P, item] = Capacity[P, I] The sum of derived hours exactly equals the person's capacity for the Iteration. Holds for both variants. Always. No exceptions.

6. Dual-view CW: two questions, one dataset

CW = 0.25 for a reviewer can mean two things. These are two different questions — the model solves both from the same data:

Per-person normalization

Question: How is person P's capacity distributed among their items?

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

Output: report per person for audit

Per-item normalization

Question: How is work on item X distributed among people?

ItemShare[P, item] = DerivedHours[P, item] / Σ DerivedHours[*, item] Guarantee: Σ shares per item = 100 %

Output: cost card per deliverable

ViewQuestionOutputGuarantee
Per-personHow many hours did P spend on what?Report, auditΣ = capacity
Per-itemHow many people and hours did item X cost?Cost allocationΣ shares = 100%

7. Cadence configuration

Variant A: Classic (2/10)
CycleDuration1.0 FTE0.50.25
Iteration2 weeks80h40h20h
PI10 weeks400h200h100h
Variant B: AI-Native (1/5)
CycleDuration1.0 FTE0.50.25
Iteration1 week40h20h10h
PI5 weeks200h100h50h
Recommendation: start with A. After the first PI, evaluate transition to B based on velocity and lead time data.

8. Learning loop

Velocity tracking
Story_Velocity = Σ JS of closed Stories / iteration Feature_Velocity = Σ JS of closed Features / PI Accuracy = Actual / Planned × 100 %
Calibration
  • CW: After 2–3 iterations, evaluate the heuristic. PM underestimated? Arch overestimated?
  • Job Size: Reference Story “3” ≠ Feature “3”. Independent per level.
  • AI: You report time for delivery, not minutes of coding. AI → velocity, not report.

9. GitHub implementation

9.1 Custom fields

FieldTypeValues
Issue TypeIssue typeInitiative, Epic, Feature, Story, Task, Bug
Job SizeNumberFibonacci 1–20
BV / TC / RRNumberFibonacci 1–20
WSJF ScoreNumberAuto (Action)
Planning IntervalIteration5 or 10 weeks
IterationIteration1 or 2 weeks
TeamSingle selectTeam values
Primary OwnerAssigneeAccountable owner
What not to keep as a GitHub field: Capacity, Derived Hours, FTE, signature state → belong to the evidence layer.

9.2 GitHub Actions

#ActionTriggerFunction
1WSJF CalculatorField changeAuto WSJF calculation
2Contributor DetectorPR merge / reviewContributor detection + evidence
3Iteration CloseManual dispatchSnapshot + reports (MD/JSON/XLSX) + per-item
4PI CloseManual dispatchIteration aggregation
5Velocity TrackerIter/PI closeVelocity JSON + dashboard

9.3 Branch naming & DoR

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

CI check blocks PRs without reference to an issue (S-XXX, F-XXX, E-XXX). DoR: Issue Type, Parent, Job Size, BV+TC+RR, Owner.

10. Reports and audit

10.1 Pipeline

/snapshots/ iteration-PI-2026-1.3.json ← frozen snapshot /reports/ iteration-PI-2026-1.3/ report-urbanek.md ← human-readable report report-urbanek.json ← machine data summary.xlsx ← summary Excel item-costs.xlsx ← per-item view /signed/ PI-2026-1.3-urbanek.pdf ← BankID signed

10.2 Freeze rule

After Iteration Close: snapshot is frozen. Evidence is not overwritten in-place. Every correction is a new revision. Essential for audit defense.

10.3 Audit principle

Provability rests on 5 pillars:

  1. GitHub delivery evidence
  2. Capacity registry (YAML)
  3. Frozen snapshot (reproducible input)
  4. Reproducible calculation (Score = JS × CW × RS)
  5. Signed output (BankID, law 21/2020 Sb.)

11. Assumptions and risks

Assumptions
  • All items are closed (undelivered items are moved)
  • Capacity confirmed at Iteration Planning
  • Branch naming enforced (CI check)
  • Job Size consistent per level
  • CW is calibrated after the first iterations
Risks
RiskMitigation
Auditor rejectsMethodology + snapshots + BankID
CW mismatchOverride + calibration
Commit without S-/F-/E-XXXCI check blocks PR
PM/Arch without commitsComments + /contribute
0 items for a personProcess escalation

12. Comparison with alternatives

Fixed Split

Pre-defined buckets (e.g., 60% Dev, 20% Arch, 20% QA). Hours are split fixedly by role, regardless of actual contribution. Simple, but inaccurate.

EDPA v1.0.0

Evidence-Driven Proportional Allocation. Hours are derived automatically from GitHub delivery evidence (commits, PRs, reviews). Mathematical guarantee: Σ = Capacity.

Manual timesheets

Each team member manually fills in hours. Subjective, administratively demanding, has no per-item view, unauditable without additional evidence.

PropertyFixed SplitEDPA v1.0.0Manual timesheets
Fixed bucketsYesNoNo
Empty levelsProblemDo not existN/A
Per-person viewYesYes (primary)Yes
Per-item viewNoYes (dual-view)No
Cross-functionalLimitedFullFull
AutomationMediumHighNone
Math. guaranteeComplexNativeNo

13. Implementation plan

PhaseTimeContents
Day 16hGitHub org, Projects setup, custom fields
Week 13 daysActions 1–2 (WSJF + Contributor Detector)
Week 22 daysActions 3–5 (Iteration Close + PI Close + Velocity)
Iteration 11–2wPilot operation, first reports, CW calibration
Retro PI 11 dayCadence, CW accuracy, velocity, dual-view validation