@ulysses-ai/create-workspace 0.13.0-beta.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.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/bin/create.mjs +79 -0
- package/lib/git.mjs +26 -0
- package/lib/init.mjs +129 -0
- package/lib/payload.mjs +44 -0
- package/lib/prompts.mjs +113 -0
- package/lib/scaffold.mjs +84 -0
- package/lib/upgrade.mjs +42 -0
- package/package.json +43 -0
- package/template/.claude/agents/aside-researcher.md +48 -0
- package/template/.claude/agents/implementer.md +39 -0
- package/template/.claude/agents/researcher.md +40 -0
- package/template/.claude/agents/reviewer.md +47 -0
- package/template/.claude/hooks/_utils.mjs +196 -0
- package/template/.claude/hooks/_utils.test.mjs +99 -0
- package/template/.claude/hooks/post-compact.mjs +7 -0
- package/template/.claude/hooks/pre-compact.mjs +34 -0
- package/template/.claude/hooks/repo-write-detection.mjs +107 -0
- package/template/.claude/hooks/session-end.mjs +91 -0
- package/template/.claude/hooks/session-start.mjs +150 -0
- package/template/.claude/hooks/subagent-start.mjs +44 -0
- package/template/.claude/hooks/workspace-update-check.mjs +42 -0
- package/template/.claude/hooks/worktree-create.mjs +53 -0
- package/template/.claude/lib/session-frontmatter.mjs +265 -0
- package/template/.claude/lib/session-frontmatter.test.mjs +242 -0
- package/template/.claude/recipes/migrate-from-notion.md +120 -0
- package/template/.claude/rules/agent-rules.md.skip +32 -0
- package/template/.claude/rules/cloud-infrastructure.md.skip +15 -0
- package/template/.claude/rules/coherent-revisions.md +24 -0
- package/template/.claude/rules/documentation.md.skip +13 -0
- package/template/.claude/rules/git-conventions.md +34 -0
- package/template/.claude/rules/honest-pushback.md +56 -0
- package/template/.claude/rules/local-dev-environment.md.skip +60 -0
- package/template/.claude/rules/memory-guidance.md +26 -0
- package/template/.claude/rules/product-integrity.md.skip +24 -0
- package/template/.claude/rules/scope-guard.md.skip +22 -0
- package/template/.claude/rules/superpowers-workflow.md.skip +22 -0
- package/template/.claude/rules/token-economics.md.skip +31 -0
- package/template/.claude/rules/work-item-tracking.md +90 -0
- package/template/.claude/rules/workspace-structure.md +69 -0
- package/template/.claude/scripts/add-repo-to-session.mjs +78 -0
- package/template/.claude/scripts/cleanup-work-session.mjs +108 -0
- package/template/.claude/scripts/create-work-session.mjs +124 -0
- package/template/.claude/scripts/migrate-open-work.mjs +91 -0
- package/template/.claude/scripts/migrate-session-layout.mjs +236 -0
- package/template/.claude/scripts/migrate-session-layout.test.mjs +144 -0
- package/template/.claude/scripts/trackers/github-issues.mjs +170 -0
- package/template/.claude/scripts/trackers/github-issues.test.mjs +190 -0
- package/template/.claude/scripts/trackers/interface.mjs +25 -0
- package/template/.claude/scripts/trackers/interface.test.mjs +40 -0
- package/template/.claude/settings.json +107 -0
- package/template/.claude/skills/aside/SKILL.md +125 -0
- package/template/.claude/skills/braindump/SKILL.md +96 -0
- package/template/.claude/skills/build-docs-site/SKILL.md +323 -0
- package/template/.claude/skills/build-docs-site/checklists/framing.md +221 -0
- package/template/.claude/skills/build-docs-site/checklists/pitfalls.md +228 -0
- package/template/.claude/skills/build-docs-site/checklists/review.md +130 -0
- package/template/.claude/skills/build-docs-site/scripts/bulk-fill-migration.py +393 -0
- package/template/.claude/skills/build-docs-site/scripts/forbidden-word-grep.mjs +159 -0
- package/template/.claude/skills/build-docs-site/scripts/leak-grep.mjs +328 -0
- package/template/.claude/skills/build-docs-site/templates/custom.css.tmpl +212 -0
- package/template/.claude/skills/build-docs-site/templates/docusaurus.config.ts.tmpl +95 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/Arrow.tsx +87 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/Box.tsx +90 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/DiagramContainer.tsx +46 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/Region.tsx +68 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/SectionTitle.tsx +42 -0
- package/template/.claude/skills/build-docs-site/templates/primitives/tokens.ts +67 -0
- package/template/.claude/skills/build-docs-site/templates/sidebars.ts.tmpl +89 -0
- package/template/.claude/skills/build-docs-site/templates/spec.md.tmpl +119 -0
- package/template/.claude/skills/complete-work/SKILL.md +369 -0
- package/template/.claude/skills/handoff/SKILL.md +98 -0
- package/template/.claude/skills/maintenance/SKILL.md +116 -0
- package/template/.claude/skills/pause-work/SKILL.md +98 -0
- package/template/.claude/skills/promote/SKILL.md +77 -0
- package/template/.claude/skills/release/SKILL.md +126 -0
- package/template/.claude/skills/setup-tracker/SKILL.md +117 -0
- package/template/.claude/skills/start-work/SKILL.md +234 -0
- package/template/.claude/skills/sync-work/SKILL.md +73 -0
- package/template/.claude/skills/workspace-init/SKILL.md +420 -0
- package/template/.claude/skills/workspace-update/SKILL.md +108 -0
- package/template/.mcp.json +12 -0
- package/template/CLAUDE.md.tmpl +32 -0
- package/template/_gitignore +28 -0
- package/template/workspace.json.tmpl +15 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: complete-work
|
|
3
|
+
description: Finalize a work session — rebase, synthesize release notes from spec/plan/session tracker/commits, create PRs with unified presentation. Handles all project repos and workspace repo. Use when work on a session is done.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Complete Work
|
|
7
|
+
|
|
8
|
+
Finalize the active work session. Handles all project repos (code changes, release notes, PRs) and the workspace repo (context processing, PR). Presents a unified summary with a single merge approval, then tears down the session folder.
|
|
9
|
+
|
|
10
|
+
## Flow
|
|
11
|
+
|
|
12
|
+
### Step 1: Detect context
|
|
13
|
+
|
|
14
|
+
Read the active-session pointer from `.claude/.active-session.json` in the current worktree.
|
|
15
|
+
If no active session: "No active work session. Nothing to complete."
|
|
16
|
+
|
|
17
|
+
Read the full session tracker at `work-sessions/{session-name}/workspace/session.md` (use the frontmatter helper in `.claude/lib/session-frontmatter.mjs` — scripts and hooks use `_utils.mjs` which wraps it).
|
|
18
|
+
|
|
19
|
+
Determine paths:
|
|
20
|
+
- Session folder: `work-sessions/{session-name}/`
|
|
21
|
+
- Workspace worktree: `work-sessions/{session-name}/workspace/`
|
|
22
|
+
- Project worktrees: `work-sessions/{session-name}/workspace/repos/{repo}/` for each repo in the tracker's `repos:` list
|
|
23
|
+
- Read each repo's default branch from workspace.json (`repos.{repo}.branch`)
|
|
24
|
+
|
|
25
|
+
### Step 2: Rebase project repos
|
|
26
|
+
|
|
27
|
+
For each repo in the tracker's `repos:`:
|
|
28
|
+
```bash
|
|
29
|
+
# {repo-branch} = repos.{repo}.branch from workspace.json
|
|
30
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
31
|
+
git fetch origin
|
|
32
|
+
git rebase origin/{repo-branch}
|
|
33
|
+
```
|
|
34
|
+
If conflicts arise in any repo, STOP and present them to the user. Do not auto-resolve.
|
|
35
|
+
|
|
36
|
+
### Step 3: Capture final discussion state
|
|
37
|
+
|
|
38
|
+
Run `/braindump` to capture any final discussion/reasoning to the session tracker body.
|
|
39
|
+
If the user declines or there's nothing to capture, skip.
|
|
40
|
+
|
|
41
|
+
### Step 4: Gather source material
|
|
42
|
+
|
|
43
|
+
Formally read ALL sources before synthesizing — do not write release notes from memory alone:
|
|
44
|
+
|
|
45
|
+
1. **Session tracker** at `work-sessions/{session-name}/workspace/session.md` — read the full body (frontmatter is machine state, body is human content)
|
|
46
|
+
|
|
47
|
+
2. **Session-scoped specs/plans** at the top of the session worktree:
|
|
48
|
+
- `work-sessions/{session-name}/workspace/design-*.md` files
|
|
49
|
+
- `work-sessions/{session-name}/workspace/plan-*.md` files
|
|
50
|
+
- Read each one fully
|
|
51
|
+
|
|
52
|
+
3. **Handoffs** — any shared-context entries referencing this branch:
|
|
53
|
+
```bash
|
|
54
|
+
grep -rl "branch: {branch}" shared-context/
|
|
55
|
+
```
|
|
56
|
+
Read each matching file.
|
|
57
|
+
|
|
58
|
+
4. **Branch commit logs** (per repo):
|
|
59
|
+
```bash
|
|
60
|
+
# For each repo in the tracker's repos list:
|
|
61
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
62
|
+
git log origin/{repo-branch}..HEAD --oneline
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Step 5: Synthesize release notes
|
|
66
|
+
|
|
67
|
+
For each repo in the tracker's `repos:` list that has commits beyond the base branch:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
71
|
+
COMMIT_ID=$(git rev-parse --short HEAD)
|
|
72
|
+
mkdir -p release-notes/unreleased
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**File 1: `release-notes/unreleased/branch-release-notes-{COMMIT_ID}.md`**
|
|
76
|
+
```markdown
|
|
77
|
+
---
|
|
78
|
+
branch: {branch}
|
|
79
|
+
type: {feature|fix|chore}
|
|
80
|
+
author: {user}
|
|
81
|
+
date: {YYYY-MM-DD}
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## {Human-readable title}
|
|
85
|
+
|
|
86
|
+
{Coherent narrative synthesized from tracker + spec + plan + commits.
|
|
87
|
+
Written from scratch per coherent-revisions rule.}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**File 2: `release-notes/unreleased/branch-release-questions-{COMMIT_ID}.md`**
|
|
91
|
+
```markdown
|
|
92
|
+
---
|
|
93
|
+
branch: {branch}
|
|
94
|
+
author: {user}
|
|
95
|
+
date: {YYYY-MM-DD}
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Open Questions
|
|
99
|
+
|
|
100
|
+
{Only genuinely open questions — not things resolved during implementation.}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Commit per repo:
|
|
104
|
+
```bash
|
|
105
|
+
git add release-notes/unreleased/
|
|
106
|
+
git commit -m "docs: add release notes for {branch}"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
If a repo has no commits beyond the base, skip release notes for it.
|
|
110
|
+
|
|
111
|
+
### Step 6: Consume session-scoped sources
|
|
112
|
+
|
|
113
|
+
The entire `work-sessions/{session-name}/` folder is removed by the cleanup script in Step 11. Before that happens, make sure everything worth preserving has landed in release notes.
|
|
114
|
+
|
|
115
|
+
No separate "consume spec and plan" commit is needed for the project repos — specs and plans now live in the session folder, not in the project worktrees. The project worktrees only carry source code changes.
|
|
116
|
+
|
|
117
|
+
### Step 6c: Remove session artifacts from the workspace branch
|
|
118
|
+
|
|
119
|
+
Session content (tracker, specs, plans) lives at the top of the workspace worktree on the session branch. Its purpose was synthesis into release notes in Step 5 — that work is now done. Remove the files from the branch before the final push so main's top level stays free of session artifacts:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
cd work-sessions/{session-name}/workspace
|
|
123
|
+
git rm -f session.md 2>/dev/null || true
|
|
124
|
+
git rm -f design-*.md 2>/dev/null || true
|
|
125
|
+
git rm -f plan-*.md 2>/dev/null || true
|
|
126
|
+
git commit -m "chore: remove session artifacts before PR" 2>/dev/null || true
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The `|| true` guards keep this idempotent — if a file is already gone (e.g., a session without specs), the step is a no-op. The commit is skipped when there's nothing staged.
|
|
130
|
+
|
|
131
|
+
This commit persists in the branch's history. On squash merge or rebase merge, branch history collapses to one clean commit on main with no session artifacts. On merge commits, branch history is reachable but the final tree on main shows no session content.
|
|
132
|
+
|
|
133
|
+
### Step 6b: Version bump (if applicable)
|
|
134
|
+
|
|
135
|
+
For each repo in the tracker's `repos:`, check if the repo has versioning:
|
|
136
|
+
```bash
|
|
137
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
138
|
+
cat package.json 2>/dev/null | grep '"version"'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If no `package.json` or no `version` field: skip this repo — no versioning to manage.
|
|
142
|
+
|
|
143
|
+
If the repo has a version, determine the appropriate bump from the release notes just written:
|
|
144
|
+
|
|
145
|
+
1. Read the `type:` field from the branch release notes created in Step 5
|
|
146
|
+
2. Determine the bump:
|
|
147
|
+
- `type: fix` or `type: chore` → **patch** (auto-bump, no confirmation needed)
|
|
148
|
+
- `type: feature` → **minor** (present to user: "This session adds new functionality. Suggested bump: {current} → {next-minor}. Confirm or adjust?")
|
|
149
|
+
- Breaking changes detected (schema changes, removed APIs, convention changes) → **major** (present to user: "This session includes breaking changes. Suggested bump: {current} → {next-major}. Confirm or adjust?")
|
|
150
|
+
|
|
151
|
+
3. Apply the bump:
|
|
152
|
+
```bash
|
|
153
|
+
git add package.json
|
|
154
|
+
git commit -m "chore: bump version to {new-version}"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The user can override any suggestion. Accept their decision.
|
|
158
|
+
|
|
159
|
+
### Step 7: Detect remote type per repo
|
|
160
|
+
|
|
161
|
+
For each repo in the tracker's `repos:` plus the workspace repo, determine the remote type. This drives how Step 8 and Step 9 push and merge.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
165
|
+
git remote get-url origin 2>&1
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Classify the result:
|
|
169
|
+
|
|
170
|
+
- **GitHub remote** — URL contains `github.com` or `gh repo view` succeeds against origin → use the PR flow (Step 8a, Step 9a).
|
|
171
|
+
- **Local / bare remote** — URL is a filesystem path (starts with `/`, `./`, `file://`, or points at a `.git` bare mirror) → use the local merge flow (Step 8b, Step 9b).
|
|
172
|
+
- **Other remote** (e.g., GitLab, Bitbucket, self-hosted) — no `gh` support → fall back to the local merge flow (Step 8b, Step 9b), and mention it in the final summary.
|
|
173
|
+
- **No remote at all** — "No remote configured for {repo}. Want me to create one on GitHub, add an existing URL, or keep the session local (push/merge inside the local clone only)?" Act on the user's choice. Never silently skip push.
|
|
174
|
+
|
|
175
|
+
### Step 8: Push all repos
|
|
176
|
+
|
|
177
|
+
#### Step 8a: GitHub remotes
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Each project repo with a GitHub remote
|
|
181
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
182
|
+
git push -u origin {branch}
|
|
183
|
+
|
|
184
|
+
# Workspace repo — from the workspace worktree
|
|
185
|
+
cd work-sessions/{session-name}/workspace
|
|
186
|
+
git add .
|
|
187
|
+
git commit -m "chore: finalize context for {session-name}"
|
|
188
|
+
git push -u origin {branch}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Step 8b: Local/bare remotes
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Push the feature branch to the bare remote so it exists there
|
|
195
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
196
|
+
git push -u origin {branch}
|
|
197
|
+
|
|
198
|
+
# Workspace repo — same commit + push pattern
|
|
199
|
+
cd work-sessions/{session-name}/workspace
|
|
200
|
+
git add .
|
|
201
|
+
git commit -m "chore: finalize context for {session-name}"
|
|
202
|
+
git push -u origin {branch}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The push shape is the same as 8a — what differs is the merge mechanics in Step 9b.
|
|
206
|
+
|
|
207
|
+
### Step 9: Merge and present unified summary
|
|
208
|
+
|
|
209
|
+
#### Step 9a: GitHub remotes — create PRs, unified summary, merge
|
|
210
|
+
|
|
211
|
+
Create one PR per project repo plus one workspace PR:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# For each repo in the tracker's repos with a GitHub remote:
|
|
215
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
216
|
+
gh pr create --title "{type}: {description}" --body "..."
|
|
217
|
+
|
|
218
|
+
# Workspace PR — from the workspace worktree
|
|
219
|
+
cd work-sessions/{session-name}/workspace
|
|
220
|
+
gh pr create --title "context: {session-name} work session" --body "..."
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Present unified summary:
|
|
224
|
+
```
|
|
225
|
+
Work session complete:
|
|
226
|
+
|
|
227
|
+
PROJECT: {repo-1}
|
|
228
|
+
PR #{n}: {type}: {description}
|
|
229
|
+
Branch: {branch} → {repo-1-branch}
|
|
230
|
+
Changes:
|
|
231
|
+
- {bullet points from release notes}
|
|
232
|
+
Release notes: branch-release-notes-{COMMIT_ID}.md
|
|
233
|
+
|
|
234
|
+
PROJECT: {repo-2}
|
|
235
|
+
PR #{m}: {type}: {description}
|
|
236
|
+
Branch: {branch} → {repo-2-branch}
|
|
237
|
+
Changes:
|
|
238
|
+
- {bullet points from release notes}
|
|
239
|
+
|
|
240
|
+
WORKSPACE: {workspace-name}
|
|
241
|
+
PR #{p}: context: {session-name} work session
|
|
242
|
+
Branch: {branch} → main
|
|
243
|
+
|
|
244
|
+
Merge all? [Y/n]
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
If yes — merge all PRs atomically:
|
|
248
|
+
```bash
|
|
249
|
+
# For each project PR:
|
|
250
|
+
gh pr merge {pr-number} --merge
|
|
251
|
+
|
|
252
|
+
# Workspace PR:
|
|
253
|
+
gh pr merge {workspace-pr-number} --merge
|
|
254
|
+
|
|
255
|
+
# Pull all repos to their default branches
|
|
256
|
+
# For each repo in the tracker's repos:
|
|
257
|
+
cd repos/{repo} && git pull origin {repo-branch}
|
|
258
|
+
cd {main-workspace-root} && git pull origin main
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### Step 9b: Local / bare / other remotes — local merge flow
|
|
262
|
+
|
|
263
|
+
No PRs are created — these remotes don't have a PR concept (or we don't have a client wired up for them). Present an adjusted summary:
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
Work session complete:
|
|
267
|
+
|
|
268
|
+
PROJECT: {repo-1} (local remote)
|
|
269
|
+
Branch: {branch} → {repo-1-branch}
|
|
270
|
+
Changes:
|
|
271
|
+
- {bullet points from release notes}
|
|
272
|
+
Release notes: branch-release-notes-{COMMIT_ID}.md
|
|
273
|
+
|
|
274
|
+
PROJECT: {repo-2} (local remote)
|
|
275
|
+
Branch: {branch} → {repo-2-branch}
|
|
276
|
+
Changes:
|
|
277
|
+
- {bullet points from release notes}
|
|
278
|
+
|
|
279
|
+
WORKSPACE: {workspace-name} (local remote)
|
|
280
|
+
Branch: {branch} → main
|
|
281
|
+
|
|
282
|
+
Merge all locally? [Y/n]
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
If yes — fast-forward merge on each remote, delete the feature branch, pull the source clone:
|
|
286
|
+
```bash
|
|
287
|
+
# For each repo in the tracker's repos with a local/bare remote:
|
|
288
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
289
|
+
git push origin HEAD:{repo-branch} # fast-forward the default branch
|
|
290
|
+
git push origin --delete {branch} # remove the feature branch from the remote
|
|
291
|
+
cd repos/{repo} && git checkout {repo-branch} && git pull origin {repo-branch}
|
|
292
|
+
|
|
293
|
+
# Workspace repo — same pattern from the workspace worktree
|
|
294
|
+
cd work-sessions/{session-name}/workspace
|
|
295
|
+
git push origin HEAD:main
|
|
296
|
+
git push origin --delete {branch}
|
|
297
|
+
cd {main-workspace-root} && git pull origin main
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
If the fast-forward push fails because the remote's default branch has moved ahead, STOP and present the divergence — the user decides whether to rebase and retry or handle it another way. Do not auto-resolve.
|
|
301
|
+
|
|
302
|
+
For repos with no remote at all (user chose "keep local"): skip push entirely. The branch lives only in the source clone after cleanup merges it:
|
|
303
|
+
```bash
|
|
304
|
+
cd repos/{repo} && git merge --ff-only {branch}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Step 10: Close the linked issue on the tracker
|
|
308
|
+
|
|
309
|
+
If the session tracker has a `workItem:` field AND `workspace.tracker` is configured, close the linked issue via the adapter after all PRs have merged:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
import { createTracker } from './.claude/scripts/trackers/interface.mjs';
|
|
313
|
+
import { readFileSync } from 'node:fs';
|
|
314
|
+
const ws = JSON.parse(readFileSync('workspace.json', 'utf-8'));
|
|
315
|
+
if (ws.workspace?.tracker) {
|
|
316
|
+
const tracker = createTracker(ws.workspace.tracker);
|
|
317
|
+
const comment = [
|
|
318
|
+
`**Completed by @${currentUser}**`,
|
|
319
|
+
'',
|
|
320
|
+
'Merged PRs:',
|
|
321
|
+
...mergedPrs.map(p => `- ${p.repo}: ${p.url}`),
|
|
322
|
+
'',
|
|
323
|
+
releaseSummary, // 1-3 sentence synthesis of what shipped, drawn from release notes
|
|
324
|
+
].join('\n');
|
|
325
|
+
await tracker.closeIssue(workItem, { comment });
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
If `workItem:` is unset, skip the close — this was a blank session.
|
|
330
|
+
|
|
331
|
+
If the close call fails (tracker unreachable, auth expired), report the error in the unified summary but do not block Step 11 cleanup. The issue can be closed manually via the GitHub UI; no data is at risk.
|
|
332
|
+
|
|
333
|
+
### Step 11: Cleanup
|
|
334
|
+
|
|
335
|
+
Run the cleanup helper script from the main workspace root:
|
|
336
|
+
```bash
|
|
337
|
+
node .claude/scripts/cleanup-work-session.mjs --session-name "{session-name}"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
The script tears down in the **mandatory** order:
|
|
341
|
+
1. Remove each nested project worktree from its project repo
|
|
342
|
+
2. Remove the workspace worktree from the workspace repo
|
|
343
|
+
3. `git worktree prune` on each project repo (belt-and-suspenders for orphan records)
|
|
344
|
+
4. Delete local branches in all repos
|
|
345
|
+
5. `rm -rf work-sessions/{session-name}/` — the tracker, specs, plans, and any local-only artifacts vanish. Their content was already archived into release notes in Step 5.
|
|
346
|
+
|
|
347
|
+
Workspace-first removal silently deletes the nested project worktrees' `.git` files and leaves orphan worktree records in the project repos. The script enforces the safe order.
|
|
348
|
+
|
|
349
|
+
Verify workspace root is still on main:
|
|
350
|
+
```bash
|
|
351
|
+
git branch --show-current # should be "main"
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Handling Unformal Work Sessions
|
|
355
|
+
|
|
356
|
+
If /complete-work is called but changes were made without a formal work session (no branch, changes on default branch):
|
|
357
|
+
|
|
358
|
+
Ask: "These changes weren't part of a formal work session. What do you want to do?"
|
|
359
|
+
- **Accept as work** — create a session retroactively, proceed with normal completion
|
|
360
|
+
- **Stash for later** — create a user-scoped handoff describing what was done, stash the changes
|
|
361
|
+
- **Hand off to someone** — create a team-visible handoff at root shared-context/ for another member to pick up
|
|
362
|
+
- **Revert** — undo the changes (with confirmation)
|
|
363
|
+
|
|
364
|
+
## Notes
|
|
365
|
+
- Release notes live in the PROJECT repo worktrees — never the workspace
|
|
366
|
+
- The session tracker's body is the primary source for release note synthesis — it captures the full session history alongside specs and plans
|
|
367
|
+
- All repos get PRed and merged together — one approval for all
|
|
368
|
+
- The teardown order is mandatory: project worktrees first, then workspace worktree, then prune, then delete the session folder
|
|
369
|
+
- Context consumption, cleanup, and auto-committing release notes are intentional workflow behavior — these bypass normal commit conventions by design
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: handoff
|
|
3
|
+
description: Save workstream state as shared context. Use anytime during work to capture progress, decisions, and next steps. Accepts optional name parameter.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Handoff
|
|
7
|
+
|
|
8
|
+
Save structured workstream state to shared context. Usable anytime, any number of times. User-scoped by default.
|
|
9
|
+
|
|
10
|
+
## Parameters
|
|
11
|
+
- `/handoff {name}` — create or update a named handoff
|
|
12
|
+
- `/handoff` (no param) — analyze session and suggest name(s)
|
|
13
|
+
|
|
14
|
+
## Session-Aware Behavior
|
|
15
|
+
|
|
16
|
+
When called within an active work session (the active-session pointer at `.claude/.active-session.json` exists inside the current worktree):
|
|
17
|
+
|
|
18
|
+
- Default behavior: update the session tracker body at `work-sessions/{session-name}/workspace/session.md`
|
|
19
|
+
- Rewrite the tracker's `## Progress` section with current state (coherent-revisions rule)
|
|
20
|
+
- Do NOT touch the frontmatter — it's machine state managed by hooks and scripts
|
|
21
|
+
- Skip the naming and scoping questions — the tracker is already scoped to this session
|
|
22
|
+
- Auto-commit from inside the worktree so the update lands on the session branch:
|
|
23
|
+
```bash
|
|
24
|
+
cd work-sessions/{session-name}/workspace
|
|
25
|
+
git add session.md
|
|
26
|
+
git commit -m "handoff: update {session-name} tracker"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
When called from the workspace root (no active session):
|
|
30
|
+
- Only `local-only-*` files are writable from the root
|
|
31
|
+
- Suggest starting a work session first, or create a `local-only-{name}.md` file
|
|
32
|
+
|
|
33
|
+
The flows below apply when NOT in an active work session, or when the user explicitly asks for a standalone handoff file.
|
|
34
|
+
|
|
35
|
+
## Flow: Named
|
|
36
|
+
|
|
37
|
+
1. Read workspace user identity from `.claude/settings.local.json` (`workspace.user`)
|
|
38
|
+
2. Check if handoff already exists in `shared-context/{user}/` or `shared-context/` root
|
|
39
|
+
3. If exists: read it, prepare to update with current session state
|
|
40
|
+
4. If new: prepare to create
|
|
41
|
+
5. Ask: "Should this be user-scoped (default), team-visible, or local-only?"
|
|
42
|
+
- User-scoped (default): `shared-context/{user}/{name}.md`
|
|
43
|
+
- Team-visible: `shared-context/{name}.md`
|
|
44
|
+
- Local-only: `shared-context/local-only-{name}.md`
|
|
45
|
+
6. Write the handoff file:
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
---
|
|
49
|
+
state: ephemeral
|
|
50
|
+
lifecycle: active
|
|
51
|
+
type: handoff
|
|
52
|
+
topic: {name}
|
|
53
|
+
branch: {current-branch-if-any}
|
|
54
|
+
repo: {current-repo-if-any}
|
|
55
|
+
author: {user}
|
|
56
|
+
updated: {YYYY-MM-DD}
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Status
|
|
60
|
+
{What was accomplished in this session}
|
|
61
|
+
|
|
62
|
+
## Key Decisions
|
|
63
|
+
{Important choices made and their rationale}
|
|
64
|
+
|
|
65
|
+
## Next Steps
|
|
66
|
+
- [ ] {Specific next actions}
|
|
67
|
+
|
|
68
|
+
## Open Questions
|
|
69
|
+
{Unresolved questions, if any}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
7. Auto-commit the handoff file alone:
|
|
73
|
+
```bash
|
|
74
|
+
git add shared-context/{path-to-file}
|
|
75
|
+
git commit -m "handoff: {name}"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Flow: No Parameter
|
|
79
|
+
|
|
80
|
+
1. Analyze the current session: what topics have been discussed?
|
|
81
|
+
2. If one clear topic: suggest a name, ask to confirm
|
|
82
|
+
3. If multiple topics are conflated: "I see work on {topic-1} and {topic-2}. Split into separate handoffs?"
|
|
83
|
+
- If yes: run the named flow for each topic
|
|
84
|
+
- If no: ask for a single name that covers both
|
|
85
|
+
4. Proceed with the named flow for each handoff
|
|
86
|
+
|
|
87
|
+
## Updating Existing Handoffs
|
|
88
|
+
|
|
89
|
+
When updating an existing handoff, rewrite it as a fresh snapshot of current understanding (coherent-revisions rule). Don't append below the old content. The updated handoff should read as if written in one pass reflecting the current state.
|
|
90
|
+
|
|
91
|
+
Update the `updated` date in frontmatter. Keep the `lifecycle` as-is unless the user indicates a change.
|
|
92
|
+
|
|
93
|
+
## Notes
|
|
94
|
+
- User-scoped is the default — root is only for content deliberately made team-visible
|
|
95
|
+
- Handoffs are always committed individually — never bundled with code commits
|
|
96
|
+
- One topic, one file — don't let handoffs become grab-bags
|
|
97
|
+
- Name before writing — the name forces you to identify the single topic
|
|
98
|
+
- Auto-committing context files without user request is a workflow artifact — this intentionally bypasses the "do not commit unless asked" convention, not the "committed individually" constraint above
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maintenance
|
|
3
|
+
description: Workspace maintenance — audit integrity, clean up stale context, suggest merges. Run periodically or before /release.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Maintenance
|
|
7
|
+
|
|
8
|
+
Keep the workspace healthy. Combines integrity auditing with active cleanup recommendations.
|
|
9
|
+
|
|
10
|
+
## Parameters
|
|
11
|
+
- `/maintenance` — full run (audit + cleanup)
|
|
12
|
+
- `/maintenance audit` — integrity checks only (read-only)
|
|
13
|
+
- `/maintenance cleanup` — stale context, suggested merges, reconciliation only
|
|
14
|
+
|
|
15
|
+
## Audit
|
|
16
|
+
|
|
17
|
+
Read-only integrity checks. Reports problems but never modifies files.
|
|
18
|
+
|
|
19
|
+
### 1. Cross-reference consistency
|
|
20
|
+
Scan all shared-context files against each other:
|
|
21
|
+
- **Stale references** — file A mentions "2 mandatory rules" but there are now 4
|
|
22
|
+
- **Path references** — file A mentions a file that was moved or deleted
|
|
23
|
+
- **Contradictions** — file A says "user-scoped is default" but file B says "root is default"
|
|
24
|
+
|
|
25
|
+
### 2. Frontmatter integrity
|
|
26
|
+
For each shared-context `.md` file and each `work-sessions/*/workspace/session.md`:
|
|
27
|
+
- Valid frontmatter? (state, lifecycle, type, topic, author, updated; plus name/status/branch/repos for session trackers)
|
|
28
|
+
- `branch` field references a branch that still exists?
|
|
29
|
+
- `repo`/`repos` field references repos that exist in workspace.json?
|
|
30
|
+
- `lifecycle: active` on a file not updated in 7+ days? (stale candidate)
|
|
31
|
+
- `lifecycle: resolved` files that should have been processed by /complete-work?
|
|
32
|
+
- Session tracker `status: active` but the workspace worktree at `work-sessions/{name}/workspace/` is missing? (orphaned)
|
|
33
|
+
|
|
34
|
+
### 3. Workspace structure
|
|
35
|
+
- Actual directory layout matches what workspace-structure rule describes?
|
|
36
|
+
- CLAUDE.md references skills and rules that actually exist?
|
|
37
|
+
- Orphaned rules or skills not referenced anywhere?
|
|
38
|
+
- workspace.json repos all present in `repos/`?
|
|
39
|
+
|
|
40
|
+
### 4. Git state
|
|
41
|
+
- Worktrees with no recent commits? (orphaned)
|
|
42
|
+
- Local branches with no remote tracking? (unpushed work)
|
|
43
|
+
- Worktrees whose branch has already been merged? (cleanup candidates)
|
|
44
|
+
- Workspace repo on expected branch?
|
|
45
|
+
- Orphan worktree records in project repos — run `git -C repos/{repo} worktree list` for each repo and flag any `prunable` markers. These usually come from a workspace-first teardown (the unsafe order) leaving stale admin records behind. Suggest `git worktree prune` on the affected repo.
|
|
46
|
+
|
|
47
|
+
## Cleanup
|
|
48
|
+
|
|
49
|
+
Active recommendations. Flags problems and suggests fixes, but asks before acting.
|
|
50
|
+
|
|
51
|
+
### 5. Stale context
|
|
52
|
+
- Ephemeral files not updated in 7+ days — suggest resolve, update, or archive
|
|
53
|
+
- `work-sessions/{name}/` folders whose worktrees are gone — suggest cleanup
|
|
54
|
+
- Session trackers whose branches have been merged — suggest `/complete-work` post-flight cleanup
|
|
55
|
+
- Braindumps that overlap significantly — suggest merging (e.g., "workspace-branching.md and persistent-work-sessions.md cover the same topic")
|
|
56
|
+
- Handoffs referencing deleted branches — suggest resolve or remove
|
|
57
|
+
|
|
58
|
+
### 6. Context reconciliation
|
|
59
|
+
- Read recent shared-context writes (last session or last N files by updated date)
|
|
60
|
+
- For each, scan other shared-context files for references that are now stale
|
|
61
|
+
- Surface: "{file} says X but {newer-file} now says Y. Update {file}?"
|
|
62
|
+
- This is the capture-time cross-check, run retroactively instead of inline
|
|
63
|
+
|
|
64
|
+
### 7. Health metrics
|
|
65
|
+
- Total size of `shared-context/locked/` — flag if over 10KB target
|
|
66
|
+
- Number of ephemeral files — flag if accumulating without resolution
|
|
67
|
+
- Session log stats (if `workspace-scratchpad/session-log.jsonl` exists):
|
|
68
|
+
- Sessions without capture
|
|
69
|
+
- Average session length
|
|
70
|
+
- Compaction-to-capture ratio
|
|
71
|
+
|
|
72
|
+
## Output Format
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
/maintenance results:
|
|
76
|
+
|
|
77
|
+
Issues (3):
|
|
78
|
+
✗ shared-context/alice/old-handoff.md references branch feature/old
|
|
79
|
+
but that branch was deleted
|
|
80
|
+
✗ 2 inflight files exist but no active work session (orphaned?)
|
|
81
|
+
✗ Locked context is 12.3KB (target: <10KB)
|
|
82
|
+
|
|
83
|
+
Warnings (2):
|
|
84
|
+
⚠ shared-context/alice/workspace-analytics.md not updated in 8 days
|
|
85
|
+
⚠ Worktree work-sessions/old-feature/workspace has no commits in 5 days
|
|
86
|
+
|
|
87
|
+
Cleanup suggestions (2):
|
|
88
|
+
⊕ workspace-branching.md and persistent-work-sessions.md overlap
|
|
89
|
+
significantly — merge into one?
|
|
90
|
+
⊕ migration-recipes.md still says "/sync handles dogfood" but
|
|
91
|
+
/sync was replaced by /sync-work — update?
|
|
92
|
+
|
|
93
|
+
OK (4):
|
|
94
|
+
✓ All CLAUDE.md skill references valid
|
|
95
|
+
✓ Workspace structure matches rule
|
|
96
|
+
✓ workspace.json repos all present
|
|
97
|
+
✓ No frontmatter errors
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Flow
|
|
101
|
+
|
|
102
|
+
1. Scan shared-context/ recursively — read all `.md` files and their frontmatter
|
|
103
|
+
2. Read CLAUDE.md — extract skill and rule references
|
|
104
|
+
3. Read workspace.json — extract repo manifest
|
|
105
|
+
4. Check `.claude/rules/`, `.claude/skills/`, `.claude/agents/` against references
|
|
106
|
+
5. Check git state (worktrees, branches, remotes)
|
|
107
|
+
6. Read session-log.jsonl if it exists
|
|
108
|
+
7. If cleanup mode: compare files pairwise for overlap, scan for stale cross-references
|
|
109
|
+
8. Compile and present findings grouped by severity
|
|
110
|
+
|
|
111
|
+
## Notes
|
|
112
|
+
- Audit mode is always read-only — never modifies files
|
|
113
|
+
- Cleanup mode asks before acting on any suggestion
|
|
114
|
+
- Run before /release to catch drift before it compounds
|
|
115
|
+
- Run after long gaps between sessions to surface stale context
|
|
116
|
+
- Consider running at the start of each work session
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pause-work
|
|
3
|
+
description: Suspend current work — updates session tracker, captures state to the tracker body, pushes all repos, creates draft PRs. Use when stepping away from work that isn't finished.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pause Work
|
|
7
|
+
|
|
8
|
+
Suspend the active work session. Captures state in the session tracker, pushes work, and marks the session as paused for later resumption.
|
|
9
|
+
|
|
10
|
+
## Flow
|
|
11
|
+
|
|
12
|
+
### Step 1: Detect active session
|
|
13
|
+
|
|
14
|
+
Read the active-session pointer from `.claude/.active-session.json` in the current worktree.
|
|
15
|
+
If no active session: "No active work session. Nothing to pause."
|
|
16
|
+
|
|
17
|
+
Read the full session tracker at `work-sessions/{session-name}/workspace/session.md`.
|
|
18
|
+
|
|
19
|
+
### Step 2: Update session tracker body
|
|
20
|
+
|
|
21
|
+
Rewrite the `## Progress` section of `work-sessions/{session-name}/workspace/session.md` with:
|
|
22
|
+
- What was accomplished in this chat session
|
|
23
|
+
- Key decisions made
|
|
24
|
+
- Current state of the work
|
|
25
|
+
- Specific next steps for whoever resumes
|
|
26
|
+
|
|
27
|
+
This is a coherent rewrite of the Progress section, not an append (coherent-revisions rule). Leave the frontmatter alone — the session-end hook will mark this chat's `ended` timestamp automatically when the chat closes.
|
|
28
|
+
|
|
29
|
+
### Step 3: Update frontmatter status and post pause comment on tracker
|
|
30
|
+
|
|
31
|
+
Use the session-frontmatter helper to set `status: paused` in the tracker's frontmatter.
|
|
32
|
+
|
|
33
|
+
If the session tracker has a `workItem:` field AND `workspace.tracker` is configured, post a pause comment on the linked issue via the adapter:
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import { createTracker } from './.claude/scripts/trackers/interface.mjs';
|
|
37
|
+
import { readFileSync } from 'node:fs';
|
|
38
|
+
const ws = JSON.parse(readFileSync('workspace.json', 'utf-8'));
|
|
39
|
+
if (ws.workspace?.tracker) {
|
|
40
|
+
const tracker = createTracker(ws.workspace.tracker);
|
|
41
|
+
const progressBody = /* the ## Progress section of session.md, as written in Step 2 */;
|
|
42
|
+
const body = [
|
|
43
|
+
`**Session paused by @${currentUser}** (${branch})`,
|
|
44
|
+
'',
|
|
45
|
+
progressBody,
|
|
46
|
+
'',
|
|
47
|
+
`Resume with \`/start-work\` from any worktree on \`${branch}\`.`,
|
|
48
|
+
].join('\n');
|
|
49
|
+
await tracker.comment(workItem, body);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If `workItem:` is unset, skip the comment — this is a blank session with no tracker linkage.
|
|
54
|
+
|
|
55
|
+
If the comment fails (tracker unreachable, auth expired), report the error but do not block the pause. The pause state lives locally in the session tracker regardless.
|
|
56
|
+
|
|
57
|
+
### Step 4: Commit and push workspace
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# From the workspace worktree
|
|
61
|
+
cd work-sessions/{session-name}/workspace
|
|
62
|
+
git add .
|
|
63
|
+
git commit -m "handoff: pause {session-name}"
|
|
64
|
+
git push -u origin {branch}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Step 5: Push project repos
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# For each repo in the tracker's repos:
|
|
71
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
72
|
+
git push -u origin {branch}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Step 6: Create draft PRs
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# For each repo in the tracker's repos:
|
|
79
|
+
cd work-sessions/{session-name}/workspace/repos/{repo}
|
|
80
|
+
gh pr create --draft --title "WIP: {description}" --body "Work in progress. Session paused."
|
|
81
|
+
|
|
82
|
+
# Workspace repo — from the workspace worktree
|
|
83
|
+
gh pr create --draft --title "context: {session-name} (paused)" --body "Workspace context for paused session."
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If PRs already exist, update them to draft status if needed.
|
|
87
|
+
|
|
88
|
+
### Step 7: Confirm
|
|
89
|
+
|
|
90
|
+
"Session '{session-name}' paused. Resume anytime with /start-work."
|
|
91
|
+
|
|
92
|
+
No worktree cleanup — the session is meant to be resumed. The `work-sessions/{session-name}/` folder stays intact.
|
|
93
|
+
|
|
94
|
+
## Notes
|
|
95
|
+
- Pause writes ONLY to `work-sessions/{session-name}/workspace/session.md` — never to ongoing or root shared-context
|
|
96
|
+
- The session tracker's frontmatter stays in the session folder — it's the resume mechanism
|
|
97
|
+
- Draft PRs signal work-in-progress without implying merge readiness
|
|
98
|
+
- Auto-committing the pause capture is a workflow artifact — this intentionally bypasses normal commit conventions
|