#
tokens: 45585/50000 34/34 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── .npmignore
├── api
│   └── spec-workflow.openapi.yaml
├── eslint.config.js
├── LICENSE
├── logo.png
├── package-lock.json
├── package.json
├── README-zh.md
├── README.md
├── scripts
│   ├── generateOpenApiWebUI.ts
│   ├── generateTypes.ts
│   ├── publish-npm.sh
│   ├── sync-package.sh
│   └── validateOpenApi.ts
├── src
│   ├── features
│   │   ├── check
│   │   │   ├── analyzeStage.ts
│   │   │   ├── checkWorkflow.ts
│   │   │   └── generateNextDocument.ts
│   │   ├── confirm
│   │   │   └── confirmStage.ts
│   │   ├── executeWorkflow.ts
│   │   ├── init
│   │   │   ├── createRequirementsDoc.ts
│   │   │   └── initWorkflow.ts
│   │   ├── shared
│   │   │   ├── confirmationStatus.ts
│   │   │   ├── documentAnalyzer.ts
│   │   │   ├── documentStatus.ts
│   │   │   ├── documentTemplates.ts
│   │   │   ├── documentUtils.ts
│   │   │   ├── mcpTypes.ts
│   │   │   ├── openApiLoader.ts
│   │   │   ├── openApiTypes.ts
│   │   │   ├── progressCalculator.ts
│   │   │   ├── responseBuilder.ts
│   │   │   ├── taskGuidanceTemplate.ts
│   │   │   ├── taskParser.ts
│   │   │   └── typeGuards.ts
│   │   ├── skip
│   │   │   └── skipStage.ts
│   │   └── task
│   │       └── completeTask.ts
│   ├── index.ts
│   └── tools
│       └── specWorkflowTool.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Claude configuration
.claude
/memory

# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Testing related
# 排除所有测试相关文件
/src/**/*.test.js
/src/**/*.spec.js
/src/**/*.test.ts
/src/**/*.spec.ts
coverage/
# test-specs/ - 在 dev 分支中保留测试套件
test-specs/reports/
test-specs/node_modules/
test-specs/temp/

# Documentation
docs/
guidance/zh/

# Build artifacts
dist/
build/
*.log

# Generated package directory (auto-generated during build)
package/

# Environment configuration
.env
.env.local
.env.*.local
test-specs/.env.test

# Editor configuration
.vscode/
.idea/
*.swp
*.swo
*~

# System files
.DS_Store
Thumbs.db

# Temporary files
*.tmp
*.temp
.cache/

# Local configuration
*.local.*
mcp-config.json
CLAUDE.local.md

# Preview files
preview/

# Prompt files (migrated to OpenAPI)
prompts/

# WebUI generated files
webui/
/specs

# Debug files
debug.sh

# Security - Never commit these files
push-to-github.sh
*-token.sh
*.token
.clinerules

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Spec Workflow MCP

[![npm version](https://img.shields.io/npm/v/spec-workflow-mcp.svg)](https://www.npmjs.com/package/spec-workflow-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![MCP](https://img.shields.io/badge/MCP-Compatible-blue)](https://modelcontextprotocol.com)

[English](README.md) | [简体中文](README-zh.md)

Guide AI to systematically complete software development through a structured **Requirements → Design → Tasks** workflow, ensuring code implementation stays aligned with business needs.

## Why Use It?

### ❌ Without Spec Workflow
- AI jumps randomly between tasks, lacking systematic approach
- Requirements disconnect from actual code implementation
- Scattered documentation, difficult to track project progress
- Missing design decision records

### ✅ With Spec Workflow
- AI completes tasks sequentially, maintaining focus and context
- Complete traceability from user stories to code implementation
- Standardized document templates with automatic progress management
- Each stage requires confirmation, ensuring correct direction
- **Persistent progress**: Continue from where you left off with `check`, even in new conversations

## Recent Updates

> **v1.0.7**
> - 🎯 Improved reliability for most models to manage tasks with spec workflow
>
> **v1.0.6**
> - ✨ Batch task completion: Complete multiple tasks at once for faster progress on large projects
> 
> **v1.0.5** 
> - 🐛 Edge case fixes: Distinguish between "task not found" and "task already completed" to prevent workflow interruption
> 
> **v1.0.4**
> - ✅ Task management: Added task completion tracking for systematic project progression
> 
> **v1.0.3**
> - 🎉 Initial release: Core workflow framework for Requirements → Design → Tasks

## Quick Start

### 1. Install (Claude Code Example)
```bash
claude mcp add spec-workflow-mcp -s user -- npx -y spec-workflow-mcp@latest
```

See [full installation guide](#installation) for other clients.

### 2. Start a New Project
```
"Help me use spec workflow to create a user authentication system"
```

### 3. Continue Existing Project
```
"Use spec workflow to check ./my-project"
```

The AI will automatically detect project status and continue from where it left off.

## Workflow Example

### 1. You describe requirements
```
You: "I need to build a user authentication system"
```

### 2. AI creates structured documents
```
AI: "I'll help you create spec workflow for user authentication..."

📝 requirements.md - User stories and functional requirements
🎨 design.md - Technical architecture and design decisions
✅ tasks.md - Concrete implementation task list
```

### 3. Review and implement step by step
After each stage, the AI requests your confirmation before proceeding, ensuring the project stays on the right track.

## Document Organization

### Basic Structure
```
my-project/specs/
├── requirements.md              # Requirements: user stories, functional specs
├── design.md                    # Design: architecture, APIs, data models
├── tasks.md                     # Tasks: numbered implementation steps
└── .workflow-confirmations.json # Status: automatic progress tracking
```

### Multi-module Projects
```
my-project/specs/
├── user-authentication/         # Auth module
├── payment-system/             # Payment module
└── notification-service/       # Notification module
```

You can specify any directory: `"Use spec workflow to create auth docs in ./src/features/auth"`

## AI Usage Guide

### 🤖 Make AI Use This Tool Better

**Strongly recommended** to add the following prompt to your AI assistant configuration. Without it, AI may:
- ❌ Not know when to invoke Spec Workflow
- ❌ Forget to manage task progress, causing disorganized work
- ❌ Not utilize Spec Workflow for systematic documentation
- ❌ Unable to continuously track project status

With this configuration, AI will intelligently use Spec Workflow to manage the entire development process.

> **Configuration Note**: Please modify the following based on your needs:
> 1. Change `./specs` to your preferred documentation directory path
> 2. Change "English" to your preferred documentation language (e.g., "Chinese")

```
# Spec Workflow Usage Guidelines

## 1. Check Project Progress
When user mentions continuing previous project or is unsure about current progress, proactively use:
specs-workflow tool with action.type="check" and path="./specs"

## 2. Documentation Language
All spec workflow documents should be written in English consistently, including all content in requirements, design, and task documents.

## 3. Documentation Directory
All spec workflow documents should be placed in ./specs directory to maintain consistent project documentation organization.

## 4. Task Management
Always use the following to manage task progress:
specs-workflow tool with action.type="complete_task" and taskNumber="current task number"
Follow the workflow guidance to continue working until all tasks are completed.

## 5. Best Practices
- Proactive progress check: When user says "continue from last time", first use check to see current status
- Language consistency: Use the same language throughout all project documents
- Flexible structure: Choose single-module or multi-module organization based on project scale
- Task granularity: Each task should be completable within 1-2 hours
```

## Installation

<details>
<summary>📦 Installation Instructions</summary>

### Requirements

- Node.js ≥ v18.0.0
- npm or yarn
- Claude Desktop or any MCP-compatible client

### Install in Different MCP Clients

#### Claude Code (Recommended)

Use the Claude CLI to add the MCP server:

```bash
claude mcp add spec-workflow-mcp -s user -- npx -y spec-workflow-mcp@latest
```

#### Claude Desktop

Add to your Claude Desktop configuration:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%/Claude/claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "spec-workflow": {
      "command": "npx",
      "args": ["-y", "spec-workflow-mcp@latest"]
    }
  }
}
```

#### Cursor

Add to your Cursor configuration (`~/.cursor/config.json`):

```json
{
  "mcpServers": {
    "spec-workflow": {
      "command": "npx",
      "args": ["-y", "spec-workflow-mcp@latest"]
    }
  }
}
```

#### Cline

Use Cline's MCP server management UI to add the server:

1. Open VS Code with Cline extension
2. Open Cline settings (gear icon)
3. Navigate to MCP Servers section
4. Add new server with:
   - Command: `npx`
   - Arguments: `-y spec-workflow-mcp@latest`

#### Windsurf (Codeium)

Add to your Windsurf configuration (`~/.codeium/windsurf/mcp_config.json`):

```json
{
  "mcpServers": {
    "spec-workflow": {
      "command": "npx",
      "args": ["-y", "spec-workflow-mcp@latest"],
      "env": {},
      "autoApprove": [],
      "disabled": false,
      "timeout": 60,
      "transportType": "stdio"
    }
  }
}
```

#### VS Code (with MCP extension)

Add to your VS Code settings (`settings.json`):

```json
{
  "mcp.servers": {
    "spec-workflow": {
      "command": "npx",
      "args": ["-y", "spec-workflow-mcp@latest"]
    }
  }
}
```

#### Zed

Add to your Zed configuration (`~/.config/zed/settings.json`):

```json
{
  "assistant": {
    "version": "2",
    "mcp": {
      "servers": {
        "spec-workflow": {
          "command": "npx",
          "args": ["-y", "spec-workflow-mcp@latest"]
        }
      }
    }
  }
}
```

### Install from Source

```bash
git clone https://github.com/kingkongshot/specs-mcp.git
cd specs-mcp
npm install
npm run build
```

Then add to Claude Desktop configuration:

```json
{
  "mcpServers": {
    "spec-workflow": {
      "command": "node",
      "args": ["/absolute/path/to/specs-mcp/dist/index.js"]
    }
  }
}
```

</details>


## Links

- [GitHub Repository](https://github.com/kingkongshot/specs-mcp)
- [NPM Package](https://www.npmjs.com/package/spec-workflow-mcp)
- [Report Issues](https://github.com/kingkongshot/specs-mcp/issues)

## License

MIT License

---

<a href="https://glama.ai/mcp/servers/@kingkongshot/specs-workflow-mcp">
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@kingkongshot/specs-workflow-mcp/badge" alt="Spec Workflow MCP server" />
</a>
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "moduleResolution": "node",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "types": ["node"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}
```

--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------

```javascript
import js from '@eslint/js';
import tseslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';

export default [
  {
    files: ['src/**/*.ts'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        ecmaVersion: 2022,
        sourceType: 'module',
        project: './tsconfig.json'
      }
    },
    plugins: {
      '@typescript-eslint': tseslint
    },
    rules: {
      ...js.configs.recommended.rules,
      ...tseslint.configs.recommended.rules,
      '@typescript-eslint/explicit-function-return-type': 'error',
      '@typescript-eslint/no-unused-vars': 'error',
      '@typescript-eslint/no-explicit-any': 'error'
    }
  },
  {
    ignores: ['dist/', 'node_modules/', '*.js', 'scripts/']
  }
];
```

--------------------------------------------------------------------------------
/src/features/init/createRequirementsDoc.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Create requirements document
 */

import { writeFileSync, existsSync } from 'fs';
import { join } from 'path';
import { getRequirementsTemplate } from '../shared/documentTemplates.js';

export interface CreateResult {
  generated: boolean;
  message: string;
  filePath?: string;
  fileName?: string;
}

export function createRequirementsDocument(
  path: string,
  featureName: string,
  introduction: string
): CreateResult {
  const fileName = 'requirements.md';
  const filePath = join(path, fileName);
  
  if (existsSync(filePath)) {
    return {
      generated: false,
      message: 'Requirements document already exists',
      fileName,
      filePath
    };
  }
  
  try {
    const content = getRequirementsTemplate(featureName, introduction);
    writeFileSync(filePath, content, 'utf-8');
    
    return {
      generated: true,
      message: 'Requirements document',
      fileName,
      filePath
    };
  } catch (error) {
    return {
      generated: false,
      message: `Failed to create document: ${error}`,
      fileName
    };
  }
}
```

--------------------------------------------------------------------------------
/src/features/shared/documentAnalyzer.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Document content analyzer
 * Uses XML markers to detect if document has been edited
 */

import { readFileSync, existsSync } from 'fs';

// XML marker definitions - matching actual template placeholders
export const TEMPLATE_MARKERS = {
  REQUIREMENTS_START: '<template-requirements>',
  REQUIREMENTS_END: '</template-requirements>',
  DESIGN_START: '<template-design>',
  DESIGN_END: '</template-design>',
  TASKS_START: '<template-tasks>',
  TASKS_END: '</template-tasks>'
};

/**
 * Analyze if document has been edited
 * Determined by checking if XML template markers exist
 */
export function isDocumentEdited(filePath: string): boolean {
  if (!existsSync(filePath)) {
    return false;
  }
  
  try {
    const content = readFileSync(filePath, 'utf-8');
    
    // Check if contains any template markers
    const hasTemplateMarkers = Object.values(TEMPLATE_MARKERS).some(marker => 
      content.includes(marker)
    );
    
    // If no template markers, it means it has been edited
    return !hasTemplateMarkers;
  } catch {
    return false;
  }
}


```

--------------------------------------------------------------------------------
/src/features/shared/documentUtils.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Shared utilities for document processing
 */

import { readFileSync } from 'fs';

export interface DocumentInfo {
  featureName: string;
  introduction: string;
}

export function extractDocumentInfo(requirementsPath: string): DocumentInfo {
  try {
    const content = readFileSync(requirementsPath, 'utf-8');
    const lines = content.split('\n');
    
    // Extract feature name
    const titleLine = lines.find(line => line.startsWith('# '));
    const featureName = titleLine 
      ? titleLine.replace('# ', '').replace(' - Requirements Document', '').trim()
      : 'Unnamed Feature';
    
    // Extract project background
    const backgroundIndex = lines.findIndex(line => line.includes('## Project Background'));
    let introduction = '';
    
    if (backgroundIndex !== -1) {
      for (let i = backgroundIndex + 1; i < lines.length; i++) {
        if (lines[i].startsWith('##')) break;
        if (lines[i].trim()) {
          introduction += lines[i] + '\n';
        }
      }
    }
    
    return {
      featureName,
      introduction: introduction.trim() || 'No description'
    };
  } catch {
    return {
      featureName: 'Unnamed Feature',
      introduction: 'No description'
    };
  }
}
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "spec-workflow-mcp",
  "version": "1.0.8",
  "description": "MCP server for managing spec workflow (requirements, design, implementation)",
  "type": "module",
  "main": "dist/index.js",
  "bin": {
    "spec-workflow-mcp": "dist/index.js"
  },
  "files": [
    "dist/**/*",
    "api/**/*"
  ],
  "scripts": {
    "build": "tsc && chmod 755 dist/index.js && ./scripts/sync-package.sh",
    "dev": "tsx src/index.ts",
    "start": "node dist/index.js",
    "lint": "eslint src",
    "typecheck": "tsc --noEmit",
    "debug": "./debug.sh",
    "watch": "tsc --watch",
    "inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
    "generate:types": "tsx scripts/generateTypes.ts",
    "generate:webui": "tsx scripts/generateOpenApiWebUI.ts",
    "sync:package": "./scripts/sync-package.sh",
    "publish": "./scripts/publish-npm.sh"
  },
  "keywords": [
    "mcp",
    "workflow",
    "spec"
  ],
  "author": "kingkongshot",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kingkongshot/specs-workflow-mcp.git"
  },
  "bugs": {
    "url": "https://github.com/kingkongshot/specs-workflow-mcp/issues"
  },
  "homepage": "https://github.com/kingkongshot/specs-workflow-mcp#readme",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.16.0",
    "@types/js-yaml": "^4.0.9",
    "js-yaml": "^4.1.0",
    "zod": "^3.25.76"
  },
  "devDependencies": {
    "@eslint/js": "^9.32.0",
    "@types/node": "^22.10.5",
    "@typescript-eslint/eslint-plugin": "^8.20.0",
    "@typescript-eslint/parser": "^8.20.0",
    "eslint": "^9.17.0",
    "tsx": "^4.19.2",
    "typescript": "^5.7.3"
  }
}

```

--------------------------------------------------------------------------------
/scripts/publish-npm.sh:
--------------------------------------------------------------------------------

```bash
#!/bin/bash

# Publish package to npm
# This script builds the project, generates the package, and publishes to npm

set -e

echo "🚀 Publishing to npm..."

# Check if user is logged in to npm
if ! npm whoami > /dev/null 2>&1; then
    echo "❌ Error: Not logged in to npm"
    echo "Please run: npm login"
    exit 1
fi

# Build the project (this will also generate the package directory)
echo "🏗️ Building project..."
npm run build

# Verify package directory exists
if [ ! -d "package" ]; then
    echo "❌ Error: Package directory not found"
    echo "Build process may have failed"
    exit 1
fi

# Check if package already exists on npm
PACKAGE_NAME=$(node -p "require('./package/package.json').name")
PACKAGE_VERSION=$(node -p "require('./package/package.json').version")

echo "📦 Package: $PACKAGE_NAME@$PACKAGE_VERSION"

# Check if this version already exists
if npm view "$PACKAGE_NAME@$PACKAGE_VERSION" version > /dev/null 2>&1; then
    echo "⚠️ Warning: Version $PACKAGE_VERSION already exists on npm"
    echo "Please update the version in package.json and try again"
    exit 1
fi

# Publish to npm
echo "📤 Publishing to npm..."
cd package

# Dry run first to check for issues
echo "🔍 Running dry-run..."
npm publish --dry-run

# Ask for confirmation
echo ""
read -p "🤔 Proceed with publishing $PACKAGE_NAME@$PACKAGE_VERSION? (y/N): " -n 1 -r
echo ""

if [[ $REPLY =~ ^[Yy]$ ]]; then
    # Actual publish
    npm publish
    
    echo ""
    echo "✅ Successfully published $PACKAGE_NAME@$PACKAGE_VERSION!"
    echo "🔗 View on npm: https://www.npmjs.com/package/$PACKAGE_NAME"
    echo ""
    echo "📥 Install with:"
    echo "  npm install -g $PACKAGE_NAME"
else
    echo "❌ Publishing cancelled"
    exit 1
fi

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

/**
 * MCP specification workflow server
 * Standard implementation based on MCP SDK
 */

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { specWorkflowTool } from './tools/specWorkflowTool.js';
import { openApiLoader } from './features/shared/openApiLoader.js';
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const packageJson = JSON.parse(
  readFileSync(join(__dirname, '..', 'package.json'), 'utf-8')
);

// Create server instance
const server = new McpServer({
  name: 'specs-workflow-mcp',
  version: packageJson.version
});

// Register tools
specWorkflowTool.register(server);

// Start server
async function main(): Promise<void> {
  try {
    // Initialize OpenAPI loader to ensure examples are cached
    openApiLoader.loadSpec();

    const transport = new StdioServerTransport();
    await server.connect(transport);

    // eslint-disable-next-line no-console
    console.error('✨ MCP specification workflow server started');
    // eslint-disable-next-line no-console
    console.error(`📍 Version: ${packageJson.version} (Fully compliant with MCP best practices)`);

  } catch (error) {
    // eslint-disable-next-line no-console
    console.error('❌ Startup failed:', error);
    // eslint-disable-next-line no-undef
    process.exit(1);
  }
}

// Graceful shutdown
// eslint-disable-next-line no-undef
process.on('SIGINT', () => {
  // eslint-disable-next-line no-console
  console.error('\n👋 Server shutdown');
  // eslint-disable-next-line no-undef
  process.exit(0);
});

main();
```

--------------------------------------------------------------------------------
/src/features/shared/progressCalculator.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Progress calculation
 */

import { WorkflowStatus } from './documentStatus.js';
import { getWorkflowConfirmations } from './confirmationStatus.js';

export interface WorkflowProgress {
  percentage: number;
  completedStages: number;
  totalStages: number;
  details: {
    requirements: StageProgress;
    design: StageProgress;
    tasks: StageProgress;
  };
}

interface StageProgress {
  exists: boolean;
  confirmed: boolean;
  skipped: boolean;
}

export function calculateWorkflowProgress(
  path: string,
  status: WorkflowStatus
): WorkflowProgress {
  const confirmations = getWorkflowConfirmations(path);
  
  const details = {
    requirements: getStageProgress(status.requirements, confirmations.confirmed.requirements, confirmations.skipped.requirements),
    design: getStageProgress(status.design, confirmations.confirmed.design, confirmations.skipped.design),
    tasks: getStageProgress(status.tasks, confirmations.confirmed.tasks, confirmations.skipped.tasks)
  };
  
  const stages = [details.requirements, details.design, details.tasks];
  const completedStages = stages.filter(s => s.confirmed || s.skipped).length;
  const totalStages = stages.length;
  
  // Simplified progress calculation: each stage takes 1/3
  // const stageProgress = 100 / totalStages; // \u672a\u4f7f\u7528
  let totalProgress = 0;
  
  // Requirements stage: 30%
  if (details.requirements.confirmed || details.requirements.skipped) {
    totalProgress += 30;
  }
  
  // Design stage: 30%
  if (details.design.confirmed || details.design.skipped) {
    totalProgress += 30;
  }
  
  // Tasks stage: 40% (only if confirmed, not skipped)
  // Skipping tasks doesn't count as progress since it's essential for development
  if (details.tasks.confirmed) {
    totalProgress += 40;
  }
  
  return {
    percentage: Math.round(totalProgress),
    completedStages,
    totalStages,
    details
  };
}

function getStageProgress(
  status: { exists: boolean },
  confirmed: boolean,
  skipped: boolean
): StageProgress {
  return {
    exists: status.exists,
    confirmed,
    skipped
  };
}
```

