@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.
Files changed (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/bin/create.mjs +79 -0
  4. package/lib/git.mjs +26 -0
  5. package/lib/init.mjs +129 -0
  6. package/lib/payload.mjs +44 -0
  7. package/lib/prompts.mjs +113 -0
  8. package/lib/scaffold.mjs +84 -0
  9. package/lib/upgrade.mjs +42 -0
  10. package/package.json +43 -0
  11. package/template/.claude/agents/aside-researcher.md +48 -0
  12. package/template/.claude/agents/implementer.md +39 -0
  13. package/template/.claude/agents/researcher.md +40 -0
  14. package/template/.claude/agents/reviewer.md +47 -0
  15. package/template/.claude/hooks/_utils.mjs +196 -0
  16. package/template/.claude/hooks/_utils.test.mjs +99 -0
  17. package/template/.claude/hooks/post-compact.mjs +7 -0
  18. package/template/.claude/hooks/pre-compact.mjs +34 -0
  19. package/template/.claude/hooks/repo-write-detection.mjs +107 -0
  20. package/template/.claude/hooks/session-end.mjs +91 -0
  21. package/template/.claude/hooks/session-start.mjs +150 -0
  22. package/template/.claude/hooks/subagent-start.mjs +44 -0
  23. package/template/.claude/hooks/workspace-update-check.mjs +42 -0
  24. package/template/.claude/hooks/worktree-create.mjs +53 -0
  25. package/template/.claude/lib/session-frontmatter.mjs +265 -0
  26. package/template/.claude/lib/session-frontmatter.test.mjs +242 -0
  27. package/template/.claude/recipes/migrate-from-notion.md +120 -0
  28. package/template/.claude/rules/agent-rules.md.skip +32 -0
  29. package/template/.claude/rules/cloud-infrastructure.md.skip +15 -0
  30. package/template/.claude/rules/coherent-revisions.md +24 -0
  31. package/template/.claude/rules/documentation.md.skip +13 -0
  32. package/template/.claude/rules/git-conventions.md +34 -0
  33. package/template/.claude/rules/honest-pushback.md +56 -0
  34. package/template/.claude/rules/local-dev-environment.md.skip +60 -0
  35. package/template/.claude/rules/memory-guidance.md +26 -0
  36. package/template/.claude/rules/product-integrity.md.skip +24 -0
  37. package/template/.claude/rules/scope-guard.md.skip +22 -0
  38. package/template/.claude/rules/superpowers-workflow.md.skip +22 -0
  39. package/template/.claude/rules/token-economics.md.skip +31 -0
  40. package/template/.claude/rules/work-item-tracking.md +90 -0
  41. package/template/.claude/rules/workspace-structure.md +69 -0
  42. package/template/.claude/scripts/add-repo-to-session.mjs +78 -0
  43. package/template/.claude/scripts/cleanup-work-session.mjs +108 -0
  44. package/template/.claude/scripts/create-work-session.mjs +124 -0
  45. package/template/.claude/scripts/migrate-open-work.mjs +91 -0
  46. package/template/.claude/scripts/migrate-session-layout.mjs +236 -0
  47. package/template/.claude/scripts/migrate-session-layout.test.mjs +144 -0
  48. package/template/.claude/scripts/trackers/github-issues.mjs +170 -0
  49. package/template/.claude/scripts/trackers/github-issues.test.mjs +190 -0
  50. package/template/.claude/scripts/trackers/interface.mjs +25 -0
  51. package/template/.claude/scripts/trackers/interface.test.mjs +40 -0
  52. package/template/.claude/settings.json +107 -0
  53. package/template/.claude/skills/aside/SKILL.md +125 -0
  54. package/template/.claude/skills/braindump/SKILL.md +96 -0
  55. package/template/.claude/skills/build-docs-site/SKILL.md +323 -0
  56. package/template/.claude/skills/build-docs-site/checklists/framing.md +221 -0
  57. package/template/.claude/skills/build-docs-site/checklists/pitfalls.md +228 -0
  58. package/template/.claude/skills/build-docs-site/checklists/review.md +130 -0
  59. package/template/.claude/skills/build-docs-site/scripts/bulk-fill-migration.py +393 -0
  60. package/template/.claude/skills/build-docs-site/scripts/forbidden-word-grep.mjs +159 -0
  61. package/template/.claude/skills/build-docs-site/scripts/leak-grep.mjs +328 -0
  62. package/template/.claude/skills/build-docs-site/templates/custom.css.tmpl +212 -0
  63. package/template/.claude/skills/build-docs-site/templates/docusaurus.config.ts.tmpl +95 -0
  64. package/template/.claude/skills/build-docs-site/templates/primitives/Arrow.tsx +87 -0
  65. package/template/.claude/skills/build-docs-site/templates/primitives/Box.tsx +90 -0
  66. package/template/.claude/skills/build-docs-site/templates/primitives/DiagramContainer.tsx +46 -0
  67. package/template/.claude/skills/build-docs-site/templates/primitives/Region.tsx +68 -0
  68. package/template/.claude/skills/build-docs-site/templates/primitives/SectionTitle.tsx +42 -0
  69. package/template/.claude/skills/build-docs-site/templates/primitives/tokens.ts +67 -0
  70. package/template/.claude/skills/build-docs-site/templates/sidebars.ts.tmpl +89 -0
  71. package/template/.claude/skills/build-docs-site/templates/spec.md.tmpl +119 -0
  72. package/template/.claude/skills/complete-work/SKILL.md +369 -0
  73. package/template/.claude/skills/handoff/SKILL.md +98 -0
  74. package/template/.claude/skills/maintenance/SKILL.md +116 -0
  75. package/template/.claude/skills/pause-work/SKILL.md +98 -0
  76. package/template/.claude/skills/promote/SKILL.md +77 -0
  77. package/template/.claude/skills/release/SKILL.md +126 -0
  78. package/template/.claude/skills/setup-tracker/SKILL.md +117 -0
  79. package/template/.claude/skills/start-work/SKILL.md +234 -0
  80. package/template/.claude/skills/sync-work/SKILL.md +73 -0
  81. package/template/.claude/skills/workspace-init/SKILL.md +420 -0
  82. package/template/.claude/skills/workspace-update/SKILL.md +108 -0
  83. package/template/.mcp.json +12 -0
  84. package/template/CLAUDE.md.tmpl +32 -0
  85. package/template/_gitignore +28 -0
  86. 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