From 169f218f7a52f007704d2741ff70d042ecfc3023 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sun, 28 Dec 2025 19:27:34 +0800 Subject: [PATCH] feat(discovery): enhance discovery index reading and issue exporting - Improved the reading of the discovery index by adding a fallback mechanism to scan directories for discovery folders if the index.json is invalid or missing. - Added sorting of discoveries by creation time in descending order. - Enhanced the `appendToIssuesJsonl` function to include deduplication logic for issues based on ID and source finding ID. - Updated the discovery route handler to reflect the number of issues added and skipped during export. - Introduced UI elements for selecting and deselecting findings in the dashboard. - Added CSS styles for exported findings and action buttons. - Implemented search functionality for filtering findings based on title, file, and description. - Added internationalization support for new UI elements. - Created scripts for automated API extraction from various project types, including FastAPI and TypeScript. - Documented the API extraction process and library bundling instructions. --- .claude/commands/issue/discover.md | 458 ++++-------------- .claude/commands/issue/new.md | 14 +- .claude/commands/issue/plan.md | 5 +- .claude/skills/software-manual/SKILL.md | 39 +- .../phases/02.5-api-extraction.md | 161 ++++++ .../phases/03-parallel-analysis.md | 104 ++-- .../phases/05-html-assembly.md | 36 +- .../software-manual/scripts/api-extractor.md | 245 ++++++++++ .../scripts/bundle-libraries.md | 85 ++++ .../software-manual/scripts/extract_apis.py | 270 +++++++++++ .../templates/css/wiki-base.css | 157 ++++-- .../templates/tiddlywiki-shell.html | 11 +- .../schemas/discovery-state-schema.json | 167 ++++--- .../schemas/issues-jsonl-schema.json | 128 ++++- ccw/src/core/routes/discovery-routes.ts | 163 ++++++- .../templates/dashboard-css/34-discovery.css | 64 +++ ccw/src/templates/dashboard-js/i18n.js | 10 + .../dashboard-js/views/issue-discovery.js | 97 +++- 18 files changed, 1602 insertions(+), 612 deletions(-) create mode 100644 .claude/skills/software-manual/phases/02.5-api-extraction.md create mode 100644 .claude/skills/software-manual/scripts/api-extractor.md create mode 100644 .claude/skills/software-manual/scripts/bundle-libraries.md create mode 100644 .claude/skills/software-manual/scripts/extract_apis.py diff --git a/.claude/commands/issue/discover.md b/.claude/commands/issue/discover.md index e520f49b..b66f127b 100644 --- a/.claude/commands/issue/discover.md +++ b/.claude/commands/issue/discover.md @@ -59,19 +59,20 @@ Phase 2: Interactive Perspective Selection Phase 3: Parallel Perspective Analysis ├─ Launch N @cli-explore-agent instances (one per perspective) ├─ Security & Best-Practices auto-trigger Exa research - ├─ Generate perspective JSON + markdown reports + ├─ Agent writes perspective JSON, returns summary └─ Update discovery-progress.json Phase 4: Aggregation & Prioritization - ├─ Load all perspective JSON files + ├─ Collect agent return summaries + ├─ Load perspective JSON files ├─ Merge findings, deduplicate by file+line - ├─ Calculate priority scores based on impact/urgency - └─ Generate candidate issue list + └─ Calculate priority scores -Phase 5: Issue Generation +Phase 5: Issue Generation & Summary ├─ Convert high-priority discoveries to issue format - ├─ Write to discovery-issues.jsonl (preview) - └─ Generate summary report + ├─ Write to discovery-issues.jsonl + ├─ Generate single summary.md from agent returns + └─ Update discovery-state.json to complete ``` ## Perspectives @@ -96,18 +97,14 @@ When no `--perspectives` flag is provided, the command uses AskUserQuestion: ```javascript AskUserQuestion({ questions: [{ - question: "Select discovery perspectives (multi-select)", - header: "Perspectives", - multiSelect: true, + question: "Select primary discovery focus:", + header: "Focus", + multiSelect: false, options: [ - { label: "bug", description: "Potential bugs (edge cases, null checks, resource leaks)" }, - { label: "ux", description: "User experience (error messages, loading states, accessibility)" }, - { label: "test", description: "Test coverage (missing tests, edge cases, integration gaps)" }, - { label: "quality", description: "Code quality (complexity, duplication, naming)" }, - { label: "security", description: "Security issues (auto-enables Exa research)" }, - { label: "performance", description: "Performance (N+1 queries, memory, caching)" }, - { label: "maintainability", description: "Maintainability (coupling, tech debt, extensibility)" }, - { label: "best-practices", description: "Best practices (auto-enables Exa research)" } + { label: "Bug + Test + Quality", description: "Quick scan: potential bugs, test gaps, code quality (Recommended)" }, + { label: "Security + Performance", description: "System audit: security issues, performance bottlenecks" }, + { label: "Maintainability + Best-practices", description: "Long-term health: coupling, tech debt, conventions" }, + { label: "Full analysis", description: "All 7 perspectives (comprehensive, takes longer)" } ] }] }) @@ -138,37 +135,18 @@ const discoveryId = `DSC-${formatDate(new Date(), 'YYYYMMDD-HHmmss')}`; const outputDir = `.workflow/issues/discoveries/${discoveryId}`; await mkdir(outputDir, { recursive: true }); await mkdir(`${outputDir}/perspectives`, { recursive: true }); -await mkdir(`${outputDir}/reports`, { recursive: true }); -// Step 4: Initialize discovery state +// Step 4: Initialize unified discovery state (merged state+progress) await writeJson(`${outputDir}/discovery-state.json`, { discovery_id: discoveryId, target_pattern: targetPattern, - metadata: { - created_at: new Date().toISOString(), - resolved_files: resolvedFiles, - perspectives: [], // filled after selection - external_research_enabled: false - }, phase: "initialization", - perspectives_completed: [], - total_findings: 0, - priority_distribution: { critical: 0, high: 0, medium: 0, low: 0 }, - issues_generated: 0 -}); - -// Step 5: Initialize progress tracking -await writeJson(`${outputDir}/discovery-progress.json`, { - discovery_id: discoveryId, - last_update: new Date().toISOString(), - phase: "initialization", - progress: { - perspective_analysis: { total: 0, completed: 0, in_progress: 0, percent_complete: 0 }, - external_research: { enabled: false, completed: false }, - aggregation: { completed: false }, - issue_generation: { completed: false } - }, - agent_status: [] + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + target: { files_count: { total: resolvedFiles.length }, project: {} }, + perspectives: [], // filled after selection: [{name, status, findings}] + external_research: { enabled: false, completed: false }, + results: { total_findings: 0, issues_generated: 0, priority_distribution: {} } }); ``` @@ -182,34 +160,13 @@ if (args.perspectives) { selectedPerspectives = args.perspectives.split(',').map(p => p.trim()); } else { // Interactive selection via AskUserQuestion - const response = await AskUserQuestion({ - questions: [{ - question: "Select discovery perspectives to analyze:", - header: "Perspectives", - multiSelect: true, - options: PERSPECTIVE_OPTIONS - }] - }); + const response = await AskUserQuestion({...}); selectedPerspectives = parseSelectedPerspectives(response); } -// Validate perspectives -const validPerspectives = ['bug', 'ux', 'test', 'quality', 'security', 'performance', 'maintainability', 'best-practices']; -for (const p of selectedPerspectives) { - if (!validPerspectives.includes(p)) { - throw new Error(`Invalid perspective: ${p}`); - } -} - -// Determine if Exa is needed -const exaEnabled = selectedPerspectives.includes('security') || - selectedPerspectives.includes('best-practices') || - args.external; - -// Update state +// Validate and update state await updateDiscoveryState(outputDir, { 'metadata.perspectives': selectedPerspectives, - 'metadata.external_research_enabled': exaEnabled, phase: 'parallel' }); ``` @@ -219,40 +176,25 @@ await updateDiscoveryState(outputDir, { Launch N agents in parallel (one per selected perspective): ```javascript -// Launch agents in parallel +// Launch agents in parallel - agents write JSON and return summary const agentPromises = selectedPerspectives.map(perspective => Task({ subagent_type: "cli-explore-agent", run_in_background: false, - description: `Discover ${perspective} issues via Deep Scan`, + description: `Discover ${perspective} issues`, prompt: buildPerspectivePrompt(perspective, discoveryId, resolvedFiles, outputDir) }) ); -// For perspectives with Exa enabled, add external research -if (exaEnabled) { - for (const perspective of ['security', 'best-practices']) { - if (selectedPerspectives.includes(perspective)) { - agentPromises.push( - Task({ - subagent_type: "cli-explore-agent", - run_in_background: false, - description: `External research for ${perspective} via Exa`, - prompt: buildExaResearchPrompt(perspective, projectTech, outputDir) - }) - ); - } - } -} - -// Wait for all agents +// Wait for all agents - collect their return summaries const results = await Promise.all(agentPromises); +// results contain agent summaries for final report ``` **Phase 4: Aggregation & Prioritization** ```javascript -// Load all perspective results +// Load all perspective JSON files written by agents const allFindings = []; for (const perspective of selectedPerspectives) { const jsonPath = `${outputDir}/perspectives/${perspective}.json`; @@ -262,66 +204,37 @@ for (const perspective of selectedPerspectives) { } } -// Deduplicate by file+line -const uniqueFindings = deduplicateFindings(allFindings); +// Deduplicate and prioritize +const prioritizedFindings = deduplicateAndPrioritize(allFindings); -// Calculate priority scores -const prioritizedFindings = uniqueFindings.map(finding => ({ - ...finding, - priority_score: calculatePriorityScore(finding) -})).sort((a, b) => b.priority_score - a.priority_score); - -// Update state with aggregation results +// Update unified state await updateDiscoveryState(outputDir, { phase: 'aggregation', - total_findings: prioritizedFindings.length, - priority_distribution: countByPriority(prioritizedFindings) + 'results.total_findings': prioritizedFindings.length, + 'results.priority_distribution': countByPriority(prioritizedFindings) }); ``` -**Phase 5: Issue Generation** +**Phase 5: Issue Generation & Summary** ```javascript -// Filter high-priority findings for issue generation +// Convert high-priority findings to issues const issueWorthy = prioritizedFindings.filter(f => f.priority === 'critical' || f.priority === 'high' || f.priority_score >= 0.7 ); -// Convert to issue format -const issues = issueWorthy.map((finding, idx) => ({ - id: `DSC-${String(idx + 1).padStart(3, '0')}`, - title: finding.suggested_issue?.title || finding.title, - status: 'discovered', - priority: mapPriorityToNumber(finding.priority), - source: 'discovery', - source_discovery_id: discoveryId, - perspective: finding.perspective, - context: finding.description, - labels: [finding.perspective, ...(finding.labels || [])], - file: finding.file, - line: finding.line, - created_at: new Date().toISOString() -})); - -// Write discovery issues (preview, not committed to main issues.jsonl) +// Write discovery-issues.jsonl await writeJsonl(`${outputDir}/discovery-issues.jsonl`, issues); -// Generate summary report -await generateSummaryReport(outputDir, prioritizedFindings, issues); +// Generate single summary.md from agent return summaries +// Orchestrator briefly summarizes what agents returned (NO detailed reports) +await writeSummaryFromAgentReturns(outputDir, results, prioritizedFindings, issues); // Update final state await updateDiscoveryState(outputDir, { phase: 'complete', - issues_generated: issues.length -}); - -// Update index -await updateDiscoveryIndex(outputDir, discoveryId, { - target_pattern: targetPattern, - perspectives: selectedPerspectives, - total_findings: prioritizedFindings.length, - issues_generated: issues.length, - completed_at: new Date().toISOString() + updated_at: new Date().toISOString(), + 'results.issues_generated': issues.length }); ``` @@ -331,23 +244,12 @@ await updateDiscoveryIndex(outputDir, discoveryId, { .workflow/issues/discoveries/ ├── index.json # Discovery session index └── {discovery-id}/ - ├── discovery-state.json # State machine - ├── discovery-progress.json # Real-time progress (dashboard polling) + ├── discovery-state.json # Unified state (merged state+progress) ├── perspectives/ - │ ├── bug.json - │ ├── ux.json - │ ├── test.json - │ ├── quality.json - │ ├── security.json - │ ├── performance.json - │ ├── maintainability.json - │ └── best-practices.json - ├── external-research.json # Exa research results + │ └── {perspective}.json # Per-perspective findings + ├── external-research.json # Exa research results (if enabled) ├── discovery-issues.jsonl # Generated candidate issues - └── reports/ - ├── summary.md - ├── bug-report.md - └── {perspective}-report.md + └── summary.md # Single summary (from agent returns) ``` ### Schema References @@ -359,12 +261,6 @@ await updateDiscoveryIndex(outputDir, discoveryId, { | **Discovery State** | `~/.claude/workflows/cli-templates/schemas/discovery-state-schema.json` | Session state machine | | **Discovery Finding** | `~/.claude/workflows/cli-templates/schemas/discovery-finding-schema.json` | Perspective analysis results | -**Agent Schema Loading Protocol**: -```bash -# Agent MUST read schema before generating any JSON output -cat ~/.claude/workflows/cli-templates/schemas/discovery-finding-schema.json -``` - ### Agent Invocation Template **Perspective Analysis Agent**: @@ -373,23 +269,10 @@ cat ~/.claude/workflows/cli-templates/schemas/discovery-finding-schema.json Task({ subagent_type: "cli-explore-agent", run_in_background: false, - description: `Discover ${perspective} issues via Deep Scan`, + description: `Discover ${perspective} issues`, prompt: ` ## Task Objective - Discover potential ${perspective} issues in specified module files using Deep Scan mode (Bash + Gemini dual-source strategy) - - ## Analysis Mode - Use **Deep Scan mode** for this discovery: - - Phase 1: Bash structural scan for standard patterns - - Phase 2: Gemini semantic analysis for ${perspective}-specific concerns - - Phase 3: Synthesis with attribution - - ## MANDATORY FIRST STEPS - 1. Read discovery state: ${discoveryStateJsonPath} - 2. Get target files from discovery-state.json - 3. Validate file access: bash(ls -la ${targetFiles.join(' ')}) - 4. **CRITICAL**: Read schema FIRST: cat ~/.claude/workflows/cli-templates/schemas/discovery-finding-schema.json - 5. Read: .workflow/project-tech.json (technology stack) + Discover potential ${perspective} issues in specified module files. ## Discovery Context - Discovery ID: ${discoveryId} @@ -398,59 +281,30 @@ Task({ - Resolved Files: ${resolvedFiles.length} files - Output Directory: ${outputDir} - ## CLI Configuration - - Tool Priority: gemini → qwen → codex - - Mode: analysis (READ-ONLY for code analysis, WRITE for output files) - - Context Pattern: ${targetFiles.map(f => `@${f}`).join(' ')} + ## MANDATORY FIRST STEPS + 1. Read discovery state: ${outputDir}/discovery-state.json + 2. Read schema: ~/.claude/workflows/cli-templates/schemas/discovery-finding-schema.json + 3. Analyze target files for ${perspective} concerns - ## ⚠️ CRITICAL OUTPUT GUIDELINES + ## Output Requirements - **Agent MUST write JSON files directly - DO NOT return JSON to orchestrator**: + **1. Write JSON file**: ${outputDir}/perspectives/${perspective}.json + - Follow discovery-finding-schema.json exactly + - Each finding: id, title, priority, category, description, file, line, snippet, suggested_issue, confidence - 1. **Schema Compliance**: Read and strictly follow discovery-finding-schema.json - - All required fields MUST be present - - Use exact enum values (lowercase priority: critical/high/medium/low) - - ID format: dsc-{perspective}-{seq}-{uuid8} - - 2. **Direct File Output**: Agent writes files using Write/mcp__ccw-tools__write_file: - - JSON: ${outputDir}/perspectives/${perspective}.json - - Report: ${outputDir}/reports/${perspective}-report.md - - DO NOT return raw JSON in response - write to file - - 3. **Validation Before Write**: - - Validate JSON against schema structure - - Ensure all findings have required fields - - Verify file paths are relative to project root - - 4. **Progress Update**: After writing, update discovery-progress.json: - - Set perspective status to "completed" - - Update findings_count - - Update completed_at timestamp - - ## Expected Deliverables - - 1. Perspective Results JSON: ${outputDir}/perspectives/${perspective}.json - - Follow discovery-finding-schema.json exactly - - Root structure MUST be object with findings array - - Each finding MUST include: id, title, priority, category, description, file, line, snippet, suggested_issue, confidence - - 2. Discovery Report: ${outputDir}/reports/${perspective}-report.md - - Human-readable summary - - Grouped by priority - - Include file:line references + **2. Return summary** (DO NOT write report file): + - Return a brief text summary of findings + - Include: total findings, priority breakdown, key issues + - This summary will be used by orchestrator for final report ## Perspective-Specific Guidance ${getPerspectiveGuidance(perspective)} ## Success Criteria - - [ ] Schema read and understood before analysis - - [ ] All target files analyzed for ${perspective} concerns - - [ ] JSON written directly to ${outputDir}/perspectives/${perspective}.json - - [ ] Report written to ${outputDir}/reports/${perspective}-report.md + - [ ] JSON written to ${outputDir}/perspectives/${perspective}.json + - [ ] Summary returned with findings count and key issues - [ ] Each finding includes actionable suggested_issue - - [ ] Priority assessment is accurate (lowercase enum values) - - [ ] Recommendations are specific and implementable - - [ ] discovery-progress.json updated with completion status + - [ ] Priority uses lowercase enum: critical/high/medium/low ` }) ``` @@ -464,66 +318,26 @@ Task({ description: `External research for ${perspective} via Exa`, prompt: ` ## Task Objective - Research industry best practices and common patterns for ${perspective} using Exa search - - ## MANDATORY FIRST STEPS - 1. Read project tech stack: .workflow/project-tech.json - 2. Read external research schema structure (if exists) - 3. Identify key technologies (e.g., Node.js, React, Express) + Research industry best practices for ${perspective} using Exa search ## Research Steps - 1. Use Exa to search for: - - "${technology} ${perspective} best practices 2025" - - "${technology} common ${perspective} issues" - - "${technology} ${perspective} checklist" - 2. Synthesize findings relevant to this project + 1. Read project tech stack: .workflow/project-tech.json + 2. Use Exa to search for best practices + 3. Synthesize findings relevant to this project - ## ⚠️ CRITICAL OUTPUT GUIDELINES + ## Output Requirements - **Agent MUST write files directly - DO NOT return content to orchestrator**: + **1. Write JSON file**: ${outputDir}/external-research.json + - Include sources, key_findings, gap_analysis, recommendations - 1. **Direct File Output**: Agent writes files using Write/mcp__ccw-tools__write_file: - - JSON: ${outputDir}/external-research.json - - Report: ${outputDir}/reports/${perspective}-external.md - - DO NOT return raw content in response - write to file - - 2. **JSON Structure for external-research.json**: - \`\`\`json - { - "discovery_id": "${discoveryId}", - "perspective": "${perspective}", - "research_timestamp": "ISO8601", - "sources": [ - { "title": "...", "url": "...", "relevance": "..." } - ], - "key_findings": [...], - "gap_analysis": [...], - "recommendations": [...] - } - \`\`\` - - 3. **Progress Update**: After writing, update discovery-progress.json: - - Set external_research.completed to true - - ## Expected Deliverables - - 1. External Research JSON: ${outputDir}/external-research.json - - Sources with URLs - - Key findings - - Relevance to current codebase - - 2. Comparison report in ${outputDir}/reports/${perspective}-external.md - - Industry standards vs current implementation - - Gap analysis - - Prioritized recommendations + **2. Return summary** (DO NOT write report file): + - Brief summary of external research findings + - Key recommendations for the project ## Success Criteria - - [ ] At least 3 authoritative sources consulted - - [ ] JSON written directly to ${outputDir}/external-research.json - - [ ] Report written to ${outputDir}/reports/${perspective}-external.md + - [ ] JSON written to ${outputDir}/external-research.json + - [ ] Summary returned with key recommendations - [ ] Findings are relevant to project's tech stack - - [ ] Recommendations are actionable - - [ ] discovery-progress.json updated ` }) ``` @@ -534,127 +348,38 @@ Task({ function getPerspectiveGuidance(perspective) { const guidance = { bug: ` - Focus Areas: - - Null/undefined checks before property access - - Edge cases in conditionals (empty arrays, 0 values, empty strings) - - Resource leaks (unclosed connections, streams, file handles) - - Race conditions in async code - - Boundary conditions (array indices, date ranges) - - Exception handling gaps (missing try-catch, swallowed errors) - - Priority Criteria: - - Critical: Data corruption, security bypass, system crash - - High: Feature malfunction, data loss potential - - Medium: Unexpected behavior in edge cases - - Low: Minor inconsistencies, cosmetic issues + Focus: Null checks, edge cases, resource leaks, race conditions, boundary conditions, exception handling + Priority: Critical=data corruption/crash, High=malfunction, Medium=edge case issues, Low=minor `, ux: ` - Focus Areas: - - Error messages (are they user-friendly and actionable?) - - Loading states (are long operations indicated?) - - Feedback (do users know their action succeeded?) - - Accessibility (keyboard navigation, screen readers, color contrast) - - Interaction patterns (consistent behavior across the app) - - Form validation (immediate feedback, clear requirements) - - Priority Criteria: - - Critical: Inaccessible features, misleading feedback - - High: Confusing error messages, missing loading states - - Medium: Inconsistent patterns, minor feedback issues - - Low: Cosmetic improvements, nice-to-haves + Focus: Error messages, loading states, feedback, accessibility, interaction patterns, form validation + Priority: Critical=inaccessible, High=confusing, Medium=inconsistent, Low=cosmetic `, test: ` - Focus Areas: - - Missing unit tests for public functions - - Edge case coverage (null, empty, boundary values) - - Integration test gaps (API endpoints, database operations) - - Coverage holes in critical paths (auth, payment, data mutation) - - Assertion quality (are tests actually verifying behavior?) - - Test isolation (do tests depend on each other?) - - Priority Criteria: - - Critical: No tests for security-critical code - - High: Missing tests for core business logic - - Medium: Edge cases not covered, weak assertions - - Low: Minor coverage gaps, test organization issues + Focus: Missing unit tests, edge case coverage, integration gaps, assertion quality, test isolation + Priority: Critical=no security tests, High=no core logic tests, Medium=weak coverage, Low=minor gaps `, quality: ` - Focus Areas: - - Cyclomatic complexity (deeply nested conditionals) - - Code duplication (copy-pasted logic) - - Naming (unclear variable/function names) - - Documentation (missing JSDoc for public APIs) - - Code smells (long functions, large files, magic numbers) - - Readability (overly clever code, unclear intent) - - Priority Criteria: - - Critical: Unmaintainable complexity blocking changes - - High: Significant duplication, confusing logic - - Medium: Naming issues, missing documentation - - Low: Minor refactoring opportunities + Focus: Complexity, duplication, naming, documentation, code smells, readability + Priority: Critical=unmaintainable, High=significant issues, Medium=naming/docs, Low=minor refactoring `, security: ` - Focus Areas: - - Input validation and sanitization - - Authentication and authorization mechanisms - - SQL/NoSQL injection vulnerabilities - - XSS, CSRF vulnerabilities - - Sensitive data exposure (logs, errors, responses) - - Access control gaps - - Priority Criteria: - - Critical: Authentication bypass, injection, RCE - - High: Missing authorization, exposed secrets - - Medium: Missing input validation, weak encryption - - Low: Security headers, verbose errors + Focus: Input validation, auth/authz, injection, XSS/CSRF, data exposure, access control + Priority: Critical=auth bypass/injection, High=missing authz, Medium=weak validation, Low=headers `, performance: ` - Focus Areas: - - N+1 query problems in ORM usage - - Memory usage patterns (large objects, memory leaks) - - Caching opportunities (repeated computations, API calls) - - Algorithm efficiency (O(n²) where O(n log n) possible) - - Blocking operations on main thread - - Resource usage (CPU, network, disk I/O) - - Priority Criteria: - - Critical: Memory leaks, blocking main thread - - High: N+1 queries, inefficient algorithms in hot paths - - Medium: Missing caching, suboptimal data structures - - Low: Minor optimization opportunities + Focus: N+1 queries, memory leaks, caching, algorithm efficiency, blocking operations + Priority: Critical=memory leaks, High=N+1/inefficient, Medium=missing cache, Low=minor optimization `, maintainability: ` - Focus Areas: - - Module coupling (tight dependencies between unrelated modules) - - Interface design (unclear contracts, leaky abstractions) - - Technical debt indicators (TODOs, FIXMEs, temporary solutions) - - Extensibility (hard to add new features without touching core) - - Module boundaries (unclear separation of responsibilities) - - Configuration management (hardcoded values, environment handling) - - Priority Criteria: - - Critical: Changes require touching unrelated code - - High: Unclear module boundaries, significant tech debt - - Medium: Minor coupling issues, configuration problems - - Low: Refactoring opportunities, documentation gaps + Focus: Coupling, interface design, tech debt, extensibility, module boundaries, configuration + Priority: Critical=unrelated code changes, High=unclear boundaries, Medium=coupling, Low=refactoring `, 'best-practices': ` - Focus Areas: - - Framework conventions (are we using the framework idiomatically?) - - Language patterns (modern JS/TS features, async/await usage) - - Anti-patterns (god objects, callback hell, mutation of shared state) - - Deprecated API usage (using old APIs when new ones available) - - Industry standards (OWASP for security, WCAG for accessibility) - - Coding standards (consistent style, ESLint/Prettier compliance) - - Priority Criteria: - - Critical: Anti-patterns causing bugs, deprecated security APIs - - High: Major convention violations, poor patterns - - Medium: Minor style issues, suboptimal patterns - - Low: Cosmetic improvements + Focus: Framework conventions, language patterns, anti-patterns, deprecated APIs, coding standards + Priority: Critical=anti-patterns causing bugs, High=convention violations, Medium=style, Low=cosmetic ` }; - return guidance[perspective] || 'General code discovery analysis'; } ``` @@ -674,7 +399,6 @@ Navigate to **Issues > Discovery** to: - Filter findings by perspective and priority - Preview finding details - Select and export findings as issues -- Dismiss irrelevant findings ### Exporting to Issues diff --git a/.claude/commands/issue/new.md b/.claude/commands/issue/new.md index ee1ba0cd..00d6a411 100644 --- a/.claude/commands/issue/new.md +++ b/.claude/commands/issue/new.md @@ -24,7 +24,7 @@ interface Issue { status: 'registered'; // Initial status priority: number; // 1 (critical) to 5 (low) context: string; // Problem description - source: 'github' | 'text'; // Input source type + source: 'github' | 'text' | 'discovery'; // Input source type source_url?: string; // GitHub URL if applicable labels?: string[]; // Categorization labels @@ -35,6 +35,18 @@ interface Issue { affected_components?: string[];// Files/modules affected reproduction_steps?: string[]; // Steps to reproduce + // Discovery context (when source='discovery') + discovery_context?: { + discovery_id: string; // Source discovery session + perspective: string; // bug, test, quality, etc. + category: string; // Finding category + file: string; // Primary affected file + line: number; // Line number + snippet?: string; // Code snippet + confidence: number; // Agent confidence (0-1) + suggested_fix?: string; // Suggested remediation + }; + // Closed-loop requirements (guide plan generation) lifecycle_requirements: { test_strategy: 'unit' | 'integration' | 'e2e' | 'manual' | 'auto'; diff --git a/.claude/commands/issue/plan.md b/.claude/commands/issue/plan.md index 4ced15a2..5a24f4ab 100644 --- a/.claude/commands/issue/plan.md +++ b/.claude/commands/issue/plan.md @@ -202,8 +202,9 @@ ${issueList} ### Steps 1. Fetch: \`ccw issue status --json\` 2. Load project context (project-tech.json + project-guidelines.json) -3. Explore (ACE) → Plan solution (respecting guidelines) -4. Register & bind: \`ccw issue bind --solution \` +3. **If source=discovery**: Use discovery_context (file, line, snippet, suggested_fix) as planning hints +4. Explore (ACE) → Plan solution (respecting guidelines) +5. Register & bind: \`ccw issue bind --solution \` ### Generate Files \`.workflow/issues/solutions/{issue-id}.jsonl\` - Solution with tasks (schema: cat .claude/workflows/cli-templates/schemas/solution-schema.json) diff --git a/.claude/skills/software-manual/SKILL.md b/.claude/skills/software-manual/SKILL.md index b3331756..98f96b75 100644 --- a/.claude/skills/software-manual/SKILL.md +++ b/.claude/skills/software-manual/SKILL.md @@ -38,9 +38,9 @@ Generate comprehensive, interactive software manuals in TiddlyWiki-style single- 1. **主 Agent 编排,子 Agent 执行**: 所有繁重计算委托给 `universal-executor` 子 Agent 2. **Brief Returns**: Agents return path + summary, not full content (avoid context overflow) 3. **System Agents**: 使用 `cli-explore-agent` (探索) 和 `universal-executor` (执行) -4. **Chrome MCP Integration**: Batch screenshot capture with Base64 embedding +4. **成熟库内嵌**: marked.js (MD 解析) + highlight.js (语法高亮),无 CDN 依赖 5. **Single-File HTML**: TiddlyWiki-style interactive document with embedded resources -6. **User-Friendly Writing**: Clear, step-by-step guides with difficulty levels +6. **动态标签**: 根据实际章节自动生成导航标签 ## Execution Flow @@ -54,6 +54,10 @@ Generate comprehensive, interactive software manuals in TiddlyWiki-style single- │ → 并行探索: architecture, ui-routes, api-endpoints, config │ │ → Output: exploration-*.json │ ├─────────────────────────────────────────────────────────────────┤ +│ Phase 2.5: API Extraction (extract_apis.py) │ +│ → 自动提取: FastAPI/TypeDoc/pdoc │ +│ → Output: api-docs/{backend,frontend,modules}/*.md │ +├─────────────────────────────────────────────────────────────────┤ │ Phase 3: Parallel Analysis (universal-executor × 6) │ │ → 6 个子 Agent 并行: overview, ui-guide, api-docs, config, │ │ troubleshooting, code-examples │ @@ -161,17 +165,20 @@ Bash(`mkdir "${dir}\\sections" && mkdir "${dir}\\screenshots" && mkdir "${dir}\\ | Document | Purpose | |----------|---------| -| [phases/01-requirements-discovery.md](phases/01-requirements-discovery.md) | User config collection | -| [phases/02-project-exploration.md](phases/02-project-exploration.md) | Project type detection | -| [phases/03-parallel-analysis.md](phases/03-parallel-analysis.md) | 6 Agent orchestration | -| [phases/03.5-consolidation.md](phases/03.5-consolidation.md) | Cross-section synthesis | -| [phases/04-screenshot-capture.md](phases/04-screenshot-capture.md) | Chrome MCP integration | -| [phases/05-html-assembly.md](phases/05-html-assembly.md) | HTML generation | -| [phases/06-iterative-refinement.md](phases/06-iterative-refinement.md) | Quality iteration | -| [specs/quality-standards.md](specs/quality-standards.md) | Quality gates | -| [specs/writing-style.md](specs/writing-style.md) | User-friendly writing | -| [specs/html-template.md](specs/html-template.md) | HTML template spec | -| [templates/tiddlywiki-shell.html](templates/tiddlywiki-shell.html) | HTML template | -| [scripts/typedoc-runner.md](scripts/typedoc-runner.md) | TypeDoc execution | -| [scripts/swagger-runner.md](scripts/swagger-runner.md) | Swagger/OpenAPI | -| [scripts/screenshot-helper.md](scripts/screenshot-helper.md) | Chrome MCP guide | +| [phases/01-requirements-discovery.md](phases/01-requirements-discovery.md) | 用户配置收集 | +| [phases/02-project-exploration.md](phases/02-project-exploration.md) | 项目类型检测 | +| [phases/02.5-api-extraction.md](phases/02.5-api-extraction.md) | API 自动提取 | +| [phases/03-parallel-analysis.md](phases/03-parallel-analysis.md) | 6 Agent 并行分析 | +| [phases/03.5-consolidation.md](phases/03.5-consolidation.md) | 整合与质量检查 | +| [phases/04-screenshot-capture.md](phases/04-screenshot-capture.md) | Chrome MCP 截图 | +| [phases/05-html-assembly.md](phases/05-html-assembly.md) | HTML 组装 | +| [phases/06-iterative-refinement.md](phases/06-iterative-refinement.md) | 迭代优化 | +| [specs/quality-standards.md](specs/quality-standards.md) | 质量标准 | +| [specs/writing-style.md](specs/writing-style.md) | 写作风格 | +| [templates/tiddlywiki-shell.html](templates/tiddlywiki-shell.html) | HTML 模板 | +| [templates/css/wiki-base.css](templates/css/wiki-base.css) | 基础样式 | +| [templates/css/wiki-dark.css](templates/css/wiki-dark.css) | 暗色主题 | +| [scripts/bundle-libraries.md](scripts/bundle-libraries.md) | 库文件打包 | +| [scripts/api-extractor.md](scripts/api-extractor.md) | API 提取说明 | +| [scripts/extract_apis.py](scripts/extract_apis.py) | API 提取脚本 | +| [scripts/screenshot-helper.md](scripts/screenshot-helper.md) | 截图辅助 | diff --git a/.claude/skills/software-manual/phases/02.5-api-extraction.md b/.claude/skills/software-manual/phases/02.5-api-extraction.md new file mode 100644 index 00000000..9de1fc10 --- /dev/null +++ b/.claude/skills/software-manual/phases/02.5-api-extraction.md @@ -0,0 +1,161 @@ +# Phase 2.5: API Extraction + +在项目探索后、并行分析前,自动提取 API 文档。 + +## 核心原则 + +**使用成熟工具提取,确保输出格式与 wiki 模板兼容。** + +## 执行流程 + +```javascript +const config = JSON.parse(Read(`${workDir}/manual-config.json`)); + +// 检查项目路径配置 +const apiSources = config.api_sources || detectApiSources(config.project_path); + +// 执行 API 提取 +Bash({ + command: `python .claude/skills/software-manual/scripts/extract_apis.py -o "${workDir}" -p ${apiSources.join(' ')}` +}); + +// 验证输出 +const apiDocsDir = `${workDir}/api-docs`; +const extractedFiles = Glob(`${apiDocsDir}/**/*.{json,md}`); +console.log(`Extracted ${extractedFiles.length} API documentation files`); +``` + +## 支持的项目类型 + +| 类型 | 检测方式 | 提取工具 | 输出格式 | +|------|----------|----------|----------| +| FastAPI | `app/main.py` + FastAPI import | OpenAPI JSON | `openapi.json` + `API_SUMMARY.md` | +| Next.js | `package.json` + next | TypeDoc | `*.md` (Markdown) | +| Python Module | `__init__.py` + setup.py/pyproject.toml | pdoc | `*.md` (Markdown) | +| Express | `package.json` + express | swagger-jsdoc | `openapi.json` | +| NestJS | `package.json` + @nestjs | @nestjs/swagger | `openapi.json` | + +## 输出格式规范 + +### Markdown 兼容性要求 + +确保输出 Markdown 与 wiki CSS 样式兼容: + +```markdown +# API Reference →