--------------------------------------------------------------------------------
/src/features/check/generateNextDocument.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Generate next stage document
 */

import { writeFileSync, existsSync } from 'fs';
import { join } from 'path';
import { WorkflowStage, getNextStage, getStageFileName } from '../shared/documentStatus.js';
import { getDesignTemplate, getTasksTemplate } from '../shared/documentTemplates.js';
import { extractDocumentInfo } from '../shared/documentUtils.js';

export interface NextDocumentResult {
  generated: boolean;
  alreadyExists?: boolean;
  message: string;
  fileName?: string;
  filePath?: string;
  guide?: unknown;
}

export async function generateNextDocument(
  path: string,
  currentStage: WorkflowStage
): Promise<NextDocumentResult> {
  const nextStage = getNextStage(currentStage);
  
  if (nextStage === 'completed') {
    return {
      generated: false,
      message: 'All documents completed'
    };
  }
  
  const fileName = getStageFileName(nextStage);
  const filePath = join(path, fileName);
  
  if (existsSync(filePath)) {
    return {
      generated: false,
      alreadyExists: true,
      message: `${fileName} already exists`,
      fileName,
      filePath
    };
  }
  
  // Extract feature information
  const documentInfo = extractDocumentInfo(join(path, 'requirements.md'));
  
  // Generate document content
  let content: string;
  
  switch (nextStage) {
    case 'design':
      content = getDesignTemplate(documentInfo.featureName);
      // guideType = 'design'; // \u672a\u4f7f\u7528
      break;
    case 'tasks':
      content = getTasksTemplate(documentInfo.featureName);
      // guideType = 'implementation'; // \u672a\u4f7f\u7528
      break;
    default:
      return {
        generated: false,
        message: `Unknown document type: ${nextStage}`
      };
  }
  
  try {
    writeFileSync(filePath, content, 'utf-8');
    
    return {
      generated: true,
      message: `Generated ${fileName}`,
      fileName,
      filePath,
      guide: undefined // Guide resources are now handled via OpenAPI shared resources
    };
  } catch (error) {
    return {
      generated: false,
      message: `Failed to generate document: ${error}`
    };
  }
}


```

--------------------------------------------------------------------------------
/src/features/shared/documentStatus.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Document status management related functions
 */

import { existsSync } from 'fs';
import { join } from 'path';
import { isStageSkipped, isStageConfirmed } from './confirmationStatus.js';

export interface DocumentStatus {
  exists: boolean;
}

export interface WorkflowStatus {
  requirements: DocumentStatus;
  design: DocumentStatus;
  tasks: DocumentStatus;
}

export type WorkflowStage = 'requirements' | 'design' | 'tasks' | 'completed';

export function getWorkflowStatus(path: string): WorkflowStatus {
  return {
    requirements: getDocumentStatus(path, 'requirements.md'),
    design: getDocumentStatus(path, 'design.md'),
    tasks: getDocumentStatus(path, 'tasks.md')
  };
}

function getDocumentStatus(path: string, fileName: string): DocumentStatus {
  const filePath = join(path, fileName);
  return { exists: existsSync(filePath) };
}


export function getCurrentStage(status: WorkflowStatus, path?: string): WorkflowStage {
  if (!path) {
    // Backward compatibility: if no path, return the first existing document stage
    if (status.requirements.exists) return 'requirements';
    if (status.design.exists) return 'design';
    if (status.tasks.exists) return 'tasks';
    return 'completed';
  }
  
  // Determine current stage based on confirmations
  // If requirements stage is not confirmed and not skipped, current stage is requirements
  if (!isStageConfirmed(path, 'requirements') && !isStageSkipped(path, 'requirements')) {
    return 'requirements';
  }
  
  // If design stage is not confirmed and not skipped, current stage is design
  if (!isStageConfirmed(path, 'design') && !isStageSkipped(path, 'design')) {
    return 'design';
  }
  
  // If tasks stage is not confirmed and not skipped, current stage is tasks
  if (!isStageConfirmed(path, 'tasks') && !isStageSkipped(path, 'tasks')) {
    return 'tasks';
  }
  
  return 'completed';
}

export function getNextStage(stage: WorkflowStage): WorkflowStage {
  const stages: WorkflowStage[] = ['requirements', 'design', 'tasks', 'completed'];
  const index = stages.indexOf(stage);
  return stages[Math.min(index + 1, stages.length - 1)];
}

export function getStageName(stage: string): string {
  const names: Record<string, string> = {
    requirements: 'Requirements Document',
    design: 'Design Document',
    tasks: 'Task List',
    completed: 'Completed'
  };
  return names[stage] || stage;
}

export function getStageFileName(stage: string): string {
  const fileNames: Record<string, string> = {
    requirements: 'requirements.md',
    design: 'design.md',
    tasks: 'tasks.md'
  };
  return fileNames[stage] || '';
}
```

--------------------------------------------------------------------------------
/src/features/shared/confirmationStatus.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Confirmation status management
 */

import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join } from 'path';

export interface ConfirmationStatus {
  requirements: boolean;
  design: boolean;
  tasks: boolean;
}

export interface SkipStatus {
  requirements: boolean;
  design: boolean;
  tasks: boolean;
}

export interface WorkflowConfirmations {
  confirmed: ConfirmationStatus;
  skipped: SkipStatus;
}

const CONFIRMATION_FILE = '.workflow-confirmations.json';

export function getWorkflowConfirmations(path: string): WorkflowConfirmations {
  const filePath = join(path, CONFIRMATION_FILE);
  
  const defaultStatus: WorkflowConfirmations = {
    confirmed: {
      requirements: false,
      design: false,
      tasks: false
    },
    skipped: {
      requirements: false,
      design: false,
      tasks: false
    }
  };
  
  if (!existsSync(filePath)) {
    return defaultStatus;
  }
  
  try {
    const content = readFileSync(filePath, 'utf-8');
    const parsed = JSON.parse(content);
    
    // Compatible with old format
    if (!parsed.confirmed && !parsed.skipped) {
      return {
        confirmed: parsed,
        skipped: {
          requirements: false,
          design: false,
          tasks: false
        }
      };
    }
    
    return parsed;
  } catch {
    return defaultStatus;
  }
}

// Keep old function for compatibility with existing code
export function getConfirmationStatus(path: string): ConfirmationStatus {
  const confirmations = getWorkflowConfirmations(path);
  return confirmations.confirmed;
}

export function updateStageConfirmation(
  path: string, 
  stage: keyof ConfirmationStatus, 
  confirmed: boolean
): void {
  const confirmations = getWorkflowConfirmations(path);
  confirmations.confirmed[stage] = confirmed;
  
  const filePath = join(path, CONFIRMATION_FILE);
  writeFileSync(filePath, JSON.stringify(confirmations, null, 2));
}

export function updateStageSkipped(
  path: string, 
  stage: keyof SkipStatus, 
  skipped: boolean
): void {
  const confirmations = getWorkflowConfirmations(path);
  confirmations.skipped[stage] = skipped;
  
  const filePath = join(path, CONFIRMATION_FILE);
  writeFileSync(filePath, JSON.stringify(confirmations, null, 2));
}

export function isStageConfirmed(
  path: string, 
  stage: keyof ConfirmationStatus
): boolean {
  const confirmations = getWorkflowConfirmations(path);
  return confirmations.confirmed[stage];
}

export function isStageSkipped(
  path: string, 
  stage: keyof SkipStatus
): boolean {
  const confirmations = getWorkflowConfirmations(path);
  return confirmations.skipped[stage];
}
```

--------------------------------------------------------------------------------
/src/features/shared/mcpTypes.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * MCP (Model Context Protocol) compatible type definitions
 * Standard interfaces conforming to MCP specification
 */

/**
 * MCP text content
 */
export interface McpTextContent {
  type: "text";
  text: string;
}

/**
 * MCP image content
 */
export interface McpImageContent {
  type: "image";
  data: string;      // base64 encoded
  mimeType: string;  // e.g. "image/png"
}

/**
 * MCP audio content
 */
export interface McpAudioContent {
  type: "audio";
  data: string;      // base64 encoded
  mimeType: string;  // e.g. "audio/mp3"
}

/**
 * MCP resource content
 */
export interface McpResourceContent {
  type: "resource";
  resource: {
    uri: string;       // Resource URI
    title?: string;    // Optional title
    mimeType: string;  // MIME type
    text?: string;     // Optional text content
  };
}

/**
 * MCP content type union
 */
export type McpContent = 
  | McpTextContent 
  | McpImageContent 
  | McpAudioContent 
  | McpResourceContent;

/**
 * MCP tool call result
 * This is the standard format that must be returned after tool execution
 */
export interface McpCallToolResult {
  content: McpContent[];
  isError?: boolean;
  structuredContent?: unknown; // Used when outputSchema is defined
}

/**
 * Internally used workflow result
 * Used to pass data between functional modules
 */
export interface WorkflowResult {
  displayText: string;
  data: {
    success?: boolean;
    error?: string;
    [key: string]: unknown;
  };
  resources?: Array<{
    uri: string;
    title?: string;
    mimeType: string;
    text?: string;
  }>;
}

/**
 * Create text content
 */
export function createTextContent(text: string): McpTextContent {
  return {
    type: "text",
    text
  };
}

/**
 * Create resource content
 */
export function createResourceContent(resource: McpResourceContent['resource']): McpResourceContent {
  return {
    type: "resource",
    resource
  };
}

/**
 * Convert internal workflow result to MCP format
 */
export function toMcpResult(result: WorkflowResult): McpCallToolResult {
  const content: McpContent[] = [
    createTextContent(result.displayText)
  ];
  
  // Resources are now embedded in displayText, no need to add them separately
  // This avoids duplicate display in clients that support resource content type
  
  return {
    content,
    isError: result.data.success === false,
    // Add structured content, return response object conforming to OpenAPI specification
    structuredContent: result.data && typeof result.data === 'object' && 'displayText' in result.data 
      ? result.data  // If data is already a complete response object
      : undefined    // Otherwise don't return structuredContent
  };
}
```

--------------------------------------------------------------------------------
/src/features/executeWorkflow.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Workflow execution entry point
 */

import { existsSync } from 'fs';
import { getWorkflowStatus, getCurrentStage } from './shared/documentStatus.js';
import { initWorkflow } from './init/initWorkflow.js';
import { checkWorkflow } from './check/checkWorkflow.js';
import { skipStage } from './skip/skipStage.js';
import { confirmStage } from './confirm/confirmStage.js';
import { completeTask } from './task/completeTask.js';
import { WorkflowResult } from './shared/mcpTypes.js';

export interface WorkflowArgs {
  path: string;
  action?: {
    type: string;
    featureName?: string;
    introduction?: string;
    taskNumber?: string | string[];
  };
}

export async function executeWorkflow(
  args: WorkflowArgs,
  onProgress?: (progress: number, total: number, message: string) => Promise<void>
): Promise<WorkflowResult> {
  const { path, action } = args;
  
  if (!action) {
    return getStatus(path);
  }
  
  switch (action.type) {
    case 'init':
      if (!action.featureName || !action.introduction) {
        return {
          displayText: '❌ Initialization requires featureName and introduction parameters',
          data: {
            success: false,
            error: 'Missing required parameters'
          }
        };
      }
      return initWorkflow({
        path,
        featureName: action.featureName,
        introduction: action.introduction,
        onProgress
      });
      
    case 'check':
      return checkWorkflow({ path, onProgress });
      
    case 'skip':
      return skipStage({ path });
      
    case 'confirm':
      return confirmStage({ path });
      
    case 'complete_task':
      if (!action.taskNumber) {
        return {
          displayText: '❌ Completing task requires taskNumber parameter',
          data: {
            success: false,
            error: 'Missing required parameters'
          }
        };
      }
      return completeTask({
        path,
        taskNumber: action.taskNumber
      });
      
    default:
      return {
        displayText: `❌ Unknown operation type: ${action.type}`,
        data: {
          success: false,
          error: `Unknown operation type: ${action.type}`
        }
      };
  }
}

function getStatus(path: string): WorkflowResult {
  if (!existsSync(path)) {
    return {
      displayText: `📁 Directory does not exist

Please use init operation to initialize:
\`\`\`json
{
  "action": {
    "type": "init",
    "featureName": "Feature name",
    "introduction": "Feature description"
  }
}
\`\`\``,
      data: {
        message: 'Directory does not exist, initialization required'
      }
    };
  }
  
  const status = getWorkflowStatus(path);
  const stage = getCurrentStage(status, path);
  
  return {
    displayText: `📊 Current status

Available operations:
- check: Check current stage
- skip: Skip current stage`,
    data: {
      message: 'Please select an operation',
      stage
    }
  };
}
```

--------------------------------------------------------------------------------
/src/features/shared/documentTemplates.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Document templates - using OpenAPI as single source of truth
 */

import { openApiLoader } from './openApiLoader.js';
import { isObject, isArray } from './typeGuards.js';

// Format template, replace variables
function formatTemplate(template: unknown, values: { [key: string]: unknown }): string {
  const lines: string[] = [];
  
  if (!isObject(template)) {
    throw new Error('Invalid template format');
  }
  
  const title = template.title;
  if (typeof title === 'string') {
    lines.push(`# ${interpolate(title, values)}`);
    lines.push('');
  }
  
  const sections = template.sections;
  if (isArray(sections)) {
    for (const section of sections) {
      if (isObject(section)) {
        if (typeof section.content === 'string') {
          lines.push(interpolate(section.content, values));
        } else if (typeof section.placeholder === 'string') {
          lines.push(section.placeholder);
        }
        lines.push('');
      }
    }
  }
  
  return lines.join('\n');
}

// Variable interpolation
function interpolate(template: string, values: { [key: string]: unknown }): string {
  return template.replace(/\${([^}]+)}/g, (match, key) => {
    const keys = key.split('.');
    let value: unknown = values;
    
    for (const k of keys) {
      if (isObject(value) && k in value) {
        value = value[k];
      } else {
        return match;
      }
    }
    
    return String(value);
  });
}

// Get requirements document template
export function getRequirementsTemplate(featureName: string, introduction: string): string {
  // Ensure spec is loaded
  openApiLoader.loadSpec();
  const template = openApiLoader.getDocumentTemplate('requirements');
  if (!template) {
    throw new Error('Requirements template not found in OpenAPI specification');
  }

  return formatTemplate(template, { featureName, introduction });
}

// Get design document template
export function getDesignTemplate(featureName: string): string {
  // Ensure spec is loaded
  openApiLoader.loadSpec();
  const template = openApiLoader.getDocumentTemplate('design');
  if (!template) {
    throw new Error('Design template not found in OpenAPI specification');
  }

  return formatTemplate(template, { featureName });
}

// Get tasks list template
export function getTasksTemplate(featureName: string): string {
  // Ensure spec is loaded
  openApiLoader.loadSpec();
  const template = openApiLoader.getDocumentTemplate('tasks');
  if (!template) {
    throw new Error('Tasks template not found in OpenAPI specification');
  }

  return formatTemplate(template, { featureName });
}

// Get skipped marker template
export function getSkippedTemplate(featureName: string, stageName: string): string {
  // Ensure spec is loaded
  openApiLoader.loadSpec();
  const template = openApiLoader.getDocumentTemplate('skipped');
  if (!template) {
    throw new Error('Skipped template not found in OpenAPI specification');
  }

  return formatTemplate(template, { featureName, stageName });
}
```

--------------------------------------------------------------------------------
/src/features/shared/openApiTypes.ts:
--------------------------------------------------------------------------------

```typescript
// Auto-generated type definitions - do not modify manually
// Generated from api/spec-workflow.openapi.yaml

export interface WorkflowRequest {
  path: string;  // Specification directory path (e.g., /Users/link/specs-mcp/batch-log-test)
  action: Action;
}

export interface Action {
  type: 'init' | 'check' | 'skip' | 'confirm' | 'complete_task';
  featureName?: string;  // Feature name (required for init)
  introduction?: string;  // Feature introduction (required for init)
  taskNumber?: string | string[];  // Task number(s) to mark as completed (required for complete_task)
}

export interface WorkflowResponse {
  result: InitResponse | CheckResponse | SkipResponse | ConfirmResponse | BatchCompleteTaskResponse;
}

export interface InitResponse {
  success: boolean;
  data: { path: string; featureName: string; nextAction: 'edit_requirements' };
  displayText: string;
  resources?: ResourceRef[];
}

export interface CheckResponse {
  stage: Stage;
  progress: Progress;
  status: Status;
  displayText: string;
  resources?: ResourceRef[];
}

export interface SkipResponse {
  stage: string;
  skipped: boolean;
  progress: Progress;
  displayText: string;
  resources?: ResourceRef[];
}

export interface ConfirmResponse {
  stage: string;
  confirmed: boolean;
  nextStage: string;
  progress: Progress;
  displayText: string;
  resources?: ResourceRef[];
}



export interface BatchCompleteTaskResponse {
  success: boolean;  // Whether the batch operation succeeded
  completedTasks?: string[];  // Task numbers that were actually completed in this operation
  alreadyCompleted?: string[];  // Task numbers that were already completed before this operation
  failedTasks?: { taskNumber: string; reason: string }[];  // Tasks that could not be completed with reasons
  results?: { taskNumber: string; success: boolean; status: 'completed' | 'already_completed' | 'failed' }[];  // Detailed results for each task in the batch
  nextTask?: { number: string; description: string };  // Information about the next uncompleted task
  hasNextTask?: boolean;  // Whether there are more tasks to complete
  displayText: string;  // Human-readable message about the batch operation
}

export interface Stage {
}

export interface Progress {
  overall: number;  // Overall progress percentage
  requirements: number;  // Requirements phase progress
  design: number;  // Design phase progress
  tasks: number;  // Tasks phase progress
}

export interface Status {
  type: 'not_started' | 'not_edited' | 'in_progress' | 'ready_to_confirm' | 'confirmed' | 'completed';
  reason?: string;
  readyToConfirm?: boolean;
}

export interface Resource {
  id: string;  // Resource identifier
  content: string;  // Resource content (Markdown format)
}

export interface ResourceRef {
  uri: string;  // Resource URI
  title?: string;  // Optional resource title
  mimeType: string;  // Resource MIME type
  text?: string;  // Optional resource text content
}

// Extended type definitions
export interface ErrorResponse {
  displayText: string;
  variables?: Record<string, any>;
}

export interface ContentCheckRules {
  minLength?: number;
  requiredSections?: string[];
  optionalSections?: string[];
  minTasks?: number;
  taskFormat?: string;
  requiresEstimate?: boolean;
}
```

--------------------------------------------------------------------------------
/scripts/sync-package.sh:
--------------------------------------------------------------------------------

```bash
#!/bin/bash

# Generate package directory with all necessary files for npm publishing
# This script creates a complete package directory from scratch

set -e

echo "📦 Generating package directory..."

# Create package directory structure
echo "📁 Creating directory structure..."
rm -rf package
mkdir -p package/api
mkdir -p package/dist

# Generate package.json
echo "📄 Generating package.json..."
MAIN_VERSION=$(node -p "require('./package.json').version")
cat > package/package.json << EOF
{
  "name": "spec-workflow-mcp",
  "version": "$MAIN_VERSION",
  "description": "MCP server for managing spec workflow (requirements, design, implementation)",
  "type": "module",
  "main": "dist/index.js",
  "bin": {
    "spec-workflow-mcp": "dist/index.js"
  },
  "files": [
    "dist/**/*",
    "api/**/*"
  ],
  "keywords": [
    "mcp",
    "workflow",
    "spec",
    "requirements",
    "design",
    "implementation",
    "openapi"
  ],
  "author": "kingkongshot",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kingkongshot/specs-workflow-mcp.git"
  },
  "bugs": {
    "url": "https://github.com/kingkongshot/specs-workflow-mcp/issues"
  },
  "homepage": "https://github.com/kingkongshot/specs-workflow-mcp#readme",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.6",
    "@types/js-yaml": "^4.0.9",
    "js-yaml": "^4.1.0",
    "zod": "^3.25.76"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}
EOF

# Generate README.md
echo "📖 Generating README.md..."
cat > package/README.md << 'EOF'
# Spec Workflow MCP

A Model Context Protocol (MCP) server for managing specification workflows including requirements, design, and implementation phases.

## Features

- **Requirements Management**: Create and validate requirement documents
- **Design Documentation**: Generate and review design specifications
- **Task Management**: Break down implementation into manageable tasks
- **Progress Tracking**: Monitor workflow progress across all phases
- **OpenAPI Integration**: Full OpenAPI 3.1.0 specification support

## Installation

```bash
npm install -g spec-workflow-mcp
```

## Usage

### As MCP Server

Add to your MCP client configuration:

```json
{
  "mcpServers": {
    "specs-workflow": {
      "command": "spec-workflow-mcp"
    }
  }
}
```

### Available Operations

- `init` - Initialize a new feature specification
- `check` - Check current workflow status
- `confirm` - Confirm stage completion
- `skip` - Skip current stage
- `complete_task` - Mark tasks as completed

## Documentation

