@speclife/cli 0.9.0 → 0.9.1
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.
- package/package.json +1 -1
- package/templates/commands/convert.md +22 -159
- package/templates/commands/land.md +20 -241
- package/templates/commands/release.md +19 -114
- package/templates/commands/retrofit.md +21 -303
- package/templates/commands/setup.md +20 -292
- package/templates/commands/ship.md +17 -162
- package/templates/commands/start.md +17 -269
- package/templates/commands/sync.md +16 -164
|
@@ -4,165 +4,20 @@ id: speclife-ship
|
|
|
4
4
|
category: SpecLife
|
|
5
5
|
description: Commit changes, push to remote, and create a PR for review.
|
|
6
6
|
---
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/speclife ship # Ship current branch
|
|
25
|
-
/speclife ship --draft # Create as draft PR
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Quick flow:**
|
|
29
|
-
1. Detect branch type (spec vs ad-hoc)
|
|
30
|
-
2. For spec branches: validate → commit changes → archive → commit archive
|
|
31
|
-
3. For ad-hoc branches: stage, commit
|
|
32
|
-
4. Push, create/update PR
|
|
33
|
-
|
|
34
|
-
## Mode Detection
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
BRANCH=$(git branch --show-current)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
| Branch | Type | Behavior |
|
|
41
|
-
|--------|------|----------|
|
|
42
|
-
| `spec/*` | **Spec** | Full workflow with OpenSpec (validate, archive) |
|
|
43
|
-
| Any other non-main | **Ad-hoc** | Simplified (skip spec steps) |
|
|
44
|
-
| `main` | **Error** | Cannot ship from main |
|
|
45
|
-
|
|
46
|
-
Note: Spec mode is determined by branch name prefix (`spec/`), not worktree existence. Works identically whether you're in a worktree or the main repo.
|
|
47
|
-
|
|
48
|
-
## Core Steps
|
|
49
|
-
|
|
50
|
-
### 1. Spec Branch Only
|
|
51
|
-
If spec branch detected:
|
|
52
|
-
- Run `openspec validate <change-id>`
|
|
53
|
-
- Read proposal.md for commit message
|
|
54
|
-
- Commit the implementation changes:
|
|
55
|
-
```bash
|
|
56
|
-
git add -A
|
|
57
|
-
git commit -m "<type>: <description>"
|
|
58
|
-
```
|
|
59
|
-
- Run `/openspec-archive` (may require updating project.md)
|
|
60
|
-
- Commit the archive changes:
|
|
61
|
-
```bash
|
|
62
|
-
git add -A
|
|
63
|
-
git commit -m "chore: archive <change-id> spec"
|
|
64
|
-
```
|
|
65
|
-
- Skip to step 3 (push only, no additional commit needed)
|
|
66
|
-
|
|
67
|
-
### 2. Ad-hoc Branch Only
|
|
68
|
-
- Infer commit type from branch name (`fix/*` → `fix:`, `feat/*` → `feat:`)
|
|
69
|
-
- Ask user for commit message if needed
|
|
70
|
-
|
|
71
|
-
### 3. All Branches
|
|
72
|
-
```bash
|
|
73
|
-
# For ad-hoc branches only (spec branches already committed above):
|
|
74
|
-
git add -A
|
|
75
|
-
git commit -m "<type>: <description>" # if uncommitted changes
|
|
76
|
-
|
|
77
|
-
# All branches:
|
|
78
|
-
git push -u origin <branch>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### 4. Create PR
|
|
82
|
-
```bash
|
|
83
|
-
# Check if PR exists
|
|
84
|
-
gh pr view --json url 2>/dev/null
|
|
85
|
-
|
|
86
|
-
# If not, create
|
|
87
|
-
gh pr create --fill --base main
|
|
88
|
-
# Or: gh pr create --fill --base main --draft
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 5. Report and STOP
|
|
92
|
-
```
|
|
93
|
-
✓ Committed: "feat: description"
|
|
94
|
-
✓ Pushed to origin/<branch>
|
|
95
|
-
✓ Created PR #42: <url>
|
|
96
|
-
|
|
97
|
-
Next: After approval, run /speclife land
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
**⛔ STOP HERE.** Do NOT proceed to merge. Wait for:
|
|
101
|
-
1. PR review and approval
|
|
102
|
-
2. User to invoke `/speclife land`
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
<!-- REFERENCE SECTIONS - Read only when needed -->
|
|
107
|
-
|
|
108
|
-
## Appendix: Commit Type Inference
|
|
109
|
-
|
|
110
|
-
| Branch Pattern | Commit Type |
|
|
111
|
-
|----------------|-------------|
|
|
112
|
-
| `fix/*`, `bugfix/*`, `hotfix/*` | `fix:` |
|
|
113
|
-
| `feat/*`, `feature/*` | `feat:` |
|
|
114
|
-
| `docs/*` | `docs:` |
|
|
115
|
-
| `refactor/*` | `refactor:` |
|
|
116
|
-
| `chore/*` | `chore:` |
|
|
117
|
-
| Other | Ask user |
|
|
118
|
-
|
|
119
|
-
## Appendix: Error Handling
|
|
120
|
-
|
|
121
|
-
**Cannot ship from main:**
|
|
122
|
-
```
|
|
123
|
-
❌ Cannot ship from main. Create a branch first.
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**No changes:**
|
|
127
|
-
```
|
|
128
|
-
❌ No changes to ship. Working directory clean.
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
**Spec validation failed:**
|
|
132
|
-
```
|
|
133
|
-
❌ Spec validation failed:
|
|
134
|
-
- proposal.md: Missing "What" section
|
|
135
|
-
Fix issues and retry, or use --skip-validation
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
**PR already exists:**
|
|
139
|
-
```
|
|
140
|
-
ℹ️ PR #43 already exists. Pushing updates...
|
|
141
|
-
✓ Updated PR #43
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
## Appendix: Examples
|
|
145
|
-
|
|
146
|
-
**Spec branch:**
|
|
147
|
-
```
|
|
148
|
-
User: /speclife ship
|
|
149
|
-
|
|
150
|
-
Agent:
|
|
151
|
-
ℹ️ Spec branch: spec/add-oauth-login
|
|
152
|
-
✓ Validated spec
|
|
153
|
-
✓ Committed: "feat: add OAuth login"
|
|
154
|
-
✓ Archived to openspec/changes/archive/
|
|
155
|
-
✓ Committed: "chore: archive add-oauth-login spec"
|
|
156
|
-
✓ Pushed to origin/spec/add-oauth-login
|
|
157
|
-
✓ Created PR #42
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**Ad-hoc branch:**
|
|
161
|
-
```
|
|
162
|
-
User: /speclife ship
|
|
163
|
-
|
|
164
|
-
Agent:
|
|
165
|
-
ℹ️ Ad-hoc branch: fix/login-bug
|
|
166
|
-
✓ Committed: "fix: resolve login redirect"
|
|
167
|
-
✓ Created PR #43
|
|
168
|
-
```
|
|
7
|
+
**Guardrails**
|
|
8
|
+
- Execute immediately—do not ask for confirmation
|
|
9
|
+
- Detect branch type: `spec/*` = full OpenSpec workflow, other non-main = ad-hoc, `main` = error
|
|
10
|
+
- STOP after PR created—do NOT auto-invoke `/speclife land`
|
|
11
|
+
|
|
12
|
+
**Steps**
|
|
13
|
+
1. For spec branches: run `openspec validate <id>`, commit changes, run `openspec archive <id> --yes`, commit archive.
|
|
14
|
+
2. For ad-hoc branches: infer commit type from branch name (`fix/*` → `fix:`, `feat/*` → `feat:`), ask if ambiguous.
|
|
15
|
+
3. Push branch: `git push -u origin <branch>`.
|
|
16
|
+
4. Create/update PR: `gh pr create --title "<type>: <description>" --body "<body>" --base main` (add `--draft` if requested).
|
|
17
|
+
5. Report: commits made, branch pushed, PR URL. Next: `/speclife land` after approval.
|
|
18
|
+
|
|
19
|
+
**Reference**
|
|
20
|
+
- Commit type inference: fix/bugfix/hotfix → `fix:`, feat/feature → `feat:`, docs → `docs:`, refactor → `refactor:`, chore → `chore:`
|
|
21
|
+
- If PR exists, push updates it automatically
|
|
22
|
+
- PR title: use conventional commit format (`<type>: <meaningful description>`)
|
|
23
|
+
- PR body: if `.github/pull_request_template.md` exists, read it and fill in each section based on the change context
|
|
@@ -4,272 +4,20 @@ id: speclife-start
|
|
|
4
4
|
category: SpecLife
|
|
5
5
|
description: Create a new branch for a change, optionally in a worktree for parallel work.
|
|
6
6
|
---
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/speclife start <description> # New proposal, worktree (default)
|
|
25
|
-
/speclife start <description> in a branch # New proposal, branch-only
|
|
26
|
-
/speclife start "resume <change-id>" # Resume existing proposal, worktree
|
|
27
|
-
/speclife start "implement <change-id>" # Resume if exists, create if not
|
|
28
|
-
/speclife start # Interactive
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Goal
|
|
32
|
-
|
|
33
|
-
Set up a workspace for a new change with proper git branch.
|
|
34
|
-
|
|
35
|
-
## Mode Detection
|
|
36
|
-
|
|
37
|
-
Parse the input for workflow hints in this order:
|
|
38
|
-
|
|
39
|
-
### 1. Resume Intent Detection
|
|
40
|
-
|
|
41
|
-
| Phrase in input | Meaning |
|
|
42
|
-
|-----------------|---------|
|
|
43
|
-
| "resume <change-id>", "continue <change-id>", "pick up <change-id>" | **Resume existing proposal** (error if not found) |
|
|
44
|
-
| "implement <change-id>" | **Resume if exists**, create new if not |
|
|
45
|
-
|
|
46
|
-
Examples:
|
|
47
|
-
- `"resume fix-release-and-init"` → resume mode, change-id = `fix-release-and-init`
|
|
48
|
-
- `"continue working on add-oauth-login"` → resume mode, change-id = `add-oauth-login`
|
|
49
|
-
- `"implement fix-email-validation"` → try resume, fallback to new
|
|
50
|
-
|
|
51
|
-
### 2. Worktree Mode Detection
|
|
52
|
-
|
|
53
|
-
| Phrase in input | Mode |
|
|
54
|
-
|-----------------|------|
|
|
55
|
-
| "in a branch", "branch only", "no worktree", "simple" | **Branch-only** |
|
|
56
|
-
| "in a worktree", "with worktree", "parallel" | **Worktree** |
|
|
57
|
-
| Neither | **Worktree** (default) |
|
|
58
|
-
|
|
59
|
-
### 3. Parsing Order
|
|
60
|
-
|
|
61
|
-
1. Check for resume keywords → extract change-id
|
|
62
|
-
2. Check for mode keywords → determine worktree/branch
|
|
63
|
-
3. Strip workflow hints → derive description (new proposals only)
|
|
64
|
-
|
|
65
|
-
Examples:
|
|
66
|
-
- `"resume fix-bug in a branch"` → resume mode, branch-only
|
|
67
|
-
- `"implement oauth with worktree"` → resume/new mode, worktree
|
|
68
|
-
|
|
69
|
-
## Steps
|
|
70
|
-
|
|
71
|
-
### 1. Check for Resume Intent
|
|
72
|
-
|
|
73
|
-
Parse input for resume keywords (`resume`, `continue`, `pick up`, `implement`):
|
|
74
|
-
|
|
75
|
-
**If resume intent detected:**
|
|
76
|
-
```bash
|
|
77
|
-
CHANGE_ID=<extracted-from-input> # e.g., "fix-release-and-init"
|
|
78
|
-
PROPOSAL_DIR="openspec/changes/${CHANGE_ID}"
|
|
79
|
-
|
|
80
|
-
if [[ ! -d "$PROPOSAL_DIR" ]]; then
|
|
81
|
-
echo "❌ Proposal '${CHANGE_ID}' not found"
|
|
82
|
-
echo ""
|
|
83
|
-
echo "Available proposals:"
|
|
84
|
-
ls -1 openspec/changes/ | grep -v archive
|
|
85
|
-
exit 1
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
echo "✓ Found existing proposal at ${PROPOSAL_DIR}/"
|
|
89
|
-
# Skip to step 3 (create branch/worktree)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
**If "implement" keyword and proposal doesn't exist:**
|
|
93
|
-
- Continue as new proposal (steps 2-5)
|
|
94
|
-
|
|
95
|
-
**If no resume intent:**
|
|
96
|
-
- Continue to step 2
|
|
97
|
-
|
|
98
|
-
### 2. Derive change-id (New Proposals Only)
|
|
99
|
-
|
|
100
|
-
Convert description to kebab-case:
|
|
101
|
-
- "Add user authentication" → `add-user-auth`
|
|
102
|
-
- Prefix with verb: add-, fix-, update-, remove-, refactor-
|
|
103
|
-
- Keep it short (3-5 words max)
|
|
104
|
-
|
|
105
|
-
### 3. Create branch/worktree
|
|
106
|
-
|
|
107
|
-
**Branch-only mode:**
|
|
108
|
-
```bash
|
|
109
|
-
git checkout -b spec/<change-id>
|
|
110
|
-
```
|
|
111
|
-
- Works in current directory
|
|
112
|
-
- One change at a time (switch branches to context-switch)
|
|
113
|
-
|
|
114
|
-
**Worktree mode (default):**
|
|
115
|
-
```bash
|
|
116
|
-
speclife worktree create <change-id>
|
|
117
|
-
```
|
|
118
|
-
- Creates `worktrees/<change-id>/`
|
|
119
|
-
- Creates branch `spec/<change-id>`
|
|
120
|
-
- Parallel changes possible
|
|
121
|
-
|
|
122
|
-
### 4. Scaffold proposal (New Proposals Only)
|
|
123
|
-
|
|
124
|
-
**Skip this step if resuming an existing proposal.**
|
|
125
|
-
|
|
126
|
-
Invoke `/openspec-proposal` with the description (minus workflow hints)
|
|
127
|
-
- Creates `openspec/changes/<change-id>/proposal.md`
|
|
128
|
-
- Creates `openspec/changes/<change-id>/tasks.md`
|
|
129
|
-
|
|
130
|
-
### 5. Report and STOP
|
|
131
|
-
|
|
132
|
-
**New Proposal - Branch-only:**
|
|
133
|
-
```
|
|
134
|
-
✓ Derived change-id: add-oauth-login
|
|
135
|
-
✓ Created branch spec/add-oauth-login
|
|
136
|
-
✓ Scaffolded proposal at openspec/changes/add-oauth-login/
|
|
137
|
-
|
|
138
|
-
Next: Review the proposal, then run `/openspec-apply` to implement.
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
**New Proposal - Worktree:**
|
|
142
|
-
```
|
|
143
|
-
✓ Derived change-id: add-oauth-login
|
|
144
|
-
✓ Created worktree at worktrees/add-oauth-login/
|
|
145
|
-
✓ Created branch spec/add-oauth-login
|
|
146
|
-
✓ Scaffolded proposal at openspec/changes/add-oauth-login/
|
|
147
|
-
|
|
148
|
-
⚠️ IMPORTANT: You must work from the worktree directory!
|
|
149
|
-
|
|
150
|
-
Next steps:
|
|
151
|
-
1. Switch to worktree: cd worktrees/add-oauth-login/
|
|
152
|
-
2. Invoke /openspec-apply from there
|
|
153
|
-
|
|
154
|
-
🚨 CRITICAL: All file edits MUST happen in:
|
|
155
|
-
worktrees/add-oauth-login/openspec/...
|
|
156
|
-
worktrees/add-oauth-login/packages/...
|
|
157
|
-
|
|
158
|
-
NOT in the main repo paths!
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**Resume Proposal - Branch-only:**
|
|
162
|
-
```
|
|
163
|
-
✓ Found existing proposal at openspec/changes/fix-release-and-init/
|
|
164
|
-
✓ Created branch spec/fix-release-and-init
|
|
165
|
-
ℹ️ Proposal already defined - ready to implement
|
|
166
|
-
|
|
167
|
-
Next: Run `/openspec-apply` to implement tasks.
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**Resume Proposal - Worktree:**
|
|
171
|
-
```
|
|
172
|
-
✓ Found existing proposal at openspec/changes/fix-release-and-init/
|
|
173
|
-
✓ Created worktree at worktrees/fix-release-and-init/
|
|
174
|
-
✓ Created branch spec/fix-release-and-init
|
|
175
|
-
ℹ️ Proposal already defined - ready to implement
|
|
176
|
-
|
|
177
|
-
Next: cd worktrees/fix-release-and-init/ then run `/openspec-apply`.
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**⛔ STOP HERE.** Do NOT proceed to implementation. Wait for user to:
|
|
181
|
-
1. Review the proposal (if new)
|
|
182
|
-
2. Switch to worktree directory (if worktree mode)
|
|
183
|
-
3. Invoke `/openspec-apply` or `/speclife implement`
|
|
184
|
-
|
|
185
|
-
## Examples
|
|
186
|
-
|
|
187
|
-
**New proposals:**
|
|
188
|
-
```
|
|
189
|
-
User: /speclife start "Add OAuth login support"
|
|
190
|
-
→ Creates worktree (default), scaffolds new proposal
|
|
191
|
-
|
|
192
|
-
User: /speclife start "Add OAuth login" in a branch
|
|
193
|
-
→ Creates branch only, scaffolds new proposal
|
|
194
|
-
|
|
195
|
-
User: /speclife start "fix login bug" branch only
|
|
196
|
-
→ Creates branch only, scaffolds new proposal
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
**Resume existing proposals:**
|
|
200
|
-
```
|
|
201
|
-
User: /speclife start "resume fix-release-and-init"
|
|
202
|
-
→ Creates worktree, uses existing proposal
|
|
203
|
-
|
|
204
|
-
User: /speclife start "continue working on add-oauth-login"
|
|
205
|
-
→ Creates worktree, uses existing proposal
|
|
206
|
-
|
|
207
|
-
User: /speclife start "pick up fix-email-validation in a branch"
|
|
208
|
-
→ Creates branch only, uses existing proposal
|
|
209
|
-
|
|
210
|
-
User: /speclife start "implement add-user-auth"
|
|
211
|
-
→ If proposal exists: resumes it
|
|
212
|
-
→ If not: creates new proposal
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
**Error case:**
|
|
216
|
-
```
|
|
217
|
-
User: /speclife start "resume nonexistent-change"
|
|
218
|
-
|
|
219
|
-
Agent:
|
|
220
|
-
❌ Proposal 'nonexistent-change' not found
|
|
221
|
-
|
|
222
|
-
Available proposals:
|
|
223
|
-
fix-release-and-init
|
|
224
|
-
add-oauth-login
|
|
225
|
-
fix-email-validation
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Interactive:**
|
|
229
|
-
```
|
|
230
|
-
User: /speclife start
|
|
231
|
-
→ Prompts: "Describe your change" then "Worktree (default) or branch-only?"
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
## Tradeoffs
|
|
235
|
-
|
|
236
|
-
| Aspect | Worktree | Branch-only |
|
|
237
|
-
|--------|----------|-------------|
|
|
238
|
-
| Parallel changes | ✓ Multiple worktrees | One at a time |
|
|
239
|
-
| IDE support | May need reload | Seamless |
|
|
240
|
-
| Setup complexity | More dirs | Simpler |
|
|
241
|
-
| Context switching | cd to worktree | git checkout |
|
|
242
|
-
|
|
243
|
-
## Naming Conventions
|
|
244
|
-
|
|
245
|
-
- Use kebab-case for change-id
|
|
246
|
-
- Prefix with action verb: `add-`, `fix-`, `update-`, `remove-`, `refactor-`
|
|
247
|
-
- Keep it descriptive but concise
|
|
248
|
-
- Examples:
|
|
249
|
-
- `add-user-auth`
|
|
250
|
-
- `fix-login-redirect`
|
|
251
|
-
- `update-api-docs`
|
|
252
|
-
- `remove-deprecated-endpoint`
|
|
253
|
-
- `refactor-database-layer`
|
|
254
|
-
|
|
255
|
-
## Notes
|
|
256
|
-
|
|
257
|
-
### General
|
|
258
|
-
- Branch name is always `spec/<change-id>` regardless of mode
|
|
259
|
-
- If branch exists, error and suggest using existing
|
|
260
|
-
- Branch-only: uncommitted changes carry over (stash if needed)
|
|
261
|
-
- Worktree: clean checkout from main
|
|
262
|
-
- To switch modes later, use `/speclife convert`
|
|
263
|
-
|
|
264
|
-
### Resume Behavior
|
|
265
|
-
- Resume keywords: `resume`, `continue`, `pick up`, `implement`
|
|
266
|
-
- Proposals must exist in `openspec/changes/<change-id>/`
|
|
267
|
-
- Archived proposals are not searched (move from archive first if needed)
|
|
268
|
-
- Resume skips `/openspec-proposal` scaffolding
|
|
269
|
-
- "implement" keyword tries resume first, creates new if not found
|
|
270
|
-
- Combine with mode: "resume X in a branch" or "resume X with worktree"
|
|
271
|
-
|
|
272
|
-
### Next Steps
|
|
273
|
-
- After creating new proposal: Review, refine, then `/openspec-apply`
|
|
274
|
-
- After resuming proposal: Directly run `/openspec-apply` to implement tasks
|
|
275
|
-
- Both workflows converge at implementation phase
|
|
7
|
+
**Guardrails**
|
|
8
|
+
- Execute immediately when invoked
|
|
9
|
+
- Parse input for resume keywords (`resume`, `continue`, `pick up`, `implement <id>`)
|
|
10
|
+
- Parse for mode keywords: "in a branch" → branch-only, otherwise → worktree (default)
|
|
11
|
+
- STOP after scaffolding—do NOT auto-invoke `/openspec-apply`
|
|
12
|
+
|
|
13
|
+
**Steps**
|
|
14
|
+
1. If resume intent detected, verify `openspec/changes/<id>/` exists; error with available proposals if not found.
|
|
15
|
+
2. For new proposals: derive kebab-case change-id from description (prefix: add-, fix-, update-, remove-, refactor-).
|
|
16
|
+
3. Create workspace: branch-only → `git checkout -b spec/<id>`, worktree → `speclife worktree create <id>`.
|
|
17
|
+
4. For new proposals only: scaffold `proposal.md` and `tasks.md` under `openspec/changes/<id>/` (follow `/openspec-proposal` for format), then run `openspec validate <id> --strict`.
|
|
18
|
+
5. Report: change-id, branch/worktree created, path to work directory. If worktree, emphasize: "All edits must happen in worktrees/<id>/".
|
|
19
|
+
|
|
20
|
+
**Reference**
|
|
21
|
+
- Branch name always `spec/<change-id>` regardless of mode
|
|
22
|
+
- Resume skips proposal scaffolding; proceed directly to `/openspec-apply`
|
|
23
|
+
- Use `/speclife convert` to switch modes later
|
|
@@ -4,167 +4,19 @@ id: speclife-sync
|
|
|
4
4
|
category: SpecLife
|
|
5
5
|
description: Update current branch with latest changes from main.
|
|
6
6
|
---
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/speclife sync # Rebase onto main (default)
|
|
24
|
-
/speclife sync --merge # Merge main into branch
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Quick flow:**
|
|
28
|
-
1. Check prerequisites (not on main, clean working dir)
|
|
29
|
-
2. Fetch latest
|
|
30
|
-
3. Rebase or merge
|
|
31
|
-
4. Handle conflicts if any
|
|
32
|
-
5. Force push (if rebased)
|
|
33
|
-
|
|
34
|
-
## Prerequisites
|
|
35
|
-
|
|
36
|
-
- Not on main branch
|
|
37
|
-
- Working directory clean (commit or stash first)
|
|
38
|
-
|
|
39
|
-
## Core Steps
|
|
40
|
-
|
|
41
|
-
### 1. Check State
|
|
42
|
-
```bash
|
|
43
|
-
BRANCH=$(git branch --show-current)
|
|
44
|
-
[[ "$BRANCH" == "main" ]] && echo "Already on main" && exit
|
|
45
|
-
|
|
46
|
-
# Check for uncommitted changes
|
|
47
|
-
[[ -n $(git status --porcelain) ]] && echo "Commit or stash changes first"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 2. Fetch & Check
|
|
51
|
-
```bash
|
|
52
|
-
git fetch origin main
|
|
53
|
-
BEHIND=$(git rev-list --count HEAD..origin/main)
|
|
54
|
-
[[ "$BEHIND" == "0" ]] && echo "Already up to date" && exit
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### 3. Rebase (default) or Merge
|
|
58
|
-
```bash
|
|
59
|
-
# Rebase (cleaner history)
|
|
60
|
-
git rebase origin/main
|
|
61
|
-
|
|
62
|
-
# Or merge (preserves history)
|
|
63
|
-
git merge origin/main
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 4. Handle Conflicts
|
|
67
|
-
If conflicts:
|
|
68
|
-
```bash
|
|
69
|
-
# List conflicts
|
|
70
|
-
git diff --name-only --diff-filter=U
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Tell user:
|
|
74
|
-
```
|
|
75
|
-
⚠️ Conflicts in 3 files:
|
|
76
|
-
- src/auth/login.ts
|
|
77
|
-
- package.json
|
|
78
|
-
|
|
79
|
-
To resolve:
|
|
80
|
-
1. Edit files, remove <<<<<<< ======= >>>>>>> markers
|
|
81
|
-
2. git add <resolved-files>
|
|
82
|
-
3. git rebase --continue
|
|
83
|
-
|
|
84
|
-
Or abort: git rebase --abort
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### 5. Push
|
|
88
|
-
```bash
|
|
89
|
-
# After rebase (force required)
|
|
90
|
-
git push --force-with-lease origin <branch>
|
|
91
|
-
|
|
92
|
-
# After merge (normal push)
|
|
93
|
-
git push origin <branch>
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
### 6. Report
|
|
97
|
-
```
|
|
98
|
-
✓ Rebased onto main (5 commits)
|
|
99
|
-
✓ No conflicts
|
|
100
|
-
✓ Pushed
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
<!-- REFERENCE SECTIONS - Read only when needed -->
|
|
106
|
-
|
|
107
|
-
## Appendix: Conflict Resolution
|
|
108
|
-
|
|
109
|
-
**Conflict markers:**
|
|
110
|
-
```
|
|
111
|
-
<<<<<<< HEAD (yours)
|
|
112
|
-
const timeout = 5000;
|
|
113
|
-
=======
|
|
114
|
-
const timeout = 10000;
|
|
115
|
-
>>>>>>> origin/main (theirs)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Resolution strategies:**
|
|
119
|
-
- Keep yours: delete their section + markers
|
|
120
|
-
- Keep theirs: delete your section + markers
|
|
121
|
-
- Combine: merge logic, delete markers
|
|
122
|
-
|
|
123
|
-
**Common conflicts:**
|
|
124
|
-
- `package.json` version → keep higher (main)
|
|
125
|
-
- Import conflicts → combine imports
|
|
126
|
-
|
|
127
|
-
## Appendix: Error Handling
|
|
128
|
-
|
|
129
|
-
**On main:**
|
|
130
|
-
```
|
|
131
|
-
ℹ️ Already on main - nothing to sync.
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
**Uncommitted changes:**
|
|
135
|
-
```
|
|
136
|
-
⚠️ Uncommitted changes detected.
|
|
137
|
-
Commit or stash, then retry.
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
**Rebase in progress:**
|
|
141
|
-
```
|
|
142
|
-
⚠️ Rebase already in progress.
|
|
143
|
-
Continue: git rebase --continue
|
|
144
|
-
Abort: git rebase --abort
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Appendix: Examples
|
|
148
|
-
|
|
149
|
-
**Clean sync:**
|
|
150
|
-
```
|
|
151
|
-
User: /speclife sync
|
|
152
|
-
|
|
153
|
-
Agent:
|
|
154
|
-
✓ Fetched latest
|
|
155
|
-
ℹ️ 3 commits behind main
|
|
156
|
-
✓ Rebased - no conflicts
|
|
157
|
-
✓ Force pushed
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
**With conflicts:**
|
|
161
|
-
```
|
|
162
|
-
User: /speclife sync
|
|
163
|
-
|
|
164
|
-
Agent:
|
|
165
|
-
⚠️ Conflicts in 2 files:
|
|
166
|
-
- src/auth.ts
|
|
167
|
-
- package.json
|
|
168
|
-
|
|
169
|
-
[Offers to help resolve]
|
|
170
|
-
```
|
|
7
|
+
**Guardrails**
|
|
8
|
+
- Execute immediately—default to rebase unless `--merge` specified
|
|
9
|
+
- Require: not on main, working directory clean
|
|
10
|
+
- Guide user through conflict resolution if any
|
|
11
|
+
|
|
12
|
+
**Steps**
|
|
13
|
+
1. Check state: error if on main or uncommitted changes exist.
|
|
14
|
+
2. Fetch and check: `git fetch origin main`; if already up to date, report and exit.
|
|
15
|
+
3. Rebase (default) or merge: `git rebase origin/main` or `git merge origin/main`.
|
|
16
|
+
4. If conflicts: list conflicting files, explain resolution (edit files, `git add`, `git rebase --continue`), offer to help resolve.
|
|
17
|
+
5. Push: `git push --force-with-lease` (rebase) or `git push` (merge).
|
|
18
|
+
6. Report: commits synced, conflicts resolved (if any), pushed.
|
|
19
|
+
|
|
20
|
+
**Reference**
|
|
21
|
+
- Conflict markers: `<<<<<<< HEAD`, `=======`, `>>>>>>> origin/main`
|
|
22
|
+
- Abort rebase: `git rebase --abort`
|