From fdea9dae28ad7f94b75c47bb89d3fbdbbe245b26 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 10 Mar 2026 01:19:56 +0100 Subject: [PATCH 1/5] feat: Add /landed skill, remove /catchup command Close the post-merge gap in the sync-design-done workflow by adding a /landed skill that verifies merge CI, optionally checks deployments, cleans up branches, and identifies next phases. Remove /catchup which overlapped with /sync. Co-Authored-By: Claude Opus 4.6 --- .claude/commands/catchup.md | 48 -------------- .claude/deploy.json.example | 7 +++ .claude/skills/landed/SKILL.md | 112 +++++++++++++++++++++++++++++++++ .gitignore | 1 + CLAUDE.md | 2 +- docs/CHANGELOG.md | 12 +++- docs/DEVELOPMENT_PROCESS.md | 14 ++++- tests/test_commands.py | 13 ---- tests/test_skills.py | 28 ++++++++- 9 files changed, 170 insertions(+), 67 deletions(-) delete mode 100644 .claude/commands/catchup.md create mode 100644 .claude/deploy.json.example create mode 100644 .claude/skills/landed/SKILL.md diff --git a/.claude/commands/catchup.md b/.claude/commands/catchup.md deleted file mode 100644 index b6e99e4..0000000 --- a/.claude/commands/catchup.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -allowed-tools: Read, Glob, Grep, Bash -description: Restore context after /clear or session start. Analyzes git history, recent changes, and project state to recommend next steps. ---- - -# Context Restoration - -Restore full project context and recommend next steps. - -## Steps - -1. **Read project documentation** - - Read `docs/IMPLEMENTATION_PLAN.md` for current phase status - - Read `docs/CHANGELOG.md` for recent changes - - Read `CLAUDE.md` for development methodology - -2. **Analyze git state** - - Run `git log --oneline -20` for recent commit history - - Run `git status` for uncommitted changes - - Run `git branch -a` to see all branches - - Run `git diff --stat HEAD~5..HEAD` for recent file changes - -3. **Scan for outstanding work** - - Search for `TODO`, `FIXME`, `HACK`, `XXX` markers in recently modified files - - Check for any failing tests with `uv run pytest --tb=no -q` - - Check for lint issues with `uv run ruff check .` - -4. **Summarize and recommend** - -Present findings in this format: - -```markdown -## Current State -- Branch: [branch name] -- Phase: [current phase from IMPLEMENTATION_PLAN.md] -- Uncommitted changes: [yes/no, summary] - -## Recent Work (last 5 commits) -- [commit summaries] - -## Outstanding Items -- [TODOs, failing tests, lint issues] - -## Recommended Next Steps -1. [most important action] -2. [second priority] -3. [third priority] -``` diff --git a/.claude/deploy.json.example b/.claude/deploy.json.example new file mode 100644 index 0000000..d384cc1 --- /dev/null +++ b/.claude/deploy.json.example @@ -0,0 +1,7 @@ +{ + "__comment": "Copy to .claude/deploy.json and customize. Used by /landed.", + "environments": [ + {"name": "dev", "workflow": "deploy-dev.yml"}, + {"name": "staging", "workflow": "deploy-staging.yml", "health_check": "https://staging.example.com/health"} + ] +} diff --git a/.claude/skills/landed/SKILL.md b/.claude/skills/landed/SKILL.md new file mode 100644 index 0000000..a27b89b --- /dev/null +++ b/.claude/skills/landed/SKILL.md @@ -0,0 +1,112 @@ +--- +name: landed +description: Post-merge lifecycle. Verifies merge CI, optional deployment checks, cleans up branches, and prepares next phase. +allowed-tools: Bash, Read, Grep, Glob +disable-model-invocation: true +--- + +# Landed + +Post-merge lifecycle command. Run this after a PR is merged to verify CI, check deployments, clean up branches, and identify next steps. + +## Step 1: Detect Merged PR + +Identify the PR that was just merged. + +1. Run `git branch --show-current` to get the current branch +2. If already on master: + - Check `git reflog --oneline -20` for the previous branch name + - If no branch found, ask the user for the PR number or branch name +3. Look up the merged PR: + ``` + gh pr list --state merged --head --json number,title,mergeCommit -L 1 + ``` +4. If no PR found: ask the user for the PR number directly +5. Display: PR number, title, merge commit SHA + +**Pre-check**: Run `gh auth status` early. If not authenticated, stop and instruct the user to run `gh auth login`. + +## Step 2: Verify Merge CI + +Check that CI passed on the merge commit. + +1. List recent runs on master: + ``` + gh run list --branch master -L 5 --json status,conclusion,databaseId,name,headSha + ``` +2. Match by merge commit SHA if possible +3. Based on status: + - **in_progress**: watch it with `gh run watch ` + - **success/completed with conclusion=success**: proceed + - **failure**: show details via `gh run view --log-failed` + - Ask: "Is this a recurring issue or specific to this PR?" + - If recurring: suggest adding to `/done` validation or pre-merge CI + - If specific: diagnose inline from the failed log output + +## Step 3: Deployment Verification (Configurable) + +Check for deployment status if configured. + +1. Check if `.claude/deploy.json` exists +2. If it exists: + - Read the file and iterate over configured environments + - For each environment: + - Watch the deployment workflow: `gh run list --workflow -L 1 --json status,conclusion,databaseId` + - If `health_check` URL is configured, fetch it and verify a 200 response + - Report per-environment status (success/failure/in_progress) +3. If no config file: + - Ask the user: "Is there a deployment to verify? (skip if none)" + - If user says no or skips: mark as "skipped" + +## Step 4: Branch Cleanup + +Switch to master and clean up the feature branch. + +1. `git checkout master && git pull --rebase` +2. Delete local branch: `git branch -d ` (safe delete, will fail if unmerged) +3. Check if remote branch still exists: `git ls-remote --heads origin ` +4. If remote branch exists: + - Ask the user before deleting: "Delete remote branch origin/?" + - If approved: `git push origin --delete ` + - If denied: note "kept" in summary +5. If remote branch already deleted (e.g., GitHub auto-delete): note "already deleted by GitHub" in summary + +**Edge case**: If already on master and the branch was already deleted locally, skip local deletion gracefully. + +## Step 5: Next Phase (P-scope Only) + +Check if there is more planned work. + +1. Read `docs/IMPLEMENTATION_PLAN.md` +2. If the file exists and has unchecked phases (`- [ ]`): + - Identify the next unchecked phase + - Summarize what it covers and any noted dependencies +3. If all phases are checked (`- [x]`) or no plan file exists: skip this step + +## Step 6: Summary Report + +Output a summary of everything that happened: + +``` +# Landed + +PR: #N "" merged into master +CI: PASS (run #ID) | FAIL (run #ID) | WATCHING +Deploy: verified / skipped / failed + +## Cleanup +- Deleted local branch: <branch> +- Deleted remote branch: <branch> [or "kept" or "already deleted by GitHub"] +- Now on: master (up to date) + +## Next Steps +- [next phase summary / "Ready for new work" / "Project complete"] +``` + +## Edge Cases + +- **Already on master**: check `git reflog` for previous branch, or ask the user +- **PR not found via branch name**: ask the user for the PR number +- **Remote branch already deleted**: GitHub auto-delete is common; handle gracefully +- **gh not authenticated**: check `gh auth status` early and stop with instructions +- **No CI runs found**: report "no CI runs found for merge commit" and proceed diff --git a/.gitignore b/.gitignore index f54b7fd..a995a33 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ Thumbs.db # Claude Code local overrides .claude/settings.local.json +.claude/deploy.json .claude/hooks/*.log CLAUDE.local.md diff --git a/CLAUDE.md b/CLAUDE.md index db72ed1..195add4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,7 +2,7 @@ ## Development Process -Use `/sync` before starting work, `/design` to formalize a plan, and `/done` when finished. `/design` estimates scope (Q/S/P) during planning; `/done` auto-detects actual scope at completion based on workspace signals. Before creating any plan, read `docs/DEVELOPMENT_PROCESS.md` first. +Use `/sync` before starting work, `/design` to formalize a plan, `/done` when finished, and `/landed` after the PR merges. `/design` estimates scope (Q/S/P) during planning; `/done` auto-detects actual scope at completion based on workspace signals. Before creating any plan, read `docs/DEVELOPMENT_PROCESS.md` first. ## Security diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 778c291..cffa1de 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- `/landed` skill for post-merge lifecycle -- verifies merge CI, optionally checks deployments (via `.claude/deploy.json`), cleans up feature branches, and identifies the next phase for P-scope work +- `.claude/deploy.json.example` template for configuring deployment verification in `/landed` + +### Removed +- `/catchup` command -- its context restoration role overlaps with `/sync`, which already covers pre-flight workspace state + +### Changed +- Development workflow expanded from sync-design-done to sync-design-done-landed, closing the post-merge gap + ### Added - Chain-of-Verification (CoVe) commands (`/cove`, `/cove-isolated`) for high-stakes accuracy -- 4-step self-verification process based on Meta's CoVe paper, with an isolated variant that runs verification in a separate agent to prevent confirmation bias - Template sync workflow (`.github/workflows/template-sync.yml`) for downstream projects to auto-sync upstream template improvements -- runs weekly or on manual trigger, creates PRs with changed template-managed files while preserving project-specific code @@ -18,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Workflow skill `/done` auto-detects scope (Q/S/P) and runs the full validate-ship-document pipeline, including the former `/ship` checklist - Three graduated permission tiers (Assisted, Autonomous, Full Trust) for devcontainer environments -- container isolation (firewall, non-root, hooks) enables safely expanding Claude Code permissions, reducing unnecessary prompts from dozens per session to zero in Tier 2/3 while blocking tool installation, package publishing, and container escape vectors via curated deny lists and a policy-enforcement hook - 5 hook scripts in `.claude/hooks/` run automatically during Claude Code sessions -- 3 security hooks block destructive commands, secret leaks, and invisible Unicode attacks in real time; 2 productivity hooks auto-format Python files and auto-run associated tests after every edit -- 4 slash commands (`/catchup`, `/cove`, `/cove-isolated`, `/security-audit`) provide context restoration, chain-of-verification for accuracy, and a 6-phase security posture scan with A-F grading +- 3 slash commands (`/cove`, `/cove-isolated`, `/security-audit`) provide chain-of-verification for accuracy and a 6-phase security posture scan with A-F grading - 3 new specialized agents: `security-auditor` (OWASP-based vulnerability analysis, read-only), `refactoring-specialist` (SOLID/code smell detection, read-only), `output-evaluator` (LLM-as-Judge quality scoring for automated pipelines) - 4 review rules in `.claude/rules/` auto-loaded as project context -- cover architecture, code quality, performance, and test quality concerns that linters cannot catch - AI-powered PR review via GitHub Actions (`claude-code-review.yml`) using `anthropics/claude-code-action@v1` -- automatically reviews PRs with read-only tools on open/sync/ready_for_review diff --git a/docs/DEVELOPMENT_PROCESS.md b/docs/DEVELOPMENT_PROCESS.md index f6ff858..c76ea10 100644 --- a/docs/DEVELOPMENT_PROCESS.md +++ b/docs/DEVELOPMENT_PROCESS.md @@ -101,6 +101,14 @@ All agents use `subagent_type: "general-purpose"`. Do NOT use `feature-dev:code- --- +## Post-merge + +Run `/landed` after a PR is merged. It verifies merge CI, optionally checks +deployments (via `.claude/deploy.json`), cleans up branches, and identifies the +next phase for P-scope work. + +--- + ## P. Project Path **P.1 Analyze** @@ -161,11 +169,10 @@ All hooks require `jq` for JSON parsing and degrade gracefully if jq is missing. ## Commands -4 slash commands in `.claude/commands/`: +3 slash commands in `.claude/commands/`: | Command | Purpose | |---------|---------| -| `/catchup` | Context restoration after `/clear`. Reads IMPLEMENTATION_PLAN.md, CHANGELOG.md, git history; recommends next steps. | | `/cove` | Chain-of-Verification (CoVe) for high-stakes accuracy. 4-step process: generate baseline, plan verifications, verify from source, produce corrected response. | | `/cove-isolated` | Isolated CoVe variant. Verification step runs in a separate agent that cannot see the baseline response, preventing confirmation bias. | | `/security-audit` | 6-phase Python security scan (deps, secrets, code patterns, input validation, config, scoring). Outputs A-F grade. | @@ -174,13 +181,14 @@ All hooks require `jq` for JSON parsing and degrade gracefully if jq is missing. ## Skills -4 skills in `.claude/skills/`: +5 skills in `.claude/skills/`: | Skill | Purpose | |-------|---------| | `/sync` | Pre-flight workspace sync. Fetches remote, reports branch state, dirty files, ahead/behind, recent commits. | | `/design` | Crystallize brainstorming into a structured plan. Reads DECISIONS.md for conflicts, auto-classifies scope, outputs actionable plan. | | `/done` | Universal completion. Auto-detects scope (Q/S/P), validates (3-tier checklist), ships/lands/delivers, updates docs. Absorbs former `/ship`. | +| `/landed` | Post-merge lifecycle. Verifies merge CI, optional deployment checks, cleans up branches, prepares next phase. | | `/edit-permissions` | Manage Claude Code permission rules in settings.json. Pattern syntax reference and safety guardrails. | --- diff --git a/tests/test_commands.py b/tests/test_commands.py index f11f430..66e144c 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -7,7 +7,6 @@ COMMANDS_DIR = Path(__file__).parent.parent / ".claude" / "commands" ALL_COMMANDS = [ - "catchup.md", "cove.md", "cove-isolated.md", "security-audit.md", @@ -71,18 +70,6 @@ def test_command_has_markdown_heading(self, command_name: str) -> None: class TestCommandContent: """Verify specific command content.""" - def test_catchup_reads_implementation_plan(self) -> None: - content = (COMMANDS_DIR / "catchup.md").read_text(encoding="utf-8") - assert "IMPLEMENTATION_PLAN" in content, "catchup should reference IMPLEMENTATION_PLAN.md" - - def test_catchup_reads_changelog(self) -> None: - content = (COMMANDS_DIR / "catchup.md").read_text(encoding="utf-8") - assert "CHANGELOG" in content, "catchup should reference CHANGELOG.md" - - def test_catchup_checks_git(self) -> None: - content = (COMMANDS_DIR / "catchup.md").read_text(encoding="utf-8") - assert "git log" in content, "catchup should analyze git history" - def test_security_audit_has_scoring(self) -> None: content = (COMMANDS_DIR / "security-audit.md").read_text(encoding="utf-8") assert "Grade" in content or "grade" in content, "security-audit should include grading" diff --git a/tests/test_skills.py b/tests/test_skills.py index 3dad401..053c1e5 100644 --- a/tests/test_skills.py +++ b/tests/test_skills.py @@ -11,6 +11,7 @@ "sync", "design", "done", + "landed", ] @@ -80,7 +81,7 @@ def test_skill_has_markdown_heading(self, skill_name: str) -> None: class TestSkillSideEffects: """Verify side-effect declarations are correct.""" - @pytest.mark.parametrize("skill_name", ["sync", "done"]) + @pytest.mark.parametrize("skill_name", ["sync", "done", "landed"]) def test_side_effect_skills_disable_model_invocation(self, skill_name: str) -> None: content = (SKILLS_DIR / skill_name / "SKILL.md").read_text(encoding="utf-8") parts = content.split("---", 2) @@ -181,3 +182,28 @@ def test_done_has_scope_detection(self) -> None: assert "ship" in content.lower(), "done should describe Q=ship" assert "land" in content.lower(), "done should describe S=land" assert "deliver" in content.lower(), "done should describe P=deliver" + + # /landed + def test_landed_detects_merged_pr(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "gh pr list" in content, "landed should detect merged PR" + + def test_landed_verifies_ci(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "gh run" in content, "landed should verify CI runs" + + def test_landed_cleans_branches(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "git branch -d" in content, "landed should clean up branches" + + def test_landed_checks_deployment(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "deploy.json" in content, "landed should check deployment config" + + def test_landed_checks_next_phase(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "IMPLEMENTATION_PLAN" in content, "landed should check for next phase" + + def test_landed_produces_summary(self) -> None: + content = (SKILLS_DIR / "landed" / "SKILL.md").read_text(encoding="utf-8") + assert "# Landed" in content, "landed should produce a summary report" From b996022c2ca5bd9d537f2d1137b59d286b03f0ca Mon Sep 17 00:00:00 2001 From: Martin Stransky <stranma5@gmail.com> Date: Tue, 10 Mar 2026 01:29:39 +0100 Subject: [PATCH 2/5] fix: Use Status Summary table for phase detection in /landed The IMPLEMENTATION_PLAN.md tracks phase completion via a "Quick Status Summary" table, not phase-level checkboxes. Update Step 5 to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --- .claude/skills/landed/SKILL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/skills/landed/SKILL.md b/.claude/skills/landed/SKILL.md index a27b89b..566e066 100644 --- a/.claude/skills/landed/SKILL.md +++ b/.claude/skills/landed/SKILL.md @@ -78,10 +78,10 @@ Switch to master and clean up the feature branch. Check if there is more planned work. 1. Read `docs/IMPLEMENTATION_PLAN.md` -2. If the file exists and has unchecked phases (`- [ ]`): - - Identify the next unchecked phase +2. If the file exists, check the "Quick Status Summary" table near the top for any phase whose status is not "Complete": + - Identify the next incomplete phase - Summarize what it covers and any noted dependencies -3. If all phases are checked (`- [x]`) or no plan file exists: skip this step +3. If all phases show "Complete" or no plan file exists: skip this step ## Step 6: Summary Report From bdf84fe07bf63314abdb6530a37c05c1d2055892 Mon Sep 17 00:00:00 2001 From: Martin Stransky <stranma5@gmail.com> Date: Tue, 10 Mar 2026 01:34:26 +0100 Subject: [PATCH 3/5] fix: Merge duplicate changelog sections, restore proper structure Consolidate two ### Added sections into one and place Removed/Changed entries in their correct existing sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --- docs/CHANGELOG.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index cffa1de..dbc943f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,14 +10,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `/landed` skill for post-merge lifecycle -- verifies merge CI, optionally checks deployments (via `.claude/deploy.json`), cleans up feature branches, and identifies the next phase for P-scope work - `.claude/deploy.json.example` template for configuring deployment verification in `/landed` - -### Removed -- `/catchup` command -- its context restoration role overlaps with `/sync`, which already covers pre-flight workspace state - -### Changed -- Development workflow expanded from sync-design-done to sync-design-done-landed, closing the post-merge gap - -### Added - Chain-of-Verification (CoVe) commands (`/cove`, `/cove-isolated`) for high-stakes accuracy -- 4-step self-verification process based on Meta's CoVe paper, with an isolated variant that runs verification in a separate agent to prevent confirmation bias - Template sync workflow (`.github/workflows/template-sync.yml`) for downstream projects to auto-sync upstream template improvements -- runs weekly or on manual trigger, creates PRs with changed template-managed files while preserving project-specific code - Python-specific SOLID checklist in `refactoring-specialist` agent -- checks for mutable default arguments, ABC/Protocol misuse, missing dependency injection, god classes, `@property` overuse, and circular imports @@ -46,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Development workflow expanded from sync-design-done to sync-design-done-landed, closing the post-merge gap - QSP scope classification is now auto-detected by `/done` based on branch, diff size, and IMPLEMENTATION_PLAN.md state -- users no longer classify manually before starting work - PCC shorthand now triggers `/done` instead of manually executing S.5-S.7 - Setup script now makes `.claude/hooks/*.sh` files executable after placeholder substitution -- hook scripts work immediately after project setup without manual `chmod` @@ -60,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +- `/catchup` command -- its context restoration role overlaps with `/sync`, which already covers pre-flight workspace state - `/ship` slash command -- its 3-tier validation checklist (Blockers, High Priority, Recommended) is preserved in `/done` Phase 2 - Shell Command Style and Allowed Operations sections from CLAUDE.md -- absolute path preferences and read-only command lists are now handled by settings.json permission rules rather than prose instructions From 62d0a1d8b1f36bdc08d7526229c93394064698d7 Mon Sep 17 00:00:00 2001 From: Martin Stransky <stranma5@gmail.com> Date: Tue, 10 Mar 2026 01:41:45 +0100 Subject: [PATCH 4/5] docs: Record /landed decisions in DECISIONS.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --- docs/DECISIONS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 37fd667..c3bcfb3 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -113,6 +113,16 @@ When a decision is superseded or obsolete, delete it (git history preserves the - `/sync` and `/done` have `disable-model-invocation: true` (side effects: git fetch, git commit/push, PR creation); `/design` is intentionally model-invocable so Claude can suggest it during brainstorming - QSP paths (Q/S/P) and their step descriptions preserved in DEVELOPMENT_PROCESS.md -- skills orchestrate the paths, they don't replace them +## 2026-03-10: Post-merge /landed Skill + +**Request**: Close the post-merge gap in the sync-design-done workflow. After `/done` creates a PR and it merges, nothing verifies merge CI, checks deployments, cleans up branches, or identifies the next phase. + +**Decisions**: +- New `/landed` skill (not command) -- follows same pattern as `/sync` and `/done` with `disable-model-invocation: true` +- `/catchup` removed -- its context restoration overlaps with `/sync` which already covers pre-flight state +- Optional deployment verification via `.claude/deploy.json` (gitignored) -- not all projects have deployments, so it's opt-in with an example file +- Phase detection uses "Quick Status Summary" table in IMPLEMENTATION_PLAN.md, not `- [ ]` checkboxes -- matches actual file structure + ## 2026-03-10: Template Integration CI Pipeline **Request**: Create a CI pipeline that applies the template in various settings to catch template bugs before merge. From bf5bd6545de11d267e78161124cdef091af53f6d Mon Sep 17 00:00:00 2001 From: Martin Stransky <stranma5@gmail.com> Date: Tue, 10 Mar 2026 01:44:43 +0100 Subject: [PATCH 5/5] fix: Address CodeRabbit review -- CI aggregation, commit-scoped deploys, markdown lint - CI verification now fetches -L 20 runs and filters by headSha to check all workflow runs for the merge commit, not just one - Deployment check uses --commit <sha> to avoid verifying stale runs - Fenced code blocks have language annotations and blank line spacing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --- .claude/skills/landed/SKILL.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.claude/skills/landed/SKILL.md b/.claude/skills/landed/SKILL.md index 566e066..225fb37 100644 --- a/.claude/skills/landed/SKILL.md +++ b/.claude/skills/landed/SKILL.md @@ -18,9 +18,11 @@ Identify the PR that was just merged. - Check `git reflog --oneline -20` for the previous branch name - If no branch found, ask the user for the PR number or branch name 3. Look up the merged PR: - ``` + + ```bash gh pr list --state merged --head <branch> --json number,title,mergeCommit -L 1 ``` + 4. If no PR found: ask the user for the PR number directly 5. Display: PR number, title, merge commit SHA @@ -31,14 +33,16 @@ Identify the PR that was just merged. Check that CI passed on the merge commit. 1. List recent runs on master: + + ```bash + gh run list --branch master -L 20 --json status,conclusion,databaseId,name,headSha ``` - gh run list --branch master -L 5 --json status,conclusion,databaseId,name,headSha - ``` -2. Match by merge commit SHA if possible -3. Based on status: - - **in_progress**: watch it with `gh run watch <id>` - - **success/completed with conclusion=success**: proceed - - **failure**: show details via `gh run view <id> --log-failed` + +2. Filter to runs whose `headSha` matches the merge commit SHA +3. Evaluate all matched runs: + - **in_progress**: watch still-running run(s) with `gh run watch <id>` + - **success**: all matched runs must be `completed` with `conclusion=success` to proceed + - **failure**: show details via `gh run view <id> --log-failed` for each failing run - Ask: "Is this a recurring issue or specific to this PR?" - If recurring: suggest adding to `/done` validation or pre-merge CI - If specific: diagnose inline from the failed log output @@ -51,7 +55,7 @@ Check for deployment status if configured. 2. If it exists: - Read the file and iterate over configured environments - For each environment: - - Watch the deployment workflow: `gh run list --workflow <workflow> -L 1 --json status,conclusion,databaseId` + - Watch the deployment workflow: `gh run list --workflow <workflow> --commit <merge-commit-sha> --json status,conclusion,databaseId` - If `health_check` URL is configured, fetch it and verify a 200 response - Report per-environment status (success/failure/in_progress) 3. If no config file: @@ -87,7 +91,7 @@ Check if there is more planned work. Output a summary of everything that happened: -``` +```text # Landed PR: #N "<title>" merged into master