From 1f72bc5ceb6924b4dc4e8b556a8e0d87915a760a Mon Sep 17 00:00:00 2001 From: Gianluca Carucci Date: Sun, 19 Jul 2026 21:25:52 +0200 Subject: [PATCH 1/3] [#256] feat: implement composes checkpoint + publish-pr via handoff-only subagent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Phase 0 resume probe (Step 0.0): /checkpoint $mode=resume, jump to first pending task, no repeat (AC2) - Phase 3 closing: /checkpoint $mode=write then /publish-pr in an anonymous handoff-only subagent — clean context, D23/D7 (AC1) - Degraded inline path when subagent spawning unavailable; degradation noted in output (AC3) - Edge cases: branch-missing HALT (divergence), stale-checkpoint confirm, subagent-fail idempotent rerun - 5-step task cycle unchanged (AC4); implement composes /publish-pr, never re-does gate/PR logic - Regenerated .claude mirror via content-ops transforms (byte-consistent with pair update) - Conformance test guarding the composition/resume/degrade invariants - Tasks: T1, T2, T3, T4 Refs: #256 --- .../skills/pair-process-implement/SKILL.md | 134 ++++++++++-------- .../.skills/process/implement/SKILL.md | 130 +++++++++-------- .../implement-compose-close.test.ts | 126 ++++++++++++++++ 3 files changed, 266 insertions(+), 124 deletions(-) create mode 100644 packages/knowledge-hub/src/conformance/implement-compose-close.test.ts diff --git a/.claude/skills/pair-process-implement/SKILL.md b/.claude/skills/pair-process-implement/SKILL.md index 43ec79c2..71c732ab 100644 --- a/.claude/skills/pair-process-implement/SKILL.md +++ b/.claude/skills/pair-process-implement/SKILL.md @@ -1,13 +1,17 @@ --- name: pair-process-implement -description: "Implements a refined user story task-by-task, via a 5-step cycle per task (context, branch, implementation, quality, commit), and opens one PR when the story completes. Composes /pair-capability-verify-quality, /pair-capability-record-decision." -version: 0.4.1 +description: "Implements a refined user story task-by-task, via a 5-step cycle per task (context, branch, implementation, quality, commit). At the closing phase it writes a checkpoint and publishes the PR through a handoff-only subagent (clean context), resuming from the checkpoint when re-invoked on an interrupted story. Composes /pair-capability-verify-quality, /pair-capability-record-decision, /pair-capability-checkpoint, /pair-capability-publish-pr." +version: 0.5.0 author: Foomakers --- # /pair-process-implement — Task Implementation -Implement a user story by processing its tasks sequentially. Each task follows a 5-step cycle: context → branch → implementation → quality → commit. The story-level process has 5 phases (0–4): analysis, setup, implementation, PR creation, and post-review merge. Creates a single PR when all tasks are done. +Implement a user story by processing its tasks sequentially. Each task follows a 5-step cycle: context → branch → implementation → quality → commit. The story-level process has 5 phases (0–4): analysis, setup, implementation, **closing (checkpoint + PR)**, and post-review merge. When all tasks are done the closing phase writes a checkpoint (the handoff artifact) and composes `/pair-capability-publish-pr` — inside a **handoff-only subagent** so the PR is always built on a guaranteed-clean context — to produce a single ready-for-review PR. + +**Two AI macro-phases (R4.2):** refinement → implementation. The boundary artifact between them is a **checkpoint**: it is written at the closing phase and re-read at the opening phase so an interrupted story resumes exactly where it stopped, never repeating completed tasks. + +**implement composes, it never re-does gate/PR logic.** The gate → PR → board sequence lives entirely in `/pair-capability-publish-pr`; this skill composes it (never re-implements PR creation). Task iteration and the checkpoint boundary are what `/pair-process-implement` owns. **One PR per story:** the story lands on ONE branch with ONE PR; subsequent work on the story (further tasks/features) updates that same PR, never a new one unless a human explicitly requests it. @@ -17,6 +21,8 @@ Implement a user story by processing its tasks sequentially. Each task follows a | ------------------ | ---------- | --------------------------------------------------------------------------------------------------- | | `/pair-capability-verify-quality` | Capability | Yes — invoked at quality validation phase | | `/pair-capability-record-decision` | Capability | Yes — invoked when a decision needs recording | +| `/pair-capability-checkpoint` | Capability | Yes — `$mode=resume` at the opening phase (resume probe), `$mode=write` at the closing phase (handoff artifact). If not installed, degrade to git+PM-tool resume (see Graceful Degradation). | +| `/pair-capability-publish-pr` | Capability | Yes — the closing phase composes it (gate → PR → board) inside a handoff-only subagent. If not installed → **HALT** (implement never re-implements PR creation). | | `/pair-capability-assess-stack` | Capability | Optional — invoked when a new dependency is detected. If not installed, warn and continue. | | `/pair-capability-verify-adoption` | Capability | Optional — invoked before commit to check adoption compliance. If not installed, warn and continue. | @@ -24,6 +30,19 @@ Implement a user story by processing its tasks sequentially. Each task follows a #### No implementation without complete understanding. +### Step 0.0: Resume Probe (checkpoint) — NEVER SKIP + +The opening phase re-reads the checkpoint so an interrupted story resumes exactly where it stopped (AC2). This runs first, before loading the story, so completed tasks are never re-done. + +1. **Check**: Is `/pair-capability-checkpoint` installed AND does a checkpoint exist for this story (`.pair/working/checkpoints/.md`)? +2. **Skip**: If no checkpoint exists → this is a fresh start. Proceed to Step 0.1 (normal one-shot flow — no regression, AC4). +3. **Act**: Compose `/pair-capability-checkpoint $mode=resume` (pass `$story` when known). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. +4. **Act — edge cases** (resolve before continuing): + - **Checkpoint exists but its branch is missing** (checkpoint says branch X, repo has none): **HALT** and report the divergence. Do not guess a branch. + - **Stale checkpoint (story already Done)**: warn that the story is already Done and **require explicit developer confirmation** before reusing the checkpoint. Never silently resume a finished story. + - **Corrupted/incomplete checkpoint**: `/pair-capability-checkpoint` reports what parsed and what is missing — confirm the gaps with the developer before proceeding (never guess). +5. **Verify**: Either a fresh start is confirmed, or a valid checkpoint is resumed with the first pending task identified. If `/pair-capability-checkpoint` is not installed, fall back to the git+PM-tool resume (Idempotent Re-invocation) and continue. + ### Step 0.1: Load Story 1. **Check**: Is the user story already loaded in this session? @@ -223,11 +242,14 @@ Follow the TDD discipline rules strictly, and the [Design Rules](../../../.pair/ 7. **Act**: Update the PM tool story issue body: - Mark the completed task checkbox (`- [x] **T-N**`) in the **Task Breakdown** section. - Mark any **Definition of Done** checkboxes that are now factually satisfied by this task's work (e.g., "SKILL.md created", "template validated"). Leave unchecked items that require reviewer confirmation (e.g., "Code reviewed and merged"). -8. **Check**: Is this the last task? - - **Yes**: Move to Phase 3 (PR). +8. **Act — persist progress**: If `/pair-capability-checkpoint` is installed, compose `/pair-capability-checkpoint $mode=write` to update `.pair/working/checkpoints/.md` with the tasks now done. This keeps the checkpoint current so an interruption after this task resumes from the next pending one (Step 0.0). If `/pair-capability-checkpoint` is not installed, skip — git+PM state still supports the git-based resume. +9. **Check**: Is this the last task? + - **Yes**: Move to Phase 3 (Closing: checkpoint + PR). - **No**: Return to Step 2.1. -## Phase 3: Commit (if per-story), Push & PR +## Phase 3: Closing — Checkpoint + Publish PR + +The task cycle is done. The closing phase writes the checkpoint (handoff artifact) and composes `/pair-capability-publish-pr` inside a handoff-only subagent, so the PR is built on a guaranteed-clean context. implement never re-does the gate/PR/board logic here — it composes `/pair-capability-publish-pr` only. ### Step 3.1: Final Commit (if commit-per-story) @@ -261,82 +283,63 @@ Follow the TDD discipline rules strictly, and the [Design Rules](../../../.pair/ - Mark ALL task checkboxes (`- [x] **T-N**`) in the **Task Breakdown** section. - Mark all **Definition of Done** checkboxes that are factually satisfied by the implementation. Leave unchecked items that require reviewer confirmation (e.g., "Code reviewed and merged"). -### Step 3.2: Push Branch +### Step 3.2: Write the Checkpoint (handoff artifact) -1. **Check**: Is the branch already pushed and up to date with remote? -2. **Skip**: If up to date, move to Step 3.3. -3. **Act**: Push the branch: +The checkpoint is the boundary artifact (R4.2) and the **input contract for `/pair-capability-publish-pr`** — the handoff document the subagent runs on. - ```bash - git push -u origin feature/#- - ``` - -4. **Verify**: Branch pushed to remote. +1. **Act**: Compose `/pair-capability-checkpoint $mode=write` (pass `$story`). This creates/updates `.pair/working/checkpoints/.md` with the five sections: story, branch, tasks done, key decisions, remaining todos. +2. **Verify**: The checkpoint file exists and captures the completed story state (all tasks done, branch, decisions). This file — not this session's memory — is what the PR is built from. +3. **Act — if `/pair-capability-checkpoint` is not installed**: synthesize the handoff inline (branch, tasks done, decisions, ACs) and pass it directly to `/pair-capability-publish-pr` as `$handoff`; note the absence in the output. -### Step 3.3: Confirm PR with Developer +### Step 3.3: Publish the PR via a Handoff-Only Subagent (AC1) -1. **Act**: Present a summary before creating the PR: +The PR is produced on a **guaranteed-clean context**: a fresh subagent whose entire prompt is the handoff, nothing from this session. This is mechanical isolation (D23) — an **anonymous** subagent, **no named role**. A skill cannot `/clear` its own context (D7), so the reset is achieved by delegating to a subagent. - ```text - PR READY: - ├── Branch: [feature/#story-id-description] - ├── Tasks: [N/N completed] - ├── Commits: [N commits on branch] - ├── Quality: [All gates passing] - └── Title: [#] : - ``` +1. **Check**: Is subagent spawning available in this tool/environment? +2. **Act — primary path (subagent)**: Spawn an **anonymous subagent** whose prompt is the **handoff document only** — the checkpoint contents (or the path `.pair/working/checkpoints/.md`) plus a single instruction: run `/pair-capability-publish-pr $story= $handoff=.pair/working/checkpoints/.md`. Pass **no other session context** — the subagent's context is the handoff and nothing else (clean context / fresh context reset within one execution, R4.1). The subagent runs `/pair-capability-publish-pr` (gate → PR → tags → ready-for-review → board) and returns the PR number/URL and board result. +3. **Act — degraded inline path (AC3)**: If subagent spawning is **unavailable** (tool/environment cannot spawn one — subagent spawning unavailable), do NOT skip the split: the checkpoint is already written (Step 3.2), then compose `/pair-capability-publish-pr` **inline** in the current session (`$story`, `$handoff` = the checkpoint). **Note the degradation in the output** (`Context: degraded — inline publish, no subagent reset`). Behavior is otherwise equivalent to the primary path. +4. **Act — edge case (subagent fails mid-PR)**: The checkpoint remains valid. Re-invoking `/pair-process-implement` re-runs this closing phase; `/pair-capability-publish-pr` is **idempotent** — it detects an existing PR and updates it in place rather than opening a second one. Never open a second PR for the story. +5. **Verify**: A single ready-for-review PR exists (created or updated), and its number/URL is captured for the output. A red quality gate inside `/pair-capability-publish-pr` propagates here as a **HALT** (no PR side effects) — implement does not create the PR itself. -2. **Ask**: _"Ready to create the PR?"_ -3. **Verify**: Developer confirms. If not → wait for developer instructions. - -### Step 3.4: Create or Update PR - -1. **Check**: Does a PR already exist for this branch? -2. **Skip**: If PR exists, update its description and move to output. -3. **Act**: Read the [PR template](../../../.pair/knowledge/guidelines/collaboration/templates/pr-template.md) and fill ALL its sections: - - **Title**: `[#] : ` - - **Body**: Use the PR template structure exactly. Fill each section: - - **Summary** (What Changed + Why): from story statement and implementation - - **Story Context**: link to user story issue, list AC coverage - - **Changes Made**: list all completed tasks, files added/modified/deleted - - **Testing**: test coverage, quality gate results (from /pair-capability-verify-quality output) - - Omit template sections that do not apply (e.g., Database Changes, API Changes for KB-only PRs) — do not leave unfilled placeholders. - - **Link**: Reference the user story issue (`Closes #`) - - **Labels**: Apply appropriate labels -4. **Act**: Mark the PR as **ready for review** — ensure it is not in draft state. If the PM tool supports review request (e.g., GitHub `gh pr ready`), mark it explicitly. -5. **Verify**: PR created, description follows template, PR is ready for review. +Note: the checkpoint is **not** removed here — it must survive the review/fix loop so a re-review or fix round can resume from it. Cleanup happens at merge (Phase 4). ## Phase 4: Post-Review Merge -After code review approval (typically via `/pair-process-review`), re-invoke `/pair-process-implement` to merge and close — see [post-review-merge.md](./post-review-merge.md) for the verify-approval, merge-commit, merge, and parent-cascade steps (Steps 4.1–4.4) plus the completion output. +After code review approval (typically via `/pair-process-review`), re-invoke `/pair-process-implement` to merge and close — see [post-review-merge.md](post-review-merge.md) for the verify-approval, merge-commit, merge, and parent-cascade steps (Steps 4.1–4.4) plus the completion output. + +On story completion (Done, at merge), the checkpoint is no longer needed — remove `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). ## Output Format -At PR creation (Phase 3): +At the closing phase (Phase 3): ```text IMPLEMENTATION COMPLETE: -├── Story: [#ID: Title] -├── Branch: [feature/#ID-description] -├── Strategy: [commit-per-task | commit-per-story] -├── Tasks: [N/N completed] -├── Commits: [N commits on branch] -├── PR: [#PR-number — URL] -└── Quality: [All gates passing] +├── Story: [#ID: Title] +├── Branch: [feature/#ID-description] +├── Strategy: [commit-per-task | commit-per-story] +├── Tasks: [N/N completed] +├── Commits: [N commits on branch] +├── Checkpoint: [.pair/working/checkpoints/.md — written] +├── Context: [clean — subagent handoff-only | degraded — inline publish, no subagent reset] +├── PR: [#PR-number — URL — Created | Updated (from /publish-pr)] +└── Quality: [All gates passing] ``` -At merge (Phase 4): see [post-review-merge.md](./post-review-merge.md). +At merge (Phase 4): see [post-review-merge.md](post-review-merge.md). ## HALT Conditions Implementation stops immediately when: +- **Checkpoint/branch divergence** (Step 0.0) — checkpoint names a branch the repo does not have; report and stop, do not guess a branch - **Story not loaded or incomplete** (Phase 0) - **Task specifications incomplete** (Step 2.2) - **Quality gate failure** (Step 2.7) — developer must fix - **New dependency rejected by /assess-stack** (Step 2.4) -- **PR template not found** (Step 3.4) — cannot create PR without template - **Commit template not found** (Step 2.8 / Step 3.1) — cannot commit without template +- **`/pair-capability-publish-pr` not installed** (Step 3.3) — implement composes the PR sequence, never re-implements it +- **Quality gate red inside `/pair-capability-publish-pr`** (Step 3.3) — propagates as implement's HALT; no PR side effects (the PR-template-not-found and gate HALTs live in `/pair-capability-publish-pr`) - **PR not approved** (Step 4.1) — cannot merge without review approval On HALT: report the blocker clearly, propose resolution, wait for developer. @@ -345,12 +348,13 @@ On HALT: report the blocker clearly, propose resolution, wait for developer. See [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md). Re-invoking `/pair-process-implement` on a partially completed story is safe and expected — per-step: -1. **Branch**: detects existing branch, switches to it. -2. **Commit strategy**: if commits already exist on branch, infer strategy from history. -3. **Tasks**: scans task checklist and git log to identify completed tasks. Skips them. -4. **PR**: detects existing PR, updates instead of creating duplicate. -5. **Quality gates**: re-runs all gates (fast if already passing). -6. **Merge**: if PR exists and is approved, proceeds directly to Phase 4 (merge). +1. **Checkpoint**: the opening-phase resume probe (Step 0.0) reads the checkpoint and jumps to the first pending task — never repeating completed tasks. When `/pair-capability-checkpoint` is absent, the git+PM resume below applies. +2. **Branch**: detects existing branch, switches to it. +3. **Commit strategy**: if commits already exist on branch, infer strategy from history. +4. **Tasks**: scans task checklist and git log to identify completed tasks. Skips them. +5. **PR**: the closing phase re-composes `/pair-capability-publish-pr`, which detects an existing PR and updates it in place — never a duplicate. A subagent that failed mid-PR is recovered this way (the checkpoint stays valid, the rerun is idempotent). +6. **Quality gates**: re-runs all gates (fast if already passing). +7. **Merge**: if PR exists and is approved, proceeds directly to Phase 4 (merge). The skill resumes from the first incomplete step — never re-does completed work. @@ -358,14 +362,18 @@ The skill resumes from the first incomplete step — never re-does completed wor See [graceful degradation](../../../.pair/knowledge/skill-conventions/graceful-degradation.md) (PM tool not accessible → ask the developer directly; adoption file missing → proceed with guideline defaults) for the standard scenarios. Additional cases: +- **Subagent spawning unavailable**: take the degraded inline path (Step 3.3) — checkpoint still written, `/pair-capability-publish-pr` composed inline, degradation noted in the output. Never skip the checkpoint/PR split. +- **`/pair-capability-checkpoint` not installed**: skip the resume probe and the write step; resume from git+PM state (Idempotent Re-invocation) and synthesize the handoff inline for `/pair-capability-publish-pr`. +- **`/pair-capability-publish-pr` not installed**: **HALT** — implement composes the gate/PR/board sequence, it never re-implements it. Report the missing dependency. - **`/pair-capability-assess-stack` not installed**: Warn on new dependency, continue without validation. - **`/pair-capability-verify-adoption` not installed**: Warn, skip adoption compliance check. - **No quality gate command**: Fall back to individual checks (lint, test, type check). ## Notes -- This skill **modifies files and creates git artifacts** (branches, commits, PRs). +- This skill **modifies files and creates git artifacts** (branches, commits) and **writes the checkpoint**. The PR itself is created/updated by the composed `/pair-capability-publish-pr` (in the subagent, or inline when degraded) — implement never re-implements PR creation. +- The **subagent's prompt is the handoff only** — the checkpoint, nothing from this session. Anonymous, no named role (mechanical isolation, D23); a skill cannot `/clear` its own context (D7), so the subagent provides the clean-context reset. - Task iteration is sequential — each task completes its full cycle before the next begins. -- The developer can stop between tasks; re-invoke to resume (see [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md)). +- The developer can stop between tasks; re-invoke to resume — the opening-phase resume probe (Step 0.0) reads the checkpoint (see [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md)). - Single PR per story regardless of commit strategy. - **Squash happens at merge** (Phase 4), not before PR creation. Individual commits are preserved on the branch during review. diff --git a/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md b/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md index 8a386b7e..eb31d4ed 100644 --- a/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md +++ b/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md @@ -1,13 +1,17 @@ --- name: implement -description: "Implements a refined user story task-by-task, via a 5-step cycle per task (context, branch, implementation, quality, commit), and opens one PR when the story completes. Composes /verify-quality, /record-decision." -version: 0.4.1 +description: "Implements a refined user story task-by-task, via a 5-step cycle per task (context, branch, implementation, quality, commit). At the closing phase it writes a checkpoint and publishes the PR through a handoff-only subagent (clean context), resuming from the checkpoint when re-invoked on an interrupted story. Composes /verify-quality, /record-decision, /checkpoint, /publish-pr." +version: 0.5.0 author: Foomakers --- # /implement — Task Implementation -Implement a user story by processing its tasks sequentially. Each task follows a 5-step cycle: context → branch → implementation → quality → commit. The story-level process has 5 phases (0–4): analysis, setup, implementation, PR creation, and post-review merge. Creates a single PR when all tasks are done. +Implement a user story by processing its tasks sequentially. Each task follows a 5-step cycle: context → branch → implementation → quality → commit. The story-level process has 5 phases (0–4): analysis, setup, implementation, **closing (checkpoint + PR)**, and post-review merge. When all tasks are done the closing phase writes a checkpoint (the handoff artifact) and composes `/publish-pr` — inside a **handoff-only subagent** so the PR is always built on a guaranteed-clean context — to produce a single ready-for-review PR. + +**Two AI macro-phases (R4.2):** refinement → implementation. The boundary artifact between them is a **checkpoint**: it is written at the closing phase and re-read at the opening phase so an interrupted story resumes exactly where it stopped, never repeating completed tasks. + +**implement composes, it never re-does gate/PR logic.** The gate → PR → board sequence lives entirely in `/publish-pr`; this skill composes it (never re-implements PR creation). Task iteration and the checkpoint boundary are what `/implement` owns. **One PR per story:** the story lands on ONE branch with ONE PR; subsequent work on the story (further tasks/features) updates that same PR, never a new one unless a human explicitly requests it. @@ -17,6 +21,8 @@ Implement a user story by processing its tasks sequentially. Each task follows a | ------------------ | ---------- | --------------------------------------------------------------------------------------------------- | | `/verify-quality` | Capability | Yes — invoked at quality validation phase | | `/record-decision` | Capability | Yes — invoked when a decision needs recording | +| `/checkpoint` | Capability | Yes — `$mode=resume` at the opening phase (resume probe), `$mode=write` at the closing phase (handoff artifact). If not installed, degrade to git+PM-tool resume (see Graceful Degradation). | +| `/publish-pr` | Capability | Yes — the closing phase composes it (gate → PR → board) inside a handoff-only subagent. If not installed → **HALT** (implement never re-implements PR creation). | | `/assess-stack` | Capability | Optional — invoked when a new dependency is detected. If not installed, warn and continue. | | `/verify-adoption` | Capability | Optional — invoked before commit to check adoption compliance. If not installed, warn and continue. | @@ -24,6 +30,19 @@ Implement a user story by processing its tasks sequentially. Each task follows a #### No implementation without complete understanding. +### Step 0.0: Resume Probe (checkpoint) — NEVER SKIP + +The opening phase re-reads the checkpoint so an interrupted story resumes exactly where it stopped (AC2). This runs first, before loading the story, so completed tasks are never re-done. + +1. **Check**: Is `/checkpoint` installed AND does a checkpoint exist for this story (`.pair/working/checkpoints/.md`)? +2. **Skip**: If no checkpoint exists → this is a fresh start. Proceed to Step 0.1 (normal one-shot flow — no regression, AC4). +3. **Act**: Compose `/checkpoint $mode=resume` (pass `$story` when known). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. +4. **Act — edge cases** (resolve before continuing): + - **Checkpoint exists but its branch is missing** (checkpoint says branch X, repo has none): **HALT** and report the divergence. Do not guess a branch. + - **Stale checkpoint (story already Done)**: warn that the story is already Done and **require explicit developer confirmation** before reusing the checkpoint. Never silently resume a finished story. + - **Corrupted/incomplete checkpoint**: `/checkpoint` reports what parsed and what is missing — confirm the gaps with the developer before proceeding (never guess). +5. **Verify**: Either a fresh start is confirmed, or a valid checkpoint is resumed with the first pending task identified. If `/checkpoint` is not installed, fall back to the git+PM-tool resume (Idempotent Re-invocation) and continue. + ### Step 0.1: Load Story 1. **Check**: Is the user story already loaded in this session? @@ -223,11 +242,14 @@ Follow the TDD discipline rules strictly, and the [Design Rules](../../../.pair/ 7. **Act**: Update the PM tool story issue body: - Mark the completed task checkbox (`- [x] **T-N**`) in the **Task Breakdown** section. - Mark any **Definition of Done** checkboxes that are now factually satisfied by this task's work (e.g., "SKILL.md created", "template validated"). Leave unchecked items that require reviewer confirmation (e.g., "Code reviewed and merged"). -8. **Check**: Is this the last task? - - **Yes**: Move to Phase 3 (PR). +8. **Act — persist progress**: If `/checkpoint` is installed, compose `/checkpoint $mode=write` to update `.pair/working/checkpoints/.md` with the tasks now done. This keeps the checkpoint current so an interruption after this task resumes from the next pending one (Step 0.0). If `/checkpoint` is not installed, skip — git+PM state still supports the git-based resume. +9. **Check**: Is this the last task? + - **Yes**: Move to Phase 3 (Closing: checkpoint + PR). - **No**: Return to Step 2.1. -## Phase 3: Commit (if per-story), Push & PR +## Phase 3: Closing — Checkpoint + Publish PR + +The task cycle is done. The closing phase writes the checkpoint (handoff artifact) and composes `/publish-pr` inside a handoff-only subagent, so the PR is built on a guaranteed-clean context. implement never re-does the gate/PR/board logic here — it composes `/publish-pr` only. ### Step 3.1: Final Commit (if commit-per-story) @@ -261,68 +283,47 @@ Follow the TDD discipline rules strictly, and the [Design Rules](../../../.pair/ - Mark ALL task checkboxes (`- [x] **T-N**`) in the **Task Breakdown** section. - Mark all **Definition of Done** checkboxes that are factually satisfied by the implementation. Leave unchecked items that require reviewer confirmation (e.g., "Code reviewed and merged"). -### Step 3.2: Push Branch +### Step 3.2: Write the Checkpoint (handoff artifact) -1. **Check**: Is the branch already pushed and up to date with remote? -2. **Skip**: If up to date, move to Step 3.3. -3. **Act**: Push the branch: +The checkpoint is the boundary artifact (R4.2) and the **input contract for `/publish-pr`** — the handoff document the subagent runs on. - ```bash - git push -u origin feature/#- - ``` - -4. **Verify**: Branch pushed to remote. +1. **Act**: Compose `/checkpoint $mode=write` (pass `$story`). This creates/updates `.pair/working/checkpoints/.md` with the five sections: story, branch, tasks done, key decisions, remaining todos. +2. **Verify**: The checkpoint file exists and captures the completed story state (all tasks done, branch, decisions). This file — not this session's memory — is what the PR is built from. +3. **Act — if `/checkpoint` is not installed**: synthesize the handoff inline (branch, tasks done, decisions, ACs) and pass it directly to `/publish-pr` as `$handoff`; note the absence in the output. -### Step 3.3: Confirm PR with Developer +### Step 3.3: Publish the PR via a Handoff-Only Subagent (AC1) -1. **Act**: Present a summary before creating the PR: +The PR is produced on a **guaranteed-clean context**: a fresh subagent whose entire prompt is the handoff, nothing from this session. This is mechanical isolation (D23) — an **anonymous** subagent, **no named role**. A skill cannot `/clear` its own context (D7), so the reset is achieved by delegating to a subagent. - ```text - PR READY: - ├── Branch: [feature/#story-id-description] - ├── Tasks: [N/N completed] - ├── Commits: [N commits on branch] - ├── Quality: [All gates passing] - └── Title: [#] : - ``` +1. **Check**: Is subagent spawning available in this tool/environment? +2. **Act — primary path (subagent)**: Spawn an **anonymous subagent** whose prompt is the **handoff document only** — the checkpoint contents (or the path `.pair/working/checkpoints/.md`) plus a single instruction: run `/publish-pr $story= $handoff=.pair/working/checkpoints/.md`. Pass **no other session context** — the subagent's context is the handoff and nothing else (clean context / fresh context reset within one execution, R4.1). The subagent runs `/publish-pr` (gate → PR → tags → ready-for-review → board) and returns the PR number/URL and board result. +3. **Act — degraded inline path (AC3)**: If subagent spawning is **unavailable** (tool/environment cannot spawn one — subagent spawning unavailable), do NOT skip the split: the checkpoint is already written (Step 3.2), then compose `/publish-pr` **inline** in the current session (`$story`, `$handoff` = the checkpoint). **Note the degradation in the output** (`Context: degraded — inline publish, no subagent reset`). Behavior is otherwise equivalent to the primary path. +4. **Act — edge case (subagent fails mid-PR)**: The checkpoint remains valid. Re-invoking `/implement` re-runs this closing phase; `/publish-pr` is **idempotent** — it detects an existing PR and updates it in place rather than opening a second one. Never open a second PR for the story. +5. **Verify**: A single ready-for-review PR exists (created or updated), and its number/URL is captured for the output. A red quality gate inside `/publish-pr` propagates here as a **HALT** (no PR side effects) — implement does not create the PR itself. -2. **Ask**: _"Ready to create the PR?"_ -3. **Verify**: Developer confirms. If not → wait for developer instructions. - -### Step 3.4: Create or Update PR - -1. **Check**: Does a PR already exist for this branch? -2. **Skip**: If PR exists, update its description and move to output. -3. **Act**: Read the [PR template](../../../.pair/knowledge/guidelines/collaboration/templates/pr-template.md) and fill ALL its sections: - - **Title**: `[#] : ` - - **Body**: Use the PR template structure exactly. Fill each section: - - **Summary** (What Changed + Why): from story statement and implementation - - **Story Context**: link to user story issue, list AC coverage - - **Changes Made**: list all completed tasks, files added/modified/deleted - - **Testing**: test coverage, quality gate results (from /verify-quality output) - - Omit template sections that do not apply (e.g., Database Changes, API Changes for KB-only PRs) — do not leave unfilled placeholders. - - **Link**: Reference the user story issue (`Closes #`) - - **Labels**: Apply appropriate labels -4. **Act**: Mark the PR as **ready for review** — ensure it is not in draft state. If the PM tool supports review request (e.g., GitHub `gh pr ready`), mark it explicitly. -5. **Verify**: PR created, description follows template, PR is ready for review. +Note: the checkpoint is **not** removed here — it must survive the review/fix loop so a re-review or fix round can resume from it. Cleanup happens at merge (Phase 4). ## Phase 4: Post-Review Merge After code review approval (typically via `/review`), re-invoke `/implement` to merge and close — see [post-review-merge.md](post-review-merge.md) for the verify-approval, merge-commit, merge, and parent-cascade steps (Steps 4.1–4.4) plus the completion output. +On story completion (Done, at merge), the checkpoint is no longer needed — remove `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). + ## Output Format -At PR creation (Phase 3): +At the closing phase (Phase 3): ```text IMPLEMENTATION COMPLETE: -├── Story: [#ID: Title] -├── Branch: [feature/#ID-description] -├── Strategy: [commit-per-task | commit-per-story] -├── Tasks: [N/N completed] -├── Commits: [N commits on branch] -├── PR: [#PR-number — URL] -└── Quality: [All gates passing] +├── Story: [#ID: Title] +├── Branch: [feature/#ID-description] +├── Strategy: [commit-per-task | commit-per-story] +├── Tasks: [N/N completed] +├── Commits: [N commits on branch] +├── Checkpoint: [.pair/working/checkpoints/.md — written] +├── Context: [clean — subagent handoff-only | degraded — inline publish, no subagent reset] +├── PR: [#PR-number — URL — Created | Updated (from /publish-pr)] +└── Quality: [All gates passing] ``` At merge (Phase 4): see [post-review-merge.md](post-review-merge.md). @@ -331,12 +332,14 @@ At merge (Phase 4): see [post-review-merge.md](post-review-merge.md). Implementation stops immediately when: +- **Checkpoint/branch divergence** (Step 0.0) — checkpoint names a branch the repo does not have; report and stop, do not guess a branch - **Story not loaded or incomplete** (Phase 0) - **Task specifications incomplete** (Step 2.2) - **Quality gate failure** (Step 2.7) — developer must fix - **New dependency rejected by /assess-stack** (Step 2.4) -- **PR template not found** (Step 3.4) — cannot create PR without template - **Commit template not found** (Step 2.8 / Step 3.1) — cannot commit without template +- **`/publish-pr` not installed** (Step 3.3) — implement composes the PR sequence, never re-implements it +- **Quality gate red inside `/publish-pr`** (Step 3.3) — propagates as implement's HALT; no PR side effects (the PR-template-not-found and gate HALTs live in `/publish-pr`) - **PR not approved** (Step 4.1) — cannot merge without review approval On HALT: report the blocker clearly, propose resolution, wait for developer. @@ -345,12 +348,13 @@ On HALT: report the blocker clearly, propose resolution, wait for developer. See [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md). Re-invoking `/implement` on a partially completed story is safe and expected — per-step: -1. **Branch**: detects existing branch, switches to it. -2. **Commit strategy**: if commits already exist on branch, infer strategy from history. -3. **Tasks**: scans task checklist and git log to identify completed tasks. Skips them. -4. **PR**: detects existing PR, updates instead of creating duplicate. -5. **Quality gates**: re-runs all gates (fast if already passing). -6. **Merge**: if PR exists and is approved, proceeds directly to Phase 4 (merge). +1. **Checkpoint**: the opening-phase resume probe (Step 0.0) reads the checkpoint and jumps to the first pending task — never repeating completed tasks. When `/checkpoint` is absent, the git+PM resume below applies. +2. **Branch**: detects existing branch, switches to it. +3. **Commit strategy**: if commits already exist on branch, infer strategy from history. +4. **Tasks**: scans task checklist and git log to identify completed tasks. Skips them. +5. **PR**: the closing phase re-composes `/publish-pr`, which detects an existing PR and updates it in place — never a duplicate. A subagent that failed mid-PR is recovered this way (the checkpoint stays valid, the rerun is idempotent). +6. **Quality gates**: re-runs all gates (fast if already passing). +7. **Merge**: if PR exists and is approved, proceeds directly to Phase 4 (merge). The skill resumes from the first incomplete step — never re-does completed work. @@ -358,14 +362,18 @@ The skill resumes from the first incomplete step — never re-does completed wor See [graceful degradation](../../../.pair/knowledge/skill-conventions/graceful-degradation.md) (PM tool not accessible → ask the developer directly; adoption file missing → proceed with guideline defaults) for the standard scenarios. Additional cases: +- **Subagent spawning unavailable**: take the degraded inline path (Step 3.3) — checkpoint still written, `/publish-pr` composed inline, degradation noted in the output. Never skip the checkpoint/PR split. +- **`/checkpoint` not installed**: skip the resume probe and the write step; resume from git+PM state (Idempotent Re-invocation) and synthesize the handoff inline for `/publish-pr`. +- **`/publish-pr` not installed**: **HALT** — implement composes the gate/PR/board sequence, it never re-implements it. Report the missing dependency. - **`/assess-stack` not installed**: Warn on new dependency, continue without validation. - **`/verify-adoption` not installed**: Warn, skip adoption compliance check. - **No quality gate command**: Fall back to individual checks (lint, test, type check). ## Notes -- This skill **modifies files and creates git artifacts** (branches, commits, PRs). +- This skill **modifies files and creates git artifacts** (branches, commits) and **writes the checkpoint**. The PR itself is created/updated by the composed `/publish-pr` (in the subagent, or inline when degraded) — implement never re-implements PR creation. +- The **subagent's prompt is the handoff only** — the checkpoint, nothing from this session. Anonymous, no named role (mechanical isolation, D23); a skill cannot `/clear` its own context (D7), so the subagent provides the clean-context reset. - Task iteration is sequential — each task completes its full cycle before the next begins. -- The developer can stop between tasks; re-invoke to resume (see [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md)). +- The developer can stop between tasks; re-invoke to resume — the opening-phase resume probe (Step 0.0) reads the checkpoint (see [idempotency convention](../../../.pair/knowledge/skill-conventions/idempotency.md)). - Single PR per story regardless of commit strategy. - **Squash happens at merge** (Phase 4), not before PR creation. Individual commits are preserved on the branch during review. diff --git a/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts new file mode 100644 index 00000000..5031184e --- /dev/null +++ b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts @@ -0,0 +1,126 @@ +import { describe, it, expect } from 'vitest' +import { readFileSync } from 'fs' +import { join } from 'path' + +// Conformance guard for story #256: /implement's closing phase composes +// /checkpoint (write) + /publish-pr (via a handoff-only subagent), and its +// opening phase resumes from the checkpoint without repeating completed tasks. +// The 5-step task cycle is unchanged (AC4 — no regression). The subagent +// boundary is mechanical isolation (D23): anonymous, no named role, its prompt +// is the handoff only. Degradation: subagent spawning unavailable ⇒ checkpoint +// still written, /publish-pr invoked inline, degradation noted (AC3). +// See issue #256 and epic #206. + +const DATASET = join(__dirname, '../../dataset/.skills/process/implement/SKILL.md') +const MIRROR = join(__dirname, '../../../../.claude/skills/pair-process-implement/SKILL.md') + +const dataset = (): string => readFileSync(DATASET, 'utf-8') +const mirror = (): string => readFileSync(MIRROR, 'utf-8') + +describe('implement composes checkpoint + publish-pr (#256)', () => { + it('lists /checkpoint and /publish-pr as composed skills (dataset short refs)', () => { + const c = dataset() + expect(c).toMatch(/\/checkpoint\b/) + expect(c).toMatch(/\/publish-pr\b/) + }) + + it('lists the prefixed composed skills in the installed mirror', () => { + const c = mirror() + expect(c).toMatch(/\/pair-capability-checkpoint\b/) + expect(c).toMatch(/\/pair-capability-publish-pr\b/) + }) +}) + +describe('closing phase: checkpoint(write) then publish-pr (AC1)', () => { + const c = dataset() + + it('writes the checkpoint as the boundary/handoff artifact before publishing', () => { + // checkpoint is written in write mode at the closing phase. + expect(c).toMatch(/\$mode\s*=?:?\s*write/i) + expect(c.toLowerCase()).toContain('checkpoint') + // the write happens before the publish-pr composition (ordering). + const writeIdx = c.toLowerCase().indexOf('checkpoint') + const publishIdx = c.indexOf('/publish-pr') + expect(writeIdx).toBeGreaterThanOrEqual(0) + expect(publishIdx).toBeGreaterThan(writeIdx) + }) + + it('spawns an anonymous subagent whose prompt is the handoff only (D23)', () => { + const low = c.toLowerCase() + expect(low).toContain('subagent') + expect(low).toContain('handoff') + expect(low).toContain('anonymous') + // mechanical isolation, no named role. + expect(c).toContain('D23') + // clean/fresh context reset within one execution. + expect(low).toMatch(/clean context|fresh context/) + }) + + it('delegates gate + PR to /publish-pr instead of re-doing PR logic', () => { + // implement never re-does gate/PR logic — composes /publish-pr only. + expect(c.toLowerCase()).toMatch(/never re-?do|composes .*publish-pr only/) + // the old raw "create or update PR" template-fill step is gone. + expect(c).not.toMatch(/#+\s*Step\s*3\.4:\s*Create or Update PR/i) + }) +}) + +describe('opening phase: resume from checkpoint (AC2)', () => { + const c = dataset() + + it('probes the checkpoint in resume mode at Phase 0', () => { + expect(c).toMatch(/\$mode\s*=?:?\s*resume/i) + }) + + it('resumes from the first pending task without repeating completed work', () => { + const low = c.toLowerCase() + expect(low).toMatch(/first pending task|first incomplete/) + expect(low).toMatch(/without repeating|never re-?does completed|skip.*completed/) + }) +}) + +describe('degraded inline path (AC3)', () => { + const c = dataset() + + it('falls back to inline /publish-pr when subagent spawning is unavailable', () => { + const low = c.toLowerCase() + expect(low).toContain('inline') + expect(low).toMatch(/subagent spawn|spawning.*unavailable|cannot spawn|no subagent/) + }) + + it('notes the degradation in the output', () => { + expect(c.toLowerCase()).toMatch(/degrad/) + }) +}) + +describe('edge cases (#256)', () => { + const c = dataset() + + it('HALTs on checkpoint/branch divergence (branch missing)', () => { + const low = c.toLowerCase() + expect(low).toMatch(/branch.*missing|missing.*branch|diverg/) + expect(c).toContain('HALT') + }) + + it('warns and requires confirmation on a stale checkpoint (story Done)', () => { + const low = c.toLowerCase() + expect(low).toMatch(/stale checkpoint|already done|story.*done/) + expect(low).toMatch(/confirm/) + }) + + it('treats a subagent failure mid-PR as idempotent rerun (publish-pr updates)', () => { + const low = c.toLowerCase() + expect(low).toMatch(/idempotent/) + expect(low).toMatch(/subagent fail|fails mid|rerun|re-run|re-invoke/) + }) +}) + +describe('no regression on the 5-step task cycle (AC4)', () => { + const c = dataset() + + it('keeps the 5-step per-task cycle intact', () => { + // Phase 2 task cycle anchors remain. + expect(c).toMatch(/Step 2\.1: Select Next Task/) + expect(c).toMatch(/Step 2\.7: Verify Quality/) + expect(c).toMatch(/Step 2\.8: Task Completion/) + }) +}) From 1001bf2cba088261ed799194be45965baa073553 Mon Sep 17 00:00:00 2001 From: Gianluca Carucci Date: Sun, 19 Jul 2026 22:35:37 +0200 Subject: [PATCH 2/3] =?UTF-8?q?[#256]=20fix:=20review=20remediation=20?= =?UTF-8?q?=E2=80=94=20docs-site=20flow,=20checkpoint=20cleanup=20step,=20?= =?UTF-8?q?mirror=20byte-equality=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - skills-catalog.mdx: implement composes checkpoint+publish-pr; publish-pr now wired (not "future/not yet") - execution.mdx: PR Creation → Closing Phase (checkpoint write → fresh subagent resume → publish-pr) + loop diagram - post-review-merge.md: add Step 4.5 checkpoint cleanup (owns merge steps); SKILL.md Phase 4 refs it (mirror synced) - implement SKILL.md: add ## Arguments defining $story (resume-probe source); mirror synced - conformance test: full mirror byte-equality via applyKnownMirrorTransforms+syncFrontmatter (neutralizing the copy pipeline's same-dir ./-prepend, link-rewriter.ts); anchor ordering to Step 3.2/3.3 headings Refs: #256 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../skills/pair-process-implement/SKILL.md | 14 +++-- .../post-review-merge.md | 9 +++ .../docs/developer-journey/execution.mdx | 17 +++--- .../content/docs/reference/skills-catalog.mdx | 4 +- .../.skills/process/implement/SKILL.md | 12 +++- .../process/implement/post-review-merge.md | 9 +++ .../implement-compose-close.test.ts | 58 +++++++++++++++++-- 7 files changed, 102 insertions(+), 21 deletions(-) diff --git a/.claude/skills/pair-process-implement/SKILL.md b/.claude/skills/pair-process-implement/SKILL.md index 71c732ab..d1d253b8 100644 --- a/.claude/skills/pair-process-implement/SKILL.md +++ b/.claude/skills/pair-process-implement/SKILL.md @@ -26,6 +26,12 @@ Implement a user story by processing its tasks sequentially. Each task follows a | `/pair-capability-assess-stack` | Capability | Optional — invoked when a new dependency is detected. If not installed, warn and continue. | | `/pair-capability-verify-adoption` | Capability | Optional — invoked before commit to check adoption compliance. If not installed, warn and continue. | +## Arguments + +| Argument | Required | Description | +| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `$story` | No | Story ID to implement, supplied by the invocation (e.g. `/pair-process-implement #256`). If omitted, detected from session context or the current branch (`feature/#-*`). This is the id the resume probe (Step 0.0) uses and the closing phase forwards to `/pair-capability-checkpoint` and `/pair-capability-publish-pr`. If it cannot be resolved when a checkpoint operation needs it → **HALT**. | + ## Phase 0: Story & Task Analysis (BLOCKING) #### No implementation without complete understanding. @@ -36,7 +42,7 @@ The opening phase re-reads the checkpoint so an interrupted story resumes exactl 1. **Check**: Is `/pair-capability-checkpoint` installed AND does a checkpoint exist for this story (`.pair/working/checkpoints/.md`)? 2. **Skip**: If no checkpoint exists → this is a fresh start. Proceed to Step 0.1 (normal one-shot flow — no regression, AC4). -3. **Act**: Compose `/pair-capability-checkpoint $mode=resume` (pass `$story` when known). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. +3. **Act**: Compose `/pair-capability-checkpoint $mode=resume` (pass `$story` — the story id from the invocation, see [Arguments](#arguments); if absent it is detected from the branch). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. 4. **Act — edge cases** (resolve before continuing): - **Checkpoint exists but its branch is missing** (checkpoint says branch X, repo has none): **HALT** and report the divergence. Do not guess a branch. - **Stale checkpoint (story already Done)**: warn that the story is already Done and **require explicit developer confirmation** before reusing the checkpoint. Never silently resume a finished story. @@ -305,9 +311,9 @@ Note: the checkpoint is **not** removed here — it must survive the review/fix ## Phase 4: Post-Review Merge -After code review approval (typically via `/pair-process-review`), re-invoke `/pair-process-implement` to merge and close — see [post-review-merge.md](post-review-merge.md) for the verify-approval, merge-commit, merge, and parent-cascade steps (Steps 4.1–4.4) plus the completion output. +After code review approval (typically via `/pair-process-review`), re-invoke `/pair-process-implement` to merge and close — see [post-review-merge.md](./post-review-merge.md) for the verify-approval, merge-commit, merge, parent-cascade, and checkpoint-cleanup steps (Steps 4.1–4.5) plus the completion output. -On story completion (Done, at merge), the checkpoint is no longer needed — remove `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). +On story completion (Done, at merge), the checkpoint is no longer needed — `post-review-merge.md` Step 4.5 removes `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). ## Output Format @@ -326,7 +332,7 @@ IMPLEMENTATION COMPLETE: └── Quality: [All gates passing] ``` -At merge (Phase 4): see [post-review-merge.md](post-review-merge.md). +At merge (Phase 4): see [post-review-merge.md](./post-review-merge.md). ## HALT Conditions diff --git a/.claude/skills/pair-process-implement/post-review-merge.md b/.claude/skills/pair-process-implement/post-review-merge.md index d914d403..ebaaa07e 100644 --- a/.claude/skills/pair-process-implement/post-review-merge.md +++ b/.claude/skills/pair-process-implement/post-review-merge.md @@ -43,6 +43,15 @@ Disclosed from [SKILL.md](./SKILL.md) Phase 4 — only reached when `/pair-proce 3. **Act**: Check parent initiative — if ALL epics in the initiative are Done, update initiative status to "Done". 4. **Verify**: Story and parent hierarchy updated recursively. +### Step 4.5: Clean Up the Checkpoint + +The checkpoint's lifecycle ends at merge — it exists only to survive context resets and the review/fix loop, both of which are over once the story is Done. + +1. **Check**: Does `.pair/working/checkpoints/.md` exist? +2. **Skip**: If no checkpoint file exists (e.g. `/pair-capability-checkpoint` was not installed), nothing to clean up. +3. **Act**: Remove `.pair/working/checkpoints/.md` so finished-story state never lingers. +4. **Verify**: The checkpoint file is gone (checkpoint lifecycle: written at the closing phase — Step 3.2 — cleaned up here at merge). + ## Output Format (merge) ```text diff --git a/apps/website/content/docs/developer-journey/execution.mdx b/apps/website/content/docs/developer-journey/execution.mdx index 93dcbacb..6150413e 100644 --- a/apps/website/content/docs/developer-journey/execution.mdx +++ b/apps/website/content/docs/developer-journey/execution.mdx @@ -51,13 +51,14 @@ Every new module file must have a corresponding unit test file (1:1 mapping). Mo With commit-per-task, the developer gets a checkpoint between every task — the AI presents a summary and waits for confirmation before committing. -### PR Creation +### Closing Phase: Checkpoint + PR -After all tasks are complete, the skill: -1. Pushes the feature branch -2. Creates a PR following the team's [PR template](/docs/reference/guidelines-catalog) -3. Links the PR to the story issue -4. Marks the PR as ready for review +After all tasks are complete, the skill's closing phase splits the handoff from the publish so the PR is always built on a clean context: + +1. **Writes a checkpoint** (`/pair-capability-checkpoint` in write mode) — the boundary artifact capturing story, branch, tasks done, decisions, and remaining todos. This is the handoff document the PR is built from, not this session's memory. +2. **Publishes the PR via a handoff-only subagent** — spawns a fresh, anonymous subagent whose entire prompt is the checkpoint, which resumes from it and runs `/pair-capability-publish-pr`. That skill runs the quality gate, pushes the branch, creates or updates one PR from the [PR template](/docs/reference/guidelines-catalog), links it to the story, copies the classification tags, and marks it ready for review. + +If subagent spawning is unavailable, the skill degrades to running `/pair-capability-publish-pr` inline in the same session (checkpoint still written) and notes the degradation. Re-invoking `/pair-process-implement` on an interrupted story reads the checkpoint and resumes from the first pending task — completed tasks are never repeated, and `publish-pr` updates the existing PR rather than opening a second one. ## Step 9: Code Review @@ -106,7 +107,9 @@ After merge, the skill updates the status hierarchy: │ ├── Task 1: RED → GREEN → REFACTOR → commit ├── Task 2: RED → GREEN → REFACTOR → commit - └── Task N: ... → commit → PR created + └── Task N: ... → commit + │ + └── Closing: checkpoint (write) → fresh subagent resumes → publish-pr → PR ready │ /pair-process-review #pr-number │ diff --git a/apps/website/content/docs/reference/skills-catalog.mdx b/apps/website/content/docs/reference/skills-catalog.mdx index 7829cd0f..ed35472e 100644 --- a/apps/website/content/docs/reference/skills-catalog.mdx +++ b/apps/website/content/docs/reference/skills-catalog.mdx @@ -26,7 +26,7 @@ Process skills orchestrate multi-step workflows by composing capability skills. | **plan-stories** | `/pair-process-plan-stories` | Slices an epic into user stories via vertical slicing and INVEST validation, each sized for one sprint. | `/pair-capability-write-issue` | | **refine-story** | `/pair-process-refine-story` | Refines a user story from Draft to Ready — the single Draft→Ready path (D24): phase 0 grill(sync), Given-When-Then acceptance criteria, map-subdomains/map-contexts scoped analysis, classify matrix, sprint readiness. Not for sizing an already-refined story (use estimate). | `/pair-capability-grill`, `/pair-capability-write-issue`; `/pair-capability-map-subdomains`, `/pair-capability-map-contexts`, `/pair-capability-classify` (optional) | | **plan-tasks** | `/pair-process-plan-tasks` | Breaks a refined user story into implementation tasks — checklist, dependency graph, AC-coverage table — added to the story body; no separate task issues. | `/pair-capability-write-issue` | -| **implement** | `/pair-process-implement` | Implements a refined user story task-by-task via a 5-step cycle per task (context, branch, implementation, quality, commit); opens one PR when the story completes. | `/pair-capability-verify-quality`, `/pair-capability-record-decision` | +| **implement** | `/pair-process-implement` | Implements a refined user story task-by-task via a 5-step cycle per task (context, branch, implementation, quality, commit); at the closing phase it writes a checkpoint and publishes one PR through a handoff-only subagent, resuming from the checkpoint when re-invoked on an interrupted story. | `/pair-capability-verify-quality`, `/pair-capability-record-decision`, `/pair-capability-checkpoint`, `/pair-capability-publish-pr` | | **review** | `/pair-process-review` | Reviews a pull request through 6 sequential phases (5 review + optional merge with parent cascade) to decide whether it merges. Not a quick build/test sanity check (use verify-quality). | `/pair-capability-classify`, `/pair-capability-verify-quality`, `/pair-capability-verify-done`, `/pair-capability-record-decision`, `/pair-capability-analyze-debt`, `/pair-capability-assess-security` (required); `/pair-capability-verify-adoption`, `/pair-capability-assess-stack`, `/pair-capability-execute-manual-tests` (optional) | ## Capability Skills @@ -118,7 +118,7 @@ All `analyze-*` skills are **output-only report producers**: they analyze and re | Skill | Command | Description | | ----- | ------- | ----------- | | **checkpoint** | `/pair-capability-checkpoint` | Writes and resumes a self-contained progress checkpoint (story, branch, tasks done, decisions, remaining todos) in `.pair/working/checkpoints/`, so work survives a context reset. Invoke directly to save or resume progress. | -| **publish-pr** | `/pair-capability-publish-pr` | Publishes a completed story branch as a pull request: runs the quality gate (HALTs on red), creates or updates ONE PR from the pr-template with conditional sections (Services to Release, Screenshots) filled only when pertinent, copies the story's classification tags, marks it ready-for-review, and updates the board state. Standalone — driven by a handoff/checkpoint; reads the WoW `git-workflow` (base-branch, squash) and `code-host`. Composed by a future closing phase of `/pair-process-implement` (not yet wired); reused by hotfix and automation loops. Never merges. | +| **publish-pr** | `/pair-capability-publish-pr` | Publishes a completed story branch as a pull request: runs the quality gate (HALTs on red), creates or updates ONE PR from the pr-template with conditional sections (Services to Release, Screenshots) filled only when pertinent, copies the story's classification tags, marks it ready-for-review, and updates the board state. Standalone — driven by a handoff/checkpoint; reads the WoW `git-workflow` (base-branch, squash) and `code-host`. Composed by the closing phase of `/pair-process-implement` (invoked in a handoff-only subagent so the PR is built on a clean context); reused by hotfix and automation loops. Never merges. | ## Skill Properties diff --git a/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md b/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md index eb31d4ed..6b1cbe3c 100644 --- a/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md +++ b/packages/knowledge-hub/dataset/.skills/process/implement/SKILL.md @@ -26,6 +26,12 @@ Implement a user story by processing its tasks sequentially. Each task follows a | `/assess-stack` | Capability | Optional — invoked when a new dependency is detected. If not installed, warn and continue. | | `/verify-adoption` | Capability | Optional — invoked before commit to check adoption compliance. If not installed, warn and continue. | +## Arguments + +| Argument | Required | Description | +| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `$story` | No | Story ID to implement, supplied by the invocation (e.g. `/implement #256`). If omitted, detected from session context or the current branch (`feature/#-*`). This is the id the resume probe (Step 0.0) uses and the closing phase forwards to `/checkpoint` and `/publish-pr`. If it cannot be resolved when a checkpoint operation needs it → **HALT**. | + ## Phase 0: Story & Task Analysis (BLOCKING) #### No implementation without complete understanding. @@ -36,7 +42,7 @@ The opening phase re-reads the checkpoint so an interrupted story resumes exactl 1. **Check**: Is `/checkpoint` installed AND does a checkpoint exist for this story (`.pair/working/checkpoints/.md`)? 2. **Skip**: If no checkpoint exists → this is a fresh start. Proceed to Step 0.1 (normal one-shot flow — no regression, AC4). -3. **Act**: Compose `/checkpoint $mode=resume` (pass `$story` when known). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. +3. **Act**: Compose `/checkpoint $mode=resume` (pass `$story` — the story id from the invocation, see [Arguments](#arguments); if absent it is detected from the branch). Use the parsed state — branch, tasks done, key decisions, remaining todos — to skip re-analysis and jump straight to the **first pending task** in Phase 2, **without repeating** completed tasks. 4. **Act — edge cases** (resolve before continuing): - **Checkpoint exists but its branch is missing** (checkpoint says branch X, repo has none): **HALT** and report the divergence. Do not guess a branch. - **Stale checkpoint (story already Done)**: warn that the story is already Done and **require explicit developer confirmation** before reusing the checkpoint. Never silently resume a finished story. @@ -305,9 +311,9 @@ Note: the checkpoint is **not** removed here — it must survive the review/fix ## Phase 4: Post-Review Merge -After code review approval (typically via `/review`), re-invoke `/implement` to merge and close — see [post-review-merge.md](post-review-merge.md) for the verify-approval, merge-commit, merge, and parent-cascade steps (Steps 4.1–4.4) plus the completion output. +After code review approval (typically via `/review`), re-invoke `/implement` to merge and close — see [post-review-merge.md](post-review-merge.md) for the verify-approval, merge-commit, merge, parent-cascade, and checkpoint-cleanup steps (Steps 4.1–4.5) plus the completion output. -On story completion (Done, at merge), the checkpoint is no longer needed — remove `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). +On story completion (Done, at merge), the checkpoint is no longer needed — `post-review-merge.md` Step 4.5 removes `.pair/working/checkpoints/.md` so finished-story state never lingers (checkpoint lifecycle: written at the closing phase, cleaned up at merge). ## Output Format diff --git a/packages/knowledge-hub/dataset/.skills/process/implement/post-review-merge.md b/packages/knowledge-hub/dataset/.skills/process/implement/post-review-merge.md index 7f9b54a0..92b7e987 100644 --- a/packages/knowledge-hub/dataset/.skills/process/implement/post-review-merge.md +++ b/packages/knowledge-hub/dataset/.skills/process/implement/post-review-merge.md @@ -43,6 +43,15 @@ Disclosed from [SKILL.md](SKILL.md) Phase 4 — only reached when `/implement` i 3. **Act**: Check parent initiative — if ALL epics in the initiative are Done, update initiative status to "Done". 4. **Verify**: Story and parent hierarchy updated recursively. +### Step 4.5: Clean Up the Checkpoint + +The checkpoint's lifecycle ends at merge — it exists only to survive context resets and the review/fix loop, both of which are over once the story is Done. + +1. **Check**: Does `.pair/working/checkpoints/.md` exist? +2. **Skip**: If no checkpoint file exists (e.g. `/checkpoint` was not installed), nothing to clean up. +3. **Act**: Remove `.pair/working/checkpoints/.md` so finished-story state never lingers. +4. **Verify**: The checkpoint file is gone (checkpoint lifecycle: written at the closing phase — Step 3.2 — cleaned up here at merge). + ## Output Format (merge) ```text diff --git a/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts index 5031184e..5aa2d0fc 100644 --- a/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts +++ b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts @@ -1,6 +1,12 @@ import { describe, it, expect } from 'vitest' import { readFileSync } from 'fs' import { join } from 'path' +import { syncFrontmatter } from '@pair/content-ops' +import { + buildDatasetSkillNameMap, + buildSkillLinkPathMap, + applyKnownMirrorTransforms, +} from '../tools/skills-guide-mirror' // Conformance guard for story #256: /implement's closing phase composes // /checkpoint (write) + /publish-pr (via a handoff-only subagent), and its @@ -13,6 +19,7 @@ import { join } from 'path' const DATASET = join(__dirname, '../../dataset/.skills/process/implement/SKILL.md') const MIRROR = join(__dirname, '../../../../.claude/skills/pair-process-implement/SKILL.md') +const SKILLS_DIR = join(__dirname, '../../dataset/.skills') const dataset = (): string => readFileSync(DATASET, 'utf-8') const mirror = (): string => readFileSync(MIRROR, 'utf-8') @@ -29,6 +36,37 @@ describe('implement composes checkpoint + publish-pr (#256)', () => { expect(c).toMatch(/\/pair-capability-checkpoint\b/) expect(c).toMatch(/\/pair-capability-publish-pr\b/) }) + + it('installed mirror is byte-for-byte reproducible from the dataset via the real transform', () => { + // Whole-file mirror consistency (the same guarantee skills-guide-mirror.test.ts + // asserts for skills-guide.md): the installed SKILL.md must equal the dataset + // SKILL.md run through the `pair update` copy pipeline — + // 1. syncFrontmatter: the `name:` rename `implement` -> `pair-process-implement` + // the flatten+prefix directory rename triggers (a SKILL.md carries a renamed + // frontmatter `name`, unlike the frontmatter-free skills-guide.md), then + // 2. applyKnownMirrorTransforms: content-ops `rewriteSkillReferences` + + // `rewriteSkillLinkPaths` (the `/command` token + SKILL.md link-path rewrites). + // + // One further copy-pipeline transform is NOT modeled by applyKnownMirrorTransforms: + // the flatten/prefix link-rewriter prepends `./` to a bare same-dir relative link + // when the file moves (link-rewriter.ts computeNewHref: `if (!startsWith('.')) './'+p`). + // For this skill that affects only the same-dir sibling `post-review-merge.md` links + // (`](post-review-merge.md)` in the bare-authored dataset -> `](./post-review-merge.md)` + // in the mirror). skills-guide.md has no same-dir sibling links, so that helper alone + // suffices there but not here. We neutralize exactly that systematic `./`-prepend on + // both sides — every OTHER byte must still match, so any real drift (hand-edited mirror, + // a dataset edit not propagated via `pair update`) still fails. `pair update` remains + // the ground truth for regeneration. + const skillNameMap = buildDatasetSkillNameMap(SKILLS_DIR) + const linkPathMap = buildSkillLinkPathMap(SKILLS_DIR) + const reconstructed = applyKnownMirrorTransforms( + syncFrontmatter(dataset(), { from: 'implement', to: 'pair-process-implement' }), + skillNameMap, + linkPathMap, + ) + const neutralizeSameDirDotSlash = (s: string): string => s.split('](./').join('](') + expect(neutralizeSameDirDotSlash(mirror())).toBe(neutralizeSameDirDotSlash(reconstructed)) + }) }) describe('closing phase: checkpoint(write) then publish-pr (AC1)', () => { @@ -38,11 +76,21 @@ describe('closing phase: checkpoint(write) then publish-pr (AC1)', () => { // checkpoint is written in write mode at the closing phase. expect(c).toMatch(/\$mode\s*=?:?\s*write/i) expect(c.toLowerCase()).toContain('checkpoint') - // the write happens before the publish-pr composition (ordering). - const writeIdx = c.toLowerCase().indexOf('checkpoint') - const publishIdx = c.indexOf('/publish-pr') - expect(writeIdx).toBeGreaterThanOrEqual(0) - expect(publishIdx).toBeGreaterThan(writeIdx) + // Ordering within Phase 3: the checkpoint-write step (Step 3.2) precedes the + // publish-via-subagent step (Step 3.3). Anchoring on the step HEADINGS is + // load-bearing: bare indexOf('checkpoint') / indexOf('/publish-pr') both fall + // inside the frontmatter description, so that comparison is trivially true and + // would not actually guard the closing-phase ordering. + const step32Idx = c.search(/#+\s*Step\s*3\.2:\s*Write the Checkpoint/i) + const step33Idx = c.search(/#+\s*Step\s*3\.3:\s*Publish the PR/i) + expect(step32Idx).toBeGreaterThanOrEqual(0) + expect(step33Idx).toBeGreaterThan(step32Idx) + // and within those steps: checkpoint write ($mode=write) comes before the + // subagent spawn that runs /publish-pr. + const writeInvocationIdx = c.search(/\$mode\s*=?:?\s*write/i) + const subagentSpawnIdx = c.toLowerCase().indexOf('spawn an') + expect(writeInvocationIdx).toBeGreaterThanOrEqual(0) + expect(subagentSpawnIdx).toBeGreaterThan(writeInvocationIdx) }) it('spawns an anonymous subagent whose prompt is the handoff only (D23)', () => { From f943b7216b844553f0f227f8863e52d69f9349b6 Mon Sep 17 00:00:00 2001 From: Gianluca Carucci Date: Sun, 19 Jul 2026 22:50:57 +0200 Subject: [PATCH 3/3] =?UTF-8?q?[#256]=20fix:=20re-review=20remediation=20?= =?UTF-8?q?=E2=80=94=20ASCII=20tree=20connector=20+=20tighter=20conformanc?= =?UTF-8?q?e=20guards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - execution.mdx: Task N uses ├── (sibling), Closing keeps └── (last child) - test: anchor $mode=write search to the Step 3.2 span (not first global occ) - test: restrict same-dir ./-neutralization to sibling links (no nested path) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../docs/developer-journey/execution.mdx | 2 +- .../implement-compose-close.test.ts | 20 +++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/website/content/docs/developer-journey/execution.mdx b/apps/website/content/docs/developer-journey/execution.mdx index 6150413e..dbd22435 100644 --- a/apps/website/content/docs/developer-journey/execution.mdx +++ b/apps/website/content/docs/developer-journey/execution.mdx @@ -107,7 +107,7 @@ After merge, the skill updates the status hierarchy: │ ├── Task 1: RED → GREEN → REFACTOR → commit ├── Task 2: RED → GREEN → REFACTOR → commit - └── Task N: ... → commit + ├── Task N: ... → commit │ └── Closing: checkpoint (write) → fresh subagent resumes → publish-pr → PR ready │ diff --git a/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts index 5aa2d0fc..b0fbc681 100644 --- a/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts +++ b/packages/knowledge-hub/src/conformance/implement-compose-close.test.ts @@ -57,6 +57,11 @@ describe('implement composes checkpoint + publish-pr (#256)', () => { // both sides — every OTHER byte must still match, so any real drift (hand-edited mirror, // a dataset edit not propagated via `pair update`) still fails. `pair update` remains // the ground truth for regeneration. + // + // Restrict the neutralization to SAME-DIR SIBLING links only (`](./name.md)` with no + // further `/`) — that is the exact and only shape the flatten link-rewriter produces + // here. A blanket `](./` strip would also mask a nested `](./sub/file.md)` drift, so we + // keep the guard tight: any `./`-prefixed link with a path segment still fails. const skillNameMap = buildDatasetSkillNameMap(SKILLS_DIR) const linkPathMap = buildSkillLinkPathMap(SKILLS_DIR) const reconstructed = applyKnownMirrorTransforms( @@ -64,7 +69,8 @@ describe('implement composes checkpoint + publish-pr (#256)', () => { skillNameMap, linkPathMap, ) - const neutralizeSameDirDotSlash = (s: string): string => s.split('](./').join('](') + const neutralizeSameDirDotSlash = (s: string): string => + s.replace(/\]\(\.\/([^/)]+)\)/g, ']($1)') expect(neutralizeSameDirDotSlash(mirror())).toBe(neutralizeSameDirDotSlash(reconstructed)) }) }) @@ -86,10 +92,16 @@ describe('closing phase: checkpoint(write) then publish-pr (AC1)', () => { expect(step32Idx).toBeGreaterThanOrEqual(0) expect(step33Idx).toBeGreaterThan(step32Idx) // and within those steps: checkpoint write ($mode=write) comes before the - // subagent spawn that runs /publish-pr. - const writeInvocationIdx = c.search(/\$mode\s*=?:?\s*write/i) + // subagent spawn that runs /publish-pr. Anchor the write search to the + // Step 3.2 SPAN (step32..step33), not the first global occurrence — the + // first `$mode=write` in the file is the composed-skills table (and the + // between-task Step 2.8 write), so a global search would not actually prove + // the closing-phase write lives inside Step 3.2. + const step32Span = c.slice(step32Idx, step33Idx) + const writeWithinStep32 = step32Span.search(/\$mode\s*=?:?\s*write/i) + expect(writeWithinStep32).toBeGreaterThanOrEqual(0) + const writeInvocationIdx = step32Idx + writeWithinStep32 const subagentSpawnIdx = c.toLowerCase().indexOf('spawn an') - expect(writeInvocationIdx).toBeGreaterThanOrEqual(0) expect(subagentSpawnIdx).toBeGreaterThan(writeInvocationIdx) })