Skip to content

Commit fb00259

Browse files
authored
Merge pull request #26 from SimTimms/worktree-hardening-and-docs-alignment
chore: harden branch protection and align docs
2 parents 1c7fa59 + 39843f7 commit fb00259

11 files changed

Lines changed: 94 additions & 85 deletions

.claude/commands/deploynope-deploy.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -320,21 +320,29 @@ the option to poll until staging is released rather than abandoning the workflow
320320
321321
If the user accepts:
322322

323-
1. **Set up a recurring poll** using `CronCreate` with a `*/1 * * * *` schedule that runs:
323+
1. **Set up a background polling loop** using the Bash tool with `run_in_background: true`:
324324

325325
```shell
326-
git fetch origin && git tag -l "staging/active"
326+
while true; do
327+
git fetch origin 2>/dev/null
328+
if ! git tag -l "staging/active" | grep -q "staging/active"; then
329+
UNRELEASED=$(git log origin/<production-branch>..origin/<staging-branch> --oneline 2>/dev/null)
330+
if [ -z "$UNRELEASED" ]; then
331+
echo "STAGING_CLEAR"
332+
exit 0
333+
fi
334+
fi
335+
echo "Still waiting — staging claimed."
336+
sleep 60
337+
done
327338
```
328339

329-
- If `staging/active` still exists → report "Still waiting — staging claimed by `<name>`."
330-
- If `staging/active` is gone **and** `git log origin/<production-branch>..origin/<staging-branch> --oneline`
331-
shows no unreleased commits → report **"Staging is now clear!"** and proceed.
340+
- The loop checks every 60 seconds whether `staging/active` has been removed.
341+
- When the tag is gone **and** there are no unreleased commits on staging, it prints
342+
`STAGING_CLEAR` and exits.
343+
- You will be notified when the background task completes — do not poll or sleep-wait for it.
332344

333-
2. **Clean up immediately** — as soon as staging is detected as clear (or the user cancels
334-
the wait), delete the cron job using `CronDelete` with the job ID returned by `CronCreate`.
335-
Never leave a polling job running after it has served its purpose.
336-
337-
3. **Resume the deployment flow** — once staging is clear and the cron job is cleaned up,
345+
2. **Resume the deployment flow** — once the background poll reports staging is clear,
338346
continue from the "Claiming staging" step below without requiring the user to re-invoke
339347
the deployment command.
340348

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ reset, release, etc.), the confirmation prompt **must** include a visible
4343
Examples:
4444
> "Ready to commit all of this? **`🤓 DeployNOPE 2.10.0 · Feature`**"
4545
> "Shall I push this to origin? **`🤓 DeployNOPE 2.10.0 · Feature`**"
46-
> "Ready to reset `master` to match `staging`? **`⚠️ DeployNOPE 2.10.0 · Production`**"
46+
> "Ready to reset `main` to match `staging`? **`⚠️ DeployNOPE 2.10.0 · Production`**"
4747
4848
The absence of the tag on a deployment-related confirmation is itself a red flag that
4949
the framework was not loaded.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ All commands are prefixed with `deploynope-` so they stay distinct in your slash
4545
| `/deploynope-rollback` | Guides you through rolling back production to a previous release. Supports standard (through staging) and emergency (skip staging) modes. Handles frontend cache-busting automatically. |
4646
| `/deploynope-stale-check` | Identifies stale branches, aging PRs, and pipeline bottlenecks. Helps keep the repo tidy and surfaces work that may have been forgotten. |
4747
| `/deploynope-verify-rules` | A read-only self-check that confirms the deployment ruleset is loaded and Claude understands all 10 critical safety rules. Good for sanity-checking before a big release. |
48+
| `/deploynope-console` | **DEPRECATED** (removed in 2.10.0). The sidecar console log feature has been replaced by inline chat tags (`<emoji> DeployNOPE <context> · <Stage>`). |
4849

4950
---
5051

@@ -221,7 +222,7 @@ If you previously had these commands inside a project's `.claude/commands/`, you
221222