For detailed usage instructions and examples, visit the [GitHub repository](https://github.com/kingkongshot/specs-workflow-mcp).

## License

MIT
EOF

# Copy OpenAPI specification
echo "📋 Copying OpenAPI specification..."
cp api/spec-workflow.openapi.yaml package/api/spec-workflow.openapi.yaml

# Copy built files
echo "🏗️ Copying built files..."
if [ -d "dist" ]; then
    cp -r dist/* package/dist/
else
    echo "❌ Error: dist directory not found. Run 'npm run build' first."
    exit 1
fi

echo "✅ Package directory generated successfully!"
echo "📦 Version: $MAIN_VERSION"
echo "📁 Location: ./package/"
echo ""
echo "Contents:"
echo "  📄 package.json"
echo "  📖 README.md"
echo "  📋 api/spec-workflow.openapi.yaml"
echo "  🏗️ dist/ (compiled JavaScript)"

```

--------------------------------------------------------------------------------
/src/tools/specWorkflowTool.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Intelligent specification workflow tool
 * Implementation fully compliant with MCP best practices
 */

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { executeWorkflow } from '../features/executeWorkflow.js';
import { toMcpResult } from '../features/shared/mcpTypes.js';

// Input parameter Schema
const inputSchema = {
  path: z.string().describe('Specification directory path (e.g., /Users/link/specs-mcp/batch-log-test)'),
  action: z.object({
    type: z.enum(['init', 'check', 'skip', 'confirm', 'complete_task']).describe('Operation type'),
    featureName: z.string().optional().describe('Feature name (required for init)'),
    introduction: z.string().optional().describe('Feature introduction (required for init)'),
    taskNumber: z.union([
      z.string(),
      z.array(z.string())
    ]).optional().describe('Task number(s) to mark as completed (required for complete_task). Can be a single string or an array of strings')
  }).optional().describe('Operation parameters')
};

export const specWorkflowTool = {
  /**
   * Register tool to MCP server
   */
  register(server: McpServer): void {
    server.registerTool(
      'specs-workflow',
      {
        title: 'Intelligent Specification Workflow Tool',  // Added title property
        description: 'Manage intelligent writing workflow for software project requirements, design, and task documents. Supports initialization, checking, skipping, confirmation, and task completion operations (single or batch).',
        inputSchema,
        annotations: {
          progressReportingHint: true,
          longRunningHint: true,
          readOnlyHint: false,      // This tool modifies files
          idempotentHint: false     // Operation is not idempotent
        }
      },
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      async (args, _extra) => {
        try {
          // Temporarily not using progress callback, as MCP SDK type definitions may differ
          const onProgress = undefined;
          
          // Execute workflow
          const workflowResult = await executeWorkflow({
            path: args.path,
            action: args.action
          }, onProgress);
          
          // Use standard MCP format converter
          const mcpResult = toMcpResult(workflowResult);
          
          // Return format that meets SDK requirements, including structuredContent
          const callToolResult: Record<string, unknown> = {
            content: mcpResult.content,
            isError: mcpResult.isError
          };
          
          if (mcpResult.structuredContent !== undefined) {
            callToolResult.structuredContent = mcpResult.structuredContent;
          }
          
          // Type assertion to satisfy MCP SDK requirements
          return callToolResult as {
            content: Array<{
              type: 'text';
              text: string;
              [x: string]: unknown;
            }>;
            isError?: boolean;
            [x: string]: unknown;
          };
          
        } catch (error) {
          // Error handling must also comply with MCP format
          return {
            content: [{
              type: 'text' as const,
              text: `Execution failed: ${error instanceof Error ? error.message : String(error)}`
            }],
            isError: true
          };
        }
      }
    );
  }
};
```

--------------------------------------------------------------------------------
/src/features/check/checkWorkflow.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Check workflow status
 */

import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import { getWorkflowStatus, getCurrentStage } from '../shared/documentStatus.js';
import { calculateWorkflowProgress } from '../shared/progressCalculator.js';
import { analyzeStage } from './analyzeStage.js';
import { generateNextDocument } from './generateNextDocument.js';
import { responseBuilder } from '../shared/responseBuilder.js';
import { WorkflowResult } from '../shared/mcpTypes.js';
import { parseTasksFile, getFirstUncompletedTask, formatTaskForFullDisplay } from '../shared/taskParser.js';

export interface CheckOptions {
  path: string;
  onProgress?: (progress: number, total: number, message: string) => Promise<void>;
}

export async function checkWorkflow(options: CheckOptions): Promise<WorkflowResult> {
  const { path, onProgress } = options;
  
  if (!existsSync(path)) {
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { path }),
      data: {
        success: false,
        error: 'Directory does not exist'
      }
    };
  }
  
  await reportProgress(onProgress, 33, 100, 'Checking document status...');
  
  const status = getWorkflowStatus(path);
  
  // Check if all files do not exist
  if (!status.requirements.exists && !status.design.exists && !status.tasks.exists) {
    await reportProgress(onProgress, 100, 100, 'Check completed');
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { 
        path,
        error: 'Project not initialized' 
      }),
      data: {
        success: false,
        error: 'Project not initialized'
      }
    };
  }
  
  const currentStage = getCurrentStage(status, path);
  // const stageStatus = getStageStatus(currentStage, status, path); // 未使用
  
  await reportProgress(onProgress, 66, 100, 'Analyzing document content...');
  
  // Analyze current stage
  const analysis = analyzeStage(path, currentStage, status);
  
  // Check if need to generate next document
  if (analysis.canProceed) {
    await generateNextDocument(path, currentStage);
  }
  
  await reportProgress(onProgress, 100, 100, 'Check completed');
  
  const progress = calculateWorkflowProgress(path, status);
  
  // Determine status type
  let statusType: string;
  let reason: string | undefined;
  
  if (currentStage === 'completed') {
    statusType = 'completed';
  } else if (!status[currentStage].exists) {
    statusType = 'not_edited';
    reason = `${currentStage === 'requirements' ? 'Requirements' : currentStage === 'design' ? 'Design' : 'Tasks'} document does not exist`;
  } else if (analysis.canProceed) {
    statusType = 'ready_to_confirm';
  } else if (analysis.needsConfirmation) {
    statusType = 'ready_to_confirm';
  } else {
    statusType = 'not_edited';
    reason = analysis.reason;
  }
  
  // If workflow is completed, get the first uncompleted task
  let firstTask = null;
  if (currentStage === 'completed') {
    const tasks = parseTasksFile(path);
    const task = getFirstUncompletedTask(tasks);
    if (task) {
      const tasksPath = join(path, 'tasks.md');
      const content = readFileSync(tasksPath, 'utf-8');
      firstTask = formatTaskForFullDisplay(task, content);
    }
  }
  
  return responseBuilder.buildCheckResponse(
    currentStage,
    progress,
    { 
      type: statusType, 
      reason,
      readyToConfirm: analysis.canProceed 
    },
    analysis,
    path,
    firstTask
  );
}

async function reportProgress(
  onProgress: ((progress: number, total: number, message: string) => Promise<void>) | undefined,
  progress: number,
  total: number,
  message: string
): Promise<void> {
  if (onProgress) {
    await onProgress(progress, total, message);
  }
}
```

--------------------------------------------------------------------------------
/src/features/confirm/confirmStage.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Confirm stage completion
 */

import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import { getWorkflowStatus, getStageName, getNextStage, getCurrentStage, getStageFileName } from '../shared/documentStatus.js';
import { updateStageConfirmation, isStageSkipped } from '../shared/confirmationStatus.js';
import { generateNextDocument } from '../check/generateNextDocument.js';
import { responseBuilder } from '../shared/responseBuilder.js';
import { WorkflowResult } from '../shared/mcpTypes.js';
import { parseTasksFile, getFirstUncompletedTask, formatTaskForFullDisplay } from '../shared/taskParser.js';
import { isDocumentEdited } from '../shared/documentAnalyzer.js';
import { calculateWorkflowProgress } from '../shared/progressCalculator.js';

export interface ConfirmOptions {
  path: string;
}

export async function confirmStage(options: ConfirmOptions): Promise<WorkflowResult> {
  const { path } = options;
  
  if (!existsSync(path)) {
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { path }),
      data: {
        success: false,
        error: 'Directory does not exist'
      }
    };
  }
  
  const status = getWorkflowStatus(path);
  const currentStage = getCurrentStage(status, path);
  
  // Check if all stages are completed
  if (currentStage === 'completed') {
    return {
      displayText: `✅ All stages completed!

Workflow completed, no need to confirm again.`,
      data: {
        success: false,
        reason: 'All stages completed'
      }
    };
  }
  
  const stageData = status[currentStage as keyof typeof status];
  
  // Check if document exists
  if (!stageData || !stageData.exists) {
    return {
      displayText: `⚠️ ${getStageName(currentStage)} does not exist

Please create ${getStageName(currentStage)} document before confirming.`,
      data: {
        success: false,
        reason: `${getStageName(currentStage)} does not exist`
      }
    };
  }
  
  // Check if already skipped
  if (isStageSkipped(path, currentStage)) {
    return {
      displayText: `⚠️ ${getStageName(currentStage)} already skipped

This stage has been skipped, no need to confirm.`,
      data: {
        success: false,
        reason: `${getStageName(currentStage)} already skipped`
      }
    };
  }
  
  // Check if document has been edited
  const fileName = getStageFileName(currentStage);
  const filePath = join(path, fileName);
  if (!isDocumentEdited(filePath)) {
    return {
      displayText: responseBuilder.buildErrorResponse('documentNotEdited', { 
        documentName: getStageName(currentStage)
      }),
      data: {
        success: false,
        error: 'Document not edited'
      }
    };
  }
  
  // Update confirmation status
  updateStageConfirmation(path, currentStage, true);
  
  // Get next stage
  const nextStage = getNextStage(currentStage);
  
  // Generate document for next stage
  if (nextStage !== 'completed') {
    await generateNextDocument(path, currentStage);
  }
  
  // If tasks stage, get first task details
  let firstTaskContent = null;
  if (currentStage === 'tasks' && nextStage === 'completed') {
    const tasks = parseTasksFile(path);
    const firstTask = getFirstUncompletedTask(tasks);
    if (firstTask) {
      const tasksPath = join(path, 'tasks.md');
      const content = readFileSync(tasksPath, 'utf-8');
      firstTaskContent = formatTaskForFullDisplay(firstTask, content);
    }
  }
  
  // Calculate progress after confirmation
  const updatedStatus = getWorkflowStatus(path);
  const progress = calculateWorkflowProgress(path, updatedStatus);
  
  return responseBuilder.buildConfirmResponse(currentStage, nextStage === 'completed' ? null : nextStage, path, firstTaskContent, progress);
}
```

--------------------------------------------------------------------------------
/scripts/generateTypes.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env tsx
/**
 * Generate TypeScript type definitions from OpenAPI specification
 */

import * as fs from 'fs';
import * as path from 'path';
import * as yaml from 'js-yaml';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Read OpenAPI specification
const specPath = path.join(__dirname, '../api/spec-workflow.openapi.yaml');
const spec = yaml.load(fs.readFileSync(specPath, 'utf8')) as any;

// Generate TypeScript types
function generateTypes(): string {
  const types: string[] = [];
  
  types.push('// Auto-generated type definitions - do not modify manually');
  types.push('// Generated from api/spec-workflow.openapi.yaml');
  types.push('');
  
  // Generate types for schemas
  for (const [schemaName, schema] of Object.entries(spec.components.schemas)) {
    types.push(generateSchemaType(schemaName, schema));
    types.push('');
  }
  
  // Generate extended types
  types.push('// Extended type definitions');
  types.push('export interface ErrorResponse {');
  types.push('  displayText: string;');
  types.push('  variables?: Record<string, any>;');
  types.push('}');
  types.push('');
  
  types.push('export interface ContentCheckRules {');
  types.push('  minLength?: number;');
  types.push('  requiredSections?: string[];');
  types.push('  optionalSections?: string[];');
  types.push('  minTasks?: number;');
  types.push('  taskFormat?: string;');
  types.push('  requiresEstimate?: boolean;');
  types.push('}');
  
  return types.join('\n');
}

function generateSchemaType(name: string, schema: any): string {
  const lines: string[] = [];
  
  lines.push(`export interface ${name} {`);
  
  if (schema.properties) {
    for (const [propName, prop] of Object.entries(schema.properties) as [string, any][]) {
      const required = schema.required?.includes(propName) || false;
      const optional = required ? '' : '?';
      const type = getTypeScriptType(prop);
      const comment = prop.description ? `  // ${prop.description}` : '';
      
      lines.push(`  ${propName}${optional}: ${type};${comment}`);
    }
  }
  
  // Handle oneOf
  if (schema.oneOf) {
    lines.push('  // oneOf:');
    schema.oneOf.forEach((item: any) => {
      if (item.$ref) {
        const refType = item.$ref.split('/').pop();
        lines.push(`  // - ${refType}`);
      }
    });
  }
  
  lines.push('}');
  
  return lines.join('\n');
}

function getTypeScriptType(prop: any): string {
  if (prop.$ref) {
    return prop.$ref.split('/').pop();
  }
  
  if (prop.oneOf) {
    const types = prop.oneOf.map((item: any) => {
      if (item.$ref) {
        return item.$ref.split('/').pop();
      }
      return getTypeScriptType(item);
    });
    return types.join(' | ');
  }
  
  if (prop.enum) {
    return prop.enum.map((v: any) => `'${v}'`).join(' | ');
  }
  
  switch (prop.type) {
    case 'string':
      if (prop.const) {
        return `'${prop.const}'`;
      }
      return 'string';
    case 'number':
    case 'integer':
      return 'number';
    case 'boolean':
      return 'boolean';
    case 'array':
      if (prop.items) {
        return `${getTypeScriptType(prop.items)}[]`;
      }
      return 'any[]';
    case 'object':
      if (prop.properties) {
        const props = Object.entries(prop.properties)
          .map(([k, v]: [string, any]) => `${k}: ${getTypeScriptType(v)}`)
          .join('; ');
        return `{ ${props} }`;
      }
      return 'Record<string, any>';
    default:
      return 'any';
  }
}

// Generate type file
const types = generateTypes();
const outputPath = path.join(__dirname, '../src/features/shared/openApiTypes.ts');
fs.writeFileSync(outputPath, types, 'utf8');

console.log('✅ TypeScript types generated to:', outputPath);
```

--------------------------------------------------------------------------------
/src/features/skip/skipStage.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Skip current stage
 */

import { existsSync, writeFileSync } from 'fs';
import { join } from 'path';
import { getWorkflowStatus, getCurrentStage, getNextStage, getStageName, getStageFileName } from '../shared/documentStatus.js';
import { getSkippedTemplate, getDesignTemplate, getTasksTemplate } from '../shared/documentTemplates.js';
import { updateStageConfirmation, updateStageSkipped } from '../shared/confirmationStatus.js';
import { responseBuilder } from '../shared/responseBuilder.js';
import { WorkflowResult } from '../shared/mcpTypes.js';
import { extractDocumentInfo } from '../shared/documentUtils.js';
import { calculateWorkflowProgress } from '../shared/progressCalculator.js';

export interface SkipOptions {
  path: string;
}

export async function skipStage(options: SkipOptions): Promise<WorkflowResult> {
  const { path } = options;
  
  if (!existsSync(path)) {
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { path }),
      data: {
        success: false,
        error: 'Directory does not exist'
      }
    };
  }
  
  const status = getWorkflowStatus(path);
  const currentStage = getCurrentStage(status, path);
  
  if (currentStage === 'completed') {
    return {
      displayText: '✅ All stages completed, no need to skip',
      data: {
        success: false,
        reason: 'All stages completed'
      }
    };
  }
  
  // Get document information
  const documentInfo = extractDocumentInfo(join(path, 'requirements.md'));
  
  // Create document for skipped stage
  createSkippedDocument(path, currentStage, documentInfo.featureName);
  
  // Mark current stage as skipped
  updateStageSkipped(path, currentStage, true);
  // For tasks stage, don't mark as confirmed when skipping
  // since it's essential for development
  if (currentStage !== 'tasks') {
    updateStageConfirmation(path, currentStage, true);
  }
  
  // Generate next document (if needed)
  const nextStage = getNextStage(currentStage);
  
  if (nextStage !== 'completed') {
    createNextStageDocument(path, nextStage, documentInfo.featureName);
    // Initialize next stage confirmation status as unconfirmed
    updateStageConfirmation(path, nextStage, false);
  }
  
  // Calculate progress after skip
  const updatedStatus = getWorkflowStatus(path);
  const progress = calculateWorkflowProgress(path, updatedStatus);
  
  return responseBuilder.buildSkipResponse(currentStage, path, progress);
}


interface DocumentResult {
  created: boolean;
  fileName: string;
  message: string;
}

function createSkippedDocument(
  path: string,
  stage: string,
  featureName: string
): DocumentResult {
  const fileName = getStageFileName(stage);
  const filePath = join(path, fileName);
  
  // If document already exists, don't overwrite
  if (existsSync(filePath)) {
    return {
      created: false,
      fileName,
      message: `${fileName} already exists, keeping original content`
    };
  }
  
  const content = getSkippedTemplate(getStageName(stage), featureName);
  
  try {
    writeFileSync(filePath, content, 'utf-8');
    return {
      created: true,
      fileName,
      message: `Created skip marker document: ${fileName}`
    };
  } catch (error) {
    return {
      created: false,
      fileName,
      message: `Failed to create skip document: ${error}`
    };
  }
}

function createNextStageDocument(
  path: string,
  stage: string,
  featureName: string
): DocumentResult | null {
  const fileName = getStageFileName(stage);
  const filePath = join(path, fileName);
  
  if (existsSync(filePath)) {
    return {
      created: false,
      fileName,
      message: `${fileName} already exists`
    };
  }
  
  let content: string;
  switch (stage) {
    case 'design':
      content = getDesignTemplate(featureName);
      break;
    case 'tasks':
      content = getTasksTemplate(featureName);
      break;
    default:
      return null;
  }
  
  try {
    writeFileSync(filePath, content, 'utf-8');
    return {
      created: true,
      fileName,
      message: `Created next stage document: ${fileName}`
    };
  } catch (error) {
    return {
      created: false,
      fileName,
      message: `Failed to create document: ${error}`
    };
  }
}
```

--------------------------------------------------------------------------------
/scripts/validateOpenApi.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env tsx
/**
 * Validate if MCP responses conform to OpenAPI specification
 */

import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import * as fs from 'fs/promises';
import * as yaml from 'js-yaml';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Load OpenAPI specification
async function loadOpenApiSpec() {
  const specPath = join(__dirname, '../api/spec-workflow.openapi.yaml');
  const specContent = await fs.readFile(specPath, 'utf-8');
  return yaml.load(specContent) as any;
}

// Manually validate response
function validateResponse(response: any, schemaName: string, spec: any): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  const schema = spec.components.schemas[schemaName];
  
  if (!schema) {
    return { valid: false, errors: [`Schema ${schemaName} not found`] };
  }
  
  // Check required fields
  if (schema.required) {
    for (const field of schema.required) {
      if (!(field in response)) {
        errors.push(`Missing required field: ${field}`);
      }
    }
  }
  
  // Check field types
  if (schema.properties) {
    for (const [field, fieldSchema] of Object.entries(schema.properties)) {
      if (field in response) {
        const value = response[field];
        const expectedType = (fieldSchema as any).type;
        
        if (expectedType) {
          const actualType = Array.isArray(value) ? 'array' : typeof value;
          
          if (expectedType === 'integer' && typeof value === 'number') {
            // integer and number are compatible
          } else if (expectedType !== actualType) {
            errors.push(`Field ${field}: expected ${expectedType}, got ${actualType}`);
          }
        }
        
        // Recursively check nested objects
        if ((fieldSchema as any).$ref) {
          const refSchemaName = (fieldSchema as any).$ref.split('/').pop();
          const nestedResult = validateResponse(value, refSchemaName, spec);
          errors.push(...nestedResult.errors.map(e => `${field}.${e}`));
        }
      }
    }
  }
  
  return { valid: errors.length === 0, errors };
}

// Test example responses
async function testResponses() {
  const spec = await loadOpenApiSpec();
  
  // Test response examples
  const testCases = [
    {
      name: 'InitResponse',
      response: {
        success: true,
        data: {
          path: '/test/path',
          featureName: 'Test Feature',
          nextAction: 'edit_requirements'
        },
        displayText: 'Initialization successful',
        resources: []
      }
    },
    {
      name: 'CheckResponse',
      response: {
        stage: 'requirements',
        progress: {
          overall: 30,
          requirements: 100,
          design: 0,
          tasks: 0
        },
        status: {
          type: 'ready_to_confirm',
          readyToConfirm: true
        },
        displayText: 'Check passed'
      }
    },
    {
      name: 'SkipResponse',
      response: {
        stage: 'requirements',
        skipped: true,
        displayText: 'Skipped'
      }
    }
  ];
  
  console.log('🧪 Validating OpenAPI response format\n');
  
  for (const testCase of testCases) {
    console.log(`📝 Testing ${testCase.name}:`);
    const result = validateResponse(testCase.response, testCase.name, spec);
    
    if (result.valid) {
      console.log('   ✅ Validation passed');
    } else {
      console.log('   ❌ Validation failed:');
      result.errors.forEach(error => {
        console.log(`      - ${error}`);
      });
    }
    console.log();
  }
  
  // Check Progress definition
  console.log('📊 Progress Schema definition:');
  const progressSchema = spec.components.schemas.Progress;
  console.log('Required fields:', progressSchema.required);
  console.log('Properties:', Object.keys(progressSchema.properties));
  console.log();
  
  // Test Progress
  const progressTest = {
    overall: 30,
    requirements: 100,
    design: 0,
    tasks: 0
  };
  
  const progressResult = validateResponse(progressTest, 'Progress', spec);
  console.log('Progress validation:', progressResult.valid ? '✅ Passed' : '❌ Failed');
  if (!progressResult.valid) {
    progressResult.errors.forEach(error => {
      console.log(`   - ${error}`);
    });
  }
}

