Files
Claude-Code-Workflow/.codex/skills/parallel-dev-cycle/phases/01-session-init.md
catlog22 4344e79e68 Add benchmark results for fast3 and fast4, implement KeepAliveLspBridge, and add tests for staged strategies
- Added new benchmark result files: compare_2026-02-09_score_fast3.json and compare_2026-02-09_score_fast4.json.
- Implemented KeepAliveLspBridge to maintain a persistent LSP connection across multiple queries, improving performance.
- Created unit tests for staged clustering strategies in test_staged_stage3_fast_strategies.py, ensuring correct behavior of score and dir_rr strategies.
2026-02-09 20:45:29 +08:00

7.8 KiB

Phase 1: Session Initialization

Create or resume a development cycle, initialize state file and directory structure.

Objective

  • Parse user arguments (TASK, --cycle-id, --extend, --auto, --parallel)
  • Create new cycle with unique ID OR resume existing cycle
  • Initialize directory structure for all agents
  • Create master state file
  • Output: cycleId, state, progressDir

Execution

Step 1.1: Parse Arguments & Load Prep Package

const { cycleId: existingCycleId, task, mode = 'interactive', extension } = options

// Validate mutual exclusivity
if (!existingCycleId && !task) {
  console.error('Either --cycle-id or task description is required')
  return { status: 'error', message: 'Missing cycleId or task' }
}

// ── Prep Package: Detect → Validate → Consume ──
let prepPackage = null
const prepPath = `${projectRoot}/.workflow/.cycle/prep-package.json`

if (fs.existsSync(prepPath)) {
  const raw = JSON.parse(Read(prepPath))
  const checks = validatePrepPackage(raw, projectRoot)

  if (checks.valid) {
    prepPackage = raw
    task = prepPackage.task.refined
    console.log(`✓ Prep package loaded: score=${prepPackage.task.quality_score}/10, auto=${prepPackage.auto_iteration.enabled}`)
    console.log(`  Checks passed: ${checks.passed.join(', ')}`)
  } else {
    console.warn(`⚠ Prep package found but failed validation:`)
    checks.failures.forEach(f => console.warn(`  ✗ ${f}`))
    console.warn(`  → Falling back to default behavior (prep-package ignored)`)
    prepPackage = null
  }
}

/**
 * Validate prep-package.json integrity before consumption.
 * Returns { valid: bool, passed: string[], failures: string[] }
 */
function validatePrepPackage(prep, projectRoot) {
  const passed = []
  const failures = []

  // Check 1: prep_status must be "ready"
  if (prep.prep_status === 'ready') {
    passed.push('status=ready')
  } else {
    failures.push(`prep_status is "${prep.prep_status}", expected "ready"`)
  }

  // Check 2: project_root must match current project
  if (prep.environment?.project_root === projectRoot) {
    passed.push('project_root match')
  } else {
    failures.push(`project_root mismatch: prep="${prep.environment?.project_root}", current="${projectRoot}"`)
  }

  // Check 3: quality_score must be >= 6
  if ((prep.task?.quality_score || 0) >= 6) {
    passed.push(`quality=${prep.task.quality_score}/10`)
  } else {
    failures.push(`quality_score ${prep.task?.quality_score || 0} < 6 minimum`)
  }

  // Check 4: generated_at must be within 24 hours
  const generatedAt = new Date(prep.generated_at)
  const hoursSince = (Date.now() - generatedAt.getTime()) / (1000 * 60 * 60)
  if (hoursSince <= 24) {
    passed.push(`age=${Math.round(hoursSince)}h`)
  } else {
    failures.push(`prep-package is ${Math.round(hoursSince)}h old (max 24h), may be stale`)
  }

  // Check 5: required fields exist
  const requiredFields = [
    'task.refined',
    'auto_iteration.convergence.test_pass_rate',
    'auto_iteration.convergence.coverage',
    'auto_iteration.phase_gates.zero_to_one',
    'auto_iteration.phase_gates.one_to_hundred',
    'auto_iteration.agent_focus.zero_to_one',
    'auto_iteration.agent_focus.one_to_hundred'
  ]
  const missing = requiredFields.filter(path => {
    const val = path.split('.').reduce((obj, key) => obj?.[key], prep)
    return val === undefined || val === null
  })
  if (missing.length === 0) {
    passed.push('fields complete')
  } else {
    failures.push(`missing fields: ${missing.join(', ')}`)
  }

  // Check 6: convergence values are valid numbers
  const conv = prep.auto_iteration?.convergence
  if (conv && typeof conv.test_pass_rate === 'number' && typeof conv.coverage === 'number'
      && conv.test_pass_rate > 0 && conv.test_pass_rate <= 100
      && conv.coverage > 0 && conv.coverage <= 100) {
    passed.push(`convergence valid (test≥${conv.test_pass_rate}%, cov≥${conv.coverage}%)`)
  } else {
    failures.push(`convergence values invalid: test_pass_rate=${conv?.test_pass_rate}, coverage=${conv?.coverage}`)
  }

  return {
    valid: failures.length === 0,
    passed,
    failures
  }
}

