Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Changelog

## 2.2.0 — 2026-06-01 — Create PI: edpa_pi_create tool + /edpa:create-pi command & skill

Adds a first-class way to create the **PI-level metadata file**
`.edpa/iterations/<PI-YYYY-N>.yaml` (top-level `pi:` block). Previously only
per-iteration files had tooling (`edpa_iteration_create`); the PI parent had to
be hand-written, which was error-prone — most notably the loader globs `*.yaml`
only, so a `PI-2026-1.yml` (short extension) is silently ignored and the PI
metadata (status, `pi_iterations`, dates) silently falls back to values derived
from the child iterations.

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

### feat(pi): `create_pi.py` — single source of behavior
New `plugin/edpa/scripts/create_pi.py` with an importable `create_pi()` core
(validates a PI-level id, refuses to overwrite, atomic write of the `pi:` block)
plus a CLI (`--start/--end/--weeks/--iterations/--status/--no-commit`) that runs
continuity validation and auto-commits. Self-contained — no dependency on the
MCP layer, so it runs as a plain CLI and is importable by the server.

### feat(mcp): `edpa_pi_create` tool
Thin delegate that imports `create_pi()` — no business logic in the handler
(write only; no commit, like the other MCP write tools). Inputs: `id` (required,
PI-level), `start_date`, `end_date`, `iteration_weeks`, `pi_iterations`,
`status`. Rejects an iteration-level id (`PI-YYYY-N.M`) and duplicates. The tool
surface is now 7 read + 8 write.

### feat(skill+command): `/edpa:create-pi` and `edpa:create-pi`
Both shell out to `create_pi.py` (like `/edpa:capacity` → `capacity_override.py`).
The command takes explicit args; the skill auto-triggers on "create / start a
PI". Neither scaffolds the child iterations — those are added with
`edpa_iteration_create` (`<PI>.1 … .N`, last `type: IP`).

### tests + docs
New `tests/test_create_pi.py` (core + CLI + loader round-trip); `edpa_pi_create`
added to the MCP write-tool and idempotency suites and the advertised-tool
assertions. `docs/mcp.md` gains a write-tools note (and the stale "read-only"
claim is corrected); `docs/playbook.md` §1.5, `docs/RUNBOOK.md`, and
`plugin/README.md` list the new tool / command / skill.

## 2.1.10 — 2026-06-01 — Drop dead `cadence:` config (cadence is iteration-sourced)