if (import.meta.url === `file://${process.argv[1]}`) {
  testResponses().catch(console.error);
}
```

--------------------------------------------------------------------------------
/src/features/init/initWorkflow.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Initialize workflow functionality
 */

import { existsSync, mkdirSync } from 'fs';
import { join } from 'path';
import { getWorkflowStatus, getCurrentStage } from '../shared/documentStatus.js';
import { calculateWorkflowProgress } from '../shared/progressCalculator.js';
import { createRequirementsDocument } from './createRequirementsDoc.js';
import { updateStageConfirmation } from '../shared/confirmationStatus.js';
import { responseBuilder } from '../shared/responseBuilder.js';
import { WorkflowResult } from '../shared/mcpTypes.js';

export interface InitOptions {
  path: string;
  featureName: string;
  introduction: string;
  onProgress?: (progress: number, total: number, message: string) => Promise<void>;
}

export async function initWorkflow(options: InitOptions): Promise<WorkflowResult> {
  const { path, featureName, introduction, onProgress } = options;
  
  try {
    await reportProgress(onProgress, 0, 100, 'Starting initialization...');
    
    // Create directory
    if (!existsSync(path)) {
      mkdirSync(path, { recursive: true });
    }
    
    await reportProgress(onProgress, 50, 100, 'Checking project status...');
    
    // Comprehensively check if project already exists
    const requirementsPath = join(path, 'requirements.md');
    const designPath = join(path, 'design.md');
    const tasksPath = join(path, 'tasks.md');
    const confirmationsPath = join(path, '.workflow-confirmations.json');
    
    // If any workflow-related files exist, consider the project already exists
    const projectExists = existsSync(requirementsPath) || 
                         existsSync(designPath) || 
                         existsSync(tasksPath) || 
                         existsSync(confirmationsPath);
    
    if (projectExists) {
      await reportProgress(onProgress, 100, 100, 'Found existing project');
      
      const status = getWorkflowStatus(path);
      const currentStage = getCurrentStage(status, path);
      const progress = calculateWorkflowProgress(path, status);
      
      const enhancedStatus = {
        ...status,
        design: { ...status.design, exists: existsSync(designPath) },
        tasks: { ...status.tasks, exists: existsSync(tasksPath) }
      };
      
      // Build detailed existing reason
      const existingFiles = [];
      if (existsSync(requirementsPath)) existingFiles.push('Requirements document');
      if (existsSync(designPath)) existingFiles.push('Design document');
      if (existsSync(tasksPath)) existingFiles.push('Task list');
      if (existsSync(confirmationsPath)) existingFiles.push('Workflow status');
      
      // Use responseBuilder to build error response
      return {
        displayText: responseBuilder.buildErrorResponse('alreadyInitialized', { 
          path,
          existingFiles: existingFiles.join(', ')
        }),
        data: {
          success: false,
          error: 'PROJECT_ALREADY_EXISTS',
          existingFiles: existingFiles,
          currentStage: currentStage,
          progress: progress
        }
      };
    }
    
    // Generate requirements document
    const result = createRequirementsDocument(path, featureName, introduction);
    
    if (!result.generated) {
      return {
        displayText: responseBuilder.buildErrorResponse('invalidPath', { path }),
        data: {
          success: false,
          error: 'Failed to create requirements document',
          details: result
        }
      };
    }
    
    // Initialize status file, mark requirements stage as unconfirmed
    updateStageConfirmation(path, 'requirements', false);
    updateStageConfirmation(path, 'design', false);
    updateStageConfirmation(path, 'tasks', false);
    
    await reportProgress(onProgress, 100, 100, 'Initialization completed!');
    
    // Use responseBuilder to build success response
    return responseBuilder.buildInitResponse(path, featureName);
    
  } catch (error) {
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { 
        path,
        error: String(error) 
      }),
      data: {
        success: false,
        error: `Initialization failed: ${error}`
      }
    };
  }
}

async function reportProgress(
  onProgress: ((progress: number, total: number, message: string) => Promise<void>) | undefined,
  progress: number,
  total: number,
  message: string
): Promise<void> {
  if (onProgress) {
    await onProgress(progress, total, message);
  }
}
```

--------------------------------------------------------------------------------
/src/features/check/analyzeStage.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Analyze workflow stage
 */

import { join } from 'path';
import { WorkflowStatus, WorkflowStage, getStageFileName, getStageName } from '../shared/documentStatus.js';
import { isStageConfirmed, isStageSkipped, ConfirmationStatus, SkipStatus } from '../shared/confirmationStatus.js';
import { openApiLoader } from '../shared/openApiLoader.js';
import { isDocumentEdited } from '../shared/documentAnalyzer.js';
import { isObject, hasProperty } from '../shared/typeGuards.js';

export interface StageAnalysis {
  canProceed: boolean;
  needsConfirmation: boolean;
  reason?: string;
  suggestions: string[];
  guide?: unknown; // Writing guide provided when document is not edited
}

export interface StageStatus {
  exists: boolean;
  confirmed: boolean;
  skipped: boolean;
  displayStatus: string;
}

export function analyzeStage(
  path: string,
  stage: WorkflowStage,
  status: WorkflowStatus
): StageAnalysis {
  if (stage === 'completed') {
    return {
      canProceed: false,
      needsConfirmation: false,
      reason: 'All stages completed',
      suggestions: []
    };
  }
  
  const stageData = status[stage as keyof WorkflowStatus];
  // Type guard to handle 'completed' stage
  const isCompletedStage = (s: WorkflowStage): s is 'completed' => s === 'completed';
  const confirmed = isCompletedStage(stage) ? false : isStageConfirmed(path, stage as keyof ConfirmationStatus);
  const skipped = isCompletedStage(stage) ? false : isStageSkipped(path, stage as keyof SkipStatus);
  
  // If stage is skipped or confirmed, can proceed
  if (confirmed || skipped) {
    return {
      canProceed: true,
      needsConfirmation: false,
      suggestions: [`${getStageName(stage)} completed, can proceed to next stage`]
    };
  }
  
  // Check if document exists
  if (!stageData || !stageData.exists) {
    return {
      canProceed: false,
      needsConfirmation: false,
      reason: `${getStageName(stage)} does not exist`,
      suggestions: [`Create ${getStageName(stage)}`],
      guide: getStageGuide(stage)
    };
  }
  
  // Check if document has been edited
  const fileName = getStageFileName(stage);
  const filePath = join(path, fileName);
  const edited = isDocumentEdited(filePath);
  
  if (!edited) {
    // Document exists but not edited
    return {
      canProceed: false,
      needsConfirmation: false,
      reason: `${getStageName(stage)} not edited yet (still contains template markers)`,
      suggestions: [
        `Please edit ${fileName} and remove all <template-*> markers`,
        'Fill in actual content before using check operation'
      ],
      guide: getStageGuide(stage)
    };
  }
  
  // Document edited but not confirmed
  return {
    canProceed: false,
    needsConfirmation: true,
    reason: `${getStageName(stage)} edited but not confirmed yet`,
    suggestions: ['Please use confirm operation to confirm this stage is complete'],
    guide: getStageGuide(stage)
  };
}

export function getStageStatus(
  stage: string,
  status: WorkflowStatus,
  path: string
): StageStatus {
  const stageData = status[stage as keyof WorkflowStatus];
  const exists = stageData?.exists || false;
  const confirmed = exists && stage !== 'completed' ? isStageConfirmed(path, stage as keyof ConfirmationStatus) : false;
  const skipped = exists && stage !== 'completed' ? isStageSkipped(path, stage as keyof SkipStatus) : false;
  
  const globalConfig = openApiLoader.getGlobalConfig();
  const statusTextConfig = isObject(globalConfig) && hasProperty(globalConfig, 'status_text') && isObject(globalConfig.status_text) ? globalConfig.status_text : {};
  const statusText = {
    not_created: typeof statusTextConfig.not_created === 'string' ? statusTextConfig.not_created : 'Not created',
    not_confirmed: typeof statusTextConfig.not_confirmed === 'string' ? statusTextConfig.not_confirmed : 'Pending confirmation',
    completed: typeof statusTextConfig.completed === 'string' ? statusTextConfig.completed : 'Completed',
    skipped: typeof statusTextConfig.skipped === 'string' ? statusTextConfig.skipped : 'Skipped'
  };
  
  let displayStatus = statusText.not_created;
  if (exists) {
    if (skipped) {
      displayStatus = statusText.skipped;
    } else if (confirmed) {
      displayStatus = statusText.completed;
    } else {
      displayStatus = statusText.not_confirmed;
    }
  }
  
  return {
    exists,
    confirmed,
    skipped,
    displayStatus
  };
}


function getStageGuide(stage: WorkflowStage): unknown {
  const guideMap: Record<WorkflowStage, string> = {
    requirements: 'requirements-guide',
    design: 'design-guide',
    tasks: 'tasks-guide',
    completed: ''
  };
  
  const guideId = guideMap[stage];
  if (!guideId) return null;
  
  // Get resource from OpenAPI - already in MCP format
  const resource = openApiLoader.getSharedResource(guideId);
  return resource || null;
}
```

--------------------------------------------------------------------------------
/src/features/shared/taskGuidanceTemplate.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Task guidance template extractor
 * Reads task completion guidance text templates from OpenAPI specification
 */

import { openApiLoader, OpenApiLoader } from './openApiLoader.js';

export class TaskGuidanceExtractor {
  private static _template: ReturnType<typeof openApiLoader.getTaskGuidanceTemplate> | undefined;
  
  private static get template() {
    if (!this._template) {
      // Lazy loading to ensure OpenAPI spec is loaded
      openApiLoader.loadSpec();
      this._template = openApiLoader.getTaskGuidanceTemplate();
    }
    return this._template;
  }
  
  /**
   * Build task guidance text
   * Read templates from OpenAPI spec and assemble them
   */
  static buildGuidanceText(
    nextTaskContent: string,
    firstSubtask: string,
    taskNumber?: string,
    isFirstTask: boolean = false
  ): string {
    const template = this.template;
    if (!template) {
      throw new Error('Failed to load task guidance template from OpenAPI specification');
    }
    
    const parts: string[] = [];
    
    // Add separator line
    parts.push(template.separator);
    parts.push('');
    
    // Add task header
    parts.push(template.header);
    parts.push(nextTaskContent);
    parts.push('');
    
    // Add model instructions
    parts.push(template.instructions.prefix);
    const taskFocusText = OpenApiLoader.replaceVariables(template.instructions.taskFocus, { firstSubtask });
    parts.push(taskFocusText);
    
    parts.push('');
    parts.push(template.instructions.progressTracking);
    parts.push(template.instructions.workflow);
    parts.push('');
    
    // Add model prompt based on scenario
    let prompt: string;
    if (isFirstTask) {
      // Replace firstSubtask placeholder in firstTask prompt
      prompt = OpenApiLoader.replaceVariables(template.prompts.firstTask, { firstSubtask });
    } else if (taskNumber) {
      // Determine if it's a new task or continuation
      if (taskNumber.includes('.')) {
        // Subtask, use continuation prompt
        prompt = OpenApiLoader.replaceVariables(template.prompts.continueTask, { taskNumber, firstSubtask });
      } else {
        // Main task, use new task prompt
        prompt = OpenApiLoader.replaceVariables(template.prompts.nextTask, { taskNumber, firstSubtask });
      }
    } else {
      // Batch completion scenario, no specific task number
      prompt = OpenApiLoader.replaceVariables(template.prompts.batchContinue, { firstSubtask });
    }
    
    parts.push(prompt);
    
    return parts.join('\n');
  }
  
  /**
   * Extract the first uncompleted task with its context
   */
  static extractFirstSubtask(taskContent: string): string {
    const taskLines = taskContent.split('\n');
    let firstSubtaskFound = false;
    let firstSubtaskLines: string[] = [];
    let currentIndent = '';

    for (let i = 0; i < taskLines.length; i++) {
      const line = taskLines[i];

      // 忽略空行(但在收集过程中保留)
      if (!line.trim()) {
        if (firstSubtaskFound) {
          firstSubtaskLines.push(line);
        }
        continue;
      }

      // 寻找第一个包含 [ ] 的行(未完成任务)
      if (line.includes('[ ]') && !firstSubtaskFound) {
        // 提取任务号验证这是一个子任务(包含点号)
        const taskMatch = line.match(/(\d+(?:\.\d+)+)\./);
        if (taskMatch) {
          firstSubtaskFound = true;
          firstSubtaskLines.push(line);
          currentIndent = line.match(/^(\s*)/)?.[1] || '';
          continue;
        }
      }

      // 如果已经找到第一个子任务,继续收集其详细内容
      if (firstSubtaskFound) {
        const lineIndent = line.match(/^(\s*)/)?.[1] || '';

        // 如果遇到同级或更高级的任务,停止收集
        if (line.includes('[ ]') && lineIndent.length <= currentIndent.length) {
          break;
        }

        // 如果是更深层次的缩进内容,继续收集
        if (lineIndent.length > currentIndent.length || line.trim().startsWith('-') || line.trim().startsWith('*')) {
          firstSubtaskLines.push(line);
        } else {
          // 遇到非缩进内容,停止收集
          break;
        }
      }
    }

    // 如果找到了第一个子任务,返回其完整内容
    if (firstSubtaskLines.length > 0) {
      return firstSubtaskLines.join('\n').trim();
    }

    // 如果没有找到子任务,尝试找第一个未完成的任务
    for (const line of taskLines) {
      if (!line.trim()) continue;

      if (line.includes('[ ]')) {
        const taskMatch = line.match(/(\d+(?:\.\d+)*)\.\s*(.+)/);
        if (taskMatch) {
          const taskNumber = taskMatch[1];
          const taskDesc = taskMatch[2].replace(/\*\*|\*/g, '').trim();
          return `${taskNumber}. ${taskDesc}`;
        }
        return line.replace(/[-[\]\s]/g, '').replace(/\*\*|\*/g, '').trim();
      }
    }

    return 'Next task';
  }
  
  /**
   * Get completion message
   */
  static getCompletionMessage(type: 'taskCompleted' | 'allCompleted' | 'alreadyCompleted' | 'batchSucceeded' | 'batchCompleted', taskNumber?: string): string {
    const template = this.template;
    if (!template) {
      throw new Error('Failed to load task guidance template from OpenAPI specification');
    }
    
    const message = template.completionMessages[type];
    if (taskNumber && message.includes('${taskNumber}')) {
      return OpenApiLoader.replaceVariables(message, { taskNumber });
    }
    return message;
  }
}
```

--------------------------------------------------------------------------------
/src/features/shared/openApiLoader.ts:
--------------------------------------------------------------------------------

```typescript
import * as yaml from 'js-yaml';
import * as fs from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import { isObject } from './typeGuards.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// OpenAPI specification type definitions
export interface OpenApiSpec {
  paths: {
    '/spec': {
      post: {
        responses: {
          '200': {
            content: {
              'application/json': {
                schema: {
                  $ref: string;
                };
              };
            };
          };
        };
      };
    };
  };
  components: {
    schemas: Record<string, unknown>;
  };
  'x-error-responses': Record<string, {
    displayText: string;
  }>;
  'x-shared-resources': Record<string, {
    uri: string;
    title?: string;
    mimeType: string;
    text?: string;
  }>;
  'x-global-config': unknown;
  'x-document-templates': Record<string, unknown>;
  'x-task-guidance-template'?: {
    separator: string;
    header: string;
    instructions: {
      prefix: string;
      taskFocus: string;
      progressTracking: string;
      workflow: string;
    };
    prompts: {
      firstTask: string;
      nextTask: string;
      continueTask: string;
      batchContinue: string;
    };
    completionMessages: {
      taskCompleted: string;
      allCompleted: string;
      alreadyCompleted: string;
      batchSucceeded: string;
      batchCompleted: string;
    };
  };
}

// Singleton pattern for loading OpenAPI specification
export class OpenApiLoader {
  private static instance: OpenApiLoader;
  private spec: OpenApiSpec | null = null;
  private examples: Map<string, unknown[]> = new Map();

  private constructor() {}

  static getInstance(): OpenApiLoader {
    if (!OpenApiLoader.instance) {
      OpenApiLoader.instance = new OpenApiLoader();
    }
    return OpenApiLoader.instance;
  }

  // Load OpenAPI specification
  loadSpec(): OpenApiSpec {
    if (this.spec) {
      return this.spec;
    }

    const specPath = path.join(__dirname, '../../../api/spec-workflow.openapi.yaml');
    const specContent = fs.readFileSync(specPath, 'utf8');
    this.spec = yaml.load(specContent) as OpenApiSpec;

    // Parse and cache all examples
    this.cacheExamples();

    return this.spec;
  }

  // Cache all response examples
  private cacheExamples(): void {
    if (!this.spec) return;

    const schemas = this.spec.components.schemas;
    for (const [schemaName, schema] of Object.entries(schemas)) {
      if (!isObject(schema)) continue;
      // Support standard OpenAPI 3.1.0 examples field
      if ('examples' in schema && Array.isArray(schema.examples)) {
        this.examples.set(schemaName, schema.examples);
      }
      // Maintain backward compatibility with custom x-examples field
      else if ('x-examples' in schema && Array.isArray(schema['x-examples'])) {
        this.examples.set(schemaName, schema['x-examples']);
      }
    }
  }

  // Get response example
  getResponseExample(responseType: string, criteria?: Record<string, unknown>): unknown {
    const examples = this.examples.get(responseType);
    if (!examples || examples.length === 0) {
      return null;
    }

    // If no filter criteria, return the first example
    if (!criteria) {
      return examples[0];
    }

    // Filter examples by criteria
    for (const example of examples) {
      let matches = true;
      for (const [key, value] of Object.entries(criteria)) {
        if (this.getNestedValue(example, key) !== value) {
          matches = false;
          break;
        }
      }
      if (matches) {
        return example;
      }
    }

    // No match found, return the first one
    return examples[0];
  }

  // Get error response template
  getErrorResponse(errorType: string): string | null {
    if (!this.spec || !this.spec['x-error-responses']) {
      return null;
    }
    
    const errorResponse = this.spec['x-error-responses'][errorType];
    return errorResponse?.displayText || null;
  }


  // Get progress calculation rules
  getProgressRules(): unknown {
    if (!this.spec) return null;

    const progressSchema = this.spec.components.schemas.Progress;
    if (isObject(progressSchema) && 'x-progress-rules' in progressSchema) {
      return progressSchema['x-progress-rules'];
    }
    return null;
  }

  // Utility function: get nested object value
  private getNestedValue(obj: unknown, path: string): unknown {
    const keys = path.split('.');
    let current = obj;
    
    for (const key of keys) {
      if (isObject(current) && key in current) {
        current = current[key];
      } else {
        return undefined;
      }
    }
    
    return current;
  }

  // Replace template variables
  static replaceVariables(template: string, variables: Record<string, unknown>): string {
    let result = template;
    
    for (const [key, value] of Object.entries(variables)) {
      const regex = new RegExp(`\\$\\{${key}\\}`, 'g');
      result = result.replace(regex, String(value));
    }
    
    return result;
  }

  // Get shared resource - directly return MCP format
  getSharedResource(resourceId: string): { uri: string; title?: string; mimeType: string; text?: string } | null {
    if (!this.spec || !this.spec['x-shared-resources']) {
      return null;
    }
    
    return this.spec['x-shared-resources'][resourceId] || null;
  }

  // Get global configuration
  getGlobalConfig(): unknown {
    if (!this.spec) return {};
    return this.spec['x-global-config'] || {};
  }

  // Get document template
  getDocumentTemplate(templateType: string): unknown {
    if (!this.spec) return null;
    return this.spec['x-document-templates']?.[templateType] || null;
  }

  // Resolve resource list - no conversion needed, use MCP format directly
  resolveResources(resources?: Array<unknown>): Array<{ uri: string; title?: string; mimeType: string; text?: string }> | undefined {
    if (!resources || resources.length === 0) {
      return undefined;
    }

    const resolved: Array<{ uri: string; title?: string; mimeType: string; text?: string }> = [];
    
    for (const resource of resources) {
      if (isObject(resource) && 'ref' in resource && typeof resource.ref === 'string') {
        // Get from shared resources - already in MCP format
        const sharedResource = this.getSharedResource(resource.ref);
        if (sharedResource) {
          resolved.push(sharedResource);
        }
      }
    }

    return resolved.length > 0 ? resolved : undefined;
  }

  // Get task guidance template
  getTaskGuidanceTemplate(): OpenApiSpec['x-task-guidance-template'] | null {
    if (!this.spec) return null;
    return this.spec['x-task-guidance-template'] || null;
  }

  // Debug method: get cached examples count
  getExamplesCount(responseType: string): number {
    return this.examples.get(responseType)?.length || 0;
  }
}

export const openApiLoader = OpenApiLoader.getInstance();

```

--------------------------------------------------------------------------------
/src/features/shared/taskParser.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Parse tasks from tasks.md file
 */

import { readFileSync } from 'fs';
import { join } from 'path';

export interface Task {
  number: string;
  description: string;
  checked: boolean;
  subtasks?: Task[];
  isVirtual?: boolean; // 标识是否为虚拟创建的任务
}

export function parseTasksFile(path: string): Task[] {
  try {
    const tasksPath = join(path, 'tasks.md');
    const content = readFileSync(tasksPath, 'utf-8');
    
    // Remove template marker blocks
    const cleanContent = content
      .replace(/<!--\s*SPEC-MARKER[\s\S]*?-->/g, '') // Compatible with old format
      .replace(/<template-tasks>[\s\S]*?<\/template-tasks>/g, '') // Match actual task template markers
      .trim();
    
    if (!cleanContent) {
      return [];
    }
    
    return parseTasksFromContent(cleanContent);
  } catch {
    return [];
  }
}