(wiki-base.css) + +## Endpoints →

+ +| Method | Path | Summary | → 蓝色表头 +|--------|------|---------| +| `GET` | `/api/...` | ... | → 红色高亮 + +### GET /api/users →

+ +\`\`\`json →
 深色背景
+{
+  "id": 1,
+  "name": "example"
+}
+\`\`\`
+
+- Parameter: `id` (required)       → 
  • + +``` + +### 格式验证检查 + +```javascript +function validateApiDocsFormat(apiDocsDir) { + const issues = []; + const mdFiles = Glob(`${apiDocsDir}/**/*.md`); + + for (const file of mdFiles) { + const content = Read(file); + + // 检查表格格式 + if (content.includes('|') && !content.match(/\|.*\|.*\|/)) { + issues.push(`${file}: 表格格式不完整`); + } + + // 检查代码块语言标注 + const codeBlocks = content.match(/```(\w*)\n/g) || []; + const unlabeled = codeBlocks.filter(b => b === '```\n'); + if (unlabeled.length > 0) { + issues.push(`${file}: ${unlabeled.length} 个代码块缺少语言标注`); + } + + // 检查标题层级 + if (!content.match(/^# /m)) { + issues.push(`${file}: 缺少一级标题`); + } + } + + return issues; +} +``` + +## 项目配置示例 + +在 `manual-config.json` 中配置 API 源: + +```json +{ + "software": { + "name": "Hydro Generator Workbench", + "type": "web" + }, + "api_sources": { + "backend": { + "path": "D:/dongdiankaifa9/backend", + "type": "fastapi", + "entry": "app.main:app" + }, + "frontend": { + "path": "D:/dongdiankaifa9/frontend", + "type": "typescript", + "entries": ["lib", "hooks", "components"] + }, + "hydro_generator_module": { + "path": "D:/dongdiankaifa9/hydro_generator_module", + "type": "python" + }, + "multiphysics_network": { + "path": "D:/dongdiankaifa9/multiphysics_network", + "type": "python" + } + } +} +``` + +## 输出结构 + +``` +{workDir}/api-docs/ +├── backend/ +│ ├── openapi.json # OpenAPI 3.0 规范 +│ └── API_SUMMARY.md # Markdown 摘要(wiki 兼容) +├── frontend/ +│ ├── modules.md # TypeDoc 模块文档 +│ ├── classes/ # 类文档 +│ └── functions/ # 函数文档 +├── hydro_generator/ +│ ├── assembler.md # pdoc 模块文档 +│ ├── blueprint.md +│ └── builders/ +└── multiphysics/ + ├── analysis_domain.md + ├── builders.md + └── compilers.md +``` + +## 质量门禁 + +- [ ] 所有配置的 API 源已提取 +- [ ] Markdown 格式与 wiki CSS 兼容 +- [ ] 表格正确渲染(蓝色表头) +- [ ] 代码块有语言标注 +- [ ] 无空文件或错误文件 + +## 下一阶段 + +→ [Phase 3: Parallel Analysis](03-parallel-analysis.md) diff --git a/.claude/skills/software-manual/phases/03-parallel-analysis.md b/.claude/skills/software-manual/phases/03-parallel-analysis.md index a4c3c49e..e0765c4d 100644 --- a/.claude/skills/software-manual/phases/03-parallel-analysis.md +++ b/.claude/skills/software-manual/phases/03-parallel-analysis.md @@ -11,51 +11,66 @@ const AGENT_CONFIGS = { output: 'section-overview.md', task: '撰写产品概览、核心功能、快速入门指南', focus: '产品定位、目标用户、5步快速入门、系统要求', - input: ['exploration-architecture.json', 'README.md', 'package.json'] + input: ['exploration-architecture.json', 'README.md', 'package.json'], + tag: 'getting-started' }, - 'ui-guide': { - role: 'UX Expert', - output: 'section-ui-guide.md', - task: '撰写界面操作指南,标注所有需要截图的 UI 元素', - focus: '界面布局、导航流程、功能操作、快捷键', - input: ['exploration-ui-routes.json', 'pages/**', 'views/**'], + 'interface-guide': { + role: 'Product Designer', + output: 'section-interface.md', + task: '撰写界面或交互指南(Web 截图、CLI 命令交互、桌面应用操作)', + focus: '视觉布局、交互流程、命令行参数、输入/输出示例', + input: ['exploration-ui-routes.json', 'src/**', 'pages/**', 'views/**', 'components/**', 'src/commands/**'], + tag: 'interface', screenshot_rules: ` -每个关键 UI 交互点必须插入截图标记: - +根据项目类型标注交互点: -示例: -- 页面全貌: -- 特定组件: -- 交互状态: +[Web] +[CLI] 使用代码块展示命令交互: +\`\`\`bash +$ command --flag value +Expected output here +\`\`\` +[Desktop] ` }, - 'api-docs': { - role: 'API Architect', - output: 'section-api-reference.md', - task: '撰写 REST API 和前端 API 参考文档', - focus: 'API 概览、端点分类、请求/响应示例、错误码', - input: ['exploration-api-endpoints.json', 'controllers/**', 'routes/**'] + 'api-reference': { + role: 'Technical Architect', + output: 'section-reference.md', + task: '撰写接口参考文档(REST API / 函数库 / CLI 命令)', + focus: '函数签名、端点定义、参数说明、返回值、错误代码', + pre_extract: 'python .claude/skills/software-manual/scripts/extract_apis.py -o ${workDir}', + input: [ + '${workDir}/api-docs/backend/openapi.json', // FastAPI OpenAPI + '${workDir}/api-docs/backend/API_SUMMARY.md', // Backend summary + '${workDir}/api-docs/frontend/**/*.md', // TypeDoc output + '${workDir}/api-docs/hydro_generator/**/*.md', // Python module + '${workDir}/api-docs/multiphysics/**/*.md' // Python module + ], + tag: 'api' }, config: { role: 'DevOps Engineer', output: 'section-configuration.md', task: '撰写配置指南,涵盖环境变量、配置文件、部署设置', focus: '环境变量表格、配置文件格式、部署选项、安全设置', - input: ['exploration-config.json', '.env.example', 'config/**'] + input: ['exploration-config.json', '.env.example', 'config/**', '*.config.*'], + tag: 'config' }, troubleshooting: { role: 'Support Engineer', output: 'section-troubleshooting.md', task: '撰写故障排查指南,涵盖常见问题、错误码、FAQ', focus: '常见问题与解决方案、错误码参考、FAQ、获取帮助', - input: ['all exploration files', 'error handling code'] + input: ['docs/troubleshooting.md', 'src/**/errors.*', 'src/**/exceptions.*', 'TROUBLESHOOTING.md'], + tag: 'troubleshooting' }, 'code-examples': { role: 'Developer Advocate', output: 'section-examples.md', task: '撰写多难度级别代码示例(入门40%/进阶40%/高级20%)', focus: '完整可运行代码、分步解释、预期输出、最佳实践', - input: ['all exploration files', 'examples/**', 'tests/**'] + input: ['examples/**', 'tests/**', 'demo/**', 'samples/**'], + tag: 'examples' } }; ``` @@ -65,7 +80,16 @@ const AGENT_CONFIGS = { ```javascript const config = JSON.parse(Read(`${workDir}/manual-config.json`)); -// 并行启动 6 个 universal-executor +// 1. 预提取 API 文档(如有 pre_extract 配置) +for (const [name, cfg] of Object.entries(AGENT_CONFIGS)) { + if (cfg.pre_extract) { + const cmd = cfg.pre_extract.replace(/\$\{workDir\}/g, workDir); + console.log(`[Pre-extract] ${name}: ${cmd}`); + Bash({ command: cmd }); + } +} + +// 2. 并行启动 6 个 universal-executor const tasks = Object.entries(AGENT_CONFIGS).map(([name, cfg]) => Task({ subagent_type: 'universal-executor', @@ -83,35 +107,51 @@ const results = await Promise.all(tasks); function buildAgentPrompt(name, cfg, config, workDir) { const screenshotSection = cfg.screenshot_rules ? `\n[SCREENSHOT RULES]\n${cfg.screenshot_rules}` - : '\n[SCREENSHOT]\n截图标记: '; + : ''; return ` [ROLE] ${cfg.role} +[PROJECT CONTEXT] +项目类型: ${config.software.type} (web/cli/sdk/desktop) +语言: ${config.software.language || 'auto-detect'} +名称: ${config.software.name} + [TASK] ${cfg.task} 输出: ${workDir}/sections/${cfg.output} [INPUT] -- Read: ${workDir}/manual-config.json -- Read: ${cfg.input.map(f => `${workDir}/exploration/${f}`).join(', ')} +- 配置: ${workDir}/manual-config.json +- 探索结果: ${workDir}/exploration/ +- 扫描路径: ${cfg.input.join(', ')} -[STYLE] -- 用户友好语言,避免技术术语 -- 步骤编号清晰 -- 代码块标注语言 +[CONTENT REQUIREMENTS] +- 标题层级: # ## ### (最多3级) +- 代码块: \`\`\`language ... \`\`\` (必须标注语言) +- 表格: | col1 | col2 | 格式 +- 列表: 有序 1. 2. 3. / 无序 - - - +- 内联代码: \`code\` +- 链接: [text](url) ${screenshotSection} [FOCUS] ${cfg.focus} +[OUTPUT FORMAT] +Markdown 文件,包含: +- 清晰的章节结构 +- 具体的代码示例 +- 参数/配置表格 +- 常见用例说明 + [RETURN JSON] { "status": "completed", "output_file": "sections/${cfg.output}", "summary": "<50字>", - "screenshots_needed": [{ "id": "ss-xxx", "url": "/path", "selector": ".class", "description": "..." }], - "cross_references": [] + "tag": "${cfg.tag}", + "screenshots_needed": [] } `; } diff --git a/.claude/skills/software-manual/phases/05-html-assembly.md b/.claude/skills/software-manual/phases/05-html-assembly.md index e3a5c372..ea5e33f8 100644 --- a/.claude/skills/software-manual/phases/05-html-assembly.md +++ b/.claude/skills/software-manual/phases/05-html-assembly.md @@ -29,29 +29,40 @@ function buildAssemblyPrompt(config, workDir) { [ROLE] HTML Assembler [TASK] -生成 TiddlyWiki 风格的交互式 HTML 手册 +生成 TiddlyWiki 风格的交互式 HTML 手册(使用成熟库,无外部 CDN 依赖) [INPUT] - 模板: .claude/skills/software-manual/templates/tiddlywiki-shell.html - CSS: .claude/skills/software-manual/templates/css/wiki-base.css, wiki-dark.css - 配置: ${workDir}/manual-config.json - 章节: ${workDir}/sections/section-*.md +- Agent 结果: ${workDir}/agent-results.json (含 tag 信息) - 截图: ${workDir}/screenshots/ +[LIBRARIES TO EMBED] +1. marked.js (v14+) - Markdown 转 HTML + - 从 https://unpkg.com/marked/marked.min.js 获取内容内嵌 +2. highlight.js (v11+) - 代码语法高亮 + - 核心 + 常用语言包 (js, ts, python, bash, json, yaml, html, css) + - 使用 github-dark 主题 + [STEPS] 1. 读取 HTML 模板和 CSS -2. 逐个读取 section-*.md,转换为 HTML tiddlers -3. 处理 标记,嵌入 Base64 图片 -4. 生成目录、搜索索引 -5. 组装最终 HTML,写入 ${workDir}/${config.software.name}-使用手册.html -6. 生成构建报告 ${workDir}/build-report.json +2. 内嵌 marked.js 和 highlight.js 代码 +3. 读取 agent-results.json 提取各章节 tag +4. 动态生成 {{TAG_BUTTONS_HTML}} (基于实际使用的 tags) +5. 逐个读取 section-*.md,使用 marked 转换为 HTML +6. 为代码块添加 data-language 属性和语法高亮 +7. 处理 标记,嵌入 Base64 图片 +8. 生成目录、搜索索引 +9. 组装最终 HTML,写入 ${workDir}/${config.software.name}-使用手册.html -[HTML FEATURES] -- 搜索: 全文检索 + 高亮 -- 折叠: 章节可展开/收起 -- 标签: 分类过滤 -- 主题: 亮/暗模式切换 -- 离线: 所有资源内嵌 +[CONTENT FORMATTING] +- 代码块: 深色背景 + 语言标签 + 语法高亮 +- 表格: 蓝色表头 + 边框 + 悬停效果 +- 内联代码: 红色高亮 +- 列表: 有序/无序样式增强 +- 左侧导航: 固定侧边栏 + TOC [RETURN JSON] { @@ -59,6 +70,7 @@ function buildAssemblyPrompt(config, workDir) { "output_file": "${config.software.name}-使用手册.html", "file_size": "", "sections_count": , + "tags_generated": [], "screenshots_embedded": } `; diff --git a/.claude/skills/software-manual/scripts/api-extractor.md b/.claude/skills/software-manual/scripts/api-extractor.md new file mode 100644 index 00000000..7e13dfb0 --- /dev/null +++ b/.claude/skills/software-manual/scripts/api-extractor.md @@ -0,0 +1,245 @@ +# API 文档提取脚本 + +根据项目类型自动提取 API 文档,支持 FastAPI、Next.js、Python 模块。 + +## 支持的技术栈 + +| 类型 | 技术栈 | 工具 | 输出格式 | +|------|--------|------|----------| +| Backend | FastAPI | openapi-to-md | Markdown | +| Frontend | Next.js/TypeScript | TypeDoc | Markdown | +| Python Module | Python | pdoc | Markdown/HTML | + +## 使用方法 + +### 1. FastAPI Backend (OpenAPI) + +```bash +# 提取 OpenAPI JSON +cd D:/dongdiankaifa9/backend +python -c " +from app.main import app +import json +print(json.dumps(app.openapi(), indent=2)) +" > api-docs/openapi.json + +# 转换为 Markdown (使用 widdershins) +npx widdershins api-docs/openapi.json -o api-docs/API_REFERENCE.md --language_tabs 'python:Python' 'javascript:JavaScript' 'bash:cURL' +``` + +**备选方案 (无需启动服务)**: +```python +# scripts/extract_fastapi_openapi.py +import sys +sys.path.insert(0, 'D:/dongdiankaifa9/backend') + +from app.main import app +import json + +openapi_schema = app.openapi() +with open('api-docs/openapi.json', 'w', encoding='utf-8') as f: + json.dump(openapi_schema, f, indent=2, ensure_ascii=False) + +print(f"Extracted {len(openapi_schema.get('paths', {}))} endpoints") +``` + +### 2. Next.js Frontend (TypeDoc) + +```bash +cd D:/dongdiankaifa9/frontend + +# 安装 TypeDoc +npm install --save-dev typedoc typedoc-plugin-markdown + +# 生成文档 +npx typedoc --plugin typedoc-plugin-markdown \ + --out api-docs \ + --entryPoints "./lib" "./hooks" "./components" \ + --entryPointStrategy expand \ + --exclude "**/node_modules/**" \ + --exclude "**/*.test.*" \ + --readme none +``` + +**typedoc.json 配置**: +```json +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["./lib", "./hooks", "./components"], + "entryPointStrategy": "expand", + "out": "api-docs", + "plugin": ["typedoc-plugin-markdown"], + "exclude": ["**/node_modules/**", "**/*.test.*", "**/*.spec.*"], + "excludePrivate": true, + "excludeInternal": true, + "readme": "none", + "name": "Frontend API Reference" +} +``` + +### 3. Python Module (pdoc) + +```bash +# 安装 pdoc +pip install pdoc + +# hydro_generator_module +cd D:/dongdiankaifa9 +pdoc hydro_generator_module \ + --output-dir api-docs/hydro_generator \ + --format markdown \ + --no-show-source + +# multiphysics_network +pdoc multiphysics_network \ + --output-dir api-docs/multiphysics \ + --format markdown \ + --no-show-source +``` + +**备选: Sphinx (更强大)**: +```bash +# 安装 Sphinx +pip install sphinx sphinx-markdown-builder + +# 生成 API 文档 +sphinx-apidoc -o docs/source hydro_generator_module +cd docs && make markdown +``` + +## 集成脚本 + +```python +#!/usr/bin/env python3 +# scripts/extract_all_apis.py + +import subprocess +import sys +from pathlib import Path + +PROJECTS = { + 'backend': { + 'path': 'D:/dongdiankaifa9/backend', + 'type': 'fastapi', + 'output': 'api-docs/backend' + }, + 'frontend': { + 'path': 'D:/dongdiankaifa9/frontend', + 'type': 'typescript', + 'output': 'api-docs/frontend' + }, + 'hydro_generator_module': { + 'path': 'D:/dongdiankaifa9/hydro_generator_module', + 'type': 'python', + 'output': 'api-docs/hydro_generator' + }, + 'multiphysics_network': { + 'path': 'D:/dongdiankaifa9/multiphysics_network', + 'type': 'python', + 'output': 'api-docs/multiphysics' + } +} + +def extract_fastapi(config): + """提取 FastAPI OpenAPI 文档""" + path = Path(config['path']) + sys.path.insert(0, str(path)) + + try: + from app.main import app + import json + + output_dir = Path(config['output']) + output_dir.mkdir(parents=True, exist_ok=True) + + # 导出 OpenAPI JSON + with open(output_dir / 'openapi.json', 'w', encoding='utf-8') as f: + json.dump(app.openapi(), f, indent=2, ensure_ascii=False) + + print(f"✓ FastAPI: {len(app.openapi().get('paths', {}))} endpoints") + return True + except Exception as e: + print(f"✗ FastAPI error: {e}") + return False + +def extract_typescript(config): + """提取 TypeScript 文档""" + try: + subprocess.run([ + 'npx', 'typedoc', + '--plugin', 'typedoc-plugin-markdown', + '--out', config['output'], + '--entryPoints', './lib', './hooks', + '--entryPointStrategy', 'expand' + ], cwd=config['path'], check=True) + print(f"✓ TypeDoc: {config['path']}") + return True + except Exception as e: + print(f"✗ TypeDoc error: {e}") + return False + +def extract_python(config): + """提取 Python 模块文档""" + try: + module_name = Path(config['path']).name + subprocess.run([ + 'pdoc', module_name, + '--output-dir', config['output'], + '--format', 'markdown' + ], cwd=Path(config['path']).parent, check=True) + print(f"✓ pdoc: {module_name}") + return True + except Exception as e: + print(f"✗ pdoc error: {e}") + return False + +EXTRACTORS = { + 'fastapi': extract_fastapi, + 'typescript': extract_typescript, + 'python': extract_python +} + +if __name__ == '__main__': + for name, config in PROJECTS.items(): + print(f"\n[{name}]") + extractor = EXTRACTORS.get(config['type']) + if extractor: + extractor(config) +``` + +## Phase 3 集成 + +在 `api-reference` Agent 提示词中添加: + +``` +[PRE-EXTRACTION] +运行 API 提取脚本获取结构化文档: +- python scripts/extract_all_apis.py + +[INPUT FILES] +- api-docs/backend/openapi.json (FastAPI endpoints) +- api-docs/frontend/*.md (TypeDoc output) +- api-docs/hydro_generator/*.md (pdoc output) +- api-docs/multiphysics/*.md (pdoc output) +``` + +## 输出结构 + +``` +api-docs/ +├── backend/ +│ ├── openapi.json # Raw OpenAPI spec +│ └── API_REFERENCE.md # Converted Markdown +├── frontend/ +│ ├── modules.md +│ ├── functions.md +│ └── classes/ +├── hydro_generator/ +│ ├── assembler.md +│ ├── blueprint.md +│ └── builders/ +└── multiphysics/ + ├── analysis_domain.md + ├── builders.md + └── compilers.md +``` diff --git a/.claude/skills/software-manual/scripts/bundle-libraries.md b/.claude/skills/software-manual/scripts/bundle-libraries.md new file mode 100644 index 00000000..1cb0505b --- /dev/null +++ b/.claude/skills/software-manual/scripts/bundle-libraries.md @@ -0,0 +1,85 @@ +# 库文件打包说明 + +## 依赖库 + +HTML 组装阶段需要内嵌以下成熟库(无 CDN 依赖): + +### 1. marked.js - Markdown 解析 + +```bash +# 获取最新版本 +curl -o templates/libs/marked.min.js https://unpkg.com/marked/marked.min.js +``` + +### 2. highlight.js - 代码语法高亮 + +```bash +# 获取核心 + 常用语言包 +curl -o templates/libs/highlight.min.js https://unpkg.com/@highlightjs/cdn-assets/highlight.min.js + +# 获取 github-dark 主题 +curl -o templates/libs/github-dark.min.css https://unpkg.com/@highlightjs/cdn-assets/styles/github-dark.min.css +``` + +## 内嵌方式 + +Phase 5 Agent 应: + +1. 读取 `templates/libs/*.js` 和 `*.css` +2. 将内容嵌入 HTML 的 `