@pareto4/pp-core 1.7.1 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/bin/install.js +197 -81
- package/commands/pp-build-handoff.md +8 -2
- package/commands/pp-discovery-to-build.md +40 -0
- package/commands/pp-ns-project.md +3 -1
- package/gemini-extension.json +1 -1
- package/package.json +2 -1
- package/pareto-skills/_shared/create-project-board.sh +195 -0
- package/pareto-skills/_shared/pp-claude-md-protocol.md +306 -0
- package/pareto-skills/_shared/sync-phase-status.sh +139 -0
- package/pareto-skills/pp-brand/SKILL.md +644 -0
- package/pareto-skills/pp-brand/assets/crew/ParetoAgent.inline.html +120 -0
- package/pareto-skills/pp-brand/assets/crew/ParetoAgent.tsx +239 -0
- package/pareto-skills/pp-brand/assets/crew/build.svg +11 -0
- package/pareto-skills/pp-brand/assets/crew/deploy.svg +11 -0
- package/pareto-skills/pp-brand/assets/crew/discovery.svg +11 -0
- package/pareto-skills/pp-brand/assets/crew/plan.svg +11 -0
- package/pareto-skills/pp-brand/assets/crew/run.svg +11 -0
- package/pareto-skills/pp-brand/assets/crew/validate.svg +11 -0
- package/pareto-skills/pp-brand/assets/pareto-brand-preview.html +547 -0
- package/pareto-skills/pp-obsidian-notes/SKILL.md +127 -0
- package/pareto-skills/pp-obsidian-notes/templates/CLAUDE.md +29 -0
- package/pareto-skills/pp-obsidian-notes/templates/client-context.md +116 -0
- package/pareto-skills/pp-obsidian-notes/templates/meeting-note.md +66 -0
- package/pareto-skills/pp-obsidian-notes/templates/pareto-context.md +102 -0
- package/pareto-skills/pp-obsidian-notes/templates/proposal.md +117 -0
- package/pareto-skills/pp-project-setup/SKILL.md +1364 -0
- package/pp-core/bin/lib/clusters.cjs +4 -0
- package/pp-core/bin/lib/intel.cjs +1 -1
- package/pp-core/bin/lib/io.cjs +120 -0
- package/pp-core/bin/lib/profile-pipeline-command-router.cjs +1 -1
- package/pp-core/bin/lib/roadmap-parser.cjs +1 -1
- package/pp-core/bin/lib/runtime-artifact-conversion.cjs +2 -2
- package/pp-core/bin/lib/surface.cjs +1 -1
- package/pp-core/bin/lib/worktree-safety.cjs +2 -2
- package/pp-core/bin/pp-tools.cjs +23 -0
- package/pp-core/references/ui-brand.md +73 -11
- package/pp-core/templates/codebase/structure.md +5 -5
- package/pp-core/templates/spec.md +7 -7
- package/pp-core/workflows/add-backlog.md +1 -1
- package/pp-core/workflows/autonomous.md +4 -4
- package/pp-core/workflows/debug.md +1 -1
- package/pp-core/workflows/{build-handoff.md → discovery-to-build.md} +6 -3
- package/pp-core/workflows/execute-phase.md +9 -1
- package/pp-core/workflows/plan-phase.md +14 -12
- package/pp-core/workflows/pr-branch.md +5 -4
- package/pp-core/workflows/reapply-patches.md +1 -1
- package/pp-core/workflows/ship.md +1 -1
- package/pp-core/workflows/thread.md +1 -1
- package/pp-core/workflows/verify-work.md +6 -5
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pp:build-handoff
|
|
3
|
-
description:
|
|
3
|
+
description: "[DEPRECATED] Alias for /pp-discovery-to-build; removed in a future major."
|
|
4
4
|
argument-hint: "[--skip-validation] [--scaffold]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -18,6 +18,12 @@ requires: [new-project]
|
|
|
18
18
|
**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API.
|
|
19
19
|
</runtime_note>
|
|
20
20
|
|
|
21
|
+
<deprecation_note>
|
|
22
|
+
**Deprecated:** `/pp-build-handoff` was renamed to `/pp-discovery-to-build` in v1.8.0. This
|
|
23
|
+
alias runs the identical workflow and is kept for back-compat with v1.7.x. Prefer
|
|
24
|
+
`/pp-discovery-to-build`; this alias will be removed in a future major release.
|
|
25
|
+
</deprecation_note>
|
|
26
|
+
|
|
21
27
|
<objective>
|
|
22
28
|
Bridge the gap between a completed Pareto Discovery Sprint and pp-core execution.
|
|
23
29
|
|
|
@@ -32,7 +38,7 @@ execution, or `/pp-autonomous` to run all phases.
|
|
|
32
38
|
</objective>
|
|
33
39
|
|
|
34
40
|
<execution_context>
|
|
35
|
-
@~/.claude/pp-core/workflows/build
|
|
41
|
+
@~/.claude/pp-core/workflows/discovery-to-build.md
|
|
36
42
|
</execution_context>
|
|
37
43
|
|
|
38
44
|
<process>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pp:discovery-to-build
|
|
3
|
+
description: Transition a completed Pareto Discovery Sprint into a pp-core-ready project.
|
|
4
|
+
argument-hint: "[--skip-validation] [--scaffold]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Bash
|
|
10
|
+
- Glob
|
|
11
|
+
- Grep
|
|
12
|
+
- Agent
|
|
13
|
+
- AskUserQuestion
|
|
14
|
+
requires: [new-project]
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<runtime_note>
|
|
18
|
+
**Copilot (VS Code):** Use `vscode_askquestions` wherever this workflow calls `AskUserQuestion`. They are equivalent — `vscode_askquestions` is the VS Code Copilot implementation of the same interactive question API.
|
|
19
|
+
</runtime_note>
|
|
20
|
+
|
|
21
|
+
<objective>
|
|
22
|
+
Bridge the gap between a completed Pareto Discovery Sprint and pp-core execution.
|
|
23
|
+
|
|
24
|
+
Validates all 13 Discovery sessions are complete, synthesizes their outputs into a
|
|
25
|
+
single structured handoff document, bootstraps the `.planning/` project state
|
|
26
|
+
(PROJECT.md, REQUIREMENTS.md, ROADMAP.md, STATE.md, config.json), and wires up
|
|
27
|
+
cross-references so pp-core agents can trace every decision back to the Discovery
|
|
28
|
+
session that produced it.
|
|
29
|
+
|
|
30
|
+
**After this command:** pp-core is initialized. Run `/pp-plan-phase 1` to start
|
|
31
|
+
execution, or `/pp-autonomous` to run all phases.
|
|
32
|
+
</objective>
|
|
33
|
+
|
|
34
|
+
<execution_context>
|
|
35
|
+
@~/.claude/pp-core/workflows/discovery-to-build.md
|
|
36
|
+
</execution_context>
|
|
37
|
+
|
|
38
|
+
<process>
|
|
39
|
+
Execute end-to-end.
|
|
40
|
+
</process>
|
|
@@ -5,7 +5,7 @@ argument-hint: ""
|
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
7
7
|
- Skill
|
|
8
|
-
requires: [init, new-project, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
|
|
8
|
+
requires: [init, new-project, discovery-to-build, build-handoff, new-milestone, complete-milestone, audit-milestone, milestone-summary, import, ingest-docs, profile-user, review-backlog]
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
Route to the appropriate project / milestone skill based on the user's intent.
|
|
@@ -16,6 +16,8 @@ inline as part of `pp-audit-milestone`'s output.
|
|
|
16
16
|
|---|---|
|
|
17
17
|
| Initialize a project (canonical front door) | pp-init |
|
|
18
18
|
| Start a new project | pp-new-project |
|
|
19
|
+
| Hand off a completed Discovery Sprint into the build flow | pp-discovery-to-build |
|
|
20
|
+
| (deprecated) Discovery→build handoff alias | pp-build-handoff |
|
|
19
21
|
| Create a new milestone | pp-new-milestone |
|
|
20
22
|
| Complete the current milestone | pp-complete-milestone |
|
|
21
23
|
| Audit a milestone for issues | pp-audit-milestone |
|
package/gemini-extension.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pp-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "PP Core — a meta-prompting, context engineering, and spec-driven development system for AI coding agents. Loads pp-core's operating context into every Gemini CLI session.",
|
|
5
5
|
"contextFileName": "GEMINI.md"
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pareto4/pp-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Pareto pp-core — The Pareto Project's AI-assisted engineering framework: meta-prompting, context engineering, and spec-driven development for AI coding agents.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"pp-core": "bin/install.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"pp-core",
|
|
14
14
|
"assets",
|
|
15
15
|
"agents",
|
|
16
|
+
"pareto-skills",
|
|
16
17
|
".claude-plugin",
|
|
17
18
|
"gemini-extension.json",
|
|
18
19
|
"GEMINI.md",
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# create-project-board.sh
|
|
3
|
+
#
|
|
4
|
+
# Canonical GitHub Project v2 board creation for Pareto skills.
|
|
5
|
+
# Creates (or updates) a project board for a given owner/repo with the
|
|
6
|
+
# standard Pareto status columns, custom fields, and label palette.
|
|
7
|
+
#
|
|
8
|
+
# Used by:
|
|
9
|
+
# - pareto-project-setup (initial scaffold)
|
|
10
|
+
# - pareto-build-handoff (Discovery → pp-core handoff)
|
|
11
|
+
# - pareto-push-issues (standalone requirements push)
|
|
12
|
+
#
|
|
13
|
+
# Single source of truth — edit here, not in the skills.
|
|
14
|
+
#
|
|
15
|
+
# Usage:
|
|
16
|
+
# source _shared/create-project-board.sh
|
|
17
|
+
# create_project_board "<owner>" "<project_title>" "<repo_slug>"
|
|
18
|
+
#
|
|
19
|
+
# Example:
|
|
20
|
+
# create_project_board "pareto-project" "my-app" "pareto-project/my-app"
|
|
21
|
+
#
|
|
22
|
+
# Environment variables honored:
|
|
23
|
+
# BOARD_OWNER_FALLBACK (default: "@me") — used if org create fails
|
|
24
|
+
#
|
|
25
|
+
# Returns (via stdout, space-separated): <board_number> <owner>
|
|
26
|
+
# Exits non-zero on fatal error.
|
|
27
|
+
|
|
28
|
+
set -euo pipefail
|
|
29
|
+
|
|
30
|
+
# -----------------------------------------------------------------------------
|
|
31
|
+
# Canonical column schema
|
|
32
|
+
# -----------------------------------------------------------------------------
|
|
33
|
+
# Any change here propagates to every skill that sources this file.
|
|
34
|
+
#
|
|
35
|
+
# Status flow:
|
|
36
|
+
# Backlog → Discuss → Planned → In Progress → Verification → PR Raised → Done
|
|
37
|
+
#
|
|
38
|
+
# Each column maps 1:1 to a pp-core workflow step:
|
|
39
|
+
# Discuss = /pp-discuss-phase (CONTEXT.md written)
|
|
40
|
+
# Planned = /pp-plan-phase (PLAN.md created)
|
|
41
|
+
# In Progress = /pp-execute-phase (branch active, executing)
|
|
42
|
+
# Verification = VERIFICATION.md written, tests passing
|
|
43
|
+
# PR Raised = PR created from phase branch, awaiting merge
|
|
44
|
+
# Done = PR merged, issue closed
|
|
45
|
+
#
|
|
46
|
+
PARETO_STATUS_OPTIONS='[
|
|
47
|
+
{name: "Backlog", color: GRAY, description: "Not yet started"},
|
|
48
|
+
{name: "Discuss", color: PINK, description: "Context gathering via /pp-discuss-phase"},
|
|
49
|
+
{name: "Planned", color: BLUE, description: "Plans created via /pp-plan-phase"},
|
|
50
|
+
{name: "In Progress", color: YELLOW, description: "Executing via /pp-execute-phase"},
|
|
51
|
+
{name: "Verification", color: ORANGE, description: "Verification passed — VERIFICATION.md written"},
|
|
52
|
+
{name: "PR Raised", color: PURPLE, description: "PR created from phase branch, awaiting merge"},
|
|
53
|
+
{name: "Done", color: GREEN, description: "PR merged, issue closed"}
|
|
54
|
+
]'
|
|
55
|
+
|
|
56
|
+
# Label color palette for per-EPIC labels. Cycle through these in order.
|
|
57
|
+
PARETO_EPIC_COLORS=(
|
|
58
|
+
"0E8A16" "1AA393" "D93F0B" "B44EFF"
|
|
59
|
+
"4A9EFF" "EF4444" "F5C842" "8B5CF6"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# -----------------------------------------------------------------------------
|
|
63
|
+
# create_project_board <owner> <title> <owner/repo>
|
|
64
|
+
# -----------------------------------------------------------------------------
|
|
65
|
+
create_project_board() {
|
|
66
|
+
local OWNER="$1"
|
|
67
|
+
local TITLE="$2"
|
|
68
|
+
local REPO="$3"
|
|
69
|
+
local BOARD_NUM
|
|
70
|
+
|
|
71
|
+
# 1. Check for existing board matching title
|
|
72
|
+
BOARD_NUM=$(gh project list --owner "$OWNER" --format json 2>/dev/null \
|
|
73
|
+
| jq -r ".projects[] | select(.title==\"$TITLE\") | .number" || true)
|
|
74
|
+
|
|
75
|
+
if [ -z "$BOARD_NUM" ]; then
|
|
76
|
+
# 2. Try to create under the given owner
|
|
77
|
+
BOARD_NUM=$(gh project create --owner "$OWNER" --title "$TITLE" \
|
|
78
|
+
--format json 2>/dev/null | jq -r '.number' || true)
|
|
79
|
+
|
|
80
|
+
# 3. Fall back to personal projects if org creation failed
|
|
81
|
+
if [ -z "$BOARD_NUM" ]; then
|
|
82
|
+
OWNER="${BOARD_OWNER_FALLBACK:-@me}"
|
|
83
|
+
BOARD_NUM=$(gh project create --owner "$OWNER" --title "$TITLE" \
|
|
84
|
+
--format json | jq -r '.number')
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# 4. Link board to repo
|
|
88
|
+
gh project link "$BOARD_NUM" --owner "$OWNER" --repo "$REPO" >/dev/null
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# 5. Configure Status field with Pareto schema (idempotent — safe to re-run)
|
|
92
|
+
configure_status_field "$BOARD_NUM" "$OWNER"
|
|
93
|
+
|
|
94
|
+
# 6. Ensure custom fields exist (Priority, Sprint, Estimate, Phase)
|
|
95
|
+
ensure_custom_fields "$BOARD_NUM" "$OWNER"
|
|
96
|
+
|
|
97
|
+
echo "$BOARD_NUM $OWNER"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# -----------------------------------------------------------------------------
|
|
101
|
+
# configure_status_field <board_num> <owner>
|
|
102
|
+
# -----------------------------------------------------------------------------
|
|
103
|
+
configure_status_field() {
|
|
104
|
+
local BOARD_NUM="$1"
|
|
105
|
+
local OWNER="$2"
|
|
106
|
+
local STATUS_FIELD_ID
|
|
107
|
+
|
|
108
|
+
STATUS_FIELD_ID=$(gh project field-list "$BOARD_NUM" --owner "$OWNER" --format json \
|
|
109
|
+
--jq '.fields[] | select(.name=="Status") | .id')
|
|
110
|
+
|
|
111
|
+
if [ -z "$STATUS_FIELD_ID" ]; then
|
|
112
|
+
echo "ERROR: Status field not found on board $BOARD_NUM" >&2
|
|
113
|
+
return 1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
gh api graphql -f query="
|
|
117
|
+
mutation {
|
|
118
|
+
updateProjectV2Field(input: {
|
|
119
|
+
fieldId: \"$STATUS_FIELD_ID\"
|
|
120
|
+
singleSelectOptions: $PARETO_STATUS_OPTIONS
|
|
121
|
+
}) {
|
|
122
|
+
projectV2Field { ... on ProjectV2SingleSelectField { id name } }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
" >/dev/null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# -----------------------------------------------------------------------------
|
|
129
|
+
# ensure_custom_fields <board_num> <owner>
|
|
130
|
+
# -----------------------------------------------------------------------------
|
|
131
|
+
ensure_custom_fields() {
|
|
132
|
+
local BOARD_NUM="$1"
|
|
133
|
+
local OWNER="$2"
|
|
134
|
+
|
|
135
|
+
# Priority (single-select)
|
|
136
|
+
gh project field-create "$BOARD_NUM" --owner "$OWNER" \
|
|
137
|
+
--name "Priority" --data-type "SINGLE_SELECT" \
|
|
138
|
+
--single-select-options "Must Have,Should Have,Could Have,Won't Have" \
|
|
139
|
+
2>/dev/null || true
|
|
140
|
+
|
|
141
|
+
# Sprint (iteration — created manually in UI if needed)
|
|
142
|
+
gh project field-create "$BOARD_NUM" --owner "$OWNER" \
|
|
143
|
+
--name "Sprint" --data-type "ITERATION" 2>/dev/null || true
|
|
144
|
+
|
|
145
|
+
# Estimate (number)
|
|
146
|
+
gh project field-create "$BOARD_NUM" --owner "$OWNER" \
|
|
147
|
+
--name "Estimate" --data-type "NUMBER" 2>/dev/null || true
|
|
148
|
+
|
|
149
|
+
# Phase (text — pp-core phase number reference, e.g. "3" or "3.1")
|
|
150
|
+
gh project field-create "$BOARD_NUM" --owner "$OWNER" \
|
|
151
|
+
--name "Phase" --data-type "TEXT" 2>/dev/null || true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# -----------------------------------------------------------------------------
|
|
155
|
+
# ensure_core_labels <owner/repo>
|
|
156
|
+
# -----------------------------------------------------------------------------
|
|
157
|
+
# Idempotent — uses --force so existing labels get updated.
|
|
158
|
+
ensure_core_labels() {
|
|
159
|
+
local REPO="$1"
|
|
160
|
+
|
|
161
|
+
gh label create "epic" -c "3E4B9E" -d "Epic — high-level feature group" --force -R "$REPO"
|
|
162
|
+
gh label create "user-story" -c "1D76DB" -d "User story" --force -R "$REPO"
|
|
163
|
+
gh label create "must-have" -c "B60205" -d "Must Have — MVP required" --force -R "$REPO"
|
|
164
|
+
gh label create "should-have" -c "FBCA04" -d "Should Have — important" --force -R "$REPO"
|
|
165
|
+
gh label create "could-have" -c "0E8A16" -d "Could Have — nice to have" --force -R "$REPO"
|
|
166
|
+
gh label create "in-progress" -c "FBCA04" -d "Phase branch actively executing" --force -R "$REPO"
|
|
167
|
+
gh label create "verification" -c "D93F0B" -d "In pp-core verification + PR review" --force -R "$REPO"
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# -----------------------------------------------------------------------------
|
|
171
|
+
# create_epic_label <owner/repo> <slug> <epic_id> <epic_title> <index>
|
|
172
|
+
# -----------------------------------------------------------------------------
|
|
173
|
+
# Color cycles through PARETO_EPIC_COLORS by index.
|
|
174
|
+
create_epic_label() {
|
|
175
|
+
local REPO="$1"
|
|
176
|
+
local SLUG="$2"
|
|
177
|
+
local EPIC_ID="$3"
|
|
178
|
+
local TITLE="$4"
|
|
179
|
+
local IDX="$5"
|
|
180
|
+
local COLOR="${PARETO_EPIC_COLORS[$((IDX % ${#PARETO_EPIC_COLORS[@]}))]}"
|
|
181
|
+
|
|
182
|
+
gh label create "epic:${SLUG}" -c "$COLOR" -d "${EPIC_ID}: ${TITLE}" --force -R "$REPO"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# -----------------------------------------------------------------------------
|
|
186
|
+
# If sourced, functions above are exported to the caller. If executed directly,
|
|
187
|
+
# run create_project_board with positional args.
|
|
188
|
+
# -----------------------------------------------------------------------------
|
|
189
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
190
|
+
if [ $# -lt 3 ]; then
|
|
191
|
+
echo "Usage: $0 <owner> <title> <owner/repo>" >&2
|
|
192
|
+
exit 1
|
|
193
|
+
fi
|
|
194
|
+
create_project_board "$@"
|
|
195
|
+
fi
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
pp-claude-md-protocol.md
|
|
3
|
+
|
|
4
|
+
Canonical pp-core ↔ GitHub protocol injected into a project's CLAUDE.md.
|
|
5
|
+
|
|
6
|
+
Used by:
|
|
7
|
+
- pareto-build-handoff (Step 6b: CLAUDE.md update)
|
|
8
|
+
- pareto-push-issues (Step 5.5: CLAUDE.md injection)
|
|
9
|
+
|
|
10
|
+
To inject: append the block below `## GitHub Board Sync` (if a section of
|
|
11
|
+
that name already exists, replace it — idempotent).
|
|
12
|
+
|
|
13
|
+
Single source of truth — edit here, not in the skills. Every repo that
|
|
14
|
+
runs build-handoff or push-issues gets the same protocol.
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
## GitHub Board Sync
|
|
18
|
+
|
|
19
|
+
Requirements are tracked as GitHub issues on a project board. The mapping
|
|
20
|
+
between pp-core requirement IDs (EPIC-xxx, US-xxx, FR-xxx) and GitHub issue
|
|
21
|
+
numbers lives in `.planning/github-issues.json`.
|
|
22
|
+
|
|
23
|
+
**Status flow:**
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
Backlog → Discuss → Planned → In Progress → Verification → PR Raised → Done
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Every phase runs on its own branch and merges to `main` via a pull request
|
|
30
|
+
after verification passes. Stories only close when their phase PR is merged.
|
|
31
|
+
|
|
32
|
+
### Per-phase lifecycle
|
|
33
|
+
|
|
34
|
+
**1. Phase starts (executing begins)**
|
|
35
|
+
|
|
36
|
+
Create a branch from `main` named `phase/{N}-{slug}` (slug from ROADMAP.md
|
|
37
|
+
phase title, kebab-case). All phase commits — code AND `.planning/` artifacts
|
|
38
|
+
— land on this branch.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git checkout main && git pull
|
|
42
|
+
git checkout -b "phase/${N}-${SLUG}"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Move each story issue covered by the phase to **In Progress**:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
gh issue edit {number} --add-label "in-progress,phase:{N}" \
|
|
49
|
+
--remove-label "verification" -R {repo}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Also set the `Phase` custom field on the board item to the phase number.
|
|
53
|
+
|
|
54
|
+
**2. Phase implementation complete (SUMMARY.md written)**
|
|
55
|
+
|
|
56
|
+
Push the branch (first push uses `-u origin HEAD`) and move the stories to
|
|
57
|
+
**Verification**:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git push -u origin HEAD
|
|
61
|
+
gh issue edit {number} --add-label "verification" \
|
|
62
|
+
--remove-label "in-progress" -R {repo}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**3. Verification passes (VERIFICATION.md result = PASS)**
|
|
66
|
+
|
|
67
|
+
Open a pull request from the phase branch to `main`. The PR body MUST use
|
|
68
|
+
`Closes #N` for every story issue so GitHub auto-closes them on merge.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
PR_BODY=$(cat <<EOF
|
|
72
|
+
# Phase ${N}: ${PHASE_TITLE}
|
|
73
|
+
|
|
74
|
+
## Summary
|
|
75
|
+
${SUMMARY_FROM_SUMMARY_MD}
|
|
76
|
+
|
|
77
|
+
## Requirements delivered
|
|
78
|
+
Closes #${ISSUE1} — ${US_ID_1}: ${STORY_TITLE_1}
|
|
79
|
+
Closes #${ISSUE2} — ${US_ID_2}: ${STORY_TITLE_2}
|
|
80
|
+
|
|
81
|
+
## Verification
|
|
82
|
+
VERIFICATION.md result: PASS
|
|
83
|
+
- ${KEY_OUTCOMES}
|
|
84
|
+
|
|
85
|
+
## Phase artifacts
|
|
86
|
+
- \`.planning/phases/${N}-${SLUG}/PLAN.md\`
|
|
87
|
+
- \`.planning/phases/${N}-${SLUG}/SUMMARY.md\`
|
|
88
|
+
- \`.planning/phases/${N}-${SLUG}/VERIFICATION.md\`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
Generated by pp-core phase execution.
|
|
92
|
+
EOF
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
gh pr create \
|
|
96
|
+
--base main \
|
|
97
|
+
--head "phase/${N}-${SLUG}" \
|
|
98
|
+
--title "Phase ${N}: ${PHASE_TITLE}" \
|
|
99
|
+
--body "$PR_BODY" \
|
|
100
|
+
--label "phase:${N}"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Do not close the story issues at this step.** They stay in Verification
|
|
104
|
+
until the PR merges. Keeping them open until merge is what makes the board
|
|
105
|
+
reflect *merged* reality, not just *verified* intent.
|
|
106
|
+
|
|
107
|
+
If verification fails: fix the code on the same phase branch, re-run
|
|
108
|
+
verification, update the PR (it auto-updates from new commits). No new
|
|
109
|
+
branch.
|
|
110
|
+
|
|
111
|
+
**4. PR merged**
|
|
112
|
+
|
|
113
|
+
GitHub auto-closes linked issues. The sync protocol then reconciles:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Sync loop — run after merge (or via /pareto-sync-board)
|
|
117
|
+
gh issue edit {number} --remove-label "in-progress,verification" -R {repo}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Update `.planning/github-issues.json`: set each story's `status` to `"Done"`
|
|
121
|
+
and each EPIC's `status` based on whether all its stories are now closed.
|
|
122
|
+
|
|
123
|
+
If the merged phase closed ALL stories under an EPIC, also close the EPIC
|
|
124
|
+
issue with a delivery note:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
gh issue close {epic_number} -R {repo} \
|
|
128
|
+
-c "All stories delivered across phases {list}."
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Status map for .planning/github-issues.json
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
"status_map": {
|
|
135
|
+
"Backlog": "Backlog",
|
|
136
|
+
"discussing": "Discuss",
|
|
137
|
+
"planned": "Planned",
|
|
138
|
+
"executing": "In Progress",
|
|
139
|
+
"verifying": "Verification",
|
|
140
|
+
"pr_open": "PR Raised",
|
|
141
|
+
"complete": "Done"
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Filtered code-only PRs (optional)
|
|
146
|
+
|
|
147
|
+
If the team wants PR diffs without `.planning/` noise, run `/pp-pr-branch`
|
|
148
|
+
after Step 3 to produce a filtered branch. The filtered branch becomes the
|
|
149
|
+
PR head instead of `phase/{N}-{slug}`. The original phase branch stays as
|
|
150
|
+
the auditable work record.
|
|
151
|
+
|
|
152
|
+
### MANDATORY: Board sync after pp-core phase transitions
|
|
153
|
+
|
|
154
|
+
**These instructions are project-level overrides.** When `.planning/github-issues.json`
|
|
155
|
+
exists, you MUST run the sync script and issue updates at each lifecycle transition
|
|
156
|
+
below. Sync is non-blocking — failures must never stop the pp-core workflow (always
|
|
157
|
+
append `|| true`).
|
|
158
|
+
|
|
159
|
+
**After `/pp-discuss-phase` completes** (CONTEXT.md written):
|
|
160
|
+
|
|
161
|
+
Move stories to **Discuss** and comment on each with key decisions:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "Discuss" 2>&1 || true
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Comment on each story issue for this phase with key decisions that affect it:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
if [ -f ".planning/github-issues.json" ]; then
|
|
171
|
+
REPO=$(jq -r '.repo' .planning/github-issues.json)
|
|
172
|
+
# For each story in the phase, add a comment with relevant decisions from CONTEXT.md
|
|
173
|
+
jq -r --argjson p "${PHASE_NUMBER}" '.issues | to_entries[] | select(.value.phase == $p and .value.type == "story") | "\(.key) \(.value.number)"' .planning/github-issues.json | while read REQ_ID ISSUE_NUM; do
|
|
174
|
+
gh issue comment "$ISSUE_NUM" -R "$REPO" --body "## Phase ${PHASE_NUMBER} — Context gathered
|
|
175
|
+
|
|
176
|
+
Decisions from \`/pp-discuss-phase\` that affect ${REQ_ID}:
|
|
177
|
+
|
|
178
|
+
${DECISIONS_RELEVANT_TO_THIS_STORY}
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
_Auto-posted by pp-core discuss-phase_" 2>/dev/null || true
|
|
182
|
+
done
|
|
183
|
+
fi
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Replace `${DECISIONS_RELEVANT_TO_THIS_STORY}` with the actual decisions from CONTEXT.md
|
|
187
|
+
that are relevant to each story. Extract from `<decisions>` section.
|
|
188
|
+
|
|
189
|
+
**After `/pp-plan-phase` completes planning** (plans pass all gates, STATE.md updated):
|
|
190
|
+
|
|
191
|
+
Move stories to **Planned** and comment with plan assignment:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "Planned" 2>&1 || true
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Then comment on each story issue with which plan covers it:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
if [ -f ".planning/github-issues.json" ]; then
|
|
201
|
+
REPO=$(jq -r '.repo' .planning/github-issues.json)
|
|
202
|
+
# For each story, find which PLAN.md references its requirement ID and comment
|
|
203
|
+
jq -r --argjson p "${PHASE_NUMBER}" '.issues | to_entries[] | select(.value.phase == $p and .value.type == "story") | "\(.key) \(.value.number)"' .planning/github-issues.json | while read REQ_ID ISSUE_NUM; do
|
|
204
|
+
gh issue comment "$ISSUE_NUM" -R "$REPO" --body "## Phase ${PHASE_NUMBER} — Planned
|
|
205
|
+
|
|
206
|
+
Covered by: \`${PLAN_FILE}\` (Wave ${WAVE})
|
|
207
|
+
Key tasks: ${TASK_SUMMARY}
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
_Auto-posted by pp-core plan-phase_" 2>/dev/null || true
|
|
211
|
+
done
|
|
212
|
+
fi
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Replace `${PLAN_FILE}`, `${WAVE}`, and `${TASK_SUMMARY}` with actual values from the
|
|
216
|
+
PLAN.md that contains this story's requirement ID in its `requirements` frontmatter field.
|
|
217
|
+
|
|
218
|
+
**After `/pp-execute-phase` begins execution** (branch created, STATE.md shows phase active):
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "In Progress" --label-add "in-progress" --label-remove "verification" 2>&1 || true
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**After `/pp-execute-phase` verification passes** (VERIFICATION.md written, ROADMAP.md updated):
|
|
225
|
+
|
|
226
|
+
Move stories to **Verification**:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "Verification" --label-add "verification" --label-remove "in-progress" 2>&1 || true
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**After PR is created** (push branch, create PR):
|
|
233
|
+
|
|
234
|
+
Push the branch and create a PR, then move stories to **PR Raised**:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# 1. Push the phase branch
|
|
238
|
+
git push -u origin HEAD 2>&1 || true
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# 2. Build PR body with Closes links for every story in this phase
|
|
243
|
+
if [ -f ".planning/github-issues.json" ]; then
|
|
244
|
+
REPO=$(jq -r '.repo' .planning/github-issues.json)
|
|
245
|
+
CLOSES_LINES=$(jq -r --argjson p "${PHASE_NUMBER}" '
|
|
246
|
+
.issues | to_entries[]
|
|
247
|
+
| select(.value.phase == $p and .value.type == "story")
|
|
248
|
+
| "Closes #\(.value.number) — \(.key): \(.value.title)"
|
|
249
|
+
' .planning/github-issues.json)
|
|
250
|
+
|
|
251
|
+
gh pr create \
|
|
252
|
+
--base main \
|
|
253
|
+
--head "phase/${PHASE_NUMBER}-${PHASE_SLUG}" \
|
|
254
|
+
--title "Phase ${PHASE_NUMBER}: ${PHASE_NAME}" \
|
|
255
|
+
--body "$(cat <<EOF
|
|
256
|
+
## Summary
|
|
257
|
+
|
|
258
|
+
${SUMMARY_FROM_VERIFICATION_MD}
|
|
259
|
+
|
|
260
|
+
## Requirements delivered
|
|
261
|
+
|
|
262
|
+
${CLOSES_LINES}
|
|
263
|
+
|
|
264
|
+
## Verification
|
|
265
|
+
|
|
266
|
+
VERIFICATION.md result: PASS
|
|
267
|
+
|
|
268
|
+
## Phase artifacts
|
|
269
|
+
|
|
270
|
+
- \`.planning/phases/${PADDED_PHASE}-${PHASE_SLUG}/PLAN.md\`
|
|
271
|
+
- \`.planning/phases/${PADDED_PHASE}-${PHASE_SLUG}/SUMMARY.md\`
|
|
272
|
+
- \`.planning/phases/${PADDED_PHASE}-${PHASE_SLUG}/VERIFICATION.md\`
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
Generated by pp-core phase execution.
|
|
276
|
+
EOF
|
|
277
|
+
)" 2>/dev/null || true
|
|
278
|
+
fi
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# 4. Move stories to PR Raised
|
|
283
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "PR Raised" 2>&1 || true
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Stories stay in **PR Raised** until the PR is merged. GitHub auto-closes
|
|
287
|
+
the linked issues via `Closes #N`, which moves them to **Done** on the board.
|
|
288
|
+
|
|
289
|
+
After PR merge, clean up labels:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
[ -f ".planning/github-issues.json" ] && bash "$HOME/.claude/skills/pareto/_shared/sync-phase-status.sh" "${PHASE_NUMBER}" "Done" --label-remove "in-progress,verification" 2>&1 || true
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
If any sync is missed or the board drifts, use the recovery steps below.
|
|
296
|
+
|
|
297
|
+
### Recovery
|
|
298
|
+
|
|
299
|
+
If any step is missed, run `/pareto-sync-board` to reconcile. It:
|
|
300
|
+
- Reads `.planning/STATE.md`, `ROADMAP.md`, and every phase directory
|
|
301
|
+
- Checks `gh pr list --head phase/{N}-*` for PR state
|
|
302
|
+
- Only closes stories whose phase PR shows state `MERGED`
|
|
303
|
+
- Rewrites `github-issues.json` to match live board state
|
|
304
|
+
|
|
305
|
+
If `.planning/github-issues.json` is missing entirely, run
|
|
306
|
+
`/pareto-push-issues` to rebuild it from `.planning/REQUIREMENTS.md`.
|