The `cadence:` block (`iteration_weeks` / `pi_weeks` / `delivery_iterations_per_pi`
Expand Down
1 change: 1 addition & 0 deletions docs/RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ YAML is the source of truth, git is the audit trail. GitHub Projects sync is
| Command | Underlying script / skill | Status |
|----------------------|------------------------------------|--------|
| `/edpa:setup` | `.edpa/engine/scripts/project_setup.py` | ✅ vendors engine + seeds `.edpa/` (local-first) |
| `/edpa:create-pi` | `.edpa/engine/scripts/create_pi.py` | ✅ writes the PI-level `pi:` file (also `edpa_pi_create` MCP tool) |
| `/edpa:close-iteration` | `.edpa/engine/scripts/engine.py` → `edpa-reports` skill | ✅ verified by `tests/test_invariants.py`, `tests/test_gate_allocation.py` |
| `/edpa:reports` | `edpa-reports` skill (no script) | ✅ manual + skill execution |
| `/edpa:board` | `.edpa/engine/scripts/board.py` | ✅ manual run |
Expand Down
30 changes: 28 additions & 2 deletions docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,30 @@ Returns:
for items not yet closed. Both require timestamp fields synced from GitHub
(see `sync pull` timestamp extraction).

### Write tools

The server also exposes local-first **write** tools (V2). They mutate `.edpa/`
files directly (atomic tmp+rename) and do **not** commit or call the network —
the calling skill/command owns the commit. Full set: `edpa_item_create`,
`edpa_item_update`, `edpa_item_transition`, `edpa_item_link_parent`,
`edpa_iteration_create`, `edpa_iteration_close`, `edpa_pi_create`,
`edpa_people_upsert`.

#### `edpa_pi_create`

```json
{ "id": "PI-2026-2", "start_date": "2026-06-02", "iteration_weeks": 1,
"pi_iterations": 5, "status": "active" }
```

Creates the PI-level metadata file `.edpa/iterations/<id>.yaml` (top-level
`pi:` block). Only `id` is required, and it must be **PI-level** (`PI-YYYY-N`) —
an iteration id with a `.N` suffix is rejected, as is overwriting an existing
PI. The filename is always `.yaml` (the loader globs `*.yaml`; a `.yml` is
silently ignored). Delegates to `create_pi.py`, the single source of behavior
also used by the `/edpa:create-pi` command and `edpa:create-pi` skill. Does not
scaffold child iterations — add those with `edpa_iteration_create`.

---

## Production hardening (v1.3-beta)
Expand Down Expand Up @@ -259,8 +283,10 @@ What changed from the v1.0–v1.2 prototype:

## Security model

- **Read-only.** No tool writes `.edpa/`. Bidirectional sync (`/edpa:sync`)
goes through the regular CLI, not MCP.
- **Local-first writes.** Read tools never mutate state. The V2 write tools
(`edpa_item_*`, `edpa_iteration_*`, `edpa_pi_create`, `edpa_people_upsert`)
write `.edpa/` files via atomic tmp+rename and do not commit or call the
network; the calling skill/command owns the commit.
- **Path traversal blocked.** `item_id` parameter is the only user input that
reaches the filesystem; the regex guard plus prefix→directory whitelist
means a request like `{"item_id": "../etc/passwd"}` is rejected at the
Expand Down
10 changes: 8 additions & 2 deletions docs/playbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Kompletni prirucka pro nasazeni metodiky EDPA (Evidence-Driven Proportional Allo

EDPA V2 je **local-first**: zdrojem pravdy je `.edpa/backlog/**/*.md` (YAML frontmatter), git je audit trail. GitHub je **volitelny** -- zadny GitHub Project, zadne org Issue Types, zadny obousmerny sync.

**Verze:** EDPA 2.1.9
**Verze:** EDPA 2.2.0
**Posledni aktualizace:** 2026-06-01

---
Expand Down Expand Up @@ -205,7 +205,7 @@ project:

governance:
# Auto-razitkovano na verzi pluginu instalatorem.
methodology: "EDPA 2.1.9"
methodology: "EDPA 2.2.0"
# Jedina vypocetni cesta od v1.14 (zadny simple/full/gates mode selector,
# zadny audit_mode -- snapshoty vzdy nesou plny signals[] audit trail).

Expand Down Expand Up @@ -279,6 +279,12 @@ Vytvoř obdobně `PI-2026-1.{2..5}.yaml`. Poslední iterace dostane
překryvy, `weeks` × 7 ≈ rozdíl dat) hlídá `validate_iterations.py`
i automatický PostToolUse hook.

> **Tip:** PI-level soubor (`pi:`) nemusíš psát ručně — založ ho příkazem
> `/edpa:create-pi PI-2026-1` (nebo MCP nástrojem `edpa_pi_create` / skillem
> `edpa:create-pi`). Validuje id, odmítne přepis a commitne. Per-iteration
> soubory přidávej přes `edpa_iteration_create`. Pozor: přípona musí být
> `.yaml`, ne `.yml` — loader `.yml` tiše ignoruje.

> **Odstraneno v 2.0.0:** sync blok (`github_org`, `github_project_number`, `sync_interval`) -- V2 je local-first, zadny GitHub Project se neprovisionuje.

### 1.6 Naplnit backlog
Expand Down
8 changes: 5 additions & 3 deletions plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "edpa",
"version": "2.1.10",
"version": "2.2.0",
"description": "EDPA — Evidence-Driven Proportional Allocation. Derive hours from local git evidence (commits, yaml edits, status transitions). Zero timesheets, mathematical guarantee, Monte Carlo calibrated CW weights. Local-first: .edpa/backlog/ YAML as source of truth, git as the audit trail. GitHub Projects sync optional.",
"author": {
"name": "TECHNOMATON",
Expand All @@ -17,13 +17,15 @@
"./skills/edpa-engine",
"./skills/edpa-reports",
"./skills/edpa-autocalib",
"./skills/edpa-server"
"./skills/edpa-server",
"./skills/edpa-create-pi"
],
"commands": [
"./commands/close-iteration.md",
"./commands/board.md",
"./commands/capacity.md",
"./commands/server.md"
"./commands/server.md",
"./commands/create-pi.md"
],
"agents": []
}
14 changes: 9 additions & 5 deletions plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,22 @@ plugin/
├── requirements.txt # Python runtime deps (pyyaml, ruamel.yaml, mcp, openpyxl)
├── hooks/
│ └── hooks.json # SessionStart (install_deps) + PostToolUse (validate_on_save, post_commit)
├── skills/ # 6 skills, auto-discovered. Slug = name: field in SKILL.md frontmatter
├── skills/ # 7 skills, auto-discovered. Slug = name: field in SKILL.md frontmatter
│ ├── edpa-setup/SKILL.md # → /edpa:setup — provision .edpa/ governance (engine, config, hooks, CI)
│ ├── edpa-add/SKILL.md # → /edpa:add — create a backlog item (local-first, id_counters)
│ ├── edpa-engine/SKILL.md # → /edpa:engine — evidence-driven calculation
│ ├── edpa-reports/SKILL.md # → /edpa:reports — timesheets, exports, snapshots
│ ├── edpa-autocalib/SKILL.md # → /edpa:autocalib — CW heuristic optimization (Monte Carlo + coord descent)
│ └── edpa-server/SKILL.md # → /edpa:server — optional PI-planning HTTP server (experimental)
├── commands/ # 4 slash commands, flat layout (no edpa/ subdir)
│ ├── edpa-server/SKILL.md # → /edpa:server — optional PI-planning HTTP server (experimental)
│ └── edpa-create-pi/SKILL.md # → /edpa:create-pi — create the PI-level metadata file (pi: block)
├── commands/ # 5 slash commands, flat layout (no edpa/ subdir)
│ ├── close-iteration.md # → /edpa:close-iteration — capacity prep + engine + reports
│ ├── board.md # → /edpa:board — HTML Kanban snapshot
│ ├── capacity.md # → /edpa:capacity — per-iteration capacity overrides
│ └── server.md # → /edpa:server — start/stop PI-planning server
│ ├── server.md # → /edpa:server — start/stop PI-planning server
│ └── create-pi.md # → /edpa:create-pi — create the PI-level metadata file (pi: block)
└── edpa/
├── scripts/ # 31 Python modules
├── scripts/ # 32 Python modules
│ ├── engine.py # Core engine (Score, DerivedHours, invariants)
│ ├── mcp_server.py # MCP server for /edpa:status, /edpa:backlog, /edpa:iterations, /edpa:flow_metrics
│ ├── calibrate_signals.py # CW signal-weights calibrator (Monte Carlo + coordinate descent)
Expand All @@ -80,6 +82,7 @@ plugin/
│ ├── local_evidence.py # post-commit: commit_author + /contribute signals → evidence[]
│ ├── sync_pr_contributions.py # CI: PR review/comment signals (edpa-contribution-sync)
│ ├── capacity_override.py # per-iteration capacity overrides (/edpa:capacity)
│ ├── create_pi.py # create the PI-level metadata file (edpa_pi_create / /edpa:create-pi)
│ ├── project_setup.py # provision .edpa/ governance (config, id_counters, --with-ci/hooks/rules)
│ ├── traceability.py # Parent-chain validation
│ ├── pi_close.py + velocity.py + transitions.py
Expand Down Expand Up @@ -127,6 +130,7 @@ PR-thread signals (`pr_reviewer`, `issue_comment`) arrive only via the optional
| `/edpa:close-iteration` | command | Capacity prep + engine + reports for an iteration |
| `/edpa:capacity` | command | Per-iteration per-person capacity overrides (PTO, overtime) |
| `/edpa:board` | command | HTML Kanban snapshot from local backlog |
| `/edpa:create-pi` | command | Create the PI-level `pi:` file (also `edpa:create-pi` skill + `edpa_pi_create` MCP tool) |

