Skip to content

Migration Guide

This guide covers migrating from existing project management tools to LumenFlow. You can migrate incrementally or all at once.

Keep What Works

LumenFlow replaces execution tracking, not roadmaps. Keep Jira/Linear for planning if it works.

Start Fresh

No need to migrate history. Start with new work, archive old tickets.

Link Back

Reference external IDs in WU specs for traceability.

Gradual Adoption

Migrate one team or area first. Expand when comfortable.

Jira/Linear/GitHubLumenFlowNotes
Ticket/IssueWork Unit (WU)Atomic unit of work
EpicInitiativeMulti-WU scope
SprintLane WIPNo time-boxing, flow-based
StatusWU Statusready, in_progress, blocked, waiting, done
Assigneeassigned_toOne owner per WU
Labelslane, typeStructured categorization
Story PointsComplexity estimateOptional, tool-call based for agents
Acceptance CriteriaacceptanceYAML array, verifiable outcomes
PrioritypriorityP0-P3
Jira StatusLinear StatusGitHub StatusLumenFlow Status
To DoBacklogOpenready
In ProgressIn ProgressIn Progressin_progress
BlockedBlocked-blocked
In ReviewIn ReviewIn Reviewwaiting
DoneDoneCloseddone
JiraLinearGitHubLumenFlow
Highest/BlockerUrgent-P0
HighHigh-P1
MediumMedium-P2
Low/LowestLow-P3
  1. Export issues to JSON

    Use Jira’s bulk export or REST API:

    # Using jira-cli
    jira issue list \
      --project PROJ \
      --status "To Do,In Progress" \
      --format json > jira-export.json
  2. Convert to WU YAML

    // convert-jira.mjs
    import { readFileSync, writeFileSync, mkdirSync } from 'fs';
    
    const jiraExport = JSON.parse(readFileSync('jira-export.json', 'utf8'));
    
    // Lane mapping
    const laneMap = {
      frontend: 'Experience: UI',
      backend: 'Framework: Core',
      devops: 'Operations: Infrastructure',
      docs: 'Content: Documentation',
    };
    
    // Type mapping
    const typeMap = {
      Story: 'feature',
      Bug: 'bug',
      Task: 'chore',
      Spike: 'discovery',
    };
    
    // Priority mapping
    const priorityMap = {
      Highest: 'P0',
      High: 'P1',
      Medium: 'P2',
      Low: 'P3',
      Lowest: 'P3',
    };
    
    mkdirSync('docs/04-operations/tasks/wu', { recursive: true });
    
    jiraExport.issues.forEach((issue, index) => {
      const wuId = `WU-${String(index + 1).padStart(3, '0')}`;
      const component = issue.fields.components?.[0]?.name?.toLowerCase() || 'backend';
    
      const wu = {
        id: wuId,
        title: issue.fields.summary,
        lane: laneMap[component] || 'Framework: Core',
        type: typeMap[issue.fields.issuetype.name] || 'feature',
        status: 'ready',
        priority: priorityMap[issue.fields.priority.name] || 'P2',
        description: issue.fields.description || '',
        acceptance: parseAcceptanceCriteria(issue.fields.description),
        code_paths: [],
        external_refs: [`JIRA-${issue.key}`],
      };
    
      writeFileSync(`docs/04-operations/tasks/wu/${wuId}.yaml`, toYAML(wu));
    });
    
    function parseAcceptanceCriteria(description) {
      // Extract bullet points that look like acceptance criteria
      if (!description) return ['Feature works as specified'];
      const lines = description.split('\n');
      const criteria = lines
        .filter((l) => l.match(/^[\-\*]\s/))
        .map((l) => l.replace(/^[\-\*]\s+/, '').trim())
        .filter((l) => l.length > 0);
      return criteria.length > 0 ? criteria : ['Feature works as specified'];
    }
    
    function toYAML(obj) {
      // Simple YAML serialization (use js-yaml for production)
      return Object.entries(obj)
        .map(([k, v]) => {
          if (Array.isArray(v)) {
            return `${k}:\n${v.map((i) => `  - ${JSON.stringify(i)}`).join('\n')}`;
          }
          return `${k}: ${typeof v === 'string' && v.includes('\n') ? `|\n  ${v.replace(/\n/g, '\n  ')}` : JSON.stringify(v)}`;
        })
        .join('\n');
    }
  3. Run conversion

    node convert-jira.mjs
  1. Audit existing tickets

    Count and categorize:

    • How many open tickets?
    • How many are actually actionable?
    • How many are stale (no activity in 30+ days)?
  2. Archive stale tickets

    Before migrating, close tickets that are:

    • Older than 6 months with no activity
    • Superseded by other work
    • No longer relevant to current goals
  3. Set up LumenFlow

    Follow the Existing Projects Guide to set up LumenFlow in your repo.

  4. Export remaining tickets

    Use the scripts above to export actionable tickets.

  5. Run conversion

    node convert-jira.mjs  # or convert-linear.mjs, convert-github.mjs
  6. Review converted WUs

    Check a sample:

    • Are lanes correct?
    • Are acceptance criteria specific enough?
    • Do priorities make sense?
  7. Generate backlog

    npx lumenflow backlog:generate
  8. Freeze old system

    Set ticket system to read-only for the migrated project, or add a banner:

    This project now uses LumenFlow. New work: see [repo]/docs/04-operations/tasks/

  9. Team onboarding

Pattern A: LumenFlow for Execution, Jira for Planning

Section titled “Pattern A: LumenFlow for Execution, Jira for Planning”
Jira                          LumenFlow
────                          ─────────
Epics/Roadmap                 Initiatives
  ↓ (quarterly)               (linked via external_refs)
Stories                       ──→ WUs (execution)
  (planning)                      ↓
                                 Done

Sprint Velocity ←──────────── DORA Metrics

Keep: High-level planning, stakeholder visibility, sprint reports Move: Day-to-day execution, developer workflow, CI integration

Close Jira/Linear entirely. Use LumenFlow for:

  • WUs (execution)
  • Initiatives (multi-WU planning)
  • Backlog (prioritized queue)
  • DORA metrics (reporting)
Team A: Full LumenFlow
Team B: Hybrid (LumenFlow + Linear for planning)
Team C: Not yet migrated

Teams can adopt at different paces. Cross-team WUs use external_refs for linking.

id: WU-042
title: Implement user search
external_refs:
  - JIRA-PROJ-123
  - LINEAR-ABC-45
  - GH-789
# Find WU by Jira ID
grep -r "JIRA-PROJ-123" docs/04-operations/tasks/wu/

Add WU reference back to original ticket:

Migrated to LumenFlow: WU-042

WUs support dependencies:

id: WU-101
dependencies:
  - WU-100 # Must complete first
blocked_by:
  - WU-099 # Currently blocked

LumenFlow doesn’t have sub-tasks. Instead:

  • Small sub-tasks: Include in parent WU acceptance criteria
  • Large sub-tasks: Promote to separate WUs with dependencies

Move attachments to:

  • Code comments (if small snippets)
  • Documentation files (if specs)
  • External storage with links in WU description

LumenFlow provides:

  • pnpm flow:report - DORA metrics
  • cat docs/04-operations/tasks/status.md - Recent completions
  • Initiative progress tracking

After migration, verify:

# 1. Validate all WU YAML files
npx lumenflow validate

# 2. Check for orphaned WUs (not in backlog)
npx lumenflow backlog:check

# 3. Verify external references are unique
grep -rh "external_refs" docs/04-operations/tasks/wu/ | sort | uniq -d

# 4. Run gates to ensure everything builds
npx gates