manage-features
Skill215 starsChanged 2 months agoMITView on GitHub
Create, group, and rearrange Switchboard features — Create (remote file write, no extension needed), Create from Plans (create-feature.js, requires the extension running), Group (scan/cluster/propose), Rearrange (split/move/merge subtasks without rewriting content).
In this repository19 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- improve-featureSkill
- improve-planSkill
- external-team-leadSkill
- improve-featureSkill
- kanban-operationsSkill
- query-kanbanSkill
- switchboard-orchestrationSkill
- worktree-cleanupSkill
- kanban-operationsSkill
- manage-featuresSkill
- query-kanbanSkill
- switchboard-cloudSkill
- switchboard-memoSkill
- switchboard-remoteSkill
- switchboardSkill
- worktree-cleanupSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
43 rules. About 0 are common, 23 are distinctive, and 20 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈23
Distinctive · estimate
This author's own choices. Worth a look.
20
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 9
Create, group, and rearrange Switchboard features.
- Very specific: line 21
When a directive says "invoke the manage-features skill and follow the Create from Plans section", jump to that section below.
- Distinctive: line 22
Create from Plans section", jump to that section below.
- Very specific: line 28
Create a Switchboard feature by writing the feature file directly to .switchboard/features/.
- Very specific: line 38
Do NOT use this section if the extension IS running — call create-feature.js instead (it's authoritative: does DB upsert, subtask linking, …
- Very specific: line 45
If it responds with status ok, Switchboard is live — use create-feature.js.
- Distinctive: line 46
If it fails or is offline, proceed with direct file write.
- Very specific: line 92
Write it with the ## Subtasks heading and - [ ] (no subtasks) placeholder — the extension replaces this when subtasks are linked via …
- Very specific: line 111
After writing the feature file, to link existing plans (identified by their planId from kanban-board.md):
- Very specific: line 131
If the user has not specified which plans to group, read kanban-board.md, propose groupings, get approval, then create the feature files.
- Very specific: line 136
Do NOT commit or push — creating a feature is a planning action.
- Very specific: line 146
Create a Switchboard feature when the user already knows which plans belong together.
- Distinctive: line 159
Do NOT use this section if the user wants you to *discover* groupings from the board — use the Group section instead
- Distinctive: line 161
Do NOT use this section if the extension is NOT running — use the Create section (the remote fallback) instead
- Very specific: line 168
Check with switchboard api GET /health.
- Distinctive: line 194
Do NOT proceed until all plan IDs are confirmed present.
- Distinctive: line 198
If the user gave plan filenames, resolve them to planIds with the board read above.
- Distinctive: line 199
If the user gave planIds directly, use those.
- Very specific: line 222
If ok: false, read the error field.
- Very specific: line 239
All subtask plan IDs should come back with the feature's planId in featureId.
- Distinctive: line 275
Never mention tracker sync in your reply: Do not claim a sync happened, and do not hedge about whether one did — a caveat about sync is …
- Very specific: line 296
If the user already knows which plans to group (no discovery needed), use the Create from Plans section instead — it skips the …
- Distinctive: line 302
Read the board snapshot:
- Very specific: line 319
Use the planId: value from the comment — NOT the filename — when calling create-feature.js.
- Very specific: line 327
If a project name is injected: only consider plans tagged project:"<that name>".
- Very specific: line 328
If no project name is injected (empty, __unassigned__, or the literal placeholder): ignore all plans that have a project:"..." tag — only …
- Distinctive: line 334
Use this — not just titles — to determine groupings.
- Distinctive: line 335
Read plans in parallel where possible.
- Distinctive: line 345
Cross-column warning: If a proposed feature contains plans from different kanban columns (e.g.
- Distinctive: line 349
If the feature is dragged to a coder column, the CREATED subtask(s) will skip PLAN REVIEW entirely and go straight to coding without …
- Distinctive: line 355
Only once all subtasks are in PLAN REVIEWED should the feature be dragged to a coder column.
- Distinctive: line 375
Wait for user approval or edits.
- Distinctive: line 389
After all features are created, write the ## How the Subtasks Achieve This section and the ## Dependencies & sequencing section into each …
- Very specific: line 392
Use the text from your step 3 proposal — paste the How the Subtasks Achieve This section between the Goal and the <!-- BEGIN SUBTASKS --> …
- Distinctive: line 398
Cross-column note in the feature file: If the feature has subtasks in different kanban columns (e.g.
- Distinctive: line 418
Ask the user: "Would you like me to analyse the BACKLOG for feature groupings too?" Do NOT re-read the board or inspect the BACKLOG column …
- Distinctive: line 419
Do NOT re-read the board or inspect the BACKLOG column yourself.
- Distinctive: line 420
If the user says yes, repeat steps 1-5 scoped to the BACKLOG column.
- Distinctive: line 421
If the user says no or does not respond, stop.
- Distinctive: line 434
Follow steps 1, 1a, 2, 3 as written, but step 3's proposal is written to the reply for the session log, not for approval.
- Distinctive: line 463
Read the feature and every subtask first:
- Very specific: line 484
Decide the partition: Every step/section of the source lands in exactly one piece.
- Very specific: line 500
This is structure-only: If the sliced pieces need content work afterward, hand off to improve-feature as a separate, explicit step — do not …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Manage Features
Create, group, and rearrange Switchboard features. This skill consolidates four feature-management operations into one discoverable skill:
- Create — write a feature file directly (remote-session fallback when the extension is not running).
- Create from Plans — create a feature from a known set of plans via
create-feature.js(extension running). - Group — scan pre-coding columns, cluster loose plans by capability, propose groupings for one approval, then create features.
- Rearrange — restructure a feature's subtasks (split/move/merge/reorder) without rewriting their content.
When a directive says "invoke the manage-features skill and follow the
Create from Plans section", jump to that section below.
Create
Create a Switchboard feature by writing the feature file directly to
.switchboard/features/. Use this section when you are in a remote session
(Claude Code web, claude.ai) and the VS Code extension is not running —
create-feature.js routes through the extension's LocalApiServer and has no
direct-DB fallback, so it fails when the extension is unreachable.
When to Use
- You are in a remote session (no VS Code extension running).
- The user asks to create a new feature (grouping plans together, or a standalone feature).
- Do NOT use this section if the extension IS running — call
create-feature.jsinstead (it's authoritative: does DB upsert, subtask linking, file write, and board refresh atomically).
How to Detect Whether the Extension Is Running
- Run
switchboard api GET /health. - If it responds with status
ok, Switchboard is live — usecreate-feature.js. - If it fails or is offline, proceed with direct file write.
Feature File Format
Feature files live in .switchboard/features/ and follow this structure:
---
description: '{Feature Name}'
---
# {Feature Name}
## Goal
{Description of what this feature achieves and why it matters.}
## How the Subtasks Achieve This
{Narrative connecting the subtasks to the goal. Written once by the agent;
preserved by _regenerateFeatureFile on subsequent subtask changes.}
<!-- BEGIN SUBTASKS (auto-generated, do not edit) -->
## Subtasks
- [ ] (no subtasks)
<!-- END SUBTASKS -->Format notes (verified against source):
- YAML frontmatter — the extension writes
---\ndescription: '{name}'\n---\n\n# {name}\n\n...(seecreateFeatureFromPlanIdsatKanbanProvider.tsline 8771). Thedescriptionfield is quoted to prevent YAML breakage from names containing:,---, etc. The watcher extracts the topic from the H1 title, so frontmatter is not strictly required for import — but it IS the canonical format and should be included for consistency. - Full SUBTASKS marker — use
<!-- BEGIN SUBTASKS (auto-generated, do not edit) -->(see_regenerateFeatureFileatKanbanProvider.tsline 8648), not the shorter<!-- BEGIN SUBTASKS -->. The regeneration search uses the prefix<!-- BEGIN SUBTASKS, so the shorter marker would technically work — but use the full marker to match extension-generated files. - No
## Metadatasection — the extension writescomplexity: 'Unknown'andtags: ''directly to the DB (createFeatureFromPlanIdslines 8741–8742), NOT via a## Metadatasection in the file. Real feature files do NOT contain a Metadata section. An optional## Metadatasection MAY be added (the watcher will parse it if present), but it is not part of the extension-generated format.
The <!-- BEGIN SUBTASKS ... --> / <!-- END SUBTASKS --> block is managed by the extension.
Write it with the ## Subtasks heading and - [ ] (no subtasks) placeholder — the extension
replaces this when subtasks are linked via _regenerateFeatureFile.
Filename Convention
{slug}-{planId}.mdslug: lowercase, hyphens only, max 60 chars (e.g.auth-refactor)planId: a fresh UUID v4 (generate withnode -e "const {randomUUID}=require('crypto');console.log(randomUUID())")- Full path:
.switchboard/features/{slug}-{planId}.md - Never omit the planId from the filename — the watcher derives the
plan_idfrom this trailing UUID on re-import. A bare slug would mint a fresh random ID on re-import and orphan every subtask.
Linking Existing Plans as Subtasks
After writing the feature file, to link existing plans (identified by their planId from
kanban-board.md):
node .agents/skills/kanban_operations/assign-to-feature.js "{featurePlanId}" '["subtaskPlanId1","subtaskPlanId2"]' "{workspaceRoot}"This also routes through the extension; in a remote session it will fail and the agent should note that subtask linking will need to be done when VS Code is next opened, OR the user can drag-and-drop in the kanban UI.
Sourcing Existing Suggest-Feature Content
The kanban UI's "Suggest Features" button generates a detailed prompt (see
_buildSuggestFeaturesPrompt in KanbanProvider.ts) that:
- Scans
kanban-board.mdfor ungrouped plans in pre-coding columns - Groups them by theme
- Proposes feature names and goals for user approval
- Then calls
create-feature.js
If the user has not specified which plans to group, read kanban-board.md, propose groupings,
get approval, then create the feature files.
After Writing
- Do NOT commit or push — creating a feature is a planning action. Leave the new
file in the working tree for the user. (The features folder will be tracked once
expose-features-folder-in-gitignore.mdis deployed.) - Note to the user that the extension will automatically import the feature into the kanban DB on next activation via the GlobalPlanWatcherService.
Create from Plans
Create a Switchboard feature when the user already knows which plans belong together. This is the direct path — no board scanning, no clustering, no proposal step. Just create the feature, verify it, and write the narrative.
When to Use
- The user says "create a feature from these plans" / "group these into a feature" / "make a feature for X containing plans A, B, C"
- The user has just written several related plans and wants them grouped
- The planner persona (switchboard-chat) flagged 3+ related plans and the user confirmed they want a feature
- The improve-plan workflow restructured plans into a feature set during review and needs to create the feature
- Do NOT use this section if the user wants you to discover groupings from the board — use the Group section instead
- Do NOT use this section if the extension is NOT running — use the Create section (the remote fallback) instead
Prerequisites
1. Extension or standalone host must be running
Check with switchboard api GET /health. If unreachable, the host is not running — fall back to the Create section (direct file write).
2. Plans must be on the board
create-feature.js needs planId values from the board. If the plans were just
written as files to .switchboard/plans/, the GlobalPlanWatcherService will
import them within a few seconds.
To check if plans are imported, read the board through the API — never the database file. The file is not present in a per-feature worktree and its path differs per deployment mode:
switchboard api GET /kanban/board \
| jq '.data[] | select(.planFile | contains("{plan-filename}")) | {planId, topic}'Three outcomes, and you must tell them apart:
- Rows — the plans are imported; collect their
planIds and proceed. 200with an empty result — the watcher has not imported them yet. Wait 3-5 seconds and re-check.503withcode: "STORE_UNAVAILABLE"— the store did not answer. This is not "the plans are missing". Do NOT wait-and-retry in a loop and do NOT proceed: retry once, then report the store as unreachable (naming thetierfrom the response) and stop. Creating a feature against a board you cannot read produces a blank feature.
Do NOT proceed until all plan IDs are confirmed present.
3. Collect plan IDs
If the user gave plan filenames, resolve them to planIds with the board read above. If the user gave planIds directly, use those.
Execution
Step 1: Create the feature
node .agents/skills/kanban_operations/create-feature.js \
"<feature name>" \
'["planId1","planId2","planId3"]' \
"<workspace root absolute path>" \
"<goal description — 2-4 sentences>"The description becomes the ## Goal section in the feature file.
Shell escaping: Escape double quotes (" → \"). Avoid $, backticks, and backslashes — shell metacharacters inside double quotes. Newlines ARE safe and preserved as multi-line Goal content — do not flatten them.
Expected output:
{"ok":true,"featurePlanId":"<uuid>","featureSessionId":"<uuid>"}If ok: false, read the error field. Common failures:
- Extension not reachable → fall back to the Create section (the script itself returns ok:false with a clear message; the AGENT then switches sections).
- Zero subtasks linked (silent blank feature) →
create-feature.jsreturnsok: trueeven when none of the supplied plan IDs resolve to board rows (the extension deliberately allows blank features). This is NOT an error. The Prerequisites §2 pre-flight board read is the ONLY gate that prevents this. If you skipped it, Step 2 verification will show zero subtasks — recover by deleting the blank feature:node .agents/skills/kanban_operations/delete-feature.js "<featurePlanId>" "<workspaceRoot>", then re-run the pre-flight and retry.
Step 2: Verify
switchboard api GET "/kanban/plan?planId=<featurePlanId>" \
| jq '.data | {planId, topic, isFeature, source}'Confirm isFeature is 1. Then verify subtasks are linked:
switchboard api GET "/kanban/plans?featureId=<featurePlanId>" \
| jq '.data[] | {planId, topic, featureId}'All subtask plan IDs should come back with the feature's planId in featureId.
GET /kanban/plan spans the board window and the archive, so a 404 here means the
feature really was not created — not that it aged out. .data.source says which store
answered (board for anything just created). A 503 with
code: "STORE_UNAVAILABLE" means the read failed, NOT that the feature is missing:
report the store as unreachable rather than deleting and retrying.
Step 3: Write narrative sections
The feature file is at .switchboard/features/{slug}-{featurePlanId}.md.
create-feature.js only writes the ## Goal section. Write the remaining
narrative sections manually:
## How the Subtasks Achieve This— one bullet per subtask plan:- **{Plan Name}**: {what it does and how it contributes to the goal}## Dependencies & sequencing— note ordering constraints between subtasks. If none, write "No hard ordering constraints; subtasks can be executed in parallel."
Insert ## How the Subtasks Achieve This between the ## Goal section and
the <!-- BEGIN SUBTASKS --> marker. Insert ## Dependencies & sequencing
immediately after the <!-- END SUBTASKS --> marker.
These sections are preserved by _regenerateFeatureFile on subsequent
subtask changes, so they only need to be written once.
Notes
- Feature creation syncs to Linear/ClickUp: the feature is pushed as a parent
issue/task and subtasks are linked as children. Gated per tracker on BOTH
setupCompleteandrealTimeSyncEnabledbeing true — with either off, that tracker is skipped silently. A subtask is only linked if its own issue/task already exists; ones that don't are skipped and get linked on a later feature-sync trigger. - Never mention tracker sync in your reply. Do not claim a sync happened,
and do not hedge about whether one did — a caveat about sync is noise the
user has to read and cannot act on. Say nothing about Linear/ClickUp unless
the user asks, or unless a sync error was actually returned to you. If asked,
confirm it by reading
linear_issue_id/clickup_task_idon the feature and subtask rows rather than speculating. - To add more plans to an existing feature later, use
node .agents/skills/kanban_operations/assign-to-feature.js "{featurePlanId}" '["newPlanId"]' "{workspaceRoot}" - The
<!-- BEGIN SUBTASKS -->block is auto-managed by the extension — do not edit it manually.
Group
You are grouping loose Switchboard plans into features. Follow this flow exactly — do not create any feature before the user approves.
When to Use
Triggered when the user asks to "group plans into a feature", "organise loose plans into features", or "suggest feature groupings", OR by clicking the Suggest Features board button (which copies this skill's text with the workspace root injected).
If the user already knows which plans to group (no discovery needed), use the Create from Plans section instead — it skips the scan/propose/confirm flow and goes straight to creation.
Flow
1. SCAN
Read the board snapshot:
cat {{WORKSPACE_ROOT}}/.switchboard/kanban-board.mdScope: CREATED and PLAN REVIEWED columns only. Ignore BACKLOG and all post-coding columns.
Each plan line ends with an HTML comment, e.g.:
- [.switchboard/plans/foo.md](...) — Foo <!-- planId:abc-123 -->
- [.switchboard/features/feature-def.md](...) — Bar Feature <!-- planId:def-456 feature -->
- [.switchboard/plans/baz.md](...) — Baz <!-- planId:ghi-789 subtask-of:"Bar Feature" -->Skip lines tagged feature (they are features) or subtask-of:... (already assigned).
Use the planId: value from the comment — NOT the filename — when calling create-feature.js.
(A path under .switchboard/features/ also indicates a feature, but subtask detection
requires the subtask-of tag — do not rely on filenames alone.)
1a. PROJECT SCOPE
The active project filter is injected above as {{ACTIVE_PROJECT_FILTER}}.
- If a project name is injected: only consider plans tagged
project:"<that name>". - If no project name is injected (empty,
__unassigned__, or the literal placeholder): ignore all plans that have aproject:"..."tag — only untagged plans are candidates.
2. READ PLAN BODIES
For each candidate plan in scope, read the full plan file. Extract: goal, problem summary, dependencies, tags. Use this — not just titles — to determine groupings. Read plans in parallel where possible. If >25 candidates, first-pass cluster by title then deep-read within each cluster.
3. PROPOSE (single message, all groups at once)
Group by underlying capability theme, not by surface keyword. Cross-provider plans that address the same capability go into one feature. Minimum 2 plans per feature. Single-plan "groups" go in the Standalone section. Flag POSSIBLE OVERLAP / REDUNDANCY / GAP where detected.
Cross-column warning: If a proposed feature contains plans from different kanban columns (e.g. one CREATED + one PLAN REVIEWED), you MUST flag this prominently in the proposal with a ⚠ CROSS-COLUMN warning. Explain:
- The CREATED plan(s) have NOT been plan-reviewed yet.
- If the feature is dragged to a coder column, the CREATED subtask(s) will skip PLAN REVIEW entirely and go straight to coding without refinement.
- To fix this after feature creation: select the feature card on the
kanban board and press the Replan button (the re-plan icon in the
PLAN REVIEWED column header). This sends the CREATED subtasks to the
planner agent for
improve-planrefinement, moving them to PLAN REVIEWED. - Only once all subtasks are in PLAN REVIEWED should the feature be dragged to a coder column.
For each proposed feature, write:
- Feature name
- Goal: 2-4 sentences describing what the feature achieves, what problem it solves, and why these plans are grouped together.
- How the Subtasks Achieve This: one bullet per member plan explaining what
it does and how it contributes to the feature's goal. Format:
- Plan Name:
<what it does and how it contributes>
- Plan Name:
- Dependencies & sequencing: note any ordering constraints between subtasks (e.g. "Subtask A must land before Subtask B can be tested") and any cross-subtask dependencies. If there are none, state "No hard ordering constraints; subtasks can be executed in parallel."
- Member plans with planId, one-line summary, and current kanban column
List genuinely standalone plans separately. Then stop and wait.
4. CONFIRM
Wait for user approval or edits. Do not touch the database until confirmed.
5. EXECUTE
For each approved group, pass the Goal text as the description argument. Escape any double quotes in the Goal text (replace " with ") or rephrase to avoid them, so the bash command does not break. Also avoid $, backticks, and backslashes in the Goal text — these are shell metacharacters inside double quotes.
node .agents/skills/kanban_operations/create-feature.js "<feature name>" '["planId1","planId2",...]' "{{WORKSPACE_ROOT}}" "<goal text with escaped quotes>"The description becomes the ## Goal section in the feature file.
After all features are created, write the ## How the Subtasks Achieve This section
and the ## Dependencies & sequencing section into each feature file manually (the
create-feature script only writes the Goal).
Use the text from your step 3 proposal — paste the How the Subtasks Achieve This
section between the Goal and the <!-- BEGIN SUBTASKS --> marker, then paste the
Dependencies & sequencing section immediately after the Subtasks block. Both
sections are preserved by _regenerateFeatureFile on subsequent subtask changes, so
they only need to be written once.
Cross-column note in the feature file: If the feature has subtasks in different kanban columns (e.g. some CREATED, some PLAN REVIEWED), add a ⚠ Cross-Column Review Note section immediately after the Subtasks block (before Dependencies & sequencing). Write:
This feature contains subtasks in different kanban columns. The subtasks in CREATED have NOT been plan-reviewed yet. Before dragging this feature to a coder column, select the feature on the kanban board and press the Replan button (re-plan icon in the PLAN REVIEWED column header) to send the CREATED subtasks to the planner for
improve-planrefinement. Only review/refine the CREATED subtasks — the PLAN REVIEWED subtasks have already been reviewed.
This note is preserved by _regenerateFeatureFile along with the other
manual sections.
To add more plans to a feature later, use assign-to-feature.js with the feature planId from the create-feature.js output.
6. BACKLOG (optional, after execution)
Ask the user: "Would you like me to analyse the BACKLOG for feature groupings too?" Do NOT re-read the board or inspect the BACKLOG column yourself. If the user says yes, repeat steps 1-5 scoped to the BACKLOG column. If the user says no or does not respond, stop.
Notes
- Feature creation updates the Switchboard board, writes a
.switchboard/features/file, and syncs to Linear/ClickUp — the feature is pushed as a parent issue/task with subtasks linked as children. Gated per tracker on BOTHsetupCompleteandrealTimeSyncEnabledbeing true; with either off that tracker is skipped silently. Subtasks without an existing issue/task are skipped and get linked on a later feature-sync trigger. - Never mention tracker sync in your reply. Do not claim a sync happened, and do not hedge about whether one did — a caveat about sync is noise the user has to read and cannot act on. Say nothing about Linear/ClickUp unless the user asks, or unless a sync error was actually returned to you. If asked, confirm it by reading
linear_issue_id/clickup_task_idon the feature and subtask rows rather than speculating. - The
create-feature.js/assign-to-feature.jsverb scripts are documented in.agents/skills/kanban_operations/SKILL.md. - The confirm gate is load-bearing in interactive mode: never create any feature before the user approves. Unattended mode's authorization comes from the user pressing Start orchestrator.
Unattended mode (orchestration)
This section applies ONLY when the invoking prompt contains the directive UNATTENDED=true (which the Orchestration kickoff prompt injects). It is the explicit, documented exception to the confirm gate above. After the removal of the Miscellaneous sweep, UNATTENDED=true's only remaining effect is gating the confirm-skip below.
- Follow steps 1, 1a, 2, 3 as written, but step 3's proposal is written to the reply for the session log, not for approval; skip step 4 (CONFIRM) entirely and proceed to step 5 EXECUTE immediately. Never skip step 4 outside unattended mode.
- Standalone plans are left standalone — under the
noneworktree default a plan with no feature dispatches straight to a team, so there is no sweep and noMiscellaneouscatch-all. - Repeat the EXECUTE shell-safety rules here: escape
"in goal text; avoid$, backticks, backslashes. No human reviews the generated commands in this mode, so escaping is mandatory, not hygiene. - Skip step 6 (BACKLOG) in unattended mode — BACKLOG stays human-curated.
Rearrange
Re-slice the subtasks of an existing feature so each one is the right size and scope for a single coding agent — while keeping the subtask content as written. This is the structure-only operation: it changes boundaries (how work is partitioned across subtasks), not words (how each subtask is authored).
Use it when a feature's subtasks are the wrong shape for execution — most often when one subtask bundles several independent tasks and burns a coder's whole context on reading before it can code — and you want to split/move/merge the pieces without a content rewrite.
When to use vs. the neighbours
- This section (
rearrange) — the subtask boundaries are wrong (one is too big, two overlap, work is in the wrong subtask). Split one into N, move scope between them, merge, reorder. Content is preserved verbatim. improve-feature/switchboard-feature— the subtask content needs work (deepen, dedupe, make the set coherent). It re-authors each subtask in its own voice, so it will re-inflate content you deliberately trimmed. Use it after rearrange if the freshly-sliced pieces then need polishing — never as a substitute for a structure-only change.switchboard-split— the narrow special case: one plan → two, along complexity lines (Complex/Risky vs Routine). If that's exactly the split you want, use it. This section is the general form: any subtask → N pieces along any axis (usually task-separation), plus move/merge/reorder across the whole feature.- Group / Create from Plans — the inverse direction: composing loose plans into a feature. This section decomposes/rearranges an existing one.
Core principle — preserve content, change structure
Every implementation step, code block, line reference, and edge case in the source subtasks must land in exactly one destination subtask (shared context — Goal/background/dependencies — may be duplicated into each so every file stays self-contained). Do not re-author. If a piece reads well already, it reads well in its new home unchanged. Git is the undo.
Inputs
- The feature (its feature plan-id, or the feature file path — the id is in
.switchboard/features/<slug>-<uuid>.md). - The target shape: which subtask splits into what, and/or what moves where. If not given, propose the re-slicing and confirm before touching anything.
Read the feature and every subtask first:
switchboard api GET "/kanban/plans?featureId=<featurePlanId>" --json | jq '.result.data[] | {planId, topic, planFile, kanbanColumn}'The building blocks
Subtask membership is <!-- planId:… subtask-of:"<feature name>" --> in the kanban-state mirror, backed by kanban.db. Never edit kanban.db or the state .md mirror by hand (this workspace has a history of board-clobber from that). Compose the rearrangement from these primitives instead:
| Goal | Local (extension running) | Remote (no extension) |
| Keep a subtask but change its scope | Rewrite its .md file in place. This preserves its planId, subtask-of, and column — zero board churn. The most important move: make one output be the rewritten original. | Same — just a file write. |
| Create a new subtask in the feature | POST /kanban/plans (writes file, imports, returns planId) → node .agents/skills/kanban_operations/assign-to-feature.js <featurePlanId> '["<newPlanId>"]' <workspaceRoot> | Write the .md with **Feature:** <feature-plan-id> (and **Project:** <name> if needed) in the metadata block — applied apply-if-empty on import — then move it to PLAN REVIEWED via the Notion/Linear provider or MCP. |
| Detach a subtask (keep the plan) | node .agents/skills/kanban_operations/remove-from-feature.js <subtaskPlanId> <workspaceRoot> (or POST /kanban/feature/remove) | Remove the **Feature:** line and re-import. |
| Delete a subtask entirely | DELETE /kanban/plans?planId=<id>&deleteFile=true — deleteFile=true is required, or the file re-imports on the next scan | Delete the .md file. |
POST /kanban/plans body: { title, slug?, complexity?, tags?, project?, body?, workspaceRoot? } — returns { planId, planFile, slug }. It refuses to overwrite an existing slug (409).
Steps — split one subtask into N (the common case)
- Read the feature and the target subtask in full.
- Decide the partition. Every step/section of the source lands in exactly one piece; shared Goal/background/dependencies are copied into each so each is self-contained.
- Rewrite the original file in place to hold piece 1 (keeps its
planId+ linkage + column). Do NOT create a new file for piece 1 — reuse the original, so one card stays stable. - Create pieces 2..N as new subtasks via the table above (local:
POST /kanban/plans→assign-to-feature.js; remote: file +**Feature:**line → move toPLAN REVIEWED). - Verify nothing was lost — every source step/code block/edge case is now in exactly one piece.
- Update the feature's prose — the
## Goal,## How the Subtasks Achieve This, and any dependencies/sequencing narrative — to describe the new subtask set. Never touch the auto-generated<!-- BEGIN/END SUBTASKS -->block — the extension regenerates it from the DB. - Confirm the board reflects the new set:
switchboard api GET "/kanban/plans?featureId=<featurePlanId>" --json | jq '.result.data[].topic'.
Move scope, merge, and reorder are the same primitives: move = rewrite two files (cut from one, paste into the other); merge = fold one file's steps into another, then delete the emptied subtask (deleteFile=true); reorder = purely narrative (subtask order is presentation — encode intended sequence in the feature's dependencies prose, not by renumbering cards).
Guardrails
- Preserve content, not structure — nothing in the source subtasks may be dropped or rewritten for style; git is the undo.
- Rewrite-in-place to keep
planIds stable — creating four new cards to replace two churns the board and loses history. Reuse originals wherever a piece maps back to one. - Never touch a feature's
<!-- BEGIN/END SUBTASKS -->block — it is regenerated from the DB; hand-edits are cosmetic and get overwritten. - Never write
kanban.dborkanban-state-*.mddirectly — go through the API /kanban_operationsscripts (local) or plan-file frontmatter (remote). deleteFile=trueon real deletes — otherwise the.mdre-imports and the subtask reappears.- This is structure-only. If the sliced pieces need content work afterward, hand off to
improve-featureas a separate, explicit step — do not let a rearrangement quietly become a rewrite.
Report
State: the feature, the before→after subtask list (which cards were reused-in-place vs. newly created vs. deleted), and a one-line confirmation that every source step landed in exactly one destination subtask.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

