standard_id-google 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/hooks/enforce-worktree.sh +84 -0
- data/.claude/settings.json +24 -0
- data/.claude/skills/publish-gem/SKILL.md +211 -0
- data/.claude/skills/start/SKILL.md +185 -0
- data/.claude/skills/worktree/SKILL.md +143 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +28 -1
- data/CLAUDE.md +26 -0
- data/lib/standard_id/google/providers/google.rb +0 -2
- data/lib/standard_id/google/railtie.rb +13 -0
- data/lib/standard_id/google/version.rb +1 -1
- data/lib/standard_id/google.rb +1 -0
- metadata +16 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 48adde03a7f835aa201d6874ff53cdf949b5cc92a123e42a3481421ff8d3ebb3
|
|
4
|
+
data.tar.gz: 52a7009ce1d2015890d8f56f461e49f307250feca184f80953eecadf13ef16a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8865520036b8f389c0acd3d02607370ffa0b19822750e934cb04d2ac3d01cbf2d1c530627e76e01aadf5a1aa72ac5b095d4299d960067599e3196611855d7e30
|
|
7
|
+
data.tar.gz: c326578aecf2141db5e4f4d476242fafcda37699394121f1d7a7e14d1ff4af6cb4ff2f8cd4ff92950baef55cfad270155930f81acfcaeaf4972916a18d990ef8
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Enforce worktree-only file modifications for Claude Code
|
|
3
|
+
#
|
|
4
|
+
# Runs on PreToolUse for Edit, Write, and NotebookEdit tools.
|
|
5
|
+
# Blocks all file modifications in the main checkout — changes must
|
|
6
|
+
# happen inside a git worktree (.worktrees/<name>/).
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 — allow (in a worktree, CI, or non-git path)
|
|
10
|
+
# 2 — block (in main checkout)
|
|
11
|
+
#
|
|
12
|
+
# No programmatic bypass — this is intentional. If the hook itself has a bug,
|
|
13
|
+
# a human must fix it manually (edit the file or remove from settings.json).
|
|
14
|
+
#
|
|
15
|
+
# Note: This hook covers Edit, Write, and NotebookEdit tools. Bash tool writes
|
|
16
|
+
# (echo/sed/tee/cp) are not intercepted — the CLAUDE.md instruction is the
|
|
17
|
+
# enforcement layer for those. Covering Bash reliably would require parsing
|
|
18
|
+
# arbitrary shell commands, which is brittle.
|
|
19
|
+
|
|
20
|
+
# Guard: jq required for JSON parsing
|
|
21
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Skip in CI environments
|
|
26
|
+
if [[ "${CI:-}" == "true" ]] || [[ -n "${GITHUB_ACTIONS:-}" ]]; then
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
INPUT=$(cat)
|
|
31
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // ""') || exit 0
|
|
32
|
+
|
|
33
|
+
# Extract file path based on tool (NotebookEdit uses notebook_path, not file_path)
|
|
34
|
+
case "$TOOL_NAME" in
|
|
35
|
+
Edit|Write)
|
|
36
|
+
FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // ""') || exit 0
|
|
37
|
+
;;
|
|
38
|
+
NotebookEdit)
|
|
39
|
+
FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.notebook_path // .tool_input.file_path // ""') || exit 0
|
|
40
|
+
;;
|
|
41
|
+
*)
|
|
42
|
+
exit 0
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
|
|
46
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Find an existing directory to run git commands in
|
|
51
|
+
if [[ -d "$FILE_PATH" ]]; then
|
|
52
|
+
CHECK_DIR="$FILE_PATH"
|
|
53
|
+
elif [[ -e "$FILE_PATH" ]]; then
|
|
54
|
+
CHECK_DIR=$(dirname "$FILE_PATH")
|
|
55
|
+
else
|
|
56
|
+
# File doesn't exist yet — walk up to find an existing directory
|
|
57
|
+
CHECK_DIR=$(dirname "$FILE_PATH")
|
|
58
|
+
while [[ ! -d "$CHECK_DIR" ]] && [[ "$CHECK_DIR" != "/" ]]; do
|
|
59
|
+
CHECK_DIR=$(dirname "$CHECK_DIR")
|
|
60
|
+
done
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [[ ! -d "$CHECK_DIR" ]]; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Check if we're inside a git repository at all
|
|
68
|
+
GIT_DIR=$(cd "$CHECK_DIR" && git rev-parse --git-dir 2>/dev/null) || exit 0
|
|
69
|
+
|
|
70
|
+
# Make relative paths absolute
|
|
71
|
+
if [[ "$GIT_DIR" != /* ]]; then
|
|
72
|
+
GIT_DIR=$(cd "$CHECK_DIR" && cd "$GIT_DIR" && pwd) || exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# If git-dir contains /worktrees/, we're in a worktree — allow
|
|
76
|
+
if [[ "$GIT_DIR" == *".git/worktrees/"* ]]; then
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# We're in the main checkout — block
|
|
81
|
+
echo "❌ Blocked: Cannot modify files in the main checkout." >&2
|
|
82
|
+
echo " Create a worktree first: /worktree or /start <issue>" >&2
|
|
83
|
+
echo " File: $FILE_PATH" >&2
|
|
84
|
+
exit 2
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Skill(worktree)",
|
|
5
|
+
"Skill(start)",
|
|
6
|
+
"Bash(git worktree:*)",
|
|
7
|
+
"Bash(git stash:*)"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
"hooks": {
|
|
11
|
+
"PreToolUse": [
|
|
12
|
+
{
|
|
13
|
+
"matcher": "Edit|Write|NotebookEdit",
|
|
14
|
+
"hooks": [
|
|
15
|
+
{
|
|
16
|
+
"type": "command",
|
|
17
|
+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-worktree.sh",
|
|
18
|
+
"timeout": 10
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: publish-gem
|
|
3
|
+
description: "Publish a Ruby gem to RubyGems.org via CI. Use when the user says 'publish gem', 'push gem', 'release gem', or '/publish-gem'. Handles version bump, changelog, build verification, PR, tagging, and CI-driven publish."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Publish Gem Skill
|
|
7
|
+
|
|
8
|
+
Prepare and publish a Ruby gem to RubyGems.org via GitHub Actions trusted publishing.
|
|
9
|
+
|
|
10
|
+
Publishing is done by CI (not locally) — pushing a version tag triggers the `release.yml` workflow which builds the gem, creates a GitHub Release, and pushes to RubyGems via OIDC. This skill handles everything up to and including the tag push.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
/publish-gem # Full release flow
|
|
16
|
+
/publish-gem --dry-run # Verify everything, stop before PR creation
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
### 1. Verify Context
|
|
22
|
+
|
|
23
|
+
Confirm we're in a gem project:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Check current branch
|
|
27
|
+
git branch --show-current
|
|
28
|
+
|
|
29
|
+
# Must have a .gemspec file
|
|
30
|
+
ls *.gemspec
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Blockers:**
|
|
34
|
+
- No `.gemspec` found — stop, not a gem project
|
|
35
|
+
- Multiple `.gemspec` files found — ask the user which one to build
|
|
36
|
+
|
|
37
|
+
**Branch handling:**
|
|
38
|
+
- If not on `main`, switch automatically: `git checkout main` (publishing from non-main is almost never intentional). If the user explicitly requested publishing from a non-main branch, warn and ask for confirmation before switching.
|
|
39
|
+
- After switching (or if already on `main`), always sync with remote:
|
|
40
|
+
```bash
|
|
41
|
+
git pull --rebase origin main
|
|
42
|
+
```
|
|
43
|
+
- If the rebase fails due to conflicts, stop and ask the user to resolve them before proceeding
|
|
44
|
+
- After syncing, verify the working tree is clean (`git status --porcelain`). Warn if dirty — the build may include uncommitted changes.
|
|
45
|
+
- Clean up any stale `.gem` files in the working directory before proceeding:
|
|
46
|
+
```bash
|
|
47
|
+
rm -f *.gem
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Extract Gem Metadata
|
|
51
|
+
|
|
52
|
+
Read the gemspec to extract key details:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Get gem name and version
|
|
56
|
+
ruby -e "spec = Gem::Specification.load(Dir['*.gemspec'].first); puts \"#{spec.name} #{spec.version}\""
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Also read and display:
|
|
60
|
+
- Current version from the gemspec
|
|
61
|
+
- CHANGELOG.md entry for this version (if exists)
|
|
62
|
+
- `spec.files` count to verify packaging
|
|
63
|
+
|
|
64
|
+
### 3. Pre-Publish Checks
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Check if this version is already published on RubyGems.org
|
|
68
|
+
gem info -r <gem_name> -v <version>
|
|
69
|
+
|
|
70
|
+
# Check if CHANGELOG.md exists when gemspec references it
|
|
71
|
+
ruby -e "spec = Gem::Specification.load(Dir['*.gemspec'].first); puts spec.metadata['changelog_uri']"
|
|
72
|
+
test -f CHANGELOG.md && echo "CHANGELOG.md found" || echo "CHANGELOG.md missing"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Blockers:**
|
|
76
|
+
- Version already published — ask the user what version to bump to (suggest next patch/minor/major). If the user declines, abort the publish.
|
|
77
|
+
|
|
78
|
+
**Warnings:**
|
|
79
|
+
- Gemspec `changelog_uri` is set but `CHANGELOG.md` does not exist locally — warn the user. This will result in a broken link on RubyGems.org.
|
|
80
|
+
- CHANGELOG.md has no entry for the version being published — warn the user. The `release.yml` workflow will fail if no changelog entry exists for the version.
|
|
81
|
+
|
|
82
|
+
### 4. Version Bump (if needed)
|
|
83
|
+
|
|
84
|
+
When the current version is already published, or the user requests a bump:
|
|
85
|
+
|
|
86
|
+
1. Update `lib/<gem_name>/version.rb` with the new version
|
|
87
|
+
2. Run `bundle install` to sync `Gemfile.lock`
|
|
88
|
+
|
|
89
|
+
**Critical:** Always run `bundle install` after changing the version to keep `Gemfile.lock` in sync. Skipping this causes CI failures.
|
|
90
|
+
|
|
91
|
+
### 5. Update CHANGELOG.md
|
|
92
|
+
|
|
93
|
+
If the `[Unreleased]` section in CHANGELOG.md has content:
|
|
94
|
+
1. Rename `[Unreleased]` to `[<version>] - <today's date>` (format: YYYY-MM-DD)
|
|
95
|
+
2. Add a new empty `[Unreleased]` section above it
|
|
96
|
+
|
|
97
|
+
If `[Unreleased]` is empty, warn the user and ask if they want to proceed without changelog entries for this version.
|
|
98
|
+
|
|
99
|
+
### 6. Run Tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
bundle exec rspec
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Blockers:**
|
|
106
|
+
- Tests fail — stop and ask the user to fix. Do not proceed with a failing test suite.
|
|
107
|
+
|
|
108
|
+
### 7. Build Verification
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
gem build <name>.gemspec
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Verify the `.gem` file was created, show its size, then clean up:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
rm <name>-<version>.gem
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 8. Release Summary
|
|
121
|
+
|
|
122
|
+
Present a summary before proceeding:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
## Release Summary
|
|
126
|
+
|
|
127
|
+
Name: <gem_name>
|
|
128
|
+
Version: <version>
|
|
129
|
+
Files: <file count> files in gem
|
|
130
|
+
Registry: https://rubygems.org (published by CI via trusted publisher)
|
|
131
|
+
|
|
132
|
+
Changelog:
|
|
133
|
+
<first few lines of the version's CHANGELOG entry>
|
|
134
|
+
|
|
135
|
+
Next steps:
|
|
136
|
+
1. Create version bump PR
|
|
137
|
+
2. Merge PR (manual)
|
|
138
|
+
3. Tag release → CI publishes to RubyGems + creates GitHub Release
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If `--dry-run` was passed, stop here.
|
|
142
|
+
|
|
143
|
+
### 9. Create Version Bump PR
|
|
144
|
+
|
|
145
|
+
Commit the version bump, changelog, and lockfile on a branch and open a PR:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
git checkout -b chore/release-v<version>
|
|
149
|
+
git add lib/<gem_name>/version.rb Gemfile.lock CHANGELOG.md
|
|
150
|
+
git commit -m "chore: Release v<version>"
|
|
151
|
+
git push -u origin chore/release-v<version>
|
|
152
|
+
gh pr create --title "chore: Release v<version>" --body "$(cat <<'EOF'
|
|
153
|
+
## Release v<version>
|
|
154
|
+
|
|
155
|
+
<changelog entry for this version>
|
|
156
|
+
|
|
157
|
+
After merging, Claude will tag `v<version>` which triggers CI to:
|
|
158
|
+
- Create a GitHub Release with changelog notes
|
|
159
|
+
- Build and publish the gem to RubyGems.org via trusted publisher
|
|
160
|
+
EOF
|
|
161
|
+
)"
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Tell the user to review and merge the PR, then let you know when it's merged.
|
|
165
|
+
|
|
166
|
+
### 10. Tag the Release (after PR merge)
|
|
167
|
+
|
|
168
|
+
When the user confirms the PR is merged:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# Sync main — use reset to avoid divergent branch issues from squash merge
|
|
172
|
+
git checkout main
|
|
173
|
+
git fetch origin main
|
|
174
|
+
git reset --hard origin/main
|
|
175
|
+
|
|
176
|
+
# Tag the merged commit
|
|
177
|
+
git tag -a v<version> -m "Release v<version>"
|
|
178
|
+
git push origin v<version>
|
|
179
|
+
|
|
180
|
+
# Clean up the bump branch locally
|
|
181
|
+
# -D needed because squash merge doesn't preserve individual commits in main's history
|
|
182
|
+
git branch -D chore/release-v<version>
|
|
183
|
+
# Remote branch may already be deleted by GitHub's auto-delete setting — ignore errors
|
|
184
|
+
git push origin --delete chore/release-v<version> 2>/dev/null || true
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The tag push triggers `release.yml` which:
|
|
188
|
+
1. Verifies the tag version matches `version.rb`
|
|
189
|
+
2. Waits for CI to pass
|
|
190
|
+
3. Extracts changelog notes and creates a GitHub Release
|
|
191
|
+
4. Builds the gem and publishes to RubyGems.org via OIDC trusted publisher
|
|
192
|
+
|
|
193
|
+
### 11. Output
|
|
194
|
+
|
|
195
|
+
Report:
|
|
196
|
+
1. RubyGems URL: `https://rubygems.org/gems/<name>` (available after CI completes)
|
|
197
|
+
2. Git tag created: `v<version>`
|
|
198
|
+
3. GitHub Release + RubyGems publish: triggered by CI — link: `https://github.com/<owner>/<repo>/actions`
|
|
199
|
+
4. Remind: allow a few minutes for CI to complete, then the gem will appear on RubyGems and the GitHub Release will be created
|
|
200
|
+
|
|
201
|
+
## Error Handling
|
|
202
|
+
|
|
203
|
+
| Error | Solution |
|
|
204
|
+
|-------|----------|
|
|
205
|
+
| `gem build` fails | Fix gemspec errors and retry |
|
|
206
|
+
| Tests fail | Fix tests before proceeding |
|
|
207
|
+
| Tag already exists | Version was previously tagged — skip tagging |
|
|
208
|
+
| Tag push fails | Likely a permissions issue — report and continue |
|
|
209
|
+
| Remote branch already deleted | GitHub auto-deleted it — ignore the error |
|
|
210
|
+
| User declines version bump | Abort the publish |
|
|
211
|
+
| CI publish fails | Check the Actions tab — common causes: trusted publisher not configured on RubyGems.org, `rubygems` environment not set up in GitHub repo settings, or version mismatch between tag and version.rb |
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: start
|
|
3
|
+
description: "Start working on Linear issues. Use when the user says 'start working on', 'pick up issue', 'work on RAR-123', or wants to begin development on Linear issues. Handles status updates, branch creation, and context gathering."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Start Skill
|
|
7
|
+
|
|
8
|
+
Begin working on Linear issues with proper setup: update status, create branches, gather context, and track progress.
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
This skill requires the Linear MCP server to be configured. If Linear tools (`mcp__linear__*`) are not available, the skill will warn and offer to proceed with git-only setup (branch creation without status updates).
|
|
13
|
+
|
|
14
|
+
## Scope
|
|
15
|
+
|
|
16
|
+
This skill sets up local development for Linear issues. It does **NOT**:
|
|
17
|
+
- Merge PRs to main (merging is a human decision)
|
|
18
|
+
- Delete branches or worktrees automatically
|
|
19
|
+
- Close or complete Linear issues
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
/start <issue-identifiers...> # Start specific issues (e.g., /start RAR-123 RAR-124)
|
|
25
|
+
/start --mine # Show my assigned issues ready to start
|
|
26
|
+
/start --backlog # Show backlog issues for a team
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Workflow
|
|
30
|
+
|
|
31
|
+
> **Note:** MCP tool calls shown below use pseudocode syntax for readability.
|
|
32
|
+
> Actual invocation uses Claude's tool use API with the `mcp__linear__*` tools.
|
|
33
|
+
|
|
34
|
+
### 1. Parse Input and Fetch Issues
|
|
35
|
+
|
|
36
|
+
**If specific identifiers provided:**
|
|
37
|
+
|
|
38
|
+
Fetch each issue using Linear MCP:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
mcp__linear__get_issue(id: "RAR-123", includeRelations: true)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**If `--mine` flag:**
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
mcp__linear__list_issues(assignee: "me", state: "Todo", limit: 10)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**If `--backlog` flag (with optional `--team` and `--project` filters):**
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
mcp__linear__list_issues(
|
|
54
|
+
team: "<from --team flag, default: Rarebit>",
|
|
55
|
+
project: "<from --project flag, if provided>",
|
|
56
|
+
state: "Backlog",
|
|
57
|
+
limit: 10
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Present the issues and let the user select which to work on.
|
|
62
|
+
|
|
63
|
+
### 2. Pre-Work Checks
|
|
64
|
+
|
|
65
|
+
Before starting, verify:
|
|
66
|
+
|
|
67
|
+
**Check for blockers:**
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
# From get_issue with includeRelations: true
|
|
71
|
+
# Look at the blocking/blockedBy relations
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If blocked:
|
|
75
|
+
```
|
|
76
|
+
Warning: RAR-123 is blocked by:
|
|
77
|
+
- RAR-120: "Set up middleware" (In Progress)
|
|
78
|
+
|
|
79
|
+
Options:
|
|
80
|
+
1. Start anyway (work may be blocked)
|
|
81
|
+
2. Start the blocking issue instead
|
|
82
|
+
3. Cancel
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Check issue readiness:**
|
|
86
|
+
- Has description/acceptance criteria?
|
|
87
|
+
- Has assigned estimate?
|
|
88
|
+
|
|
89
|
+
If missing context, warn but allow proceeding.
|
|
90
|
+
|
|
91
|
+
### 3. Update Issue Status
|
|
92
|
+
|
|
93
|
+
**Skip this step if `--no-status` flag is provided.**
|
|
94
|
+
|
|
95
|
+
Update each issue to "In Progress":
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
mcp__linear__save_issue(
|
|
99
|
+
id: "<issue-uuid>",
|
|
100
|
+
stateId: "<in-progress-state-id>"
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The workflow should not block on Linear failures — local development can proceed.
|
|
105
|
+
|
|
106
|
+
### 4. Set Up Worktree
|
|
107
|
+
|
|
108
|
+
**Always create a worktree** to isolate this work from any other state in the repo. This prevents changes from different sessions bleeding into unrelated PRs.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@refs/remotes/origin/@@')
|
|
112
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
113
|
+
git fetch origin "$DEFAULT_BRANCH"
|
|
114
|
+
git worktree add .worktrees/<identifier> -b <branch-name> "origin/$DEFAULT_BRANCH"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**`--no-worktree` flag:** If the user explicitly passes `--no-worktree`, check the current state:
|
|
118
|
+
- On the default branch with a clean working tree → fall back to a simple branch:
|
|
119
|
+
```bash
|
|
120
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@refs/remotes/origin/@@')
|
|
121
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
122
|
+
git fetch origin "$DEFAULT_BRANCH"
|
|
123
|
+
git checkout -b <branch-name> "origin/$DEFAULT_BRANCH"
|
|
124
|
+
```
|
|
125
|
+
- Otherwise → **stop and report why**:
|
|
126
|
+
_"Cannot skip worktree: working tree has uncommitted changes (or is on a feature branch). Stash or commit your changes first, switch to the default branch, then re-run with `--no-worktree`."_
|
|
127
|
+
|
|
128
|
+
> **Note:** The previous version of this skill offered stash and branch-switch workflows. Those paths have been removed in favor of always using worktrees. If you prefer to stash instead, run `git stash push -m "WIP"` manually before `/start`.
|
|
129
|
+
|
|
130
|
+
See `/worktree` skill for full worktree conventions.
|
|
131
|
+
|
|
132
|
+
**Branch name format:**
|
|
133
|
+
|
|
134
|
+
Use Linear's `gitBranchName` field if available, or generate:
|
|
135
|
+
`{identifier}/{short-description}` (e.g., `rar-123/add-feature-name`)
|
|
136
|
+
|
|
137
|
+
**Worktree naming:** `.worktrees/<identifier>` (e.g., `.worktrees/rar-123`)
|
|
138
|
+
|
|
139
|
+
### 5. Display Issue Context
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
Starting: RAR-123
|
|
143
|
+
Issue: <title>
|
|
144
|
+
URL: https://linear.app/...
|
|
145
|
+
|
|
146
|
+
Description:
|
|
147
|
+
<full description>
|
|
148
|
+
|
|
149
|
+
Acceptance Criteria:
|
|
150
|
+
- [ ] ...
|
|
151
|
+
|
|
152
|
+
Branch: <branch-name>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 6. Create Initial Todo List
|
|
156
|
+
|
|
157
|
+
Based on the issue description, create a todo list to track progress.
|
|
158
|
+
|
|
159
|
+
## Flags Reference
|
|
160
|
+
|
|
161
|
+
| Flag | Description |
|
|
162
|
+
|------|-------------|
|
|
163
|
+
| `--mine` | List my assigned issues in Todo state |
|
|
164
|
+
| `--backlog` | List team backlog issues |
|
|
165
|
+
| `--no-worktree` | Skip worktree if on the default branch + clean; stops with error otherwise |
|
|
166
|
+
| `--no-status` | Skip status update (just create branch) |
|
|
167
|
+
| `--team <name>` | Filter by team (default: Rarebit) |
|
|
168
|
+
| `--project <name>` | Filter by project |
|
|
169
|
+
|
|
170
|
+
## Error Handling
|
|
171
|
+
|
|
172
|
+
| Error | Solution |
|
|
173
|
+
|-------|----------|
|
|
174
|
+
| Linear MCP unavailable | Warn and offer to proceed with just git setup |
|
|
175
|
+
| Issue not found | Verify identifier, check team access |
|
|
176
|
+
| Issue already in progress | Ask if user wants to continue anyway |
|
|
177
|
+
| Issue is done/canceled | Warn and suggest reopening or selecting different issue |
|
|
178
|
+
| Status update fails | Offer to continue with local setup, retry, or cancel |
|
|
179
|
+
| Branch already exists | Offer to checkout existing or create with suffix |
|
|
180
|
+
| Worktree already exists | Offer to use existing worktree or create with suffix |
|
|
181
|
+
|
|
182
|
+
## Integration with Other Skills
|
|
183
|
+
|
|
184
|
+
- After completing work, create a PR with `gh pr create`, or use `/publish-gem` when ready to release
|
|
185
|
+
- The branch naming convention ensures the Linear issue can be auto-detected from the branch
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: worktree
|
|
3
|
+
description: "Create an isolated worktree for new work. Always creates a worktree by default to prevent cross-contamination between sessions. Use at the start of any session, or when the user says 'worktree', 'isolate', 'fresh start', or 'new worktree'."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Worktree Skill
|
|
7
|
+
|
|
8
|
+
Creates an isolated worktree for new work. **Always creates a worktree by default** — this prevents changes from different work sessions bleeding into unrelated PRs.
|
|
9
|
+
|
|
10
|
+
## Why Worktree-by-Default
|
|
11
|
+
|
|
12
|
+
Every new piece of work gets its own worktree. This eliminates the most common source of cross-contamination: starting new work in a repo that has leftover state from a previous session (uncommitted changes, wrong branch, etc.). The only exception is when the user explicitly opts out.
|
|
13
|
+
|
|
14
|
+
> **Note:** The previous version of this skill offered a stash-based workflow. That path has been removed in favor of always using worktrees. If you prefer to stash instead, run `git stash push -m "WIP"` manually before invoking `/start` or `/worktree`.
|
|
15
|
+
|
|
16
|
+
## Why `.worktrees/`
|
|
17
|
+
|
|
18
|
+
Worktrees are created inside the repo at `.worktrees/<name>` (not under `.claude/worktrees/`). This ensures:
|
|
19
|
+
- Worktrees are accessible inside devcontainers (mounted at `/workspace/.worktrees/`)
|
|
20
|
+
- Consistent convention across all repos in the workspace
|
|
21
|
+
- The `.worktrees/` directory is gitignored in each repo
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/worktree # Create a worktree (always, regardless of state)
|
|
27
|
+
/worktree <name> # Create a named worktree directly
|
|
28
|
+
/worktree --stay # Skip worktree creation, work in current checkout
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
### Phase 1: Detect Current State
|
|
34
|
+
|
|
35
|
+
Gather the repo state (for reporting, not for deciding whether to create a worktree):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Current branch
|
|
39
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
40
|
+
|
|
41
|
+
# Default branch
|
|
42
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@refs/remotes/origin/@@')
|
|
43
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
44
|
+
|
|
45
|
+
# Uncommitted changes (staged + unstaged + untracked)
|
|
46
|
+
git status --porcelain
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Phase 2: Decision
|
|
50
|
+
|
|
51
|
+
**Default behavior:** Always create a worktree. Go straight to Phase 3 → Phase 4. Any uncommitted changes on the current branch are left untouched — the worktree is a separate checkout, so existing work is preserved exactly as-is.
|
|
52
|
+
|
|
53
|
+
**`--stay` flag:** Skip worktree creation and stay in the current checkout. This is for when the user explicitly wants to continue work on the current branch (e.g., resuming a previous session). If dirty state is detected, inform the user what's there but **do not stop** — the user is consciously choosing to stay. This differs from `/start --no-worktree`, which hard-stops on dirty state because starting new work on an unclean tree risks cross-contamination.
|
|
54
|
+
|
|
55
|
+
### Phase 3: Fetch Latest
|
|
56
|
+
|
|
57
|
+
Always fetch the latest default branch, regardless of whether a worktree will be created:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git fetch origin "$DEFAULT_BRANCH"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This ensures any new branch or worktree starts from the latest codebase.
|
|
64
|
+
|
|
65
|
+
### Phase 4: Create Worktree
|
|
66
|
+
|
|
67
|
+
**Naming convention:**
|
|
68
|
+
|
|
69
|
+
If a name is provided (e.g., from a Linear issue identifier):
|
|
70
|
+
```bash
|
|
71
|
+
git worktree add .worktrees/<name> -b <branch-name> "origin/$DEFAULT_BRANCH"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If no name is provided, generate one from context:
|
|
75
|
+
- If starting a Linear issue: use the issue identifier (e.g., `swe-123`)
|
|
76
|
+
- If the user described the task: use a short slug (e.g., `fix-auth-timeout`)
|
|
77
|
+
- Fallback: use today's date in `YYYY-MM-DD` format
|
|
78
|
+
|
|
79
|
+
**Ensure `.worktrees/` is gitignored:**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Check if .worktrees is already in .gitignore
|
|
83
|
+
if ! grep -q '\.worktrees' .gitignore 2>/dev/null; then
|
|
84
|
+
echo '.worktrees/' >> .gitignore
|
|
85
|
+
fi
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Phase 5: Report
|
|
89
|
+
|
|
90
|
+
After setup, display:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Worktree created at: .worktrees/<name>
|
|
94
|
+
Branch: <branch-name>
|
|
95
|
+
Based on: origin/$DEFAULT_BRANCH (fetched latest)
|
|
96
|
+
|
|
97
|
+
Previous state preserved:
|
|
98
|
+
Branch: <original-branch>
|
|
99
|
+
Changes: <summary of uncommitted changes left behind, if any>
|
|
100
|
+
|
|
101
|
+
Working directory: .worktrees/<name>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If `--stay` was used:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Staying in current checkout: <branch>
|
|
108
|
+
(fetched latest origin/$DEFAULT_BRANCH)
|
|
109
|
+
<summary of uncommitted changes, if any>
|
|
110
|
+
|
|
111
|
+
To create a new branch:
|
|
112
|
+
git checkout -b <branch-name> origin/$DEFAULT_BRANCH
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Integration with /start
|
|
116
|
+
|
|
117
|
+
The `/start` skill always creates a worktree as part of its workflow. Both skills follow the same conventions:
|
|
118
|
+
- Worktrees go in `.worktrees/`
|
|
119
|
+
- Always fetch latest before creating
|
|
120
|
+
- Naming follows the `<identifier>` convention (e.g., `.worktrees/swe-123`)
|
|
121
|
+
|
|
122
|
+
**Opt-out flags differ by context:**
|
|
123
|
+
- `/worktree --stay` — "stay in current checkout" (you invoked the worktree tool, you're opting out of its action; dirty state is allowed)
|
|
124
|
+
- `/start --no-worktree` — "don't create a worktree" (you're starting new work, skipping one aspect; dirty state causes a hard stop)
|
|
125
|
+
|
|
126
|
+
This `/worktree` skill can also be invoked independently when you want to isolate work without picking up a Linear issue.
|
|
127
|
+
|
|
128
|
+
## Error Handling
|
|
129
|
+
|
|
130
|
+
| Error | Solution |
|
|
131
|
+
|-------|----------|
|
|
132
|
+
| `.worktrees/<name>` already exists | Offer to reuse existing or create with suffix |
|
|
133
|
+
| Branch name already exists | Check out existing branch in the worktree instead of `-b` |
|
|
134
|
+
| No origin remote | Create worktree from local default branch HEAD |
|
|
135
|
+
| Fetch fails | Warn and create from local default branch HEAD |
|
|
136
|
+
| `.gitignore` is read-only | Warn the user to add `.worktrees/` manually |
|
|
137
|
+
|
|
138
|
+
## Safety Rules
|
|
139
|
+
|
|
140
|
+
1. **Never discard uncommitted changes** - the whole point is to preserve them
|
|
141
|
+
2. **Never force-checkout** over dirty state - always worktree instead
|
|
142
|
+
3. **Always fetch before creating** - worktrees should start from latest
|
|
143
|
+
4. **This skill only creates worktrees** - it does not remove or clean up stale ones
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
1
8
|
## [Unreleased]
|
|
2
9
|
|
|
10
|
+
## [0.2.0] - 2026-04-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Auto-register provider with StandardId via `Rails::Railtie` on `config.after_initialize`, so apps that bundle the gem no longer need an explicit initializer (#27)
|
|
15
|
+
|
|
16
|
+
## [0.1.2] - 2026-01-13
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Support nonce and passing custom parameters to Google Sign In (#1)
|
|
21
|
+
|
|
22
|
+
## [0.1.1] - 2025-12-24
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- Thread safety improvements
|
|
27
|
+
|
|
3
28
|
## [0.1.0] - 2025-12-20
|
|
4
29
|
|
|
5
|
-
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Initial release of Google Sign In provider plugin for StandardId
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Worktree-Only Workflow (Enforced)
|
|
4
|
+
|
|
5
|
+
**All file modifications are blocked in the main checkout.** A PreToolUse hook (`enforce-worktree.sh`) rejects Edit, Write, and NotebookEdit operations targeting files outside a worktree. There are no opt-outs. Do not use Bash to write files in the main checkout either (e.g., `echo >`, `sed -i`, `tee`, `cp`) — the hook cannot intercept shell commands, so this rule is instruction-enforced.
|
|
6
|
+
|
|
7
|
+
Before writing any code, create a worktree:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@refs/remotes/origin/@@')
|
|
11
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
12
|
+
git fetch origin "$DEFAULT_BRANCH"
|
|
13
|
+
git worktree add .worktrees/<name> -b <branch-name> "origin/$DEFAULT_BRANCH"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then work inside `.worktrees/<name>/` for the rest of the session.
|
|
17
|
+
|
|
18
|
+
**Naming:** Use the Linear issue identifier if available (e.g., `.worktrees/<identifier>`), a task slug (e.g., `.worktrees/fix-auth-timeout`), or today's date (e.g., `.worktrees/2026-04-01`) as fallback.
|
|
19
|
+
|
|
20
|
+
**The hook allows modifications only when:**
|
|
21
|
+
|
|
22
|
+
1. The file is inside a git worktree (detected via `git rev-parse --git-dir` returning a path under `.git/worktrees/`)
|
|
23
|
+
2. Running in a CI/automated context where the checkout is already isolated
|
|
24
|
+
**Why this matters:** Working directly on the main checkout causes cross-contamination between sessions — uncommitted changes, wrong branches, and dirty state leak into unrelated work. Worktrees eliminate this entirely.
|
|
25
|
+
|
|
26
|
+
See the `/worktree` and `/start` skills for full conventions and flags.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StandardId
|
|
4
|
+
module Google
|
|
5
|
+
class Railtie < ::Rails::Railtie
|
|
6
|
+
config.after_initialize do
|
|
7
|
+
StandardId::ProviderRegistry.register(:google, StandardId::Providers::Google)
|
|
8
|
+
|
|
9
|
+
Rails.logger.debug("[StandardId::Google] registered provider") if Rails.logger
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/standard_id/google.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: standard_id-google
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -43,32 +43,40 @@ dependencies:
|
|
|
43
43
|
- - ">="
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
45
|
version: 0.1.7
|
|
46
|
-
description: Extracted StandardId::Providers::
|
|
47
|
-
gem so StandardId installations can opt into Sign in with
|
|
46
|
+
description: Extracted StandardId::Providers::Google implementation packaged as a
|
|
47
|
+
standalone gem so StandardId installations can opt into Sign in with Google independently.
|
|
48
48
|
email:
|
|
49
49
|
- code@jaryl.dev
|
|
50
50
|
executables: []
|
|
51
51
|
extensions: []
|
|
52
52
|
extra_rdoc_files: []
|
|
53
53
|
files:
|
|
54
|
+
- ".claude/hooks/enforce-worktree.sh"
|
|
55
|
+
- ".claude/settings.json"
|
|
56
|
+
- ".claude/skills/publish-gem/SKILL.md"
|
|
57
|
+
- ".claude/skills/start/SKILL.md"
|
|
58
|
+
- ".claude/skills/worktree/SKILL.md"
|
|
54
59
|
- ".rspec"
|
|
55
60
|
- ".rubocop.yml"
|
|
56
61
|
- ".ruby-version"
|
|
57
62
|
- CHANGELOG.md
|
|
63
|
+
- CLAUDE.md
|
|
58
64
|
- CODE_OF_CONDUCT.md
|
|
59
65
|
- LICENSE.txt
|
|
60
66
|
- README.md
|
|
61
67
|
- Rakefile
|
|
62
68
|
- lib/standard_id/google.rb
|
|
63
69
|
- lib/standard_id/google/providers/google.rb
|
|
70
|
+
- lib/standard_id/google/railtie.rb
|
|
64
71
|
- lib/standard_id/google/version.rb
|
|
65
|
-
homepage: https://github.com/rarebit-one/
|
|
72
|
+
homepage: https://github.com/rarebit-one/standard_id_google
|
|
66
73
|
licenses:
|
|
67
74
|
- MIT
|
|
68
75
|
metadata:
|
|
69
|
-
homepage_uri: https://github.com/rarebit-one/
|
|
70
|
-
source_code_uri: https://github.com/rarebit-one/
|
|
71
|
-
changelog_uri: https://github.com/rarebit-one/
|
|
76
|
+
homepage_uri: https://github.com/rarebit-one/standard_id_google
|
|
77
|
+
source_code_uri: https://github.com/rarebit-one/standard_id_google
|
|
78
|
+
changelog_uri: https://github.com/rarebit-one/standard_id_google/blob/main/CHANGELOG.md
|
|
79
|
+
bug_tracker_uri: https://github.com/rarebit-one/standard_id_google/issues
|
|
72
80
|
rdoc_options: []
|
|
73
81
|
require_paths:
|
|
74
82
|
- lib
|
|
@@ -83,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
83
91
|
- !ruby/object:Gem::Version
|
|
84
92
|
version: '0'
|
|
85
93
|
requirements: []
|
|
86
|
-
rubygems_version:
|
|
94
|
+
rubygems_version: 4.0.3
|
|
87
95
|
specification_version: 4
|
|
88
96
|
summary: Google Sign In provider plugin for the StandardId engine.
|
|
89
97
|
test_files: []
|