@ulysses-ai/create-workspace 0.17.0-beta.0 → 0.19.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/README.md +3 -3
- package/lib/init.mjs +4 -1
- package/lib/payload.mjs +18 -1
- package/lib/payload.test.mjs +55 -0
- package/lib/scaffold.mjs +23 -6
- package/lib/scaffold.test.mjs +59 -0
- package/package.json +1 -1
- package/template/CLAUDE.md.tmpl +19 -2
- package/template/{.claude → _claude}/hooks/_utils.mjs +1 -1
- package/template/_claude/hooks/repo-write-detection.mjs +204 -0
- package/template/{.claude → _claude}/hooks/session-start.mjs +35 -1
- package/template/_claude/hooks/subagent-start.mjs +111 -0
- package/template/{.claude → _claude}/lib/session-frontmatter.mjs +28 -0
- package/template/{.claude → _claude}/rules/coherent-revisions.md +1 -1
- package/template/_claude/rules/forge-operations.md +57 -0
- package/template/_claude/rules/git-conventions.md +39 -0
- package/template/_claude/rules/goal-driven-work.md +24 -0
- package/template/_claude/rules/honest-pushback.md +56 -0
- package/template/_claude/rules/memory-guidance.md +66 -0
- package/template/{.claude → _claude}/rules/superpowers-workflow.md.skip +1 -1
- package/template/{.claude → _claude}/rules/task-list-mirroring.md +6 -0
- package/template/_claude/rules/work-item-tracking.md +48 -0
- package/template/_claude/rules/workspace-structure.md +79 -0
- package/template/{.claude → _claude}/scripts/build-workspace-context.mjs +86 -30
- package/template/_claude/scripts/chat-record.mjs +315 -0
- package/template/_claude/scripts/cleanup-work-session.mjs +436 -0
- package/template/_claude/scripts/context-footprint.mjs +391 -0
- package/template/{.claude → _claude}/scripts/forges/github.mjs +46 -0
- package/template/{.claude → _claude}/scripts/forges/gitlab.mjs +3 -2
- package/template/{.claude → _claude}/scripts/forges/interface.mjs +13 -0
- package/template/{.claude → _claude}/scripts/generate-claude-local.mjs +21 -2
- package/template/_claude/scripts/migrate-sessions.mjs +1571 -0
- package/template/{.claude → _claude}/scripts/migrate-to-workspace-context.mjs +7 -2
- package/template/_claude/scripts/task-pr.mjs +447 -0
- package/template/_claude/scripts/task-worktree.mjs +525 -0
- package/template/{.claude → _claude}/scripts/trackers/github-issues.mjs +11 -0
- package/template/{.claude → _claude}/scripts/trackers/interface.mjs +8 -0
- package/template/_claude/scripts/workspace-diagnostics.mjs +654 -0
- package/template/{.claude → _claude}/skills/braindump/SKILL.md +12 -4
- package/template/{.claude → _claude}/skills/build-docs-site/SKILL.md +5 -5
- package/template/{.claude → _claude}/skills/build-docs-site/templates/spec.md.tmpl +1 -1
- package/template/_claude/skills/complete-work/SKILL.md +452 -0
- package/template/_claude/skills/context-placement/SKILL.md +202 -0
- package/template/{.claude/rules/goal-driven-work.md → _claude/skills/goal-driven-work/SKILL.md} +46 -19
- package/template/{.claude → _claude}/skills/handoff/SKILL.md +12 -4
- package/template/{.claude → _claude}/skills/maintenance/SKILL.md +56 -17
- package/template/_claude/skills/migrate-sessions/SKILL.md +70 -0
- package/template/{.claude → _claude}/skills/pause-work/SKILL.md +9 -1
- package/template/_claude/skills/release/SKILL.md +91 -0
- package/template/{.claude → _claude}/skills/start-work/SKILL.md +89 -7
- package/template/{.claude → _claude}/skills/workspace-init/SKILL.md +3 -1
- package/template/{.claude → _claude}/skills/workspace-update/SKILL.md +4 -0
- package/template/_gitignore +9 -0
- package/template/workspace.json.tmpl +4 -3
- package/template/.claude/hooks/repo-write-detection.mjs +0 -107
- package/template/.claude/hooks/subagent-start.mjs +0 -44
- package/template/.claude/rules/forge-operations.md +0 -107
- package/template/.claude/rules/git-conventions.md +0 -34
- package/template/.claude/rules/honest-pushback.md +0 -56
- package/template/.claude/rules/memory-guidance.md +0 -109
- package/template/.claude/rules/work-item-tracking.md +0 -90
- package/template/.claude/rules/workspace-structure.md +0 -137
- package/template/.claude/scripts/cleanup-work-session.mjs +0 -247
- package/template/.claude/skills/complete-work/SKILL.md +0 -498
- package/template/.claude/skills/release/SKILL.md +0 -151
- /package/template/{.claude → _claude}/agents/aside-researcher.md +0 -0
- /package/template/{.claude → _claude}/agents/implementer.md +0 -0
- /package/template/{.claude → _claude}/agents/researcher.md +0 -0
- /package/template/{.claude → _claude}/agents/reviewer.md +0 -0
- /package/template/{.claude → _claude}/hooks/bash-output-advisory.mjs +0 -0
- /package/template/{.claude → _claude}/hooks/post-compact.mjs +0 -0
- /package/template/{.claude → _claude}/hooks/pre-compact.mjs +0 -0
- /package/template/{.claude → _claude}/hooks/session-end.mjs +0 -0
- /package/template/{.claude → _claude}/hooks/version-freshness-check.mjs +0 -0
- /package/template/{.claude → _claude}/hooks/workspace-update-check.mjs +0 -0
- /package/template/{.claude → _claude}/lib/freshness.mjs +0 -0
- /package/template/{.claude → _claude}/lib/registry-check.mjs +0 -0
- /package/template/{.claude → _claude}/lib/require-node.mjs +0 -0
- /package/template/{.claude → _claude}/recipes/migrate-from-notion.md +0 -0
- /package/template/{.claude → _claude}/rules/agent-rules.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/cloud-infrastructure.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/config-review.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/documentation.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/local-dev-environment.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/product-integrity.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/scope-guard.md.skip +0 -0
- /package/template/{.claude → _claude}/rules/token-economics.md.skip +0 -0
- /package/template/{.claude → _claude}/scripts/add-repo-to-session.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/capture-context.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/create-work-session.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/migrate-canonical-priority.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/migrate-claude-md-freshness-include.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/migrate-open-work.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/migrate-session-layout.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/sweep-references.mjs +0 -0
- /package/template/{.claude → _claude}/scripts/sync-tasks.mjs +0 -0
- /package/template/{.claude → _claude}/settings.json +0 -0
- /package/template/{.claude → _claude}/skills/aside/SKILL.md +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/checklists/framing.md +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/checklists/pitfalls.md +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/checklists/review.md +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/scripts/bulk-fill-migration.py +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/scripts/forbidden-word-grep.mjs +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/scripts/leak-grep.mjs +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/custom.css.tmpl +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/docusaurus.config.ts.tmpl +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/Arrow.tsx +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/Box.tsx +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/DiagramContainer.tsx +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/Region.tsx +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/SectionTitle.tsx +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/primitives/tokens.ts +0 -0
- /package/template/{.claude → _claude}/skills/build-docs-site/templates/sidebars.ts.tmpl +0 -0
- /package/template/{.claude → _claude}/skills/promote/SKILL.md +0 -0
- /package/template/{.claude → _claude}/skills/setup-tracker/SKILL.md +0 -0
- /package/template/{.claude → _claude}/skills/sync-work/SKILL.md +0 -0
- /package/template/{.mcp.json → _mcp.json} +0 -0
|
@@ -263,3 +263,31 @@ export function writeSessionFile(filePath, fields, body = '') {
|
|
|
263
263
|
export function readSessionFields(filePath) {
|
|
264
264
|
return readSessionFile(filePath).fields;
|
|
265
265
|
}
|
|
266
|
+
|
|
267
|
+
// This module is a LIBRARY, not a CLI. Several skills say "update the tracker
|
|
268
|
+
// via the session-frontmatter helper", and the natural reading of that — given
|
|
269
|
+
// that everything else a skill invokes (sync-tasks.mjs, create-work-session.mjs,
|
|
270
|
+
// build-workspace-context.mjs) is a real CLI — is to run this file with flags.
|
|
271
|
+
//
|
|
272
|
+
// Without this guard, Node imports the module, finds no side effects, ignores
|
|
273
|
+
// the arguments and EXITS 0. The caller sees success, the frontmatter is
|
|
274
|
+
// untouched, and a `cmd || fallback` idiom never fires because exit 0 is
|
|
275
|
+
// success. That silently dropped a `workItem:` linkage during the gh:89
|
|
276
|
+
// session and was only caught by re-reading the file (gh:143).
|
|
277
|
+
//
|
|
278
|
+
// So: fail loudly and say what to call instead.
|
|
279
|
+
if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
|
|
280
|
+
process.stderr.write(
|
|
281
|
+
'session-frontmatter.mjs is a library, not a CLI — it takes no arguments.\n' +
|
|
282
|
+
'\n' +
|
|
283
|
+
'Import it instead:\n' +
|
|
284
|
+
' node --input-type=module -e \'\n' +
|
|
285
|
+
' import { updateSessionFile } from "./.claude/lib/session-frontmatter.mjs";\n' +
|
|
286
|
+
' updateSessionFile("session.md", { workItem: "gh:42" });\n' +
|
|
287
|
+
' \'\n' +
|
|
288
|
+
'\n' +
|
|
289
|
+
'Exports: parseSessionContent, updateSessionContent, updateSessionFile,\n' +
|
|
290
|
+
'readSessionFile, readSessionFields, writeSessionFile.\n',
|
|
291
|
+
);
|
|
292
|
+
process.exit(2);
|
|
293
|
+
}
|
|
@@ -19,6 +19,6 @@ Injected revisions create fragmented, hard-to-follow output where the seams betw
|
|
|
19
19
|
|
|
20
20
|
- When updating a section of a document, rewrite the entire section — not just the changed sentences
|
|
21
21
|
- When updating a workspace-context file, rewrite it as a fresh snapshot of current understanding
|
|
22
|
-
- When synthesizing multiple sources into
|
|
22
|
+
- When synthesizing multiple sources into a PR body or summary, write the narrative from scratch — don't concatenate
|
|
23
23
|
- When revising code with comments, ensure the comments tell a coherent story, not a changelog
|
|
24
24
|
- Small, isolated edits (fixing a typo, updating a single value) are fine — this rule targets substantive revisions
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/.claude/skills/**"
|
|
4
|
+
- "**/.claude/scripts/**"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Activate this rule if the workspace creates PRs, watches CI runs, or interacts with releases from skills. Sibling to `work-item-tracking.md` (which covers issues); together they cover everything a workspace does against a code-hosting forge.
|
|
8
|
+
|
|
9
|
+
# Forge Operations
|
|
10
|
+
|
|
11
|
+
**Skills never call `gh` (or `glab`, or any forge CLI) inline for pull-request, release, or
|
|
12
|
+
workflow-run operations.** They go through the adapter at `.claude/scripts/forges/{type}.mjs`,
|
|
13
|
+
reached via `createForge()` from `.claude/scripts/forges/interface.mjs`.
|
|
14
|
+
|
|
15
|
+
The interface module is the source of truth for the available methods and their shapes —
|
|
16
|
+
read it when you need the API. `/complete-work` and `/pause-work` each carry the exact calls
|
|
17
|
+
they make, so in practice you rarely need to look.
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
Switching code hosts becomes a `workspace.json` field plus one adapter file instead of a
|
|
22
|
+
sweep across six skills. Failure modes share typed errors — `PrNotFound`, `MergeRejected`,
|
|
23
|
+
`WorkflowNotFound`, `ReleaseNotFound` — instead of every callsite parsing stderr. And the
|
|
24
|
+
adapter takes an injectable `spawnFn`, so tests mock subprocesses rather than running them.
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
`workspace.json` → `workspace.forge`: `{ "type": "github" }`. `type` names the adapter module;
|
|
29
|
+
`github` is the default and the only complete one, `gitlab.mjs` is a stub that throws
|
|
30
|
+
`NOT_IMPLEMENTED`. Optional `repo` is an `owner/name` slug; unset or `"auto"` resolves from the
|
|
31
|
+
git `origin` remote. An absent `workspace.forge` is treated as `{ type: 'github' }`; setting it
|
|
32
|
+
to `false` makes every adapter method throw `FORGE_DISABLED`.
|
|
33
|
+
|
|
34
|
+
## Deliberate exceptions — do not "fix" these
|
|
35
|
+
|
|
36
|
+
These stay as direct `gh` calls. Wrapping them would create a leaky abstraction, so leave them
|
|
37
|
+
alone:
|
|
38
|
+
|
|
39
|
+
- **Issue lifecycle** — issues, comments, labels and milestones belong to the tracker adapter.
|
|
40
|
+
See `work-item-tracking.md`. The two abstractions are intentionally separate.
|
|
41
|
+
- **`/setup-tracker` repo configuration** — `gh repo view --json hasIssuesEnabled` and
|
|
42
|
+
`gh api repos/{slug} -X PATCH -f has_issues=true` are GitHub-API-specific setup, not
|
|
43
|
+
cross-cutting operations. A GitLab user's setup flow differs entirely.
|
|
44
|
+
- **`gh repo view` as a remote-type probe** — a one-line capability check, not an operation.
|
|
45
|
+
- **`gh repo create`** — an interactive one-off when a workspace has no remote.
|
|
46
|
+
- **Manual recovery prose** — `gh run rerun`, `gh run view`, `gh release view` in `/release`
|
|
47
|
+
guidance are for an operator at a terminal, not for skill code.
|
|
48
|
+
|
|
49
|
+
## Boundaries
|
|
50
|
+
|
|
51
|
+
The adapter covers the operations the template's skills actually perform, not every `gh`
|
|
52
|
+
capability. New operations land as additive interface methods, never by a skill going around
|
|
53
|
+
the adapter. Forge-native features — PR comments, review webhooks, branch protection — remain
|
|
54
|
+
UI and direct-CLI territory.
|
|
55
|
+
|
|
56
|
+
Workspaces predating `workspace.forge` keep working, since `createForge(undefined)` defaults to
|
|
57
|
+
GitHub. `/maintenance` surfaces a notice suggesting the explicit value.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Git Conventions
|
|
2
|
+
|
|
3
|
+
## Branching
|
|
4
|
+
|
|
5
|
+
- Prefixes: `feature/`, `bugfix/`, `chore/`
|
|
6
|
+
- Names: kebab-case after prefix, no grouping/nesting
|
|
7
|
+
- Examples: `feature/ble-provisioning`, `bugfix/mqtt-reconnect`
|
|
8
|
+
- All branches merge to the repo's default branch
|
|
9
|
+
- Branch names should be unique — if revisiting previous work, distinguish the new branch name
|
|
10
|
+
|
|
11
|
+
## Worktrees
|
|
12
|
+
|
|
13
|
+
Both lifecycles are built on worktrees; `workspace.sessionModel` in `workspace.json` routes new work to one of them.
|
|
14
|
+
|
|
15
|
+
**Task model** (`"task"`): one worktree per repo the task touches, created and removed with `.claude/scripts/task-worktree.mjs` (the chat stays at the workspace root):
|
|
16
|
+
|
|
17
|
+
- Project repos: `repos/{repo}/.claude/worktrees/{slug}/`, where `{slug}` is the branch with `/` replaced by `-`
|
|
18
|
+
- The workspace repo itself, addressed as `.`: `.claude/worktrees/{slug}/` — Claude Code's native worktree location
|
|
19
|
+
- Source clones at `repos/{repo}/` stay on their default branch; `/complete-work` tears each worktree down with `task-worktree.mjs --remove` (worktree first, then the branch)
|
|
20
|
+
|
|
21
|
+
**Session model** (default): N+1 worktrees in one self-contained folder at `work-sessions/{session-name}/`:
|
|
22
|
+
|
|
23
|
+
- `work-sessions/{session-name}/workspace/` — workspace worktree
|
|
24
|
+
- `work-sessions/{session-name}/workspace/repos/{repo-name}/` — project worktrees nested inside it (no symlink)
|
|
25
|
+
- Example, session `fix-auth` on `bugfix/fix-auth` touching `my-app` and `my-api`: `work-sessions/fix-auth/workspace/` plus `workspace/repos/my-app/` and `workspace/repos/my-api/`
|
|
26
|
+
- Teardown order is mandatory: project worktrees first, then the workspace worktree, then prune — the cleanup helper enforces it
|
|
27
|
+
|
|
28
|
+
The workspace `.gitignore` covers all of it: `repos` (no trailing slash) matches the root's `repos/` and every session worktree's nested `repos/`; `.claude/worktrees/` matches task worktrees of the workspace repo itself.
|
|
29
|
+
|
|
30
|
+
## Branch Maintenance
|
|
31
|
+
|
|
32
|
+
- Before creating a PR, fetch and rebase onto the latest parent branch
|
|
33
|
+
- If conflicts arise during rebase, stop and present them to the user — do not auto-resolve
|
|
34
|
+
|
|
35
|
+
## Commits
|
|
36
|
+
|
|
37
|
+
- Conventional commit format: `feat:`, `fix:`, `refactor:`, `chore:`, `docs:`
|
|
38
|
+
- Never amend commits unless explicitly asked
|
|
39
|
+
- Never force push unless explicitly asked
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Goal-Driven Work
|
|
2
|
+
|
|
3
|
+
How to use Claude Code's built-in `/goal` command in a Ulysses workspace for multi-phase, agent-team-driven work. `/goal` is the autonomy loop; this rule is the convention layer that gives the main agent durable phase state and a consistent dispatch pattern across turns and resumes.
|
|
4
|
+
|
|
5
|
+
## When to reach for `/goal`
|
|
6
|
+
|
|
7
|
+
Use `/goal` when the work meets all three:
|
|
8
|
+
|
|
9
|
+
1. **Multi-phase.** It naturally decomposes into discrete phases (research, design, implementation, validation, etc.) and the phases produce intermediate artifacts before the work is done.
|
|
10
|
+
2. **Verifiable end state.** "Done" can be demonstrated from the conversation transcript — a PR opened, a set of artifacts written, a test suite passing — rather than judged subjectively.
|
|
11
|
+
3. **Spans more than one or two turns of natural conversation.** Single-skill invocations (one brainstorm, one plan, one fix) don't need `/goal`; the existing skills carry them.
|
|
12
|
+
|
|
13
|
+
If any of the three fails, prefer plain session work or a single skill invocation. `/goal` is overhead. Pay it only when the work is long enough to earn it.
|
|
14
|
+
|
|
15
|
+
## The convention lives in a skill
|
|
16
|
+
|
|
17
|
+
Everything past this decision — the `goal-{topic}.md` frontmatter schema, the three phase
|
|
18
|
+
types, agent-team dispatch, gate conventions, the integration-branch model with per-phase
|
|
19
|
+
sub-PRs, model tiering, and the worked example — is in the `goal-driven-work` skill.
|
|
20
|
+
|
|
21
|
+
Invoke it before drafting a goal artifact or running a goal phase. It is a skill rather than
|
|
22
|
+
a rule because it is a procedure needed by the small number of sessions that run `/goal`,
|
|
23
|
+
not a constraint every session must carry. Loading it on demand keeps roughly 27 KB out of
|
|
24
|
+
every session's always-loaded context.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Honest Pushback
|
|
2
|
+
|
|
3
|
+
Do not agree to be agreeable. Do not keep trying things that aren't working. Do not assume
|
|
4
|
+
when you can verify. Challenge assumptions and flag concerns even when the user is
|
|
5
|
+
enthusiastic.
|
|
6
|
+
|
|
7
|
+
## What this means
|
|
8
|
+
|
|
9
|
+
- If an approach has obvious downsides, say so before implementing.
|
|
10
|
+
- If a decision contradicts an earlier one, name the contradiction.
|
|
11
|
+
- If scope is creeping, name it: "This started as X but is becoming Y. Split?"
|
|
12
|
+
- If you don't know, say so — don't fabricate confidence.
|
|
13
|
+
- If the idea is good, "that works" is enough. No embellishment.
|
|
14
|
+
- If you made a mistake, own it plainly. No hedging.
|
|
15
|
+
|
|
16
|
+
## No retry loops
|
|
17
|
+
|
|
18
|
+
If a fix produced the same error or an unexpected result twice, stop. Do not try a variation
|
|
19
|
+
of the same approach. Instead:
|
|
20
|
+
|
|
21
|
+
1. **State expected vs actual**, specifically — not "it didn't work" but "expected 200, got
|
|
22
|
+
403 with message X".
|
|
23
|
+
2. **Name the failing assumption.** What is surprising, and why?
|
|
24
|
+
3. **Research it.** Read the docs, search the error, read the source. Use web search if local
|
|
25
|
+
sources don't explain it.
|
|
26
|
+
4. **Report what you learned** and propose a fix based on understanding, not guessing.
|
|
27
|
+
|
|
28
|
+
This stops the cycle of trying broken variations when reading the docs would take one turn.
|
|
29
|
+
|
|
30
|
+
## Verify, don't assume
|
|
31
|
+
|
|
32
|
+
When evidence is available, check it before proceeding. Logs, the database, the actual UI,
|
|
33
|
+
runtime state, a real API call — whichever settles the question. If the logs aren't verbose
|
|
34
|
+
enough, add instrumentation, run it, read the output, remove it.
|
|
35
|
+
|
|
36
|
+
The tell is reaching for "I think the issue is…", "probably", or "likely" about something
|
|
37
|
+
you could check in one step. Reasoning about what a function returns when you could call it
|
|
38
|
+
is the same mistake.
|
|
39
|
+
|
|
40
|
+
**Ask once**, then stop asking: "I want to verify {what} by {how}. Go ahead, or should I
|
|
41
|
+
just check without asking each time?" If the user says just check, verify proactively for
|
|
42
|
+
the rest of the session. Asking once is polite; asking every time is friction.
|
|
43
|
+
|
|
44
|
+
Use judgment — don't over-verify the trivial.
|
|
45
|
+
|
|
46
|
+
## What this does not mean
|
|
47
|
+
|
|
48
|
+
Don't be contrarian as a personality trait; push back where there is substance. Don't refuse
|
|
49
|
+
to execute — voice the concern, then follow the user's decision. Don't lecture: state it
|
|
50
|
+
once and move on.
|
|
51
|
+
|
|
52
|
+
## Why
|
|
53
|
+
|
|
54
|
+
Sycophancy wastes time and lets bad decisions through. Retry loops burn tokens. Assumptions
|
|
55
|
+
that could have been checked cascade into wrong decisions. A useful collaborator says when
|
|
56
|
+
something is off, stops when it isn't working, and finds out why before trying again.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Memory and Placement Guidance
|
|
2
|
+
|
|
3
|
+
Where durable content goes, and what each destination costs.
|
|
4
|
+
|
|
5
|
+
## Where durable content goes
|
|
6
|
+
|
|
7
|
+
Eight destinations, ordered cheapest first. Work down and stop at the first that genuinely
|
|
8
|
+
fits. The right column is what every session pays, forever, for the choice.
|
|
9
|
+
|
|
10
|
+
| destination | for | always-loaded cost |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| nowhere | already covered, or true only today | zero |
|
|
13
|
+
| `.claude/rules/*.md` with `paths:` | an instruction that applies only to certain files | zero until a match is read |
|
|
14
|
+
| a skill | a procedure with steps, invoked on demand | its `description` line |
|
|
15
|
+
| auto-memory | machine-local preference or correction; not shared, not reviewable | one `MEMORY.md` line |
|
|
16
|
+
| `team-member/{user}/` | one person's working context | one index line, that user |
|
|
17
|
+
| `shared/` | team-visible reference, looked up when relevant | one index line |
|
|
18
|
+
| `shared/locked/` | canonical team truth | **the whole file, every session** |
|
|
19
|
+
| `.claude/rules/*.md` (no `paths:`) | an instruction that must hold in every session | **the whole file, every session** |
|
|
20
|
+
|
|
21
|
+
**`nowhere` is the most common correct answer.** A second copy in a second location is
|
|
22
|
+
worse than none — they drift, and the reader cannot tell which is current.
|
|
23
|
+
|
|
24
|
+
The two bold rows tax every session in this workspace, and anything shipped in the template
|
|
25
|
+
taxes every downstream workspace too. Reach them only after the cheaper rows are actually
|
|
26
|
+
ruled out. Prefer `paths:` for anything domain-specific: a rule about migration scripts does
|
|
27
|
+
not need to be in context while editing documentation.
|
|
28
|
+
|
|
29
|
+
**Before writing to either bold row, state the cost:**
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
node .claude/scripts/context-footprint.mjs --root . --add <bytes> --as <destination>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A rule that applies only to certain files should carry `paths:` frontmatter — it costs nothing
|
|
36
|
+
until a matching file is touched — and the same script checks the live total against
|
|
37
|
+
`workspace.alwaysLoadedBudgetBytes`.
|
|
38
|
+
|
|
39
|
+
## The canonical test
|
|
40
|
+
|
|
41
|
+
Canonical describes what *is* and what *to do*, never what *to think*.
|
|
42
|
+
|
|
43
|
+
> If Claude read this for the first time during a session about an unrelated topic, would it
|
|
44
|
+
> (a) help frame the problem correctly, or (b) push it toward a particular answer to a
|
|
45
|
+
> question that hasn't been asked yet?
|
|
46
|
+
|
|
47
|
+
(a) is canonical. (b) is `shared/` at most, more often `team-member/{user}/`. Pre-loaded
|
|
48
|
+
conclusions don't read as opinions to Claude — they read as ground truth, and they frame
|
|
49
|
+
what Claude considers before the question is asked.
|
|
50
|
+
|
|
51
|
+
## Auto-memory specifically
|
|
52
|
+
|
|
53
|
+
Save: architecture decisions and their rationale, patterns that caused bugs, user
|
|
54
|
+
corrections about project conventions, external URLs and API quirks, tooling workarounds.
|
|
55
|
+
|
|
56
|
+
Don't save: temporary debugging state, file contents (re-read them), anything already in a
|
|
57
|
+
workspace-context file or a rule.
|
|
58
|
+
|
|
59
|
+
When work is in flight, its decisions and progress go in the lifecycle's own state — the
|
|
60
|
+
session tracker body at `work-sessions/{name}/workspace/session.md` (session model) or the
|
|
61
|
+
chat drawer at `workspace-scratchpad/chats/{chat}/` (task model) — which `/complete-work`
|
|
62
|
+
consumes. Auto-memory is for what outlives the work. Never both.
|
|
63
|
+
|
|
64
|
+
For the full routing procedure, the frontmatter schema, the generator invocations, and the
|
|
65
|
+
belongs/doesn't-belong lists behind the canonical test, invoke the `context-placement`
|
|
66
|
+
skill.
|
|
@@ -12,7 +12,7 @@ Activate this rule if the superpowers plugin is installed.
|
|
|
12
12
|
## Specs and Plans
|
|
13
13
|
|
|
14
14
|
- Specs and plans live in the active worktree during development
|
|
15
|
-
- They are ephemeral — consumed by /complete-work into
|
|
15
|
+
- They are ephemeral — consumed by /complete-work into the PR body, then removed
|
|
16
16
|
- If a spec/plan already exists for the current branch, version it: `-v2`, `-v3`, etc.
|
|
17
17
|
|
|
18
18
|
## Execution
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "work-sessions/**"
|
|
4
|
+
- "**/session.md"
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# Task List Mirroring
|
|
2
8
|
|
|
3
9
|
The Claude Code `TodoWrite` checklist is a live mirror of the workspace lifecycle. The durable backing store is a `## Tasks` section in `session.md`, round-tripped by `.claude/scripts/sync-tasks.mjs`. This rule defines the contract.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Work Item Tracking
|
|
2
|
+
|
|
3
|
+
When a workspace has a tracker configured, **all work items — bugs, features, chores — live
|
|
4
|
+
in that tracker.** There is no local file mirroring its state. Skills reach it through
|
|
5
|
+
`createTracker()` from `.claude/scripts/trackers/interface.mjs`; that module is the source of
|
|
6
|
+
truth for the available methods, and the four skills that use it (`start-work`, `pause-work`,
|
|
7
|
+
`complete-work`, `setup-tracker`) each carry the exact calls they make.
|
|
8
|
+
|
|
9
|
+
## Why external-first
|
|
10
|
+
|
|
11
|
+
Two people can't start the same ticket — the tracker is the source of truth for who has what.
|
|
12
|
+
Status changes reach the whole team the moment they happen rather than after a push. And
|
|
13
|
+
humans and Claude read the same list in the same place.
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
`workspace.json` → `workspace.tracker`: `{ "type": "github-issues", "repo": "owner/name" }`.
|
|
18
|
+
`type` names the adapter at `.claude/scripts/trackers/{type}.mjs`; only `github-issues` ships.
|
|
19
|
+
`repo` is adapter-specific — for GitHub, the slug where issues live, or `"auto"` to resolve
|
|
20
|
+
from the git remote. No `workspace.tracker` means tracking is disabled, and skills fall back
|
|
21
|
+
to a blank describe-the-work flow rather than fabricating a local mirror.
|
|
22
|
+
|
|
23
|
+
## Session linkage
|
|
24
|
+
|
|
25
|
+
`/start-work` records the adapter-prefixed issue ID in session frontmatter as `workItem: gh:42`.
|
|
26
|
+
The prefix makes it self-describing across adapter swaps.
|
|
27
|
+
|
|
28
|
+
## When to create issues
|
|
29
|
+
|
|
30
|
+
- **Work described during `/start-work`** → create the issue, then claim it.
|
|
31
|
+
- **A bug or feature found mid-session** → ask "Create an issue for this? [Y/n]". Link it to
|
|
32
|
+
the session if it is in scope; leave it unassigned if it is a future concern.
|
|
33
|
+
- **Never during braindumps or handoffs.** Those are discussion artifacts. Action items can
|
|
34
|
+
graduate to issues later, at `/start-work`.
|
|
35
|
+
|
|
36
|
+
## What not to do
|
|
37
|
+
|
|
38
|
+
- Do not create, read, or write `workspace-context/open-work.md`. It is deprecated.
|
|
39
|
+
- Do not put ticket state in session frontmatter beyond the `workItem:` pointer. Status,
|
|
40
|
+
assignment, labels and milestone live in the tracker.
|
|
41
|
+
- Do not cache issue bodies locally. Fetch with `tracker.getIssue(id)` when you need one.
|
|
42
|
+
|
|
43
|
+
## Boundaries
|
|
44
|
+
|
|
45
|
+
Adapter choice is per workspace; this rule prescribes no particular tracker. Beyond the six
|
|
46
|
+
labels `ensureLabels()` creates (`bug`, `feat`, `chore`, `P1`, `P2`, `P3`), it prescribes no
|
|
47
|
+
schema — teams with an existing tracker skip label creation. Tracker-native features like
|
|
48
|
+
comments, reactions and linked PRs stay in the tracker's own UI.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Workspace Structure
|
|
2
|
+
|
|
3
|
+
All paths are relative to the workspace root. Two work lifecycles coexist, selected for new work by `workspace.sessionModel` in `workspace.json`: **task** (the forward path — one issue, one branch, one worktree per touched repo, chat at the root) and **session** (supported — a self-contained `work-sessions/{name}/` folder per effort with a workspace worktree and a `session.md` tracker).
|
|
4
|
+
|
|
5
|
+
## Directory Layout
|
|
6
|
+
|
|
7
|
+
| Path | Purpose | Tracked? |
|
|
8
|
+
|------|---------|----------|
|
|
9
|
+
| `repos/{repo}/` | Source clones (always on the default branch) | No |
|
|
10
|
+
| `repos/{repo}/.claude/worktrees/{slug}/` | Task worktree for a project repo (`{slug}` = branch with `/` → `-`) | No |
|
|
11
|
+
| `.claude/worktrees/{slug}/` | Task worktree for the workspace repo (`--repo .`) — Claude Code's native worktree location; the two converge | No |
|
|
12
|
+
| `work-sessions/{name}/workspace/…` | Session lifecycle: workspace worktree, nested project worktrees at `workspace/repos/{repo}/`, `session.md` + artifacts (`design/plan/goal/research/crossref-*.md`) on top | Session branch |
|
|
13
|
+
| `workspace-context/` | Team knowledge: `shared/` (ephemerals), `shared/locked/` (canonical truths), `team-member/{user}/` (per-user) | Yes |
|
|
14
|
+
| `workspace-context/index.md`, `canonical.md`, `team-member/{user}/index.md` | Auto-generated catalogs (`canonical.md` = verbatim `shared/locked/`; `.indexignore` excludes paths) — regenerate with `build-workspace-context.mjs`, never hand-edit | Yes |
|
|
15
|
+
| `workspace-scratchpad/` | Machine-local, regenerable: session log, hook debug output, chat records `chats/{chat}.json`, chat drawers `chats/{chat}/` (task-lifecycle designs, plans, braindumps, research in progress) | No |
|
|
16
|
+
| `CLAUDE.md`, `CLAUDE.local.md`, `.claude/` | Launcher prompt (imports `canonical.md` + `index.md`); per-user prompt; rules, agents, skills, hooks, scripts | All but `CLAUDE.local.md`, `settings.local.json`, `.claude/.active-session.json`, and `.claude/worktrees/` |
|
|
17
|
+
|
|
18
|
+
## Workspace-Context Levels
|
|
19
|
+
|
|
20
|
+
| Level | Path | What lives there | How it gets there |
|
|
21
|
+
|-------|------|------------------|-------------------|
|
|
22
|
+
| Personal | `team-member/{user}/` | Per-user braindumps, handoffs, research | Default for `/braindump`, `/handoff`, `/aside` (session lifecycle / no drawer; task-lifecycle chats default to the chat drawer) |
|
|
23
|
+
| Shared | `shared/` | Team-visible ephemerals | Explicit `--scope shared` or `/promote` |
|
|
24
|
+
| Canonical | `shared/locked/` | Promoted truths — conventions, discipline, status | `/promote` (locked target) |
|
|
25
|
+
|
|
26
|
+
Canonical loads verbatim into every session (`CLAUDE.md` → `@workspace-context/canonical.md`); personal only for the active user (`CLAUDE.local.md`). Inflight work state (session tracker, chat drawer) never lives in `workspace-context/` — that is for knowledge that outlives any single effort.
|
|
27
|
+
|
|
28
|
+
## Dynamic context loading (hooks)
|
|
29
|
+
|
|
30
|
+
- **`session-start.mjs`** (`SessionStart`): injects the workspace name, a `Chat record:` line naming this chat's record, and a `Workspace root:` line with the launcher's absolute path (git-derived roots land on the source clone from inside a task worktree); with an active session pointer, also the session's name, branch, work item, and shared-context catalog.
|
|
31
|
+
- **`subagent-start.mjs`** (`SubagentStart`): gives subagents the canonical truths they miss (subagents do not load `CLAUDE.md`) — locked files under `workspace.subagentInlineMaxBytes` (8192) are inlined with frontmatter stripped, larger ones become pointers, and past `workspace.subagentContextMaxBytes` (32768) the largest demote first. Gitignored and `local-only-*` files are excluded.
|
|
32
|
+
|
|
33
|
+
Both are Node.js scripts — cross-platform, no shell dependency.
|
|
34
|
+
|
|
35
|
+
## Spec and Plan Locations — MANDATORY OVERRIDE
|
|
36
|
+
|
|
37
|
+
**Specs, plans, and goal artifacts MUST be written to the current lifecycle's work area, not to `docs/superpowers/` or any other location.**
|
|
38
|
+
|
|
39
|
+
- Session: top of the session worktree — `design-{topic}.md`, `plan-{topic}.md`, `goal-{topic}.md`, plus goal-native `research-*.md`/`crossref-*.md` siblings. On the session branch; stripped before the final PR.
|
|
40
|
+
- Task: the chat drawer `workspace-scratchpad/chats/{chat}/` — same artifact names. Machine-local; `/complete-work` promotes what deserves to survive into `workspace-context/`.
|
|
41
|
+
|
|
42
|
+
This overrides external skills' default paths (e.g., Superpowers' `docs/superpowers/specs/`) — those skills defer to user preferences, and this rule IS that override. Never create `docs/superpowers/` directories. Version an existing artifact: `design-{topic}-v2.md`.
|
|
43
|
+
|
|
44
|
+
## File Naming Conventions
|
|
45
|
+
|
|
46
|
+
Ephemeral files under `shared/` and `team-member/{user}/` carry a type prefix:
|
|
47
|
+
|
|
48
|
+
| Skill | Filename prefix |
|
|
49
|
+
|-------|-----------------|
|
|
50
|
+
| `/braindump` | `braindump_{topic}.md` |
|
|
51
|
+
| `/handoff` | `handoff_{topic}.md` |
|
|
52
|
+
| `/aside` (full) / `--quick` | `research_{topic}.md` / `braindump_{topic}.md` (`variant: aside`) |
|
|
53
|
+
| `/promote` | preserves source prefix |
|
|
54
|
+
|
|
55
|
+
Local-only drafts add a `local-only-` prefix to stay gitignored until promoted.
|
|
56
|
+
|
|
57
|
+
## Rules
|
|
58
|
+
|
|
59
|
+
- The workspace root stays on its default branch — it is the launcher, not a worktree.
|
|
60
|
+
- All real work happens in worktrees — `work-sessions/{name}/workspace/` (session) or a `.claude/worktrees/{slug}/` location (task). Source clones at `repos/{repo}/` never take a feature branch.
|
|
61
|
+
- Session content commits to the session branch; task work to task worktrees; drawer writes need no commit (gitignored, machine-local).
|
|
62
|
+
- `workspace-scratchpad/` is machine-local and regenerable — losing it costs a re-derivation, not the work. Not all of it is disposable: `session-log.jsonl` is real history no other file carries.
|
|
63
|
+
- Hand edits to auto-generated catalogs are overwritten by `build-workspace-context.mjs` — update the source files (or their `description:` frontmatter) instead.
|
|
64
|
+
|
|
65
|
+
## Per-repo commands
|
|
66
|
+
|
|
67
|
+
Per-repo test, lint, and build commands belong in `repos/{repo}/CLAUDE.md` under `## Commands`, scoping invocations to that repo instead of the whole monorepo. `/workspace-init` scaffolds the stub.
|
|
68
|
+
|
|
69
|
+
## Explore before editing
|
|
70
|
+
|
|
71
|
+
Before editing an unfamiliar codebase, map the affected surface first — typically a `researcher.md` subagent dispatch (`disallowedTools: [Edit, Write, Bash]`) returning affected files, callers, and dependencies. Edit only after the map is established.
|
|
72
|
+
|
|
73
|
+
## Launching Claude inside a worktree
|
|
74
|
+
|
|
75
|
+
A git worktree is a context boundary: `CLAUDE.md` discovery stops at the worktree's root, and gitignored content (`repos/`, `local-only-*`, `workspace-scratchpad/`) is absent from it. So a chat launched inside a project worktree — a session's `workspace/repos/{repo}/` or a task's `repos/{repo}/.claude/worktrees/{slug}/` — sees only that repo's own `CLAUDE.md`, not the workspace conventions or hooks. Keep the chat at the workspace root and reach worktrees by path; launch inside one only for deliberately isolated, repo-only work.
|
|
76
|
+
|
|
77
|
+
## Grep vs LSP
|
|
78
|
+
|
|
79
|
+
**Grep/Ripgrep** searches content as text — fast, no server, but no language awareness, so symbol searches surface false positives. **LSP** (`mcp__lsp__*`) understands types and scope — find-all-references returns only real usages — but needs an LSP MCP server in `.mcp.json`. Grep when you don't know where to look; LSP for precise navigation of a specific symbol.
|