diff --git a/land-and-deploy/SKILL.md b/land-and-deploy/SKILL.md index bad8549f..d447cd5d 100644 --- a/land-and-deploy/SKILL.md +++ b/land-and-deploy/SKILL.md @@ -290,7 +290,96 @@ Record merge timestamp and duration. Determine what kind of project this is and how to verify the deploy. -Run `gstack-diff-scope` to classify the changes: +First, run the deploy configuration bootstrap to detect or read persisted deploy settings: + +## Deploy Configuration Bootstrap + +**Detect existing deploy configuration in CLAUDE.md:** + +```bash +grep -q "## Deploy Configuration" CLAUDE.md 2>/dev/null && echo "DEPLOY_CONFIG_EXISTS" || echo "NO_DEPLOY_CONFIG" +``` + +**If DEPLOY_CONFIG_EXISTS:** Read the Deploy Configuration section from CLAUDE.md. Use the detected platform, production URL, deploy workflow name, and merge method in subsequent steps. **Skip the rest of bootstrap.** + +**If NO_DEPLOY_CONFIG — auto-detect:** + +### D1. Detect deploy platform + +```bash +# Check for platform config files +[ -f vercel.json ] || [ -d .vercel ] && echo "PLATFORM:vercel" +[ -f netlify.toml ] || [ -d netlify ] && echo "PLATFORM:netlify" +[ -f fly.toml ] && echo "PLATFORM:fly" +[ -f render.yaml ] && echo "PLATFORM:render" +[ -f Procfile ] && echo "PLATFORM:heroku" +[ -f railway.json ] || [ -f railway.toml ] && echo "PLATFORM:railway" +[ -f Dockerfile ] || [ -f docker-compose.yml ] && echo "PLATFORM:docker" +# Check for GitHub Actions deploy workflows +for f in .github/workflows/*.yml .github/workflows/*.yaml; do + [ -f "$f" ] && grep -qiE "deploy|release|production|staging|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f" +done +# Check project type +[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli" +[ -f Cargo.toml ] && grep -q '\[\[bin\]\]' Cargo.toml 2>/dev/null && echo "PROJECT_TYPE:cli" +[ -f setup.py ] || [ -f pyproject.toml ] && grep -qiE "console_scripts|entry_points" setup.py pyproject.toml 2>/dev/null && echo "PROJECT_TYPE:cli" +ls *.gemspec 2>/dev/null && echo "PROJECT_TYPE:library" +``` + +### D2. Detect production URL + +```bash +# Check package.json homepage +[ -f package.json ] && grep -o '"homepage":\s*"[^"]*"' package.json 2>/dev/null +# Check for common URL patterns in config +[ -f vercel.json ] && cat vercel.json 2>/dev/null +[ -f netlify.toml ] && grep -i "url\|domain" netlify.toml 2>/dev/null +[ -f fly.toml ] && grep "app" fly.toml 2>/dev/null +``` + +### D3. Detect merge method + +```bash +gh api repos/{owner}/{repo} --jq '{squash: .allow_squash_merge, merge: .allow_merge_commit, rebase: .allow_rebase_merge}' 2>/dev/null || echo "MERGE_DETECT_FAILED" +``` + +Default preference order: squash (cleanest history) > merge > rebase. + +### D4. Classify and present + +Based on the detection results, determine the deploy configuration: + +1. **If PLATFORM detected:** Note the platform and any associated URL. +2. **If DEPLOY_WORKFLOW detected:** Note the workflow file path and name. +3. **If PROJECT_TYPE is "cli" or "library":** Note that this project likely doesn't have a web deploy. Post-merge verification is not applicable. +4. **If no platform, no workflow, and not a CLI/library:** Use AskUserQuestion: + - **Context:** Setting up deploy configuration for /land-and-deploy. + - **Question:** No deploy platform detected. What does your deploy look like? + - **RECOMMENDATION:** Choose the option that matches your setup. + - A) We deploy via GitHub Actions (specify workflow name) + - B) We deploy via Vercel / Netlify / Fly.io / other platform (specify URL) + - C) We deploy manually or via custom scripts + - D) This project doesn't deploy (library, CLI tool) + +### D5. Persist to CLAUDE.md + +If CLAUDE.md exists, append. If it doesn't exist, create it. + +Add a section: +```markdown +## Deploy Configuration (auto-detected by gstack) +- Platform: {platform or "none detected"} +- Production URL: {url or "not detected — provide via /land-and-deploy "} +- Deploy workflow: {workflow file or "none"} +- Merge method: {squash/merge/rebase} +- Project type: {web app / CLI / library} +``` + +Tell the user: "Deploy configuration saved to CLAUDE.md. Future /land-and-deploy runs will use these settings automatically. Edit the section manually to update." + +--- + +Then run `gstack-diff-scope` to classify the changes: ```bash eval $(~/.claude/skills/gstack/bin/gstack-diff-scope $(gh pr view --json baseRefName -q .baseRefName 2>/dev/null || echo main) 2>/dev/null) diff --git a/land-and-deploy/SKILL.md.tmpl b/land-and-deploy/SKILL.md.tmpl index b7b43177..4439b280 100644 --- a/land-and-deploy/SKILL.md.tmpl +++ b/land-and-deploy/SKILL.md.tmpl @@ -152,7 +152,11 @@ Record merge timestamp and duration. Determine what kind of project this is and how to verify the deploy. -Run `gstack-diff-scope` to classify the changes: +First, run the deploy configuration bootstrap to detect or read persisted deploy settings: + +{{DEPLOY_BOOTSTRAP}} + +Then run `gstack-diff-scope` to classify the changes: ```bash eval $(~/.claude/skills/gstack/bin/gstack-diff-scope $(gh pr view --json baseRefName -q .baseRefName 2>/dev/null || echo main) 2>/dev/null) diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index ce799fe1..4ebbaa57 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -735,7 +735,7 @@ echo "---CONFIG---" ~/.claude/skills/gstack/bin/gstack-config get skip_eng_review 2>/dev/null || echo "false" ``` -Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display: +Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, land-and-deploy). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. For Deployed, show the most recent `land-and-deploy` entry with status mapped: SUCCESS→HEALTHY, REVERTED→REVERTED, other→ISSUES. Display: ``` +====================================================================+ @@ -746,6 +746,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES | | CEO Review | 0 | — | — | no | | Design Review | 0 | — | — | no | +| Deployed | 0 | — | — | no | +--------------------------------------------------------------------+ | VERDICT: CLEARED — Eng Review passed | +====================================================================+ @@ -755,6 +756,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \`gstack-config set skip_eng_review true\` (the "don't bother me" setting). - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup. - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes. +- **Deployed (informational):** Shows whether the most recent PR on this branch was successfully deployed and verified via \`/land-and-deploy\`. Status: HEALTHY, REVERTED, or ISSUES. Never gates shipping. **Verdict logic:** - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \`skip_eng_review\` is \`true\`) diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index 507952c4..2d3021c1 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -410,7 +410,7 @@ echo "---CONFIG---" ~/.claude/skills/gstack/bin/gstack-config get skip_eng_review 2>/dev/null || echo "false" ``` -Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display: +Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, land-and-deploy). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. For Deployed, show the most recent `land-and-deploy` entry with status mapped: SUCCESS→HEALTHY, REVERTED→REVERTED, other→ISSUES. Display: ``` +====================================================================+ @@ -421,6 +421,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES | | CEO Review | 0 | — | — | no | | Design Review | 0 | — | — | no | +| Deployed | 0 | — | — | no | +--------------------------------------------------------------------+ | VERDICT: CLEARED — Eng Review passed | +====================================================================+ @@ -430,6 +431,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \`gstack-config set skip_eng_review true\` (the "don't bother me" setting). - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup. - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes. +- **Deployed (informational):** Shows whether the most recent PR on this branch was successfully deployed and verified via \`/land-and-deploy\`. Status: HEALTHY, REVERTED, or ISSUES. Never gates shipping. **Verdict logic:** - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \`skip_eng_review\` is \`true\`) diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index 48fe7230..d17a7e61 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -348,7 +348,7 @@ echo "---CONFIG---" ~/.claude/skills/gstack/bin/gstack-config get skip_eng_review 2>/dev/null || echo "false" ``` -Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display: +Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, land-and-deploy). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. For Deployed, show the most recent `land-and-deploy` entry with status mapped: SUCCESS→HEALTHY, REVERTED→REVERTED, other→ISSUES. Display: ``` +====================================================================+ @@ -359,6 +359,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES | | CEO Review | 0 | — | — | no | | Design Review | 0 | — | — | no | +| Deployed | 0 | — | — | no | +--------------------------------------------------------------------+ | VERDICT: CLEARED — Eng Review passed | +====================================================================+ @@ -368,6 +369,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \`gstack-config set skip_eng_review true\` (the "don't bother me" setting). - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup. - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes. +- **Deployed (informational):** Shows whether the most recent PR on this branch was successfully deployed and verified via \`/land-and-deploy\`. Status: HEALTHY, REVERTED, or ISSUES. Never gates shipping. **Verdict logic:** - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \`skip_eng_review\` is \`true\`) diff --git a/scripts/gen-skill-docs.ts b/scripts/gen-skill-docs.ts index 05ff9eaf..3913fb3a 100644 --- a/scripts/gen-skill-docs.ts +++ b/scripts/gen-skill-docs.ts @@ -904,7 +904,7 @@ echo "---CONFIG---" ~/.claude/skills/gstack/bin/gstack-config get skip_eng_review 2>/dev/null || echo "false" \`\`\` -Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between \`plan-design-review\` (full visual audit) and \`design-review-lite\` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display: +Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, land-and-deploy). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between \`plan-design-review\` (full visual audit) and \`design-review-lite\` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. For Deployed, show the most recent \`land-and-deploy\` entry with status mapped: SUCCESS→HEALTHY, REVERTED→REVERTED, other→ISSUES. Display: \`\`\` +====================================================================+ @@ -915,6 +915,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES | | CEO Review | 0 | — | — | no | | Design Review | 0 | — | — | no | +| Deployed | 0 | — | — | no | +--------------------------------------------------------------------+ | VERDICT: CLEARED — Eng Review passed | +====================================================================+ @@ -924,6 +925,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \\\`gstack-config set skip_eng_review true\\\` (the "don't bother me" setting). - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup. - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes. +- **Deployed (informational):** Shows whether the most recent PR on this branch was successfully deployed and verified via \\\`/land-and-deploy\\\`. Status: HEALTHY, REVERTED, or ISSUES. Never gates shipping. **Verdict logic:** - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \\\`skip_eng_review\\\` is \\\`true\\\`) @@ -1087,6 +1089,95 @@ Only commit if there are changes. Stage all bootstrap files (config, test direct ---`; } +function generateDeployBootstrap(): string { + return `## Deploy Configuration Bootstrap + +**Detect existing deploy configuration in CLAUDE.md:** + +\`\`\`bash +grep -q "## Deploy Configuration" CLAUDE.md 2>/dev/null && echo "DEPLOY_CONFIG_EXISTS" || echo "NO_DEPLOY_CONFIG" +\`\`\` + +**If DEPLOY_CONFIG_EXISTS:** Read the Deploy Configuration section from CLAUDE.md. Use the detected platform, production URL, deploy workflow name, and merge method in subsequent steps. **Skip the rest of bootstrap.** + +**If NO_DEPLOY_CONFIG — auto-detect:** + +### D1. Detect deploy platform + +\`\`\`bash +# Check for platform config files +[ -f vercel.json ] || [ -d .vercel ] && echo "PLATFORM:vercel" +[ -f netlify.toml ] || [ -d netlify ] && echo "PLATFORM:netlify" +[ -f fly.toml ] && echo "PLATFORM:fly" +[ -f render.yaml ] && echo "PLATFORM:render" +[ -f Procfile ] && echo "PLATFORM:heroku" +[ -f railway.json ] || [ -f railway.toml ] && echo "PLATFORM:railway" +[ -f Dockerfile ] || [ -f docker-compose.yml ] && echo "PLATFORM:docker" +# Check for GitHub Actions deploy workflows +for f in .github/workflows/*.yml .github/workflows/*.yaml; do + [ -f "$f" ] && grep -qiE "deploy|release|production|staging|cd" "$f" 2>/dev/null && echo "DEPLOY_WORKFLOW:$f" +done +# Check project type +[ -f package.json ] && grep -q '"bin"' package.json 2>/dev/null && echo "PROJECT_TYPE:cli" +[ -f Cargo.toml ] && grep -q '\\[\\[bin\\]\\]' Cargo.toml 2>/dev/null && echo "PROJECT_TYPE:cli" +[ -f setup.py ] || [ -f pyproject.toml ] && grep -qiE "console_scripts|entry_points" setup.py pyproject.toml 2>/dev/null && echo "PROJECT_TYPE:cli" +ls *.gemspec 2>/dev/null && echo "PROJECT_TYPE:library" +\`\`\` + +### D2. Detect production URL + +\`\`\`bash +# Check package.json homepage +[ -f package.json ] && grep -o '"homepage":\\s*"[^"]*"' package.json 2>/dev/null +# Check for common URL patterns in config +[ -f vercel.json ] && cat vercel.json 2>/dev/null +[ -f netlify.toml ] && grep -i "url\\|domain" netlify.toml 2>/dev/null +[ -f fly.toml ] && grep "app" fly.toml 2>/dev/null +\`\`\` + +### D3. Detect merge method + +\`\`\`bash +gh api repos/{owner}/{repo} --jq '{squash: .allow_squash_merge, merge: .allow_merge_commit, rebase: .allow_rebase_merge}' 2>/dev/null || echo "MERGE_DETECT_FAILED" +\`\`\` + +Default preference order: squash (cleanest history) > merge > rebase. + +### D4. Classify and present + +Based on the detection results, determine the deploy configuration: + +1. **If PLATFORM detected:** Note the platform and any associated URL. +2. **If DEPLOY_WORKFLOW detected:** Note the workflow file path and name. +3. **If PROJECT_TYPE is "cli" or "library":** Note that this project likely doesn't have a web deploy. Post-merge verification is not applicable. +4. **If no platform, no workflow, and not a CLI/library:** Use AskUserQuestion: + - **Context:** Setting up deploy configuration for /land-and-deploy. + - **Question:** No deploy platform detected. What does your deploy look like? + - **RECOMMENDATION:** Choose the option that matches your setup. + - A) We deploy via GitHub Actions (specify workflow name) + - B) We deploy via Vercel / Netlify / Fly.io / other platform (specify URL) + - C) We deploy manually or via custom scripts + - D) This project doesn't deploy (library, CLI tool) + +### D5. Persist to CLAUDE.md + +If CLAUDE.md exists, append. If it doesn't exist, create it. + +Add a section: +\`\`\`markdown +## Deploy Configuration (auto-detected by gstack) +- Platform: {platform or "none detected"} +- Production URL: {url or "not detected — provide via /land-and-deploy "} +- Deploy workflow: {workflow file or "none"} +- Merge method: {squash/merge/rebase} +- Project type: {web app / CLI / library} +\`\`\` + +Tell the user: "Deploy configuration saved to CLAUDE.md. Future /land-and-deploy runs will use these settings automatically. Edit the section manually to update." + +---`; +} + const RESOLVERS: Record string> = { COMMAND_REFERENCE: generateCommandReference, SNAPSHOT_FLAGS: generateSnapshotFlags, @@ -1098,6 +1189,7 @@ const RESOLVERS: Record string> = { DESIGN_REVIEW_LITE: generateDesignReviewLite, REVIEW_DASHBOARD: generateReviewDashboard, TEST_BOOTSTRAP: generateTestBootstrap, + DEPLOY_BOOTSTRAP: generateDeployBootstrap, }; // ─── Template Processing ──────────────────────────────────── diff --git a/ship/SKILL.md b/ship/SKILL.md index 875845dc..ffa940dc 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -186,7 +186,7 @@ echo "---CONFIG---" ~/.claude/skills/gstack/bin/gstack-config get skip_eng_review 2>/dev/null || echo "false" ``` -Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display: +Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, land-and-deploy). Ignore entries with timestamps older than 7 days. For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. For Deployed, show the most recent `land-and-deploy` entry with status mapped: SUCCESS→HEALTHY, REVERTED→REVERTED, other→ISSUES. Display: ``` +====================================================================+ @@ -197,6 +197,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES | | CEO Review | 0 | — | — | no | | Design Review | 0 | — | — | no | +| Deployed | 0 | — | — | no | +--------------------------------------------------------------------+ | VERDICT: CLEARED — Eng Review passed | +====================================================================+ @@ -206,6 +207,7 @@ Parse the output. Find the most recent entry for each skill (plan-ceo-review, pl - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \`gstack-config set skip_eng_review true\` (the "don't bother me" setting). - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup. - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes. +- **Deployed (informational):** Shows whether the most recent PR on this branch was successfully deployed and verified via \`/land-and-deploy\`. Status: HEALTHY, REVERTED, or ISSUES. Never gates shipping. **Verdict logic:** - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \`skip_eng_review\` is \`true\`)