jpicklyk/task-orchestrator/adopt-project-scope
Claude Code and agent skill by jpicklyk/task-orchestrator
- community
Checking that the SKILL.md file is still in the repository.
Migrates an already-populated, unscoped Task Orchestrator database in place to the project-scoping convention — creates a project anchor root, re-parents existing work trees under it, and writes rootId back to config.yaml. Use when a user says: adopt project scope, migrate this database to project scoping, make this DB multi-project, project-scope this workspace, adopt existing database, or set up project scoping for an existing DB.
Install
npx vskill@latest install jpicklyk/task-orchestrator/adopt-project-scopeSKILL.md
Adopt Project Scope — In-Place Migration to Project Scoping
Take an existing, unscoped database (many depth-0 roots, no project anchor) and migrate it in place to the project-scoping convention: one type=project root that owns the workspace's work trees, with its UUID written back to .taskorchestrator/config.yaml under a project: block. Global containers (retrospectives, observations) stay at depth 0; test artifacts are flagged for cleanup, never moved or deleted.
This is a destructive-by-execution skill: the EXECUTE step re-parents real items. It defaults to a dry run and never mutates anything without an explicit confirmation. It deletes nothing.
For a fresh workspace with no existing unscoped work, use /task-orchestrator:init instead; this skill is for databases that already hold unscoped work trees.
Not a director-mode skill: run it outside director mode (/task-orchestrator:director off); director-guard denies its file, shell and config steps partway through. Step 0 refuses to start when the session context says director mode is on, because a guard denial between the anchor create and the config write would leave a partial anchor.
Every tool call below is a to-call block, {tool, select|op, args}, in the shapes of call-shapes.md. The config tool is orchestration-profile only.
Non-goals: cross-DB consolidation (merging items from a second database); merging multiple existing project anchors into one; any server-side enforcement of scope. This skill adopts a single workspace's single database.
Step 0 — Parse Arguments
- Director mode. When the session context says this session is in director mode, stop before anything else: tell the user to run
/task-orchestrator:director offand re-run. Do not create the anchor first.
- Project name — the first non-flag token(s) in
$ARGUMENTS. If absent, do not guess; ask for it in Step 3 (the dry-run plan) viaAskUserQuestionbefore any mutation. - `--dry-run` — if present, the skill stops after Step 3 (the plan) and performs zero mutations regardless of confirmation. The dry run is ALSO always rendered before execution even without the flag; the flag only forces an early exit.
Step 1 — Preflight (abort gates)
Run these checks in order. Each abort prints a clear, user-facing reason and stops.
1a — Already adopted?
Read <main>/.taskorchestrator/config.yaml, where <main> is the parent of git rev-parse --path-format=absolute --git-common-dir (the same file Step 4(b) writes, correct from a linked worktree). If it contains a project: block with a non-empty rootId:, the workspace is already scoped:
Stop. (If the file is missing entirely, that is fine — a fresh unscoped DB has no config project: block. Continue.)
1b — Existing anchor already in the DB?
Drop any result tagged personal-root: a personal root is not a project anchor and must never be adopted as one.
- No results → continue to 1c.
- One or more results → do NOT silently create a second anchor. Offer, via
AskUserQuestion:
- Attach to existing — write the existing anchor's UUID into
config.yaml(skip anchor creation in EXECUTE; still re-parent MOVE roots under it) and continue. - Abort — stop and let the user resolve the ambiguity manually.
If the user picks "attach", record the existing anchor UUID as ANCHOR_ID and note that EXECUTE step (a) is skipped.
1c — Config-push capability (tolerant)
The config tool (orchestration profile) pushes the config in EXECUTE step (c). Do not probe it destructively here — just remember to attempt the push there and, if the tool is not served (a knowledge-profile connection) or fails with data.results[0].error.code forbidden (the credential lacks write-config), skip it with a note rather than failing the whole adoption. The local config.yaml write (step b) is the source of truth; the server push is a convenience sync.
Step 2 — Inventory & Classify
Full depth-0 census:
If the response carries page.next, continue with that cursor until every root is listed so none is missed.
Read which types the server layer declares, so process items can be told apart from project work. config effective with no rootId returns the server config alone:
If data.results[0].types is empty, the server declares no types: an undeclared type is rejected only when the declared set is non-empty, so the project anchor create in Step 4 would succeed schema-free and the anchor would carry no schema. Point the user to /task-orchestrator:configure-server to mount the process-schema floor now, before the plan is confirmed; continue only if they choose to adopt without it.
Classify every depth-0 root into exactly one bucket:
| Bucket | Rule | Action | |
|---|---|---|---|
| KEEP-GLOBAL | The root's type is declared by the server layer (from the effective call above) and is not container or project — e.g. agent-observation items, which are standalone depth-0 roots; OR a container root titled Session Retrospectives, Improvement Proposals or Retrospective Trends; OR a depth-0 type=project item tagged personal-root (never MOVE it). | Stays at depth 0. | |
| MOVE | Any work container or work tree (a root with work/queue/review children), and any standalone work item. Everything that is real project work. | Re-parented under the new anchor. | |
| CLEANUP-CANDIDATE | Evident test artifacts: titles containing probe, smoke, depth-test, zzprobe; or tags matching mtest-*. | Flagged only — never moved, never deleted. Recommend /batch-complete. |
Per MOVE root, read and record four things (they feed the plan; nothing is mutated). Open runs, the root's config head, its documents and its pending decision blocks:
Keep entries whose status is open or paused. A root with no per-root config answers not_found, which means "no head":
From the blocked list keep the explicit blocks whose reason is awaiting_decision. A config head that exists is per-root config that stops applying after the move. Documents stay keyed to the old root id; the count is inventory only.
Ambiguous roots (no clear rule match — e.g., an untagged standalone item that could be work or a stray container): do NOT guess. Collect them and present via AskUserQuestion (multiSelect) asking which should MOVE vs stay KEEP-GLOBAL. Test-artifact-looking items always go to CLEANUP-CANDIDATE without asking.
Step 3 — Dry-Run Plan (always shown; --dry-run stops here)
Render the full plan before any mutation. Require explicit confirmation to proceed.
Add to the plan, per MOVE root: its open or paused runs, its config head (version), its document count and its pending-decision blocks. Then apply these rules before the confirmation:
- Open or paused runs: HOLD. A MOVE root with any open or paused run is reclassified HOLD and is not moved until those runs are closed (by a coordinator, director or human). A run belongs to the root it opened under and
runs_writeopenrefuses a non-root, so moving the root would strand the run. The plan says so, per root. - Pending decisions. Recommend answering them first. A decision stays keyed to the old root id after a move (it is not restamped), so a director's
runs_readdecisionswith the anchor asrootIdwill not show it. - Config head. Either merge it into the workspace
config.yamlbefore the move or accept losing it: a per-root config on a root that is no longer a root stops applying. - Credential warning (always printed). List every MOVE root id and state: any token-file
scope.root_ids, or JWTto_scope.root_ids, that names one of these ids must be re-scoped to the anchor before the next server restart. A token file fails startup on a non-root id; a JWT is refused with401. - If the project name is still unknown, ask for it now via
AskUserQuestionbefore showing the final counts. - `--dry-run`: stop here. State plainly: "Dry run — no changes made. Re-run without --dry-run to execute."
- Otherwise, confirm via
AskUserQuestion:
``` ◆ Proceed with adoption? This re-parents <N> tree(s) under a new project anchor.
- Yes — execute
- No — abort, make no changes
``` Wait for the answer. Only "Yes" proceeds.
Step 4 — Execute
Perform in this order. Record pre-execution counts first (used by Step 5): the depth-0 root count, the MOVE count, and the KEEP-GLOBAL count from Step 2.
(a) Create the project anchor — skip if attaching to an existing anchor (Step 1b). The global floor declares project; if the create fails (call-level partial_failure) with data.results[0].error.code schema_violation and its detail.availableTypes lacks project (the server declares types, but not this one), follow the fallback in /task-orchestrator:init (offer container or adding project to the server file; never pick a type silently):
Capture the new UUID as ANCHOR_ID.
(b) Write the `project:` block into `config.yaml` at the main checkout root (the parent of git rev-parse --path-format=absolute --git-common-dir, so it is correct from a linked worktree; refuse a home directory, as /task-orchestrator:init does) — read-modify-write, preserving ALL existing content:
- Read the current
<main>/.taskorchestrator/config.yamltext (create the file with just the block if it does not exist). - Insert this top-level block (surgical insert/append — do NOT regenerate or reformat the rest of the file; leave
work_item_schemas:,traits:,extensions:, comments, and formatting byte-for-byte intact):
``yaml project: rootId: "<ANCHOR_ID>" name: "<project name>" ``
- If a
project:key somehow already exists (it should not — Step 1a would have aborted), update itsrootId/namein place rather than adding a duplicate key. - If the config write in (b) was denied or failed, stop before (c) and (d): report that the anchor exists without a config block, and that nothing was re-parented.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingclaude-plugins/task-orchestrator/skills/adopt-project-scope/SKILL.md
Popularity
- Repository stars
- 205
- Repository forks
- 20
- 7-day trend score
- 27
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/jpicklyk/task-orchestrator/adopt-project-scope)