| name | promote |
| description | Crystallise a closed workspace's results into its target project. Reads `_summary.md`, proposes Key Facts + Related Workspaces references + new tasks, appends on approval. The bridge between divergent thinking (`/focus`) and convergent execution (`/project`). Use after `/close` has produced `_summary.md`. |
| gui | {"label":"/promote","hint":"Crystallise a closed workspace into its project hub","match":["workspace/*/_workspace.md","workspace/*/_summary.md"],"arg":"workspace-id","order":22,"mode":"live"} |
/promote — Workspace → Project Crystallisation
Conduct all conversation with the user — and write all generated output — in the language defined by .claude/rules/personal-language.md (or the user's input language if that file is absent). Follow the language rules in full — exceptions and translation quality are defined in the Language Rules of .claude/rules/rill-core.md and the vault's personal-*.md overrides, never restated per skill. The English instructions below are for skill clarity, not for output style.
Tool references in this skill (Read, Edit, Grep, Glob, AskUserQuestion, shell) describe intent, not Claude-specific tool calls. Each harness should map them to its native equivalent — Claude Code uses its built-in tools as named; Codex CLI uses apply_patch / its own question primitive / shell as appropriate.
Decants a closed workspace's results into the project execution hub:
- Workspace artifact references →
_project.md ## Related Workspaces (refreshed by /refresh-project, but /promote may write provisional entries)
- Key findings →
_project.md ## Key Facts (3–5 items, user-confirmed)
- Actionable items in the workspace → optional new tasks under
tasks/{slug}/_task.md with mentions: [projects/{target-id}]
This skill is the bridge between divergent thinking (/focus, workspace artifacts) and convergent execution (/project, task hub).
Prerequisite — closed workspaces only
/promote requires the workspace's _summary.md to exist. _summary.md is generated by /close's Phase 2 (analysis sub-agent). Active workspaces do not have one yet — running /promote against an active workspace will error out and suggest running /close first.
If the user really needs to crystallise mid-workspace insights without closing, the correct path is to author the workspace artifact manually and rerun /promote after closing. There is no "force" or "draft" mode here — the design contract is that promotion follows summarisation.
Arguments
$ARGUMENTS — one of:
{workspace-id} (e.g. 2026-04-24-stock-distribution-and-seo-foundation or full path workspace/2026-04-24-stock-distribution-and-seo-foundation/_workspace.md) → Promote the named workspace
- Omitted → Inspect
.claude/state/current-workspace (if present) for the in-focus workspace; otherwise ask via the harness's question primitive
Procedure
Phase 0: Workspace resolution + summary check
- Resolve the argument to a workspace directory:
workspace/{id}/
- Verify
workspace/{id}/_workspace.md (or legacy _session.md / _project.md) exists. If not, exit with one-line error
- Check
workspace/{id}/_summary.md:
- Missing → exit with: "_summary.md not found. This workspace has not been closed yet. Run
/close {workspace-id} first." Do not attempt to run /close automatically
- Present → continue
- Read the workspace's frontmatter
status:
- If
status: active (but _summary.md exists for some reason — e.g. user reopened after close) → warn and ask whether to proceed
- If
status: completed (the expected case) → continue
- Otherwise → continue with a note
Phase 1: Target project resolution
By default /promote proposes creating a new project for the workspace, not merging into an existing one. A workspace is a single design session whose actionable items form one execution unit; co-locating that unit under its own project keeps "where is this workspace's execution layer?" trivially answerable. The user may still merge into an existing project — /promote just stops defaulting to it.
-
Read the workspace's _workspace.md frontmatter mentions. Extract every entry matching projects/{id}
-
Pre-check mentioned projects — for each projects/{id} in mentions, Read projects/{id}/_project.md and classify:
- eligible:
status: planning / active / paused
- ineligible — done:
status: done (these projects are no longer accumulating work and must not receive new tasks)
- ineligible — stale:
_project.md does not exist (stale mention after rename or cleanup)
- malformed:
_project.md exists but frontmatter is malformed (no status field, or unreadable). Excluded from option (b) AND announced loudly in the Question 1 prelude so the user knows to repair the broken target if they intended it as the promotion destination (rather than silently routing the workspace into a fresh project hub)
status is the sole gate for healthy existing projects. Body-text markers (e.g. "decomposed into sub-projects", "umbrella dissolved") are not part of the check — the vault language is unconstrained and any body-pattern check is brittle. Projects in active umbrella-dissolution should already carry status: done
-
Suggest a new-project slug from the workspace id / name: strip the leading YYYY-MM-DD- date prefix, strip trailing -design / -investigation / -exploration suffixes if present, and propose the remainder. Example: 2026-05-14-ai-agent-language-localization-design → suggest ai-agent-language-localization. The user may rename (e.g. prefix with a parent-project tag) at confirmation time
-
Ask the user via the harness's question primitive (Question 1 — coarse choice). If any mentioned projects were excluded by pre-check (malformed, stale, or done), prepend a warning line before the question so the user can see what was filtered out — particularly important in mixed cases where one mention is eligible and another was silently dropped:
Note: {X} mentioned project{s} excluded from option (b):
- projects/{id-x} — malformed (no status field) — repair if you intended this as the target
- projects/{id-y} — stale (file not found at projects/{id-y}/_project.md)
- projects/{id-z} — done (no longer accepting new tasks)
How should the workspace's results land?
(a) Create a new project (default, recommended)
Suggested slug: {suggested-slug}
Reason: 1 workspace = 1 execution unit; keep this workspace's tasks under their own hub
(b) Merge into an existing project
({N} eligible candidate{s} remaining{; see exclusions above})
(c) Specify a different project (slug)
-
Branch on the answer:
- (a) new project → branch to Phase 4 (new-project path), which is now the default path, not an exception
- (b) merge into existing:
- If exactly 1 eligible candidate → that is the target; continue to Phase 2
- If 2+ eligible candidates → ask a second question (Question 2) listing each eligible
projects/{id} as a flat option (one per row, with status: ...). The user selects one. Cap the list at 4 (AskUserQuestion's max); if more than 4 eligible candidates exist, list the 3 most-recently-touched and add a 4th option "Specify another slug" that falls through to (c) handling
- (c) specify other → ask for the slug. Validate
projects/{slug}/_project.md:
- File missing → ask if the user meant to create a new project with that slug; on yes, fall through to (a) with the slug as the suggestion; on no, re-prompt
- File exists and
status: done → refuse: "Project is done and not accepting new tasks. Pick another slug or take option (a)"
- File exists but frontmatter is malformed → refuse: "Project's
_project.md is malformed. Repair it before promoting (see Error handling)" and exit /promote
- File exists and
status ≠ done → record this slug as the target. Do not edit the workspace's mentions yet — the backlink is written at the end of Phase 5 only if Phase 3 succeeds (avoids leaving the workspace linked to a project the user later cancelled into)
-
Edge case — zero eligible candidates (eligible == 0, whether because there are zero mentions, all mentions are done, all are stale, or all are malformed): option (b) is suppressed entirely. Present (a) and (c) only, default still (a). When the suppression is because of done/stale/malformed mentions, announce why in the prelude: "All mentioned projects are ineligible ({K} done / {M} stale / {L} malformed); pick (a) new project or (c) specify another slug"
Phase 2: Candidate extraction
Read workspace/{id}/_summary.md and the workspace directory's artifacts (NNN-*.md). Build three candidate lists:
- Artifact references — every artifact file in the workspace, with its
type (decision / research / analysis / progress / review) and its # heading. These will be linked from the project, not duplicated
- Key findings (3–5 items) — pull from
_summary.md's Decisions / Key Findings section. The user will confirm before they land in ## Key Facts
- Actionable items — checkbox items in
_workspace.md or in artifacts that look like committed actions (- [ ] do X). Same extraction rules as /distill's _distill/task-extraction.md (see that file for the qualitative test of what counts as an action)
Present the candidates to the user via the harness's question primitive:
## /promote candidates — workspace: {id} → project: {target-slug}
### Decisions / Key Findings (proposed for Key Facts append, 3–5 max)
- {finding 1} (source: 003-...md)
- {finding 2} (source: _summary.md)
- ...
### Workspace artifacts (proposed for Related Workspaces reference)
- {summary}: workspace/{id}/_summary.md
- {artifact title}: workspace/{id}/NNN-*.md (type: decision)
- ...
### Actionable items (proposed for new tasks under tasks/{...}/)
- [ ] {item 1} — source: workspace/{id}/005-distribution-plan.md
- [ ] {item 2} — source: workspace/{id}/003-decision.md
- ...
Choose:
- Promote all
- Pick individually (interactive)
- Adjust the Key Facts wording before append
- Cancel
Phase 3: Append to target project + optional task creation
After user approval:
## Key Facts append — Edit projects/{slug}/_project.md to add the approved findings as bullet items at the end of ## Key Facts, each annotated with the workspace id for provenance:
- {finding} (workspace/{id}, {YYYY-MM-DD})
If ## Key Facts already has 20 items (the soft cap defined in .claude/rules/rill-projects.md), warn the user. Do not auto-move overflow to knowledge/notes/ — that's a /distill knowledge-agent responsibility
- Related Workspaces —
/refresh-project {slug} will pick up the workspace via mentions reverse-lookup automatically. /refresh-project lists both active and completed workspaces (the latter capped at the 20 most-recently-touched), each with an explicit status: marker. The workspace is already linked via mentions: [projects/{slug}]. /promote does not directly edit this section; it just makes sure the next /refresh-project will reflect the change
- Task creation — for each approved actionable item:
- Check for duplicates against existing tasks in
tasks/ (Grep the title, judge whether the existing one already covers it)
- If unique: invoke
_task:create-agent in extract mode with source_path={artifact-path}, candidate={the actionable item}, and shared taxonomy / people / orgs / projects context. The agent owns slug generation, frontmatter assembly, and substance authoring; it creates tasks/{slug}/_task.md with status: draft per its contract. Note: the agent's extract mode can transparently fall back to enrich when it detects a duplicate, returning an existing task's path instead of a new draft.
- After the agent returns the path: Read the returned file's frontmatter
status. Flip status: draft → status: open only if the current status is draft (the newly-created case). If the status is anything else (open / waiting / done / cancelled), the agent enriched an existing task — leave its status untouched to preserve its existing workflow state. Regardless of the status path, Edit mentions to include projects/{target-slug} if not already present (the agent does not know /promote's target project). Rationale for the draft → open flip on newly-created tasks: /promote itself gates task creation behind the Phase 2 candidate-approval AskUserQuestion, so each created task has already passed a human review. ADR-069's draft-review pattern targets unattended task extraction (e.g. /distill task-extraction); /promote is an attended path and does not need a second review surface
- If a near-duplicate exists, ask the user whether to skip, enrich the existing task (re-invoke
_task:create-agent in enrich mode with task_path pointing at the duplicate), or create anyway
- The
/refresh-project {target-slug} call is deferred to Phase 5 (after the workspace backlink lands). Calling it here would refresh ## Related Workspaces before the mentions reverse-lookup key exists, leaving the just-promoted workspace missing from the project's surface until a later manual refresh
Phase 4: New project creation (Phase 1 default path)
This phase runs when Phase 1's user choice was (a) — the default. It also runs when the user picked (c) and the named slug did not exist.
- Confirm the slug with the user (default = the slug proposed in Phase 1 Step 3 — Phase 1 already routed the user here by selecting option (a); no separate "create a new project?" confirmation is needed)
- Draft seeds for
/project new's four required inputs from the workspace's _summary.md (falling back to _workspace.md when the summary is absent) and present them as proposals the user can accept verbatim or rewrite:
- Slug: the slug confirmed in Step 1
- Name: a descriptive one-line title (~30–60 chars). Pull from the workspace's frontmatter
name if it already reads like a project title, otherwise summarise the summary's first paragraph
- Description: 1–3 sentences (~120–300 chars) derived from the summary's overview / outcome sections. This will go into
_project.md frontmatter and is read by task-classification skills, so keep it factual and scope-bearing rather than narrative
- Goal: the project's completion condition (DoD). Often the summary already names a verifiable end-state; lift it if so
- Invoke
/project new {slug} with these four seeds. /project new confirms each with the user (it asks for name, description, Goal, status) before calling rill mkfile projects --field 'name=...' --field 'description=...' --field 'status=...'. The seeds avoid double-prompting cold while still letting the user adjust before commit
- After
/project new returns successfully, set the target = projects/{slug} and branch back to Phase 2 (candidate extraction). The workspace's mentions backlink is written at the end of Phase 5 only if Phase 3 succeeds (avoids leaving the workspace linked to a project the user later cancelled into)
If the user cancels at any sub-step (including inside /project new), exit /promote without changes.
Phase 5: Workspace backlink + Next Steps update + project refresh
This phase runs only if Phase 3 succeeded (Key Facts appended, tasks created without error). On any earlier user cancellation, Phase 5 is skipped — the workspace stays as-is.
-
If projects/{target-slug} is not already in the workspace's _workspace.md mentions, Edit _workspace.md to add it. Preserve other mentions. This is the deferred backlink for both the (c) "specify other" path and the Phase 4 new-project path
-
Update the workspace's _workspace.md ## Next Steps section to point forward to the project:
- Continued in [projects/{slug}/_project.md](../../projects/{slug}/_project.md)
-
Invoke /refresh-project {target-slug} (deferred from Phase 3 Step 4). Running it here, after the workspace's mentions backlink has been written, ensures the project's ## Related Workspaces regenerates with the just-promoted workspace included. ## Active Tasks also picks up the new tickets created in Phase 3
Do not change the workspace's frontmatter status — that stays completed. /promote does not close, reopen, or otherwise modify the workspace's lifecycle.
Phase 6: Completion report
/promote complete — workspace: {id} → project: [{name}](../../projects/{slug}/_project.md)
- Key Facts appended: {N}
- Tasks created: {M} (status: open — actionable immediately; review their Goal / Background if needed)
- Related Workspaces refreshed via /refresh-project
Next:
- `/project {slug}` to view the refreshed project state
- `/project {slug} continue` to start on a new task
- Or run `/close` if it has not been run yet (this skill assumed `_summary.md` already exists)
Coordination with /close
/close may schedule /promote to run after its own completion. The chain is:
/close Phase 0 — detect whether the workspace mentions a project and has actionable items. If both, predeclare a /promote follow-up via the harness's question primitive: "After this /close completes, should I chain /promote {id} to crystallise into [{project}]?"
/close Phase 9 (end) — if the user predeclared yes, chain into /promote {id} after the completion report. By this point _summary.md exists and /promote's Phase 0 prerequisite is satisfied
- If the user said no in Phase 0,
/close completes without chaining. The user can run /promote manually later
The Phase 0 predeclare + Phase 9 chain pattern is needed because /promote requires _summary.md, which is created in /close Phase 2. Running /promote at the start of /close would race that artifact.
/close is the canonical creator of _summary.md. /promote is the canonical consumer. Both can be run manually in either order, but the natural chain is /close → /promote.
Error handling
| Situation | Behavior |
|---|
_summary.md missing | Exit with "Run /close {id} first" — do not invoke /close automatically |
Workspace status: active but _summary.md exists | Warn (suggests user reopened after close); ask whether to proceed |
| Workspace mentions zero projects | Run the default Phase 1 flow; option (b) has no candidates |
Workspace mentions only status: done projects | Run the default Phase 1 flow; option (b) is excluded with an explanation |
| Workspace mentions multiple eligible projects | Two-step question: first (a/b/c), then list eligible projects as flat options if (b) is chosen |
Target project's _project.md is malformed | Refuse to write into a broken file; ask the user to fix it first |
## Key Facts already at 20 items | Warn before appending; let the user decide |
| Task creation would duplicate an existing task | Ask: skip / enrich the existing / create anyway |
/refresh-project in Phase 3 fails | Log the warning; report /promote as successful since the file appends already landed |
Rules
- Closed workspaces only —
_summary.md is the prerequisite. Active workspaces are not promotable by design (see "Prerequisite" above)
- Never modify the workspace's
status — /promote is decant-only, not close-emulating
- Never modify
inbox/ source files
- Default to a new project per workspace — Phase 1 proposes new-project creation by default. Merging into an existing project is opt-in. Projects with
status: done are never valid merge targets (see Phase 1 pre-check)
- All actionable-item tasks are created with
status: open. The Phase 2 candidate AskUserQuestion is the human review gate; ADR-069's status: draft default applies to unattended task extraction (e.g. /distill task-extraction) and not to /promote
- All in-body file references use Markdown links
[display name](../../relative-path). Backtick-only ID references are forbidden
- After writing, always invoke
/refresh-project {target-slug} so the project's auto-sections reflect the changes
See also
.claude/rules/rill-projects.md — body structure, section ownership
.claude/rules/rill-workspace.md — workspace lifecycle
/close skill — generates the prerequisite _summary.md
/refresh-project skill — invoked after Phase 3 to refresh auto-sections
/project skill — viewing surface for the promoted project
_distill/task-extraction.md — qualitative rules for what counts as an actionable item