export function parseTasksFromContent(content: string): Task[] {
  const lines = content.split('\n');
  const allTasks: Task[] = [];
  
  // Phase 1: Collect all tasks with checkboxes
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    
    // Find checkbox pattern
    const checkboxMatch = line.match(/\[([xX ])\]/);
    if (!checkboxMatch) continue;
    
    // Extract task number (flexible matching)
    const numberMatch = line.match(/(\d+(?:\.\d+)*)/);
    if (!numberMatch) continue;
    
    const taskNumber = numberMatch[1];
    const isChecked = checkboxMatch[1].toLowerCase() === 'x';
    
    // Extract description (remove task number and checkbox)
    let description = line
      .replace(/\[([xX ])\]/, '')  // Remove checkbox
      .replace(/(\d+(?:\.\d+)*)\s*[.:\-)]?/, '') // Remove task number
      .replace(/^[\s\-*]+/, '')  // Remove leading symbols
      .trim();
    
    // If description is empty, try to get from next line
    if (!description && i + 1 < lines.length) {
      const nextLine = lines[i + 1].trim();
      if (nextLine && !nextLine.match(/\[([xX ])\]/) && !nextLine.match(/^#/)) {
        description = nextLine;
        i++; // Skip next line
      }
    }
    
    if (!description) continue;
    
    allTasks.push({
      number: taskNumber,
      description: description,
      checked: isChecked
    });
  }
  
  // Phase 2: Build hierarchy structure
  const taskMap = new Map<string, Task>();
  const rootTasks: Task[] = [];
  
  // Infer main tasks from task numbers
  for (const task of allTasks) {
    if (!task.number.includes('.')) {
      // Top-level task
      taskMap.set(task.number, task);
      rootTasks.push(task);
    }
  }
  
  // Process subtasks
  for (const task of allTasks) {
    if (task.number.includes('.')) {
      const parts = task.number.split('.');
      const parentNumber = parts[0];
      
      // If main task doesn't exist, create virtual parent task
      if (!taskMap.has(parentNumber)) {
        // Try to find better title from document
        const betterTitle = findMainTaskTitle(lines, parentNumber);
        const virtualParent: Task = {
          number: parentNumber,
          description: betterTitle || `Task Group ${parentNumber}`,
          checked: false,
          subtasks: [],
          isVirtual: true // 标记为虚拟任务
        };
        taskMap.set(parentNumber, virtualParent);
        rootTasks.push(virtualParent);
      }
      
      // Add subtask to main task
      const parent = taskMap.get(parentNumber)!;
      if (!parent.subtasks) {
        parent.subtasks = [];
      }
      parent.subtasks.push(task);
    }
  }
  
  // Update main task completion status (only when all subtasks are completed)
  for (const task of rootTasks) {
    if (task.subtasks && task.subtasks.length > 0) {
      task.checked = task.subtasks.every(st => st.checked);
    }
  }
  
  // Sort by task number
  rootTasks.sort((a, b) => {
    const numA = parseInt(a.number);
    const numB = parseInt(b.number);
    return numA - numB;
  });
  
  // Sort subtasks
  for (const task of rootTasks) {
    if (task.subtasks) {
      task.subtasks.sort((a, b) => {
        const partsA = a.number.split('.').map(n => parseInt(n));
        const partsB = b.number.split('.').map(n => parseInt(n));
        for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
          const diff = (partsA[i] || 0) - (partsB[i] || 0);
          if (diff !== 0) return diff;
        }
        return 0;
      });
    }
  }
  
  return rootTasks;
}

// Find main task title (from headers or other places)
function findMainTaskTitle(lines: string[], taskNumber: string): string | null {
  // Look for lines like "### 1. Title" or "## 1. Title"
  for (const line of lines) {
    const headerMatch = line.match(/^#+\s*(\d+)\.\s*(.+)$/);
    if (headerMatch && headerMatch[1] === taskNumber) {
      return headerMatch[2].trim();
    }
  }
  
  // Also support other formats like "1. **Title**"
  for (const line of lines) {
    const boldMatch = line.match(/^(\d+)\.\s*\*\*(.+?)\*\*$/);
    if (boldMatch && boldMatch[1] === taskNumber) {
      return boldMatch[2].trim();
    }
  }
  
  return null;
}

export function getFirstUncompletedTask(tasks: Task[]): Task | null {
  for (const task of tasks) {
    // 如果任务有子任务,优先检查子任务
    if (task.subtasks && task.subtasks.length > 0) {
      // 检查是否有未完成的子任务
      const firstUncompletedSubtask = task.subtasks.find(subtask => !subtask.checked);

      if (firstUncompletedSubtask) {
        // 无论是虚拟主任务还是真实主任务,都返回第一个未完成的子任务
        return firstUncompletedSubtask;
      }

      // 如果所有子任务都完成了,但主任务未完成,返回主任务
      if (!task.checked) {
        return task;
      }
    } else {
      // 没有子任务的情况,直接检查主任务
      if (!task.checked) {
        return task;
      }
    }
  }

  return null;
}

export function formatTaskForDisplay(task: Task): string {
  let display = `📋 Task ${task.number}: ${task.description}`;
  
  if (task.subtasks && task.subtasks.length > 0) {
    display += '\n\nSubtasks:';
    for (const subtask of task.subtasks) {
      const status = subtask.checked ? '✓' : '☐';
      display += `\n  ${status} ${subtask.number}. ${subtask.description}`;
    }
  }
  
  return display;
}

export function formatTaskForFullDisplay(task: Task, content: string): string {
  const lines = content.split('\n');
  const taskLines: string[] = [];
  let capturing = false;
  let indent = '';
  
  for (const line of lines) {
    // Find task start (supports two formats: `1. - [ ] task` or `- [ ] 1. task`)
    const taskPattern1 = new RegExp(`^(\\s*)${task.number}\\.\\s*-\\s*\\[[ x]\\]\\s*`);
    const taskPattern2 = new RegExp(`^(\\s*)-\\s*\\[[ x]\\]\\s*${task.number}\\.\\s*`);
    if (line.match(taskPattern1) || line.match(taskPattern2)) {
      capturing = true;
      taskLines.push(line);
      indent = line.match(/^(\s*)/)?.[1] || '';
      continue;
    }
    
    // If capturing task content
    if (capturing) {
      // Check if reached next task at same or higher level
      const nextTaskPattern = /^(\s*)-\s*\[[ x]\]\s*\d+(\.\d+)*\.\s*/;
      const nextMatch = line.match(nextTaskPattern);
      if (nextMatch) {
        const nextIndent = nextMatch[1] || '';
        if (nextIndent.length <= indent.length) {
          break; // Found same or higher level task, stop capturing
        }
      }
      
      // Continue capturing content belonging to current task
      if (line.trim() === '') {
        taskLines.push(line);
      } else if (line.startsWith(indent + '  ') || line.startsWith(indent + '\t')) {
        // Deeper indented content belongs to current task
        taskLines.push(line);
      } else if (line.match(/^#+\s/)) {
        // Found header, stop capturing
        break;
      } else if (line.match(/^\d+\.\s*-\s*\[[ x]\]/)) {
        // Found other top-level task, stop
        break;
      } else {
        // Other cases continue capturing (might be continuation of task description)
        const isTaskLine = line.match(/^(\s*)-\s*\[[ x]\]/) || line.match(/^(\s*)\d+(\.\d+)*\.\s*-\s*\[[ x]\]/);
        if (isTaskLine) {
          break; // Found other task, stop
        } else if (line.match(/^\s/) && !line.match(/^\s{8,}/)) {
          // If indented but not too deep, might still be current task content
          taskLines.push(line);
        } else {
          break; // Otherwise stop
        }
      }
    }
  }
  
  return taskLines.join('\n').trimEnd();
}

// Format task list overview for display
export function formatTaskListOverview(path: string): string {
  try {
    const tasks = parseTasksFile(path);
    if (tasks.length === 0) {
      return 'No tasks found.';
    }
    
    const taskItems = tasks.map(task => {
      const status = task.checked ? '[x]' : '[ ]';
      return `- ${status} ${task.number}. ${task.description}`;
    });
    
    return taskItems.join('\n');
  } catch {
    return 'Error loading tasks list.';
  }
}
```

--------------------------------------------------------------------------------
/src/features/shared/responseBuilder.ts:
--------------------------------------------------------------------------------

```typescript
import { openApiLoader } from './openApiLoader.js';
import { OpenApiLoader } from './openApiLoader.js';
import { WorkflowResult } from './mcpTypes.js';
import { isObject, hasProperty, isArray } from './typeGuards.js';
import { TaskGuidanceExtractor } from './taskGuidanceTemplate.js';

// Response builder - builds responses based on OpenAPI specification
export class ResponseBuilder {

  // Build initialization response
  buildInitResponse(path: string, featureName: string): WorkflowResult {
    const example = openApiLoader.getResponseExample('InitResponse', {
      success: true
    });

    if (!example) {
      throw new Error('Initialization response template not found');
    }

    // Deep copy example
    const response = JSON.parse(JSON.stringify(example));

    // Replace variables
    response.displayText = OpenApiLoader.replaceVariables(response.displayText, {
      featureName,
      path,
      progress: response.progress?.overall || 0
    });

    // Update data
    response.data.path = path;
    response.data.featureName = featureName;

    // Resolve resource references
    if (response.resources) {
      response.resources = openApiLoader.resolveResources(response.resources);
    }

    // Embed resources into display text for better client compatibility
    const enhancedDisplayText = this.embedResourcesIntoText(response.displayText, response.resources);

    // Return WorkflowResult format, but include complete OpenAPI response in data
    return {
      displayText: enhancedDisplayText,
      data: response,
      resources: response.resources
    };
  }

  // Build check response
  buildCheckResponse(
    stage: string,
    progress: unknown,
    status: unknown,
    checkResults?: unknown,
    path?: string,
    firstTask?: string | null
  ): WorkflowResult {
    // Select appropriate example based on status type
    const statusType = isObject(status) && 'type' in status ? status.type : 'not_started';

    // Debug info: check examples cache
    const examplesCount = openApiLoader.getExamplesCount('CheckResponse');

    const example = openApiLoader.getResponseExample('CheckResponse', {
      stage,
      'status.type': statusType
    });

    if (!example) {
      throw new Error(`Check response template not found: stage=${stage}, status=${statusType} (cached examples: ${examplesCount})`);
    }

    // Deep copy example
    const response = JSON.parse(JSON.stringify(example));

    // Update actual values
    response.stage = stage;
    
    // Convert progress format to comply with OpenAPI specification
    // If input is WorkflowProgress format, need to convert
    if (isObject(progress) && hasProperty(progress, 'percentage')) {
      // Calculate phase progress based on stage status
      const details = isObject(progress.details) ? progress.details : {};
      const requirements = isObject(details.requirements) ? details.requirements : {};
      const design = isObject(details.design) ? details.design : {};
      const tasks = isObject(details.tasks) ? details.tasks : {};
      
      const requirementsProgress = requirements.confirmed || requirements.skipped ? 100 : 0;
      const designProgress = design.confirmed || design.skipped ? 100 : 0;
      // Tasks stage: only count as progress if confirmed, not skipped
      const tasksProgress = tasks.confirmed ? 100 : 0;
      
      response.progress = this.calculateProgress(requirementsProgress, designProgress, tasksProgress);
    } else {
      // If already in correct format, use directly
      response.progress = progress;
    }
    
    response.status = status;

    // If there are check results, update display text
    if (checkResults && response.displayText.includes('The tasks document includes')) {
      // Dynamically build check items list
      const checkItems = this.buildCheckItemsList(checkResults);
      // More precise regex that only matches until next empty line or "Model please" line
      response.displayText = response.displayText.replace(
        /The tasks document includes:[\s\S]*?(?=\n\s*Model please|\n\s*\n\s*Model please|$)/,
        `The tasks document includes:\n${checkItems}\n\n`
      );
    }

    // Replace variables including progress
    const variables: Record<string, unknown> = {};
    if (path) {
      variables.path = path;
    }
    if (response.progress && typeof response.progress.overall === 'number') {
      variables.progress = response.progress.overall;
    }
    response.displayText = OpenApiLoader.replaceVariables(response.displayText, variables);
    
    // If completed stage and has uncompleted tasks, add task information
    if (stage === 'completed' && firstTask) {
      response.displayText += `\n\n📄 Next uncompleted task:\n${firstTask}\n\nModel please ask the user: "Ready to start the next task?"`;
    }

    // Resolve resource references
    if (response.resources) {
      response.resources = openApiLoader.resolveResources(response.resources);
    }

    // Embed resources into display text for better client compatibility
    const enhancedDisplayText = this.embedResourcesIntoText(response.displayText, response.resources);

    // Return WorkflowResult format
    return {
      displayText: enhancedDisplayText,
      data: response,
      resources: response.resources
    };
  }

  // Build skip response
  buildSkipResponse(stage: string, path?: string, progress?: unknown): WorkflowResult {
    const example = openApiLoader.getResponseExample('SkipResponse', {
      stage
    });

    if (!example) {
      throw new Error(`Skip response template not found: stage=${stage}`);
    }

    // Deep copy example
    const response = JSON.parse(JSON.stringify(example));
    response.stage = stage;
    
    // Update progress if provided
    if (progress) {
      // Convert progress format to comply with OpenAPI specification
      if (isObject(progress) && hasProperty(progress, 'percentage')) {
        // Calculate phase progress based on stage status
        const details = isObject(progress.details) ? progress.details : {};
        const requirements = isObject(details.requirements) ? details.requirements : {};
        const design = isObject(details.design) ? details.design : {};
        const tasks = isObject(details.tasks) ? details.tasks : {};
        
        const requirementsProgress = requirements.confirmed || requirements.skipped ? 100 : 0;
        const designProgress = design.confirmed || design.skipped ? 100 : 0;
        // Tasks stage: only count as progress if confirmed, not skipped
        const tasksProgress = tasks.confirmed ? 100 : 0;
        
        response.progress = this.calculateProgress(requirementsProgress, designProgress, tasksProgress);
      } else {
        // If already in correct format, use directly
        response.progress = progress;
      }
    }

    // Replace variables including progress
    const variables: Record<string, unknown> = {};
    if (path) {
      variables.path = path;
    }
    if (response.progress && typeof response.progress.overall === 'number') {
      variables.progress = response.progress.overall;
    }
    response.displayText = OpenApiLoader.replaceVariables(response.displayText, variables);

    // Resolve resource references
    if (response.resources) {
      response.resources = openApiLoader.resolveResources(response.resources);
    }

    // Embed resources into display text for better client compatibility
    const enhancedDisplayText = this.embedResourcesIntoText(response.displayText, response.resources);

    // Return WorkflowResult format
    return {
      displayText: enhancedDisplayText,
      data: response,
      resources: response.resources
    };
  }

  // Build confirm response
  buildConfirmResponse(stage: string, nextStage: string | null, path?: string, firstTaskContent?: string | null, progress?: unknown): WorkflowResult {
    const example = openApiLoader.getResponseExample('ConfirmResponse', {
      stage,
      nextStage: nextStage || null
    });

    if (!example) {
      throw new Error(`Confirm response template not found: stage=${stage}`);
    }

    // Deep copy example
    const response = JSON.parse(JSON.stringify(example));
    response.stage = stage;
    response.nextStage = nextStage;
    
    // Update progress if provided
    if (progress) {
      // Convert progress format to comply with OpenAPI specification
      if (isObject(progress) && hasProperty(progress, 'percentage')) {
        // Calculate phase progress based on stage status
        const details = isObject(progress.details) ? progress.details : {};
        const requirements = isObject(details.requirements) ? details.requirements : {};
        const design = isObject(details.design) ? details.design : {};
        const tasks = isObject(details.tasks) ? details.tasks : {};
        
        const requirementsProgress = requirements.confirmed || requirements.skipped ? 100 : 0;
        const designProgress = design.confirmed || design.skipped ? 100 : 0;
        // Tasks stage: only count as progress if confirmed, not skipped
        const tasksProgress = tasks.confirmed ? 100 : 0;
        
        response.progress = this.calculateProgress(requirementsProgress, designProgress, tasksProgress);
      } else {
        // If already in correct format, use directly
        response.progress = progress;
      }
    }

    // Replace variables including progress
    const variables: Record<string, unknown> = {};
    if (path) {
      variables.path = path;
    }
    if (response.progress && typeof response.progress.overall === 'number') {
      variables.progress = response.progress.overall;
    }
    response.displayText = OpenApiLoader.replaceVariables(response.displayText, variables);

    // If tasks stage confirmation and has first task content, append to display text
    if (stage === 'tasks' && nextStage === null && firstTaskContent) {
      // Extract first uncompleted subtask for focused planning
      const firstSubtask = TaskGuidanceExtractor.extractFirstSubtask(firstTaskContent);

      // 如果没有找到子任务,从任务内容中提取任务描述
      let effectiveFirstSubtask = firstSubtask;
      if (!effectiveFirstSubtask) {
        // 从 firstTaskContent 中提取任务号和描述
        const taskMatch = firstTaskContent.match(/(\d+(?:\.\d+)*)\.\s*\*?\*?([^*\n]+)/);
        if (taskMatch) {
          effectiveFirstSubtask = `${taskMatch[1]}. ${taskMatch[2].trim()}`;
        } else {
          effectiveFirstSubtask = 'Next task';
        }
      }

      // Build guidance text using the template
      const guidanceText = TaskGuidanceExtractor.buildGuidanceText(
        firstTaskContent,
        effectiveFirstSubtask,
        undefined, // no specific task number
        true // is first task
      );

      response.displayText += '\n\n' + guidanceText;
    }

    // Resolve resource references
    if (response.resources) {
      response.resources = openApiLoader.resolveResources(response.resources);
    }

    // Embed resources into display text for better client compatibility
    const enhancedDisplayText = this.embedResourcesIntoText(response.displayText, response.resources);

    // Return WorkflowResult format
    return {
      displayText: enhancedDisplayText,
      data: response,
      resources: response.resources
    };
  }

  // Build error response
  buildErrorResponse(errorType: string, variables?: Record<string, unknown>): string {
    const template = openApiLoader.getErrorResponse(errorType);
    
    if (!template) {
      return `❌ Error: ${errorType}`;
    }

    if (variables) {
      return OpenApiLoader.replaceVariables(template, variables);
    }

    return template;
  }

  // Calculate progress
  calculateProgress(
    requirementsProgress: number,
    designProgress: number,
    tasksProgress: number
  ): Record<string, unknown> {
    // const rules = openApiLoader.getProgressRules(); // \u672a\u4f7f\u7528
    
    // Use rules defined in OpenAPI to calculate overall progress
    const overall = Math.round(
      requirementsProgress * 0.3 +
      designProgress * 0.3 +
      tasksProgress * 0.4
    );

    return {
      overall,
      requirements: requirementsProgress,
      design: designProgress,
      tasks: tasksProgress
    };
  }




  // Private method: embed resources into display text
  private embedResourcesIntoText(displayText: string, resources?: unknown[]): string {
    if (!resources || resources.length === 0) {
      return displayText;
    }

    // 为每个 resource 构建嵌入文本
    const resourceTexts = resources.map(resource => {
      if (!isObject(resource)) return '';
      const header = `\n\n---\n[Resource: ${resource.title || resource.uri}]\n`;
      const content = resource.text || '';
      return header + content;
    });

    // 将资源内容附加到显示文本末尾
    return displayText + resourceTexts.join('');
  }

  // Private method: build check items list
  private buildCheckItemsList(checkResults: unknown): string {
    const items: string[] = [];

    if (!isObject(checkResults)) return '';
    
    if (isArray(checkResults.requiredSections)) {
      checkResults.requiredSections.forEach((section: unknown) => {
        if (typeof section === 'string') {
          items.push(`- ✓ ${section}`);
        }
      });
    }

    if (isArray(checkResults.optionalSections) && checkResults.optionalSections.length > 0) {
      checkResults.optionalSections.forEach((section: unknown) => {
        if (typeof section === 'string') {
          items.push(`- ✓ ${section}`);
        }
      });
    }

    return items.join('\n');
  }
}

// Export singleton
export const responseBuilder = new ResponseBuilder();

```

--------------------------------------------------------------------------------
/src/features/task/completeTask.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Complete task - 统一使用批量完成逻辑
 */

import { existsSync, readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { parseTasksFromContent, getFirstUncompletedTask, formatTaskForFullDisplay, Task } from '../shared/taskParser.js';
import { responseBuilder } from '../shared/responseBuilder.js';
import { WorkflowResult } from '../shared/mcpTypes.js';
import { BatchCompleteTaskResponse } from '../shared/openApiTypes.js';
import { TaskGuidanceExtractor } from '../shared/taskGuidanceTemplate.js';

export interface CompleteTaskOptions {
  path: string;
  taskNumber: string | string[];
}

export async function completeTask(options: CompleteTaskOptions): Promise<WorkflowResult> {
  const { path, taskNumber } = options;

  // 统一转换为数组格式进行批量处理
  const taskNumbers = Array.isArray(taskNumber) ? taskNumber : [taskNumber];

  if (!existsSync(path)) {
    return {
      displayText: responseBuilder.buildErrorResponse('invalidPath', { path }),
      data: {
        success: false,
        error: 'Directory does not exist'
      }
    };
  }

  const tasksPath = join(path, 'tasks.md');
  if (!existsSync(tasksPath)) {
    return {
      displayText: '❌ Error: tasks.md file does not exist\n\nPlease complete writing the tasks document first.',
      data: {
        success: false,
        error: 'tasks.md does not exist'
      }
    };
  }

  // 统一使用批量处理逻辑
  const batchResult = await completeBatchTasks(tasksPath, taskNumbers);
  return {
    displayText: batchResult.displayText,
    data: { ...batchResult }
  };
}


/**
 * Complete multiple tasks in batch
 */
async function completeBatchTasks(tasksPath: string, taskNumbers: string[]): Promise<BatchCompleteTaskResponse> {
  // Read tasks file
  const originalContent = readFileSync(tasksPath, 'utf-8');
  const tasks = parseTasksFromContent(originalContent);
  
  // Categorize tasks: already completed, can be completed, cannot be completed
  const alreadyCompleted: string[] = [];
  const canBeCompleted: string[] = [];
  const cannotBeCompleted: Array<{
    taskNumber: string;
    reason: string;
  }> = [];
  
  for (const taskNum of taskNumbers) {
    const targetTask = findTaskByNumber(tasks, taskNum);
    
    if (!targetTask) {
      cannotBeCompleted.push({
        taskNumber: taskNum,
        reason: 'Task does not exist'
      });
    } else if (targetTask.checked) {
      alreadyCompleted.push(taskNum);
    } else if (targetTask.subtasks && targetTask.subtasks.some(s => !s.checked)) {
      cannotBeCompleted.push({
        taskNumber: taskNum,
        reason: 'Has uncompleted subtasks'
      });
    } else {
      canBeCompleted.push(taskNum);
    }
  }
  
  // If there are tasks that cannot be completed (excluding already completed), return error
  if (cannotBeCompleted.length > 0) {
    const errorMessages = cannotBeCompleted
      .map(v => `- ${v.taskNumber}: ${v.reason}`)
      .join('\n');
    
    return {
      success: false,
      completedTasks: [],
      alreadyCompleted: [],
      failedTasks: cannotBeCompleted,
      displayText: `❌ Batch task completion failed\n\nThe following tasks cannot be completed:\n${errorMessages}\n\nPlease resolve these issues and try again.`
    };
  }
  
  // If no tasks can be completed but there are already completed tasks, still return success
  if (canBeCompleted.length === 0 && alreadyCompleted.length > 0) {
    const allTasks = parseTasksFromContent(originalContent);
    const nextTask = getFirstUncompletedTask(allTasks);
    
    const alreadyCompletedText = alreadyCompleted
      .map(t => `- ${t} (already completed)`)
      .join('\n');
    
    const displayText = `${TaskGuidanceExtractor.getCompletionMessage('batchCompleted')}\n\nThe following tasks were already completed:\n${alreadyCompletedText}\n\n${nextTask ? `Next task: ${nextTask.number}. ${nextTask.description}` : TaskGuidanceExtractor.getCompletionMessage('allCompleted')}`;
    
    return {
      success: true,
      completedTasks: [],
      alreadyCompleted,
      nextTask: nextTask ? {
        number: nextTask.number,
        description: nextTask.description
      } : undefined,
      hasNextTask: nextTask !== null,
      displayText
    };
  }
  
  // Execution phase: complete tasks in dependency order
  let currentContent = originalContent;
  const actuallyCompleted: string[] = [];
  const results: Array<{
    taskNumber: string;
    success: boolean;
    status: 'completed' | 'already_completed' | 'failed';
  }> = [];
  
  try {
    // Sort by task number, ensure parent tasks are processed after subtasks (avoid dependency conflicts)
    const sortedTaskNumbers = [...canBeCompleted].sort((a, b) => {
      // Subtasks first (numbers with more dots have priority)
      const aDepth = a.split('.').length;
      const bDepth = b.split('.').length;
      if (aDepth !== bDepth) {
        return bDepth - aDepth; // Process deeper levels first
      }
      return a.localeCompare(b); // Same depth, sort by string
    });
    
    for (const taskNum of sortedTaskNumbers) {
      const updatedContent = markTaskAsCompleted(currentContent, taskNum);
      
      if (!updatedContent) {
        // This should not happen as we have already validated
        throw new Error(`Unexpected error: Task ${taskNum} could not be marked`);
      }
      
      currentContent = updatedContent;
      actuallyCompleted.push(taskNum);
      results.push({
        taskNumber: taskNum,
        success: true,
        status: 'completed' as const
      });
    }
    
    // Add results for already completed tasks
    for (const taskNum of alreadyCompleted) {
      results.push({
        taskNumber: taskNum,
        success: true,
        status: 'already_completed' as const
      });
    }
    
    // All tasks completed successfully, save file
    if (actuallyCompleted.length > 0) {
      writeFileSync(tasksPath, currentContent, 'utf-8');
    }
    
    // Build success response
    const allTasks = parseTasksFromContent(currentContent);
    const nextTask = getFirstUncompletedTask(allTasks);
    
    // Build detailed completion information
    let completedInfo = '';
    if (actuallyCompleted.length > 0) {
      completedInfo += 'Newly completed tasks:\n' + actuallyCompleted.map(t => `- ${t}`).join('\n');
    }
    if (alreadyCompleted.length > 0) {
      if (completedInfo) completedInfo += '\n\n';
      completedInfo += 'Already completed tasks:\n' + alreadyCompleted.map(t => `- ${t} (already completed)`).join('\n');
    }
    
    let displayText = `${TaskGuidanceExtractor.getCompletionMessage('batchSucceeded')}\n\n${completedInfo}`;
    
    // Add enhanced guidance for next task
    if (nextTask) {
      // 获取主任务的完整内容用于显示任务块
      let mainTask = nextTask;
      let mainTaskContent = '';

      // 如果当前是子任务,需要找到对应的主任务
      if (nextTask.number.includes('.')) {
        const mainTaskNumber = nextTask.number.split('.')[0];
        const mainTaskObj = allTasks.find(task => task.number === mainTaskNumber);
        if (mainTaskObj) {
          mainTask = mainTaskObj;
          mainTaskContent = formatTaskForFullDisplay(mainTask, currentContent);
        } else {
          // 如果找不到主任务,使用当前任务
          mainTaskContent = formatTaskForFullDisplay(nextTask, currentContent);
        }
      } else {
        // 如果本身就是主任务,直接使用
        mainTaskContent = formatTaskForFullDisplay(nextTask, currentContent);
      }

      // 构建下一个具体子任务的描述(用于指导文本)
      let effectiveFirstSubtask: string;
      let actualNextSubtask: Task | null = null;

      if (nextTask.number.includes('.')) {
        // 如果下一个任务是子任务,直接使用
        actualNextSubtask = nextTask;
      } else {
        // 如果下一个任务是主任务,找到第一个未完成的子任务
        if (mainTask.subtasks && mainTask.subtasks.length > 0) {
          actualNextSubtask = mainTask.subtasks.find(subtask => !subtask.checked) || null;
        }
      }

      if (actualNextSubtask) {
        // 使用具体的子任务构建指导文本,包含完整内容
        const nextSubtaskContent = formatTaskForFullDisplay(actualNextSubtask, currentContent);

        if (nextSubtaskContent.trim()) {
          // 如果能获取到完整内容,直接使用
          effectiveFirstSubtask = nextSubtaskContent.trim();
        } else {
          // 如果获取不到完整内容,手动构建
          effectiveFirstSubtask = `- [ ] ${actualNextSubtask.number} ${actualNextSubtask.description}`;

          // 从主任务内容中提取这个子任务的详细信息
          const mainTaskLines = mainTaskContent.split('\n');
          let capturing = false;
          let taskIndent = '';

          for (const line of mainTaskLines) {
            // 找到目标子任务的开始
            if (line.includes(`${actualNextSubtask.number} ${actualNextSubtask.description}`) ||
                line.includes(`${actualNextSubtask.number}. ${actualNextSubtask.description}`)) {
              capturing = true;
              taskIndent = line.match(/^(\s*)/)?.[1] || '';
              continue;
            }

            // 如果正在捕获内容
            if (capturing) {
              const lineIndent = line.match(/^(\s*)/)?.[1] || '';

              // 如果遇到下一个任务(同级或更高级),停止捕获
              if (line.includes('[ ]') && lineIndent.length <= taskIndent.length) {
                break;
              }

              // 如果是更深层次的内容,添加到结果中
              if (lineIndent.length > taskIndent.length && line.trim()) {
                effectiveFirstSubtask += `\n${line}`;
              }
            }
          }
        }
      } else {
        // 如果找不到具体的子任务,使用主任务
        effectiveFirstSubtask = `${nextTask.number}. ${nextTask.description}`;
      }

      // Build guidance text using the template
      const guidanceText = TaskGuidanceExtractor.buildGuidanceText(
        mainTaskContent,  // 显示主任务块
        effectiveFirstSubtask,  // 用于指导文本的具体子任务
        undefined, // no specific task number for batch
        false // not first task
      );

      displayText += '\n\n' + guidanceText;
    } else {
      displayText += '\n\n' + TaskGuidanceExtractor.getCompletionMessage('allCompleted');
    }
    
    return {
      success: true,
      completedTasks: actuallyCompleted,
      alreadyCompleted,
      failedTasks: [],
      results,
      nextTask: nextTask ? {
        number: nextTask.number,
        description: nextTask.description
      } : undefined,
      hasNextTask: nextTask !== null,
      displayText
    };
    
  } catch (error) {
    // Execution failed, need to rollback to original state
    if (actuallyCompleted.length > 0) {
      writeFileSync(tasksPath, originalContent, 'utf-8');
    }
    
    return {
      success: false,
      completedTasks: [],
      alreadyCompleted: [],
      failedTasks: [{
        taskNumber: 'batch',
        reason: error instanceof Error ? error.message : String(error)
      }],
      results,
      displayText: `❌ Batch task execution failed\n\nError: ${error instanceof Error ? error.message : String(error)}\n\nRolled back to original state.`
    };
  }
}



/**
 * Mark task as completed
 */
function markTaskAsCompleted(content: string, taskNumber: string): string | null {
  const lines = content.split('\n');
  const tasks = parseTasksFromContent(content);
  let found = false;
  
  // Find target task (including subtasks)
  const targetTask = findTaskByNumber(tasks, taskNumber);
  if (!targetTask) {
    return null;
  }
  
  // Build set of task numbers to mark
  const numbersToMark = new Set<string>();
  numbersToMark.add(taskNumber);
  
  // If it's a leaf task, check if parent task should be auto-marked
  const parentNumber = taskNumber.substring(0, taskNumber.lastIndexOf('.'));
  if (parentNumber && taskNumber.includes('.')) {
    const parentTask = findTaskByNumber(tasks, parentNumber);
    if (parentTask && parentTask.subtasks) {
      // Check if all sibling tasks are completed
      const allSiblingsCompleted = parentTask.subtasks
        .filter(s => s.number !== taskNumber)
        .every(s => s.checked);
      
      if (allSiblingsCompleted) {
        numbersToMark.add(parentNumber);
      }
    }
  }
  
  // Mark all related tasks
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    
    // Skip already completed tasks
    if (!line.includes('[ ]')) continue;
    
    // Check if line contains task number to mark
    for (const num of numbersToMark) {
      // More robust matching strategy: as long as the line contains both task number and checkbox
      // Don't care about their relative position and format details
      if (containsTaskNumber(line, num)) {
        lines[i] = line.replace('[ ]', '[x]');
        found = true;
        break;
      }
    }
  }
  
  return found ? lines.join('\n') : null;
}

/**
 * Check if line contains specified task number
 * Use flexible matching strategy, ignore format details
 */
function containsTaskNumber(line: string, taskNumber: string): boolean {
  // Remove checkbox part to avoid interference with matching
  const lineWithoutCheckbox = line.replace(/\[[xX ]\]/g, '');
  
  // Use word boundary to ensure matching complete task number
  // For example: won't mistakenly match "11.1" as "1.1"
  const escapedNumber = escapeRegExp(taskNumber);
  const regex = new RegExp(`\\b${escapedNumber}\\b`);
  
  return regex.test(lineWithoutCheckbox);
}

/**
 * Escape regex special characters
 */
function escapeRegExp(string: string): string {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

/**
 * Recursively find task (including subtasks)
 */
function findTaskByNumber(tasks: Task[], targetNumber: string): Task | null {
  for (const task of tasks) {
    if (task.number === targetNumber) {
      return task;
    }
    
    // Recursively search subtasks
    if (task.subtasks) {
      const found = findTaskByNumber(task.subtasks, targetNumber);
      if (found) {
        return found;
      }
    }
  }
  
  return null;
}
```

--------------------------------------------------------------------------------
/scripts/generateOpenApiWebUI.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env tsx
/**
 * Generate WebUI directly from OpenAPI specification
 * No intermediate JSON files needed, directly parse YAML to generate HTML
 */

import * as fs from 'fs';
import * as path from 'path';
import * as yaml from 'js-yaml';
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Read OpenAPI specification
const specPath = path.join(__dirname, '../api/spec-workflow.openapi.yaml');
const spec = yaml.load(fs.readFileSync(specPath, 'utf8')) as any;

// Scenario type definition
interface Scenario {
  id: string;
  title: string;
  description: string;
  responseType: string;
  example: any;
  schema: any;
}

// Extract all scenarios from OpenAPI
function extractScenarios(): Scenario[] {
  const allScenarios: Scenario[] = [];
  
  // First collect all scenarios, without numbering
  const responseSchemas = ['InitResponse', 'CheckResponse', 'SkipResponse', 'ConfirmResponse', 'CompleteTaskResponse'];
  
  for (const schemaName of responseSchemas) {
    const schema = spec.components.schemas[schemaName];
    if (!schema || !schema.examples) continue;

    schema.examples.forEach((example: any, index: number) => {
      allScenarios.push({
        id: `${schemaName.toLowerCase()}-${index + 1}`,
        title: getScenarioTitle(schemaName, example),
        description: getScenarioDescription(schemaName, example),
        responseType: schemaName,
        example: example,
        schema: schema
      });
    });
  }

  // Add error response scenarios
  if (spec['x-error-responses']) {
    for (const [errorType, errorDef] of Object.entries(spec['x-error-responses']) as [string, any][]) {
      allScenarios.push({
        id: `error-${errorType}`,
        title: `Error: ${errorType}`,
        description: 'Error response example',
        responseType: 'ErrorResponse',
        example: { displayText: errorDef.displayText },
        schema: null
      });
    }
  }

  // Reorder scenarios by workflow sequence
  const orderedScenarios: Scenario[] = [];
  
  // 1. Initialization
  const initScenario = allScenarios.find(s => s.responseType === 'InitResponse');
  if (initScenario) orderedScenarios.push(initScenario);
  
  // 2. requirements stage
  const reqNotEdited = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'requirements' && 
    s.example.status?.type === 'not_edited' &&
    !s.example.status?.skipIntent
  );
  if (reqNotEdited) orderedScenarios.push(reqNotEdited);
  
  const reqReadyToConfirm = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'requirements' && 
    s.example.status?.type === 'ready_to_confirm' &&
    !s.example.status?.userApproved
  );
  if (reqReadyToConfirm) orderedScenarios.push(reqReadyToConfirm);
  
  const confirmReq = allScenarios.find(s => 
    s.responseType === 'ConfirmResponse' && 
    s.example.stage === 'requirements'
  );
  if (confirmReq) orderedScenarios.push(confirmReq);
  
  // 3. design stage
  const designNotEdited = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'design' && 
    s.example.status?.type === 'not_edited'
  );
  if (designNotEdited) orderedScenarios.push(designNotEdited);
  
  const designReadyToConfirm = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'design' && 
    s.example.status?.type === 'ready_to_confirm'
  );
  if (designReadyToConfirm) orderedScenarios.push(designReadyToConfirm);
  
  const confirmDesign = allScenarios.find(s => 
    s.responseType === 'ConfirmResponse' && 
    s.example.stage === 'design'
  );
  if (confirmDesign) orderedScenarios.push(confirmDesign);
  
  // 4. tasks stage
  const tasksNotEdited = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'tasks' && 
    s.example.status?.type === 'not_edited'
  );
  if (tasksNotEdited) orderedScenarios.push(tasksNotEdited);
  
  const tasksReadyToConfirm = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'tasks' && 
    s.example.status?.type === 'ready_to_confirm'
  );
  if (tasksReadyToConfirm) orderedScenarios.push(tasksReadyToConfirm);
  
  const confirmTasks = allScenarios.find(s => 
    s.responseType === 'ConfirmResponse' && 
    s.example.stage === 'tasks'
  );
  if (confirmTasks) orderedScenarios.push(confirmTasks);
  
  // 5. Complete task scenarios
  const completeTaskScenarios = allScenarios.filter(s => s.responseType === 'CompleteTaskResponse');
  orderedScenarios.push(...completeTaskScenarios);
  
  // 6. Skip related scenarios
  // First add skip intent detection
  const reqSkipIntent = allScenarios.find(s => 
    s.responseType === 'CheckResponse' && 
    s.example.stage === 'requirements' && 
    s.example.status?.skipIntent
  );
  if (reqSkipIntent) orderedScenarios.push(reqSkipIntent);
  
  // Then add actual skip responses
  const skipScenarios = allScenarios.filter(s => s.responseType === 'SkipResponse');
  orderedScenarios.push(...skipScenarios);
  
  // 7. Error scenarios
  const errorScenarios = allScenarios.filter(s => s.responseType === 'ErrorResponse');
  orderedScenarios.push(...errorScenarios);
  
  // Renumber
  orderedScenarios.forEach((scenario, index) => {
    scenario.title = `${index + 1}. ${scenario.title}`;
  });
  
  return orderedScenarios;
}

