# FlyDocs Upgrade — Local to Cloud Migration (PM/Planning Agent)

AI-guided migration from local tier to cloud tier. Handles API connection,
issue migration, and local content disposition in a single guided flow.

Read the workflow skill's `reference/script-catalog.md` for operation IDs and
their arguments before executing anything.

Triggers: "upgrade to cloud", "migrate to cloud", "local to cloud", "flydocs cloud"

---

## IMPORTANT: Use Plan Mode

**Before executing any migration steps, enter plan mode.** This migration
involves multiple phases with irreversible actions. Planning first ensures
the user understands what will happen:

1. Run pre-flight checks (Phase 0) to inventory the current state
2. Present a migration summary with issue counts and what each phase does
3. Get user approval before making any changes

Only exit plan mode and begin execution after the user approves the plan.

---

## Phase 0: Pre-flight Checks

Before starting, verify the project is eligible for migration.

**Step 1: Read config and verify tier.**

Read `.flydocs/config.json` and check the `tier` field.

- If `tier` is `cloud`: abort with message:
  ```
  This project is already on the cloud tier. No migration needed.
  Run flydocs init to configure your cloud workspace.
  ```
- If `tier` is not `local`: abort with error about unexpected tier value.

**Step 2: Inventory local issues.**

Scan `flydocs/issues/` for all issue files across status directories:

```
flydocs/issues/backlog/*.md
flydocs/issues/ready/*.md
flydocs/issues/implementing/*.md
flydocs/issues/review/*.md
flydocs/issues/validating/*.md
flydocs/issues/done/*.md
flydocs/issues/closed/*.md
```

For each issue file found, read the YAML frontmatter to extract:

- Title
- Type (feature, bug, chore, idea)
- Priority
- Status (from parent directory name)
- Any comments in the body

Count totals by status and type.

**Step 3: Check for API readiness.**

Check if an API key is available via environment variable (`FLYDOCS_API_KEY`),
global credentials (`~/.flydocs/credentials`), or legacy `.env.local`. If not
found, warn the user to run `flydocs init` or `flydocs auth` before Phase 1.

**Step 4: Present migration summary.**

```
Migration Summary
─────────────────
Current tier: local
Target tier: cloud

Local issues found: [N total]
  - Backlog: [n]
  - Ready: [n]
  - Implementing: [n]
  - Review: [n]
  - Done: [n]

Migration will:
  1. Connect to cloud provider via flydocs connect
  2. Create [N] issues in your cloud provider with matching status
  3. Archive, delete, or keep local issue files (your choice)

API key: [set / not set — will be needed in Phase 1]

Ready to proceed?
```

Confirm with the user before continuing.

---

## Phase 1: Connect to Cloud

Guide the user through connecting to the cloud provider. This swaps the
tier, stores the API key, and configures the workflow skill for cloud access.

**Step 1: Get API key.**

Ask the user for their FlyDocs API key (`fdk_...`). If `FLYDOCS_API_KEY`
is already set in the environment, confirm they want to use the existing
key or enter a new one.

If no key is available, instruct the user:

```
You'll need a FlyDocs API key (fdk_...) from your dashboard at app.flydocs.ai.

Option A: Run `flydocs connect --here` in your terminal (handles everything)
Option B: Add FLYDOCS_API_KEY=fdk_... to your .env or .env.local file
```

Wait for the user to confirm the key is set before proceeding.

**Step 2: Update config to cloud tier.**

Read `.flydocs/config.json`, update `tier` to `"cloud"`, and write it back.
Preserve all existing config values (detected stack, skills, etc.).

**Step 3: Complete tier configuration.**

Instruct the user to run `flydocs connect --here` from their terminal if
they haven't already. This handles the tier configuration update and
connects to the relay API.

**Step 4: Verify connection.**

After the user confirms the connection, verify:

1. Read `.flydocs/config.json` — `tier` should now be `cloud`
2. Run a test command to verify the connection:
   ```bash
   flydocs run issue.list --limit 1
   ```

If any check fails, help the user troubleshoot before proceeding.

---

## Phase 2: Issue Migration

Migrate local issues to the cloud provider. After `flydocs connect` updates
the tier, the workflow skill now routes to the cloud API.

**IMPORTANT:** For migration, read the local issue markdown files directly
from `flydocs/issues/` rather than through workflow operations.

**Step 1: Read local issue files.**

For each issue file in `flydocs/issues/{status}/*.md`, parse:

- **YAML frontmatter** — between `---` markers at the top of the file.
  Fields: `title`, `type`, `priority`, `estimate`, `created`, `assigned`.
- **Body** — everything after the frontmatter closing `---`.
  This is the issue description in markdown.
- **Comments** — look for `## Comments` section in the body.
  Each comment has a timestamp header and content.
- **Status** — derived from the parent directory name. Map to cloud status:
  - `backlog` -> `BACKLOG`
  - `ready` -> `READY`
  - `implementing` -> `IMPLEMENTING`
  - `review` -> `REVIEW`
  - `validating` -> `VALIDATING`
  - `done` -> `DONE`
  - `closed` -> `CLOSED`

