Engine
EDPA — Evidence-Driven Proportional Allocation. Derive hours from Git evidence. No timesheets.
npx -y skills add technomaton/edpa --skill engineAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Run EDPA evidence-driven calculation for an iteration by invoking the vendored engine script (.edpa/engine/scripts/engine.py). The engine reads the materialized evidence[]/contributors[] persisted in each item's YAML (written by the post-commit hook / /edpa:materialize — it does not scan git at compute time), computes CW from cw_heuristics, calculates Score and DerivedHours, validates invariants, and writes results JSON + XLSX + a frozen snapshot. Use when closing an iteration, computing derived hours, or running "EDPA výpočet". Produces the input for the reports skill.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.1 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it
EDPA Engine — Evidence-Driven Calculation
What this does
Computes derived hours for all team members for a given iteration by
running the deterministic engine script. Per ADR-003 ("heavy compute /
file generation → directly script"), this skill is a thin wrapper: it
resolves the iteration argument, shells out to
.edpa/engine/scripts/engine.py, and interprets the output. It never
re-implements the calculation.
One successful run writes, under .edpa/:
| Artifact | Path |
|---|---|
| Engine results | reports/iteration-<ID>/edpa_results.json |
| Excel workbook (Team Summary + Item Costs tabs) | reports/iteration-<ID>/edpa-results.xlsx |
| Frozen audit snapshot (content-hashed) | snapshots/<ID>.json |
Arguments
$ARGUMENTS = iteration ID (e.g., "PI-2026-1.3") or "latest" for most recent closed iteration.
Argument resolution (when $ARGUMENTS is empty)
If $ARGUMENTS is empty, blank, or "help":
- Call MCP tool
edpa_iterations(or read.edpa/iterations/*.yamldirectly). PI/iteration timeline data is reconstructed at runtime from those per-PI and per-iteration YAML files —edpa.yamlno longer carriespis[]. - Present available iterations with status and dates:
Available iterations: PI-2026-1.1 [closed] 2026-04-06–2026-04-17 PI-2026-1.2 [closed] 2026-04-20–2026-05-01 PI-2026-1.3 [closed] 2026-05-04–2026-05-15 PI-2026-1.4 [active] 2026-05-18–2026-05-29 <-- suggested PI-2026-1.5 [planned] 2026-06-01–2026-06-12 (IP) - Default suggestion: the iteration with
status: active. If none is active, suggest the latestclosed. - Ask user: "Which iteration to compute? [suggested-id]"
- If user confirms or provides an ID, proceed. If
.edpa/config/edpa.yamldoes not exist, inform user to run/edpa setupfirst.
Prerequisites
.edpa/config/people.yamlexists (run /edpa:setup first).edpa/config/cw_heuristics.yamlexists (seeded byproject_setup.py; a legacyheuristics.yamlis still accepted as fallback)- Backlog items carry
js:(Job Size) in their YAML — V2 keeps Job Size in the backlog files, not in any GitHub field - The iteration has Done stories/defects/tasks and/or recorded gate transitions
- Evidence is materialized in the item YAML (see "Where the signals come from" below)
Run the engine
python3 .edpa/engine/scripts/engine.py --edpa-root .edpa --iteration <iteration-id>
Never hand-compute. Do not load config with inline Python, do not
hand-calculate scores or hours, and do not hand-write
edpa_results.json. The script is the single deterministic
implementation — it enforces the invariants, stamps the methodology
version into results and snapshot, and produces the XLSX + content-hashed
snapshot the audit trail relies on.
Useful variants:
# Setup doctor — what is configured, what is missing (read-only)
python3 .edpa/engine/scripts/engine.py --status
# Worked example with built-in sample data (writes no files)
python3 .edpa/engine/scripts/engine.py --demo
# Explain one person's allocation from already-computed results
python3 .edpa/engine/scripts/engine.py --edpa-root .edpa \
--iteration <iteration-id> --explain <person-id> [--explain-item <item-id>]
--output <path> overrides the results JSON path.
Interpret the output
- Summary table — stdout ends with a per-person summary (capacity, derived hours, items, invariant status). Relay it to the user.
- Invariants — on a hard invariant failure the engine reports it
and exits 1 (
all_invariants_passed: falsein the JSON). Report which check failed; never "fix" numbers by hand. - Snapshot line —
Snapshot frozen: …on first freeze;refreshed (same content, frozen_at updated)on an identical rerun;new revision (content changed); previous: <ID>.jsonwhen inputs changed. Frozen snapshots are immutable — changed reruns create<ID>_rev<N>.jsoninstead of overwriting. Excel export skipped (install openpyxl for XLSX output)— XLSX needs openpyxl; the JSON results and snapshot are unaffected.
Then:
- Suggest
/edpa:reports <iteration-id>to render per-person timesheets. - Nothing is auto-committed. The engine only writes files; commit
the generated
reports/+snapshots/outputs as part of the iteration-close batch.
Background — what the script computes
For reference when explaining results (the script does all of this; you never re-do it):
-
Pure reader. The engine reads the materialized
evidence[]/contributors[]blocks persisted in each item's YAML. It does not scan git (or callgh) at compute time — so the report equals the persisted state, deterministically, on any machine. -
CW comes from
detect_contributors.pyaggregation: additive signal weights fromcw_heuristics.yaml(contribution_score[P, item] = Σ signal_weight), normalized per item soΣ_persons cw[*, item] = 1.0. Manual/contributeweights stack additively. Role labels (owner/key/reviewer/consulted) are display-time projections, never stored. -
Score per person P:
Score[P, done_item] = JobSize[item] × CW[P, item] # Story / Defect / Task at Done Score[P, gate_event] = JobSize[parent] × gate_weight × CW[P, parent] # Feature/Epic/Initiative transition Score[P, activity] = JobSize[story] × credit_factor × CW[P, story] # in-flight Story yaml_edit activityWhen git history records no transitions and no yaml_edit activity, only Done-item credit fires — the calculation degenerates gracefully to Done-only behaviour (the pre-v1.14
--modeselector is gone). -
Hours:
DerivedHours[P, item] = (Score[P, item] / Σ Score[P, *]) × Capacity[P]. -
Invariants (hard ones halt the run):
Σ DerivedHours[P, *] = Capacity[P] ± 0.01, share ratios sum to 1.0, no negative hours. Missing Job Size warns and skips the item.
Where the signals come from (not the engine's job)
The post-commit hook (local_evidence.py) materializes commit_author,
/contribute, yaml_edit, and state_transition signals as each commit
lands. To backfill history, commits made with EDPA_NO_LOCAL_EVIDENCE=1,
or signals from another machine, run /edpa:materialize (MCP tool
edpa_materialize, or local_evidence.py --materialize --iteration <id>
/ --all-iterations) — idempotent, deduped by ref. PR-thread signals
(pr_reviewer, issue_comment) are materialized by the optional
edpa-contribution-sync CI workflow. The engine then just reads the
result.
Error handling
- Script errors with
--edpa-root or (--iteration + --capacity + --heuristics) required→ always pass--edpa-root .edpain a V2 project (the flag has no default). - PI id instead of iteration id (e.g. "PI-2026-1" not "PI-2026-1.3") →
the engine refuses: a PI label would silently drop every item tagged
<pi>.N. Use/edpa:close-pi <PI>for PI rollups. - No items in iteration → "No closed items found for {iteration}. Check iteration label."
- Missing Job Size → warn per item, excluded from calculation.
- Person with 0 relevant items → 0h derived (process issue, not math issue).
- Evidence missing / contributors empty → the engine does not scan
git to recover it; run
/edpa:materialize <iteration>to persist the signals intoevidence[], then re-run the engine.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.