222223
## Tests
223224

224-
DeployNOPE includes a bash test suite covering all 9 hooks with 116 assertions. Tests create disposable git repos, simulate hook JSON input, and verify deny/ask/passthrough decisions.
225+
DeployNOPE includes a bash test suite covering all 9 hooks with 124 assertions. Tests create disposable git repos, simulate hook JSON input, and verify deny/ask/passthrough decisions.
225226

226227
```bash
227228
./tests/run-tests.sh # all tests

docs/deploy-process-demo.html

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,8 @@
418418

419419
<header>
420420
<h1><span class="nerd">&#129299;</span> Deploy<span class="nope">NOPE</span></h1>
421-
<p>Deployment Process &mdash; the core 17-step workflow that all releases follow from staging to master to release</p>
422-
<div class="tag">staging &rarr; master &rarr; release</div>
421+
<p>Deployment Process &mdash; the core 17-step workflow that all releases follow from staging to production to release</p>
422+
<div class="tag">staging &rarr; production &rarr; release</div>
423423
</header>
424424

425425
<!-- Workflow Tabs -->
@@ -460,12 +460,12 @@ <h2>How It Works</h2>
460460
<div class="how-card">
461461
<div class="how-icon">&#128737;</div>
462462
<h4>Branch Protection</h4>
463-
<p>Direct pushes to <code>staging</code>, <code>master</code>, and <code>development</code> are blocked. All changes flow through release branches with controlled resets.</p>
463+
<p>Direct pushes to <code>staging</code>, the production branch, and <code>development</code> are blocked. All changes flow through release branches with controlled resets.</p>
464464
</div>
465465
<div class="how-card">
466466
<div class="how-icon">&#128721;</div>
467467
<h4>Human Gates</h4>
468-
<p>Three mandatory human checkpoints: release readiness, staging validation, and master reset. No gate can be skipped or automated away.</p>
468+
<p>Three mandatory human checkpoints: release readiness, staging validation, and production reset. No gate can be skipped or automated away.</p>
469469
</div>
470470
<div class="how-card">
471471
<div class="how-icon">&#128274;</div>
@@ -475,7 +475,7 @@ <h4>Staging Contention</h4>
475475
<div class="how-card">
476476
<div class="how-icon">&#128260;</div>
477477
<h4>Cross-Repo Parity</h4>
478-
<p>Before promoting to master, version numbers are checked across all related repositories to prevent mismatched deployments.</p>
478+
<p>Before promoting to production, version numbers are checked across all related repositories to prevent mismatched deployments.</p>
479479
</div>
480480
<div class="how-card">
481481
<div class="how-icon">&#128203;</div>
@@ -485,7 +485,7 @@ <h4>Release Manifests</h4>
485485
<div class="how-card">
486486
<div class="how-icon">&#9989;</div>
487487
<h4>Auto Post-Deploy</h4>
488-
<p>After master is updated, branches are synced, staging is cleared, Confluence notes are written, and health checks run automatically.</p>
488+
<p>After the production branch is updated, branches are synced, staging is cleared, Confluence notes are written, and health checks run automatically.</p>
489489
</div>
490490
</div>
491491
</div>
@@ -498,39 +498,39 @@ <h4>Auto Post-Deploy</h4>
498498
// --- Step definitions ---
499499
const ALL_STEPS = [
500500
{ id: 'merge-features', icon: '&#128256;', title: 'Merge feature branches into release branch', desc: 'All approved feature branches are merged into the release branch via fast-forward merges.', gate: false, tags: ['feature'] },
501-
{ id: 'sync-master', icon: '&#128260;', title: 'Sync release branch with master', desc: 'Rebase or merge master into the release branch to pick up any hotfix commits.', gate: false, tags: ['feature', 'chore'] },
501+
{ id: 'sync-master', icon: '&#128260;', title: 'Sync release branch with production', desc: 'Rebase or merge the production branch into the release branch to pick up any hotfix commits.', gate: false, tags: ['feature', 'chore'] },
502502
{ id: 'update-changelog', icon: '&#128221;', title: 'Update changelog', desc: 'CHANGELOG.md is updated with all changes included in this release.', gate: false, tags: ['feature', 'hotfix'] },
503503
{ id: 'confirm-ready', icon: '&#128227;', title: 'Confirm release branch ready', desc: 'Human reviews the release branch and confirms it is ready to proceed.', gate: true, tags: ['feature', 'hotfix', 'chore'] },
504504
{ id: 'contention-check', icon: '&#128270;', title: 'Staging contention check', desc: 'Three-point check: unreleased commits, staging/active tag, stale branch guard.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
505505
{ id: 'claim-staging', icon: '&#128274;', title: 'Claim staging (tag staging/active)', desc: 'Creates staging/active tag annotated with release name and deployer.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
506506
{ id: 'reset-staging', icon: '&#128259;', title: 'Reset staging to release branch', desc: 'git reset --hard staging to the release branch HEAD, then force push.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
507507
{ id: 'validate-staging', icon: '&#128065;', title: 'Validate on staging', desc: 'Human verifies the release works correctly on the staging environment.', gate: true, tags: ['feature', 'hotfix', 'chore'] },
508508
{ id: 'cross-repo-parity', icon: '&#128260;', title: 'Cross-repo version parity check', desc: 'Verify version numbers match across all related repositories before promotion.', gate: false, tags: ['feature', 'hotfix'] },
509-
{ id: 'reset-master', icon: '&#128721;', title: 'Reset master to match staging', desc: 'Human confirms master reset. Master is force-reset to match staging exactly.', gate: true, tags: ['feature', 'hotfix', 'chore'] },
510-
{ id: 'codepipeline', icon: '&#9881;', title: 'Confirm CodePipeline healthy', desc: 'Wait for CI/CD pipeline to report all green after the master push.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
509+
{ id: 'reset-master', icon: '&#128721;', title: 'Reset production to match staging', desc: 'Human confirms production reset. The production branch is force-reset to match staging exactly.', gate: true, tags: ['feature', 'hotfix', 'chore'] },
510+
{ id: 'codepipeline', icon: '&#9881;', title: 'Confirm CodePipeline healthy', desc: 'Wait for CI/CD pipeline to report all green after the production push.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
511511
{ id: 'github-release', icon: '&#127873;', title: 'Create GitHub Release', desc: 'Tag and publish a GitHub Release with auto-generated release notes.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
512512
{ id: 'write-manifest', icon: '&#128203;', title: 'Write release manifest', desc: 'Immediately write the release manifest to the repository after the GitHub Release.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
513-
{ id: 'sync-branches', icon: '&#128257;', title: 'Sync staging + development with master', desc: 'Reset staging and development branches to match the new master.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
513+
{ id: 'sync-branches', icon: '&#128257;', title: 'Sync staging + development with production', desc: 'Reset staging and development branches to match the new production branch.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
514514
{ id: 'clear-staging', icon: '&#128275;', title: 'Clear staging (remove tag)', desc: 'Delete the staging/active tag to release the staging lock for other deployments.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
515515
{ id: 'confluence', icon: '&#128220;', title: 'Write Confluence release notes', desc: 'Publish structured release notes to the team Confluence space.', gate: false, tags: ['feature', 'hotfix'] },
516516
{ id: 'post-deploy', icon: '&#9989;', title: 'Post-deploy checks', desc: 'Automatic health checks, smoke tests, and deployment verification.', gate: false, tags: ['feature', 'hotfix', 'chore'] },
517517
];
518518

519519
const TERMINAL_COMMANDS = {
520520
'merge-features': 'git checkout release/2.5.0 && git merge --ff-only feature/new-widget',
521-
'sync-master': 'git fetch origin master && git rebase origin/master',
521+
'sync-master': 'git fetch origin main && git rebase origin/main',
522522
'update-changelog': 'echo "## 2.5.0" >> CHANGELOG.md && git add CHANGELOG.md',
523523
'confirm-ready': '# HUMAN GATE: Awaiting confirmation that release branch is ready...',
524524
'contention-check': 'git fetch origin && git tag -l "staging/active"',
525525
'claim-staging': 'git tag -a staging/active -m "Claimed by Tim for 2.5.0" && git push origin staging/active',
526526
'reset-staging': 'git checkout staging && git reset --hard release/2.5.0 && git push --force origin staging',
527527
'validate-staging': '# HUMAN GATE: Validate release on staging environment...',
528528
'cross-repo-parity': 'node scripts/check-parity.js --repos api,frontend,shared --version 2.5.0',
529-
'reset-master': '# HUMAN GATE: git checkout master && git reset --hard staging && git push --force origin master',
529+
'reset-master': '# HUMAN GATE: git checkout main && git reset --hard staging && git push --force origin main',
530530
'codepipeline': 'aws codepipeline get-pipeline-state --name prod-pipeline | jq .stageStates[].latestExecution.status',
531-
'github-release': 'gh release create v2.5.0 --generate-notes --target master',
531+
'github-release': 'gh release create v2.5.0 --generate-notes --target main',
532532
'write-manifest': 'echo \'{"version":"2.5.0","date":"2026-03-14","sha":"abc1234"}\' > manifests/2.5.0.json',
533-
'sync-branches': 'git checkout staging && git reset --hard master && git push --force origin staging development',
533+
'sync-branches': 'git checkout staging && git reset --hard main && git push --force origin staging development',
534534
'clear-staging': 'git tag -d staging/active && git push origin :refs/tags/staging/active',
535535
'confluence': 'node scripts/publish-confluence.js --version 2.5.0 --space DEPLOY',
536536
'post-deploy': 'curl -sf https://api.example.com/health && echo "All checks passed"',

docs/hooks-demo.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ <h2>Hook Overview
470470
<span class="hook-badge badge-deny">Deny</span>
471471
</div>
472472
<div class="hook-intercepts">Intercepts: <strong>gh pr create</strong></div>
473-
<div class="hook-desc">Hard-blocks PRs targeting master, main, staging, or development. Only release branches are valid PR targets &mdash; no exceptions.</div>
473+
<div class="hook-desc">Hard-blocks PRs targeting the production branch (main/master), staging, or development. Only release branches are valid PR targets &mdash; no exceptions.</div>
474474
</div>
475475

476476
<div class="hook-card">
@@ -725,7 +725,7 @@ <h4>Deny</h4>
725725
{ text: '', delay: 300 },
726726
{ text: '<span class="hook-label">[hook] check-gh-pr-create.sh</span> intercepting gh pr create...', delay: 600 },
727727
{ text: '<span class="dim">PR target: main</span>', delay: 900 },
728-
{ text: '<span class="dim">Checking protected branch list: master, main, staging, development</span>', delay: 1200 },
728+
{ text: '<span class="dim">Checking protected branch list: main, master, staging, development</span>', delay: 1200 },
729729
{ text: '<span class="warn">Target branch "main" is protected.</span>', delay: 1500 },
730730
{ text: '', delay: 1700 },
731731
{ text: '<span class="error">&#128721; DENIED &mdash; PRs to main are not allowed.</span>', delay: 1900 },

docs/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ <h3>Staging Contention Polling</h3>
207207
<a class="card" href="deploy-process-demo.html">
208208
<div class="icon">&#128640;</div>
209209
<h3>Deployment Process</h3>
210-
<p>The full 17-step deployment pipeline — from feature merge through staging, master reset, release, and post-deploy. Three workflow variants.</p>
210+
<p>The full 17-step deployment pipeline — from feature merge through staging, production reset, release, and post-deploy. Three workflow variants.</p>
211211
<div class="badges">
212212
<span class="badge interactive">interactive</span>
213213
<span class="badge simulation">step-through sim</span>

docs/preflight-postdeploy-demo.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ <h2>&#9989; Post-Deploy <span class="panel-badge badge-after">After Deploy</span
535535
<ul class="check-list" id="postdeploy-list">
536536
<li class="check-item pending" data-index="0">
537537
<span class="check-icon"></span>
538-
<span class="check-label">Master reset completed (master = staging)</span>
538+
<span class="check-label">Production reset completed (production = staging)</span>
539539
</li>
540540
<li class="check-item pending" data-index="1">
541541
<span class="check-icon"></span>
@@ -563,7 +563,7 @@ <h2>&#9989; Post-Deploy <span class="panel-badge badge-after">After Deploy</span
563563
</li>
564564
<li class="check-item pending" data-index="7">
565565
<span class="check-icon"></span>
566-
<span class="check-label">Branch alignment (master = staging = dev)</span>
566+
<span class="check-label">Branch alignment (production = staging = dev)</span>
567567
</li>
568568
<li class="check-item pending" data-index="8">
569569
<span class="check-icon"></span>
@@ -609,12 +609,12 @@ <h2>Branch Alignment Report</h2>
609609
</thead>
610610
<tbody>
611611
<tr>
612-
<td class="check-name">master = staging</td>
612+
<td class="check-name">production = staging</td>
613613
<td class="status-pass">&#9989;</td>
614614
<td class="detail">abc1234 &mdash; heads match</td>
615615
</tr>
616616
<tr>
617-
<td class="check-name">master = development</td>
617+
<td class="check-name">production = development</td>
618618
<td class="status-pass">&#9989;</td>
619619
<td class="detail">abc1234 &mdash; heads match</td>
620620
</tr>
@@ -749,14 +749,14 @@ <h2>Branch Alignment Report</h2>
749749

750750
// ---- Post-Deploy ----
751751
const postdeployLabels = [
752-
'Master reset completed (master = staging)',
752+
'Production reset completed (production = staging)',
753753
'GitHub Releases created',
754754
'Release manifest written',
755755
'Release branch merged into development',
756756
'Branch protection re-enabled',
757757
'Staging cleared (staging/active removed)',
758758
'Confluence release notes written',
759-
'Branch alignment (master = staging = dev)',
759+
'Branch alignment (production = staging = dev)',
760760
'Changelog updated',
761761
'Production smoke test confirmed'
762762
];
@@ -815,12 +815,12 @@ <h2>Branch Alignment Report</h2>
815815
if (alignmentHealthy) {
816816
tbody.innerHTML = `
817817
<tr>
818-
<td class="check-name">master = staging</td>
818+
<td class="check-name">production = staging</td>
819819
<td class="status-pass">&#9989;</td>
820820
<td class="detail">abc1234 &mdash; heads match</td>
821821
</tr>
822822
<tr>
823-
<td class="check-name">master = development</td>
823+
<td class="check-name">production = development</td>
824824
<td class="status-pass">&#9989;</td>
825825
<td class="detail">abc1234 &mdash; heads match</td>
826826
</tr>
@@ -848,14 +848,14 @@ <h2>Branch Alignment Report</h2>
848848
} else {
849849
tbody.innerHTML = `
850850
<tr>
851-
<td class="check-name">master = staging</td>
851+
<td class="check-name">production = staging</td>
852852
<td class="status-fail">&#10060;</td>
853-
<td class="detail">master: abc1234, staging: def5678 &mdash; 3 commits ahead</td>
853+
<td class="detail">main: abc1234, staging: def5678 &mdash; 3 commits ahead</td>
854854
</tr>
855855
<tr>
856-
<td class="check-name">master = development</td>
856+
<td class="check-name">production = development</td>
857857
<td class="status-fail">&#10060;</td>
858-
<td class="detail">master: abc1234, dev: 9ab0cde &mdash; 5 commits behind</td>
858+
<td class="detail">main: abc1234, dev: 9ab0cde &mdash; 5 commits behind</td>
859859
</tr>
860860
<tr>
861861
<td class="check-name">Version parity</td>

0 commit comments

Comments
 (0)