@ulysses-ai/create-workspace 0.14.0-beta.3 → 0.15.0-beta.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/lib/init.mjs +12 -25
- package/lib/scaffold.mjs +3 -2
- package/package.json +1 -1
- package/template/.claude/agents/reviewer.md +1 -1
- package/template/.claude/hooks/pre-compact.mjs +1 -1
- package/template/.claude/hooks/repo-write-detection.mjs +2 -2
- package/template/.claude/hooks/session-start.mjs +10 -7
- package/template/.claude/hooks/subagent-start.mjs +3 -3
- package/template/.claude/recipes/migrate-from-notion.md +6 -6
- package/template/.claude/rules/coherent-revisions.md +2 -2
- package/template/.claude/rules/local-dev-environment.md.skip +2 -2
- package/template/.claude/rules/memory-guidance.md +23 -14
- package/template/.claude/rules/token-economics.md.skip +2 -2
- package/template/.claude/rules/work-item-tracking.md +1 -1
- package/template/.claude/rules/workspace-structure.md +36 -15
- package/template/.claude/scripts/build-workspace-context.mjs +712 -0
- package/template/.claude/scripts/capture-context.mjs +217 -0
- package/template/.claude/scripts/generate-claude-local.mjs +104 -0
- package/template/.claude/scripts/migrate-canonical-priority.mjs +108 -0
- package/template/.claude/scripts/migrate-open-work.mjs +1 -1
- package/template/.claude/scripts/migrate-to-workspace-context.mjs +520 -0
- package/template/.claude/scripts/sweep-references.mjs +177 -0
- package/template/.claude/skills/aside/SKILL.md +49 -44
- package/template/.claude/skills/braindump/SKILL.md +25 -19
- package/template/.claude/skills/build-docs-site/SKILL.md +1 -1
- package/template/.claude/skills/build-docs-site/checklists/framing.md +1 -1
- package/template/.claude/skills/complete-work/SKILL.md +91 -3
- package/template/.claude/skills/handoff/SKILL.md +31 -30
- package/template/.claude/skills/maintenance/SKILL.md +90 -22
- package/template/.claude/skills/pause-work/SKILL.md +1 -1
- package/template/.claude/skills/promote/SKILL.md +18 -8
- package/template/.claude/skills/release/SKILL.md +20 -13
- package/template/.claude/skills/start-work/SKILL.md +1 -1
- package/template/.claude/skills/workspace-init/SKILL.md +12 -12
- package/template/.claude/skills/workspace-update/SKILL.md +7 -1
- package/template/CLAUDE.md.tmpl +4 -3
- package/template/_gitignore +1 -0
- package/template/workspace.json.tmpl +3 -2
- package/template/.claude/hooks/_bash-output-advisory.test.mjs +0 -88
- package/template/.claude/hooks/_utils.test.mjs +0 -99
- package/template/.claude/lib/freshness.test.mjs +0 -175
- package/template/.claude/lib/registry-check.test.mjs +0 -130
- package/template/.claude/lib/session-frontmatter.test.mjs +0 -242
- package/template/.claude/scripts/build-shared-context-index.mjs +0 -212
- package/template/.claude/scripts/build-shared-context-index.test.mjs +0 -318
- package/template/.claude/scripts/migrate-claude-md-freshness-include.test.mjs +0 -54
- package/template/.claude/scripts/migrate-session-layout.test.mjs +0 -144
- package/template/.claude/scripts/sync-tasks.test.mjs +0 -350
- package/template/.claude/scripts/trackers/github-issues.test.mjs +0 -190
- package/template/.claude/scripts/trackers/interface.test.mjs +0 -40
|
@@ -17,13 +17,13 @@ Keep the workspace healthy. Combines integrity auditing with active cleanup reco
|
|
|
17
17
|
Read-only integrity checks. Reports problems but never modifies files.
|
|
18
18
|
|
|
19
19
|
### 1. Cross-reference consistency
|
|
20
|
-
Scan all
|
|
20
|
+
Scan all workspace-context files against each other:
|
|
21
21
|
- **Stale references** — file A mentions "2 mandatory rules" but there are now 4
|
|
22
22
|
- **Path references** — file A mentions a file that was moved or deleted
|
|
23
23
|
- **Contradictions** — file A says "user-scoped is default" but file B says "root is default"
|
|
24
24
|
|
|
25
25
|
### 2. Frontmatter integrity
|
|
26
|
-
For each
|
|
26
|
+
For each workspace-context `.md` file and each `work-sessions/*/workspace/session.md`:
|
|
27
27
|
- Valid frontmatter? (state, lifecycle, type, topic, author, updated; plus name/status/branch/repos for session trackers)
|
|
28
28
|
- `branch` field references a branch that still exists?
|
|
29
29
|
- `repo`/`repos` field references repos that exist in workspace.json?
|
|
@@ -45,23 +45,43 @@ For each shared-context `.md` file and each `work-sessions/*/workspace/session.m
|
|
|
45
45
|
- Workspace repo on expected branch?
|
|
46
46
|
- 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.
|
|
47
47
|
|
|
48
|
-
### 5.
|
|
48
|
+
### 5. Workspace-context auto-file integrity
|
|
49
49
|
|
|
50
|
-
`
|
|
50
|
+
`workspace-context/index.md`, `workspace-context/canonical.md`, and each `workspace-context/team-member/{user}/index.md` are auto-generated from frontmatter and locked content. Run the check:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
node .claude/scripts/build-
|
|
53
|
+
node .claude/scripts/build-workspace-context.mjs --check --root .
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
The script reports per-artifact status as JSON and uses three exit codes to distinguish what's wrong:
|
|
57
|
+
|
|
58
|
+
- `0` — all artifacts current and the rendered canonical fits inside `workspace.canonicalBudgetBytes`.
|
|
59
|
+
- `1` — at least one artifact is `missing` or `stale`. Run `--write` to regenerate. `missing` means the artifact does not exist yet; `stale` means it exists but no longer matches its sources (a file was added or deleted, a `description:` changed, a `shared/locked/` file was edited, an `.indexignore` rule was added).
|
|
60
|
+
- `2` — artifacts are current but canonical body bytes exceed the budget after the trim and stub stages have already run. Regeneration cannot fix this; the locked content itself needs triage. Stale wins over over-budget when both apply, so a `1` can hide an over-budget condition until you regen.
|
|
61
|
+
|
|
62
|
+
The JSON payload always includes a `canonical` block summarizing the budget outcome:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"status": "current",
|
|
67
|
+
"missing": [],
|
|
68
|
+
"stale": [],
|
|
69
|
+
"canonical": {
|
|
70
|
+
"budget": 40960,
|
|
71
|
+
"current": 47802,
|
|
72
|
+
"overBy": 6842,
|
|
73
|
+
"selectionStatus": "stubbed",
|
|
74
|
+
"trimmedFiles": ["post-release-discipline"],
|
|
75
|
+
"stubbedFiles": ["project-status", "release-flow-recipes"]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
57
79
|
|
|
58
|
-
|
|
59
|
-
- `stale` — `index.md` exists but its entries no longer match the filesystem. Causes: a file was added or deleted, a `description:` was changed, a `.indexignore` rule was added. Run `--write` to regenerate.
|
|
60
|
-
- (no failure) — `current` with the entry count.
|
|
80
|
+
`selectionStatus` walks `ok` → `trimmed` → `stubbed` → `over-budget` as the script gives up progressively more reference content trying to fit the budget. `trimmedFiles` lists reference files whose `<!-- canonical:trim --> ... <!-- canonical:end-trim -->` spans were dropped; `stubbedFiles` lists reference files whose entire body was replaced with a one-line breadcrumb. `overBy` is present only when `selectionStatus === 'over-budget'` and reports the bytes still over after stubbing.
|
|
61
81
|
|
|
62
|
-
Audit mode reports the status. Cleanup mode runs `--write`
|
|
82
|
+
Audit mode reports the status verbatim. When `selectionStatus` is `over-budget`, audit emits the budget violation and recommends `/maintenance cleanup` to triage — regeneration will not resolve it. Cleanup mode runs `--write` when `missing` or `stale`, re-checks, and then enters the budget triage flow described in cleanup step 9 if the post-regen check still reports `over-budget`.
|
|
63
83
|
|
|
64
|
-
While the
|
|
84
|
+
While the indexes are being read, also flag entries with weak fallbacks: filename-slug-only descriptions (e.g., "project status" with no period) usually indicate the underlying file is missing a `description:` or has no usable opening sentence. Suggest adding `description:` to those source files — the index will pick it up on the next regeneration.
|
|
65
85
|
|
|
66
86
|
### 6. Template freshness
|
|
67
87
|
|
|
@@ -96,13 +116,60 @@ Active recommendations. Flags problems and suggests fixes, but asks before actin
|
|
|
96
116
|
- Handoffs referencing deleted branches — suggest resolve or remove
|
|
97
117
|
|
|
98
118
|
### 8. Context reconciliation
|
|
99
|
-
- Read recent
|
|
100
|
-
- For each, scan other
|
|
119
|
+
- Read recent workspace-context writes (last session or last N files by updated date)
|
|
120
|
+
- For each, scan other workspace-context files for references that are now stale
|
|
101
121
|
- Surface: "{file} says X but {newer-file} now says Y. Update {file}?"
|
|
102
122
|
- This is the capture-time cross-check, run retroactively instead of inline
|
|
103
123
|
|
|
104
|
-
### 9.
|
|
105
|
-
|
|
124
|
+
### 9. Canonical budget triage
|
|
125
|
+
|
|
126
|
+
This step runs only when the post-regen `--check` from step 8 still reports `selectionStatus: 'over-budget'`. If the regular regen pass cleared the budget — or if `--check` was already `ok`, `trimmed`, or `stubbed` after step 8 — skip this step entirely.
|
|
127
|
+
|
|
128
|
+
The rest of cleanup is suggestion-list-with-confirmation: surface a candidate, ask before applying, move on. Triage is the one meaningfully more interactive surface in `/maintenance`. It runs as a small REPL: present the budget state and a triage menu, take one action, re-run `--check`, present the menu again with the new state. No suggestion is auto-applied; every action is the user's choice.
|
|
129
|
+
|
|
130
|
+
Inputs to gather before the first menu render:
|
|
131
|
+
|
|
132
|
+
- The `canonical` block from the `--check` JSON: `budget`, `current`, `overBy`, `selectionStatus`, `trimmedFiles`, `stubbedFiles`.
|
|
133
|
+
- Each `workspace-context/shared/locked/*.md` file with its on-disk byte size and frontmatter `priority`.
|
|
134
|
+
- Per file, a list of `## Section heading` spans with byte sizes — use a simple `^## ` boundary scan, not a full markdown AST. Locked files are short and shallow enough that the naive split is sufficient; if a file ever has nested headings that confuse it, fall back to opening the file in an editor (option `[c]` below).
|
|
135
|
+
|
|
136
|
+
Render the state and present this menu:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Canonical budget: 40960 bytes. Current: 47802 bytes. Over by 6842 bytes.
|
|
140
|
+
|
|
141
|
+
Locked files by size:
|
|
142
|
+
1. project-status.md (priority: reference, 18432 bytes) ← stubbed in canonical
|
|
143
|
+
2. post-release-discipline.md (priority: critical, 12104 bytes)
|
|
144
|
+
3. naming-conventions.md (priority: critical, 4218 bytes)
|
|
145
|
+
4. cross-platform.md (priority: critical, 702 bytes)
|
|
146
|
+
5. product-bias-risk.md (priority: critical, 1346 bytes)
|
|
147
|
+
|
|
148
|
+
Largest sections in priority:critical files (eligible for promotion to reference or trim markers):
|
|
149
|
+
- project-status.md > "What's Built" (5120 bytes)
|
|
150
|
+
- post-release-discipline.md > "Backstop: branch protection" (3892 bytes)
|
|
151
|
+
- post-release-discipline.md > "Why" (2104 bytes)
|
|
152
|
+
|
|
153
|
+
Triage (one at a time):
|
|
154
|
+
[a] Demote a file from critical to reference
|
|
155
|
+
[b] Add canonical:trim markers around a specific section
|
|
156
|
+
[c] Open a locked file in the editor for manual edits
|
|
157
|
+
[d] Skip — accept the over-budget warning
|
|
158
|
+
[q] Done
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
For each chosen action:
|
|
162
|
+
|
|
163
|
+
- **`[a]` Demote.** Ask which file. Rewrite its frontmatter `priority: critical` → `priority: reference`. No body changes. Re-run `--check`, re-render the menu with the new state.
|
|
164
|
+
- **`[b]` Add trim markers.** Ask which `file > section`. Wrap the section by inserting `<!-- canonical:trim -->` on its own line just before the section heading and `<!-- canonical:end-trim -->` on its own line just after the section's last line (the line before the next `^## ` heading or EOF). Re-run `--check`, re-render.
|
|
165
|
+
- **`[c]` Open in editor.** Print the file path and pause. The user edits manually, returns, and confirms — then re-run `--check` and re-render.
|
|
166
|
+
- **`[d]` Skip.** Accept the over-budget state for this run; record the acknowledgement in the run summary. Audit will continue to surface the warning on subsequent runs.
|
|
167
|
+
- **`[q]` Done.** Exit triage. Report the final `--check` status as the run result.
|
|
168
|
+
|
|
169
|
+
Trim markers and demotions only matter for `priority: reference` files — `<!-- canonical:trim -->` spans on a `priority: critical` file are inert until the file is demoted. The triage flow never auto-decides which file to demote or which section to wrap; it surfaces the data, presents options, and waits.
|
|
170
|
+
|
|
171
|
+
### 10. Health metrics
|
|
172
|
+
- Canonical budget — read from the same `--check` invocation as step 5. Reported as `current / budget` bytes with the selection status (e.g., `full`, `2 reference files trimmed`). Over-budget cases are deferred to the cleanup triage flow rather than re-reported here.
|
|
106
173
|
- Number of ephemeral files — flag if accumulating without resolution
|
|
107
174
|
- Session log stats (if `workspace-scratchpad/session-log.jsonl` exists):
|
|
108
175
|
- Sessions without capture
|
|
@@ -115,13 +182,14 @@ Active recommendations. Flags problems and suggests fixes, but asks before actin
|
|
|
115
182
|
/maintenance results:
|
|
116
183
|
|
|
117
184
|
Issues (3):
|
|
118
|
-
✗
|
|
185
|
+
✗ workspace-context/team-member/alice/old-handoff.md references branch feature/old
|
|
119
186
|
but that branch was deleted
|
|
120
187
|
✗ 2 inflight files exist but no active work session (orphaned?)
|
|
121
|
-
✗
|
|
188
|
+
✗ Canonical exceeds budget: 47 KB / 40 KB. 2 reference files were stubbed;
|
|
189
|
+
canonical is still 6.8 KB over. Run /maintenance cleanup to triage.
|
|
122
190
|
|
|
123
191
|
Warnings (2):
|
|
124
|
-
⚠
|
|
192
|
+
⚠ workspace-context/team-member/alice/workspace-analytics.md not updated in 8 days
|
|
125
193
|
⚠ Worktree work-sessions/old-feature/workspace has no commits in 5 days
|
|
126
194
|
|
|
127
195
|
Cleanup suggestions (2):
|
|
@@ -134,20 +202,20 @@ OK (5):
|
|
|
134
202
|
✓ All CLAUDE.md skill references valid
|
|
135
203
|
✓ Workspace structure matches rule
|
|
136
204
|
✓ workspace.json repos all present
|
|
137
|
-
✓
|
|
205
|
+
✓ Canonical: 17 KB / 40 KB (full)
|
|
138
206
|
✓ Template is up to date (v0.14.0)
|
|
139
207
|
```
|
|
140
208
|
|
|
141
209
|
## Flow
|
|
142
210
|
|
|
143
|
-
1. Scan
|
|
211
|
+
1. Scan workspace-context/ recursively — read all `.md` files and their frontmatter
|
|
144
212
|
2. Read CLAUDE.md — extract skill and rule references
|
|
145
213
|
3. Read workspace.json — extract repo manifest
|
|
146
214
|
4. Check `.claude/rules/`, `.claude/skills/`, `.claude/agents/` against references
|
|
147
215
|
5. Check git state (worktrees, branches, remotes)
|
|
148
|
-
6. Run `node .claude/scripts/build-
|
|
216
|
+
6. Run `node .claude/scripts/build-workspace-context.mjs --check --root .` — capture status. Exit `0` = clean and within budget, `1` = artifact missing or stale, `2` = artifacts current but canonical body over budget. The `canonical` block in the JSON output drives both the audit budget line and the cleanup triage decision.
|
|
149
217
|
7. Read session-log.jsonl if it exists
|
|
150
|
-
8. If cleanup mode: regenerate the
|
|
218
|
+
8. If cleanup mode: regenerate the workspace-context auto-files if stale (index.md, canonical.md, per-user team-member indexes); compare files pairwise for overlap; scan for stale cross-references. If post-regen `--check` reports `over-budget`, enter the canonical-budget triage flow described in cleanup step 9.
|
|
151
219
|
9. Compile and present findings grouped by severity
|
|
152
220
|
|
|
153
221
|
## Notes
|
|
@@ -113,7 +113,7 @@ If PRs already exist, update them to draft status if needed.
|
|
|
113
113
|
No worktree cleanup — the session is meant to be resumed. The `work-sessions/{session-name}/` folder stays intact.
|
|
114
114
|
|
|
115
115
|
## Notes
|
|
116
|
-
- Pause writes ONLY to `work-sessions/{session-name}/workspace/session.md` — never to ongoing or root
|
|
116
|
+
- Pause writes ONLY to `work-sessions/{session-name}/workspace/session.md` — never to ongoing or root workspace-context
|
|
117
117
|
- The session tracker's frontmatter stays in the session folder — it's the resume mechanism
|
|
118
118
|
- Draft PRs signal work-in-progress without implying merge readiness
|
|
119
119
|
- Auto-committing the pause capture is a workflow artifact — this intentionally bypasses normal commit conventions
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: promote
|
|
3
|
-
description: Move personal auto-memory or local-only files into
|
|
3
|
+
description: Move personal auto-memory or local-only files into workspace-context. Use when you've discovered something valuable that the team should know.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Promote
|
|
7
7
|
|
|
8
|
-
Promote personal knowledge into
|
|
8
|
+
Promote personal knowledge into workspace-context. Assess all candidates, recommend actions, let the user decide with coded references.
|
|
9
9
|
|
|
10
10
|
## Sources
|
|
11
11
|
|
|
12
12
|
This skill can promote from three sources:
|
|
13
13
|
1. **Auto-memory (AM)** — files in `~/.claude/projects/*/memory/`
|
|
14
|
-
2. **Local-only context (LOC)** — `
|
|
14
|
+
2. **Local-only context (LOC)** — `workspace-context/team-member/{user}/local-only-*.md` (and any other `local-only-*.md` under `workspace-context/`)
|
|
15
15
|
3. **Local-only rules (LOR)** — `.claude/rules/local-only-*.md`
|
|
16
16
|
|
|
17
17
|
## Flow
|
|
@@ -47,9 +47,19 @@ The user responds using codes:
|
|
|
47
47
|
**Step 3: Execute decisions**
|
|
48
48
|
|
|
49
49
|
For each **promote** action:
|
|
50
|
-
- Ask: "Team-visible, user-scoped (default), or locked?"
|
|
51
|
-
-
|
|
52
|
-
|
|
50
|
+
- Ask: "Team-visible (`workspace-context/shared/`), user-scoped (default, `workspace-context/team-member/{user}/`), or locked (`workspace-context/shared/locked/`)?"
|
|
51
|
+
- Use `capture-context.mjs --update` to write to the destination with the right frontmatter:
|
|
52
|
+
```bash
|
|
53
|
+
cat {source-file} | node .claude/scripts/capture-context.mjs \
|
|
54
|
+
--type {braindump|handoff|research} \
|
|
55
|
+
--topic {kebab-name} \
|
|
56
|
+
--scope {team-member|shared} \
|
|
57
|
+
[--user {workspace.user}] \
|
|
58
|
+
--update
|
|
59
|
+
```
|
|
60
|
+
When promoting *to locked*, write directly to `workspace-context/shared/locked/{bare-name}.md` instead — locked files use bare names (location signals the type) and don't take a prefix. Strip the `braindump_/handoff_/research_` prefix when locking.
|
|
61
|
+
- Set `type: promoted` in the destination frontmatter (the helper writes the standard fields; edit `type` afterward, or have the body's frontmatter override).
|
|
62
|
+
- Remove the `local-only-` original.
|
|
53
63
|
- Commit individually: `git commit -m "promote: {name}"`
|
|
54
64
|
|
|
55
65
|
For each **drop** action:
|
|
@@ -65,13 +75,13 @@ For each **keep** action:
|
|
|
65
75
|
|
|
66
76
|
## Rewrite on Promote
|
|
67
77
|
|
|
68
|
-
Auto-memory files are terse notes written for Claude's internal use. When promoting to
|
|
78
|
+
Auto-memory files are terse notes written for Claude's internal use. When promoting to workspace-context, rewrite into proper format with:
|
|
69
79
|
- Frontmatter (state, lifecycle, type: promoted, topic, author, updated)
|
|
70
80
|
- Sections with enough context to be useful to someone who wasn't in the original session
|
|
71
81
|
- Local-only files may already be well-formatted — copy as-is if so, just update frontmatter
|
|
72
82
|
|
|
73
83
|
## Notes
|
|
74
|
-
- Promotion is one-way:
|
|
84
|
+
- Promotion is one-way: workspace-context should not be demoted back to local-only
|
|
75
85
|
- Use this when you discover a pattern, convention, or decision that would benefit the team
|
|
76
86
|
- The coded table makes bulk decisions fast — no need to type full filenames
|
|
77
87
|
- Assess everything upfront so the user sees the full picture before deciding
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: release
|
|
3
|
-
description: Prepend a new CHANGELOG.md entry per project repo by synthesizing unreleased branch notes. Deletes consumed branch notes and synthesizes workspace
|
|
3
|
+
description: Prepend a new CHANGELOG.md entry per project repo by synthesizing unreleased branch notes. Deletes consumed branch notes and synthesizes workspace-context into canonical (locked) entries. Use at release time.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Release
|
|
7
7
|
|
|
8
|
-
Synthesize unreleased branch notes (in the **workspace** repo) into a concise, user-facing entry at the top of each project repo's `CHANGELOG.md`. Delete the consumed branch notes from the workspace. Bump the project repo's `package.json` version. In parallel, promote resolved workspace
|
|
8
|
+
Synthesize unreleased branch notes (in the **workspace** repo) into a concise, user-facing entry at the top of each project repo's `CHANGELOG.md`. Delete the consumed branch notes from the workspace. Bump the project repo's `package.json` version. In parallel, promote resolved workspace-context into canonical (locked) team knowledge.
|
|
9
9
|
|
|
10
10
|
## Why this shape
|
|
11
11
|
|
|
@@ -104,28 +104,32 @@ git commit -m "release: consume {repo} branch notes for v{version}"
|
|
|
104
104
|
Workspace and project repos have separate commits — they are separate git histories.
|
|
105
105
|
|
|
106
106
|
**Step 8: Consume project-scoped specs**
|
|
107
|
-
Project-scoped specs and plans in `
|
|
107
|
+
Project-scoped specs and plans in `workspace-context/team-member/{user}/` (ongoing) that are fully covered by this release:
|
|
108
108
|
- Consume into the CHANGELOG entry (their content is now captured there)
|
|
109
109
|
- Remove the source files
|
|
110
110
|
- If partially covered: rewrite the spec to reflect only what remains unimplemented
|
|
111
111
|
|
|
112
|
-
**Step 9: Synthesize workspace
|
|
113
|
-
Process ephemeral
|
|
112
|
+
**Step 9: Synthesize workspace-context for canonical promotion**
|
|
113
|
+
Process ephemeral workspace-context entries:
|
|
114
114
|
|
|
115
|
-
1. List all ephemeral entries with `lifecycle: resolved`
|
|
115
|
+
1. List all ephemeral entries with `lifecycle: resolved` (across `shared/` and any `team-member/{user}/`).
|
|
116
116
|
2. For each, determine:
|
|
117
117
|
- Does an existing locked entry cover this topic? → Merge into it (enrich)
|
|
118
118
|
- Are there related resolved entries? → Combine into a new locked entry
|
|
119
119
|
- Is it stale/fully consumed by release notes? → Archive or delete
|
|
120
|
-
- Is it unresolvable but still valuable? → Move to `{user}/` ongoing or keep
|
|
120
|
+
- Is it unresolvable but still valuable? → Move to `team-member/{user}/` ongoing or keep at `shared/` root ephemeral
|
|
121
121
|
3. For merged/new locked entries:
|
|
122
|
-
- Set `state: locked`, `type: synthesized`
|
|
123
|
-
-
|
|
122
|
+
- Set `state: locked`, `type: synthesized` (or `type: reference` for clean truths)
|
|
123
|
+
- Write to `workspace-context/shared/locked/{bare-name}.md` — locked files use bare names (location signals the type), so strip any `braindump_/handoff_/research_` prefix when promoting
|
|
124
124
|
- Write concise, focused content — team truths, not session history
|
|
125
|
-
4.
|
|
125
|
+
4. Regenerate auto-files so `canonical.md` and `index.md` reflect the new locked content:
|
|
126
126
|
```bash
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
node .claude/scripts/build-workspace-context.mjs --write --root .
|
|
128
|
+
```
|
|
129
|
+
5. Commit:
|
|
130
|
+
```bash
|
|
131
|
+
git add workspace-context/
|
|
132
|
+
git commit -m "release: synthesize workspace-context for v{version}"
|
|
129
133
|
```
|
|
130
134
|
|
|
131
135
|
**Step 10: Report**
|
|
@@ -137,6 +141,9 @@ Process ephemeral shared-context entries:
|
|
|
137
141
|
- Branch notes live in the WORKSPACE at `release-notes/unreleased/{repo}/`. `/complete-work` writes them; `/release` consumes and deletes them. They never reach project repos.
|
|
138
142
|
- Versions are bumped here, not in `/complete-work`. This keeps the version semantics aligned with what actually shipped (accumulated changes since last release).
|
|
139
143
|
- The public repo stays lean. Detailed per-branch retrospection exists in workspace git history (the consumed-notes commit) but is not surfaced as standalone files in either repo.
|
|
140
|
-
- Context synthesis happens in the WORKSPACE repo — Step 7c (consumed-notes) and Step 9 (
|
|
144
|
+
- Context synthesis happens in the WORKSPACE repo — Step 7c (consumed-notes) and Step 9 (workspace-context synthesis) are separate workspace commits.
|
|
141
145
|
- Per-repo is the default — each project repo has its own release cadence.
|
|
142
146
|
- The coherent-revisions rule applies: write the CHANGELOG entry from scratch, don't concatenate branch notes.
|
|
147
|
+
- Tagging happens in `/complete-work`, not here. When the session branch starts with `release/`, `/complete-work` tags the merge commit on the project repo's default branch and pushes the tag, which triggers `.github/workflows/publish.yml` to publish to npm. `/release` produces the synthesis (CHANGELOG entry + version bump + consumed-notes deletion); `/complete-work` does the push, PR, merge, and tag.
|
|
148
|
+
- Do not run `npm publish` locally. The publish workflow is the only path that exercises OIDC trusted publishing — local publish requires 2FA OTP and bypasses that. If the workflow fails, investigate via `gh run view`; do not fall back to local publish.
|
|
149
|
+
- Recovery from a failed publish. Transient failure: rerun via `gh run rerun {run_id}`. Content failure: delete the tag (`git push origin --delete v{version} && git tag -d v{version}`), then redo the release in a new release session — `/start-work`, then `/release v{version}`, then `/complete-work`. Once a version is published to npm, that version is committed on the registry; bump and start a new release.
|
|
@@ -249,7 +249,7 @@ If not: ask "Ready to start implementing, or want to brainstorm first?"
|
|
|
249
249
|
|
|
250
250
|
When /start-work is called after work has already begun:
|
|
251
251
|
|
|
252
|
-
1. Detect uncommitted changes in `repos/` or `
|
|
252
|
+
1. Detect uncommitted changes in `repos/` or `workspace-context/`
|
|
253
253
|
2. "It looks like you've already been working. Let me formalize this."
|
|
254
254
|
3. If changes are on a default branch: stash → create session → pop stash
|
|
255
255
|
4. If changes are already on a feature branch: create workspace worktree and nest the existing project worktree(s) under it, or create a fresh session if the work is small enough to re-apply
|
|
@@ -68,7 +68,7 @@ Ask the user:
|
|
|
68
68
|
|
|
69
69
|
This determines whether documentation extraction is part of the plan.
|
|
70
70
|
|
|
71
|
-
**Important:** If the user indicates a source, ask: "Has any content already been extracted from this source? (e.g., rules or context files already pulled down from Notion)" Check `
|
|
71
|
+
**Important:** If the user indicates a source, ask: "Has any content already been extracted from this source? (e.g., rules or context files already pulled down from Notion)" Check `workspace-context/` and `.claude/rules/` for files that appear to contain extracted content. If content already exists from a source, mark it as "already extracted" and skip re-fetching unless the user explicitly wants a refresh.
|
|
72
72
|
|
|
73
73
|
### Step 4: Present the plan
|
|
74
74
|
|
|
@@ -134,7 +134,7 @@ List all `.md.skip` files in `.claude/rules/`:
|
|
|
134
134
|
For each documentation source identified in Step 3:
|
|
135
135
|
|
|
136
136
|
**Before fetching from any source, check if content was already extracted:**
|
|
137
|
-
- Scan `
|
|
137
|
+
- Scan `workspace-context/` and `.claude/rules/` for files that reference the source (e.g., files mentioning Notion page IDs, Confluence URLs, etc.)
|
|
138
138
|
- If found: "Content from {source} appears to already be in {files}. Skip re-fetching? [Y/n]"
|
|
139
139
|
- If the user confirms skip: move on to the next source
|
|
140
140
|
- If the user wants a refresh: proceed with extraction but note which files will be updated
|
|
@@ -145,7 +145,7 @@ For sources that need extraction:
|
|
|
145
145
|
- **Track access failures** — if a source is unreachable, note it but don't stop
|
|
146
146
|
- For rules/conventions found: write to `.claude/rules/{rule-name}.md`
|
|
147
147
|
- For project context/decisions: stage for Step 10 (locked knowledge)
|
|
148
|
-
- For handoffs/active work: write to `
|
|
148
|
+
- For handoffs/active work: write to `workspace-context/team-member/{user}/` as ephemeral
|
|
149
149
|
|
|
150
150
|
**Commit:** `git commit -m "feat: extract rules and context from documentation sources"`
|
|
151
151
|
|
|
@@ -181,7 +181,7 @@ Write `workspace-scratchpad/chat-history-manifest.json`:
|
|
|
181
181
|
3. Update the manifest entry status to "processed"
|
|
182
182
|
4. Synthesize findings into shared context:
|
|
183
183
|
- Decisions and architecture → stage for locked context (Step 10)
|
|
184
|
-
- Work-in-progress context → `
|
|
184
|
+
- Work-in-progress context → `workspace-context/team-member/{user}/` as ephemeral handoffs
|
|
185
185
|
- Patterns and conventions → candidate rules for `.claude/rules/`
|
|
186
186
|
|
|
187
187
|
Present a summary: "Found {N} prior sessions. Extracted {M} decisions, {K} handoffs, {P} convention candidates."
|
|
@@ -199,7 +199,7 @@ rm -f workspace-scratchpad/chat-history-manifest.json
|
|
|
199
199
|
|
|
200
200
|
Read CLAUDE.md.bak for non-documentation content worth keeping:
|
|
201
201
|
- Local coding conventions → `.claude/rules/` (new rule files)
|
|
202
|
-
- Project-specific notes → `
|
|
202
|
+
- Project-specific notes → `workspace-context/shared/locked/` or `workspace-context/team-member/{user}/`
|
|
203
203
|
- Repo paths → verify they match workspace.json
|
|
204
204
|
|
|
205
205
|
**Commit:** `git commit -m "feat: preserve local preferences as rules and context"`
|
|
@@ -207,7 +207,7 @@ Read CLAUDE.md.bak for non-documentation content worth keeping:
|
|
|
207
207
|
### Step 10: Create locked team knowledge
|
|
208
208
|
|
|
209
209
|
Combine content from Steps 7, 8, 9, and existing auto-memory into locked context:
|
|
210
|
-
- For each piece of stable knowledge: write to `
|
|
210
|
+
- For each piece of stable knowledge: write to `workspace-context/shared/locked/{topic}.md`
|
|
211
211
|
- Keep locked context lean — target <10KB total
|
|
212
212
|
- One topic per file, proper frontmatter
|
|
213
213
|
- Only lock what the team needs every session. Everything else is ephemeral.
|
|
@@ -269,7 +269,7 @@ Save to `.claude/settings.local.json`:
|
|
|
269
269
|
|
|
270
270
|
### Step 14: Clean root directory
|
|
271
271
|
|
|
272
|
-
The workspace root should contain ONLY template structure: CLAUDE.md, workspace.json, .gitignore, and the standard directories (`.claude/`, `
|
|
272
|
+
The workspace root should contain ONLY template structure: CLAUDE.md, workspace.json, .gitignore, and the standard directories (`.claude/`, `workspace-context/`). The `repos/`, `work-sessions/`, and `workspace-scratchpad/` directories are lazy-created the first time something writes to them — they won't exist yet unless a repo has already been cloned.
|
|
273
273
|
|
|
274
274
|
Move everything else to `workspace-scratchpad/unmigrated/`:
|
|
275
275
|
|
|
@@ -299,8 +299,8 @@ Report: "Moved {N} items to workspace-scratchpad/unmigrated/: {list}."
|
|
|
299
299
|
|
|
300
300
|
Read EVERY created and activated file:
|
|
301
301
|
- Every `.claude/rules/*.md` (not .skip)
|
|
302
|
-
- Every `
|
|
303
|
-
- Every `
|
|
302
|
+
- Every `workspace-context/shared/locked/*.md`
|
|
303
|
+
- Every `workspace-context/team-member/{user}/*.md`
|
|
304
304
|
|
|
305
305
|
Check for:
|
|
306
306
|
- References to removed services or files
|
|
@@ -333,8 +333,8 @@ git remote -v
|
|
|
333
333
|
```bash
|
|
334
334
|
git rebase origin/main
|
|
335
335
|
```
|
|
336
|
-
If conflicts arise (e.g.,
|
|
337
|
-
- For
|
|
336
|
+
If conflicts arise (e.g., workspace-context differs between your init and what's already committed), STOP and present them. These are legitimate merge decisions — your extracted content vs what your teammate committed. Help the user resolve each conflict:
|
|
337
|
+
- For workspace-context files: the remote version likely has the teammate's extractions. Merge both perspectives or keep the more complete version.
|
|
338
338
|
- For rules: if both sides activated different optional rules, keep both.
|
|
339
339
|
- For CLAUDE.md: use the remote version (it's the established one), add any local customizations the user wants.
|
|
340
340
|
|
|
@@ -408,7 +408,7 @@ This session is done. Start a fresh Claude Code session and run /start-work to b
|
|
|
408
408
|
- **Don't suggest starting work at the end.** Tell the user to restart Claude Code and run /start-work in a fresh session.
|
|
409
409
|
- The verification step (Step 16) is mandatory — read every file, check thoroughly.
|
|
410
410
|
- **Build manifests before long operations.** Chat history scanning (Step 8) and worktree formalization (Step 11) can be interrupted by auto-compaction. Write a manifest to `workspace-scratchpad/` before starting so progress survives.
|
|
411
|
-
- **Never re-fetch content that already exists.** Always check
|
|
411
|
+
- **Never re-fetch content that already exists.** Always check workspace-context and rules for existing extractions before accessing external sources.
|
|
412
412
|
- This skill is idempotent — safe to run if interrupted and restarted.
|
|
413
413
|
|
|
414
414
|
## Notes
|
|
@@ -77,7 +77,7 @@ Read `toVersion` from `.workspace-update/.manifest.json` and update `templateVer
|
|
|
77
77
|
|
|
78
78
|
### Step 4a: Run idempotent migrators
|
|
79
79
|
|
|
80
|
-
The payload may include migrator scripts at `.workspace-update/.claude/scripts/migrate-*.mjs` that bring older workspaces forward in shape. They are idempotent — safe to re-run on already-migrated workspaces. Run each one and surface its action in the upgrade summary.
|
|
80
|
+
The payload may include migrator scripts at `.workspace-update/.claude/scripts/migrate-*.mjs` that bring older workspaces forward in shape. They are idempotent — safe to re-run on already-migrated workspaces. Run each one in document order and surface its action in the upgrade summary.
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
83
|
node .workspace-update/.claude/scripts/migrate-claude-md-freshness-include.mjs
|
|
@@ -89,6 +89,12 @@ Output is JSON: `{"action":"appended"|"unchanged"|"skipped"}`.
|
|
|
89
89
|
- `unchanged` — the line was already present.
|
|
90
90
|
- `skipped` — no `CLAUDE.md` exists at the workspace root (rare; surface to the user).
|
|
91
91
|
|
|
92
|
+
```bash
|
|
93
|
+
node .workspace-update/.claude/scripts/migrate-canonical-priority.mjs --root .
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Output is JSON: `{"status":"applied"|"noop","files":[...]}`. Back-fills `priority: critical` on every `workspace-context/shared/locked/*.md` that lacks the field, preserving today's full-load behavior until the user explicitly demotes a file. Idempotent — safe to re-run on already-migrated workspaces.
|
|
97
|
+
|
|
92
98
|
Add other migrators here as the template ships them.
|
|
93
99
|
|
|
94
100
|
### Step 5: Post-update verification
|
package/template/CLAUDE.md.tmpl
CHANGED
|
@@ -7,14 +7,15 @@ This is a claude-workspace. All conventions are defined in .claude/rules/.
|
|
|
7
7
|
- `/start-work` to create or resume a work session
|
|
8
8
|
- Each session is a self-contained folder at `work-sessions/{name}/` containing the worktree, nested project worktrees, and the session tracker
|
|
9
9
|
- From root: only `local-only-*` and `workspace-scratchpad/` are writable
|
|
10
|
-
-
|
|
10
|
+
- Team knowledge lives in `workspace-context/`
|
|
11
11
|
|
|
12
12
|
## Workspace Config
|
|
13
13
|
@workspace.json
|
|
14
14
|
@local-only-template-freshness.md
|
|
15
15
|
|
|
16
|
-
## Team Knowledge
|
|
17
|
-
@
|
|
16
|
+
## Team Knowledge
|
|
17
|
+
@workspace-context/canonical.md
|
|
18
|
+
@workspace-context/index.md
|
|
18
19
|
|
|
19
20
|
## Skills
|
|
20
21
|
- `/workspace-init` — first-time workspace setup (clone repos, install template, activate rules)
|
package/template/_gitignore
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
"versionCheck": { "ambient": true },
|
|
6
6
|
"scratchpadDir": "workspace-scratchpad",
|
|
7
7
|
"workSessionsDir": "work-sessions",
|
|
8
|
-
"
|
|
9
|
-
"releaseNotesDir": "release-notes",
|
|
8
|
+
"workspaceContextDir": "workspace-context",
|
|
9
|
+
"releaseNotesDir": "workspace-context/release-notes",
|
|
10
|
+
"canonicalBudgetBytes": 40960,
|
|
10
11
|
"subagentContextMaxBytes": 10240,
|
|
11
12
|
"greeting": "Welcome back to {{project-name}}.",
|
|
12
13
|
"releaseMode": "per-repo",
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Unit tests for bash-output-advisory.mjs pattern detection.
|
|
3
|
-
// Run: node .claude/hooks/_bash-output-advisory.test.mjs
|
|
4
|
-
import { detectNoisyPattern } from './bash-output-advisory.mjs';
|
|
5
|
-
|
|
6
|
-
let failed = 0;
|
|
7
|
-
let passed = 0;
|
|
8
|
-
|
|
9
|
-
function shouldWarn(command, label) {
|
|
10
|
-
const result = detectNoisyPattern(command);
|
|
11
|
-
if (result) {
|
|
12
|
-
passed++;
|
|
13
|
-
} else {
|
|
14
|
-
failed++;
|
|
15
|
-
console.error(` FAIL: ${label}\n command: ${command}\n expected an advisory, got null`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function shouldNotWarn(command, label) {
|
|
20
|
-
const result = detectNoisyPattern(command);
|
|
21
|
-
if (!result) {
|
|
22
|
-
passed++;
|
|
23
|
-
} else {
|
|
24
|
-
failed++;
|
|
25
|
-
console.error(` FAIL: ${label}\n command: ${command}\n expected null, got: ${result}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// === Test runners ===
|
|
30
|
-
shouldWarn('npm test', 'bare npm test');
|
|
31
|
-
shouldWarn('npm run test', 'bare npm run test');
|
|
32
|
-
shouldWarn('yarn test', 'bare yarn test');
|
|
33
|
-
shouldWarn('pnpm test', 'bare pnpm test');
|
|
34
|
-
shouldWarn('bun test', 'bare bun test');
|
|
35
|
-
shouldWarn('cargo test', 'bare cargo test');
|
|
36
|
-
shouldWarn('npm test --coverage', 'npm test with non-scoping flag');
|
|
37
|
-
|
|
38
|
-
shouldNotWarn('npm test path/to/file.test.mjs', 'npm test with file path');
|
|
39
|
-
shouldNotWarn('npm test src/', 'npm test with directory');
|
|
40
|
-
shouldNotWarn('npm test -- --grep auth', 'npm test with -- args');
|
|
41
|
-
shouldNotWarn('npm test myFile.test.js', 'npm test with bare filename');
|
|
42
|
-
shouldNotWarn('npm test | grep FAIL', 'npm test piped to grep');
|
|
43
|
-
shouldNotWarn('npm test | head -50', 'npm test piped to head');
|
|
44
|
-
shouldNotWarn('cargo test auth_module', 'cargo test with module filter');
|
|
45
|
-
|
|
46
|
-
// === grep -r ===
|
|
47
|
-
shouldWarn('grep -r "pattern" .', 'bare grep -r');
|
|
48
|
-
shouldWarn('grep --recursive "pattern" src/', 'grep --recursive long form');
|
|
49
|
-
shouldWarn('grep -rn "TODO" .', 'grep -rn (recursive + line numbers)');
|
|
50
|
-
|
|
51
|
-
shouldNotWarn('grep -r --include="*.js" pattern .', 'grep -r with --include');
|
|
52
|
-
shouldNotWarn('grep -r pattern . --exclude="*.log"', 'grep -r with --exclude');
|
|
53
|
-
shouldNotWarn('grep "pattern" file.txt', 'non-recursive grep');
|
|
54
|
-
|
|
55
|
-
// === find on broad anchors ===
|
|
56
|
-
shouldWarn('find /', 'find on root');
|
|
57
|
-
shouldWarn('find ~', 'find on home tilde');
|
|
58
|
-
shouldWarn('find $HOME', 'find on $HOME');
|
|
59
|
-
|
|
60
|
-
shouldNotWarn('find / -name "*.log"', 'find / with -name');
|
|
61
|
-
shouldNotWarn('find ~ -path "*node_modules*" -prune', 'find ~ with -path');
|
|
62
|
-
shouldNotWarn('find . -type f', 'find on cwd');
|
|
63
|
-
shouldNotWarn('find ./src -name "*.ts"', 'find on relative subdir');
|
|
64
|
-
|
|
65
|
-
// === cat on log-shaped files ===
|
|
66
|
-
shouldWarn('cat server.log', 'cat .log file');
|
|
67
|
-
shouldWarn('cat events.jsonl', 'cat .jsonl file');
|
|
68
|
-
shouldWarn('cat trace.ndjson', 'cat .ndjson file');
|
|
69
|
-
shouldWarn('cat path/to/big.log', 'cat .log in subdir');
|
|
70
|
-
|
|
71
|
-
shouldNotWarn('cat package.json', 'cat package.json');
|
|
72
|
-
shouldNotWarn('cat README.md', 'cat README');
|
|
73
|
-
shouldNotWarn('cat src/index.ts', 'cat source file');
|
|
74
|
-
shouldNotWarn('cat server.log | tail -50', 'cat .log piped to tail');
|
|
75
|
-
|
|
76
|
-
// === redirected output (always allowed) ===
|
|
77
|
-
shouldNotWarn('npm test > /tmp/test-output.txt', 'npm test redirected to file');
|
|
78
|
-
shouldNotWarn('grep -r foo . > out.txt', 'grep -r redirected to file');
|
|
79
|
-
shouldNotWarn('find / 2>&1 | tee /tmp/find.txt', 'find piped to tee');
|
|
80
|
-
|
|
81
|
-
// === unrelated commands ===
|
|
82
|
-
shouldNotWarn('git status', 'git status');
|
|
83
|
-
shouldNotWarn('ls -la', 'ls');
|
|
84
|
-
shouldNotWarn('echo hello', 'echo');
|
|
85
|
-
shouldNotWarn('node --version', 'node version');
|
|
86
|
-
|
|
87
|
-
console.log(`Passed: ${passed}, Failed: ${failed}`);
|
|
88
|
-
if (failed > 0) process.exit(1);
|