| name | taskgraph-migrate-markdown |
| description | Migrate in-repo Markdown specs, plans, task lists, TODOs, and roadmaps into Taskgraph through the Taskgraph tools while preserving hierarchy, work state, acceptance criteria, dependencies, decisions, and source provenance. Use when asked to import, convert, move, consolidate, retire, re-import, or make Taskgraph authoritative for one or more Markdown planning documents. |
Taskgraph Migrate Markdown
Move planning state from selected repository Markdown files into Taskgraph. Treat Taskgraph as the source of truth after the handoff; do not imply that the Markdown stays in sync.
Rules
- Use the Taskgraph tools for all Taskgraph reads and writes. Do not edit the workspace file directly or use an HTTP API.
- Use explicit source paths when supplied. Otherwise find likely planning files. Do not select
README.md, AGENTS.md, SKILL.md, changelogs, generated files, or vendored files merely because they contain headings; include them only when they hold live planning state or the user names them.
- Read every selected file in full before writing. Follow linked local Markdown only when it clearly belongs to the same plan.
- Preserve intent, not Markdown syntax. Do not turn each heading, paragraph, requirement, or code sample into a task.
- Inspect the target scope before creating anything. Reconcile existing items and stable Taskgraph IDs instead of making duplicates.
- Preview creates with
dry_run: true, commit related creates with atomic: true, and verify every committed subtree.
- Keep source files unchanged unless the user expressly asks to replace, archive, move, or delete them after verification.
- Treat
blocks as blocker -> blocked. Add a hard edge only when the source states a real gate.
- Resolve an existing parent, relationship endpoint, path, or embedded Taskgraph ID with
tg_resolve; pass its ID to write tools.
- Do not invent
tg_mutate_batch operations. Use tg_create_items, tg_patch_item, tg_mutate_relationships, and tg_record_entry.
- The pi extension publishes full schemas for every tool. If a strict client rejects valid create, patch, relationship, or entry arguments, report the error; do not bypass the tools with direct file writes.
1. Select the source set
Use the paths in the request. For a broad request, search filenames and content for likely plans, specs, roadmaps, TODOs, implementation plans, requirements, and Markdown checkboxes. Show the selected source set before mutation only when scope remains unclear or includes files that may be product docs rather than live plans.
For each selected file:
- Record its repository-relative path.
- Compute a SHA-256 hash with an available local tool.
- Read the full document and note its heading tree, checkboxes, explicit states, dependencies, acceptance sections, decisions, and local links.
- Assign stable source anchors based on heading paths and task text, adding a sibling ordinal only when needed.
If the Markdown contains <!-- taskgraph:<id> -->, call tg_resolve for that ID and treat the source as a re-import candidate.
2. Build a migration model
Read references/markdown-mapping.md for source-specific mapping rules.
Build an in-memory model before calling write tools. For each proposed item, keep:
- source path, anchor, and file hash;
- parent anchor or resolved Taskgraph parent ID;
- kind, execution mode, title, and status;
- description, acceptance criteria, priority, dates, tags, and required capabilities when explicit;
- explicit relationships and their direction;
- content that should become an
imported_source entry rather than work.
Store provenance in custom_fields named source_path, source_anchor, and source_sha256. Add migrated-from-markdown as a tag. Use descriptions for concise execution context and acceptance criteria for testable completion conditions.
Migrate at deliverable granularity. Map each concrete, independently completable deliverable or requirement from the source to its own action with its own acceptance criteria; do not collapse a chapter, phase, or feature area into one generic task. Milestones and phases become containers whose children are those deliverables. Keep prose, examples, and vague ideas out of the action tree — they belong in descriptions, imported-source entries, or nowhere.
Use a shared root only when multiple files describe one project. Keep separate projects separate. When importing under an existing item, map the top document heading to that item if it describes the same work; do not create a redundant wrapper.
3. Reconcile Taskgraph state
- Resolve the requested target parent or project.
- Inspect it with
tg_get_item and a bounded tg_get_graph.
- Search by exact or distinctive titles when the target is not known.
- Match in this order: embedded Taskgraph ID, matching source path plus source anchor, then a user-confirmed existing item.
- Classify each source node as create, update, unchanged, or conflict.
Do not match by title alone when duplicates are plausible. If both source and Taskgraph carry different material changes and intent is unclear, stop before writes and present the conflict. Keep Taskgraph state when a re-import source omits a field; omission is not a delete request.
For updates, fetch the current version, then call tg_patch_item with expected_version and only changed fields. On VERSION_CONFLICT, re-read and reassess.
4. Preview the target graph
Prepare a compact preview containing:
- the proposed hierarchy and canonical parent;
- create, update, unchanged, and conflict counts;
- source-to-item status and kind mappings;
- hard and soft dependency edges;
- preserved source fragments;
- warnings for unknown states, ambiguous owners, path collisions, or missing dependency targets.
Call tg_create_items with the proposed new items, relationships, atomic: true, and dry_run: true. Use one unique client_ref per new item and $client_ref for new parents and relationship endpoints. Use stable IDs for existing endpoints.
Proceed to commit when the dry run succeeds and no material ambiguity remains. Ask for a choice only when different mappings would change the work, ownership, or dependencies.
5. Commit the migration
Repeat the successful create request with dry_run: false. Keep a migration within the server's bounds; for a large source set, split it by complete subtrees in parent-before-child order and verify each chunk before continuing.
Apply version-checked patches to matched items. Add or change relationships with tg_mutate_relationships. After items exist, attach non-action source material to the nearest useful item with tg_record_entry and entry_type: "imported_source". Include the source path and anchor in each entry; keep large copied sections bounded.
After creating imported acceptance criteria, re-read their IDs. Mark a criterion met only when the source marks it complete or marks its owning item done; use waived only with an explicit source reason. Do not leave a migrated done item with pending criteria. Preserve unresolved criteria as pending and flag a conflicting done state.
Do not encode a named blocker as prose when both endpoints exist. Do not create dependencies merely from list order, heading order, or Markdown links.
If a commit times out, inspect the target for the source anchors before retrying. client_ref values are request-local and do not prevent duplicates across calls.
6. Verify and hand off
- Re-read each created or patched root with
tg_get_item.
- Inspect each migrated subtree with bounded
tg_get_graph calls. If a result is truncated, inspect smaller subtrees.
- Check item counts, hierarchy, statuses, acceptance criteria, provenance fields, and relationship direction against the migration model.
- Call
tg_explain_blocked for items expected to be ready or blocked when dependencies changed.
- Report source files, Taskgraph root IDs and canonical paths, create/update counts, relationships, warnings, and whether source files remain unchanged.
Only after this verification, perform any user-requested Markdown retirement. Prefer a short migration notice that names the Taskgraph root ID and canonical path when the user wants a traceable stub. State exactly what was changed or removed.