Skip to content

Releases: technomaton/edpa

v2.3.0 — Robust git-hook registration + lefthook support

03 Jun 17:51
96d3402

Choose a tag to compare

Fixes git hooks silently not firing after a plugin update or under lefthook — the post-commit local_evidence.py emitter never ran, so contribution evidence stopped landing on items.

Fixed

  • install_hooks no longer skips a slot with a blunt not dst.exists() guard. EDPA marks hooks with an EDPA-MANAGED-HOOK sentinel and decides per slot: install if missing, refresh if EDPA-owned, never clobber a foreign hook.
  • update_engine.sh (SessionStart auto-update) now re-registers EDPA hooks after a version bump when the project already uses them.

Added

  • lefthook support — detects lefthook.yml and prints a paste-ready snippet (use_stdin: true on pre-push, required or lefthook hangs) instead of writing .git/hooks/.
  • project_setup.py --check-hooks (read-only hooks doctor) and --refresh-hooks (register/refresh only).

Changed

  • scripts/hooks/install.sh → thin delegator to --refresh-hooks; dropped the conflicting core.hooksPath mechanism.
  • ANSI is TTY-aware (no escape-code leak in captured output).
  • Removed the dead generic pre-commit hook and the dead V1 GitHub-Projects sync workflows (referenced a sync.py removed in 2.0.0).

Docs / web

RUNBOOK §1+§6, quick-start, skills/setup/SKILL.md, playbook, README ×2; website setup/guide/playbook/methodology (CZ + EN). Live at https://edpa.technomaton.com (v2.3.0).

Tracked as D-1. Full test suite: 618 passed.

v2.2.1

01 Jun 12:35
48d3bc3

Choose a tag to compare

2.2.1 — 2026-06-01 — Skill names: drop the redundant edpa- prefix; server + create-pi are command-only