**Step 2: Create issues in cloud.**

For each local issue, create it in the cloud provider. Read the workflow
skill's `reference/script-catalog.md` first for exact argument shapes.

A migrated description is a whole issue body, so it goes in a file rather than
on the command line. Stage it under `.flydocs/scratch/` — workspace-local and
gitignored — and pass the path:

```bash
mkdir -p .flydocs/scratch
# write the parsed body to .flydocs/scratch/migrate-<local-id>.md, then:
flydocs run issue.create \
  --title "Issue title" \
  --type feature \
  --priority 3 \
  --estimate 2 \
  --file .flydocs/scratch/migrate-<local-id>.md
```

Delete each scratch file once its issue is created. A migration that leaves
dozens of half-migrated bodies behind is a migration nobody can audit.

If the issue had comments in its local file, append them to the description
body under a `## Migration Notes` section:

```markdown
## Migration Notes

Migrated from local tier on YYYY-MM-DD.

### Previous Comments

**YYYY-MM-DD HH:MM** — [comment content]
```

**Step 3: Transition non-backlog issues.**

Issues created via `issue.create` start in BACKLOG status. For issues that were
in other statuses locally, transition them to match. The comment is a required
positional, not a flag:

```bash
flydocs run issue.transition \
  <new-issue-ref> <TARGET_STATUS> \
  "Migrated from local tier — original status was [status]"
```

Status transitions must follow the workflow — you may need intermediate
transitions for some statuses. Read
`.claude/skills/flydocs-workflow/reference/status-workflow.md` for valid
transitions.

**Step 4: Track the mapping.**

Maintain and display an old-to-new ID mapping as issues are migrated:

```
Migration Progress
──────────────────
[1/N] local-1 "Setup auth" -> FLY-234 (BACKLOG)
[2/N] local-2 "Fix header" -> FLY-235 (IMPLEMENTING)
[3/N] local-3 "Add tests"  -> FLY-236 (READY)
...
```

**Step 5: Handle failures.**

If any issue fails to create or transition:

- Log the error with the local issue reference
- Continue with remaining issues (don't abort the whole migration)
- Report all failures at the end with suggestions for manual resolution

---

## Phase 3: Content Disposition

After migration, handle the local issue files. Present three options
(same pattern as the uninstall command):

```
All [N] issues have been migrated to your cloud provider.

What would you like to do with the local issue files?

1. Archive — Rename flydocs/issues/ to flydocs/issues-archive/
   (keeps files as read-only reference)

2. Delete — Remove flydocs/issues/ and .flydocs/issues.counter
   (clean slate, issues live in your cloud provider now)

3. Keep — Leave files as-is
   (local files remain alongside cloud issues)
```

Execute the user's choice:

- **Archive**: Rename `flydocs/issues/` to `flydocs/issues-archive/`
- **Delete**: Remove `flydocs/issues/` directory and `.flydocs/issues.counter` file
- **Keep**: No action needed

---

## Phase 4: Completion

Summarize the migration and provide next steps.

**Step 1: Migration summary.**

```
Migration Complete
──────────────────
Tier: local -> cloud
Issues migrated: [N] ([success] succeeded, [fail] failed)
Local files: [archived / deleted / kept]

ID Mapping:
  local-1 -> FLY-234
  local-2 -> FLY-235
  ...
```

**Step 2: Next steps.**

```
Next steps:
  1. Run flydocs init to configure milestones and labels
  2. Review migrated issues in your cloud provider
  3. Start working with /start-session
```

**Step 3: Commit prompt.**

Offer to commit the configuration changes:

```
The tier change and configuration update modified several files.
Want to commit these changes?
```

If the user agrees, create a commit with message:
`Upgrade FlyDocs from local to cloud tier`

Stage: `.flydocs/config.json`, `.claude/skills/`, `.claude/CLAUDE.md`,
`.cursor/rules/`, and any archive/deletion changes.

---

## Error Handling

- **Already cloud tier** — Abort in Phase 0 with helpful message.
- **Zero local issues** — Skip Phase 2 entirely, proceed to Phase 4.
- **flydocs connect fails** — Help troubleshoot; do not proceed to Phase 2.
- **Partial migration failure** — Report which issues succeeded and which
  failed. Offer to retry failed issues or proceed with what succeeded.
- **Cancel mid-migration** — Report current state: which issues were already
  created in cloud, which local files remain. The user can re-run to
  continue (Phase 0 will re-inventory remaining local issues).

---

## Key Rules

1. **Always read the workflow skill's `reference/script-catalog.md`** before
   running operations in Phase 2. Argument shapes may have changed.
2. **Never delete local files without explicit user consent** in Phase 3.
3. **For migration, read issue files directly.** Do not use workflow
   operations to read local tier issue files during migration.
4. **Status transitions must follow the workflow.** Read the status workflow
   reference for valid transition paths.
5. **Report progress continuously.** Show the mapping table after each
   issue is migrated so the user can follow along.

$ARGUMENTS