// Get scenario title
function getScenarioTitle(schemaName: string, example: any): string {
  const titles: Record<string, (ex: any) => string> = {
    InitResponse: (ex) => ex.success ? 'Initialization Successful' : 'Initialization Scenario',
    CheckResponse: (ex) => {
      if (ex.status?.type === 'not_edited' && ex.status?.skipIntent) return `${ex.stage || 'Stage'} Skip Confirmation`;
      if (ex.status?.type === 'not_edited') return `${ex.stage || 'Stage'} Not Edited`;
      if (ex.status?.type === 'ready_to_confirm' && ex.status?.userApproved) return `${ex.stage || 'Stage'} User Approved`;
      if (ex.status?.type === 'ready_to_confirm') return `${ex.stage || 'Stage'} Ready to Confirm`;
      return 'Check Status';
    },
    SkipResponse: (ex) => `Skip ${ex.stage || 'Stage'}`,
    ConfirmResponse: (ex) => `Confirm ${ex.stage || 'Stage'}`,
    CompleteTaskResponse: (ex) => ex.hasNextTask ? 'Complete Task (Has Next)' : 'Complete Task (All Done)'
  };

  const titleFn = titles[schemaName];
  return titleFn ? titleFn(example) : schemaName;
}

// Get scenario description
function getScenarioDescription(schemaName: string, example: any): string {
  const descriptions: Record<string, string> = {
    InitResponse: 'Response for initializing workflow',
    CheckResponse: 'Response for checking current status',
    SkipResponse: 'Response for skipping stage',
    ConfirmResponse: 'Response for confirming stage completion',
    CompleteTaskResponse: 'Response for marking task as complete'
  };
  return descriptions[schemaName] || schemaName;
}

// Generate HTML
function generateHTML(scenarios: Scenario[]): string {
  const scenarioCards = scenarios.map(scenario => `
    <div class="scenario-card">
      <h3>${scenario.title}</h3>
      <p class="description">${scenario.description}</p>
      
      <div class="response-type">Response Type: <code>${scenario.responseType}</code></div>
      
      <div class="example-section">
        <h4>Example Response:</h4>
        <pre class="example-content">${JSON.stringify(scenario.example, null, 2)}</pre>
      </div>
      
      ${scenario.example.displayText ? `
      <div class="display-text-section">
        <h4>Display Text:</h4>
        <pre class="display-text">${scenario.example.displayText}</pre>
      </div>
      ` : ''}
      
      ${scenario.example.resources ? `
      <div class="resources-section">
        <h4>Included Resources:</h4>
        <ul>
          ${scenario.example.resources.map((r: any) => `<li>${r.ref || r.id || 'Unknown Resource'}</li>`).join('')}
        </ul>
      </div>
      ` : ''}
    </div>
  `).join('');

  return `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spec Workflow - OpenAPI Response Examples</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
            background: #f6f8fa;
            color: #24292e;
            line-height: 1.6;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
        }
        
        h1 {
            text-align: center;
            font-size: 2.5em;
            margin-bottom: 10px;
            color: #0366d6;
        }
        
        .subtitle {
            text-align: center;
            color: #586069;
            margin-bottom: 20px;
            font-size: 1.1em;
        }
        
        .info-box {
            background: #f0f7ff;
            border: 1px solid #c8e1ff;
            border-radius: 6px;
            padding: 16px;
            margin-bottom: 30px;
            text-align: center;
        }
        
        .grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
            gap: 20px;
            margin-bottom: 40px;
        }
        
        .scenario-card {
            background: white;
            border: 1px solid #e1e4e8;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
            transition: all 0.3s ease;
        }
        
        .scenario-card:hover {
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
            transform: translateY(-2px);
        }
        
        .scenario-card h3 {
            color: #0366d6;
            margin-bottom: 10px;
            font-size: 1.3em;
        }
        
        .description {
            color: #586069;
            margin-bottom: 15px;
        }
        
        .response-type {
            background: #f3f4f6;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 0.9em;
            margin-bottom: 15px;
            display: inline-block;
        }
        
        code {
            background: #f3f4f6;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
        }
        
        .example-section, .display-text-section, .resources-section {
            margin-top: 15px;
        }
        
        h4 {
            color: #24292e;
            font-size: 1em;
            margin-bottom: 8px;
        }
        
        pre {
            background: #f6f8fa;
            border: 1px solid #e1e4e8;
            border-radius: 6px;
            padding: 12px;
            overflow-x: auto;
            font-size: 0.85em;
            font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
        }
        
        .example-content {
            max-height: 300px;
            overflow-y: auto;
        }
        
        .display-text {
            background: #f0f9ff;
            border-color: #bae6fd;
            white-space: pre-wrap;
        }
        
        .resources-section ul {
            list-style: none;
            padding-left: 0;
        }
        
        .resources-section li {
            background: #e7f5ff;
            padding: 4px 8px;
            border-radius: 4px;
            margin-bottom: 4px;
            font-size: 0.9em;
        }
        
        .stats {
            text-align: center;
            margin-top: 40px;
            padding: 20px;
            background: white;
            border-radius: 8px;
            border: 1px solid #e1e4e8;
        }
        
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 20px;
            margin-top: 15px;
        }
        
        .stat-item {
            text-align: center;
        }
        
        .stat-number {
            font-size: 2em;
            font-weight: bold;
            color: #0366d6;
        }
        
        .stat-label {
            color: #586069;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Spec Workflow - OpenAPI Response Examples</h1>
        <p class="subtitle">All response scenarios automatically generated from OpenAPI specification</p>
        
        <div class="info-box">
            <p>📍 Data Source: <code>api/spec-workflow.openapi.yaml</code></p>
            <p>🔄 Last Updated: ${new Date().toLocaleString('en-US')}</p>
        </div>
        
        <div class="grid">
            ${scenarioCards}
        </div>
        
        <div class="stats">
            <h2>Statistics</h2>
            <div class="stats-grid">
                <div class="stat-item">
                    <div class="stat-number">${scenarios.length}</div>
                    <div class="stat-label">Total Scenarios</div>
                </div>
                <div class="stat-item">
                    <div class="stat-number">${responseSchemas.length}</div>
                    <div class="stat-label">Response Types</div>
                </div>
                <div class="stat-item">
                    <div class="stat-number">${Object.keys(spec['x-error-responses'] || {}).length}</div>
                    <div class="stat-label">Error Types</div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>`;
}