Step 1.2: Utility Functions

const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()

function readCycleState(cycleId) {
  const stateFile = `${projectRoot}/.workflow/.cycle/${cycleId}.json`
  if (!fs.existsSync(stateFile)) {
    return null
  }
  return JSON.parse(Read(stateFile))
}

Step 1.3: New Cycle Creation

When TASK is provided (no --cycle-id):

// Generate unique cycle ID
const timestamp = getUtc8ISOString().replace(/[-:]/g, '').split('.')[0]
const random = Math.random().toString(36).substring(2, 10)
const cycleId = `cycle-v1-${timestamp}-${random}`

console.log(`Creating new cycle: ${cycleId}`)

Create Directory Structure

mkdir -p ${projectRoot}/.workflow/.cycle/${cycleId}.progress/{ra,ep,cd,vas,coordination}
mkdir -p ${projectRoot}/.workflow/.cycle/${cycleId}.progress/ra/history
mkdir -p ${projectRoot}/.workflow/.cycle/${cycleId}.progress/ep/history
mkdir -p ${projectRoot}/.workflow/.cycle/${cycleId}.progress/cd/history
mkdir -p ${projectRoot}/.workflow/.cycle/${cycleId}.progress/vas/history

Initialize State File

function createCycleState(cycleId, taskDescription) {
  const stateFile = `${projectRoot}/.workflow/.cycle/${cycleId}.json`
  const now = getUtc8ISOString()

  const state = {
    // Metadata
    cycle_id: cycleId,
    title: taskDescription.substring(0, 100),
    description: taskDescription,
    max_iterations: prepPackage?.auto_iteration?.max_iterations || 5,
    status: 'running',
    created_at: now,
    updated_at: now,

    // Agent tracking
    agents: {
      ra: { status: 'idle', output_files: [] },
      ep: { status: 'idle', output_files: [] },
      cd: { status: 'idle', output_files: [] },
      vas: { status: 'idle', output_files: [] }
    },

    // Phase tracking
    current_phase: 'init',
    completed_phases: [],
    current_iteration: 0,

    // Shared context (populated by agents)
    requirements: null,
    exploration: null,
    plan: null,
    changes: [],
    test_results: null,

    // Prep package integration (from /prompts:prep-cycle)
    convergence: prepPackage?.auto_iteration?.convergence || null,
    phase_gates: prepPackage?.auto_iteration?.phase_gates || null,
    agent_focus: prepPackage?.auto_iteration?.agent_focus || null,
    source_refs: prepPackage?.task?.source_refs || null
  }

  Write(stateFile, JSON.stringify(state, null, 2))
  return state
}

Step 1.4: Resume Existing Cycle

When --cycle-id is provided:

const cycleId = existingCycleId
const state = readCycleState(cycleId)

if (!state) {
  console.error(`Cycle not found: ${cycleId}`)
  return { status: 'error', message: 'Cycle not found' }
}

console.log(`Resuming cycle: ${cycleId}`)

// Apply extension if provided
if (extension) {
  console.log(`Extension: ${extension}`)
  state.description += `\n\n--- ITERATION ${state.current_iteration + 1} ---\n${extension}`
}

Step 1.5: Control Signal Check

Before proceeding, verify cycle status allows continuation:

function checkControlSignals(cycleId) {
  const state = readCycleState(cycleId)

  switch (state?.status) {
    case 'paused':
      return { continue: false, action: 'pause_exit' }
    case 'failed':
      return { continue: false, action: 'stop_exit' }
    case 'running':
      return { continue: true, action: 'continue' }
    default:
      return { continue: false, action: 'stop_exit' }
  }
}

Output

  • Variable: cycleId - Unique cycle identifier
  • Variable: state - Initialized or resumed cycle state object
  • Variable: progressDir - ${projectRoot}/.workflow/.cycle/${cycleId}.progress
  • TodoWrite: Mark Phase 1 completed, Phase 2 in_progress

Next Phase

Return to main flow, then auto-continue to Phase 2: Agent Execution.