Plugin skill invocations were doubly namespaced — /edpa:edpa-setup,
/edpa:edpa-engine, … — because Claude Code derives a skill's slug from its
directory name (skills/edpa-setup//edpa:edpa-setup), not the SKILL.md
name: field. The frontmatter name: and plugin/README.md already advertised
the clean /edpa:setup form, so the picker showed /edpa:setup but inserted
/edpa:edpa-setup — a half-finished rename. This completes it.

refactor(skills): rename 5 skill dirs to drop the prefix

skills/edpa-{setup,add,engine,reports,autocalib}skills/{setup,add,engine,reports,autocalib},
and each SKILL.md name: is now the bare slug matching its directory.
Invocations are now /edpa:setup, /edpa:add, /edpa:engine, /edpa:reports,
/edpa:autocalib. plugin.json skills[] paths updated.

refactor(server,create-pi): collapse the command+skill pairs to command-only

Two capabilities shipped as both a command and a same-named skill; the prefix
was the only thing keeping them from colliding (/edpa:server command vs
/edpa:edpa-server skill). Dropping the prefix would collide, so the redundant
skills are removed in favour of the commands:

  • skills/edpa-server removed — its workflow (start/stop/status, scoped
    allowed-tools, the "what NOT to do" rails) folded into commands/server.md.
  • skills/edpa-create-pi removed — commands/create-pi.md already carried the
    full workflow; the edpa_pi_create MCP tool remains the model-facing path.

plugin.json skills[] drops both; commands[] is unchanged (still 5).

Breaking — invocation surface

  • /edpa:edpa-setup / -add / -engine / -reports / -autocalib → use
    /edpa:setup/edpa:autocalib.
  • The edpa:edpa-server and edpa:edpa-create-pi skills are gone — use the
    /edpa:server and /edpa:create-pi commands (and the edpa_pi_create MCP
    tool). Run /reload-plugins after updating.

docs + web + tooling

Swept every active reference: plugin/README.md tree + table, docs/ (RUNBOOK,
playbook, faq, mcp, dev-collisions, auto-calibration, E2E plans), tests, and the
CZ+EN website (presentation, kashealth, playbook). Fixed pre-existing
double-prefix typos (/edpa:edpa-engine in capacity.md, /edpa:edpa-setup in
faq.md). scripts/bump_version.py literal-reference paths updated to the new
skill dirs.

v2.2.0 — Create PI (edpa_pi_create + /edpa:create-pi)

01 Jun 11:57
1014084

Choose a tag to compare

First-class PI-level metadata file creation (.edpa/iterations/<PI-YYYY-N>.yaml, the pi: block) — until now only per-iteration files had tooling, and the PI parent had to be hand-written (and a .yml extension was silently ignored by the loader).

Built script-first, like the rest of EDPA: behavior lives in one script and every interface delegates to it.

  • create_pi.py — single source of behavior: importable create_pi() core (validate PI-level id, refuse overwrite, atomic write) + CLI (validate + auto-commit). Self-contained, no MCP dependency.
  • edpa_pi_create MCP tool — thin delegate (write only, no commit). Tool surface now 7 read + 8 write.
  • /edpa:create-pi command + edpa:create-pi skill — shell out to the script (like /edpa:capacitycapacity_override.py).

Rejects iteration-level ids (PI-YYYY-N.M) and duplicates. Does not scaffold child iterations (use edpa_iteration_create).

Tests: tests/test_create_pi.py (core + CLI + loader round-trip) + edpa_pi_create in the MCP write/idempotency/advertised-tool suites — pytest tests/ 600 passed. Docs: docs/mcp.md (write-tools note + corrected "read-only" claim), docs/playbook.md §1.5, docs/RUNBOOK.md, plugin/README.md.

🤖 Generated with Claude Code

v2.1.9 — Windows onboarding fixes (filelock, UTF-8 console + file I/O)

01 Jun 08:28

Choose a tag to compare

Windows onboarding fixes/edpa:edpa-setup crashed on a fresh Windows box (surfaced by colleagues on 2.1.8). Two reported failures, plus two more that would have hit immediately after (masked by the first crash). All four are fixed; the engine now behaves identically on Linux, macOS, and Windows.

fix(setup): bootstrap no longer crashes on ModuleNotFoundError: filelock

id_counter.py imported filelock unconditionally, but the SessionStart dep hook (install_deps.sh) skipped pip install whenever its cheap import probe passed — and the probe never listed filelock. On a machine that already had PyYAML/mcp/openpyxl system-wide, the hook marked deps "installed" while filelock was absent, so the bootstrap died.

  • The probe now includes filelock (a new test_install_deps_probe.py cross-checks it against requirements.txt so the drift can't recur).
  • id_counter.py falls back to a pure-stdlib lock (_fallback_lock.py, O_CREAT|O_EXCL + stale-lock sweep) when filelock can't be imported, keeping the cross-process mutual-exclusion contract even without the package.

fix(cli): UTF-8 console output

25 CLI entry points print progress glyphs (✓ ✗ → ·); print("✓") raises UnicodeEncodeError on a cp1250/cp1252 console and aborts the command (the reported failure). A shared _console.py reconfigures stdout/stderr to UTF-8; each entry point opts in with a guarded import _console (try/except ImportError, so a partially-vendored engine degrades to plain output rather than crashing). mcp_server.py is excluded — its glyphs ride the MCP SDK's UTF-8 JSON-RPC framing.

fix(io): all text-mode file I/O pins encoding="utf-8"

open()/read_text()/write_text()/os.fdopen() defaulted to the locale encoding — cp1250 on a Czech/German Windows box. After the console fix the next crash would have been _stamp_methodology reading the seeded UTF-8 edpa.yaml (, ×) → UnicodeDecodeError; diacritic item titles would corrupt or crash on write too. All 28 text-mode handles now pin UTF-8. A new test_encoding_hygiene.py AST guard fails CI if any text handle drops the kwarg.

Tests

New: test_install_deps_probe.py, test_fallback_lock.py, test_console.py, test_encoding_hygiene.py. Full suite 565 → 577 (+12); 0 failures.


🤖 Generated with Claude Code

v2.1.8 — Fresh-install onboarding fixes

31 May 20:27

Choose a tag to compare

Three fresh-install onboarding friction points on the Claude-Code-only path (install the plugin, run /edpa:setup on a bare repo), found via a new deterministic E2E onboarding harness (tests/onboarding/).

fix(setup): /edpa:setup now vendors the engine into .edpa/engine/

project_setup.py vendors scripts+schemas+templates+rules+VERSION as step 1 of main() (mirrors install.sh). The Claude Code path had silently lost vendoring when the engine moved from .claude/edpa/ to .edpa/engine/ (only install.sh was rewired), so /edpa:setup produced a project referencing a .edpa/engine/scripts/ that never existed — the --with-ci workflow it installs plus the documented CLI broke, masked by the MCP server running from the plugin cache. Rules are now vendored from plugin/rules (fixes a parallel --with-rules failure).

fix(install): V2 local-first "Next steps" + stamped methodology version

install.sh no longer prints stale V1 guidance ("provision GitHub Project … push to GitHub Projects") or the removed --org/--repo/--project-title args; it shows the correct --with-ci/--with-hooks/--with-rules flow with filelock in the dependency hint. Both install.sh and project_setup.py stamp governance.methodology in a freshly seeded edpa.yaml to the live plugin version.

Tests

New tests/onboarding/ harness (pexpect + tmux) + test_project_setup_vendor.py + test_install_sh_hygiene.py. Full suite 553 → 564 (+11); 0 failures.

Fixes from #51. Full changelog: https://github.com/technomaton/edpa/blob/main/CHANGELOG.md


docs: V1→V2 docs + website sweep (PR #52)

Swept the user-facing docs and the Astro website of the removed V1 GitHub-Project flow (project_setup.py --org/--repo/--project-title, org Issue Types, project_views.py, bidirectional sync.py, issue_map.yaml, .claude/edpa/ paths, project.yaml/heuristics.yaml, .yaml backlog) → V2 local-first throughout. 31 files (repo docs + Astro pages incl. landing/pitch decks reframed to "EDPA needs only git, GitHub optional"). Live on https://edpa.technomaton.com (astro build green, 28 pages).

Merged to main after this tag — supplementary documentation/website work; the installable plugin payload above (PR #51) is unchanged.

v2.1.7 — E2E findings fixes + /contribute @id + /edpa:capacity

31 May 18:32

Choose a tag to compare

End-to-end re-validation of v2 against a real GitHub repo (2 PIs × 5 iterations, 24 PRs, 24/24 real CI runs, 560h derived, all invariants green) surfaced a set of cross-layer fixes and conveniences.

Fixes

  • Iteration close now sets the top-level lifecycle status (not just nested iteration.status), so pi_close, the board, and tooling see an iteration closed via the MCP tool. (#48)
  • backlog.py add no longer leaks ANSI color codes into machine-readable ID output — honors NO_COLOR / non-TTY. (#48)
  • Story-point rollup (velocity.py, pi_close.py) is now derived from item js — velocity and PI predictability populate instead of 0 / None. (#48)

Features

  • /contribute @<id> targets a specific contract for multi-contract people who share a GitHub handle (R-2); unknown tokens now warn instead of silently earning 0h. (#49)
  • New /edpa:capacity command wrapping per-iteration per-person capacity overrides (--list / --add / --remove); new RUNBOOK §3b + web playbook/methodology docs (CZ + EN). (#50)

Tests

  • Full suite 546 → 553 (+7 regression tests), 0 failures.

Full report: docs/v2/e2e-real-github-run-2026-05-31.md · PRs: #48, #49, #50.

v2.1.6 — Full collision documentation + methodology page section

30 May 18:34

Choose a tag to compare

Documentation-only release expanding collision handling coverage across all developer-facing surfaces.

No code changes. Engine, schema, hooks, scripts all unchanged from v2.1.5.

What's new

docs/dev-collisions.md — comprehensive guide (108 → 290 lines)

  • ASCII timeline diagram showing how a collision happens (T+0 → T+5)
  • ASCII flow diagram of the 4 defense layers (cumulative)
  • Decision tree — "I got a conflict, what do I do?"
  • Recovery flow with annotated comments for each step
  • 5 common collision shapes (single / multi / parent chain / cross-type / cascading)
  • Installation section (hooks + CI workflow)
  • Troubleshooting (3 common gotchas)
  • Bypass disclaimer

Integration into existing docs

  • docs/RUNBOOK.md — new "ID collision handling" section with operator reference table + setup checklist + recovery commands
  • docs/quick-start.md — new "Multi-developer setup" section in "What's Next?"
  • docs/github-setup.md — fixed outdated "IDs are immutable" claim
  • plugin/README.md — new "Multi-developer setup" section
  • plugin/skills/edpa-add/SKILL.md — new "Parallel ID allocation" section
  • plugin/skills/edpa-setup/SKILL.md--with-hooks cross-references layer numbers + explicit Layer 7 manual step

Web — methodology page section 9b (CZ + EN)

  • methodology.astro (CZ): "9b. ID kolize a renumbering (multi-developer setup)"
  • en/methodology.astro (EN): "9b. ID collisions and renumbering (multi-developer setup)"
  • Both: full 4-layer table + recovery flow + setup commands + link to GitHub guide

Dashboard improvement (E2E reporting)

/tmp/edpa-e2e-recovered/dashboard.html regenerator adds effective capacity bar — 3 bars per iteration:

  • Blue — planning capacity (deklarovaná, statická)
  • Yellow — effective capacity (jen aktivní lidé)
  • Green — derived (signal-based allocation)

Tooltip shows utilization % (vs both planning and effective) plus "X/Y active people" count. Resolves user feedback about confusing "Capacity vs Derived" gap when some team members were idle in an iteration.


Web: https://edpa.technomaton.com — already on v2.1.6
Install: curl -fsSL https://edpa.technomaton.com/install.sh | bash
Read first if multi-developer setup: docs/dev-collisions.md

v2.1.5 — Collision detection fix + CI workflow + dev docs

28 May 19:31

Choose a tag to compare

Bug fix release for EDPA ID collision detection in feature-branch + PR workflow, plus new defense layer (CI workflow) and developer documentation.

What was broken

renumber_collisions.py and validate_ids.py --pre-push both compared local backlog state against the matching remote branch instead of the integration target (origin/main). In the standard feature-branch + PR workflow — once you push your branch — origin/<your-branch> matches HEAD, so no diff was detected. Collisions with main were invisible to both tools.

End-to-end reproduction in tests/e2e_collision/scenario_a.sh (real GitHub sandbox, two devs both allocate S-5).

Fixes

  • renumber_collisions.find_collisions() — new optional target_branch argument, defaults to remote's default branch via refs/remotes/<remote>/HEAD. New CLI flags --target <branch> (for Git Flow projects integrating to develop) and --check (CI mode — detect + report, no prompt, exit 1 if collisions).
  • validate_ids.cmd_pre_push() — lists upstream items at the integration target tip, not at the merge-base. Items merged to main after your branch forked are now visible to the pre-push check.

New: defense layer 7 — CI workflow

plugin/edpa/templates/github-workflows/edpa-collision-check.yml runs on every PR touching .edpa/backlog/ or id_counters.yaml. Detects collisions via renumber_collisions.py --check; on detection, posts a comment with fix instructions and fails the check (PR merge button stays disabled).

New tests

  • 5 new unit tests in test_renumber_collisions.py:
    • test_multi_collision_both_renumbered_sequentially — two Story collisions get sequential IDs (S-5 + S-6), no duplicates
    • test_parent_chain_renumber_propagates_to_children_only — F-3 → F-4 updates direct children's parent: refs; grandchildren untouched
    • test_three_dev_cascading_collisions — 3-dev sequential renumbering
    • test_collision_detected_when_on_feature_branch_against_main — regression test for the --target fix
    • test_collision_target_branch_arg_overrides_default — Git Flow scenario
  • tests/e2e_collision/scenario_a.sh — real GitHub sandbox script reproducing the full Alice + Bob workflow end-to-end (init → 2 PRs → Alice merge → Bob conflict → renumber → merge → bob's PR mergeable → squash → verify).

New docs

docs/dev-collisions.md — full developer guide covering all 4 defense layers (pre-commit, pre-push, CI workflow, manual recovery), recovery flow with exact commands, common collision shapes (single / multi / parent-chain / cascading), id_counters.yaml merge resolution trick.

Migration

Existing projects pick up the fix on next bash install.sh or /edpa:setup --update-engine. The CI workflow template needs to be copied manually:

cp .edpa/engine/templates/github-workflows/edpa-collision-check.yml .github/workflows/
git add .github/workflows/edpa-collision-check.yml && git commit -m "ci: add EDPA collision check"

Web: https://edpa.technomaton.com — already on v2.1.5
Install: curl -fsSL https://edpa.technomaton.com/install.sh | bash

v2.1.4 — V2.1 local-first parity in plugin metadata

27 May 21:04

Choose a tag to compare

Patch release sweeping the last 4 customer-facing texts still mentioning "bidirectional sync" or "GitHub-native" as headline — aligning with the V2.1 local-first narrative the 2.1.2 release set elsewhere.

No engine, schema, or behavior changes.

Changes

  • plugin/.claude-plugin/plugin.json description (visible in Claude Code plugin marketplace)
  • .claude-plugin/marketplace.json plugins[] description (visible when users run /plugin marketplace add technomaton/edpa)
  • plugin/README.md file tree — sync.py now flagged as optional UI
  • web/src/pages/en/index.astro — "GitHub-native" card → "Git-native, GitHub-friendly" (parity with CZ version fixed in 2.1.2)

Web: https://edpa.technomaton.com — already on v2.1.4
Install: curl -fsSL https://edpa.technomaton.com/install.sh | bash

v2.1.3 — E2E findings + verify scripts parameterized

27 May 20:14

Choose a tag to compare

Patch release applying the 5 actionable findings surfaced by the V2 full end-to-end test, plus a verification run that exercised every fix against a fresh GitHub sandbox. The verification itself uncovered 4 more bugs in the verify + cleanup scripts (stale hard-coded constants from the previous run); those are fixed in the same release.

No engine math or schema changes. Engine behavior is unchanged; only CLI surface, close-iteration workflow, fixture, and test-infrastructure tweaks.

Highlights

  • fix(backlog)backlog.py add --type accepts all 7 types (Defect/Event/Risk added). Mirrors edpa_item_create MCP surface; no more manual YAML fallback for those types.
  • fix(close-iteration) — Stage 2b (detect_contributors.py --all-items) explicitly mandatory, with a warning about the silent 0h failure mode if skipped.
  • fix(e2e fixture)work_plan.yaml Initiative/Epic gate transitions now use portfolio ladder (Implementing, not delivery-only Validating).
  • docs(mcp) — Documents that the EDPA MCP server is single-project per session (resolves .edpa/ from host project root, not agent cwd).
  • docs(e2e) — Skill-tool subagent gotcha (returns instruction text instead of executing) captured as limitation #4.

Verification (hybrid E2E run, 2026-05-27)

Ran the full 2 PI × 5 iter E2E in hybrid mode (PI-1 real GitHub Actions, PI-2 synthetic injection) against technomaton/edpa-e2e-20260527-181051-2c56a6a0 (archived). Every fix verified live:

Verification Result
PRs merged 14/14
CI workflow runs (success) 14/14
Iterations closed (all_invariants_passed=true on first engine pass) 10/10
Frozen snapshots (no _rev2/_rev3) 10
Per-person timesheets + team rollups 50 + 10
XLSX exports 10
Backlog items in expected end-states 33/33
backlog.py validate exit 0 (previously 3 errors)

Side fixes: verify/cleanup scripts parameterized

The verification exposed 4 stale-constant bugs in tests/e2e_v2_full/phases/{10,11,12}_*.py + 99_cleanup.sh:

  • Hard-coded paths from the previous run
  • EXPECTED_MERGED_PRS=24 assumed full-real CI mode
  • EXPECTED_COUNTS predated the portfolio ladder fix
  • Wrong YAML key for iteration lifecycle status (iteration.status vs root status)

All four scripts are now parameterized via env vars + /tmp/edpa-e2e-current-run-tag fallback + EDPA_E2E_CI_MODE-aware constants (EXPECTED_MERGED_PRS returns 24/14/0 for real/hybrid/synthetic mode).

Phase run logs refreshed

tests/e2e_v2_full/phases/01..12_*.md refreshed with the hybrid-mode results, timestamps, sandbox SHAs, and script-fix findings.


Full CHANGELOG: CHANGELOG.md
Web: https://edpa.technomaton.com — already on v2.1.3
Install: curl -fsSL https://edpa.technomaton.com/install.sh | bash