// Main function
function main() {
  console.log('🔍 Extracting scenarios from OpenAPI specification...');
  
  const scenarios = extractScenarios();
  console.log(`✅ Extracted ${scenarios.length} scenarios`);
  
  const html = generateHTML(scenarios);
  
  const outputPath = path.join(__dirname, '../webui/prompt-grid.html');
  fs.writeFileSync(outputPath, html, 'utf8');
  
  console.log('✅ WebUI generated to:', outputPath);
  console.log('🚀 Open this file in browser to view all response examples');
}

// Define response type list
const responseSchemas = ['InitResponse', 'CheckResponse', 'SkipResponse', 'ConfirmResponse', 'CompleteTaskResponse'];

main();
```

--------------------------------------------------------------------------------
/api/spec-workflow.openapi.yaml:
--------------------------------------------------------------------------------

```yaml
openapi: 3.1.0
info:
  title: Spec Workflow API
  version: 1.0.0
  description: Intelligent Requirements Document Workflow API Specification

servers:
  - url: mcp://spec-workflow

# All operation definitions
paths:
  /spec:
    post:
      operationId: executeWorkflow
      summary: Execute workflow operation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkflowRequest'
      responses:
        '200':
          description: Operation successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowResponse'

# Data model definitions
components:
  schemas:
    # Request definitions
    WorkflowRequest:
      type: object
      required: [action]
      properties:
        featureName:
          type: string
          description: |
            Feature name for the specification (e.g., "用户认证", "order-management").

            **Required for**: init, check, skip, confirm, complete_task operations.

            The system will automatically resolve this to: {specsPath}/{featureName}/

            **For setup_workspace**: Not required - the system uses current working directory as project root.
        action:
          $ref: '#/components/schemas/Action'
    
    Action:
      type: object
      required: [type]
      properties:
        type:
          type: string
          enum: [setup_workspace, init, check, skip, confirm, complete_task]
          description: |
            Operation type to perform:

            - **setup_workspace**: Initialize project workspace (usually not called directly - MCP will automatically guide model to use this when needed)
            - **init**: Initialize a new feature specification
            - **check**: Check current workflow status
            - **skip**: Skip current stage
            - **confirm**: Confirm current stage completion
            - **complete_task**: Mark task(s) as completed

        introduction:
          type: string
          description: Feature introduction (required for init)
        language:
          type: string
          description: User preferred language for documentation (required for setup_workspace)
        taskNumber:
          oneOf:
            - type: string
              description: Single task number to mark as completed
            - type: array
              items:
                type: string
              description: Multiple task numbers for batch completion
          description: Task number(s) to mark as completed (required for complete_task)
      
    # Response definitions
    WorkflowResponse:
      type: object
      required: [result]
      properties:
        result:
          oneOf:
            - $ref: '#/components/schemas/ProjectInitResponse'
            - $ref: '#/components/schemas/InitResponse'
            - $ref: '#/components/schemas/CheckResponse'
            - $ref: '#/components/schemas/SkipResponse'
            - $ref: '#/components/schemas/ConfirmResponse'
            - $ref: '#/components/schemas/BatchCompleteTaskResponse'

    # Project initialization response
    ProjectInitResponse:
      type: object
      required: [success, data, displayText]
      properties:
        success:
          type: boolean
        data:
          type: object
          properties:
            success:
              type: boolean
            needsUserInput:
              type: boolean
            missingParams:
              type: array
              items:
                type: string
            projectRoot:
              type: string
            language:
              type: string
            userGuidelinesCreated:
              type: boolean
            configPath:
              type: string
            error:
              type: string
            errorType:
              type: string
            suggestions:
              type: array
              items:
                type: string
        displayText:
          type: string
      x-dynamic-fields:
        displayText: ["projectRoot", "language", "configPath", "error", "suggestions"]
      x-example-selection:
        criteria:
          - field: "success"
            required: true
          - field: "data.needsUserInput"
            when: "data.needsUserInput === true"
          - field: "data.errorType"
            when: "data.errorType !== undefined"
      examples:
        - success: false
          data:
            success: false
            needsUserInput: true
            missingParams: ["language"]
          displayText: |
            🔧 Project initialization requires more information

            Model: Please ask user for their language preference:

            **Language Preference**: I will use (user's preferred language) for document writing - do you agree?
            - User can respond with: "Chinese", "English", "zh-CN", etc.

            After getting the user's response, model please call setup_workspace again with the language parameter.

            📁 Specification documents will be automatically stored in the .specs folder in the project root directory.

        - success: true
          data:
            success: true
            projectRoot: /project/root
            language: English
            userGuidelinesCreated: true
            configPath: /project/root/.specs/.specs-workflow.json
          displayText: |
            ✅ Project initialization successful!

            📁 Project root path: ${projectRoot}
            📝 Specification documents path: ${projectRoot}/.specs
            🌐 Documentation language: ${language}

            📋 Created User Guidelines files:
            - user-guidelines-requirements.md - User preference guide for requirements documents
            - user-guidelines-design.md - User preference guide for design documents
            - user-guidelines-tasks.md - User preference guide for task documents

            💡 Model: Please ask user to edit these User Guidelines files to guide the model's behavior. These contents will be automatically displayed when showing the corresponding stage writing guides.

            Model: Please ask user to use the init operation to start creating specific feature specification documents.

        - success: false
          data:
            success: false
            error: "Project already initialized"
            errorType: "already_initialized"
            projectRoot: /project/root
            configPath: /project/root/.specs/.specs-workflow.json
            suggestions: ["Delete .specs directory and reinitialize", "Or use existing configuration directly"]
          displayText: |
            ❌ Project already initialized

            📁 Project root path: ${projectRoot}
            📝 Configuration file: ${configPath}

            If user needs to reconfigure, model please ask user to delete the .specs directory first, then run setup_workspace again.

        - success: false
          data:
            success: false
            error: "Initialization failed"
            errorType: "PermissionError"
            suggestions: ["Check directory permissions", "Run with appropriate privileges", "Contact system administrator"]
          displayText: |
            ❌ Project initialization failed

            ${error}

            Suggested solutions:
            ${suggestions}

            If the problem persists, model please ask user to check system permission settings or contact the system administrator.


    # Initialization response
    InitResponse:
      type: object
      required: [success, data, displayText]
      properties:
        success:
          type: boolean
        data:
          type: object
          properties:
            path:
              type: string
            featureName:
              type: string
            nextAction:
              type: string
              const: edit_requirements
        displayText:
          type: string
      x-dynamic-fields:
        displayText: ["featureName", "path", "progress"]
      x-example-selection:
        criteria:
          - field: "success"
            required: true
      examples:
        - success: true
          data:
            path: /specs/new-feature
            featureName: New Feature
            nextAction: edit_requirements
          displayText: |
            ✅ ${featureName} initialized successfully!

            📁 File directory: ${path}
            📝 Created: requirements.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Initialization successful (current) → Next step: write requirements document

            Model please continue with the following actions:
            1. Read the requirements-guide below
            2. First read ${path}/requirements.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Do the requirements look good?", and must not proceed to the design document until getting explicit approval (e.g., "yes", "approved", "looks good", etc.)
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to enter the design phase
            
            Special case - Skip requirements phase:
            - Only consider skipping when user explicitly requests (e.g., "skip requirements document", "go directly to design")
            - Before executing skip operation, the model must:
              1. Explain to user this is an unconventional operation, requirements document is the foundation of the entire development process
              2. Clearly state the risks: design may deviate from actual requirements, increasing rework costs
              3. Ask the user: "Understanding these risks, are you sure you want to skip the requirements phase?"
              4. Only use action.type="skip" after user explicitly confirms

    
    # Check response
    CheckResponse:
      type: object
      required: [stage, progress, status, displayText]
      properties:
        stage:
          $ref: '#/components/schemas/Stage'
        progress:
          $ref: '#/components/schemas/Progress'
        status:
          $ref: '#/components/schemas/Status'
        displayText:
          type: string
      x-dynamic-fields:
        displayText: ["path", "progress", "featureName"]
      x-example-selection:
        criteria:
          - field: "stage"
            required: true
          - field: "status.type"
            required: true
      examples:
        - stage: requirements
          progress:
            overall: 0
            requirements: 0
            design: 0
            tasks: 0
          status:
            type: not_edited
            reason: Requirements document not edited
            readyToConfirm: false
          displayText: |
            📝 requirements.md has not been written yet
            
            📁 File directory: ${path}
            📝 Created: requirements.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Writing requirements document (current) → Next step: use check to verify format
            
            Model please continue with the following actions:
            1. Read the requirements-guide below
            2. First read ${path}/requirements.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Do the requirements look good?", and must not proceed to the design document until getting explicit approval (e.g., "yes", "approved", "looks good", etc.)
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to enter the design phase
            
            Special case - Skip requirements phase:
            - Only consider skipping when user explicitly requests (e.g., "skip requirements document", "go directly to design")
            - Before executing skip operation, the model must:
              1. Explain to user this is an unconventional operation, requirements document is the foundation of the entire development process
              2. Clearly state the risks: design may deviate from actual requirements, increasing rework costs
              3. Ask the user: "Understanding these risks, are you sure you want to skip the requirements phase?"
              4. Only use action.type="skip" after user explicitly confirms

        
        - stage: requirements
          progress:
            overall: 30
            requirements: 100
            design: 0
            tasks: 0
          status:
            type: ready_to_confirm
            readyToConfirm: true
          displayText: |
            ✅ Requirements document check passed!
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Checking requirements document (current) → Next step: get user approval
            
            Model please continue with the following actions:
            1. Ask the user "Do the requirements look good?"
            2. Wait for explicit user approval (e.g., "yes", "approved", "looks good", etc.)
            3. After approval, use the specs-workflow tool with action.type="confirm"
            4. Enter the design phase
        
        - stage: design
          progress:
            overall: 30
            requirements: 100
            design: 0
            tasks: 0
          status:
            type: not_edited
            reason: Design document not edited
          displayText: |
            📝 design.md has not been written yet
            
            📁 File directory: ${path}
            📝 Created: design.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Writing design document (current) → Next step: use check to verify format
            
            Model please continue with the following actions:
            1. Read the design-guide below
            2. First read ${path}/design.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Does the design look good?", and must not proceed to task writing until getting explicit approval (e.g., "yes", "approved", "looks good", etc.)
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to enter the tasks phase
            
            Special case - Skip design phase:
            - Only consider skipping when user explicitly requests (e.g., "skip design document", "go directly to tasks")
            - Before executing skip operation, the model must:
              1. Explain to user this is an unconventional operation, design document helps better plan implementation
              2. Clearly state the risks:
                 - May not fully utilize existing features and components
                 - Implementation direction may deviate from best practices
                 - Code structure may lack overall planning
              3. Ask the user: "Understanding these risks, are you sure you want to skip the design phase?"
              4. Only use action.type="skip" after user explicitly confirms

            
        - stage: design
          progress:
            overall: 60
            requirements: 100
            design: 100
            tasks: 0
          status:
            type: ready_to_confirm
            readyToConfirm: true
          displayText: |
            ✅ Design document check passed!
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Checking design document (current) → Next step: get user approval
            
            Model please continue with the following actions:
            1. Ask the user "Does the design look good?"
            2. Wait for explicit user approval (e.g., "yes", "approved", "looks good", etc.)
            3. Must not proceed to task writing until getting explicit approval
            4. After approval, use the specs-workflow tool with action.type="confirm"
            5. Enter the tasks phase
            
        - stage: tasks
          progress:
            overall: 60
            requirements: 100
            design: 100
            tasks: 0
          status:
            type: not_edited
            reason: Tasks document not edited
          displayText: |
            📝 tasks.md has not been written yet
            
            📁 File directory: ${path}
            📝 Created: tasks.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Writing tasks document (current) → Next step: use check to verify format
            
            Model please continue with the following actions:
            1. Read the task writing guide below
            2. First read ${path}/tasks.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Does the task plan look good?", and continue after getting explicit approval
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to complete the workflow

            
        - stage: tasks
          progress:
            overall: 90
            requirements: 100
            design: 100
            tasks: 100
          status:
            type: ready_to_confirm
            readyToConfirm: true
          displayText: |
            ✅ Tasks document check passed!
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Checking tasks document (current) → Next step: get user approval
            
            The tasks document includes:
            - ✓ Implementation steps
            - ✓ Task breakdown
            - ✓ Dependencies
            - ✓ Acceptance criteria
            
            Model please continue with the following actions:
            1. Ask the user "Does the task plan look good?"
            2. Wait for explicit user approval (e.g., "yes", "approved", "looks good", etc.)
            3. After approval, use the specs-workflow tool with action.type="confirm"
            4. Complete the entire workflow
            
        - stage: completed
          progress:
            overall: 100
            requirements: 100
            design: 100
            tasks: 100
          status:
            type: completed
            readyToConfirm: false
          displayText: |
            ✅ All phases completed!
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Workflow completed ✨
            
            You have successfully completed the entire specification writing process:
            - ✓ Requirements document confirmed
            - ✓ Design document confirmed
            - ✓ Tasks document confirmed
            
            All documents have been written and confirmed.

    # Skip response
    SkipResponse:
      type: object
      required: [stage, skipped, displayText, progress]
      properties:
        stage:
          type: string
        skipped:
          type: boolean
        progress:
          $ref: '#/components/schemas/Progress'
        displayText:
          type: string
      x-dynamic-fields:
        displayText: ["stage", "progress"]
      x-example-selection:
        criteria:
          - field: "stage"
            required: true
      examples:
        - stage: requirements
          skipped: true
          progress:
            overall: 30
            requirements: 100
            design: 0
            tasks: 0
          displayText: |
            ⏭️ Skipped requirements phase

            📊 Overall progress: ${progress}%

            Note: Skipping requirements phase may cause design to deviate from expectations.
            It's recommended to supplement requirements documents later.

            Now entering design phase, model please edit design.md document.

            
        - stage: design
          skipped: true
          progress:
            overall: 60
            requirements: 100
            design: 100
            tasks: 0
          displayText: |
            ⏭️ Skipped design phase

            📊 Overall progress: ${progress}%

            Model please inform the user of the following risks:
            ⚠️ Warning: Skipping design phase may cause the following problems:
            - Lack of architectural design may cause implementation direction to deviate
            - May not fully utilize existing features and components
            - Code structure may lack overall planning

            It's recommended to gradually supplement design thinking during implementation.
            Now entering tasks phase, model please edit tasks.md document.

            
        - stage: tasks
          skipped: true
          progress:
            overall: 60
            requirements: 100
            design: 100
            tasks: 0
          displayText: |
            ⏭️ Skipped tasks phase

            📊 Overall progress: ${progress}%

            ⚠️ Important Note: Tasks document is essential for development
            - The tasks document defines the specific implementation steps
            - Without it, developers lack clear guidance on what to build
            - If user is not ready to develop now, user can skip temporarily

            To write the tasks document later:
            1. Use action.type="check" to review current status
            2. Edit the tasks.md document with implementation details
            3. Confirm when ready to start development

            The workflow is now complete. User can return to write tasks when ready to begin development.

    # Confirm response  
    ConfirmResponse:
      type: object
      required: [stage, confirmed, nextStage, displayText, progress]
      properties:
        stage:
          type: string
        confirmed:
          type: boolean
        nextStage:
          type: string
          nullable: true
        progress:
          $ref: '#/components/schemas/Progress'
        displayText:
          type: string
      x-dynamic-fields:
        displayText: ["stage", "nextStage", "progress", "path"]
      x-example-selection:
        criteria:
          - field: "stage"
            required: true
      examples:
        - stage: requirements
          confirmed: true
          nextStage: design
          progress:
            overall: 30
            requirements: 100
            design: 0
            tasks: 0
          displayText: |
            ✅ Requirements confirmed, entering design phase!
            
            📁 File directory: ${path}
            📝 Created: design.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Writing design document (current) → Next step: use check to verify format
            
            Model please continue with the following actions:
            1. Read the design-guide below
            2. First read ${path}/design.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Does the design look good?", and must not proceed to task writing until getting explicit approval (e.g., "yes", "approved", "looks good", etc.)
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to enter the tasks phase
            
            Special case - Skip design phase:
            - Only consider skipping when user explicitly requests (e.g., "skip design document", "go directly to tasks")
            - Before executing skip operation, the model must:
              1. Explain to user this is an unconventional operation, design document helps better plan implementation
              2. Clearly state the risks:
                 - May not fully utilize existing features and components
                 - Implementation direction may deviate from best practices
                 - Code structure may lack overall planning
              3. Ask the user: "Understanding these risks, are you sure you want to skip the design phase?"
              4. Only use action.type="skip" after user explicitly confirms

        
        - stage: design
          confirmed: true
          nextStage: tasks
          progress:
            overall: 60
            requirements: 100
            design: 100
            tasks: 0
          displayText: |
            ✅ Design confirmed, entering tasks phase!
            
            📁 File directory: ${path}
            📝 Created: tasks.md
            
            📊 Overall progress: ${progress}%
            🔄 Current status: Writing tasks document (current) → Next step: use check to verify format
            
            Model please continue with the following actions:
            1. Read the task writing guide below
            2. First read ${path}/tasks.md, then start writing the document
            3. After completing the document, use specs-workflow tool with action.type="check" to check the document format
            4. When check passes, the model must ask the user "Does the task plan look good?", and continue after getting explicit approval
            5. When the user approves, the model must use the specs-workflow tool with action.type="confirm" to complete the workflow

            
        - stage: tasks
          confirmed: true
          nextStage: null
          progress:
            overall: 100
            requirements: 100
            design: 100
            tasks: 100
          displayText: |
            ✅ Tasks confirmed, workflow completed!
            
            📊 Overall progress: ${progress}%
            🔄 Current status: All documents completed ✨
            
            Congratulations! You have completed the entire specification writing process:
            - ✓ Requirements document confirmed
            - ✓ Design document confirmed
            - ✓ Tasks document confirmed



    # Batch complete tasks response
    BatchCompleteTaskResponse:
      type: object
      required: [success, displayText]
      properties:
        success:
          type: boolean
          description: Whether the batch operation succeeded
        completedTasks:
          type: array
          items:
            type: string
          description: Task numbers that were actually completed in this operation
        alreadyCompleted:
          type: array
          items:
            type: string
          description: Task numbers that were already completed before this operation
        failedTasks:
          type: array
          items:
            type: object
            required: [taskNumber, reason]
            properties:
              taskNumber:
                type: string
                description: The task number that failed
              reason:
                type: string
                description: The reason why the task could not be completed
          description: Tasks that could not be completed with reasons
        results:
          type: array
          items:
            type: object
            required: [taskNumber, success]
            properties:
              taskNumber:
                type: string
              success:
                type: boolean
              status:
                type: string
                enum: [completed, already_completed, failed]
          description: Detailed results for each task in the batch
        nextTask:
          type: object
          nullable: true
          properties:
            number:
              type: string
            description:
              type: string
          description: Information about the next uncompleted task
        hasNextTask:
          type: boolean
          description: Whether there are more tasks to complete
        displayText:
          type: string
          description: Human-readable message about the batch operation
      examples:
        - success: true
          completedTasks: ["1.1", "1.2", "2.1"]
          alreadyCompleted: ["1.3"]
          failedTasks: []
          results:
            - taskNumber: "1.1"
              success: true
              status: completed
            - taskNumber: "1.2"
              success: true
              status: completed
            - taskNumber: "1.3"
              success: true
              status: already_completed
            - taskNumber: "2.1"
              success: true
              status: completed
          nextTask:
            number: "2.2"
            description: "Implement error handling"
          hasNextTask: true
          displayText: |
            ✅ Batch task processing succeeded

            Completed tasks:
            - 1.1
            - 1.2
            - 1.3
            - 2.1

            ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

            📋 Next task to implement:
            - [ ] 2.2. Implement error handling
              - *Goal*: Add comprehensive error handling to the authentication system
              - *Details*: Implement try-catch blocks, error logging, and user-friendly error messages
              - *Requirements*: 1.2, 2.3

            ⚠️ IMPORTANT INSTRUCTIONS FOR MODEL:
            1. [TASK FOCUS] Model MUST follow the workflow instructions to complete the specified task, not plan tasks independently.

            2. [PROGRESS TRACKING] After completing each subtask, model MUST use the specs-workflow tool with complete_task action to mark it complete. DO NOT edit task.md directly.
            3. [WORKFLOW] Implement task → Call complete_task to mark complete → Get next task automatically → Continue implementation

            Model: Please confirm your preferred execution mode:

            **Confirmation Required**: The model will complete tasks one by one, requiring your confirmation before proceeding to the next task.

            **Automatic Mode**: The model will complete tasks sequentially until all tasks are finished without requiring confirmation for each step.

            After you confirm your preferred approach, I will execute the development work for ${firstSubtask} according to your chosen mode, and immediately use complete_task after completing this specified task to proceed to the next one.
        - success: false
          completedTasks: []
          alreadyCompleted: []
          failedTasks:
            - taskNumber: "2.1"
              reason: "Has uncompleted subtasks"
            - taskNumber: "99"
              reason: "Task does not exist"
          results: []
          nextTask: null
          hasNextTask: false
          displayText: |
            ❌ Batch task completion failed
            
            The following tasks cannot be completed:
            - 2.1: Has uncompleted subtasks
            - 99: Task does not exist
            
            Model: Please ask user to resolve these issues and try again.

    # Common type definitions
    Stage:
      type: string
      enum: [requirements, design, tasks, completed]
      description: Current stage
    
    Progress:
      type: object
      required: [overall, requirements, design, tasks]
      properties:
        overall:
          type: integer
          minimum: 0
          maximum: 100
          description: Overall progress percentage
        requirements:
          type: integer
          minimum: 0
          maximum: 100
          description: Requirements phase progress
        design:
          type: integer
          minimum: 0
          maximum: 100
          description: Design phase progress
        tasks:
          type: integer
          minimum: 0
          maximum: 100
          description: Tasks phase progress
      x-progress-rules:
        - description: Requirements phase accounts for 30%
          formula: requirements * 0.3
        - description: Design phase accounts for 30%
          formula: design * 0.3
        - description: Tasks phase accounts for 40%
          formula: tasks * 0.4
    
    Status:
      type: object
      required: [type]
      properties:
        type:
          type: string
          enum: [not_started, not_edited, in_progress, ready_to_confirm, confirmed, completed]
        reason:
          type: string
        readyToConfirm:
          type: boolean
    
    Resource:
      type: object
      required: [id, content]
      properties:
        id:
          type: string
          description: Resource identifier
        content:
          type: string
          description: Resource content (Markdown format)
    
    ResourceRef:
      type: object
      required: [uri, mimeType]
      properties:
        uri:
          type: string
          description: Resource URI
        title:
          type: string
          description: Optional resource title
        mimeType:
          type: string
          description: Resource MIME type
        text:
          type: string
          description: Optional resource text content

# Error response definitions
x-error-responses:
  invalidPath:
    displayText: |
      ❌ Error: Invalid specification directory
      
      Path ${path} does not exist or is not a valid specification directory.
      Model: Please ask user to ensure the path is correct and has been initialized.
  
  alreadyInitialized:
    displayText: |
      ❌ Project already exists
      
      📁 Path: ${path}
      📄 Existing files: ${existingFiles}
      
      Model: Please ask user to choose one of the following actions:
      1. Delete existing files and reinitialize: rm -rf ${path}/*
      2. Initialize in a new directory: use a different path parameter
      3. Continue editing existing project: use action.type="check" to check project status and read existing documents to see if adjustments are needed
  
  missingParameters:
    displayText: |
      ❌ Error: Missing required parameters
      
      ${action} operation requires the following parameters:
      ${missingParams}
      
      Model: Please ask user to provide complete parameters and try again.
  
  documentNotEdited:
    displayText: |
      ❌ Error: Document not ready for confirmation
      
      📄 ${documentName} still contains template markers and has not been edited.
      
      The document appears to be in its initial state with placeholder content.
      Before confirming, you must edit the document and then use action.type="check" to verify the document is ready.
      
      If you want to skip writing this document:
      - Use action.type="skip" to bypass this stage
      - Note: Skipping important documents may impact project quality
  
  taskAlreadyCompleted:
    displayText: |
      ℹ️ Task ${taskNumber} is already completed
      
      This task has already been marked as completed.
      No action needed.
  
  taskNotFound:
    displayText: |
      ❌ Error: Task ${taskNumber} not found

      Model: Please ask user to check if the task number is correct.

  projectNotInitialized:
    displayText: |
      🔧 Project not yet initialized

      Before using other features, model please complete project initialization first:

      **Step 1: Call workspace setup**
      ```json
      {
        "path": "${path}",
        "action": {
          "type": "setup_workspace"
        }
      }
      ```

      The system will guide you through language preference setup.

      **Why initialization is needed?**
      - Establish a single configuration source to ensure team collaboration consistency
      - Create User Guidelines to let you guide model behavior with natural language
      - Create .specs folder in project root for easy management and maintenance

      After initialization is complete, model can use init, check, confirm and other features.

  invalidConfig:
    displayText: |
      ⚠️ Invalid project configuration

      Configuration file found but content is invalid or path is unavailable. Model please reinitialize:

      ```json
      {
        "path": "${path}",
        "action": {
          "type": "setup_workspace",
          "language": "your language preference"
        }
      }
      ```

      The system will automatically override invalid configuration, no need to delete manually.


# Shared resource definitions
x-shared-resources:
  # Template editing instructions
  template-edit-instruction:
    uri: template-edit-instruction
    title: Template Editing Instructions
    mimeType: text/plain
    text: |
      ⚠️ Important: Model please delete all content with <template-*> tags, then start writing formal content.
      These tags are used to detect whether the document has been edited. Keeping these tags will cause the document to be judged as "not edited" status.
  
  # Requirements document example (reuses existing requirements-guide)
  requirements-template-example:
    uri: requirements-template-example
    title: Requirements Document Example
    mimeType: text/plain
    text: |
      Example requirements:
      ### Core Features
      - User authentication system
        - As a user, I want to register an account to use system features
        - As a user, I want to log in securely to access personal data
        
      ### Acceptance Criteria
      - [ ] Users can register using email
      - [ ] Password strength meets security requirements
      - [ ] Account locks for 15 minutes after 3 failed login attempts
  
  # Design document example (reuses existing design-guide)
  design-template-example:
    uri: design-template-example
    title: Design Document Example
    mimeType: text/plain
    text: |
      Example design:
      ### Technical Architecture
      - Frontend: React + TypeScript
      - Backend: Node.js + Express
      - Database: PostgreSQL
      - Cache: Redis
      
      ### Authentication Flow
      ```mermaid
      sequenceDiagram
          User->>Frontend: Enter credentials
          Frontend->>Backend: POST /auth/login
          Backend->>Database: Verify user
          Database->>Backend: Return user information
          Backend->>Frontend: Return JWT Token
      ```
  
  # Tasks document example (reuses existing tasks-guide)
  tasks-template-example:
    uri: tasks-template-example
    title: Task List Example
    mimeType: text/plain
    text: |
      Example tasks:
      ### Phase 1: Foundation Setup
      - [ ] Initialize project structure (2h)
      - [ ] Configure development environment (1h)
      - [ ] Set up database connection (2h)
      
      ### Phase 2: Core Features
      - [ ] Implement user registration API (4h)
        - Dependency: Database connection
      - [ ] Implement login authentication (4h)
        - Dependency: User registration API
  
  requirements-guide:
    uri: requirements-guide
    title: Requirements Document Writing Guide
    mimeType: text/markdown
    text: |
      # Requirements Gathering Generation
      
      Workflow Stage: Requirements Gathering
      
      First, generate an initial set of requirements in EARS format based on the feature idea, then iterate with the user to refine them until they are complete and accurate.
      
      Don't focus on code exploration in this phase. Instead, just focus on writing requirements which will later be turned into a design.
      
      **Constraints:**
      
      - The model MUST write the requirements document in the user's preferred regional language
      - The model MUST edit the existing requirements.md file by removing the SPEC-MARKER comment block
      - The model MUST fill in the requirements document based on the user's rough idea WITHOUT asking sequential questions first
      - The model MUST format the requirements.md document with:
        - A clear introduction section that summarizes the feature
        - A hierarchical numbered list of requirements where each contains:
          - A user story in the format "As a [role], I want [feature], so that [benefit]"
          - A numbered list of acceptance criteria in EARS format (Easy Approach to Requirements Syntax)
      - The model SHOULD consider edge cases, user experience, technical constraints, and success criteria in the initial requirements
      - After updating the requirement document, the model MUST ask the user "Do the requirements look good? If so, we can move on to the design." 
      - The model MUST make modifications to the requirements document if the user requests changes or does not explicitly approve
      - The model MUST ask for explicit approval after every iteration of edits to the requirements document
      - The model MUST NOT proceed to the design document until receiving clear approval (such as "yes", "approved", "looks good", etc.)
      - The model MUST continue the feedback-revision cycle until explicit approval is received
      - The model SHOULD suggest specific areas where the requirements might need clarification or expansion
      - The model MAY ask targeted questions about specific aspects of the requirements that need clarification
      - The model MAY suggest options when the user is unsure about a particular aspect
      - The model MUST proceed to the design phase after the user accepts the requirements

  design-guide:
    uri: design-guide
    title: Design Document Writing Guide
    mimeType: text/markdown
    text: |
      # Design Document Creation Generation
      
      Workflow Stage: Design Document Creation
      
      After the user approves the Requirements, you should develop a comprehensive design document based on the feature requirements, conducting necessary research during the design process.
      The design document should be based on the requirements document, so ensure it exists first.
      
      **Constraints:**
      
      - The model MUST write the design document in the user's preferred regional language
      - The model MUST edit the existing design.md file by removing the SPEC-MARKER comment block
      - The model MUST identify areas where research is needed based on the feature requirements
      - The model MUST conduct research and build up context in the conversation thread
      - The model SHOULD NOT create separate research files, but instead use the research as context for the design and implementation plan
      - The model MUST summarize key findings that will inform the feature design
      - The model SHOULD cite sources and include relevant links in the conversation
      - The model MUST fill in the detailed design document in the existing design.md file
      - The model MUST incorporate research findings directly into the design process
      - The model MUST include the following sections in the design document:
        - Overview
        - Architecture
        - Components and Interfaces
        - Data Models
        - Error Handling
        - Testing Strategy
      - The model SHOULD include diagrams or visual representations when appropriate (use Mermaid for diagrams if applicable)
      - The model MUST ensure the design addresses all feature requirements identified during the clarification process
      - The model SHOULD highlight design decisions and their rationales
      - The model MAY ask the user for input on specific technical decisions during the design process
      - After updating the design document, the model MUST ask the user "Does the design look good? If so, we can move on to the implementation plan."
      - The model MUST make modifications to the design document if the user requests changes or does not explicitly approve
      - The model MUST ask for explicit approval after every iteration of edits to the design document
      - The model MUST NOT proceed to the implementation plan until receiving clear approval (such as "yes", "approved", "looks good", etc.)
      - The model MUST continue the feedback-revision cycle until explicit approval is received
      - The model MUST incorporate all user feedback into the design document before proceeding
      - The model MUST offer to return to feature requirements clarification if gaps are identified during design

  tasks-guide:
    uri: tasks-guide
    title: Task List Writing Guide
    mimeType: text/markdown
    text: |
      # Implementation Planning Generation
      
      Workflow Stage: Implementation Planning
      
      After the user approves the Design, create an actionable implementation plan with a checklist of coding tasks based on the requirements and design.
      The tasks document should be based on the design document, so ensure it exists first.
      
      **Constraints:**
      
      - The model MUST write the tasks document in the user's preferred regional language
      - The model MUST edit the existing tasks.md file by removing the SPEC-MARKER comment block
      - The model MUST return to the design step if the user indicates any changes are needed to the design
      - The model MUST return to the requirement step if the user indicates that we need additional requirements
      - The model MUST fill in the implementation plan in the existing tasks.md file
      - The model MUST use the following specific instructions when creating the implementation plan: Convert the feature design into a series of prompts for a code-generation LLM that will implement each step in a test-driven manner. Prioritize best practices, incremental progress, and early testing, ensuring no big jumps in complexity at any stage. Make sure that each prompt builds on the previous prompts, and ends with wiring things together. There should be no hanging or orphaned code that isn't integrated into a previous step. Focus ONLY on tasks that involve writing, modifying, or testing code.
      - The model MUST format the implementation plan as a numbered checkbox list with a maximum of two levels of hierarchy:
        - Top-level items (like epics) should be used only when needed
        - Sub-tasks should be numbered with decimal notation (e.g., 1.1, 1.2, 2.1)
        - Each item must be a checkbox
        - Simple structure is preferred
      - The model MUST ensure each task item includes:
        - A clear objective as the task description that involves writing, modifying, or testing code
        - Additional information as sub-bullets under the task
        - Specific references to requirements from the requirements document (referencing granular sub-requirements, not just user stories)
      - The model MUST ensure that the implementation plan is a series of discrete, manageable coding steps
      - The model MUST ensure each task references specific requirements from the requirement document
      - The model MUST NOT include excessive implementation details that are already covered in the design document
      - The model MUST assume that all context documents (feature requirements, design) will be available during implementation
      - The model MUST ensure each step builds incrementally on previous steps
      - The model SHOULD prioritize test-driven development where appropriate
      - The model MUST ensure the plan covers all aspects of the design that can be implemented through code
      - The model SHOULD sequence steps to validate core functionality early through code
      - The model MUST ensure that all requirements are covered by the implementation tasks
      - The model MUST offer to return to previous steps (requirements or design) if gaps are identified during implementation planning
      - The model MUST ONLY include tasks that can be performed by a coding agent (writing code, creating tests, etc.)
      - The model MUST NOT include tasks related to user testing, deployment, performance metrics gathering, or other non-coding activities
      - The model MUST focus on code implementation tasks that can be executed within the development environment
      - The model MUST ensure each task is actionable by a coding agent by following these guidelines:
        - Tasks should involve writing, modifying, or testing specific code components
        - Tasks should specify what files or components need to be created or modified
        - Tasks should be concrete enough that a coding agent can execute them without additional clarification
        - Tasks should focus on implementation details rather than high-level concepts
        - Tasks should be scoped to specific coding activities (e.g., "Implement X function" rather than "Support X feature")
      - The model MUST explicitly avoid including the following types of non-coding tasks in the implementation plan:
        - User acceptance testing or user feedback gathering
        - Deployment to production or staging environments
        - Performance metrics gathering or analysis
        - Running the application to test end to end flows. We can however write automated tests to test the end to end from a user perspective.
        - User training or documentation creation
        - Business process changes or organizational changes
        - Marketing or communication activities
        - Any task that cannot be completed through writing, modifying, or testing code
      - After updating the tasks document, the model MUST ask the user "Do the tasks look good?" 
      - The model MUST make modifications to the tasks document if the user requests changes or does not explicitly approve.
      - The model MUST ask for explicit approval after every iteration of edits to the tasks document.
      - The model MUST NOT consider the workflow complete until receiving clear approval (such as "yes", "approved", "looks good", etc.).
      - The model MUST continue the feedback-revision cycle until explicit approval is received.
      - The model MUST stop once the task document has been approved.
      
      **This workflow is ONLY for creating design and planning artifacts. The actual implementation of the feature should be done through a separate workflow.**
      
      - The model MUST NOT attempt to implement the feature as part of this workflow
      - The model MUST clearly communicate to the user that this workflow is complete once the design and planning artifacts are created
      - When the model receives the confirmation response for tasks stage, it will include the first uncompleted task
      - The model MUST present this task to the user and ask: "Ready to start the first task?"
      - The model MUST begin implementation only after user confirmation

# Global configuration
x-global-config:
  icons:
    exists: "✅"
    not_exists: "❌"
    edited: "(edited)"
    not_edited: "(pending edit)"
    not_created: "(not created)"
    confirmed: "(confirmed)"
    skipped: "(skipped)"
  
  status_text:
    not_created: "Not created"
    not_edited: "Waiting for edit"
    has_format_issues: "Has format issues"
    not_confirmed: "Pending confirmation"
    completed: "Completed"
    skipped: "Skipped"
  
  stage_names:
    requirements: "Requirements Document"
    design: "Design Document"  
    tasks: "Task List"
    completed: "Completed"
  
  file_names:
    requirements: "Requirements.md"
    design: "Design.md"
    tasks: "Tasks.md"

# Document templates
x-document-templates:
  requirements:
    title: "${featureName} - Requirements Document"
    sections:
      - name: "Project Background"
        content: "${introduction}"
      - name: "Core Features"
        placeholder: "## Core Features\n\n<template-requirements>\nDescribe the core functionality of the feature here.\n</template-requirements>"
      - name: "User Stories"
        placeholder: "## User Stories\n\n<template-requirements>\n- As a [user type], I want [feature], so that [benefit]\n</template-requirements>"
      - name: "Acceptance Criteria"
        placeholder: "## Acceptance Criteria\n\n<template-requirements>\n- [ ] Criterion 1\n- [ ] Criterion 2\n</template-requirements>"
      - name: "Non-functional Requirements"
        placeholder: "## Non-functional Requirements\n\n<template-requirements>\n- Performance requirements\n- Security requirements\n- Compatibility requirements\n</template-requirements>"
  
  design:
    title: "${featureName} - Design Document"
    sections:
      - name: "Overview"
        placeholder: "## Overview\n\n<template-design>\nProvide a high-level overview of the design approach.\n</template-design>"
      - name: "Architecture"
        placeholder: "## Architecture\n\n<template-design>\nDescribe the overall architecture and key components.\n</template-design>"
      - name: "Components and Interfaces"
        placeholder: "## Components and Interfaces\n\n<template-design>\nDetail the main components and their interfaces.\n</template-design>"
      - name: "Data Models"
        placeholder: "## Data Models\n\n<template-design>\nDefine the data structures and models.\n</template-design>"
      - name: "Error Handling"
        placeholder: "## Error Handling\n\n<template-design>\nExplain error handling strategies.\n</template-design>"
      - name: "Testing Strategy"
        placeholder: "## Testing Strategy\n\n<template-design>\nOutline the testing approach.\n</template-design>"
  
  tasks:
    title: "${featureName} - Task List"
    sections:
      - name: "Implementation Tasks"
        placeholder: "## Implementation Tasks\n\n<template-tasks>\n- [ ] 1. **Main Task 1**\n    - [ ] 1.1. Subtask description\n        - *Goal*: Describe what this task aims to achieve\n        - *Details*: Implementation details and considerations\n        - *Requirements*: Reference to requirement numbers\n    - [ ] 1.2. Subtask description\n        - *Goal*: Describe what this task aims to achieve\n        - *Details*: Implementation details and considerations\n        - *Requirements*: Reference to requirement numbers\n- [ ] 2. **Main Task 2**\n    - [ ] 2.1. Subtask description\n        - *Goal*: Describe what this task aims to achieve\n        - *Details*: Implementation details and considerations\n        - *Requirements*: Reference to requirement numbers\n</template-tasks>"
      - name: "Task Dependencies"
        placeholder: "## Task Dependencies\n\n<template-tasks>\n- Task 1 must be completed before Task 2\n- Tasks 2.1 and 2.2 can be executed in parallel\n- Task 3 depends on completion of Tasks 1 and 2\n</template-tasks>"
      - name: "Estimated Timeline"
        placeholder: "## Estimated Timeline\n\n<template-tasks>\n- Task 1: 8 hours\n- Task 2: 12 hours\n- Task 3: 6 hours\n- **Total: 26 hours**\n</template-tasks>"
  
  skipped:
    title: "${featureName} - ${stageName}"
    sections:
      - name: "Status"
        content: "[Skipped] - This stage has been skipped"
      - name: "Reason"
        content: "User chose to skip this stage and proceed directly to next step."
      - name: "Note"
        content: "To supplement this document, model please delete [Skipped] marker and fill in corresponding content."

# Task guidance template
x-task-guidance-template:
  separator: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
  header: "📋 Next task to implement:"
  instructions:
    prefix: "⚠️ IMPORTANT INSTRUCTIONS FOR MODEL:"
    taskFocus: "1. [TASK FOCUS] Model MUST follow the workflow instructions to complete the specified task, not plan tasks independently."
    progressTracking: "2. [PROGRESS TRACKING] After completing each subtask, model MUST use the specs-workflow tool with complete_task action to mark it complete. DO NOT edit task.md directly."
    workflow: "3. [WORKFLOW] Implement task → Call complete_task to mark complete → Get next task automatically → Continue implementation"
  prompts:
    firstTask: "Model: Please ask user \"Would you prefer to complete tasks one by one and report progress for your confirmation, or complete tasks sequentially and mark them as done until all tasks are finished at once?\" After user confirms, execute the development work for ${firstSubtask} according to user's preferred approach, and immediately use complete_task after completing this specified task."
    nextTask: "Model: Please execute the development work for ${firstSubtask} and immediately use complete_task after completing this specified task."
    continueTask: "Model: Please execute the development work for ${firstSubtask} and immediately use complete_task after completing this specified task."
    batchContinue: "Model: Please execute the development work for ${firstSubtask} and immediately use complete_task after completing this specified task."
  completionMessages:
    taskCompleted: "✅ Task ${taskNumber} marked as completed!"
    allCompleted: "🎉 Congratulations! All tasks completed!\n\nYou have successfully completed all implementation tasks. Project implementation phase completed."
    alreadyCompleted: "ℹ️ Task ${taskNumber} is already completed\n\nThis task has already been marked as completed."
    batchSucceeded: "✅ Batch task processing succeeded"
    batchCompleted: "ℹ️ Batch task processing completed"
  batchLabels:
    completedTasks: "Completed tasks"

```