## Multi-developer setup — ID collision handling

Expand Down
65 changes: 65 additions & 0 deletions plugin/commands/create-pi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
description: Create the PI-level metadata file (.edpa/iterations/PI-YYYY-N.yaml) — the parent record of a Planning Interval
allowed-tools: Read, Bash
model: sonnet
---

# EDPA Create PI

Create the **PI-level metadata file** `.edpa/iterations/<PI-YYYY-N>.yaml`
(top-level `pi:` block) — the parent record for a Planning Interval. EDPA
reconstructs the PI list at runtime from `iterations/*.yaml`
(`_pi_loader.derive_pis`); without a `pi:` file the loader still works but
warns `missing_pi_yaml` and derives PI metadata from the child iterations —
so you lose explicit `status` / `pi_iterations` / dates.

This wraps `create_pi.py`, the single source of behavior (the same engine the
`edpa_pi_create` MCP tool calls). It does **NOT** create the child iterations —
add those afterwards with `edpa_iteration_create` (`<PI>.1 … .N`, last `type: IP`).

> **Filename gotcha:** the loader globs `*.yaml` only. A `PI-2026-1.yml` (short
> extension) is silently ignored. The script always writes `.yaml`.

## Arguments

`$ARGUMENTS` — the PI id plus optional flags:
- **id** (required) — PI-level, e.g. `PI-2026-2` (NOT an iteration id `PI-2026-2.1`)
- `--start YYYY-MM-DD` / `--end YYYY-MM-DD` — PI window (optional)
- `--weeks N` — iteration cadence in weeks (default 1)
- `--iterations N` — planned number of iterations in the PI (optional)
- `--status planning|active|closed` — default `planning`
- `--no-commit` — write the file but skip the git commit

