* chore: rename npm package + bin to @opengsd/gsd-core (functional) - package.json: name @opengsd/get-shit-done-redux → @opengsd/gsd-core, bin key get-shit-done-redux → gsd-core, repository/homepage/bugs URLs - package-lock.json: regenerated (npm install --package-lock-only) - tests/**, scripts/**, bin/**, .github/**, agents/**, commands/**, get-shit-done/bin/**, get-shit-done/workflows/**: applied the 4-rule replacement (scoped npm ref, GitHub repo path, bin/clone invocations) per #505 single-source refactor Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: sweep live references to @opengsd/gsd-core Update all live documentation (README.md + translations, docs/**, CONTRIBUTING.md, VERSIONING.md, SECURITY.md, CONTEXT.md, docs/CANARY.md) to reflect the renamed package and repository. Rules applied: - @opengsd/get-shit-done-redux → @opengsd/gsd-core (scoped npm name) - open-gsd/get-shit-done-redux → open-gsd/gsd-core (GitHub repo) - GSD-redux/get-shit-done-redux → open-gsd/gsd-core (stale badge org) - bare bin/clone refs → gsd-core CHANGELOG.md, docs/adr/**, docs/RELEASE-*.md, docs/research/**, and .changeset/** are preserved byte-identical. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: add negative lookbehind to slash-command regex in bug-2954 test The extractSlashReferences regex matched /gsd-core inside npm package URLs (@opengsd/gsd-core), producing a false /gsd:core command reference. Adding a negative lookbehind (?<![a-z]) excludes matches preceded by a letter, so only standalone /gsd-<cmd> and /gsd:<cmd> tokens are found. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#518): add changeset for package rename Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#518): update package-identity expectations to the renamed coordinates The rebase regenerated the seam to @opengsd/gsd-core (bin gsd-core, repo open-gsd/gsd-core). The #498 seam tests assert deriveIdentity against the REAL package.json, so their expected literals must follow the rename. The drift-lint unit test is left as-is — its SEAM is a self-consistent fixture and its stale-literal detection cases would shift if altered; the live-repo scan in it already passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
132 lines
4.5 KiB
Markdown
132 lines
4.5 KiB
Markdown
# Branch Protection Rollout
|
|
|
|
## Rulesets
|
|
|
|
Three ruleset specs live under `.github/rulesets/`. All are committed with
|
|
`enforcement: disabled` and activated in stages via the 3-PR rollout below.
|
|
|
|
### `main-protection`
|
|
Targets `~DEFAULT_BRANCH` (main). Enforces:
|
|
- No deletions or force pushes
|
|
- Required linear history (no merge commits)
|
|
- All changes via pull request (0 required approvals, stale-review dismissal, thread resolution required, squash/rebase only)
|
|
- Required status checks: the aggregate `Required tests` gate plus PR policy
|
|
checks for size, branch name, changeset, docs, target branch, issue link, and
|
|
PR template format
|
|
|
|
### `release-branches`
|
|
Targets `refs/heads/release/**` and `refs/heads/hotfix/**`. Same rules as
|
|
`main-protection` except `required_linear_history` is omitted (merge commits
|
|
are permitted on release/hotfix branches).
|
|
|
|
### `tag-immutability`
|
|
Targets all tags (`~ALL`). Blocks tag updates and deletions — tags are
|
|
immutable once created. Tag creation is unrestricted.
|
|
|
|
## 4-PR Rollout Plan
|
|
|
|
| PR | Branch | Action |
|
|
|----|--------|--------|
|
|
| PR-1 | `chore/branch-protection-specs` | Check in spec files; `enforcement: disabled` — no effect on repo |
|
|
| PR-2 | `chore/tiered-ci-gate` | Add tiered test scope detection to `test.yml`; doc-only PRs satisfy `Required tests` without macOS/Windows noop queues |
|
|
| PR-3 | `chore/branch-protection-evaluate` | Run `sync-rulesets.sh` with `ENFORCEMENT=evaluate`; 1-week dry-run via rule-suite logs |
|
|
| PR-4 | `chore/branch-protection-active` | Run `sync-rulesets.sh` with `ENFORCEMENT=active`; protection live |
|
|
|
|
## Running `sync-rulesets.sh`
|
|
|
|
**Prerequisites:** `gh` authenticated with repo-admin scope, `jq` installed.
|
|
|
|
```bash
|
|
# Dry-run (evaluate mode — logs violations, does not block)
|
|
REPO=open-gsd/gsd-core ENFORCEMENT=evaluate bash scripts/sync-rulesets.sh
|
|
|
|
# Activate protection
|
|
REPO=open-gsd/gsd-core ENFORCEMENT=active bash scripts/sync-rulesets.sh
|
|
|
|
# Roll back to disabled
|
|
REPO=open-gsd/gsd-core ENFORCEMENT=disabled bash scripts/sync-rulesets.sh
|
|
```
|
|
|
|
The script is idempotent: running it twice with the same `ENFORCEMENT` value
|
|
is a no-op semantically (PUT with identical body).
|
|
|
|
## Reading evaluate-mode logs
|
|
|
|
After applying with `evaluate`, check which PRs/pushes would have been blocked:
|
|
|
|
```bash
|
|
REPO=open-gsd/gsd-core
|
|
RULESET_ID=$(gh api repos/$REPO/rulesets --jq '.[] | select(.name=="main-protection") | .id')
|
|
gh api repos/$REPO/rulesets/$RULESET_ID/rule-suites
|
|
```
|
|
|
|
Each entry shows the actor, ref, result (`pass`/`fail`), and which rules
|
|
triggered. Use this to validate no legitimate workflows are broken before
|
|
flipping to `active` in PR-3.
|
|
|
|
|
|
## Test scope detection
|
|
|
|
The `test.yml` workflow always runs, but its `changes` job classifies the PR
|
|
with `scripts/ci-test-scope.cjs` before starting expensive runners. The required
|
|
branch-protection context is the single aggregate `Required tests` job.
|
|
|
|
Doc-only PRs run the lightweight lint and aggregate jobs only. Code-touching PRs
|
|
run the default required matrix:
|
|
|
|
- Ubuntu / Node 22 scoped tests
|
|
- Ubuntu / Node 24 unit, integration, and security suites
|
|
- Windows / Node 24 scoped Windows/path/shell tests
|
|
- Ubuntu / Node 24 coverage
|
|
|
|
PRs that touch workflow, package, test-runner, install, release, or Windows
|
|
sensitive surfaces also run install/slow on the primary Ubuntu lane and the full
|
|
parity matrix:
|
|
|
|
- Windows / Node 22
|
|
- macOS / Node 22
|
|
- macOS / Node 24
|
|
|
|
### Canonical code-paths list
|
|
|
|
The `changes` job treats these paths as code-touching:
|
|
|
|
```
|
|
bin/**
|
|
get-shit-done/**
|
|
agents/**
|
|
commands/**
|
|
hooks/**
|
|
tests/**
|
|
scripts/**
|
|
package.json
|
|
package-lock.json
|
|
tsconfig*.json
|
|
.github/workflows/**
|
|
.github/rulesets/**
|
|
```
|
|
|
|
This list should stay aligned with changeset/docs policy where those gates care
|
|
about the same user-facing surfaces.
|
|
|
|
### Adding a new code path
|
|
|
|
When adding a directory or file that should trigger real tests:
|
|
|
|
1. Add the path classifier to `scripts/ci-test-scope.cjs`.
|
|
2. Add targeted tests for that surface in the same classifier.
|
|
3. If it requires macOS/extra-Windows coverage, mark the classifier rule
|
|
`fullMatrix: true`.
|
|
4. Add the same glob to `changeset-required.yml` if changesets should be required
|
|
for that path
|
|
|
|
The old `test-skip.yml` inverse-path workflow was removed. Do not add required
|
|
checks for individual matrix jobs; require the aggregate `Required tests` context
|
|
instead.
|
|
|
|
## Phase-2 TODO
|
|
|
|
Enable the `required_signatures` rule (signed commits) once agent commits sign
|
|
uniformly. As of PR-1 this rule is intentionally omitted — unsigned agent
|
|
commits would be blocked by it. Track readiness in the issue linked to PR-3.
|