Examples:
- `PI-2026-2`
- `PI-2026-2 --start 2026-06-02 --end 2026-09-06 --weeks 1 --iterations 5 --status active`

## Steps

1. Parse `$ARGUMENTS`. Require a PI-level id (`PI-YYYY-N`, no `.iteration`
suffix). If the user gave an iteration id, tell them to use
`edpa_iteration_create` instead — this command creates the PI parent only.

2. Run the script:
```bash
python3 .edpa/engine/scripts/create_pi.py <id> [--start …] [--end …] \
[--weeks N] [--iterations N] [--status …]
```
It validates the id, refuses to overwrite an existing PI, writes the `pi:`
block atomically, runs continuity validation, and auto-commits
`chore(pi): create <id>` (pass `--no-commit` to skip).

3. Report the created file, then suggest next steps:
- Create the child iterations `<id>.1 … <id>.N` via `edpa_iteration_create`
(the last one usually `type: IP`).
- Mark the running iteration `status: active` when it starts.

## Notes

- **Status lifecycle:** `planning → active → closed`. A PI's status is
otherwise derived from its iterations (`_pi_status_from_iterations`): active
if any iteration is active, closed once all are.
- For per-iteration files use `edpa_iteration_create`; to close an iteration
use `/edpa:close-iteration`.
- This command does not scaffold iterations by design — one explicit PI record,
iterations added deliberately.
Loading
Loading