├── .cursor
└── rules
├── .gitignore
├── LICENSE
├── PROJECT_PROGRESS.md
├── QUICKSTART.md
├── README.md
├── README.zh.md
├── learning_notes
├── daily
│ └── 2025-03-12.json
├── reviews
│ └── review_20250312.json
├── stats.json
└── topics
│ ├── python
│ └── 2025-03-12-0002.json
│ └── test
│ └── 2025-03-12-0001.json
├── learning_paths
├── current_path.json
└── paths.json
├── pdm.lock
├── project_management
├── .task_count
├── actuals
│ ├── decisions
│ │ └── .gitkeep
│ ├── reports
│ │ ├── daily
│ │ │ └── .gitkeep
│ │ └── weekly
│ │ │ └── .gitkeep
│ └── tasks
│ │ └── TASK-001_开发命令系统核心功能.md
├── control
│ ├── MAIN_CONTROL.md
│ └── REQUIREMENTS.md
├── scripts
│ └── create_task.sh
└── templates
│ ├── daily_report_template.md
│ ├── decision_template.md
│ ├── main_control_template.md
│ ├── project_progress_template.md
│ ├── risk_template.md
│ ├── task_template.md
│ └── weekly_report_template.md
├── pyproject.toml
├── requirements.txt
├── scripts
├── create_report.sh
├── generate_timestamp.py
├── hooks
│ └── pre-commit
├── init_project.sh
├── simple_timestamp.sh
├── timestamp.sh
└── update_progress.sh
├── setup.py
└── src
└── cursormind
├── __init__.py
├── __main__.py
├── cli.py
├── config
├── __init__.py
└── settings.py
├── core
├── __init__.py
├── achievement.py
├── code_review.py
├── command_handler.py
├── cursor_framework.py
├── learning_path.py
├── note_manager.py
└── project_manager.py
└── utils
├── __init__.py
├── helpers.py
└── note_manager.py
/.cursor/rules:
--------------------------------------------------------------------------------
1 | # Cursor Engineering Rules v2.0
2 |
3 | ## Project Management Structure
4 | - Use `project_management/control/MAIN_CONTROL.md` as the single source of truth for project status
5 | - Follow standardized naming conventions for all reports:
6 | - Daily: `project_management/actuals/reports/daily/daily_report_YYYYMMDD.md`
7 | - Weekly: `project_management/actuals/reports/weekly/weekly_report_YYYYWNN.md`
8 | - Decisions: `project_management/actuals/decisions/decision_DID.md`
9 | - Update `PROJECT_PROGRESS.md` for stakeholder-facing progress tracking
10 | - Always use `scripts/generate_timestamp.py` to generate consistent timestamps
11 | - Supported formats: full, date, datetime, compact, week
12 | - Never create or modify timestamps manually
13 |
14 | ## Code Development Standards
15 | - Implement complete, production-ready code with proper error handling
16 | - Maintain 80% code to 20% documentation ratio in implementation files
17 | - Follow language-specific best practices (PEP8 for Python, etc.)
18 | - Ensure unit test coverage for all new functionality (minimum 85%)
19 | - Document public APIs with standardized docstrings
20 | - Review code for security vulnerabilities before submission
21 | - Never reference non-existent files, functions, or features
22 |
23 | ## Workflow Optimization
24 | - Use [CODE NOW] when analysis exceeds 5 minutes without concrete progress
25 | - Implement [FOCUS] technique to establish clear context boundaries
26 | - Apply [RESET] command to break circular reasoning patterns
27 | - Use [DECISION] marker to document important engineering choices
28 | - Follow "implement, test, refactor" development cycle
29 | - Commit frequently with descriptive, atomic changes
30 | - Avoid thought loops: prioritize execution over excessive analysis
31 | - When uncertain, ask directly instead of making assumptions
32 |
33 | ## Task Execution Guidelines
34 | - Define tasks with SMART criteria (Specific, Measurable, Achievable, Relevant, Time-bound)
35 | - Break large tasks into sub-tasks of no more than 4 hours each
36 | - Include verification methods and acceptance criteria for each task
37 | - Link tasks to specific project requirements or objectives
38 | - Document blockers and dependencies explicitly
39 | - Set clear completion deadlines for all tasks
40 | - Provide clear progress updates during long-running tasks
41 |
42 | ## Quality Assurance Practices
43 | - Conduct peer code reviews for all significant changes
44 | - Run static analysis tools before committing (linters, type checkers)
45 | - Validate against performance benchmarks for critical components
46 | - Document edge cases and their handling mechanisms
47 | - Maintain backward compatibility unless explicitly specified otherwise
48 | - Create regression tests for all bug fixes
49 |
50 | ## Documentation Integrity
51 | - README files must accurately reflect actual project functionality
52 | - Never add descriptions of unimplemented features
53 | - Verify functionality exists before updating documentation
54 | - When referencing code, specify exact file paths and line numbers
55 | - Maintain consistent version numbers across all documents
56 |
57 | ## Memory and Context Management
58 | - Always reference current file contents before making changes
59 | - Review previous conversations to maintain context continuity
60 | - Keep track of project history and development decisions
61 | - Do not forget previous instructions or requirements
62 | - When context is unclear, review existing files before proceeding
63 |
64 | ## Error Handling Protocol
65 | - Acknowledge errors immediately without justification
66 | - Correct mistakes based on actual project content
67 | - When fabrication is detected, reset and respond with verified information
68 | - Provide concise, accurate responses without unnecessary elaboration
69 | - Document error patterns to prevent recurrence
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Python虚拟环境
2 | .venv/
3 | __pycache__/
4 | *.py[cod]
5 | *$py.class
6 |
7 | # 日报和周报文件
8 | project_management/actuals/reports/daily/*.md
9 | project_management/actuals/reports/weekly/*.md
10 | !project_management/actuals/reports/daily/.gitkeep
11 | !project_management/actuals/reports/weekly/.gitkeep
12 |
13 | # 决策记录
14 | project_management/actuals/decisions/*.md
15 | !project_management/actuals/decisions/.gitkeep
16 |
17 | # 临时文件
18 | temp_*.md
19 |
20 | # 系统文件
21 | .DS_Store
22 | Thumbs.db
23 |
24 | # 本地讨论文件
25 | project_management/ideaguide.md
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 yagami
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PROJECT_PROGRESS.md:
--------------------------------------------------------------------------------
1 | # 项目进度跟踪
2 |
3 | ## 项目信息
4 | - **项目名称**: CursorMind
5 | - **版本**: Beta 0.1 -> Beta 0.2.1
6 | - **开始日期**: 2025-03-07
7 | - **计划完成日期**: 2025-03-15
8 | - **当前状态**: 进行中
9 | - **当前进度**: 75%
10 |
11 | ## 里程碑
12 | | 里程碑 | 计划日期 | 实际日期 | 状态 | 负责人 |
13 | |-------|---------|---------|------|-------|
14 | | 项目启动 | 2025-03-07 | 2025-03-07 | 已完成 | Team |
15 | | Beta 0.1发布 | 2025-03-07 | 2025-03-07 | 已完成 | Team |
16 | | 核心功能重构 | 2025-03-12 | 2025-03-12 | 已完成 | Team |
17 | | Beta 0.2.1发布 | 2025-03-12 | 2025-03-12 | 已完成 | Team |
18 | | 文档完善 | 2025-03-13 | | 进行中 | Team |
19 | | 功能测试 | 2025-03-14 | | 未开始 | Team |
20 | | 正式版本发布 | 2025-03-15 | | 未开始 | Team |
21 |
22 | ## 进度更新历史
23 | | 日期 | 进度 | 更新内容 | 更新人 |
24 | |------|------|---------|-------|
25 | | 2025-03-07 | 15% | 项目初始化完成,基础框架搭建 | Team |
26 | | 2025-03-11 | 25% | Beta 0.1文档规范化完成,规划后续版本开发 | Team |
27 | | 2025-03-12 | 75% | 完成核心功能重构,发布Beta 0.2.1版本:
- 重构代码审查功能
- 优化性能检查逻辑
- 增强文件操作安全性
- 完善项目管理功能
- 添加学习路径功能
- 更新中英文文档 | Team |
28 |
29 | ## 已完成功能
30 | 1. **代码质量保证**
31 | - 代码风格检查
32 | - 性能分析系统
33 | - 安全检查机制
34 | - 最佳实践建议
35 |
36 | 2. **项目管理工具**
37 | - 进度追踪系统
38 | - 任务管理功能
39 | - 报告生成器
40 | - 团队协作功能
41 |
42 | 3. **学习与发展**
43 | - 学习路径管理
44 | - 最佳实践指南
45 | - 示例代码库
46 | - 技术文档系统
47 |
48 | ## 风险与问题
49 | | ID | 描述 | 影响程度 | 状态 | 解决方案 | 负责人 |
50 | |----|-----|---------|------|---------|-------|
51 | | R001 | 功能扩展与复杂度平衡 | 低 | 已解决 | 采用模块化设计,实现功能解耦 | Team |
52 | | R002 | 文档更新及时性 | 低 | 已解决 | 建立实时文档更新机制 | Team |
53 | | R003 | 用户体验一致性 | 中 | 开放 | 制定统一的UI/UX规范 | Team |
54 | | R004 | 跨平台兼容性 | 中 | 开放 | 增加平台特定的适配层 | Team |
55 |
56 | ## 下一步计划
57 | - [ ] 完善单元测试覆盖率
58 | - [ ] 添加更多实用示例
59 | - [ ] 优化错误处理机制
60 | - [ ] 改进命令行交互体验
61 | - [ ] 编写详细的API文档
62 | - [ ] 制作视频教程和演示
63 | - [ ] 建立用户反馈系统
64 |
65 | ## 版本规划
66 | ### 即将发布 (2025-03-15)
67 | - 完整的测试覆盖
68 | - 优化的错误处理
69 | - 改进的用户体验
70 | - 详细的API文档
71 | - 更多使用示例
72 |
73 | ### 未来规划
74 | - 集成更多IDE支持
75 | - 添加插件系统
76 | - 支持更多编程语言
77 | - 引入AI辅助功能
78 | - 添加可视化界面
79 |
80 | ## 备注
81 | Beta 0.2.1版本标志着项目的重要里程碑,核心功能已经完成重构,接下来将专注于提升用户体验和完善文档体系。项目进展顺利,预计能按期完成最终发布。
82 |
83 | ---
84 | *最后更新: 2025-03-11 23:37:45 PDT*
--------------------------------------------------------------------------------
/QUICKSTART.md:
--------------------------------------------------------------------------------
1 | # CursorMind 快速入门指南
2 |
3 | ## 简介
4 | CursorMind (Beta 0.1.1) 是一个专为Cursor开发者设计的轻量级项目管理框架,帮助您在使用AI辅助编程的同时,培养良好的软件工程实践。
5 |
6 | ## 快速开始(5分钟上手)
7 |
8 | ### 1. 初始化项目
9 | ```bash
10 | # 克隆项目
11 | git clone [your-repo-url]
12 | cd your-project
13 |
14 | # 初始化项目结构
15 | ./project_management/scripts/init_project.sh "我的新项目"
16 | ```
17 |
18 | ### 2. 日常工作流程
19 |
20 | #### 创建并更新日报
21 | ```bash
22 | # 创建今日工作报告
23 | ./project_management/scripts/create_daily_report.sh
24 |
25 | # 示例:更新今日工作内容
26 | vim project_management/actuals/reports/daily/daily_report_20250311.md
27 |
28 | # 更新项目进度(例:完成35%并添加说明)
29 | ./project_management/scripts/update_progress.sh 35 "完成用户认证模块开发"
30 | ```
31 |
32 | #### 生成周报
33 | ```bash
34 | # 在每周结束时生成周报
35 | ./project_management/scripts/create_weekly_report.sh
36 |
37 | # 系统会自动汇总本周的日报内容
38 | ```
39 |
40 | #### 创建新任务
41 | ```bash
42 | # 创建新任务
43 | ./project_management/scripts/create_task.sh "实现用户登录功能"
44 |
45 | # 更新任务状态
46 | ./project_management/scripts/update_task.sh TASK-001 "进行中"
47 | ```
48 |
49 | ### 3. 项目管理最佳实践
50 | - 每日更新工作日报,记录具体进展
51 | ```markdown
52 | ## 今日工作内容
53 | 1. 完成用户认证模块
54 | - 实现JWT认证
55 | - 添加密码加密
56 | ```
57 | - 及时更新项目进度文件
58 | ```markdown
59 | ## 项目进度
60 | - 版本: Beta 0.1.1
61 | - 进度: 35%
62 | - 说明: 完成核心功能开发
63 | ```
64 | - 使用标准命令管理工作流
65 | ```bash
66 | # 当遇到问题需要重新规划时
67 | [RESET] ./project_management/scripts/reset_task.sh TASK-001
68 |
69 | # 当需要快速开始执行时
70 | [CODE NOW] ./project_management/scripts/start_task.sh TASK-001
71 | ```
72 |
73 | ## 项目结构
74 | ```
75 | project_management/
76 | ├── control/ # 项目控制文档
77 | │ └── MAIN_CONTROL.md # 项目主控制文件
78 | ├── templates/ # 文档模板
79 | │ ├── daily_report_template.md
80 | │ ├── weekly_report_template.md
81 | │ └── task_template.md
82 | ├── actuals/ # 实际文档
83 | │ └── reports/ # 报告目录
84 | │ ├── daily/ # 日报
85 | │ └── weekly/ # 周报
86 | └── scripts/ # 工具脚本
87 | ├── init_project.sh
88 | ├── create_daily_report.sh
89 | └── update_progress.sh
90 | ```
91 |
92 | ## 常见命令
93 | - `create_daily_report.sh`: 创建今日工作报告
94 | ```bash
95 | # 示例:创建带有特定说明的日报
96 | ./project_management/scripts/create_daily_report.sh "重要版本发布"
97 | ```
98 | - `create_weekly_report.sh`: 生成本周工作报告
99 | ```bash
100 | # 示例:生成指定周的报告
101 | ./project_management/scripts/create_weekly_report.sh 2025W11
102 | ```
103 | - `update_progress.sh`: 更新项目进度
104 | ```bash
105 | # 示例:更新进度并添加里程碑
106 | ./project_management/scripts/update_progress.sh 50 "完成MVP版本"
107 | ```
108 |
109 | ## 注意事项
110 | 1. 所有时间戳使用PST时区
111 | ```markdown
112 | ## 时间
113 | 2025-03-11 20:02:41 PST
114 | ```
115 | 2. 文档命名遵循规范
116 | ```
117 | daily_report_20250311.md
118 | weekly_report_2025W11.md
119 | TASK-001_user_auth.md
120 | ```
121 | 3. 确保Git忽略了正确的文件
122 | ```gitignore
123 | # .gitignore示例
124 | .DS_Store
125 | node_modules/
126 | .env
127 | ```
128 |
129 | ## 常见问题
130 |
131 | Q: 如何修改默认时区?
132 | A: 编辑project_management/scripts/config.sh:
133 | ```bash
134 | # 修改时区设置
135 | TIMEZONE="America/Los_Angeles" # PST时区
136 | ```
137 |
138 | Q: 报告格式是否可以自定义?
139 | A: 可以修改templates/目录下的对应模板:
140 | ```markdown
141 | # 自定义日报模板示例
142 | ## 时间
143 | [TIMESTAMP]
144 |
145 | ## 自定义字段
146 | [YOUR_CONTENT]
147 | ```
148 |
149 | Q: 如何处理任务依赖关系?
150 | A: 在任务模板中明确标注:
151 | ```markdown
152 | ## 依赖关系
153 | - 前置任务: TASK-001, TASK-002
154 | - 后续任务: TASK-004
155 | ```
156 |
157 | ## 获取帮助
158 | 如有问题,请参考:
159 | 1. 项目文档(docs/)
160 | 2. 示例项目(examples/)
161 | 3. 提交Issue获取支持
162 |
163 | ## 命令速查表
164 | | 命令 | 说明 | 示例 |
165 | |-----|------|-----|
166 | | init_project.sh | 初始化项目 | ./scripts/init_project.sh "项目名" |
167 | | create_daily_report.sh | 创建日报 | ./scripts/create_daily_report.sh |
168 | | update_progress.sh | 更新进度 | ./scripts/update_progress.sh 35 "说明" |
169 | | create_task.sh | 创建任务 | ./scripts/create_task.sh "任务名" |
170 |
171 | ---
172 | *最后更新: 2025-03-11 20:02:41 PST*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ✨ CursorMind
2 |
3 |
4 | English Version |
5 | 中文版
6 |
7 |
8 |
9 |
CursorMind
10 |
Elevate Your Development Experience with AI-Powered Tools
11 |
Current Version: Beta 0.2.1
12 |
13 | 
14 | 
15 | 
16 | 
17 | 
18 |
19 |
20 | ## 📝 Update Log
21 |
22 | ### Beta 0.2.1 (2025-03-12 00:25:02 PDT)
23 | - 🔄 Enhanced core architecture for improved stability and performance
24 | - ✨ Introduced comprehensive code review system with multi-standard support
25 | - 🛡️ Strengthened file operation security mechanisms
26 | - ⚡️ Optimized performance analysis algorithms
27 | - 📊 Expanded project management capabilities
28 | - 📚 Launched interactive learning paths feature
29 |
30 | ### Beta 0.1 (2025-03-07)
31 | - 🎉 Initial release with foundational framework
32 | - ✅ Core functionality implementation
33 |
34 | ---
35 |
36 | ## 📖 Project Introduction
37 |
38 | 🌟 **CursorMind** is your intelligent companion for AI-assisted development, designed to serve developers 👨💻, project managers 👨💼, teams 👥, and students 👨🎓. Beyond traditional development tools, it integrates code quality assurance 🛠️, project management 📊, learning assistance 📚, and best practice guidelines 📝. For students beginning their programming journey, CursorMind provides an ideal platform 🎯 to develop proper software engineering mindset 🧠 from day one.
39 |
40 | ### 🎯 Core Values
41 |
42 | 1. **Educational Excellence**
43 | - Structured learning paths for programming beginners
44 | - Standardized teaching frameworks for educators
45 | - Hands-on projects for practical skill development
46 |
47 | 2. **Development Standards**
48 | - Industry-aligned coding guidelines
49 | - Best practice implementations
50 | - Quality-focused development approach
51 |
52 | 3. **Project Management**
53 | - Streamlined project workflows
54 | - Enhanced team collaboration
55 | - Quality-driven delivery process
56 |
57 | 4. **Automation Tools**
58 | - Intelligent code quality assessment
59 | - Performance optimization tools
60 | - Security vulnerability detection
61 |
62 | ## 🚀 Feature Details
63 |
64 | CursorMind offers comprehensive development support:
65 |
66 | ### 1. Code Quality Assurance ⚡️
67 | - Smart code review with standard compliance
68 | - Performance analysis and optimization
69 | - Automated security vulnerability detection
70 | - Best practice guidance
71 |
72 | ### 2. Project Management Tools 📊
73 | - Project progress tracking
74 | - Team collaboration workflows
75 | - Automated reporting system
76 | - Quality metrics monitoring
77 |
78 | ### 3. Learning & Development 📚
79 | - Personalized learning paths
80 | - Rich resource library
81 | - Practical project exercises
82 | - Skill assessment tools
83 |
84 | ### 4. Development Tools Integration 🛠️
85 | - Automated workflow configuration
86 | - Version control integration
87 | - CI/CD pipeline support
88 | - Development environment standardization
89 |
90 |
91 | View Detailed Feature List 👉
92 |
93 | - **Code Review**
94 | - Style Compliance: PEP8, Google Style, and other standard checks
95 | - Complexity Analysis: Cyclomatic complexity calculation and refactoring suggestions
96 | - Naming Conventions: Best practice validation for variables, functions, and classes
97 | - Documentation Coverage: Critical functionality documentation verification
98 |
99 | - **Performance Analysis**
100 | - Algorithm Complexity: Time and space complexity assessment
101 | - Memory Management: Leak detection and usage optimization
102 | - Performance Profiling: Bottleneck identification
103 | - Optimization Guide: Targeted improvement recommendations
104 |
105 | - **Project Management**
106 | - Progress Tracking: Milestone management and burndown analysis
107 | - Task Management: Smart task breakdown and workload assessment
108 | - Team Collaboration: Code review workflow and knowledge sharing
109 | - Quality Monitoring: Automated testing and performance tracking
110 |
111 | - **Learning Resources**
112 | - Skill Map: Personalized improvement pathways
113 | - Practice Projects: Curated exercise collection
114 | - Best Practices: Detailed coding standards and architecture guidelines
115 | - Reference Code: Common functionality implementations
116 |
117 | - **Tool Integration**
118 | - CI/CD: Pipeline configuration and automation
119 | - Git Integration: Version control and branch management
120 | - Environment Setup: Development environment automation
121 | - IDE Support: Popular development tool integration
122 |
123 |
124 | ## 🎯 Getting Started
125 |
126 | Choose your path with CursorMind:
127 |
128 | ### 1. Individual Developer 👨💻
129 |
130 | Quick start with code quality tools:
131 | ```bash
132 | # Install the toolkit
133 | pip install cursormind
134 | export PYTHONPATH=src # Unix/macOS
135 | set PYTHONPATH=src # Windows
136 |
137 | # Begin using
138 | cursormind review file your_code.py # Code review
139 | cursormind analyze dir your_project/ # Project analysis
140 | ```
141 |
142 | ### 2. Learner 📚
143 |
144 | Start your learning journey:
145 | ```bash
146 | # Browse available learning paths
147 | cursormind path list
148 |
149 | # Begin a learning path (e.g., Python basics)
150 | cursormind path start python-beginner
151 |
152 | # Check progress and resources
153 | cursormind path status
154 |
155 | # Complete current task and get next steps
156 | cursormind path next
157 | ```
158 |
159 | ### 3. Project Team 👥
160 |
161 | Structured project management workflow:
162 | ```bash
163 | # Step 1: Initialize new project
164 | ./project_management/scripts/init_project.sh "Project Name"
165 |
166 | # Step 2: Daily workflow management
167 | ./project_management/scripts/create_daily_report.sh # Daily report
168 | ./project_management/scripts/update_progress.sh 35 "Auth module complete" # Update progress
169 | ./project_management/scripts/create_task.sh "Implement login" # Create task
170 | ./project_management/scripts/update_task.sh TASK-001 "In Progress" # Update status
171 |
172 | # Step 3: Generate reports
173 | ./project_management/scripts/create_weekly_report.sh # Weekly summary
174 | ```
175 |
176 |
177 | View Detailed Usage Guide 👉
178 |
179 | ### Developer Workflow
180 |
181 | 1. **Quality Management**
182 | - Use `cursormind review` for code analysis
183 | - Run `cursormind analyze` for project assessment
184 | - Apply recommended best practices
185 | - Address security vulnerabilities
186 |
187 | 2. **Documentation Management**
188 | - Use standardized templates (`project_management/templates/`)
189 | - Follow timestamp conventions (`scripts/generate_timestamp.py`)
190 | - Maintain progress tracking (`PROJECT_PROGRESS.md`)
191 | - Document technical decisions
192 |
193 | 3. **Engineering Standards**
194 | - Follow language-specific guidelines (e.g., PEP8 for Python)
195 | - Maintain code-to-documentation ratio (80:20)
196 | - Ensure test coverage (minimum 85%)
197 | - Regular security audits
198 |
199 | ### Learning Guide
200 |
201 | 1. **Path Selection**
202 | - Browse available paths (`learning_paths/`)
203 | - Choose appropriate skill level
204 | - Set learning objectives
205 | - Track progress
206 |
207 | 2. **Resource Utilization**
208 | - Access recommended materials
209 | - Complete milestone projects
210 | - Study example implementations
211 | - Document learning insights
212 |
213 | 3. **Practical Development**
214 | - Use project templates
215 | - Apply learned concepts
216 | - Get mentor feedback
217 | - Continuous improvement
218 |
219 | ### Team Collaboration
220 |
221 | 1. **Project Setup**
222 | ```bash
223 | # Create project structure
224 | ./project_management/scripts/init_project.sh "Project Name"
225 |
226 | # Configure workflow
227 | cp project_management/templates/* ./
228 | ```
229 |
230 | 2. **Daily Operations**
231 | ```bash
232 | # Create daily report
233 | ./project_management/scripts/create_daily_report.sh "Version Release"
234 |
235 | # Update progress
236 | ./project_management/scripts/update_progress.sh 50 "MVP Complete"
237 |
238 | # Task management
239 | ./project_management/scripts/create_task.sh "New Feature"
240 | ./project_management/scripts/update_task.sh TASK-001 "In Progress"
241 | ```
242 |
243 | 3. **Quality Control**
244 | ```bash
245 | # Code review
246 | cursormind review file src/main.py
247 |
248 | # Project analysis
249 | cursormind analyze dir ./src
250 |
251 | # Quality report
252 | ./project_management/scripts/generate_quality_report.sh
253 | ```
254 |
255 | ### Best Practices
256 |
257 | 1. **Individual Development**
258 | - Pre-commit code review
259 | - Real-time documentation updates
260 | - Coding standard compliance
261 | - Regular performance optimization
262 |
263 | 2. **Learning Enhancement**
264 | - Structured learning plan
265 | - Consistent practice
266 | - Regular reflection
267 | - Community engagement
268 |
269 | 3. **Team Collaboration**
270 | - Standard adherence
271 | - Effective communication
272 | - Knowledge sharing
273 | - Regular code reviews
274 |
275 |
276 |
277 | ## 💻 Installation Guide
278 |
279 | Quick Start:
280 | 1. Ensure Python 3.9-3.13 is installed
281 | 2. Run installation commands:
282 | ```bash
283 | pip install cursormind
284 | export PYTHONPATH=src # Unix/macOS
285 | set PYTHONPATH=src # Windows
286 | ```
287 |
288 |
289 | View Complete Installation Guide 👉
290 |
291 | ### System Requirements
292 |
293 | - Python 3.9-3.13 (3.13 recommended)
294 | - pip package manager
295 | - Git (optional, for version control)
296 |
297 | ### Windows Installation
298 |
299 | 1. **Install Python**
300 | ```powershell
301 | # Download Python 3.13 from https://www.python.org/downloads/
302 | # Enable "Add Python to PATH" during installation
303 | ```
304 |
305 | 2. **Setup Environment**
306 | ```powershell
307 | # Create and activate virtual environment
308 | python -m venv .venv
309 | .\.venv\Scripts\Activate.ps1
310 | ```
311 |
312 | 3. **Install CursorMind**
313 | ```powershell
314 | pip install --upgrade pip
315 | pip install cursormind
316 | $env:PYTHONPATH = "src"
317 | ```
318 |
319 | ### macOS/Linux Installation
320 |
321 | 1. **Create Environment**
322 | ```bash
323 | python3.13 -m venv .venv
324 | source .venv/bin/activate
325 | ```
326 |
327 | 2. **Install CursorMind**
328 | ```bash
329 | pip install --upgrade pip
330 | pip install cursormind
331 | export PYTHONPATH=src
332 | ```
333 |
334 | ### Verify Installation
335 |
336 | Run these commands:
337 | ```bash
338 | cursormind --version
339 | cursormind review file your_code.py
340 | ```
341 |
342 | For issues, refer to the troubleshooting guide below.
343 |
344 |
345 | ### ❗ Common Issues
346 |
347 | Quick solutions for common problems:
348 |
349 | 1. Verify Python version compatibility (3.9-3.13)
350 | 2. Check PYTHONPATH environment variable
351 | 3. Confirm virtual environment activation
352 |
353 |
354 | View Complete Troubleshooting Guide 👉
355 |
356 | ### Windows Troubleshooting
357 |
358 | 1. **Python PATH Issues**
359 | ```powershell
360 | # Check Python installation
361 | python --version
362 |
363 | # Manual PATH addition if needed
364 | # System Properties -> Environment Variables -> Path
365 | # Add: C:\Users\username\AppData\Local\Programs\Python\Python313
366 | ```
367 |
368 | 2. **Virtual Environment Problems**
369 | ```powershell
370 | # Fix permission issues
371 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
372 |
373 | # Reactivate environment
374 | .\.venv\Scripts\Activate.ps1
375 | ```
376 |
377 | 3. **Module Import Errors**
378 | ```powershell
379 | # Verify PYTHONPATH
380 | echo $env:PYTHONPATH
381 |
382 | # Reset if needed
383 | $env:PYTHONPATH = "src"
384 | ```
385 |
386 | ### macOS Troubleshooting
387 |
388 | 1. **Python Version Issues**
389 | ```bash
390 | # Version check
391 | python3 --version
392 |
393 | # Use specific version
394 | python3.13 -m pip install cursormind
395 | ```
396 |
397 | 2. **Permission Problems**
398 | ```bash
399 | # Fix permissions
400 | sudo chown -R $USER ~/.local
401 | chmod +x ~/.local/bin/cursormind
402 | ```
403 |
404 | 3. **Environment Variables**
405 | ```bash
406 | # Add to shell profile
407 | echo 'export PYTHONPATH=src' >> ~/.zshrc
408 | source ~/.zshrc
409 | ```
410 |
411 | ### Ubuntu/Debian Troubleshooting
412 |
413 | 1. **PPA Issues**
414 | ```bash
415 | # Install prerequisites
416 | sudo apt install software-properties-common
417 |
418 | # Add PPA
419 | sudo add-apt-repository ppa:deadsnakes/ppa
420 | ```
421 |
422 | 2. **Dependency Problems**
423 | ```bash
424 | # Install build requirements
425 | sudo apt install build-essential libssl-dev libffi-dev python3.13-dev
426 | ```
427 |
428 | 3. **Permission Issues**
429 | ```bash
430 | # Fix permissions
431 | sudo chown -R $USER ~/.local
432 | sudo chmod +x ~/.local/bin/cursormind
433 | ```
434 |
435 |
436 |
437 | 🕒 Timestamp Standards
438 |
439 | Ensure consistency in project documentation with our timestamp tools.
440 |
441 | ### Using Timestamp Tools
442 |
443 | ```bash
444 | # Generate full timestamp (default)
445 | python3 scripts/generate_timestamp.py full
446 | # Output: 2025-03-11 23:37:45 PDT
447 |
448 | # Date only
449 | python3 scripts/generate_timestamp.py date
450 | # Output: 2025-03-11
451 |
452 | # Date and time (no timezone)
453 | python3 scripts/generate_timestamp.py datetime
454 | # Output: 2025-03-11 23:37:45
455 |
456 | # Compact format
457 | python3 scripts/generate_timestamp.py compact
458 | # Output: 20250311
459 |
460 | # Year and week
461 | python3 scripts/generate_timestamp.py week
462 | # Output: 2025W11
463 | ```
464 |
465 | ### Timestamp Guidelines
466 |
467 | 1. **Requirements**
468 | - Use `scripts/generate_timestamp.py` for all timestamps
469 | - No manual timestamp modifications
470 | - Maintain consistent timezone (default: US Pacific Time PST/PDT)
471 | - Configure timezone in `.env` file if needed
472 |
473 | 2. **Git Hook Setup**
474 | ```bash
475 | # Copy pre-commit hook
476 | cp scripts/hooks/pre-commit .git/hooks/
477 |
478 | # Set permissions
479 | chmod +x .git/hooks/pre-commit
480 | ```
481 |
482 |
483 | ### 📢 Manifesto
484 |
485 | We believe:
486 | - Technology should be accessible to everyone
487 | - Cursor is more than an IDE; it's a gateway to smarter programming
488 | - CursorMind empowers developers with AI-assisted programming
489 | - Open source drives technological progress - fork and contribute!
490 |
491 | ### 🤝 Community Participation
492 |
493 | Join our vibrant community:
494 | - 🌟 Star us if you find CursorMind helpful
495 | - 🐛 Report bugs via [Issues](https://github.com/yourusername/cursormind/issues)
496 | - 💡 Submit [Pull Requests](https://github.com/yourusername/cursormind/pulls)
497 | - 📝 Help improve documentation
498 | - 💬 Share your experience and suggestions
499 |
500 | Let's build better AI programming tools together!
501 |
502 | #### 📜 MIT License
503 |
504 | CursorMind is released under the MIT License, which means:
505 | - ✅ You can freely use, modify, and distribute this software
506 | - ✅ You can use it for commercial projects
507 | - ✅ You can make and distribute closed source versions
508 | - ℹ️ The only requirement is to include the original copyright notice and license
509 |
510 | We encourage individuals and organizations to:
511 | - 🔄 Fork and modify the project for your specific needs
512 | - 🌱 Share your improvements back with the community
513 | - 🤝 Collaborate on making AI-assisted development more accessible
514 |
515 | For full license details, see the [LICENSE](LICENSE) file.
516 |
517 |
518 |
519 | *Cursor empowers efficiency, while your vision creates the future.*
520 |
521 |
522 |
523 | ---
524 | *Last updated: 2025-03-12 02:37:42 PDT*
525 |
--------------------------------------------------------------------------------
/README.zh.md:
--------------------------------------------------------------------------------
1 | # ✨ CursorMind
2 |
3 |
4 | English Version |
5 | 中文版
6 |
7 |
8 |
9 |
CursorMind
10 |
提升您的 Cursor 开发效率与项目管理质量
11 |
当前版本:Beta 0.2.1
12 |
13 | 
14 | 
15 | 
16 | 
17 | 
18 |
19 |
20 | ## 📝 更新日志
21 |
22 | ### Beta 0.2.1 (2025-03-12 00:25:02 PDT)
23 | - 🔄 重构核心代码结构,提升系统稳定性
24 | - ✨ 新增代码审查功能,支持多种编码规范
25 | - 🛡️ 增强文件操作安全性,防止潜在风险
26 | - ⚡️ 优化性能检查逻辑,提升分析效率
27 | - 📊 改进项目管理功能,支持更多场景
28 | - 📚 添加学习路径功能,助力编程教育
29 |
30 | ### Beta 0.1 (2025-03-07)
31 | - 🎉 发布初始项目结构
32 | - ✅ 实现基础功能模块
33 |
34 | ---
35 |
36 | ## 📖 项目简介
37 |
38 | 🌟 **CursorMind** 是一个面向开发者 👨💻、项目经理 👨💼、团队 👥 和学生 👨🎓 的综合性开发工具集。它不仅提供了代码质量保证工具 🛠️,还包含了项目管理 📊、学习辅助 📚 和最佳实践指南 📝 等功能模块。对于正在学习编程的中小学生来说,CursorMind 提供了一个理想的学习平台 🎯,帮助他们在编程启蒙阶段就建立正确的软件工程思维 🧠。
39 |
40 | ### 🎯 核心价值
41 |
42 | 1. **教育赋能**
43 | - 为编程初学者提供循序渐进的学习路径
44 | - 帮助教育工作者建立标准化的教学体系
45 | - 通过实践项目培养工程思维
46 |
47 | 2. **开发规范**
48 | - 提供业界认可的编码标准
49 | - 实施最佳开发实践
50 | - 保证代码质量和一致性
51 |
52 | 3. **项目管理**
53 | - 标准化项目流程
54 | - 提高团队协作效率
55 | - 确保项目交付质量
56 |
57 | 4. **自动化工具**
58 | - 代码质量自动检查
59 | - 性能分析和优化
60 | - 安全漏洞检测
61 |
62 | ## 🚀 功能详情
63 |
64 | CursorMind 为您提供全方位的开发支持:
65 |
66 | ### 1. 代码质量保证 ⚡️
67 | - 智能代码审查,确保编码规范
68 | - 性能分析与优化建议
69 | - 安全漏洞自动检测
70 | - 最佳实践指导
71 |
72 | ### 2. 项目管理工具 📊
73 | - 项目进度追踪与管理
74 | - 团队协作流程规范
75 | - 自动化报告生成
76 | - 质量指标监控
77 |
78 | ### 3. 学习与发展 📚
79 | - 个性化学习路径规划
80 | - 丰富的学习资源库
81 | - 实战项目练习
82 | - 技术能力评估
83 |
84 | ### 4. 开发工具集成 🛠️
85 | - 自动化工作流配置
86 | - 代码版本控制集成
87 | - 持续集成/部署支持
88 | - 开发环境标准化
89 |
90 |
91 | 查看详细功能列表 👉
92 |
93 | - **代码审查**
94 | - 风格检查:确保代码符合 PEP8、Google Style 等主流编码规范
95 | - 复杂度分析:计算圈复杂度,识别需要重构的代码块
96 | - 命名规范:检查变量、函数、类的命名是否符合最佳实践
97 | - 注释完整性:验证关键功能是否有充分的文档说明
98 |
99 | - **性能分析**
100 | - 算法复杂度评估:分析时间和空间复杂度
101 | - 内存使用监控:识别内存泄漏和过度内存使用
102 | - 性能瓶颈定位:通过性能分析找出耗时操作
103 | - 优化建议:提供具体的性能优化方案
104 |
105 | - **项目管理**
106 | - 进度追踪:里程碑管理和燃尽图分析
107 | - 任务分配:智能任务分解和工作量评估
108 | - 团队协作:代码评审流程和知识共享
109 | - 质量监控:自动化测试和性能监测
110 |
111 | - **学习资源**
112 | - 技能图谱:个性化的技能提升路线
113 | - 实战项目:配套的练习项目集
114 | - 最佳实践:详细的编码规范和架构指南
115 | - 示例代码:常用功能的参考实现
116 |
117 | - **工具集成**
118 | - CI/CD:持续集成和部署流程配置
119 | - Git集成:版本控制和分支管理
120 | - 环境配置:开发环境自动化设置
121 | - 扩展支持:主流IDE和工具链集成
122 |
123 |
124 | ## 🎯 使用方式选择
125 |
126 | CursorMind 提供三种主要使用场景,选择最适合您的方式开始:
127 |
128 | ### 1. 个人开发者 👨💻
129 |
130 | 快速开始使用代码质量工具:
131 | ```bash
132 | # 安装工具
133 | pip install cursormind
134 | export PYTHONPATH=src # Unix/macOS
135 | set PYTHONPATH=src # Windows
136 |
137 | # 开始使用
138 | cursormind review file your_code.py # 代码审查
139 | cursormind analyze dir your_project/ # 项目分析
140 | ```
141 |
142 | ### 2. 学习者 📚
143 |
144 | 开始您的学习之旅:
145 | ```bash
146 | # 查看可用的学习路径
147 | cursormind path list
148 |
149 | # 选择并开始一个学习路径(如:Python入门)
150 | cursormind path start python-beginner
151 |
152 | # 查看当前进度和推荐资源
153 | cursormind path status
154 |
155 | # 完成当前任务并获取下一步建议
156 | cursormind path next
157 | ```
158 |
159 | ### 3. 项目团队 👥
160 |
161 | 规范化的项目管理流程:
162 | ```bash
163 | # 第1步:初始化新项目
164 | ./project_management/scripts/init_project.sh "项目名称"
165 |
166 | # 第2步:日常工作管理
167 | ./project_management/scripts/create_daily_report.sh # 创建日报
168 | ./project_management/scripts/update_progress.sh 35 "完成用户认证模块" # 更新进度
169 | ./project_management/scripts/create_task.sh "实现登录功能" # 创建新任务
170 | ./project_management/scripts/update_task.sh TASK-001 "进行中" # 更新任务状态
171 |
172 | # 第3步:生成工作报告
173 | ./project_management/scripts/create_weekly_report.sh # 生成周报
174 | ```
175 |
176 |
177 | 查看详细使用指南 👉
178 |
179 | ### 开发者工作流
180 |
181 | 1. **代码质量管理**
182 | - 使用 `cursormind review` 进行代码审查
183 | - 运行 `cursormind analyze` 进行项目分析
184 | - 应用推荐的最佳实践和优化建议
185 | - 检查并修复潜在的安全漏洞
186 |
187 | 2. **项目文档管理**
188 | - 使用标准化的文档模板(位于 `project_management/templates/`)
189 | - 遵循时间戳规范记录更新(使用 `scripts/generate_timestamp.py`)
190 | - 维护项目进度文件(`PROJECT_PROGRESS.md`)
191 | - 记录技术决策和设计方案
192 |
193 | 3. **工程实践规范**
194 | - 遵循语言特定的编码标准(如 Python 的 PEP8)
195 | - 保持代码文档比例(80:20)
196 | - 确保单元测试覆盖率(最低 85%)
197 | - 定期进行安全漏洞检查
198 |
199 | ### 学习路径指南
200 |
201 | 1. **选择学习路径**
202 | - 浏览可用的学习路径(`learning_paths/`)
203 | - 根据个人水平选择合适的路径
204 | - 设置学习目标和计划
205 | - 跟踪学习进度
206 |
207 | 2. **使用学习资源**
208 | - 查看推荐的学习资源和文档
209 | - 完成阶段性练习项目
210 | - 参考示例代码和最佳实践
211 | - 记录学习心得和问题
212 |
213 | 3. **实践项目开发**
214 | - 使用项目模板快速启动
215 | - 应用所学知识解决实际问题
216 | - 获取导师反馈和建议
217 | - 持续改进和优化
218 |
219 | ### 团队协作流程
220 |
221 | 1. **项目初始化**
222 | ```bash
223 | # 创建标准项目结构
224 | ./project_management/scripts/init_project.sh "项目名称"
225 |
226 | # 配置工作流程
227 | cp project_management/templates/* ./
228 | ```
229 |
230 | 2. **日常工作管理**
231 | ```bash
232 | # 创建今日工作报告
233 | ./project_management/scripts/create_daily_report.sh "重要版本发布"
234 |
235 | # 更新项目进度
236 | ./project_management/scripts/update_progress.sh 50 "完成MVP版本"
237 |
238 | # 创建和更新任务
239 | ./project_management/scripts/create_task.sh "新功能开发"
240 | ./project_management/scripts/update_task.sh TASK-001 "进行中"
241 | ```
242 |
243 | 3. **质量控制**
244 | ```bash
245 | # 代码审查
246 | cursormind review file src/main.py
247 |
248 | # 项目分析
249 | cursormind analyze dir ./src
250 |
251 | # 生成质量报告
252 | ./project_management/scripts/generate_quality_report.sh
253 | ```
254 |
255 | ### 最佳实践建议
256 |
257 | 1. **个人开发**
258 | - 每次提交前进行代码审查
259 | - 保持文档的实时更新
260 | - 遵循项目编码规范
261 | - 定期进行性能优化
262 |
263 | 2. **学习提升**
264 | - 制定合理的学习计划
265 | - 保持练习的连续性
266 | - 及时记录和总结
267 | - 参与社区讨论和分享
268 |
269 | 3. **团队协作**
270 | - 严格遵循项目规范
271 | - 保持良好的沟通习惯
272 | - 注重知识的沉淀和共享
273 | - 定期进行团队代码评审
274 |
275 |
276 |
277 | ## 💻 安装指南
278 |
279 | 快速开始:
280 | 1. 确保安装 Python 3.9-3.13
281 | 2. 运行安装命令:
282 | ```bash
283 | pip install cursormind
284 | export PYTHONPATH=src # Unix/macOS
285 | set PYTHONPATH=src # Windows
286 | ```
287 |
288 |
289 | 查看完整安装说明 👉
290 |
291 | ### 系统要求
292 |
293 | - Python 3.9-3.13(推荐使用 Python 3.13)
294 | - pip 包管理器
295 | - Git(可选,用于版本控制)
296 |
297 | ### Windows 安装步骤
298 |
299 | 1. **安装 Python**
300 | ```powershell
301 | # 从 https://www.python.org/downloads/ 下载并安装 Python 3.13
302 | # 安装时必须勾选 "Add Python to PATH"
303 | ```
304 |
305 | 2. **打开 PowerShell 并创建虚拟环境**
306 | ```powershell
307 | # 创建并激活虚拟环境
308 | python -m venv .venv
309 | .\.venv\Scripts\Activate.ps1
310 | ```
311 |
312 | 3. **安装 CursorMind**
313 | ```powershell
314 | pip install --upgrade pip
315 | pip install cursormind
316 | $env:PYTHONPATH = "src"
317 | ```
318 |
319 | ### macOS/Linux 安装步骤
320 |
321 | 1. **创建虚拟环境**
322 | ```bash
323 | python3.13 -m venv .venv
324 | source .venv/bin/activate
325 | ```
326 |
327 | 2. **安装 CursorMind**
328 | ```bash
329 | pip install --upgrade pip
330 | pip install cursormind
331 | export PYTHONPATH=src
332 | ```
333 |
334 | ### 验证安装
335 |
336 | 运行以下命令确认安装成功:
337 | ```bash
338 | cursormind --version
339 | cursormind review file your_code.py
340 | ```
341 |
342 | 如果遇到问题,请参考下方的故障排除指南。
343 |
344 |
345 | ### ❗ 常见问题
346 |
347 | 遇到问题?以下是一些快速解决方案:
348 |
349 | 1. 确保 Python 版本兼容(3.9-3.13)
350 | 2. 检查 PYTHONPATH 环境变量设置
351 | 3. 验证虚拟环境是否正确激活
352 |
353 |
354 | 查看完整故障排除指南 👉
355 |
356 | ### Windows 常见问题
357 |
358 | 1. **Python 未添加到 PATH**
359 | ```powershell
360 | # 检查 Python 是否在 PATH 中
361 | python --version
362 |
363 | # 如果未找到,手动添加到 PATH
364 | # 打开系统属性 -> 环境变量 -> Path -> 添加 Python 安装路径
365 | # 通常在:C:\Users\用户名\AppData\Local\Programs\Python\Python313
366 | ```
367 |
368 | 2. **虚拟环境激活失败**
369 | ```powershell
370 | # 如果出现权限错误
371 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
372 |
373 | # 重新激活虚拟环境
374 | .\.venv\Scripts\Activate.ps1
375 | ```
376 |
377 | 3. **模块未找到**
378 | ```powershell
379 | # 确保 PYTHONPATH 正确设置
380 | echo $env:PYTHONPATH
381 |
382 | # 如果需要,重新设置
383 | $env:PYTHONPATH = "src"
384 | ```
385 |
386 | ### macOS 常见问题
387 |
388 | 1. **Python 版本冲突**
389 | ```bash
390 | # 检查 Python 版本
391 | python3 --version
392 |
393 | # 使用特定版本
394 | python3.13 -m pip install cursormind
395 | ```
396 |
397 | 2. **权限问题**
398 | ```bash
399 | # 修复权限
400 | sudo chown -R $USER ~/.local
401 | chmod +x ~/.local/bin/cursormind
402 | ```
403 |
404 | 3. **环境变量持久化**
405 | ```bash
406 | # 添加到 .zshrc 或 .bash_profile
407 | echo 'export PYTHONPATH=src' >> ~/.zshrc
408 | source ~/.zshrc
409 | ```
410 |
411 | ### Ubuntu/Debian 常见问题
412 |
413 | 1. **PPA 添加失败**
414 | ```bash
415 | # 安装必要工具
416 | sudo apt install software-properties-common
417 |
418 | # 重试添加 PPA
419 | sudo add-apt-repository ppa:deadsnakes/ppa
420 | ```
421 |
422 | 2. **依赖问题**
423 | ```bash
424 | # 安装编译依赖
425 | sudo apt install build-essential libssl-dev libffi-dev python3.13-dev
426 | ```
427 |
428 | 3. **权限问题**
429 | ```bash
430 | # 修复权限
431 | sudo chown -R $USER ~/.local
432 | sudo chmod +x ~/.local/bin/cursormind
433 | ```
434 |
435 |
436 |
437 | 🕒 时间戳规范
438 |
439 | 为确保项目文档中的时间戳保持一致性和准确性,我们提供了专门的时间戳生成工具。
440 |
441 | ### 时间戳工具使用
442 |
443 | ```bash
444 | # 生成完整格式的时间戳(默认)
445 | python3 scripts/generate_timestamp.py full
446 | # 输出示例:2025-03-11 23:37:45 PDT
447 |
448 | # 仅生成日期
449 | python3 scripts/generate_timestamp.py date
450 | # 输出示例:2025-03-11
451 |
452 | # 生成日期和时间(不含时区)
453 | python3 scripts/generate_timestamp.py datetime
454 | # 输出示例:2025-03-11 23:37:45
455 |
456 | # 生成紧凑格式
457 | python3 scripts/generate_timestamp.py compact
458 | # 输出示例:20250311
459 |
460 | # 生成年份和周数
461 | python3 scripts/generate_timestamp.py week
462 | # 输出示例:2025W11
463 | ```
464 |
465 | ### 时间戳规范说明
466 |
467 | 1. **强制要求**
468 | - 所有文档中的时间戳必须使用 `scripts/generate_timestamp.py` 生成
469 | - 禁止手动编写或修改时间戳
470 | - 时区必须保持一致(默认使用美国太平洋时区 PST/PDT)
471 | - 如需使用其他时区,请在项目根目录的 `.env` 文件中设置 `TZ` 环境变量,并确保所有团队成员使用相同配置
472 |
473 | 2. **Git Hook 配置**
474 | ```bash
475 | # 复制 pre-commit hook 到 Git hooks 目录
476 | cp scripts/hooks/pre-commit .git/hooks/
477 |
478 | # 设置执行权限
479 | chmod +x .git/hooks/pre-commit
480 | ```
481 |
482 |
483 | ### 📢 宣言
484 |
485 | 我们坚信:
486 | - 技术应该是平等的,每个人都应该有机会学习和使用AI编程
487 | - Cursor不仅是一个IDE,更是一个让编程变得更简单、更智能的工具
488 | - 通过CursorMind,我们致力于让每个开发者都能享受到AI辅助编程的便利
489 | - 开源精神是技术进步的基石,欢迎大家fork项目,共同建设AI编程生态
490 |
491 | ### 🤝 参与贡献
492 |
493 | 我们热烈欢迎社区的每一位成员参与到CursorMind的开发中来:
494 | - 🌟 如果您觉得这个项目有帮助,请给我们一个star
495 | - 🐛 发现bug?请提交 [Issues](https://github.com/yourusername/cursormind/issues)
496 | - 💡 有新想法?欢迎提交 [Pull Requests](https://github.com/yourusername/cursormind/pulls)
497 | - 📝 帮助改进文档?这对初学者来说非常重要
498 | - 💬 分享您的使用经验和建议
499 |
500 | 让我们一起打造更好的AI编程工具!
501 |
502 | #### 📜 MIT 开源许可
503 |
504 | CursorMind 采用 MIT 许可证开源,这意味着:
505 | - ✅ 您可以自由使用、修改和分发本软件
506 | - ✅ 您可以将其用于商业项目
507 | - ✅ 您可以创建和分发闭源版本
508 | - ℹ️ 唯一的要求是包含原始版权声明和许可证
509 |
510 | 我们鼓励个人和组织:
511 | - 🔄 根据特定需求分支(Fork)和修改项目
512 | - 🌱 将改进分享回社区
513 | - 🤝 共同推进 AI 辅助开发的普及
514 |
515 | 完整许可证详情,请查看 [LICENSE](LICENSE) 文件。
516 |
517 |
518 |
519 | *Cursor赋能开发效率,而你的愿景能创造未来。*
520 |
521 |
522 |
523 | ---
524 | *最后更新:2025-03-12 02:37:42 PDT*
525 |
--------------------------------------------------------------------------------
/learning_notes/daily/2025-03-12.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "2025-03-12-0001",
4 | "content": "测试笔记",
5 | "topic": "test",
6 | "tags": [],
7 | "created_at": "2025-03-11 21:25:03 PDT",
8 | "updated_at": "2025-03-11 21:25:03 PDT"
9 | },
10 | {
11 | "id": "2025-03-12-0002",
12 | "content": "学习了Python的基本语法,包括变量定义、数据类型等",
13 | "topic": "python",
14 | "tags": [],
15 | "created_at": "2025-03-11 21:28:10 PDT",
16 | "updated_at": "2025-03-11 21:28:10 PDT"
17 | }
18 | ]
--------------------------------------------------------------------------------
/learning_notes/reviews/review_20250312.json:
--------------------------------------------------------------------------------
1 | {
2 | "period": "2025-03-06 至 2025-03-12",
3 | "total_notes": 2,
4 | "total_words": 2,
5 | "topics": {
6 | "test": 1,
7 | "python": 1
8 | },
9 | "tags": {},
10 | "daily_notes": [
11 | {
12 | "date": "2025-03-12",
13 | "notes": [
14 | {
15 | "id": "2025-03-12-0001",
16 | "content": "测试笔记",
17 | "topic": "test",
18 | "tags": [],
19 | "created_at": "2025-03-11 21:25:03 PDT",
20 | "updated_at": "2025-03-11 21:25:03 PDT"
21 | },
22 | {
23 | "id": "2025-03-12-0002",
24 | "content": "学习了Python的基本语法,包括变量定义、数据类型等",
25 | "topic": "python",
26 | "tags": [],
27 | "created_at": "2025-03-11 21:28:10 PDT",
28 | "updated_at": "2025-03-11 21:28:10 PDT"
29 | }
30 | ]
31 | },
32 | {
33 | "date": "2025-03-12",
34 | "notes": [
35 | {
36 | "id": "2025-03-12-0001",
37 | "content": "测试笔记",
38 | "topic": "test",
39 | "tags": [],
40 | "created_at": "2025-03-11 21:25:03 PDT",
41 | "updated_at": "2025-03-11 21:25:03 PDT"
42 | },
43 | {
44 | "id": "2025-03-12-0002",
45 | "content": "学习了Python的基本语法,包括变量定义、数据类型等",
46 | "topic": "python",
47 | "tags": [],
48 | "created_at": "2025-03-11 21:28:10 PDT",
49 | "updated_at": "2025-03-11 21:28:10 PDT"
50 | }
51 | ]
52 | }
53 | ],
54 | "highlights": []
55 | }
--------------------------------------------------------------------------------
/learning_notes/stats.json:
--------------------------------------------------------------------------------
1 | {
2 | "total_notes": 2,
3 | "total_words": 2,
4 | "topics": {
5 | "test": 1,
6 | "python": 1
7 | },
8 | "tags": {},
9 | "daily_streak": 1,
10 | "last_note_date": "2025-03-12T12:28:10.643288",
11 | "last_updated": "2025-03-11 21:28:10 PDT"
12 | }
--------------------------------------------------------------------------------
/learning_notes/topics/python/2025-03-12-0002.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "2025-03-12-0002",
3 | "content": "学习了Python的基本语法,包括变量定义、数据类型等",
4 | "topic": "python",
5 | "tags": [],
6 | "created_at": "2025-03-11 21:28:10 PDT",
7 | "updated_at": "2025-03-11 21:28:10 PDT"
8 | }
--------------------------------------------------------------------------------
/learning_notes/topics/test/2025-03-12-0001.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "2025-03-12-0001",
3 | "content": "测试笔记",
4 | "topic": "test",
5 | "tags": [],
6 | "created_at": "2025-03-11 21:25:03 PDT",
7 | "updated_at": "2025-03-11 21:25:03 PDT"
8 | }
--------------------------------------------------------------------------------
/learning_paths/current_path.json:
--------------------------------------------------------------------------------
1 | {
2 | "path_id": "python-beginner",
3 | "current_stage": 0,
4 | "current_step": 1,
5 | "started_at": "2025-03-11 21:27:30 PDT",
6 | "last_updated": "2025-03-11 21:27:46 PDT"
7 | }
--------------------------------------------------------------------------------
/learning_paths/paths.json:
--------------------------------------------------------------------------------
1 | {
2 | "paths": [
3 | {
4 | "id": "python-beginner",
5 | "name": "Python入门之路",
6 | "description": "从零开始学习Python编程",
7 | "difficulty": "初级",
8 | "estimated_time": "3个月",
9 | "stages": [
10 | {
11 | "name": "基础语法",
12 | "steps": [
13 | "变量和数据类型",
14 | "控制流程",
15 | "函数定义和使用"
16 | ],
17 | "resources": [
18 | {
19 | "type": "文档",
20 | "name": "Python官方教程",
21 | "url": "https://docs.python.org/zh-cn/3/tutorial/"
22 | }
23 | ],
24 | "projects": [
25 | {
26 | "name": "计算器程序",
27 | "description": "创建一个简单的命令行计算器"
28 | }
29 | ]
30 | }
31 | ]
32 | },
33 | {
34 | "id": "web-beginner",
35 | "name": "网页设计入门",
36 | "description": "学习HTML、CSS和JavaScript基础",
37 | "difficulty": "初级",
38 | "estimated_time": "2个月",
39 | "stages": []
40 | },
41 | {
42 | "id": "pm-beginner",
43 | "name": "项目管理入门",
44 | "description": "学习基本的项目管理概念和工具",
45 | "difficulty": "初级",
46 | "estimated_time": "1个月",
47 | "stages": []
48 | }
49 | ]
50 | }
--------------------------------------------------------------------------------
/pdm.lock:
--------------------------------------------------------------------------------
1 | # This file is @generated by PDM.
2 | # It is not intended for manual editing.
3 |
4 | [metadata]
5 | groups = ["default"]
6 | strategy = ["inherit_metadata"]
7 | lock_version = "4.5.0"
8 | content_hash = "sha256:03ae8673a9bbb0a0081cd7d3a90791153502b7cb3feb4e1fc1d3efdf9cc8ad54"
9 |
10 | [[metadata.targets]]
11 | requires_python = ">=3.9"
12 |
13 | [[package]]
14 | name = "click"
15 | version = "8.1.8"
16 | requires_python = ">=3.7"
17 | summary = "Composable command line interface toolkit"
18 | groups = ["default"]
19 | dependencies = [
20 | "colorama; platform_system == \"Windows\"",
21 | "importlib-metadata; python_version < \"3.8\"",
22 | ]
23 | files = [
24 | {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
25 | {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
26 | ]
27 |
28 | [[package]]
29 | name = "colorama"
30 | version = "0.4.6"
31 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
32 | summary = "Cross-platform colored terminal text."
33 | groups = ["default"]
34 | marker = "platform_system == \"Windows\""
35 | files = [
36 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
37 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
38 | ]
39 |
40 | [[package]]
41 | name = "markdown-it-py"
42 | version = "3.0.0"
43 | requires_python = ">=3.8"
44 | summary = "Python port of markdown-it. Markdown parsing, done right!"
45 | groups = ["default"]
46 | dependencies = [
47 | "mdurl~=0.1",
48 | ]
49 | files = [
50 | {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
51 | {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
52 | ]
53 |
54 | [[package]]
55 | name = "mdurl"
56 | version = "0.1.2"
57 | requires_python = ">=3.7"
58 | summary = "Markdown URL utilities"
59 | groups = ["default"]
60 | files = [
61 | {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
62 | {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
63 | ]
64 |
65 | [[package]]
66 | name = "pygments"
67 | version = "2.19.1"
68 | requires_python = ">=3.8"
69 | summary = "Pygments is a syntax highlighting package written in Python."
70 | groups = ["default"]
71 | files = [
72 | {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"},
73 | {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"},
74 | ]
75 |
76 | [[package]]
77 | name = "python-dateutil"
78 | version = "2.9.0.post0"
79 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
80 | summary = "Extensions to the standard Python datetime module"
81 | groups = ["default"]
82 | dependencies = [
83 | "six>=1.5",
84 | ]
85 | files = [
86 | {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"},
87 | {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
88 | ]
89 |
90 | [[package]]
91 | name = "pytz"
92 | version = "2025.1"
93 | summary = "World timezone definitions, modern and historical"
94 | groups = ["default"]
95 | files = [
96 | {file = "pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"},
97 | {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"},
98 | ]
99 |
100 | [[package]]
101 | name = "rich"
102 | version = "13.9.4"
103 | requires_python = ">=3.8.0"
104 | summary = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
105 | groups = ["default"]
106 | dependencies = [
107 | "markdown-it-py>=2.2.0",
108 | "pygments<3.0.0,>=2.13.0",
109 | "typing-extensions<5.0,>=4.0.0; python_version < \"3.11\"",
110 | ]
111 | files = [
112 | {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"},
113 | {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"},
114 | ]
115 |
116 | [[package]]
117 | name = "six"
118 | version = "1.17.0"
119 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
120 | summary = "Python 2 and 3 compatibility utilities"
121 | groups = ["default"]
122 | files = [
123 | {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
124 | {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
125 | ]
126 |
127 | [[package]]
128 | name = "typing-extensions"
129 | version = "4.12.2"
130 | requires_python = ">=3.8"
131 | summary = "Backported and Experimental Type Hints for Python 3.8+"
132 | groups = ["default"]
133 | marker = "python_version < \"3.11\""
134 | files = [
135 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
136 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
137 | ]
138 |
--------------------------------------------------------------------------------
/project_management/.task_count:
--------------------------------------------------------------------------------
1 | 2
2 |
--------------------------------------------------------------------------------
/project_management/actuals/decisions/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/project_management/actuals/decisions/.gitkeep
--------------------------------------------------------------------------------
/project_management/actuals/reports/daily/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/project_management/actuals/reports/daily/.gitkeep
--------------------------------------------------------------------------------
/project_management/actuals/reports/weekly/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/project_management/actuals/reports/weekly/.gitkeep
--------------------------------------------------------------------------------
/project_management/actuals/tasks/TASK-001_开发命令系统核心功能.md:
--------------------------------------------------------------------------------
1 | # 任务模板
2 |
3 |
16 |
17 | ## 任务信息
18 |
31 |
32 | - **任务ID**: TASK-001
33 | - **任务名称**: 开发命令系统核心功能
34 | - **创建时间**: 2025-03-11 20:27:36 PDT
35 | - **优先级**: 高
36 | - **状态**: 未开始
37 |
38 | ## 任务描述
39 |
53 |
54 | 开发CursorMind项目的命令系统核心功能,实现项目管理和文档生成的自动化处理。具体包括:
55 |
56 | 1. 实现基础命令解析器
57 | - 支持命令行参数解析
58 | - 实现命令注册和路由系统
59 | - 添加帮助信息生成功能
60 |
61 | 2. 开发核心命令集
62 | - 项目初始化命令
63 | - 任务管理命令(创建、更新、查询)
64 | - 报告生成命令(日报、周报)
65 | - 模板管理命令
66 |
67 | 3. 实现命令执行环境
68 | - 配置文件加载和验证
69 | - 环境变量管理
70 | - 错误处理和日志记录
71 |
72 | 4. 开发命令扩展机制
73 | - 插件系统设计
74 | - 自定义命令支持
75 | - 命令别名功能
76 |
77 | ## 验收标准
78 |
91 |
92 | 1. [ ] 命令解析器能够正确处理各类参数和选项
93 | 2. [ ] 核心命令集功能完整且稳定运行
94 | 3. [ ] 命令执行环境配置灵活,错误处理完善
95 | 4. [ ] 扩展机制设计合理,支持插件开发
96 | 5. [ ] 完成命令系统技术文档编写
97 | 6. [ ] 通过单元测试和集成测试
98 | 7. [ ] 提供详细的使用示例和最佳实践
99 |
100 | ## 时间规划
101 |
114 |
115 | - **计划开始**: 2025-03-11
116 | - **预计完成**: 2025-03-15
117 | - **实际耗时**: 0小时
118 | - **检查点**:
119 | - 2025-03-12: 完成基础命令解析器
120 | - 2025-03-13: 完成核心命令集开发
121 | - 2025-03-14: 完成执行环境和扩展机制
122 | - 2025-03-15: 完成测试和文档
123 |
124 | ## 依赖关系
125 |
137 |
138 | - **前置任务**: 无
139 | - **后续任务**: 待定
140 | - **关键路径**: 是(作为Beta 0.1.1版本的核心功能)
141 |
142 | ## 资源需求
143 |
156 |
157 | - Python 3.8+
158 | - Click库(命令行工具开发)
159 | - PyTest(测试框架)
160 | - 1人/5天开发时间
161 | - Git版本控制
162 | - VSCode开发环境
163 |
164 | ## 进展记录
165 |
176 |
177 | | 日期 | 进展 | 备注 |
178 | |------|------|------|
179 | | 2025-03-11 | 任务创建和规划 | 初始化任务,完成详细设计 |
180 |
181 | ## 备注
182 |
195 |
196 | 1. 性能考虑:命令执行效率要求小于1秒
197 | 2. 可维护性:遵循SOLID原则,确保代码质量
198 | 3. 建议:考虑添加命令执行历史记录功能
199 | 4. 风险:需要确保向后兼容性
200 |
201 | ---
202 | *最后更新: 2025-03-11 20:27:36 PDT*
203 |
204 |
--------------------------------------------------------------------------------
/project_management/control/MAIN_CONTROL.md:
--------------------------------------------------------------------------------
1 | # 项目主控制文档
2 |
3 | ## 基本信息
4 | - 项目名称:CursorMind
5 | - 版本:Beta 0.2.1
6 | - 状态:进行中
7 | - 进度:75%
8 | - 最后更新:2025-03-11 23:37:45 PDT
9 |
10 | ## 项目目标
11 | 开发一个全面的Cursor开发工具集,提供代码质量检查、项目管理、学习辅助和最佳实践指导功能。
12 |
13 | ## 当前阶段
14 | - 阶段名称:Beta 0.2.1优化阶段
15 | - 开始时间:2025-03-12
16 | - 计划完成:2025-03-19
17 | - 主要任务:代码质量优化和安全性增强
18 |
19 | ## 开发计划
20 |
21 | ### 已完成任务
22 | 1. 核心功能开发
23 | - 代码审查模块
24 | - 性能检查功能
25 | - 安全检查机制
26 | - Python 3.9+支持
27 |
28 | 2. 文档体系建设
29 | - README.zh.md更新
30 | - 配置文件优化
31 | - 文档格式规范
32 |
33 | ### 进行中任务
34 | 1. 代码质量优化
35 | - 函数复杂度重构
36 | - 局部变量优化
37 | - 代码风格统一
38 |
39 | 2. 安全性增强
40 | - 文件访问安全评估
41 | - 安全措施实施
42 | - 测试用例完善
43 |
44 | ### 待开始任务
45 | 1. 文档完善
46 | - API文档更新
47 | - 开发指南完善
48 | - 示例代码补充
49 |
50 | ## 里程碑
51 | 1. [已完成] Beta 0.1 - 2025-03-10
52 | 2. [已完成] Beta 0.2 - 2025-03-11
53 | 3. [进行中] Beta 0.2.1 - 2025-03-19
54 | 4. [计划中] Beta 0.3 - 2025-03-26
55 |
56 | ## 团队成员
57 | - 项目负责人:@kinglee
58 | - 开发团队:@dev-team
59 | - 测试团队:@test-team
60 |
61 | ## 关键决策记录
62 | 1. 2025-03-12 - 提升Python版本要求至3.9+
63 | 2. 2025-03-12 - 确定代码质量优化优先级
64 |
65 | ## 风险追踪
66 | 1. [中] 代码复杂度超标
67 | - 影响:性能和可维护性
68 | - 措施:计划重构高复杂度函数
69 |
70 | 2. [中] 安全性问题
71 | - 影响:文件访问安全
72 | - 措施:进行安全评估和加固
73 |
74 | 3. [低] 文档更新延迟
75 | - 影响:开发效率
76 | - 措施:建立文档更新机制
77 |
78 | ## 质量控制
79 | 1. 代码质量指标
80 | - 函数复杂度 ≤ 10
81 | - 局部变量数量 ≤ 15
82 | - 行长度 ≤ 88字符
83 |
84 | 2. 测试覆盖率要求
85 | - 单元测试:90%+
86 | - 集成测试:85%+
87 |
88 | ## 依赖关系
89 | 1. 外部依赖
90 | - Python 3.9+
91 | - click >= 8.0.0
92 | - rich >= 10.0.0
93 |
94 | 2. 内部依赖
95 | - 代码审查模块
96 | - 性能检查模块
97 | - 安全检查模块
98 |
99 | ## 文档链接
100 | 1. [README.zh.md](../../README.zh.md)
101 | 2. [REQUIREMENTS.md](./REQUIREMENTS.md)
102 | 3. [API文档](../docs/api/)
103 |
104 | ## 工具使用规范
105 | 1. 时间戳生成
106 | - 所有文档中的时间戳必须使用 `scripts/generate_timestamp.py` 生成
107 | - 支持的格式:
108 | * `full`: YYYY-MM-DD HH:MM:SS PST/PDT(默认)
109 | * `date`: YYYY-MM-DD
110 | * `datetime`: YYYY-MM-DD HH:MM:SS
111 | * `compact`: YYYYMMDD
112 | * `week`: YYYYWNN
113 | - 使用示例:`python3 scripts/generate_timestamp.py full`
114 |
115 | ## 命令参考
116 | - **[CODE NOW]**: 立即开始编码任务
117 | - **[FOCUS]**: 专注于当前最重要的任务
118 | - **[RESET]**: 重置当前工作状态
119 | - **[DECISION]**: 记录重要决策
120 |
121 | ---
122 | *最后更新: 2025-03-11 23:37:45 PDT*
--------------------------------------------------------------------------------
/project_management/control/REQUIREMENTS.md:
--------------------------------------------------------------------------------
1 | # 项目需求文档
2 |
3 | ## 项目信息
4 | - **项目名称**: CursorMind
5 | - **版本**: Beta 0.2.1
6 | - **最后更新**: 2025-03-12
7 | - **状态**: 已确认
8 |
9 | ## 1. 概述
10 | ### 1.1 目的
11 | 开发一个综合性的 Cursor 开发工具集,提供代码质量保证、项目管理、学习辅助和最佳实践指南等功能,帮助开发者提升开发效率和项目质量。
12 |
13 | ### 1.2 项目背景
14 | 随着软件开发复杂度的增加,开发者需要一个集成的工具来管理代码质量、项目进度和学习成长。CursorMind 旨在提供这样一个综合解决方案。
15 |
16 | ### 1.3 目标用户
17 | - 专业开发人员
18 | - 项目经理
19 | - 团队领导
20 | - 初学者
21 | - 学生(大学生、中学生、小学生)
22 |
23 | ## 2. 功能需求
24 | ### 2.1 核心功能
25 | | 需求ID | 优先级 | 描述 | 验收标准 | 状态 |
26 | |-------|-------|------|---------|------|
27 | | FR001 | 高 | 代码风格检查 | 支持多种编码规范,提供详细报告 | 已完成 |
28 | | FR002 | 高 | 性能分析 | 识别性能瓶颈,提供优化建议 | 已完成 |
29 | | FR003 | 高 | 安全检查 | 发现潜在安全隐患,提供修复方案 | 已完成 |
30 | | FR004 | 高 | 项目管理 | 支持任务跟踪和进度管理 | 已完成 |
31 | | FR005 | 高 | 学习路径 | 提供个性化学习计划 | 已完成 |
32 |
33 | ### 2.2 扩展功能
34 | | 需求ID | 优先级 | 描述 | 验收标准 | 状态 |
35 | |-------|-------|------|---------|------|
36 | | FR101 | 中 | 团队协作 | 支持多人协作和代码评审 | 进行中 |
37 | | FR102 | 中 | 插件系统 | 支持自定义扩展 | 计划中 |
38 | | FR103 | 低 | AI 辅助 | 提供智能代码建议 | 计划中 |
39 |
40 | ## 3. 非功能需求
41 | ### 3.1 性能需求
42 | | 需求ID | 优先级 | 描述 | 验收标准 | 状态 |
43 | |-------|-------|------|---------|------|
44 | | NFR001 | 高 | 响应时间 | 命令执行时间 < 1s | 已完成 |
45 | | NFR002 | 高 | 资源占用 | 内存使用 < 500MB | 已完成 |
46 | | NFR003 | 中 | 并发处理 | 支持多任务并行执行 | 进行中 |
47 |
48 | ### 3.2 安全需求
49 | | 需求ID | 优先级 | 描述 | 验收标准 | 状态 |
50 | |-------|-------|------|---------|------|
51 | | NFR101 | 高 | 文件访问安全 | 安全的文件操作机制 | 已完成 |
52 | | NFR102 | 高 | 配置文件保护 | 加密存储敏感信息 | 已完成 |
53 | | NFR103 | 中 | 用户认证 | 支持多种认证方式 | 计划中 |
54 |
55 | ### 3.3 可用性需求
56 | | 需求ID | 优先级 | 描述 | 验收标准 | 状态 |
57 | |-------|-------|------|---------|------|
58 | | NFR201 | 高 | 命令行界面 | 清晰的命令结构和帮助信息 | 已完成 |
59 | | NFR202 | 中 | 多语言支持 | 支持中英文界面 | 已完成 |
60 | | NFR203 | 中 | 错误处理 | 友好的错误提示 | 已完成 |
61 |
62 | ## 4. 约束条件
63 | - Python 版本要求:>= 3.9
64 | - 保持轻量级设计
65 | - 跨平台兼容性
66 | - 模块化架构
67 |
68 | ## 5. 假设和依赖
69 | ### 假设
70 | - 用户具备基本的命令行操作能力
71 | - 用户了解基本的编程概念
72 | - 用户有稳定的网络连接
73 |
74 | ### 依赖
75 | - Python 运行时环境
76 | - pip 包管理器
77 | - Git(可选)
78 |
79 | ## 6. 需求变更历史
80 | | 变更ID | 日期 | 描述 | 影响 | 提出人 | 状态 |
81 | |-------|------|------|------|-------|------|
82 | | CH001 | 2025-03-07 | 初始需求确定 | 项目范围定义 | Team | 已批准 |
83 | | CH002 | 2025-03-12 | 增加学习路径功能 | 扩展项目范围 | Team | 已批准 |
84 |
85 | ## 7. 附录
86 | ### 7.1 术语表
87 | | 术语 | 定义 |
88 | |------|------|
89 | | 代码审查 | 对代码质量、性能和安全性的综合检查 |
90 | | 学习路径 | 个性化的学习计划和进度追踪 |
91 | | 项目管理 | 任务分配、进度跟踪和团队协作 |
92 |
93 | ### 7.2 相关文档
94 | - [项目主控制文档](MAIN_CONTROL.md)
95 | - [项目进度文档](../../PROJECT_PROGRESS.md)
96 | - [API文档](../../docs/api/README.md)
97 |
98 | ---
99 | *最后更新: 2025-03-12 15:30:00 PST*
--------------------------------------------------------------------------------
/project_management/scripts/create_task.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 设置时区为PST
4 | export TZ="America/Los_Angeles"
5 |
6 | # 检查参数
7 | if [ $# -lt 1 ]; then
8 | echo "用法: $0 <任务名称> [优先级(高/中/低)]"
9 | exit 1
10 | fi
11 |
12 | # 获取参数
13 | TASK_NAME="$1"
14 | PRIORITY="${2:-中}" # 默认优先级为"中"
15 |
16 | # 生成任务ID(格式:TASK-XXX)
17 | TASK_COUNT_FILE="project_management/.task_count"
18 | if [ ! -f "$TASK_COUNT_FILE" ]; then
19 | echo "1" > "$TASK_COUNT_FILE"
20 | fi
21 | TASK_NUM=$(cat "$TASK_COUNT_FILE")
22 | TASK_ID="TASK-$(printf "%03d" $TASK_NUM)"
23 |
24 | # 更新任务计数
25 | echo $((TASK_NUM + 1)) > "$TASK_COUNT_FILE"
26 |
27 | # 获取当前时间戳
28 | TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S %Z")
29 |
30 | # 创建任务文件
31 | TASK_FILE="project_management/actuals/tasks/${TASK_ID}_$(echo "$TASK_NAME" | tr ' ' '_').md"
32 | mkdir -p "project_management/actuals/tasks"
33 |
34 | # 从模板创建任务文件
35 | sed -e "s/\[TASK-ID\]/$TASK_ID/g" \
36 | -e "s/\[任务名称\]/$TASK_NAME/g" \
37 | -e "s/\[TIMESTAMP\]/$TIMESTAMP/g" \
38 | -e "s/\[高\/中\/低\]/$PRIORITY/g" \
39 | -e "s/\[未开始\/进行中\/已完成\/已暂停\]/未开始/g" \
40 | "project_management/templates/task_template.md" > "$TASK_FILE"
41 |
42 | echo "已创建任务:$TASK_ID"
43 | echo "任务文件:$TASK_FILE"
--------------------------------------------------------------------------------
/project_management/templates/daily_report_template.md:
--------------------------------------------------------------------------------
1 | # 日报模板
2 |
3 |
10 |
11 | ## 时间
12 |
13 | [TIMESTAMP]
14 |
15 | ## 今日工作内容
16 |
22 |
23 | 1. [工作项1]
24 | - [具体内容]
25 | - [完成度]
26 |
27 | 2. [工作项2]
28 | - [具体内容]
29 | - [完成度]
30 |
31 | ## 明日计划
32 |
39 |
40 | 1. [计划项1]
41 | - [具体内容]
42 | - [预期目标]
43 |
44 | ## 问题与解决方案
45 |
52 |
53 | - 问题:[描述]
54 | - 解决方案:[方案]
55 |
56 | ## 项目进度
57 |
63 |
64 | - 版本: [VERSION]
65 | - 进度: [PROGRESS]%
66 |
67 | ## 备注
68 |
75 |
76 | [备注内容]
77 |
78 | ---
79 | *使用 [CODE NOW] 命令立即开始编码,避免过度分析*
--------------------------------------------------------------------------------
/project_management/templates/decision_template.md:
--------------------------------------------------------------------------------
1 | # 决策记录
2 |
3 | ## 基本信息
4 | - **决策ID**: {{DECISION_ID}}
5 | - **标题**: {{DECISION_TITLE}}
6 | - **日期**: {{DECISION_DATE}}
7 | - **时间戳**: {{TIMESTAMP}}
8 | - **状态**: {{STATUS}} (提议/已批准/已拒绝/已实施)
9 | - **决策者**: {{DECIDER}}
10 | - **相关领域**: {{DOMAIN}}
11 |
12 | ## 背景
13 | {{BACKGROUND}}
14 |
15 | ## 问题陈述
16 | {{PROBLEM_STATEMENT}}
17 |
18 | ## 决策驱动因素
19 | - {{DRIVER_1}}
20 | - {{DRIVER_2}}
21 | - {{DRIVER_3}}
22 |
23 | ## 考虑的选项
24 | ### 选项1: {{OPTION_1}}
25 | - **描述**: {{DESCRIPTION_1}}
26 | - **优点**:
27 | - {{PRO_1_1}}
28 | - {{PRO_1_2}}
29 | - **缺点**:
30 | - {{CON_1_1}}
31 | - {{CON_1_2}}
32 |
33 | ### 选项2: {{OPTION_2}}
34 | - **描述**: {{DESCRIPTION_2}}
35 | - **优点**:
36 | - {{PRO_2_1}}
37 | - {{PRO_2_2}}
38 | - **缺点**:
39 | - {{CON_2_1}}
40 | - {{CON_2_2}}
41 |
42 | ## 决策结果
43 | **选择的选项**: {{CHOSEN_OPTION}}
44 |
45 | **理由**:
46 | {{RATIONALE}}
47 |
48 | ## 影响
49 | - **技术影响**: {{TECHNICAL_IMPACT}}
50 | - **业务影响**: {{BUSINESS_IMPACT}}
51 | - **资源影响**: {{RESOURCE_IMPACT}}
52 | - **风险**: {{RISKS}}
53 |
54 | ## 实施计划
55 | 1. {{IMPLEMENTATION_STEP_1}}
56 | 2. {{IMPLEMENTATION_STEP_2}}
57 | 3. {{IMPLEMENTATION_STEP_3}}
58 |
59 | ## 验证方法
60 | {{VALIDATION_METHOD}}
61 |
62 | ## 相关决策
63 | - {{RELATED_DECISION_1}}
64 | - {{RELATED_DECISION_2}}
65 |
66 | ## 参考资料
67 | - {{REFERENCE_1}}
68 | - {{REFERENCE_2}}
69 |
70 | ## 备注
71 | {{NOTES}}
72 |
73 | ---
74 | *使用 [FOCUS] 命令限制上下文到指定范围,防止分心*
--------------------------------------------------------------------------------
/project_management/templates/main_control_template.md:
--------------------------------------------------------------------------------
1 | # 项目主控制文档模板
2 |
3 |
10 |
11 | ## 项目信息
12 |
19 |
20 | - **项目名称**: [PROJECT_NAME]
21 | - **版本**: [VERSION]
22 | - **开始日期**: [START_DATE]
23 | - **计划完成日期**: [END_DATE]
24 |
25 | ## 项目目标
26 |
33 |
34 | [项目目标描述]
35 |
36 | ## 当前阶段
37 |
44 |
45 | - 阶段:[PHASE_NAME]
46 | - 状态:[STATUS]
47 | - 进度:[PROGRESS]%
48 |
49 | ## 开发计划
50 |
57 |
58 | ### 第一阶段:[阶段名称]([时间估计])
59 | 1. [任务1]
60 | 2. [任务2]
61 | 3. [任务3]
62 |
63 | ### 第二阶段:[阶段名称]([时间估计])
64 | 1. [任务1]
65 | 2. [任务2]
66 | 3. [任务3]
67 |
68 | ## 关键里程碑
69 |
76 |
77 | 1. [ ] [里程碑1]
78 | 2. [ ] [里程碑2]
79 | 3. [ ] [里程碑3]
80 |
81 | ## 风险管理
82 |
89 |
90 | 1. [风险1]
91 | - 影响:[描述]
92 | - 对策:[措施]
93 |
94 | ## 质量控制
95 |
102 |
103 | - [质量控制项1]
104 | - [质量控制项2]
105 | - [质量控制项3]
106 |
107 | ## 下一步行动
108 |
115 |
116 | 1. [行动项1]
117 | 2. [行动项2]
118 | 3. [行动项3]
119 |
120 | ---
121 | *最后更新: [TIMESTAMP]*
122 |
123 |
--------------------------------------------------------------------------------
/project_management/templates/project_progress_template.md:
--------------------------------------------------------------------------------
1 | # 项目进度跟踪模板
2 |
3 |
10 |
11 | ## 项目信息
12 |
19 |
20 | - **项目名称**: [PROJECT_NAME]
21 | - **版本**: [VERSION]
22 | - **开始日期**: [START_DATE]
23 | - **计划完成日期**: [END_DATE]
24 | - **当前状态**: [STATUS]
25 | - **当前进度**: [PROGRESS]%
26 |
27 | ## 里程碑
28 |
35 |
36 | | 里程碑 | 计划日期 | 实际日期 | 状态 | 负责人 |
37 | |-------|---------|---------|------|-------|
38 | | [里程碑1] | [计划日期] | [实际日期] | [状态] | [负责人] |
39 | | [里程碑2] | [计划日期] | [实际日期] | [状态] | [负责人] |
40 |
41 | ## 进度更新历史
42 |
49 |
50 | | 日期 | 进度 | 更新内容 | 更新人 |
51 | |------|------|---------|-------|
52 | | [日期] | [进度]% | [更新说明] | [更新人] |
53 |
54 | ## 风险与问题
55 |
62 |
63 | | ID | 描述 | 影响程度 | 状态 | 解决方案 | 负责人 |
64 | |----|-----|---------|------|---------|-------|
65 | | [ID] | [描述] | 高/中/低 | 开放/已解决 | [方案] | [负责人] |
66 |
67 | ## 下一步计划
68 |
75 |
76 | - [ ] [任务1]
77 | - [ ] [任务2]
78 | - [ ] [任务3]
79 |
80 | ## 备注
81 |
88 |
89 | [备注内容]
90 |
91 | ---
92 | *最后更新: [TIMESTAMP]*
93 |
94 |
--------------------------------------------------------------------------------
/project_management/templates/risk_template.md:
--------------------------------------------------------------------------------
1 | # 风险评估
2 |
3 | ## 基本信息
4 | - **风险ID**: {{RISK_ID}}
5 | - **风险名称**: {{RISK_NAME}}
6 | - **创建日期**: {{CREATION_DATE}}
7 | - **最后更新**: {{LAST_UPDATED}}
8 | - **时间戳**: {{TIMESTAMP}}
9 | - **状态**: {{STATUS}} (已识别/已分析/已缓解/已关闭)
10 | - **负责人**: {{OWNER}}
11 |
12 | ## 风险描述
13 | {{RISK_DESCRIPTION}}
14 |
15 | ## 风险评估
16 | - **可能性**: {{PROBABILITY}} (高/中/低)
17 | - **影响程度**: {{IMPACT}} (高/中/低)
18 | - **风险等级**: {{RISK_LEVEL}} (高/中/低)
19 | - **触发条件**: {{TRIGGER_CONDITIONS}}
20 |
21 | ## 影响分析
22 | - **项目进度影响**: {{SCHEDULE_IMPACT}}
23 | - **项目成本影响**: {{COST_IMPACT}}
24 | - **项目质量影响**: {{QUALITY_IMPACT}}
25 | - **其他影响**: {{OTHER_IMPACT}}
26 |
27 | ## 缓解策略
28 | ### 预防措施
29 | 1. {{PREVENTION_MEASURE_1}}
30 | 2. {{PREVENTION_MEASURE_2}}
31 |
32 | ### 应对计划
33 | 1. {{RESPONSE_PLAN_1}}
34 | 2. {{RESPONSE_PLAN_2}}
35 |
36 | ### 应急计划
37 | {{CONTINGENCY_PLAN}}
38 |
39 | ## 监控指标
40 | - **指标1**: {{METRIC_1}}
41 | - **指标2**: {{METRIC_2}}
42 | - **监控频率**: {{MONITORING_FREQUENCY}}
43 | - **预警阈值**: {{WARNING_THRESHOLD}}
44 |
45 | ## 相关风险
46 | - {{RELATED_RISK_1}}
47 | - {{RELATED_RISK_2}}
48 |
49 | ## 风险状态历史
50 | | 日期 | 状态 | 更新人 | 备注 |
51 | |------|------|-------|------|
52 | | {{DATE_1}} | {{STATUS_1}} | {{UPDATER_1}} | {{NOTE_1}} |
53 | | {{DATE_2}} | {{STATUS_2}} | {{UPDATER_2}} | {{NOTE_2}} |
54 |
55 | ## 经验教训
56 | {{LESSONS_LEARNED}}
57 |
58 | ## 附件和参考
59 | - {{ATTACHMENT_1}}
60 | - {{REFERENCE_1}}
61 |
62 | ---
63 | *使用 [CODE NOW] 命令立即停止分析并开始编写代码*
--------------------------------------------------------------------------------
/project_management/templates/task_template.md:
--------------------------------------------------------------------------------
1 | # 任务模板
2 |
3 |
16 |
17 | ## 任务信息
18 |
31 |
32 | - **任务ID**: [TASK-ID]
33 | - **任务名称**: [任务名称]
34 | - **创建时间**: [TIMESTAMP]
35 | - **优先级**: [高/中/低]
36 | - **状态**: [未开始/进行中/已完成/已暂停]
37 |
38 | ## 任务描述
39 |
53 |
54 | [详细描述任务内容和目标]
55 |
56 | ## 验收标准
57 |
70 |
71 | 1. [ ] [标准1]
72 | 2. [ ] [标准2]
73 | 3. [ ] [标准3]
74 |
75 | ## 时间规划
76 |
89 |
90 | - **计划开始**: [START_DATE]
91 | - **预计完成**: [END_DATE]
92 | - **实际耗时**: [ACTUAL_HOURS]小时
93 |
94 | ## 依赖关系
95 |
107 |
108 | - **前置任务**: [依赖的任务ID]
109 | - **后续任务**: [被依赖的任务ID]
110 |
111 | ## 资源需求
112 |
125 |
126 | - [所需资源1]
127 | - [所需资源2]
128 |
129 | ## 进展记录
130 |
141 |
142 | | 日期 | 进展 | 备注 |
143 | |------|------|------|
144 | | [日期] | [进展说明] | [备注] |
145 |
146 | ## 备注
147 |
159 |
160 | [补充说明]
161 |
162 | ---
163 | *最后更新: [TIMESTAMP]*
164 |
165 |
--------------------------------------------------------------------------------
/project_management/templates/weekly_report_template.md:
--------------------------------------------------------------------------------
1 | # 周报模板
2 |
3 |
10 |
11 | ## 时间
12 |
13 | [TIMESTAMP]
14 |
15 | ## 本周主要工作
16 |
23 |
24 | 1. [重要工作1]
25 | - [具体成果]
26 | - [完成情况]
27 |
28 | 2. [重要工作2]
29 | - [具体成果]
30 | - [完成情况]
31 |
32 | ## 下周工作计划
33 |
40 |
41 | 1. [计划项1]
42 | - [具体目标]
43 | - [验收标准]
44 |
45 | 2. [计划项2]
46 | - [具体目标]
47 | - [验收标准]
48 |
49 | ## 存在的问题和风险
50 |
57 |
58 | 1. [问题1]
59 | - 影响:[描述]
60 | - 对策:[方案]
61 |
62 | 2. [风险1]
63 | - 等级:[高/中/低]
64 | - 缓解:[措施]
65 |
66 | ## 项目状态
67 |
74 |
75 | - 版本: [VERSION]
76 | - 总体进度: [PROGRESS]%
77 | - 计划完成时间: [DEADLINE]
78 |
79 | ## 其他说明
80 |
87 |
88 | [补充说明]
89 |
90 | ---
91 | *最后更新: [TIMESTAMP]*
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["pdm-backend"]
3 | build-backend = "pdm.backend"
4 |
5 | [project]
6 | name = "cursormind"
7 | version = "0.2.1"
8 | authors = [
9 | {name = "Yagami"},
10 | ]
11 | description = "A project management framework for Cursor developers"
12 | readme = "README.md"
13 | requires-python = ">=3.9"
14 | classifiers = [
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: MIT License",
22 | "Operating System :: OS Independent",
23 | ]
24 | dependencies = [
25 | "click>=8.0.0",
26 | "rich>=10.0.0",
27 | "python-dateutil>=2.8.2",
28 | "pytz>=2021.3",
29 | ]
30 |
31 | [project.scripts]
32 | cursormind = "cursormind.cli:main"
33 |
34 | [tool.pdm]
35 | package-dir = "src"
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | click>=8.0.0
2 | pytz>=2021.1
3 | pytest>=7.0.0
4 | pytest-cov>=3.0.0
5 | black>=22.0.0
6 | flake8>=4.0.0
7 | mypy>=0.900
--------------------------------------------------------------------------------
/scripts/create_report.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # CursorMind 报告创建脚本
4 | # 用法: ./create_report.sh [daily|weekly]
5 |
6 | set -e
7 |
8 | # 颜色定义
9 | RED='\033[0;31m'
10 | GREEN='\033[0;32m'
11 | YELLOW='\033[0;33m'
12 | BLUE='\033[0;34m'
13 | NC='\033[0m' # No Color
14 |
15 | # 检查参数
16 | if [ $# -lt 1 ]; then
17 | echo -e "${RED}错误: 缺少报告类型参数${NC}"
18 | echo -e "用法: $0 [daily|weekly]"
19 | exit 1
20 | fi
21 |
22 | REPORT_TYPE="$1"
23 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24 | PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
25 |
26 | # 获取太平洋时间戳
27 | # 尝试使用Python时间戳脚本,如果失败则使用简单时间戳脚本
28 | CURRENT_DATE=$("$SCRIPT_DIR/timestamp.sh" date 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" date)
29 | FULL_TIMESTAMP=$("$SCRIPT_DIR/timestamp.sh" full 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" full)
30 | COMPACT_DATE=$("$SCRIPT_DIR/timestamp.sh" compact 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" compact)
31 | WEEK_NUMBER=$("$SCRIPT_DIR/timestamp.sh" week 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" week)
32 |
33 | # 检查是否使用了简单时间戳脚本
34 | if ! "$SCRIPT_DIR/timestamp.sh" full &>/dev/null; then
35 | echo -e "${YELLOW}警告: 使用本地时间而非太平洋时间${NC}"
36 | echo -e "${YELLOW}如需使用太平洋时间,请确保已安装Python 3.6+和pytz库${NC}"
37 | fi
38 |
39 | # 获取项目名称
40 | PROJECT_NAME=$(grep "项目名称" "$PROJECT_ROOT/PROJECT_PROGRESS.md" | head -n 1 | cut -d ":" -f 2 | sed 's/^ *//' | sed 's/ *$//')
41 | if [ -z "$PROJECT_NAME" ] || [ "$PROJECT_NAME" = "[项目名称]" ]; then
42 | PROJECT_NAME="未命名项目"
43 | fi
44 |
45 | # 创建日报
46 | create_daily_report() {
47 | REPORT_FILE="$PROJECT_ROOT/project_management/actuals/reports/daily/daily_report_$COMPACT_DATE.md"
48 | TEMPLATE_FILE="$PROJECT_ROOT/project_management/templates/daily_report_template.md"
49 |
50 | echo -e "${BLUE}=== 创建日报: $COMPACT_DATE ===${NC}"
51 | echo -e "${BLUE}=== 时间戳: $FULL_TIMESTAMP ===${NC}"
52 |
53 | # 检查是否已存在
54 | if [ -f "$REPORT_FILE" ]; then
55 | echo -e "${YELLOW}警告: 今日日报已存在${NC}"
56 | read -p "是否覆盖? (y/n): " -n 1 -r
57 | echo
58 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then
59 | echo -e "${RED}已取消${NC}"
60 | return
61 | fi
62 | fi
63 |
64 | # 复制模板并替换占位符
65 | cp "$TEMPLATE_FILE" "$REPORT_FILE"
66 | sed -i '' "s/{{DATE}}/$CURRENT_DATE/g" "$REPORT_FILE"
67 | sed -i '' "s/{{PROJECT_NAME}}/$PROJECT_NAME/g" "$REPORT_FILE"
68 | sed -i '' "s/{{AUTHOR}}/$(whoami)/g" "$REPORT_FILE"
69 | sed -i '' "s/{{TIMESTAMP}}/$FULL_TIMESTAMP/g" "$REPORT_FILE"
70 |
71 | echo -e "${GREEN}日报已创建: $REPORT_FILE${NC}"
72 | }
73 |
74 | # 创建周报
75 | create_weekly_report() {
76 | # 使用太平洋时间的年份和周数
77 | YEAR_WEEK=$WEEK_NUMBER
78 | REPORT_FILE="$PROJECT_ROOT/project_management/actuals/reports/weekly/weekly_report_$YEAR_WEEK.md"
79 | TEMPLATE_FILE="$PROJECT_ROOT/project_management/templates/weekly_report_template.md"
80 |
81 | # 计算本周的开始和结束日期
82 | # 尝试使用Python脚本,如果失败则使用简单方法
83 | if "$SCRIPT_DIR/timestamp.sh" full &>/dev/null; then
84 | # 使用Python脚本计算
85 | WEEK_START=$(python3 -c "
86 | import datetime, pytz
87 | pacific = pytz.timezone('America/Los_Angeles')
88 | now = datetime.datetime.now(pacific)
89 | start = now - datetime.timedelta(days=now.weekday())
90 | print(start.strftime('%Y-%m-%d'))
91 | " 2>/dev/null || date -v-$(date +%u)d +"%Y-%m-%d")
92 |
93 | WEEK_END=$(python3 -c "
94 | import datetime, pytz
95 | pacific = pytz.timezone('America/Los_Angeles')
96 | now = datetime.datetime.now(pacific)
97 | start = now - datetime.timedelta(days=now.weekday())
98 | end = start + datetime.timedelta(days=6)
99 | print(end.strftime('%Y-%m-%d'))
100 | " 2>/dev/null || date -v-$(date +%u)d -v+6d +"%Y-%m-%d")
101 | else
102 | # 使用简单方法计算
103 | WEEK_START=$(date -v-$(date +%u)d +"%Y-%m-%d")
104 | WEEK_END=$(date -v-$(date +%u)d -v+6d +"%Y-%m-%d")
105 | fi
106 |
107 | # 提取周数
108 | WEEK_NUM=$(echo $YEAR_WEEK | cut -d 'W' -f 2)
109 |
110 | echo -e "${BLUE}=== 创建周报: 第$WEEK_NUM周 ($WEEK_START 至 $WEEK_END) ===${NC}"
111 | echo -e "${BLUE}=== 时间戳: $FULL_TIMESTAMP ===${NC}"
112 |
113 | # 检查是否已存在
114 | if [ -f "$REPORT_FILE" ]; then
115 | echo -e "${YELLOW}警告: 本周周报已存在${NC}"
116 | read -p "是否覆盖? (y/n): " -n 1 -r
117 | echo
118 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then
119 | echo -e "${RED}已取消${NC}"
120 | return
121 | fi
122 | fi
123 |
124 | # 复制模板并替换占位符
125 | cp "$TEMPLATE_FILE" "$REPORT_FILE"
126 | sed -i '' "s/{{WEEK_NUMBER}}/$WEEK_NUM/g" "$REPORT_FILE"
127 | sed -i '' "s/{{PROJECT_NAME}}/$PROJECT_NAME/g" "$REPORT_FILE"
128 | sed -i '' "s/{{START_DATE}}/$WEEK_START/g" "$REPORT_FILE"
129 | sed -i '' "s/{{END_DATE}}/$WEEK_END/g" "$REPORT_FILE"
130 | sed -i '' "s/{{AUTHOR}}/$(whoami)/g" "$REPORT_FILE"
131 | sed -i '' "s/{{TIMESTAMP}}/$FULL_TIMESTAMP/g" "$REPORT_FILE"
132 |
133 | echo -e "${GREEN}周报已创建: $REPORT_FILE${NC}"
134 | }
135 |
136 | # 根据报告类型执行相应的函数
137 | case "$REPORT_TYPE" in
138 | daily)
139 | create_daily_report
140 | ;;
141 | weekly)
142 | create_weekly_report
143 | ;;
144 | *)
145 | echo -e "${RED}错误: 无效的报告类型 '$REPORT_TYPE'${NC}"
146 | echo -e "有效的报告类型: daily, weekly"
147 | exit 1
148 | ;;
149 | esac
--------------------------------------------------------------------------------
/scripts/generate_timestamp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | """
5 | CursorMind 时间戳生成脚本
6 | 生成美国太平洋时间的时间戳
7 | """
8 |
9 | import datetime
10 | import pytz
11 | import sys
12 |
13 | def get_pacific_timestamp(format_type='full'):
14 | """
15 | 获取美国太平洋时间的时间戳
16 |
17 | 参数:
18 | format_type (str): 时间戳格式类型
19 | - 'full': 完整格式 YYYY-MM-DD HH:MM:SS PST/PDT
20 | - 'date': 仅日期 YYYY-MM-DD
21 | - 'datetime': 日期和时间 YYYY-MM-DD HH:MM:SS
22 | - 'compact': 紧凑格式 YYYYMMDD
23 | - 'week': 年份和周数 YYYYWNN
24 |
25 | 返回:
26 | str: 格式化的时间戳
27 | """
28 | # 获取太平洋时区的当前时间
29 | pacific_tz = pytz.timezone('America/Los_Angeles')
30 | now = datetime.datetime.now(pacific_tz)
31 |
32 | # 确定是PST还是PDT
33 | timezone_name = now.strftime('%Z')
34 |
35 | if format_type == 'full':
36 | # 完整格式: YYYY-MM-DD HH:MM:SS PST/PDT
37 | return now.strftime('%Y-%m-%d %H:%M:%S') + f" {timezone_name}"
38 | elif format_type == 'date':
39 | # 仅日期: YYYY-MM-DD
40 | return now.strftime('%Y-%m-%d')
41 | elif format_type == 'datetime':
42 | # 日期和时间: YYYY-MM-DD HH:MM:SS
43 | return now.strftime('%Y-%m-%d %H:%M:%S')
44 | elif format_type == 'compact':
45 | # 紧凑格式: YYYYMMDD
46 | return now.strftime('%Y%m%d')
47 | elif format_type == 'week':
48 | # 年份和周数: YYYYWNN
49 | year = now.strftime('%Y')
50 | week = now.strftime('%U')
51 | return f"{year}W{week}"
52 | else:
53 | raise ValueError(f"不支持的格式类型: {format_type}")
54 |
55 | if __name__ == "__main__":
56 | # 如果有命令行参数,使用它作为格式类型
57 | format_type = 'full'
58 | if len(sys.argv) > 1:
59 | format_type = sys.argv[1]
60 |
61 | try:
62 | timestamp = get_pacific_timestamp(format_type)
63 | print(timestamp)
64 | except ValueError as e:
65 | print(f"错误: {e}", file=sys.stderr)
66 | print("支持的格式类型: full, date, datetime, compact, week", file=sys.stderr)
67 | sys.exit(1)
--------------------------------------------------------------------------------
/scripts/hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 检查时间戳格式的 pre-commit hook
4 |
5 | # 获取当前的太平洋时间戳格式
6 | CORRECT_FORMAT=$(python3 scripts/generate_timestamp.py full)
7 | TIMEZONE=$(echo $CORRECT_FORMAT | awk '{print $NF}')
8 |
9 | # 检查文档中的时间戳格式
10 | check_timestamps() {
11 | local file="$1"
12 | if grep -E "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} (PST|PDT)" "$file" | grep -v "$TIMEZONE"; then
13 | echo "错误: $file 中存在不正确的时区格式,请使用 scripts/generate_timestamp.py 生成时间戳"
14 | return 1
15 | fi
16 | return 0
17 | }
18 |
19 | # 获取待提交的 Markdown 文件
20 | files=$(git diff --cached --name-only --diff-filter=ACM | grep "\.md$")
21 |
22 | # 检查每个文件
23 | for file in $files; do
24 | if [ -f "$file" ]; then
25 | if ! check_timestamps "$file"; then
26 | exit 1
27 | fi
28 | fi
29 | done
30 |
31 | exit 0
--------------------------------------------------------------------------------
/scripts/init_project.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # CursorMind 项目初始化脚本
4 | # 用法: ./init_project.sh "项目名称"
5 |
6 | set -e
7 |
8 | # 颜色定义
9 | RED='\033[0;31m'
10 | GREEN='\033[0;32m'
11 | YELLOW='\033[0;33m'
12 | BLUE='\033[0;34m'
13 | NC='\033[0m' # No Color
14 |
15 | # 检查参数
16 | if [ $# -lt 1 ]; then
17 | echo -e "${RED}错误: 缺少项目名称参数${NC}"
18 | echo -e "用法: $0 \"项目名称\""
19 | exit 1
20 | fi
21 |
22 | PROJECT_NAME="$1"
23 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24 | PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
25 |
26 | # 获取太平洋时间戳
27 | # 尝试使用Python时间戳脚本,如果失败则使用简单时间戳脚本
28 | CURRENT_DATE=$("$SCRIPT_DIR/timestamp.sh" date 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" date)
29 | FULL_TIMESTAMP=$("$SCRIPT_DIR/timestamp.sh" full 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" full)
30 |
31 | # 检查是否使用了简单时间戳脚本
32 | if ! "$SCRIPT_DIR/timestamp.sh" full &>/dev/null; then
33 | echo -e "${YELLOW}警告: 使用本地时间而非太平洋时间${NC}"
34 | echo -e "${YELLOW}如需使用太平洋时间,请确保已安装Python 3.6+和pytz库${NC}"
35 | fi
36 |
37 | echo -e "${BLUE}=== 初始化项目: $PROJECT_NAME ===${NC}"
38 | echo -e "${BLUE}=== 时间戳: $FULL_TIMESTAMP ===${NC}"
39 |
40 | # 更新 PROJECT_PROGRESS.md
41 | echo -e "${YELLOW}更新项目进度文件...${NC}"
42 | sed -i '' "s/\[项目名称\]/$PROJECT_NAME/g" "$PROJECT_ROOT/PROJECT_PROGRESS.md"
43 | sed -i '' "s/\[YYYY-MM-DD\]/$CURRENT_DATE/g" "$PROJECT_ROOT/PROJECT_PROGRESS.md"
44 | sed -i '' "s/最后更新: YYYY-MM-DD/最后更新: $FULL_TIMESTAMP/g" "$PROJECT_ROOT/PROJECT_PROGRESS.md"
45 |
46 | # 更新 MAIN_CONTROL.md
47 | echo -e "${YELLOW}更新中央控制文档...${NC}"
48 | sed -i '' "s/\[项目名称\]/$PROJECT_NAME/g" "$PROJECT_ROOT/project_management/control/MAIN_CONTROL.md"
49 | sed -i '' "s/\[YYYY-MM-DD\]/$CURRENT_DATE/g" "$PROJECT_ROOT/project_management/control/MAIN_CONTROL.md"
50 | sed -i '' "s/- \*\*最后更新\*\*: \[YYYY-MM-DD\]/- **最后更新**: $FULL_TIMESTAMP/g" "$PROJECT_ROOT/project_management/control/MAIN_CONTROL.md"
51 |
52 | # 更新 REQUIREMENTS.md
53 | echo -e "${YELLOW}更新需求文档...${NC}"
54 | sed -i '' "s/\[项目名称\]/$PROJECT_NAME/g" "$PROJECT_ROOT/project_management/control/REQUIREMENTS.md"
55 | sed -i '' "s/\[YYYY-MM-DD\]/$CURRENT_DATE/g" "$PROJECT_ROOT/project_management/control/REQUIREMENTS.md"
56 | sed -i '' "s/- \*\*最后更新\*\*: \[YYYY-MM-DD\]/- **最后更新**: $FULL_TIMESTAMP/g" "$PROJECT_ROOT/project_management/control/REQUIREMENTS.md"
57 |
58 | # 创建初始日报
59 | echo -e "${YELLOW}创建今日日报...${NC}"
60 | "$SCRIPT_DIR/create_report.sh" daily
61 |
62 | # 创建初始周报
63 | echo -e "${YELLOW}创建本周周报...${NC}"
64 | "$SCRIPT_DIR/create_report.sh" weekly
65 |
66 | # 设置脚本权限
67 | echo -e "${YELLOW}设置脚本执行权限...${NC}"
68 | chmod +x "$SCRIPT_DIR"/*.sh
69 | chmod +x "$SCRIPT_DIR"/*.py
70 |
71 | echo -e "${GREEN}=== 项目初始化完成! ===${NC}"
72 | echo -e "项目名称: ${BLUE}$PROJECT_NAME${NC}"
73 | echo -e "初始化时间: ${BLUE}$FULL_TIMESTAMP${NC}"
74 | echo -e "\n${YELLOW}接下来您可以:${NC}"
75 | echo -e "1. 查看和编辑 ${BLUE}PROJECT_PROGRESS.md${NC} 文件"
76 | echo -e "2. 查看和编辑 ${BLUE}project_management/control/MAIN_CONTROL.md${NC} 文件"
77 | echo -e "3. 查看今日创建的日报和周报"
78 | echo -e "\n${GREEN}祝您项目顺利!${NC}"
--------------------------------------------------------------------------------
/scripts/simple_timestamp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # CursorMind 简单时间戳生成脚本
4 | # 用法: ./simple_timestamp.sh [format_type]
5 | # format_type 可以是: full, date, datetime, compact, week
6 |
7 | # 注意: 此脚本使用系统时间,不是太平洋时间
8 | # 如果需要太平洋时间,请使用timestamp.sh脚本
9 |
10 | format_type="${1:-full}"
11 |
12 | case "$format_type" in
13 | full)
14 | # 完整格式: YYYY-MM-DD HH:MM:SS TZ
15 | date "+%Y-%m-%d %H:%M:%S %Z"
16 | ;;
17 | date)
18 | # 仅日期: YYYY-MM-DD
19 | date "+%Y-%m-%d"
20 | ;;
21 | datetime)
22 | # 日期和时间: YYYY-MM-DD HH:MM:SS
23 | date "+%Y-%m-%d %H:%M:%S"
24 | ;;
25 | compact)
26 | # 紧凑格式: YYYYMMDD
27 | date "+%Y%m%d"
28 | ;;
29 | week)
30 | # 年份和周数: YYYYWNN
31 | date "+%YW%U"
32 | ;;
33 | *)
34 | echo "错误: 不支持的格式类型: $format_type" >&2
35 | echo "支持的格式类型: full, date, datetime, compact, week" >&2
36 | exit 1
37 | ;;
38 | esac
--------------------------------------------------------------------------------
/scripts/timestamp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # CursorMind 时间戳生成脚本包装器
4 | # 用法: ./timestamp.sh [format_type]
5 | # format_type 可以是: full, date, datetime, compact, week
6 |
7 | set -e
8 |
9 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10 | PYTHON_SCRIPT="$SCRIPT_DIR/generate_timestamp.py"
11 | VENV_DIR="$SCRIPT_DIR/.venv"
12 |
13 | # 检查Python脚本是否存在
14 | if [ ! -f "$PYTHON_SCRIPT" ]; then
15 | echo "错误: 找不到Python时间戳脚本: $PYTHON_SCRIPT" >&2
16 | exit 1
17 | fi
18 |
19 | # 如果虚拟环境不存在,创建一个
20 | if [ ! -d "$VENV_DIR" ]; then
21 | echo "创建Python虚拟环境..." >&2
22 | python3 -m venv "$VENV_DIR" || {
23 | echo "错误: 无法创建虚拟环境,请确保已安装Python 3.6+" >&2
24 |
25 | # 回退方案:直接使用系统Python,但可能会失败
26 | echo "尝试使用系统Python..." >&2
27 | if ! python3 -c "import pytz" &>/dev/null; then
28 | echo "错误: 未安装pytz模块,请手动安装: pip3 install pytz" >&2
29 |
30 | # 生成一个基本的时间戳作为回退
31 | date "+%Y-%m-%d %H:%M:%S"
32 | exit 1
33 | fi
34 |
35 | python3 "$PYTHON_SCRIPT" "$@"
36 | exit $?
37 | }
38 |
39 | # 安装依赖
40 | "$VENV_DIR/bin/pip" install pytz || {
41 | echo "错误: 无法安装pytz模块" >&2
42 | exit 1
43 | }
44 | fi
45 |
46 | # 使用虚拟环境中的Python运行脚本
47 | "$VENV_DIR/bin/python" "$PYTHON_SCRIPT" "$@" || {
48 | # 如果失败,尝试使用系统Python
49 | echo "警告: 虚拟环境执行失败,尝试使用系统Python..." >&2
50 | python3 "$PYTHON_SCRIPT" "$@" || {
51 | # 如果仍然失败,使用系统日期命令作为回退
52 | echo "错误: 无法执行Python脚本,使用系统日期命令作为回退" >&2
53 | if [ "$1" = "full" ]; then
54 | date "+%Y-%m-%d %H:%M:%S"
55 | elif [ "$1" = "date" ]; then
56 | date "+%Y-%m-%d"
57 | elif [ "$1" = "compact" ]; then
58 | date "+%Y%m%d"
59 | elif [ "$1" = "week" ]; then
60 | date "+%YW%U"
61 | else
62 | date "+%Y-%m-%d %H:%M:%S"
63 | fi
64 | }
65 | }
--------------------------------------------------------------------------------
/scripts/update_progress.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # CursorMind 项目进度更新脚本
4 | # 用法: ./update_progress.sh <进度百分比> ["更新内容"]
5 |
6 | set -e
7 |
8 | # 颜色定义
9 | RED='\033[0;31m'
10 | GREEN='\033[0;32m'
11 | YELLOW='\033[0;33m'
12 | BLUE='\033[0;34m'
13 | NC='\033[0m' # No Color
14 |
15 | # 检查参数
16 | if [ $# -lt 1 ]; then
17 | echo -e "${RED}错误: 缺少进度百分比参数${NC}"
18 | echo -e "用法: $0 <进度百分比> [\"更新内容\"]"
19 | exit 1
20 | fi
21 |
22 | PROGRESS="$1"
23 | UPDATE_CONTENT="${2:-项目进度更新}"
24 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25 | PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
26 | PROGRESS_FILE="$PROJECT_ROOT/PROJECT_PROGRESS.md"
27 | MAIN_CONTROL_FILE="$PROJECT_ROOT/project_management/control/MAIN_CONTROL.md"
28 |
29 | # 获取太平洋时间戳
30 | # 尝试使用Python时间戳脚本,如果失败则使用简单时间戳脚本
31 | CURRENT_DATE=$("$SCRIPT_DIR/timestamp.sh" date 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" date)
32 | FULL_TIMESTAMP=$("$SCRIPT_DIR/timestamp.sh" full 2>/dev/null || "$SCRIPT_DIR/simple_timestamp.sh" full)
33 |
34 | # 检查是否使用了简单时间戳脚本
35 | if ! "$SCRIPT_DIR/timestamp.sh" full &>/dev/null; then
36 | echo -e "${YELLOW}警告: 使用本地时间而非太平洋时间${NC}"
37 | echo -e "${YELLOW}如需使用太平洋时间,请确保已安装Python 3.6+和pytz库${NC}"
38 | fi
39 |
40 | # 验证进度百分比
41 | if ! [[ "$PROGRESS" =~ ^[0-9]+$ ]] || [ "$PROGRESS" -lt 0 ] || [ "$PROGRESS" -gt 100 ]; then
42 | echo -e "${RED}错误: 进度百分比必须是0-100之间的整数${NC}"
43 | exit 1
44 | fi
45 |
46 | echo -e "${BLUE}=== 更新项目进度: $PROGRESS% ===${NC}"
47 | echo -e "${BLUE}=== 时间戳: $FULL_TIMESTAMP ===${NC}"
48 |
49 | # 获取当前用户
50 | CURRENT_USER=$(whoami)
51 |
52 | # 更新 PROJECT_PROGRESS.md
53 | echo -e "${YELLOW}更新项目进度文件...${NC}"
54 |
55 | # 更新当前进度
56 | sed -i '' "s/- \*\*当前进度\*\*: \[[0-9]*-[0-9]*\]%/- **当前进度**: $PROGRESS%/g" "$PROGRESS_FILE"
57 | sed -i '' "s/- \*\*当前进度\*\*: [0-9]*%/- **当前进度**: $PROGRESS%/g" "$PROGRESS_FILE"
58 |
59 | # 更新最后更新时间
60 | sed -i '' "s/最后更新: .*$/最后更新: $FULL_TIMESTAMP/g" "$PROGRESS_FILE"
61 |
62 | # 添加进度更新历史
63 | # 查找进度更新历史表格的结束位置
64 | TABLE_END=$(grep -n "## 风险与问题" "$PROGRESS_FILE" | cut -d ":" -f 1)
65 | TABLE_START=$(grep -n "## 进度更新历史" "$PROGRESS_FILE" | cut -d ":" -f 1)
66 | TABLE_START=$((TABLE_START + 2)) # 跳过表头和分隔行
67 |
68 | # 在表格开头插入新行
69 | NEW_LINE="| $CURRENT_DATE | $PROGRESS% | $UPDATE_CONTENT | $CURRENT_USER |"
70 | sed -i '' "${TABLE_START}a\\
71 | $NEW_LINE" "$PROGRESS_FILE"
72 |
73 | # 更新 MAIN_CONTROL.md
74 | echo -e "${YELLOW}更新中央控制文档...${NC}"
75 | sed -i '' "s/- \*\*进度\*\*: \[[0-9]*-[0-9]*\]%/- **进度**: $PROGRESS%/g" "$MAIN_CONTROL_FILE"
76 | sed -i '' "s/- \*\*进度\*\*: [0-9]*%/- **进度**: $PROGRESS%/g" "$MAIN_CONTROL_FILE"
77 | sed -i '' "s/- \*\*最后更新\*\*: .*$/- **最后更新**: $FULL_TIMESTAMP/g" "$MAIN_CONTROL_FILE"
78 |
79 | # 添加变更记录
80 | # 查找关键决策记录表格的开始位置
81 | DECISION_TABLE_START=$(grep -n "## 关键决策记录" "$MAIN_CONTROL_FILE" | cut -d ":" -f 1)
82 | DECISION_TABLE_START=$((DECISION_TABLE_START + 2)) # 跳过表头和分隔行
83 |
84 | # 生成新的决策ID
85 | LAST_DECISION_ID=$(grep -A 1 "## 关键决策记录" "$MAIN_CONTROL_FILE" | grep "D[0-9]\{3\}" | sort | tail -n 1 | awk '{print $1}' | sed 's/|//g')
86 | if [ -z "$LAST_DECISION_ID" ]; then
87 | NEW_DECISION_ID="D001"
88 | else
89 | LAST_NUM=${LAST_DECISION_ID:1}
90 | NEW_NUM=$((10#$LAST_NUM + 1))
91 | NEW_DECISION_ID="D$(printf "%03d" $NEW_NUM)"
92 | fi
93 |
94 | # 在表格开头插入新行
95 | DECISION_LINE="| $NEW_DECISION_ID | $CURRENT_DATE | 进度更新至 $PROGRESS% | 项目进度变更 | $CURRENT_USER |"
96 | sed -i '' "${DECISION_TABLE_START}a\\
97 | $DECISION_LINE" "$MAIN_CONTROL_FILE"
98 |
99 | echo -e "${GREEN}=== 项目进度已更新! ===${NC}"
100 | echo -e "当前进度: ${BLUE}$PROGRESS%${NC}"
101 | echo -e "更新内容: ${BLUE}$UPDATE_CONTENT${NC}"
102 | echo -e "更新时间: ${BLUE}$FULL_TIMESTAMP${NC}"
103 | echo -e "更新人: ${BLUE}$CURRENT_USER${NC}"
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name="cursormind",
5 | version="0.2.1",
6 | packages=find_packages(where="src"),
7 | package_dir={"": "src"},
8 | install_requires=[
9 | "click>=8.0.0",
10 | "rich>=10.0.0",
11 | "python-dateutil>=2.8.2",
12 | "pytz>=2021.3",
13 | ],
14 | entry_points={
15 | "console_scripts": [
16 | "cursormind=cursormind.cli:main",
17 | ],
18 | },
19 | )
--------------------------------------------------------------------------------
/src/cursormind/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | CursorMind - 你的智能学习助手 📚
3 | """
4 |
5 | __version__ = "0.2.1"
6 | __author__ = "Yagami"
--------------------------------------------------------------------------------
/src/cursormind/__main__.py:
--------------------------------------------------------------------------------
1 | """
2 | CursorMind 包的主入口
3 | """
4 | from cursormind.cli import main
5 |
6 | if __name__ == '__main__':
7 | main()
--------------------------------------------------------------------------------
/src/cursormind/cli.py:
--------------------------------------------------------------------------------
1 | """
2 | 命令行接口模块 - 你的学习助手入口 🚀
3 | """
4 | import click
5 | from typing import Dict, List, Optional
6 | from rich.console import Console
7 | from rich.table import Table
8 | from rich.markdown import Markdown
9 | from rich.progress import Progress, SpinnerColumn, TextColumn
10 | from cursormind.core.learning_path import learning_path_manager
11 | from cursormind.core.note_manager import note_manager
12 | from cursormind.core.achievement import achievement_manager
13 | from cursormind.core.cursor_framework import cursor_framework
14 | from cursormind.core.project_manager import project_manager
15 | from cursormind.core.code_review import CodeReview
16 | from cursormind.config.settings import settings
17 | from cursormind import __version__
18 |
19 | console = Console()
20 |
21 | @click.group()
22 | @click.version_option(version=__version__)
23 | def main():
24 | """CursorMind - 你的智能学习助手 📚"""
25 | pass
26 |
27 | @main.group(name='cursor')
28 | def cursor():
29 | """Cursor 规范框架 🎯"""
30 | pass
31 |
32 | @cursor.command(name='init')
33 | @click.argument('project_path', type=click.Path(exists=True), default='.')
34 | @click.option('--template', '-t', default='default', help='项目模板名称')
35 | def cursor_init(project_path: str, template: str):
36 | """初始化项目结构"""
37 | with Progress(
38 | SpinnerColumn(),
39 | TextColumn("[progress.description]{task.description}"),
40 | console=console
41 | ) as progress:
42 | progress.add_task("正在生成项目结构...", total=None)
43 | if cursor_framework.generate_project_template(project_path, template):
44 | console.print("[green]✨ 项目结构初始化成功![/green]")
45 | else:
46 | console.print("[red]❌ 项目结构初始化失败[/red]")
47 |
48 | @cursor.command(name='check')
49 | @click.argument('project_path', type=click.Path(exists=True), default='.')
50 | def cursor_check(project_path: str):
51 | """检查项目结构是否符合规范"""
52 | issues = cursor_framework.check_project_structure(project_path)
53 |
54 | if not issues["missing_dirs"] and not issues["missing_files"]:
55 | console.print("[green]✨ 项目结构符合规范![/green]")
56 | return
57 |
58 | console.print("[yellow]⚠️ 发现以下问题:[/yellow]")
59 |
60 | if issues["missing_dirs"]:
61 | console.print("\n[red]缺少必要的目录:[/red]")
62 | for dir_name in issues["missing_dirs"]:
63 | console.print(f"- {dir_name}")
64 |
65 | if issues["missing_files"]:
66 | console.print("\n[red]缺少必要的文件:[/red]")
67 | for file_name in issues["missing_files"]:
68 | console.print(f"- {file_name}")
69 |
70 | @cursor.command(name='commit')
71 | @click.argument('message')
72 | def cursor_commit(message: str):
73 | """验证提交信息是否符合规范"""
74 | result = cursor_framework.validate_commit_message(message)
75 |
76 | if result["valid"]:
77 | console.print("[green]✨ 提交信息符合规范![/green]")
78 | else:
79 | console.print("[red]❌ 提交信息不符合规范[/red]")
80 | if not result["type_valid"]:
81 | console.print("\n提交类型必须是以下之一:")
82 | for type_ in cursor_framework.rules["git"]["commit_types"]:
83 | console.print(f"- {type_}")
84 | if not result["format_valid"]:
85 | console.print(f"\n提交格式必须符合:[yellow]{cursor_framework.rules['git']['commit_format']}[/yellow]")
86 | console.print("示例:feat(user): add login function")
87 |
88 | @cursor.command(name='branch')
89 | @click.argument('branch_name')
90 | def cursor_branch(branch_name: str):
91 | """验证分支名称是否符合规范"""
92 | result = cursor_framework.validate_branch_name(branch_name)
93 |
94 | if result["valid"]:
95 | console.print("[green]✨ 分支名称符合规范![/green]")
96 | else:
97 | console.print("[red]❌ 分支名称不符合规范[/red]")
98 | console.print("\n分支名称格式必须符合:")
99 | for type_, format_ in cursor_framework.rules["git"]["branch_format"].items():
100 | console.print(f"- {type_}: {format_}")
101 | console.print(f" 示例:{format_.replace('', 'login')}")
102 |
103 | @main.group(name='path')
104 | def path():
105 | """学习路径管理 🗺️"""
106 | pass
107 |
108 | @path.command(name='list')
109 | def path_list():
110 | """列出所有可用的学习路径"""
111 | paths = learning_path_manager.get_all_paths()
112 |
113 | table = Table(title="可用的学习路径")
114 | table.add_column("ID", style="cyan")
115 | table.add_column("名称", style="green")
116 | table.add_column("描述", style="blue")
117 | table.add_column("难度", style="yellow")
118 | table.add_column("预计时间", style="magenta")
119 |
120 | for path in paths:
121 | table.add_row(
122 | path['id'],
123 | path['name'],
124 | path['description'],
125 | path['difficulty'],
126 | path['estimated_time']
127 | )
128 |
129 | console.print(table)
130 |
131 | @path.command(name='start')
132 | @click.argument('path_id')
133 | def path_start(path_id: str):
134 | """开始一个学习路径"""
135 | if learning_path_manager.set_current_path(path_id):
136 | progress = learning_path_manager.get_current_progress()
137 | console.print(f"[green]✨ 成功开始学习路径:{progress['path_name']}[/green]")
138 | console.print(f"\n当前阶段:[yellow]{progress['current_stage_name']}[/yellow]")
139 | console.print(f"当前任务:[blue]{progress['current_step_name']}[/blue]")
140 |
141 | # 显示学习资源
142 | resources = learning_path_manager.get_current_resources()
143 | if resources:
144 | console.print("\n📚 推荐学习资源:")
145 | for resource in resources:
146 | console.print(f"- {resource['name']}: {resource['url']}")
147 |
148 | # 显示练习项目
149 | projects = learning_path_manager.get_current_projects()
150 | if projects:
151 | console.print("\n🎯 练习项目:")
152 | for project in projects:
153 | console.print(f"- {project['name']}: {project['description']}")
154 | else:
155 | console.print(f"[red]❌ 未找到ID为 {path_id} 的学习路径[/red]")
156 |
157 | @path.command(name='status')
158 | def path_status():
159 | """查看当前学习进度"""
160 | progress = learning_path_manager.get_current_progress()
161 | if progress:
162 | console.print(f"\n📊 当前学习进度:[green]{progress['path_name']}[/green]")
163 | console.print(f"阶段:[yellow]{progress['current_stage_name']}[/yellow]")
164 | console.print(f"任务:[blue]{progress['current_step_name']}[/blue]")
165 | console.print(f"完成度:[magenta]{progress['progress']} ({progress['percentage']}%)[/magenta]")
166 |
167 | # 显示当前阶段的资源和项目
168 | resources = learning_path_manager.get_current_resources()
169 | if resources:
170 | console.print("\n📚 当前阶段学习资源:")
171 | for resource in resources:
172 | console.print(f"- {resource['name']}: {resource['url']}")
173 |
174 | projects = learning_path_manager.get_current_projects()
175 | if projects:
176 | console.print("\n🎯 当前阶段练习项目:")
177 | for project in projects:
178 | console.print(f"- {project['name']}: {project['description']}")
179 | else:
180 | console.print("[yellow]⚠️ 你还没有开始任何学习路径[/yellow]")
181 | console.print("使用 [green]cursormind path list[/green] 查看可用的学习路径")
182 | console.print("使用 [green]cursormind path start <路径ID>[/green] 开始学习")
183 |
184 | @path.command(name='next')
185 | def path_next():
186 | """完成当前任务,进入下一个任务"""
187 | progress_before = learning_path_manager.get_current_progress()
188 | if not progress_before:
189 | console.print("[yellow]⚠️ 你还没有开始任何学习路径[/yellow]")
190 | return
191 |
192 | if learning_path_manager.advance_progress():
193 | progress = learning_path_manager.get_current_progress()
194 | console.print(f"[green]✨ 恭喜完成任务:{progress_before['current_step_name']}[/green]")
195 | if progress:
196 | console.print(f"\n下一个任务:[blue]{progress['current_step_name']}[/blue]")
197 |
198 | # 显示新任务的资源和项目
199 | resources = learning_path_manager.get_current_resources()
200 | if resources:
201 | console.print("\n📚 推荐学习资源:")
202 | for resource in resources:
203 | console.print(f"- {resource['name']}: {resource['url']}")
204 |
205 | projects = learning_path_manager.get_current_projects()
206 | if projects:
207 | console.print("\n🎯 练习项目:")
208 | for project in projects:
209 | console.print(f"- {project['name']}: {project['description']}")
210 | else:
211 | console.print("[yellow]🎉 恭喜!你已经完成了当前学习路径的所有任务![/yellow]")
212 |
213 | @main.group(name='note')
214 | def note():
215 | """笔记管理 📝"""
216 | pass
217 |
218 | @note.command(name='add')
219 | @click.argument('content')
220 | @click.option('--topic', '-t', default='general', help='笔记主题')
221 | def note_add(content: str, topic: str):
222 | """添加新笔记"""
223 | note = note_manager.add_note(content, topic)
224 | console.print(f"[green]✨ 笔记已保存![/green]")
225 | console.print(f"ID: [blue]{note['id']}[/blue]")
226 | console.print(f"主题: [yellow]{note['topic']}[/yellow]")
227 | if note['tags']:
228 | console.print(f"标签: [magenta]{', '.join(note['tags'])}[/magenta]")
229 |
230 | @note.command(name='today')
231 | def note_today():
232 | """查看今天的笔记"""
233 | notes = note_manager.get_daily_notes()
234 | if notes:
235 | console.print("\n📝 今日笔记:")
236 | for note in notes:
237 | console.print(f"\n[blue]{note['created_at']}[/blue]")
238 | console.print(f"[yellow]主题:{note['topic']}[/yellow]")
239 | if note['tags']:
240 | console.print(f"[magenta]标签:{', '.join(note['tags'])}[/magenta]")
241 | console.print(Markdown(note['content']))
242 | else:
243 | console.print("[yellow]今天还没有记录笔记哦~[/yellow]")
244 |
245 | @note.command(name='topic')
246 | @click.argument('topic')
247 | def note_topic(topic: str):
248 | """查看指定主题的笔记"""
249 | notes = note_manager.get_topic_notes(topic)
250 | if notes:
251 | console.print(f"\n📚 主题 [green]{topic}[/green] 的笔记:")
252 | for note in notes:
253 | console.print(f"\n[blue]{note['created_at']}[/blue]")
254 | if note['tags']:
255 | console.print(f"[magenta]标签:{', '.join(note['tags'])}[/magenta]")
256 | console.print(Markdown(note['content']))
257 | else:
258 | console.print(f"[yellow]还没有 {topic} 主题的笔记~[/yellow]")
259 |
260 | @note.command(name='search')
261 | @click.argument('query')
262 | def note_search(query: str):
263 | """搜索笔记"""
264 | notes = note_manager.search_notes(query)
265 | if notes:
266 | console.print(f"\n🔍 搜索结果:")
267 | for note in notes:
268 | console.print(f"\n[blue]{note['created_at']}[/blue]")
269 | console.print(f"[yellow]主题:{note['topic']}[/yellow]")
270 | if note['tags']:
271 | console.print(f"[magenta]标签:{', '.join(note['tags'])}[/magenta]")
272 | console.print(Markdown(note['content']))
273 | else:
274 | console.print(f"[yellow]没有找到匹配的笔记~[/yellow]")
275 |
276 | @note.command(name='stats')
277 | def note_stats():
278 | """查看笔记统计信息"""
279 | stats = note_manager.get_stats()
280 |
281 | console.print("\n📊 笔记统计:")
282 | console.print(f"总笔记数:[blue]{stats['total_notes']}[/blue] 条")
283 | console.print(f"总字数:[blue]{stats['total_words']}[/blue] 字")
284 | console.print(f"连续记录:[green]{stats['daily_streak']}[/green] 天")
285 |
286 | if stats['topics']:
287 | console.print("\n📚 主题分布:")
288 | topics_table = Table(show_header=False)
289 | topics_table.add_column("主题", style="yellow")
290 | topics_table.add_column("数量", style="cyan", justify="right")
291 | for topic, count in sorted(stats['topics'].items(), key=lambda x: x[1], reverse=True):
292 | topics_table.add_row(topic, str(count))
293 | console.print(topics_table)
294 |
295 | if stats['tags']:
296 | console.print("\n🏷️ 常用标签:")
297 | tags_table = Table(show_header=False)
298 | tags_table.add_column("标签", style="magenta")
299 | tags_table.add_column("使用次数", style="cyan", justify="right")
300 | for tag, count in sorted(stats['tags'].items(), key=lambda x: x[1], reverse=True)[:10]:
301 | tags_table.add_row(tag, str(count))
302 | console.print(tags_table)
303 |
304 | @note.command(name='review')
305 | @click.option('--days', '-d', default=7, help='要回顾的天数')
306 | def note_review(days: int):
307 | """生成学习回顾报告"""
308 | review = note_manager.generate_review(days)
309 |
310 | console.print(f"\n📅 学习回顾:{review['period']}")
311 | console.print(f"记录笔记:[blue]{review['total_notes']}[/blue] 条")
312 | console.print(f"总字数:[blue]{review['total_words']}[/blue] 字")
313 |
314 | if review['topics']:
315 | console.print("\n📚 主题分布:")
316 | topics_table = Table(show_header=False)
317 | topics_table.add_column("主题", style="yellow")
318 | topics_table.add_column("数量", style="cyan", justify="right")
319 | for topic, count in sorted(review['topics'].items(), key=lambda x: x[1], reverse=True):
320 | topics_table.add_row(topic, str(count))
321 | console.print(topics_table)
322 |
323 | if review['tags']:
324 | console.print("\n🏷️ 常用标签:")
325 | tags_table = Table(show_header=False)
326 | tags_table.add_column("标签", style="magenta")
327 | tags_table.add_column("使用次数", style="cyan", justify="right")
328 | for tag, count in sorted(review['tags'].items(), key=lambda x: x[1], reverse=True)[:10]:
329 | tags_table.add_row(tag, str(count))
330 | console.print(tags_table)
331 |
332 | if review['highlights']:
333 | console.print("\n✨ 学习亮点:")
334 | for note in review['highlights']:
335 | console.print(f"\n[blue]{note['created_at']}[/blue]")
336 | console.print(f"[yellow]主题:{note['topic']}[/yellow]")
337 | if note['tags']:
338 | console.print(f"[magenta]标签:{', '.join(note['tags'])}[/magenta]")
339 | console.print(Markdown(note['content']))
340 |
341 | @main.group(name='achievement')
342 | def achievement():
343 | """成就系统 🏆"""
344 | pass
345 |
346 | @achievement.command(name='list')
347 | @click.option('--all', '-a', is_flag=True, help='显示所有成就,包括未解锁的')
348 | def achievement_list(all: bool):
349 | """查看成就列表"""
350 | achievements = achievement_manager.get_achievements(include_locked=all)
351 |
352 | console.print("\n🏆 成就系统")
353 | stats = achievement_manager.get_stats()
354 | console.print(f"总积分:[green]{stats['points']}[/green] 分")
355 | console.print(f"已解锁:[blue]{len(stats['unlocked_achievements'])}[/blue] 个成就\n")
356 |
357 | for category, category_achievements in achievements.items():
358 | if category_achievements:
359 | console.print(f"\n[yellow]== {category.upper()} ==[/yellow]")
360 | for achievement_id, achievement in category_achievements.items():
361 | status = "[green]✓[/green]" if achievement['unlocked'] else "[grey]✗[/grey]"
362 | console.print(
363 | f"{status} {achievement['icon']} [{'green' if achievement['unlocked'] else 'grey'}"
364 | f"]{achievement['name']}[/{'green' if achievement['unlocked'] else 'grey'}]"
365 | )
366 | console.print(f" {achievement['description']}")
367 | console.print(f" 奖励:[yellow]{achievement['reward']}[/yellow] 分")
368 |
369 | @achievement.command(name='stats')
370 | def achievement_stats():
371 | """查看成就统计"""
372 | stats = achievement_manager.get_stats()
373 |
374 | console.print("\n📊 学习统计")
375 | console.print(f"总积分:[green]{stats['points']}[/green] 分")
376 | console.print(f"解锁成就:[blue]{len(stats['unlocked_achievements'])}[/blue] 个")
377 |
378 | stats_data = stats['stats']
379 | console.print("\n[yellow]== 学习路径 ==[/yellow]")
380 | console.print(f"开始的路径:[blue]{stats_data['paths_started']}[/blue] 个")
381 | console.print(f"完成的路径:[green]{stats_data['paths_completed']}[/green] 个")
382 |
383 | console.print("\n[yellow]== 笔记记录 ==[/yellow]")
384 | console.print(f"笔记总数:[blue]{stats_data['notes_created']}[/blue] 条")
385 | console.print(f"连续记录:[green]{stats_data['daily_streak']}[/green] 天")
386 | console.print(f"使用的标签:[magenta]{len(stats_data['unique_tags'])}[/magenta] 个")
387 | console.print(f"涉及的主题:[cyan]{len(stats_data['unique_topics'])}[/cyan] 个")
388 |
389 | console.print("\n[yellow]== 学习回顾 ==[/yellow]")
390 | console.print(f"生成的回顾报告:[blue]{stats_data['reviews_generated']}[/blue] 次")
391 |
392 | console.print(f"\n最后更新:[grey]{stats['last_updated']}[/grey]")
393 |
394 | @main.group(name='project')
395 | def project():
396 | """项目管理 📋"""
397 | pass
398 |
399 | @project.command(name='create')
400 | @click.argument('title')
401 | @click.option('--type', '-t', 'type_', help='任务类型')
402 | @click.option('--priority', '-p', help='优先级')
403 | @click.option('--assignee', '-a', help='负责人')
404 | @click.option('--description', '-d', help='任务描述')
405 | @click.option('--deadline', help='截止日期 (YYYY-MM-DD)')
406 | @click.option('--tags', help='标签(逗号分隔)')
407 | def project_create(title: str, type_: str, priority: str, assignee: str,
408 | description: str, deadline: str, tags: str):
409 | """创建新任务"""
410 | kwargs = {}
411 | if type_:
412 | kwargs['type'] = type_
413 | if priority:
414 | kwargs['priority'] = priority
415 | if assignee:
416 | kwargs['assignee'] = assignee
417 | if description:
418 | kwargs['description'] = description
419 | if deadline:
420 | kwargs['deadline'] = deadline
421 | if tags:
422 | kwargs['tags'] = [tag.strip() for tag in tags.split(',')]
423 |
424 | task = project_manager.create_task(title, **kwargs)
425 | console.print(f"[green]✨ 任务创建成功![/green]")
426 | _print_task_details(task)
427 |
428 | @project.command(name='list')
429 | @click.option('--status', '-s', help='任务状态')
430 | @click.option('--priority', '-p', help='优先级')
431 | @click.option('--type', '-t', 'type_', help='任务类型')
432 | @click.option('--assignee', '-a', help='负责人')
433 | @click.option('--tags', help='标签(逗号分隔)')
434 | def project_list(status: str, priority: str, type_: str, assignee: str, tags: str):
435 | """列出任务"""
436 | tags_list = [tag.strip() for tag in tags.split(',')] if tags else None
437 | tasks = project_manager.list_tasks(
438 | status=status,
439 | priority=priority,
440 | type_=type_,
441 | assignee=assignee,
442 | tags=tags_list
443 | )
444 |
445 | if not tasks:
446 | console.print("[yellow]没有找到匹配的任务[/yellow]")
447 | return
448 |
449 | table = Table(title="任务列表")
450 | table.add_column("ID", style="cyan")
451 | table.add_column("标题", style="green")
452 | table.add_column("状态", style="yellow")
453 | table.add_column("优先级", style="red")
454 | table.add_column("类型", style="blue")
455 | table.add_column("负责人", style="magenta")
456 | table.add_column("截止日期", style="cyan")
457 |
458 | for task in tasks:
459 | table.add_row(
460 | task['id'],
461 | task['title'],
462 | task['status'],
463 | task['priority'],
464 | task['type'],
465 | task['assignee'] or '-',
466 | task['deadline'] or '-'
467 | )
468 |
469 | console.print(table)
470 |
471 | @project.command(name='show')
472 | @click.argument('task_id')
473 | def project_show(task_id: str):
474 | """查看任务详情"""
475 | task = project_manager.get_task(task_id)
476 | if not task:
477 | console.print(f"[red]未找到任务:{task_id}[/red]")
478 | return
479 |
480 | _print_task_details(task)
481 |
482 | @project.command(name='update')
483 | @click.argument('task_id')
484 | @click.option('--title', '-t', help='任务标题')
485 | @click.option('--status', '-s', help='任务状态')
486 | @click.option('--priority', '-p', help='优先级')
487 | @click.option('--type', 'type_', help='任务类型')
488 | @click.option('--assignee', '-a', help='负责人')
489 | @click.option('--description', '-d', help='任务描述')
490 | @click.option('--deadline', help='截止日期 (YYYY-MM-DD)')
491 | @click.option('--tags', help='标签(逗号分隔)')
492 | def project_update(task_id: str, **kwargs):
493 | """更新任务"""
494 | if kwargs.get('tags'):
495 | kwargs['tags'] = [tag.strip() for tag in kwargs['tags'].split(',')]
496 |
497 | task = project_manager.update_task(task_id, **{k: v for k, v in kwargs.items() if v is not None})
498 | if not task:
499 | console.print(f"[red]未找到任务:{task_id}[/red]")
500 | return
501 |
502 | console.print(f"[green]✨ 任务更新成功![/green]")
503 | _print_task_details(task)
504 |
505 | @project.command(name='subtask')
506 | @click.argument('task_id')
507 | @click.argument('title')
508 | @click.option('--status', '-s', help='任务状态')
509 | def project_subtask(task_id: str, title: str, status: str):
510 | """添加子任务"""
511 | kwargs = {}
512 | if status:
513 | kwargs['status'] = status
514 |
515 | subtask = project_manager.add_subtask(task_id, title, **kwargs)
516 | if not subtask:
517 | console.print(f"[red]未找到任务:{task_id}[/red]")
518 | return
519 |
520 | console.print(f"[green]✨ 子任务添加成功![/green]")
521 | console.print(f"ID: [blue]{subtask['id']}[/blue]")
522 | console.print(f"标题: [green]{subtask['title']}[/green]")
523 | console.print(f"状态: [yellow]{subtask['status']}[/yellow]")
524 |
525 | @project.command(name='note')
526 | @click.argument('task_id')
527 | @click.argument('content')
528 | def project_note(task_id: str, content: str):
529 | """添加任务笔记"""
530 | note = project_manager.add_note(task_id, content)
531 | if not note:
532 | console.print(f"[red]未找到任务:{task_id}[/red]")
533 | return
534 |
535 | console.print(f"[green]✨ 笔记添加成功![/green]")
536 | console.print(f"ID: [blue]{note['id']}[/blue]")
537 | console.print(f"内容: [green]{note['content']}[/green]")
538 | console.print(f"时间: [yellow]{note['created_at']}[/yellow]")
539 |
540 | @project.command(name='link')
541 | @click.argument('task_id')
542 | @click.argument('related_task_id')
543 | def project_link(task_id: str, related_task_id: str):
544 | """关联任务"""
545 | if project_manager.link_tasks(task_id, related_task_id):
546 | console.print(f"[green]✨ 任务关联成功![/green]")
547 | else:
548 | console.print(f"[red]任务关联失败,请检查任务ID是否正确[/red]")
549 |
550 | @project.command(name='stats')
551 | def project_stats():
552 | """查看任务统计"""
553 | stats = project_manager.get_task_stats()
554 |
555 | console.print("\n📊 任务统计")
556 | console.print(f"总任务数:[blue]{stats['total_tasks']}[/blue]")
557 | console.print(f"完成率:[green]{stats['completion_rate']:.1f}%[/green]")
558 | console.print(f"平均完成时间:[yellow]{stats['average_completion_time']:.1f} 天[/yellow]")
559 |
560 | if stats['status_counts']:
561 | console.print("\n[cyan]== 状态分布 ==[/cyan]")
562 | for status, count in stats['status_counts'].items():
563 | console.print(f"{status}: [blue]{count}[/blue]")
564 |
565 | if stats['priority_counts']:
566 | console.print("\n[cyan]== 优先级分布 ==[/cyan]")
567 | for priority, count in stats['priority_counts'].items():
568 | console.print(f"{priority}: [blue]{count}[/blue]")
569 |
570 | if stats['type_counts']:
571 | console.print("\n[cyan]== 类型分布 ==[/cyan]")
572 | for type_, count in stats['type_counts'].items():
573 | console.print(f"{type_}: [blue]{count}[/blue]")
574 |
575 | if stats['assignee_counts']:
576 | console.print("\n[cyan]== 负责人分布 ==[/cyan]")
577 | for assignee, count in stats['assignee_counts'].items():
578 | console.print(f"{assignee}: [blue]{count}[/blue]")
579 |
580 | if stats['tag_counts']:
581 | console.print("\n[cyan]== 标签统计 ==[/cyan]")
582 | for tag, count in sorted(stats['tag_counts'].items(), key=lambda x: x[1], reverse=True)[:10]:
583 | console.print(f"{tag}: [blue]{count}[/blue]")
584 |
585 | def _print_task_details(task: Dict):
586 | """打印任务详情"""
587 | console.print(f"\n[cyan]== 任务详情 ==[/cyan]")
588 | console.print(f"ID: [blue]{task['id']}[/blue]")
589 | console.print(f"标题: [green]{task['title']}[/green]")
590 | console.print(f"状态: [yellow]{task['status']}[/yellow]")
591 | console.print(f"优先级: [red]{task['priority']}[/red]")
592 | console.print(f"类型: [magenta]{task['type']}[/magenta]")
593 |
594 | if task['description']:
595 | console.print("\n[cyan]描述:[/cyan]")
596 | console.print(Markdown(task['description']))
597 |
598 | if task['assignee']:
599 | console.print(f"负责人: [blue]{task['assignee']}[/blue]")
600 |
601 | if task['deadline']:
602 | console.print(f"截止日期: [yellow]{task['deadline']}[/yellow]")
603 |
604 | if task['tags']:
605 | console.print(f"标签: [magenta]{', '.join(task['tags'])}[/magenta]")
606 |
607 | if task['subtasks']:
608 | console.print("\n[cyan]子任务:[/cyan]")
609 | for subtask in task['subtasks']:
610 | status_color = "green" if subtask['status'] == "已完成" else "yellow"
611 | console.print(
612 | f"- [{status_color}]{subtask['status']}[/{status_color}] "
613 | f"{subtask['title']} [blue]({subtask['id']})[/blue]"
614 | )
615 |
616 | if task['notes']:
617 | console.print("\n[cyan]笔记:[/cyan]")
618 | for note in task['notes']:
619 | console.print(f"\n[blue]{note['created_at']}[/blue]")
620 | console.print(Markdown(note['content']))
621 |
622 | if task['related_tasks']:
623 | console.print("\n[cyan]关联任务:[/cyan]")
624 | for related_id in task['related_tasks']:
625 | related_task = project_manager.get_task(related_id)
626 | if related_task:
627 | console.print(
628 | f"- [blue]{related_id}[/blue]: "
629 | f"[green]{related_task['title']}[/green] "
630 | f"([yellow]{related_task['status']}[/yellow])"
631 | )
632 |
633 | @main.group(name='review')
634 | def review():
635 | """代码审查 🔍"""
636 | pass
637 |
638 | @review.command(name='file')
639 | @click.argument('file_path', type=click.Path(exists=True))
640 | def review_file(file_path):
641 | """审查单个文件。
642 |
643 | Args:
644 | file_path: 要审查的文件路径
645 | """
646 | try:
647 | reviewer = CodeReview()
648 | with console.status("正在审查文件..."):
649 | report = reviewer.review_file(file_path)
650 |
651 | console.print("\n== 文件审查报告 ==")
652 | console.print(f"文件:{report['file']}")
653 | console.print(f"时间:{report['time']}")
654 |
655 | issues = report["issues"]
656 |
657 | # 统计问题
658 | total_issues = len(issues)
659 | issue_types = {}
660 | issue_severities = {}
661 |
662 | for issue in issues:
663 | issue_type = issue["type"]
664 | issue_severity = issue["severity"]
665 |
666 | issue_types[issue_type] = issue_types.get(issue_type, 0) + 1
667 | issue_severities[issue_severity] = issue_severities.get(issue_severity, 0) + 1
668 |
669 | # 打印统计信息
670 | console.print("\n统计信息:")
671 | console.print(f"总问题数:{total_issues}")
672 |
673 | if issue_types:
674 | console.print("\n问题类型分布:")
675 | for type_name, count in issue_types.items():
676 | console.print(f"- {type_name}: {count}")
677 |
678 | if issue_severities:
679 | console.print("\n严重程度分布:")
680 | for severity, count in issue_severities.items():
681 | console.print(f"- {severity}: {count}")
682 |
683 | # 打印具体问题
684 | if issues:
685 | console.print("\n具体问题:\n")
686 | for issue in issues:
687 | severity = issue["severity"].upper()
688 | line = issue["line"]
689 | type_name = issue["type"]
690 | rule = issue["rule"]
691 | message = issue["message"]
692 |
693 | console.print(f"{severity} 第 {line} 行")
694 | console.print(f"类型:{type_name}")
695 | console.print(f"规则:{rule}")
696 | console.print(f"说明:{message}\n")
697 |
698 | except Exception as e:
699 | console.print(f"[red]错误:{str(e)}[/red]")
700 | raise click.Abort()
701 |
702 | @review.command(name='dir')
703 | @click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True))
704 | def review_directory(directory):
705 | """审查目录中的所有Python文件。
706 |
707 | Args:
708 | directory: 要审查的目录路径
709 | """
710 | try:
711 | reviewer = CodeReview()
712 | with console.status("正在审查目录..."):
713 | report = reviewer.review_directory(directory)
714 |
715 | console.print("\n== 目录审查报告 ==")
716 | console.print(f"目录:{report['directory']}")
717 | console.print(f"时间:{report['time']}")
718 | console.print(f"审查文件数:{report['files_reviewed']}")
719 |
720 | total_issues = report["total_issues"]
721 | issue_types = report["issue_types"]
722 | issue_severities = report["issue_severities"]
723 | issues = report["issues"]
724 |
725 | # 打印统计信息
726 | console.print(f"\n总问题数:{total_issues}")
727 |
728 | if issue_types:
729 | console.print("\n问题类型分布:")
730 | for type_name, count in issue_types.items():
731 | console.print(f"- {type_name}: {count}")
732 |
733 | if issue_severities:
734 | console.print("\n严重程度分布:")
735 | for severity, count in issue_severities.items():
736 | console.print(f"- {severity}: {count}")
737 |
738 | # 打印具体问题
739 | if issues:
740 | console.print("\n具体问题:\n")
741 | for issue in issues:
742 | severity = issue["severity"].upper()
743 | line = issue["line"]
744 | type_name = issue["type"]
745 | rule = issue["rule"]
746 | message = issue["message"]
747 |
748 | console.print(f"{severity} 第 {line} 行")
749 | console.print(f"类型:{type_name}")
750 | console.print(f"规则:{rule}")
751 | console.print(f"说明:{message}\n")
752 |
753 | except Exception as e:
754 | console.print(f"[red]错误:{str(e)}[/red]")
755 | raise click.Abort()
756 |
757 | @review.command(name='list')
758 | def review_list():
759 | """列出审查报告"""
760 | reports = CodeReview.list_reports()
761 |
762 | if not reports:
763 | console.print("[yellow]还没有审查报告[/yellow]")
764 | return
765 |
766 | table = Table(title="审查报告列表")
767 | table.add_column("ID", style="cyan")
768 | table.add_column("时间", style="blue")
769 | table.add_column("目标", style="green")
770 | table.add_column("问题数", style="red", justify="right")
771 |
772 | for report in reports:
773 | table.add_row(
774 | report["id"],
775 | report["timestamp"],
776 | report["target"],
777 | str(report["total_issues"])
778 | )
779 |
780 | console.print(table)
781 |
782 | @review.command(name='show')
783 | @click.argument('report_id')
784 | def review_show(report_id: str):
785 | """查看审查报告"""
786 | report = CodeReview.get_report(report_id)
787 |
788 | if not report:
789 | console.print(f"[red]未找到报告:{report_id}[/red]")
790 | return
791 |
792 | _print_review_report(report)
793 |
794 | def _print_review_report(report: Dict):
795 | """打印审查报告"""
796 | if "file" in report:
797 | console.print(f"\n[cyan]== 文件审查报告 ==[/cyan]")
798 | console.print(f"文件:[blue]{report['file']}[/blue]")
799 | else:
800 | console.print(f"\n[cyan]== 目录审查报告 ==[/cyan]")
801 | console.print(f"目录:[blue]{report['directory']}[/blue]")
802 | console.print(f"文件数:[green]{report['summary']['total_files']}[/green]")
803 |
804 | console.print(f"时间:[yellow]{report['timestamp']}[/yellow]")
805 |
806 | # 打印统计信息
807 | console.print("\n[cyan]统计信息:[/cyan]")
808 | console.print(f"总问题数:[red]{report['summary']['total']}[/red]")
809 |
810 | if report["summary"]["by_type"]:
811 | console.print("\n[yellow]问题类型分布:[/yellow]")
812 | for type_, count in report["summary"]["by_type"].items():
813 | console.print(f"- {type_}: [blue]{count}[/blue]")
814 |
815 | if report["summary"]["by_severity"]:
816 | console.print("\n[yellow]严重程度分布:[/yellow]")
817 | for severity, count in report["summary"]["by_severity"].items():
818 | color = {
819 | "error": "red",
820 | "warning": "yellow",
821 | "info": "blue"
822 | }.get(severity, "white")
823 | console.print(f"- {severity}: [{color}]{count}[/{color}]")
824 |
825 | # 打印具体问题
826 | if report["issues"]:
827 | console.print("\n[cyan]具体问题:[/cyan]")
828 | for issue in sorted(report["issues"], key=lambda x: (x["severity"], x["line"])):
829 | severity_color = {
830 | "error": "red",
831 | "warning": "yellow",
832 | "info": "blue"
833 | }.get(issue["severity"], "white")
834 |
835 | console.print(
836 | f"\n[{severity_color}]{issue['severity'].upper()}[/{severity_color}] "
837 | f"第 {issue['line']} 行"
838 | )
839 | console.print(f"类型:[blue]{issue['type']}[/blue]")
840 | console.print(f"规则:[yellow]{issue['rule']}[/yellow]")
841 | console.print(f"说明:{issue['message']}")
842 |
843 | # 如果是目录报告,打印每个文件的问题数
844 | if "files" in report:
845 | console.print("\n[cyan]文件问题分布:[/cyan]")
846 | files_table = Table()
847 | files_table.add_column("文件", style="blue")
848 | files_table.add_column("问题数", style="red", justify="right")
849 |
850 | for file_report in sorted(report["files"], key=lambda x: len(x["issues"]), reverse=True):
851 | if file_report["issues"]:
852 | files_table.add_row(
853 | file_report["file"],
854 | str(len(file_report["issues"]))
855 | )
856 |
857 | console.print(files_table)
858 |
859 | if __name__ == '__main__':
860 | main()
--------------------------------------------------------------------------------
/src/cursormind/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/src/cursormind/config/__init__.py
--------------------------------------------------------------------------------
/src/cursormind/config/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | 配置管理模块 - 保存你的个人设置 ⚙️
3 | """
4 | import os
5 | import json
6 | from datetime import datetime
7 | import pytz
8 | from pathlib import Path
9 | from typing import Dict, Any, Optional
10 |
11 | class Settings:
12 | """配置管理类"""
13 |
14 | def __init__(self):
15 | self._config: Dict[str, Any] = {}
16 | self._config_dir = Path.home() / '.cursormind'
17 | self._config_file = self._config_dir / 'config.json'
18 | self._first_time = not self._config_file.exists()
19 | self.load()
20 |
21 | def load(self) -> None:
22 | """
23 | 加载配置文件
24 | 如果是第一次使用,会创建默认配置并显示欢迎信息
25 | """
26 | if self._first_time:
27 | self._create_default_config()
28 | self._show_welcome()
29 | else:
30 | with open(self._config_file, 'r', encoding='utf-8') as f:
31 | self._config = json.load(f)
32 |
33 | def save(self) -> None:
34 | """保存配置到文件"""
35 | self._config_file.parent.mkdir(parents=True, exist_ok=True)
36 | with open(self._config_file, 'w', encoding='utf-8') as f:
37 | json.dump(self._config, f, ensure_ascii=False, indent=2)
38 |
39 | def get(self, key: str, default: Any = None) -> Any:
40 | """获取配置项"""
41 | return self._config.get(key, default)
42 |
43 | def set(self, key: str, value: Any) -> None:
44 | """设置配置项"""
45 | self._config[key] = value
46 | self.save()
47 |
48 | def _get_timestamp(self) -> str:
49 | """获取当前时间戳"""
50 | tz = pytz.timezone(self.get('timezone', 'America/Los_Angeles'))
51 | now = datetime.now(tz)
52 | return now.strftime("%Y-%m-%d %H:%M:%S %Z")
53 |
54 | def _create_default_config(self) -> None:
55 | """创建默认配置"""
56 | # 获取当前工作目录作为项目根目录
57 | project_root = str(Path.cwd())
58 |
59 | default_config = {
60 | # 基本信息
61 | 'user_name': '', # 用户名
62 | 'current_project': '', # 当前项目
63 | 'learning_goal': '', # 学习目标
64 |
65 | # 个性化设置
66 | 'timezone': 'America/Los_Angeles', # 时区
67 | 'language': 'zh', # 语言
68 | 'theme': 'light', # 主题
69 | 'emoji_enabled': True, # 是否启用表情
70 |
71 | # 项目设置
72 | 'project_root': project_root, # 项目根目录
73 | 'learning_paths_dir': 'learning_paths', # 学习路径目录
74 | 'notes_dir': 'learning_notes', # 笔记目录
75 | 'backups_dir': 'backups', # 备份目录
76 |
77 | # 学习记录
78 | 'start_date': self._get_timestamp(), # 开始使用日期
79 | 'study_days': 0, # 学习天数
80 | 'total_notes': 0, # 笔记总数
81 | 'achievements': [], # 已获得的成就
82 |
83 | # 提醒设置
84 | 'daily_reminder': True, # 每日提醒
85 | 'reminder_time': '20:00', # 提醒时间
86 |
87 | # 版本信息
88 | 'version': 'Beta 0.1.1' # 当前版本
89 | }
90 | self._config = default_config
91 | self.save()
92 |
93 | def _show_welcome(self) -> None:
94 | """显示首次使用的欢迎信息"""
95 | welcome_message = """
96 | 🎉 欢迎使用 CursorMind!
97 |
98 | 这是你第一次使用这个学习助手,我已经为你创建了默认配置文件:
99 | ~/.cursormind/config.json
100 |
101 | 你可以随时修改这些设置,让它更适合你的使用习惯。
102 | 现在,让我们开始你的学习之旅吧!
103 |
104 | 💡 快速开始:
105 | 1. cursormind path # 查看学习路径
106 | 2. cursormind start # 开始今天的学习
107 | 3. cursormind note "内容" # 记录学习笔记
108 | 4. cursormind help # 查看更多帮助
109 |
110 | 记住:每一个小进步都很重要,坚持记录,你会看到自己的成长! 💪
111 | """
112 | print(welcome_message)
113 |
114 | # 创建全局配置实例
115 | settings = Settings()
--------------------------------------------------------------------------------
/src/cursormind/core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/src/cursormind/core/__init__.py
--------------------------------------------------------------------------------
/src/cursormind/core/achievement.py:
--------------------------------------------------------------------------------
1 | """
2 | 成就系统模块 - 跟踪和奖励学习进度
3 | """
4 | import json
5 | import os
6 | from datetime import datetime, timedelta
7 | from typing import Dict, List, Optional
8 | from ..utils.helpers import get_timestamp, ensure_dir
9 |
10 | class AchievementManager:
11 | """成就系统管理器"""
12 |
13 | def __init__(self):
14 | """初始化成就系统"""
15 | self.base_dir = os.path.expanduser('~/.cursormind')
16 | self.achievements_dir = os.path.join(self.base_dir, 'achievements')
17 | self.achievements_file = os.path.join(self.achievements_dir, 'achievements.json')
18 | self.stats_file = os.path.join(self.achievements_dir, 'stats.json')
19 |
20 | # 确保目录存在
21 | ensure_dir(self.achievements_dir)
22 |
23 | # 初始化成就数据
24 | self._ensure_achievements_file()
25 | self._ensure_stats_file()
26 |
27 | # 加载成就定义和用户统计
28 | self.achievements = self._load_achievements()
29 | self.stats = self._load_stats()
30 |
31 | def _ensure_achievements_file(self):
32 | """确保成就定义文件存在,不存在则创建默认成就"""
33 | if not os.path.exists(self.achievements_file):
34 | default_achievements = {
35 | "learning_path": {
36 | "first_path": {
37 | "name": "学习启航",
38 | "description": "开始第一个学习路径",
39 | "icon": "🚀",
40 | "condition": {"type": "path_started", "count": 1},
41 | "reward": 100
42 | },
43 | "path_master": {
44 | "name": "学习大师",
45 | "description": "完成一个完整的学习路径",
46 | "icon": "🎓",
47 | "condition": {"type": "path_completed", "count": 1},
48 | "reward": 500
49 | }
50 | },
51 | "notes": {
52 | "first_note": {
53 | "name": "记录者",
54 | "description": "写下第一篇学习笔记",
55 | "icon": "📝",
56 | "condition": {"type": "note_created", "count": 1},
57 | "reward": 50
58 | },
59 | "note_streak": {
60 | "name": "坚持不懈",
61 | "description": "连续7天记录学习笔记",
62 | "icon": "🔥",
63 | "condition": {"type": "daily_streak", "count": 7},
64 | "reward": 300
65 | },
66 | "note_master": {
67 | "name": "笔记达人",
68 | "description": "累计记录100篇笔记",
69 | "icon": "✍️",
70 | "condition": {"type": "note_created", "count": 100},
71 | "reward": 1000
72 | }
73 | },
74 | "tags": {
75 | "tag_organizer": {
76 | "name": "标签达人",
77 | "description": "使用20个不同的标签",
78 | "icon": "🏷️",
79 | "condition": {"type": "unique_tags", "count": 20},
80 | "reward": 200
81 | }
82 | },
83 | "topics": {
84 | "topic_explorer": {
85 | "name": "主题探索者",
86 | "description": "在5个不同主题下记录笔记",
87 | "icon": "🗺️",
88 | "condition": {"type": "unique_topics", "count": 5},
89 | "reward": 300
90 | }
91 | },
92 | "review": {
93 | "weekly_reviewer": {
94 | "name": "复习达人",
95 | "description": "生成4次周回顾报告",
96 | "icon": "📊",
97 | "condition": {"type": "review_generated", "count": 4},
98 | "reward": 200
99 | }
100 | }
101 | }
102 |
103 | with open(self.achievements_file, 'w', encoding='utf-8') as f:
104 | json.dump(default_achievements, f, ensure_ascii=False, indent=2)
105 |
106 | def _ensure_stats_file(self):
107 | """确保用户统计文件存在"""
108 | if not os.path.exists(self.stats_file):
109 | default_stats = {
110 | "points": 0,
111 | "unlocked_achievements": [],
112 | "stats": {
113 | "paths_started": 0,
114 | "paths_completed": 0,
115 | "notes_created": 0,
116 | "daily_streak": 0,
117 | "unique_tags": set(),
118 | "unique_topics": set(),
119 | "reviews_generated": 0
120 | },
121 | "last_updated": get_timestamp()
122 | }
123 |
124 | with open(self.stats_file, 'w', encoding='utf-8') as f:
125 | json.dump(default_stats, f, ensure_ascii=False, indent=2,
126 | default=lambda x: list(x) if isinstance(x, set) else x)
127 |
128 | def _load_achievements(self) -> Dict:
129 | """加载成就定义"""
130 | with open(self.achievements_file, 'r', encoding='utf-8') as f:
131 | return json.load(f)
132 |
133 | def _load_stats(self) -> Dict:
134 | """加载用户统计数据"""
135 | with open(self.stats_file, 'r', encoding='utf-8') as f:
136 | stats = json.load(f)
137 | # 将列表转换回集合
138 | stats['stats']['unique_tags'] = set(stats['stats']['unique_tags'])
139 | stats['stats']['unique_topics'] = set(stats['stats']['unique_topics'])
140 | return stats
141 |
142 | def _save_stats(self):
143 | """保存用户统计数据"""
144 | with open(self.stats_file, 'w', encoding='utf-8') as f:
145 | json.dump(self.stats, f, ensure_ascii=False, indent=2,
146 | default=lambda x: list(x) if isinstance(x, set) else x)
147 |
148 | def _check_achievements(self) -> List[Dict]:
149 | """检查是否有新的成就达成"""
150 | new_achievements = []
151 | stats = self.stats['stats']
152 |
153 | for category, achievements in self.achievements.items():
154 | for achievement_id, achievement in achievements.items():
155 | # 跳过已解锁的成就
156 | if achievement_id in self.stats['unlocked_achievements']:
157 | continue
158 |
159 | condition = achievement['condition']
160 | achieved = False
161 |
162 | # 检查不同类型的成就条件
163 | if condition['type'] == 'path_started':
164 | achieved = stats['paths_started'] >= condition['count']
165 | elif condition['type'] == 'path_completed':
166 | achieved = stats['paths_completed'] >= condition['count']
167 | elif condition['type'] == 'note_created':
168 | achieved = stats['notes_created'] >= condition['count']
169 | elif condition['type'] == 'daily_streak':
170 | achieved = stats['daily_streak'] >= condition['count']
171 | elif condition['type'] == 'unique_tags':
172 | achieved = len(stats['unique_tags']) >= condition['count']
173 | elif condition['type'] == 'unique_topics':
174 | achieved = len(stats['unique_topics']) >= condition['count']
175 | elif condition['type'] == 'review_generated':
176 | achieved = stats['reviews_generated'] >= condition['count']
177 |
178 | if achieved:
179 | self.stats['unlocked_achievements'].append(achievement_id)
180 | self.stats['points'] += achievement['reward']
181 | new_achievements.append({
182 | 'id': achievement_id,
183 | 'name': achievement['name'],
184 | 'description': achievement['description'],
185 | 'icon': achievement['icon'],
186 | 'reward': achievement['reward']
187 | })
188 |
189 | if new_achievements:
190 | self._save_stats()
191 |
192 | return new_achievements
193 |
194 | def update_stats(self, event_type: str, data: Optional[Dict] = None) -> List[Dict]:
195 | """
196 | 更新用户统计并检查成就
197 |
198 | Args:
199 | event_type: 事件类型,如 'path_started', 'note_created' 等
200 | data: 事件相关的数据
201 |
202 | Returns:
203 | 新解锁的成就列表
204 | """
205 | stats = self.stats['stats']
206 |
207 | if event_type == 'path_started':
208 | stats['paths_started'] += 1
209 | elif event_type == 'path_completed':
210 | stats['paths_completed'] += 1
211 | elif event_type == 'note_created':
212 | stats['notes_created'] += 1
213 | if data:
214 | if 'tags' in data:
215 | stats['unique_tags'].update(data['tags'])
216 | if 'topic' in data:
217 | stats['unique_topics'].add(data['topic'])
218 | elif event_type == 'review_generated':
219 | stats['reviews_generated'] += 1
220 |
221 | self.stats['last_updated'] = get_timestamp()
222 | self._save_stats()
223 |
224 | return self._check_achievements()
225 |
226 | def get_stats(self) -> Dict:
227 | """获取用户统计信息"""
228 | stats = self.stats.copy()
229 | # 转换集合为列表以便序列化
230 | stats['stats']['unique_tags'] = list(stats['stats']['unique_tags'])
231 | stats['stats']['unique_topics'] = list(stats['stats']['unique_topics'])
232 | return stats
233 |
234 | def get_achievements(self, include_locked: bool = False) -> Dict:
235 | """
236 | 获取成就列表
237 |
238 | Args:
239 | include_locked: 是否包含未解锁的成就
240 |
241 | Returns:
242 | 成就列表,包含解锁状态
243 | """
244 | result = {}
245 | for category, achievements in self.achievements.items():
246 | result[category] = {}
247 | for achievement_id, achievement in achievements.items():
248 | if achievement_id in self.stats['unlocked_achievements'] or include_locked:
249 | achievement_data = achievement.copy()
250 | achievement_data['unlocked'] = achievement_id in self.stats['unlocked_achievements']
251 | result[category][achievement_id] = achievement_data
252 | return result
253 |
254 | # 创建全局实例
255 | achievement_manager = AchievementManager()
--------------------------------------------------------------------------------
/src/cursormind/core/code_review.py:
--------------------------------------------------------------------------------
1 | """
2 | 代码审查模块,提供代码风格、性能和安全性检查功能。
3 | """
4 | import os
5 | import ast
6 | import json
7 | from typing import Dict, List, Optional, Tuple, Any
8 | from pathlib import Path
9 | import subprocess
10 | from datetime import datetime
11 |
12 | class CodeReview:
13 | """代码审查类,用于检查代码质量和安全性。
14 |
15 | 提供以下功能:
16 | 1. 代码风格检查:行长度、缩进、文档字符串等
17 | 2. 性能检查:函数复杂度、变量数量等
18 | 3. 安全性检查:SQL注入、命令注入等
19 | """
20 |
21 | def __init__(self):
22 | """初始化代码审查类,设置配置目录和加载配置。"""
23 | self.config_dir = (
24 | Path.home() /
25 | ".cursormind" /
26 | "code_review"
27 | )
28 | self.config_dir.mkdir(parents=True, exist_ok=True)
29 | self.reports_dir = self.config_dir / "reports"
30 | self.reports_dir.mkdir(exist_ok=True)
31 | self.config_file = self.config_dir / "config.json"
32 | self.config = self._load_config()
33 |
34 | def _load_config(self) -> Dict[str, Any]:
35 | """加载配置文件,如果不存在则创建默认配置。
36 |
37 | Returns:
38 | Dict[str, Any]: 配置字典
39 | """
40 | default_config = {
41 | "style": {
42 | "max_line_length": 88,
43 | "indent_size": 4,
44 | "quote_type": "double",
45 | "docstring_style": "google",
46 | "import_order": ["stdlib", "third_party", "local"]
47 | },
48 | "performance": {
49 | "max_complexity": 10,
50 | "max_locals": 15,
51 | "max_returns": 5,
52 | "max_statements": 50
53 | },
54 | "security": {
55 | "sql_risk_functions": [
56 | "execute", "executemany", "raw_query"
57 | ],
58 | "shell_risk_functions": [
59 | "system", "popen", "exec", "eval"
60 | ],
61 | "file_risk_functions": [
62 | "open", "read", "write"
63 | ]
64 | }
65 | }
66 |
67 | if not self.config_file.exists():
68 | self._save_config(default_config)
69 | return default_config
70 |
71 | try:
72 | with open(self.config_file, "r", encoding="utf-8") as f:
73 | config = json.load(f)
74 | # 验证配置文件结构
75 | if not all(
76 | key in config
77 | for key in ["style", "performance", "security"]
78 | ):
79 | raise ValueError("配置文件缺少必要的键")
80 | return config
81 | except Exception as e:
82 | print(f"加载配置文件时出错:{str(e)},使用默认配置")
83 | self._save_config(default_config)
84 | return default_config
85 |
86 | def _save_config(self, config: Dict[str, Any]) -> None:
87 | """保存配置到文件。
88 |
89 | Args:
90 | config: 要保存的配置字典
91 | """
92 | try:
93 | with open(self.config_file, "w", encoding="utf-8") as f:
94 | json.dump(config, f, ensure_ascii=False, indent=2)
95 | except Exception as e:
96 | print(f"保存配置文件时出错:{str(e)}")
97 |
98 | def _safe_open(self, file_path: str, mode: str = "r") -> Optional[Path]:
99 | """安全地打开文件。
100 |
101 | Args:
102 | file_path: 要打开的文件路径
103 | mode: 打开模式
104 |
105 | Returns:
106 | Optional[Path]: 文件路径对象,如果不安全则返回 None
107 | """
108 | try:
109 | path = Path(file_path).resolve()
110 | is_safe = True
111 |
112 | # 基本检查
113 | is_safe = is_safe and path.exists() and path.is_file()
114 |
115 | # 权限检查
116 | if mode == "w":
117 | is_safe = (
118 | is_safe and
119 | os.access(path.parent, os.W_OK) and
120 | str(path).startswith(str(self.config_dir))
121 | )
122 | elif mode == "r":
123 | is_safe = is_safe and os.access(path, os.R_OK)
124 |
125 | # 符号链接检查
126 | is_safe = is_safe and not path.is_symlink()
127 |
128 | # 文件大小检查
129 | is_safe = is_safe and path.stat().st_size <= 10 * 1024 * 1024 # 10MB
130 |
131 | return path if is_safe else None
132 |
133 | except (TypeError, ValueError, OSError):
134 | return None
135 |
136 | def _check_line_length(self, lines: List[str]) -> List[Dict[str, Any]]:
137 | """检查行长度。
138 |
139 | Args:
140 | lines: 代码行列表
141 |
142 | Returns:
143 | 包含行长度问题的列表
144 | """
145 | issues = []
146 | max_length = self.config["style"]["max_line_length"]
147 |
148 | for i, line in enumerate(lines, 1):
149 | if len(line.rstrip()) > max_length:
150 | issues.append({
151 | "type": "style",
152 | "rule": "line_length",
153 | "message": (
154 | f"行长度超过 {max_length} "
155 | "个字符"
156 | ),
157 | "line": i,
158 | "severity": "warning"
159 | })
160 |
161 | return issues
162 |
163 | def _check_indentation(self, tree: ast.AST) -> List[Dict[str, Any]]:
164 | """检查缩进。
165 |
166 | Args:
167 | tree: AST树
168 |
169 | Returns:
170 | 包含缩进问题的列表
171 | """
172 | issues = []
173 | indent_size = self.config["style"]["indent_size"]
174 |
175 | for node in ast.walk(tree):
176 | if isinstance(
177 | node,
178 | (ast.FunctionDef, ast.ClassDef, ast.If, ast.For, ast.While)
179 | ):
180 | if (hasattr(node, "col_offset") and
181 | node.col_offset % indent_size != 0):
182 | issues.append({
183 | "type": "style",
184 | "rule": "indentation",
185 | "message": (
186 | f"缩进应该是 {indent_size} "
187 | "的倍数"
188 | ),
189 | "line": node.lineno,
190 | "severity": "warning"
191 | })
192 |
193 | return issues
194 |
195 | def _check_docstring(self, tree: ast.AST) -> List[Dict[str, Any]]:
196 | """检查文档字符串。
197 |
198 | Args:
199 | tree: AST树
200 |
201 | Returns:
202 | 包含文档字符串问题的列表
203 | """
204 | issues = []
205 |
206 | for node in ast.walk(tree):
207 | if isinstance(node, (ast.FunctionDef, ast.ClassDef, ast.Module)):
208 | if not ast.get_docstring(node):
209 | issues.append({
210 | "type": "style",
211 | "rule": "docstring",
212 | "message": "缺少文档字符串",
213 | "line": node.lineno,
214 | "severity": "info"
215 | })
216 |
217 | return issues
218 |
219 | def _check_quotes(self, lines: List[str]) -> List[Dict[str, Any]]:
220 | """检查引号使用。
221 |
222 | Args:
223 | lines: 代码行列表
224 |
225 | Returns:
226 | 包含引号使用问题的列表
227 | """
228 | issues = []
229 | quote_type = self.config["style"]["quote_type"]
230 |
231 | for i, line in enumerate(lines, 1):
232 | if quote_type == "double" and "'" in line and '"' not in line:
233 | issues.append({
234 | "type": "style",
235 | "rule": "quotes",
236 | "message": "建议使用双引号",
237 | "line": i,
238 | "severity": "info"
239 | })
240 | elif quote_type == "single" and '"' in line and "'" not in line:
241 | issues.append({
242 | "type": "style",
243 | "rule": "quotes",
244 | "message": "建议使用单引号",
245 | "line": i,
246 | "severity": "info"
247 | })
248 |
249 | return issues
250 |
251 | def check_style(self, content: str) -> List[Dict[str, Any]]:
252 | """检查代码风格。
253 |
254 | Args:
255 | content: 要检查的代码内容
256 |
257 | Returns:
258 | 包含风格问题的列表
259 | """
260 | issues = []
261 |
262 | try:
263 | tree = ast.parse(content)
264 | lines = content.split("\n")
265 |
266 | # 检查行长度
267 | issues.extend(self._check_line_length(lines))
268 |
269 | # 检查缩进
270 | issues.extend(self._check_indentation(tree))
271 |
272 | # 检查文档字符串
273 | issues.extend(self._check_docstring(tree))
274 |
275 | # 检查引号使用
276 | issues.extend(self._check_quotes(lines))
277 |
278 | except SyntaxError as e:
279 | issues.append({
280 | "type": "error",
281 | "rule": "parsing",
282 | "message": f"解析代码时出错:{str(e)}",
283 | "line": e.lineno or 1,
284 | "severity": "error"
285 | })
286 | except Exception as e:
287 | issues.append({
288 | "type": "error",
289 | "rule": "parsing",
290 | "message": f"解析代码时出错:{str(e)}",
291 | "line": 1,
292 | "severity": "error"
293 | })
294 |
295 | return issues
296 |
297 | def _check_complexity(self, node: ast.FunctionDef) -> Optional[Dict[str, Any]]:
298 | """检查函数复杂度。
299 |
300 | Args:
301 | node: 函数节点
302 |
303 | Returns:
304 | 如果存在问题则返回问题字典,否则返回 None
305 | """
306 | complexity = 1
307 | for child in ast.walk(node):
308 | if isinstance(child, (ast.If, ast.For, ast.While, ast.Try)):
309 | complexity += 1
310 |
311 | if complexity > self.config["performance"]["max_complexity"]:
312 | return {
313 | "type": "performance",
314 | "rule": "complexity",
315 | "message": (
316 | f"函数复杂度为 {complexity},超过最大值 "
317 | f"{self.config['performance']['max_complexity']}"
318 | ),
319 | "line": node.lineno,
320 | "severity": "warning"
321 | }
322 |
323 | return None
324 |
325 | def _check_locals(self, node: ast.FunctionDef) -> Optional[Dict[str, Any]]:
326 | """检查局部变量数量。
327 |
328 | Args:
329 | node: 函数节点
330 |
331 | Returns:
332 | 如果存在问题则返回问题字典,否则返回 None
333 | """
334 | locals_count = len([
335 | n for n in ast.walk(node)
336 | if isinstance(n, ast.Name) and isinstance(n.ctx, ast.Store)
337 | ])
338 |
339 | if locals_count > self.config["performance"]["max_locals"]:
340 | return {
341 | "type": "performance",
342 | "rule": "locals",
343 | "message": (
344 | f"局部变量数量为 {locals_count},超过最大值 "
345 | f"{self.config['performance']['max_locals']}"
346 | ),
347 | "line": node.lineno,
348 | "severity": "warning"
349 | }
350 |
351 | return None
352 |
353 | def _check_returns(self, node: ast.FunctionDef) -> Optional[Dict[str, Any]]:
354 | """检查return语句数量。
355 |
356 | Args:
357 | node: 函数节点
358 |
359 | Returns:
360 | 如果存在问题则返回问题字典,否则返回 None
361 | """
362 | returns = len([
363 | n for n in ast.walk(node)
364 | if isinstance(n, ast.Return)
365 | ])
366 |
367 | if returns > self.config["performance"]["max_returns"]:
368 | return {
369 | "type": "performance",
370 | "rule": "returns",
371 | "message": (
372 | f"return语句数量为 {returns},超过最大值 "
373 | f"{self.config['performance']['max_returns']}"
374 | ),
375 | "line": node.lineno,
376 | "severity": "warning"
377 | }
378 |
379 | return None
380 |
381 | def _check_statements(self, node: ast.FunctionDef) -> Optional[Dict[str, Any]]:
382 | """检查语句数量。
383 |
384 | Args:
385 | node: 函数节点
386 |
387 | Returns:
388 | 如果存在问题则返回问题字典,否则返回 None
389 | """
390 | statements = len([
391 | n for n in ast.walk(node)
392 | if isinstance(n, ast.stmt)
393 | ])
394 |
395 | if statements > self.config["performance"]["max_statements"]:
396 | return {
397 | "type": "performance",
398 | "rule": "statements",
399 | "message": (
400 | f"语句数量为 {statements},超过最大值 "
401 | f"{self.config['performance']['max_statements']}"
402 | ),
403 | "line": node.lineno,
404 | "severity": "warning"
405 | }
406 |
407 | return None
408 |
409 | def check_performance(self, content: str) -> List[Dict[str, Any]]:
410 | """检查代码性能相关问题。
411 |
412 | Args:
413 | content: 要检查的代码内容
414 |
415 | Returns:
416 | 包含性能问题的列表
417 | """
418 | issues = []
419 |
420 | try:
421 | tree = ast.parse(content)
422 |
423 | for node in ast.walk(tree):
424 | if isinstance(node, ast.FunctionDef):
425 | # 检查函数复杂度
426 | if issue := self._check_complexity(node):
427 | issues.append(issue)
428 |
429 | # 检查局部变量数量
430 | if issue := self._check_locals(node):
431 | issues.append(issue)
432 |
433 | # 检查return语句数量
434 | if issue := self._check_returns(node):
435 | issues.append(issue)
436 |
437 | # 检查语句数量
438 | if issue := self._check_statements(node):
439 | issues.append(issue)
440 |
441 | except SyntaxError as e:
442 | issues.append({
443 | "type": "error",
444 | "rule": "parsing",
445 | "message": f"解析代码时出错:{str(e)}",
446 | "line": e.lineno or 1,
447 | "severity": "error"
448 | })
449 | except Exception as e:
450 | issues.append({
451 | "type": "error",
452 | "rule": "parsing",
453 | "message": f"解析代码时出错:{str(e)}",
454 | "line": 1,
455 | "severity": "error"
456 | })
457 |
458 | return issues
459 |
460 | def _check_sql_injection(self, node: ast.Call) -> Optional[Dict[str, Any]]:
461 | """检查SQL注入风险。
462 |
463 | Args:
464 | node: 函数调用节点
465 |
466 | Returns:
467 | 如果存在问题则返回问题字典,否则返回 None
468 | """
469 | if (isinstance(node.func, ast.Name) and
470 | node.func.id in self.config["security"]["sql_risk_functions"]):
471 | return {
472 | "type": "security",
473 | "rule": "sql_injection",
474 | "message": "可能存在SQL注入风险",
475 | "line": node.lineno,
476 | "severity": "error"
477 | }
478 |
479 | return None
480 |
481 | def _check_command_injection(self, node: ast.Call) -> Optional[Dict[str, Any]]:
482 | """检查命令注入风险。
483 |
484 | Args:
485 | node: 函数调用节点
486 |
487 | Returns:
488 | 如果存在问题则返回问题字典,否则返回 None
489 | """
490 | if (isinstance(node.func, ast.Name) and
491 | node.func.id in self.config["security"]["shell_risk_functions"]):
492 | return {
493 | "type": "security",
494 | "rule": "command_injection",
495 | "message": "可能存在命令注入风险",
496 | "line": node.lineno,
497 | "severity": "error"
498 | }
499 |
500 | return None
501 |
502 | def _check_file_access(self, node: ast.Call) -> Optional[Dict[str, Any]]:
503 | """检查文件访问风险。
504 |
505 | Args:
506 | node: 函数调用节点
507 |
508 | Returns:
509 | 如果存在问题则返回问题字典,否则返回 None
510 | """
511 | if (isinstance(node.func, ast.Name) and
512 | node.func.id in self.config["security"]["file_risk_functions"]):
513 | return {
514 | "type": "security",
515 | "rule": "file_access",
516 | "message": "可能存在不安全的文件访问",
517 | "line": node.lineno,
518 | "severity": "warning"
519 | }
520 |
521 | return None
522 |
523 | def check_security(self, content: str) -> List[Dict[str, Any]]:
524 | """检查代码安全性问题。
525 |
526 | Args:
527 | content: 要检查的代码内容
528 |
529 | Returns:
530 | 包含安全问题的列表
531 | """
532 | issues = []
533 |
534 | try:
535 | tree = ast.parse(content)
536 |
537 | for node in ast.walk(tree):
538 | if isinstance(node, ast.Call):
539 | # 检查SQL注入风险
540 | if issue := self._check_sql_injection(node):
541 | issues.append(issue)
542 |
543 | # 检查命令注入风险
544 | if issue := self._check_command_injection(node):
545 | issues.append(issue)
546 |
547 | # 检查文件访问风险
548 | if issue := self._check_file_access(node):
549 | issues.append(issue)
550 |
551 | except SyntaxError as e:
552 | issues.append({
553 | "type": "error",
554 | "rule": "parsing",
555 | "message": f"解析代码时出错:{str(e)}",
556 | "line": e.lineno or 1,
557 | "severity": "error"
558 | })
559 | except Exception as e:
560 | issues.append({
561 | "type": "error",
562 | "rule": "parsing",
563 | "message": f"解析代码时出错:{str(e)}",
564 | "line": 1,
565 | "severity": "error"
566 | })
567 |
568 | return issues
569 |
570 | def review_file(self, file_path: str) -> Dict[str, Any]:
571 | """审查单个文件。
572 |
573 | Args:
574 | file_path: 要审查的文件路径
575 |
576 | Returns:
577 | 包含审查结果的字典
578 | """
579 | result = {
580 | "file": file_path,
581 | "time": datetime.now().isoformat(),
582 | "issues": []
583 | }
584 |
585 | # 检查文件访问权限
586 | path = self._safe_open(file_path)
587 | if not path:
588 | result["issues"].append({
589 | "type": "error",
590 | "rule": "file_access",
591 | "message": "无法访问文件",
592 | "line": 1,
593 | "severity": "error"
594 | })
595 | return result
596 |
597 | try:
598 | with open(path, "r", encoding="utf-8") as f:
599 | content = f.read()
600 |
601 | # 检查文件是否为空
602 | if not content.strip():
603 | result["issues"].append({
604 | "type": "error",
605 | "rule": "empty_file",
606 | "message": "文件为空",
607 | "line": 1,
608 | "severity": "error"
609 | })
610 | return result
611 |
612 | # 检查文件编码
613 | try:
614 | content.encode("utf-8").decode("utf-8")
615 | except UnicodeError:
616 | result["issues"].append({
617 | "type": "error",
618 | "rule": "encoding",
619 | "message": "文件编码不是UTF-8",
620 | "line": 1,
621 | "severity": "error"
622 | })
623 | return result
624 |
625 | # 检查语法错误
626 | try:
627 | ast.parse(content)
628 | except SyntaxError as e:
629 | result["issues"].append({
630 | "type": "error",
631 | "rule": "syntax",
632 | "message": f"语法错误:{str(e)}",
633 | "line": e.lineno or 1,
634 | "severity": "error"
635 | })
636 | return result
637 |
638 | # 进行代码审查
639 | result["issues"].extend(self.check_style(content))
640 | result["issues"].extend(self.check_performance(content))
641 | result["issues"].extend(self.check_security(content))
642 |
643 | except Exception as e:
644 | result["issues"].append({
645 | "type": "error",
646 | "rule": "file_read",
647 | "message": f"读取文件时出错:{str(e)}",
648 | "line": 1,
649 | "severity": "error"
650 | })
651 |
652 | return result
653 |
654 | def review_directory(self, directory: str) -> Dict[str, Any]:
655 | """审查目录中的所有Python文件。
656 |
657 | Args:
658 | directory: 要审查的目录路径
659 |
660 | Returns:
661 | 包含审查结果的字典
662 | """
663 | try:
664 | path = Path(directory).resolve()
665 | if not path.exists() or not path.is_dir():
666 | return {
667 | "directory": directory,
668 | "time": datetime.now().isoformat(),
669 | "issues": [{
670 | "type": "error",
671 | "rule": "directory_access",
672 | "message": "无法访问目录",
673 | "line": 1,
674 | "severity": "error"
675 | }]
676 | }
677 |
678 | issues = []
679 | files_reviewed = 0
680 |
681 | for file_path in path.rglob("*.py"):
682 | result = self.review_file(str(file_path))
683 | issues.extend(result["issues"])
684 | files_reviewed += 1
685 |
686 | # 统计问题分布
687 | issue_types = {}
688 | issue_severities = {}
689 |
690 | for issue in issues:
691 | issue_type = issue["type"]
692 | issue_severity = issue["severity"]
693 |
694 | issue_types[issue_type] = issue_types.get(
695 | issue_type, 0
696 | ) + 1
697 | issue_severities[issue_severity] = issue_severities.get(
698 | issue_severity, 0
699 | ) + 1
700 |
701 | return {
702 | "directory": directory,
703 | "time": datetime.now().isoformat(),
704 | "files_reviewed": files_reviewed,
705 | "total_issues": len(issues),
706 | "issue_types": issue_types,
707 | "issue_severities": issue_severities,
708 | "issues": issues
709 | }
710 |
711 | except Exception as e:
712 | return {
713 | "directory": directory,
714 | "time": datetime.now().isoformat(),
715 | "issues": [{
716 | "type": "error",
717 | "rule": "directory_review",
718 | "message": f"审查目录时出错:{str(e)}",
719 | "line": 1,
720 | "severity": "error"
721 | }]
722 | }
723 |
724 | def save_report(self, report: Dict) -> str:
725 | """保存审查报告。
726 |
727 | Args:
728 | report: 要保存的报告
729 |
730 | Returns:
731 | str: 报告ID
732 | """
733 | report_id = datetime.now().strftime("%Y%m%d%H%M%S")
734 | report_file = self.reports_dir / f"report_{report_id}.json"
735 |
736 | path = self._safe_open(str(report_file), "w")
737 | if not path:
738 | return None
739 |
740 | with path.open("w", encoding="utf-8") as f:
741 | json.dump(report, f, ensure_ascii=False, indent=2)
742 |
743 | return report_id
744 |
745 | def get_report(self, report_id: str) -> Optional[Dict]:
746 | """获取审查报告。
747 |
748 | Args:
749 | report_id: 报告ID
750 |
751 | Returns:
752 | Optional[Dict]: 报告内容,如果不存在则返回 None
753 | """
754 | report_file = self.reports_dir / f"report_{report_id}.json"
755 | path = self._safe_open(str(report_file))
756 | if not path:
757 | return None
758 |
759 | with path.open("r", encoding="utf-8") as f:
760 | return json.load(f)
761 |
762 | def list_reports(self) -> List[Dict]:
763 | """列出所有审查报告。
764 |
765 | Returns:
766 | List[Dict]: 报告列表
767 | """
768 | reports = []
769 | for report_file in self.reports_dir.glob("report_*.json"):
770 | path = self._safe_open(str(report_file))
771 | if not path:
772 | continue
773 |
774 | with path.open("r", encoding="utf-8") as f:
775 | report = json.load(f)
776 | reports.append({
777 | "id": report_file.stem.replace("report_", ""),
778 | "timestamp": report["timestamp"],
779 | "target": report.get("file") or report.get("directory"),
780 | "total_issues": (
781 | report["summary"]["total_issues"]
782 | if "total_issues" in report["summary"]
783 | else len(report["issues"])
784 | )
785 | })
786 |
787 | return sorted(reports, key=lambda x: x["timestamp"], reverse=True)
788 |
789 | def _calculate_stats(self, issues: List[Dict[str, Any]]) -> Dict[str, Any]:
790 | """计算问题统计信息。
791 |
792 | Args:
793 | issues: 问题列表
794 |
795 | Returns:
796 | 包含统计信息的字典
797 | """
798 | stats = {
799 | "total": len(issues),
800 | "by_type": {},
801 | "by_severity": {},
802 | "by_rule": {}
803 | }
804 |
805 | for issue in issues:
806 | # 按类型统计
807 | issue_type = issue.get("type", "unknown")
808 | stats["by_type"][issue_type] = stats["by_type"].get(issue_type, 0) + 1
809 |
810 | # 按严重程度统计
811 | severity = issue.get("severity", "unknown")
812 | stats["by_severity"][severity] = stats["by_severity"].get(severity, 0) + 1
813 |
814 | # 按规则统计
815 | rule = issue.get("rule", "unknown")
816 | stats["by_rule"][rule] = stats["by_rule"].get(rule, 0) + 1
817 |
818 | return stats
819 |
820 | code_review = CodeReview()
--------------------------------------------------------------------------------
/src/cursormind/core/command_handler.py:
--------------------------------------------------------------------------------
1 | """
2 | 命令处理核心模块
3 | """
4 | from typing import Dict, Callable, Any, Optional
5 | import logging
6 |
7 | class CommandHandler:
8 | """命令处理器类"""
9 |
10 | def __init__(self):
11 | self._commands: Dict[str, Callable] = {}
12 | self._logger = logging.getLogger(__name__)
13 |
14 | def register(self, name: str) -> Callable:
15 | """
16 | 命令注册装饰器
17 |
18 | Args:
19 | name: 命令名称
20 |
21 | Returns:
22 | 装饰器函数
23 | """
24 | def decorator(func: Callable) -> Callable:
25 | self._commands[name] = func
26 | self._logger.debug(f"注册命令: {name}")
27 | return func
28 | return decorator
29 |
30 | def execute(self, name: str, *args: Any, **kwargs: Any) -> Optional[Any]:
31 | """
32 | 执行命令
33 |
34 | Args:
35 | name: 命令名称
36 | args: 位置参数
37 | kwargs: 关键字参数
38 |
39 | Returns:
40 | 命令执行结果
41 |
42 | Raises:
43 | KeyError: 命令不存在时抛出
44 | """
45 | if name not in self._commands:
46 | raise KeyError(f"未知命令: {name}")
47 |
48 | try:
49 | self._logger.info(f"执行命令: {name}")
50 | return self._commands[name](*args, **kwargs)
51 | except Exception as e:
52 | self._logger.error(f"命令执行失败: {name}, 错误: {str(e)}")
53 | raise
54 |
55 | # 创建全局命令处理器实例
56 | handler = CommandHandler()
--------------------------------------------------------------------------------
/src/cursormind/core/cursor_framework.py:
--------------------------------------------------------------------------------
1 | """
2 | Cursor 规范框架核心模块
3 | """
4 | import os
5 | import json
6 | from typing import Dict, List, Optional
7 | from datetime import datetime
8 | from pathlib import Path
9 |
10 | class CursorFramework:
11 | def __init__(self):
12 | self.config_dir = Path.home() / '.cursormind' / 'cursor_framework'
13 | self.config_dir.mkdir(parents=True, exist_ok=True)
14 | self.templates_dir = self.config_dir / 'templates'
15 | self.templates_dir.mkdir(exist_ok=True)
16 | self.rules_file = self.config_dir / 'rules.json'
17 | self._load_rules()
18 |
19 | def _load_rules(self):
20 | """加载规范规则"""
21 | if not self.rules_file.exists():
22 | self.rules = {
23 | "project_structure": {
24 | "required_dirs": ["src", "tests", "docs", "scripts"],
25 | "required_files": ["README.md", "LICENSE", "setup.py", "requirements.txt"]
26 | },
27 | "code_style": {
28 | "python": {
29 | "line_length": 88,
30 | "indent": 4,
31 | "quotes": "double",
32 | "docstring": "google"
33 | }
34 | },
35 | "git": {
36 | "commit_types": [
37 | "feat", "fix", "docs", "style", "refactor",
38 | "perf", "test", "build", "ci", "chore"
39 | ],
40 | "commit_format": "(): ",
41 | "branch_format": {
42 | "feature": "feature/",
43 | "bugfix": "bugfix/",
44 | "hotfix": "hotfix/",
45 | "release": "release/"
46 | }
47 | },
48 | "documentation": {
49 | "required_sections": [
50 | "项目简介",
51 | "快速开始",
52 | "安装指南",
53 | "使用说明",
54 | "API文档",
55 | "贡献指南"
56 | ]
57 | }
58 | }
59 | self._save_rules()
60 | else:
61 | with open(self.rules_file, 'r', encoding='utf-8') as f:
62 | self.rules = json.load(f)
63 |
64 | def _save_rules(self):
65 | """保存规范规则"""
66 | with open(self.rules_file, 'w', encoding='utf-8') as f:
67 | json.dump(self.rules, f, ensure_ascii=False, indent=2)
68 |
69 | def check_project_structure(self, project_path: str) -> Dict[str, List[str]]:
70 | """检查项目结构是否符合规范"""
71 | issues = {
72 | "missing_dirs": [],
73 | "missing_files": []
74 | }
75 |
76 | for required_dir in self.rules["project_structure"]["required_dirs"]:
77 | if not os.path.exists(os.path.join(project_path, required_dir)):
78 | issues["missing_dirs"].append(required_dir)
79 |
80 | for required_file in self.rules["project_structure"]["required_files"]:
81 | if not os.path.exists(os.path.join(project_path, required_file)):
82 | issues["missing_files"].append(required_file)
83 |
84 | return issues
85 |
86 | def validate_commit_message(self, message: str) -> Dict[str, bool]:
87 | """验证提交信息是否符合规范"""
88 | result = {
89 | "valid": False,
90 | "type_valid": False,
91 | "format_valid": False
92 | }
93 |
94 | # 检查是否为空
95 | if not message:
96 | return result
97 |
98 | # 检查格式
99 | parts = message.split(":")
100 | if len(parts) != 2:
101 | return result
102 |
103 | commit_type = parts[0].strip().lower()
104 | if "(" in commit_type:
105 | commit_type = commit_type.split("(")[0]
106 |
107 | # 检查类型
108 | result["type_valid"] = commit_type in self.rules["git"]["commit_types"]
109 |
110 | # 检查格式是否符合规范
111 | result["format_valid"] = (
112 | len(parts[1].strip()) > 0 and # 描述不能为空
113 | len(parts[1].strip()) <= 72 # 描述不能太长
114 | )
115 |
116 | result["valid"] = result["type_valid"] and result["format_valid"]
117 | return result
118 |
119 | def validate_branch_name(self, branch_name: str) -> Dict[str, bool]:
120 | """验证分支名称是否符合规范"""
121 | result = {
122 | "valid": False,
123 | "type_valid": False,
124 | "format_valid": False
125 | }
126 |
127 | if not branch_name or "/" not in branch_name:
128 | return result
129 |
130 | branch_type = branch_name.split("/")[0]
131 |
132 | # 检查分支类型
133 | result["type_valid"] = branch_type in self.rules["git"]["branch_format"]
134 |
135 | # 检查分支格式
136 | if result["type_valid"]:
137 | expected_format = self.rules["git"]["branch_format"][branch_type]
138 | format_parts = expected_format.split("/")
139 | branch_parts = branch_name.split("/")
140 |
141 | result["format_valid"] = (
142 | len(branch_parts) == len(format_parts) and
143 | branch_parts[0] == format_parts[0] and
144 | len(branch_parts[1]) > 0
145 | )
146 |
147 | result["valid"] = result["type_valid"] and result["format_valid"]
148 | return result
149 |
150 | def generate_project_template(self, project_path: str, template_name: str = "default") -> bool:
151 | """生成项目模板"""
152 | try:
153 | # 创建必要的目录
154 | for dir_name in self.rules["project_structure"]["required_dirs"]:
155 | os.makedirs(os.path.join(project_path, dir_name), exist_ok=True)
156 |
157 | # 创建必要的文件
158 | for file_name in self.rules["project_structure"]["required_files"]:
159 | file_path = os.path.join(project_path, file_name)
160 | if not os.path.exists(file_path):
161 | with open(file_path, 'w', encoding='utf-8') as f:
162 | if file_name == "README.md":
163 | f.write(self._generate_readme_template())
164 | elif file_name == "setup.py":
165 | f.write(self._generate_setup_template())
166 | elif file_name == "requirements.txt":
167 | f.write("# Project dependencies\n")
168 |
169 | return True
170 | except Exception as e:
171 | print(f"Error generating project template: {e}")
172 | return False
173 |
174 | def _generate_readme_template(self) -> str:
175 | """生成 README 模板"""
176 | sections = self.rules["documentation"]["required_sections"]
177 | template = "# 项目名称\n\n"
178 |
179 | for section in sections:
180 | template += f"## {section}\n\n"
181 |
182 | return template
183 |
184 | def _generate_setup_template(self) -> str:
185 | """生成 setup.py 模板"""
186 | return '''from setuptools import setup, find_packages
187 |
188 | setup(
189 | name="your-project-name",
190 | version="0.1.0",
191 | packages=find_packages(),
192 | install_requires=[
193 | # 在这里列出你的项目依赖
194 | ],
195 | author="Your Name",
196 | author_email="your.email@example.com",
197 | description="A short description of your project",
198 | long_description=open("README.md").read(),
199 | long_description_content_type="text/markdown",
200 | url="https://github.com/username/project",
201 | classifiers=[
202 | "Programming Language :: Python :: 3",
203 | "License :: OSI Approved :: MIT License",
204 | "Operating System :: OS Independent",
205 | ],
206 | python_requires=">=3.6",
207 | )
208 | '''
209 |
210 | cursor_framework = CursorFramework()
--------------------------------------------------------------------------------
/src/cursormind/core/learning_path.py:
--------------------------------------------------------------------------------
1 | """
2 | 学习路径管理模块 - 指导你的学习之旅 🗺️
3 | """
4 | import os
5 | import json
6 | from pathlib import Path
7 | from typing import Dict, List, Any, Optional
8 | from ..config.settings import settings
9 | from ..utils.helpers import get_timestamp, ensure_dir
10 | from .achievement import achievement_manager
11 |
12 | class LearningPath:
13 | """学习路径管理类"""
14 |
15 | def __init__(self):
16 | # 获取项目根目录和学习路径目录
17 | self._project_root = Path(settings.get('project_root'))
18 | self._paths_dir = self._project_root / settings.get('learning_paths_dir')
19 | self._paths_file = self._paths_dir / 'paths.json'
20 | self._current_path_file = self._paths_dir / 'current_path.json'
21 | self._current_path: Optional[Dict[str, Any]] = None
22 | self._ensure_paths_file()
23 | self._ensure_current_path_file()
24 |
25 | def _ensure_paths_file(self) -> None:
26 | """确保学习路径文件存在"""
27 | # 确保目录存在
28 | ensure_dir(self._paths_dir)
29 |
30 | if not self._paths_file.exists():
31 | default_paths = {
32 | "python-beginner": {
33 | "id": "python-beginner",
34 | "name": "Python入门之路",
35 | "description": "从零开始学习Python编程",
36 | "difficulty": "初级",
37 | "estimated_time": "4周",
38 | "stages": [
39 | {
40 | "name": "基础语法",
41 | "steps": [
42 | "变量和数据类型",
43 | "控制流程",
44 | "函数和模块"
45 | ],
46 | "resources": [
47 | {
48 | "name": "Python官方文档",
49 | "url": "https://docs.python.org/zh-cn/3/"
50 | },
51 | {
52 | "name": "Python入门教程",
53 | "url": "https://www.runoob.com/python3/python3-tutorial.html"
54 | }
55 | ],
56 | "projects": [
57 | {
58 | "name": "数字游戏",
59 | "description": "创建一个简单的猜数字游戏"
60 | },
61 | {
62 | "name": "计算器",
63 | "description": "实现一个基础的命令行计算器"
64 | }
65 | ]
66 | }
67 | ]
68 | },
69 | "web-beginner": {
70 | "id": "web-beginner",
71 | "name": "网页设计入门",
72 | "description": "学习HTML、CSS和JavaScript基础",
73 | "difficulty": "初级",
74 | "estimated_time": "6周",
75 | "stages": [
76 | {
77 | "name": "HTML基础",
78 | "steps": [
79 | "HTML文档结构",
80 | "常用标签",
81 | "表单和表格"
82 | ],
83 | "resources": [
84 | {
85 | "name": "MDN Web文档",
86 | "url": "https://developer.mozilla.org/zh-CN/"
87 | }
88 | ],
89 | "projects": [
90 | {
91 | "name": "个人主页",
92 | "description": "创建一个简单的个人介绍页面"
93 | }
94 | ]
95 | }
96 | ]
97 | },
98 | "project-beginner": {
99 | "id": "project-beginner",
100 | "name": "项目管理入门",
101 | "description": "学习基本的项目管理知识和工具",
102 | "difficulty": "初级",
103 | "estimated_time": "3周",
104 | "stages": [
105 | {
106 | "name": "版本控制",
107 | "steps": [
108 | "Git基础概念",
109 | "常用Git命令",
110 | "分支管理"
111 | ],
112 | "resources": [
113 | {
114 | "name": "Git教程",
115 | "url": "https://www.liaoxuefeng.com/wiki/896043488029600"
116 | }
117 | ],
118 | "projects": [
119 | {
120 | "name": "项目实践",
121 | "description": "创建一个Git仓库并进行基本操作"
122 | }
123 | ]
124 | }
125 | ]
126 | }
127 | }
128 |
129 | with open(self._paths_file, 'w', encoding='utf-8') as f:
130 | json.dump(default_paths, f, ensure_ascii=False, indent=2)
131 |
132 | def _ensure_current_path_file(self):
133 | """确保当前路径文件存在"""
134 | if not self._current_path_file.exists():
135 | current_path = {
136 | "path_id": None,
137 | "current_stage": 0,
138 | "current_step": 0,
139 | "started_at": None,
140 | "last_updated": None
141 | }
142 |
143 | with open(self._current_path_file, 'w', encoding='utf-8') as f:
144 | json.dump(current_path, f, ensure_ascii=False, indent=2)
145 |
146 | def get_all_paths(self) -> List[Dict[str, Any]]:
147 | """获取所有学习路径"""
148 | if not self._paths_file.exists():
149 | self._ensure_paths_file()
150 | with open(self._paths_file, 'r', encoding='utf-8') as f:
151 | data = json.load(f)
152 | return [
153 | {
154 | 'id': path['id'],
155 | 'name': path['name'],
156 | 'description': path['description'],
157 | 'difficulty': path['difficulty'],
158 | 'estimated_time': path['estimated_time']
159 | }
160 | for path in data['paths']
161 | ]
162 |
163 | def get_path_info(self, path_id: str) -> Optional[Dict[str, Any]]:
164 | """获取指定学习路径的信息"""
165 | with open(self._paths_file, 'r', encoding='utf-8') as f:
166 | data = json.load(f)
167 | for path in data['paths']:
168 | if path['id'] == path_id:
169 | return path
170 | return None
171 |
172 | def set_current_path(self, path_id: str) -> bool:
173 | """设置当前学习路径"""
174 | path = self.get_path_info(path_id)
175 | if not path:
176 | return False
177 |
178 | current_path = {
179 | "path_id": path_id,
180 | "current_stage": 0,
181 | "current_step": 0,
182 | "started_at": get_timestamp(),
183 | "last_updated": get_timestamp()
184 | }
185 |
186 | with open(self._current_path_file, 'w', encoding='utf-8') as f:
187 | json.dump(current_path, f, ensure_ascii=False, indent=2)
188 |
189 | # 触发成就检查
190 | achievement_manager.update_stats('path_started')
191 |
192 | return True
193 |
194 | def get_current_progress(self) -> Optional[Dict[str, Any]]:
195 | """获取当前学习进度"""
196 | if not self._current_path_file.exists():
197 | return None
198 |
199 | with open(self._current_path_file, 'r', encoding='utf-8') as f:
200 | current = json.load(f)
201 |
202 | if not current['path_id']:
203 | return None
204 |
205 | path = self.get_path_info(current['path_id'])
206 | if not path:
207 | return None
208 |
209 | total_steps = sum(len(stage['steps']) for stage in path['stages'])
210 | completed_steps = 0
211 | for i in range(current['current_stage']):
212 | completed_steps += len(path['stages'][i]['steps'])
213 | completed_steps += current['current_step']
214 |
215 | return {
216 | 'path_id': current['path_id'],
217 | 'path_name': path['name'],
218 | 'current_stage': current['current_stage'],
219 | 'current_stage_name': path['stages'][current['current_stage']]['name'],
220 | 'current_step': current['current_step'],
221 | 'current_step_name': path['stages'][current['current_stage']]['steps'][current['current_step']],
222 | 'progress': f"{completed_steps}/{total_steps}",
223 | 'percentage': round(completed_steps / total_steps * 100, 1)
224 | }
225 |
226 | def advance_progress(self) -> bool:
227 | """推进当前进度"""
228 | if not self._current_path_file.exists():
229 | return False
230 |
231 | with open(self._current_path_file, 'r', encoding='utf-8') as f:
232 | current = json.load(f)
233 |
234 | if not current['path_id']:
235 | return False
236 |
237 | path = self.get_path_info(current['path_id'])
238 | if not path:
239 | return False
240 |
241 | # 获取当前阶段
242 | stage = path['stages'][current['current_stage']]
243 |
244 | # 检查是否需要进入下一步或下一阶段
245 | if current['current_step'] + 1 < len(stage['steps']):
246 | # 进入下一步
247 | current['current_step'] += 1
248 | elif current['current_stage'] + 1 < len(path['stages']):
249 | # 进入下一阶段
250 | current['current_stage'] += 1
251 | current['current_step'] = 0
252 | else:
253 | # 学习路径已完成
254 | current['path_id'] = None
255 | # 触发成就检查
256 | achievement_manager.update_stats('path_completed')
257 |
258 | current['last_updated'] = get_timestamp()
259 |
260 | with open(self._current_path_file, 'w', encoding='utf-8') as f:
261 | json.dump(current, f, ensure_ascii=False, indent=2)
262 |
263 | return True
264 |
265 | def get_current_resources(self) -> List[Dict[str, str]]:
266 | """获取当前阶段的学习资源"""
267 | progress = self.get_current_progress()
268 | if not progress:
269 | return []
270 |
271 | path = self.get_path_info(progress['path_id'])
272 | if not path or not path['stages']:
273 | return []
274 |
275 | current_stage = int(progress['current_stage'])
276 | if current_stage >= len(path['stages']):
277 | return []
278 |
279 | stage = path['stages'][current_stage]
280 | return stage.get('resources', [])
281 |
282 | def get_current_projects(self) -> List[Dict[str, str]]:
283 | """获取当前阶段的练习项目"""
284 | progress = self.get_current_progress()
285 | if not progress:
286 | return []
287 |
288 | path = self.get_path_info(progress['path_id'])
289 | if not path or not path['stages']:
290 | return []
291 |
292 | current_stage = int(progress['current_stage'])
293 | if current_stage >= len(path['stages']):
294 | return []
295 |
296 | stage = path['stages'][current_stage]
297 | return stage.get('projects', [])
298 |
299 | # 创建全局实例
300 | learning_path_manager = LearningPath()
--------------------------------------------------------------------------------
/src/cursormind/core/note_manager.py:
--------------------------------------------------------------------------------
1 | """
2 | 笔记管理模块 - 记录你的学习心得 📝
3 | """
4 | import os
5 | import json
6 | from datetime import datetime, timedelta
7 | from pathlib import Path
8 | from typing import Dict, List, Optional, Set
9 | import re
10 | from ..config.settings import settings
11 | from ..utils.helpers import ensure_dir, get_timestamp
12 | from .achievement import achievement_manager
13 |
14 | class NoteManager:
15 | """笔记管理类"""
16 |
17 | def __init__(self):
18 | self._project_root = Path(settings.get('project_root'))
19 | self._notes_dir = self._project_root / settings.get('notes_dir')
20 | self._daily_dir = self._notes_dir / 'daily'
21 | self._topic_dir = self._notes_dir / 'topics'
22 | self._review_dir = self._notes_dir / 'reviews'
23 | self._stats_file = self._notes_dir / 'stats.json'
24 | self._ensure_structure()
25 | self._load_stats()
26 | self._update_daily_streak()
27 |
28 | def _ensure_structure(self) -> None:
29 | """确保笔记目录结构存在"""
30 | for dir_path in [self._daily_dir, self._topic_dir, self._review_dir]:
31 | ensure_dir(dir_path)
32 |
33 | if not self._stats_file.exists():
34 | self._stats = {
35 | 'total_notes': 0,
36 | 'total_words': 0,
37 | 'topics': {},
38 | 'tags': {},
39 | 'daily_streak': 0,
40 | 'last_note_date': '',
41 | 'last_updated': get_timestamp()
42 | }
43 | self._save_stats()
44 |
45 | def _load_stats(self) -> None:
46 | """加载笔记统计数据"""
47 | if self._stats_file.exists():
48 | with open(self._stats_file, 'r', encoding='utf-8') as f:
49 | self._stats = json.load(f)
50 |
51 | def _save_stats(self) -> None:
52 | """保存笔记统计数据"""
53 | with open(self._stats_file, 'w', encoding='utf-8') as f:
54 | json.dump(self._stats, f, ensure_ascii=False, indent=2)
55 |
56 | def _update_daily_streak(self):
57 | """更新连续记录天数"""
58 | with open(self._stats_file, 'r', encoding='utf-8') as f:
59 | stats = json.load(f)
60 |
61 | if not stats['last_note_date']:
62 | return
63 |
64 | last_note = datetime.fromisoformat(stats['last_note_date'])
65 | today = datetime.now()
66 |
67 | # 如果最后一条笔记是昨天的
68 | if (today - last_note).days > 1:
69 | stats['daily_streak'] = 0
70 |
71 | with open(self._stats_file, 'w', encoding='utf-8') as f:
72 | json.dump(stats, f, ensure_ascii=False, indent=2)
73 |
74 | def _extract_tags(self, content: str) -> Set[str]:
75 | """从内容中提取标签"""
76 | return set(tag.strip() for tag in re.findall(r'#(\w+)', content))
77 |
78 | def _update_stats(self, content: str, topic: str, tags: Set[str]):
79 | """更新统计数据"""
80 | with open(self._stats_file, 'r', encoding='utf-8') as f:
81 | stats = json.load(f)
82 |
83 | # 更新基本统计
84 | stats['total_notes'] += 1
85 | stats['total_words'] += len(content.split())
86 |
87 | # 更新主题统计
88 | if topic not in stats['topics']:
89 | stats['topics'][topic] = 0
90 | stats['topics'][topic] += 1
91 |
92 | # 更新标签统计
93 | for tag in tags:
94 | if tag not in stats['tags']:
95 | stats['tags'][tag] = 0
96 | stats['tags'][tag] += 1
97 |
98 | # 更新连续记录
99 | today = datetime.now().date()
100 | if stats['last_note_date']:
101 | last_note = datetime.fromisoformat(stats['last_note_date']).date()
102 | if today == last_note:
103 | pass # 同一天内不更新连续记录
104 | elif (today - last_note).days == 1:
105 | stats['daily_streak'] += 1
106 | else:
107 | stats['daily_streak'] = 1
108 | else:
109 | stats['daily_streak'] = 1
110 |
111 | stats['last_note_date'] = datetime.now().isoformat()
112 | stats['last_updated'] = get_timestamp()
113 |
114 | with open(self._stats_file, 'w', encoding='utf-8') as f:
115 | json.dump(stats, f, ensure_ascii=False, indent=2)
116 |
117 | # 触发成就检查
118 | achievement_manager.update_stats('note_created', {
119 | 'topic': topic,
120 | 'tags': list(tags)
121 | })
122 |
123 | def add_note(self, content: str, topic: str = 'general') -> Dict:
124 | """
125 | 添加新笔记
126 | :param content: 笔记内容
127 | :param topic: 主题
128 | :return: 笔记信息
129 | """
130 | timestamp = get_timestamp()
131 | date = datetime.now().strftime('%Y-%m-%d')
132 | tags = self._extract_tags(content)
133 |
134 | # 创建笔记数据
135 | note = {
136 | 'id': f"{date}-{self._stats['total_notes'] + 1:04d}",
137 | 'content': content,
138 | 'topic': topic,
139 | 'tags': list(tags),
140 | 'created_at': timestamp,
141 | 'updated_at': timestamp
142 | }
143 |
144 | # 保存到日常笔记
145 | daily_file = self._daily_dir / f"{date}.json"
146 | daily_notes = []
147 | if daily_file.exists():
148 | with open(daily_file, 'r', encoding='utf-8') as f:
149 | daily_notes = json.load(f)
150 | daily_notes.append(note)
151 | with open(daily_file, 'w', encoding='utf-8') as f:
152 | json.dump(daily_notes, f, ensure_ascii=False, indent=2)
153 |
154 | # 保存到主题目录
155 | topic_dir = ensure_dir(self._topic_dir / topic)
156 | topic_file = topic_dir / f"{note['id']}.json"
157 | with open(topic_file, 'w', encoding='utf-8') as f:
158 | json.dump(note, f, ensure_ascii=False, indent=2)
159 |
160 | # 更新统计数据
161 | self._update_stats(content, topic, tags)
162 |
163 | return note
164 |
165 | def get_daily_notes(self, date: Optional[str] = None) -> List[Dict]:
166 | """
167 | 获取指定日期的笔记
168 | :param date: 日期字符串(YYYY-MM-DD),默认为今天
169 | :return: 笔记列表
170 | """
171 | if date is None:
172 | date = datetime.now().strftime('%Y-%m-%d')
173 |
174 | daily_file = self._daily_dir / f"{date}.json"
175 | if not daily_file.exists():
176 | return []
177 |
178 | with open(daily_file, 'r', encoding='utf-8') as f:
179 | return json.load(f)
180 |
181 | def get_topic_notes(self, topic: str) -> List[Dict]:
182 | """
183 | 获取指定主题的所有笔记
184 | :param topic: 主题名称
185 | :return: 笔记列表
186 | """
187 | topic_dir = self._topic_dir / topic
188 | if not topic_dir.exists():
189 | return []
190 |
191 | notes = []
192 | for note_file in topic_dir.glob('*.json'):
193 | with open(note_file, 'r', encoding='utf-8') as f:
194 | notes.append(json.load(f))
195 |
196 | return sorted(notes, key=lambda x: x['created_at'], reverse=True)
197 |
198 | def search_notes(self, query: str) -> List[Dict]:
199 | """
200 | 搜索笔记
201 | :param query: 搜索关键词
202 | :return: 匹配的笔记列表
203 | """
204 | results = []
205 | for topic_dir in self._topic_dir.iterdir():
206 | if topic_dir.is_dir():
207 | for note_file in topic_dir.glob('*.json'):
208 | with open(note_file, 'r', encoding='utf-8') as f:
209 | note = json.load(f)
210 | if (query.lower() in note['content'].lower() or
211 | query.lower() in note['topic'].lower() or
212 | any(query.lower() in tag.lower() for tag in note['tags'])):
213 | results.append(note)
214 |
215 | return sorted(results, key=lambda x: x['created_at'], reverse=True)
216 |
217 | def get_stats(self) -> Dict:
218 | """获取笔记统计数据"""
219 | return self._stats
220 |
221 | def generate_review(self, days: int = 7) -> Dict:
222 | """
223 | 生成复习报告
224 | :param days: 要回顾的天数
225 | :return: 复习报告
226 | """
227 | end_date = datetime.now()
228 | start_date = end_date.replace(day=end_date.day - days + 1)
229 |
230 | review = {
231 | 'period': f"{start_date.strftime('%Y-%m-%d')} 至 {end_date.strftime('%Y-%m-%d')}",
232 | 'total_notes': 0,
233 | 'total_words': 0,
234 | 'topics': {},
235 | 'tags': {},
236 | 'daily_notes': [],
237 | 'highlights': []
238 | }
239 |
240 | current = start_date
241 | while current <= end_date:
242 | date = current.strftime('%Y-%m-%d')
243 | daily_notes = self.get_daily_notes(date)
244 |
245 | if daily_notes:
246 | review['total_notes'] += len(daily_notes)
247 | for note in daily_notes:
248 | review['total_words'] += len(note['content'].split())
249 |
250 | # 更新主题统计
251 | if note['topic'] not in review['topics']:
252 | review['topics'][note['topic']] = 0
253 | review['topics'][note['topic']] += 1
254 |
255 | # 更新标签统计
256 | for tag in note['tags']:
257 | if tag not in review['tags']:
258 | review['tags'][tag] = 0
259 | review['tags'][tag] += 1
260 |
261 | # 添加到每日笔记列表
262 | review['daily_notes'].append({
263 | 'date': date,
264 | 'notes': daily_notes
265 | })
266 |
267 | # 如果笔记内容超过100字,添加到亮点列表
268 | if len(note['content'].split()) > 100:
269 | review['highlights'].append(note)
270 |
271 | current = current.replace(day=current.day + 1)
272 |
273 | # 保存复习报告
274 | review_file = self._review_dir / f"review_{end_date.strftime('%Y%m%d')}.json"
275 | with open(review_file, 'w', encoding='utf-8') as f:
276 | json.dump(review, f, ensure_ascii=False, indent=2)
277 |
278 | # 触发成就检查
279 | achievement_manager.update_stats('review_generated')
280 |
281 | return review
282 |
283 | # 创建全局实例
284 | note_manager = NoteManager()
--------------------------------------------------------------------------------
/src/cursormind/core/project_manager.py:
--------------------------------------------------------------------------------
1 | """
2 | 项目管理工具模块
3 | """
4 | import os
5 | import json
6 | from typing import Dict, List, Optional
7 | from datetime import datetime
8 | from pathlib import Path
9 |
10 | class ProjectManager:
11 | def __init__(self):
12 | self.config_dir = Path.home() / '.cursormind' / 'project_manager'
13 | self.config_dir.mkdir(parents=True, exist_ok=True)
14 | self.tasks_dir = self.config_dir / 'tasks'
15 | self.tasks_dir.mkdir(exist_ok=True)
16 | self.config_file = self.config_dir / 'config.json'
17 | self._load_config()
18 |
19 | def _load_config(self):
20 | """加载配置"""
21 | if not self.config_file.exists():
22 | self.config = {
23 | "task_status_options": [
24 | "待处理", "进行中", "已完成", "已取消", "已延期"
25 | ],
26 | "task_priority_options": [
27 | "低", "中", "高", "紧急"
28 | ],
29 | "task_type_options": [
30 | "功能开发", "bug修复", "文档编写", "代码重构",
31 | "性能优化", "测试编写", "其他"
32 | ],
33 | "default_task_fields": {
34 | "status": "待处理",
35 | "priority": "中",
36 | "type": "功能开发",
37 | "deadline": None,
38 | "assignee": None,
39 | "description": "",
40 | "notes": [],
41 | "subtasks": [],
42 | "related_tasks": [],
43 | "tags": []
44 | }
45 | }
46 | self._save_config()
47 | else:
48 | with open(self.config_file, 'r', encoding='utf-8') as f:
49 | self.config = json.load(f)
50 |
51 | def _save_config(self):
52 | """保存配置"""
53 | with open(self.config_file, 'w', encoding='utf-8') as f:
54 | json.dump(self.config, f, ensure_ascii=False, indent=2)
55 |
56 | def create_task(self, title: str, **kwargs) -> Dict:
57 | """创建新任务"""
58 | task_id = datetime.now().strftime("%Y%m%d%H%M%S")
59 | task = {
60 | "id": task_id,
61 | "title": title,
62 | "created_at": datetime.now().isoformat(),
63 | "updated_at": datetime.now().isoformat(),
64 | **self.config["default_task_fields"],
65 | **kwargs
66 | }
67 |
68 | task_file = self.tasks_dir / f"{task_id}.json"
69 | with open(task_file, 'w', encoding='utf-8') as f:
70 | json.dump(task, f, ensure_ascii=False, indent=2)
71 |
72 | return task
73 |
74 | def update_task(self, task_id: str, **kwargs) -> Optional[Dict]:
75 | """更新任务"""
76 | task_file = self.tasks_dir / f"{task_id}.json"
77 | if not task_file.exists():
78 | return None
79 |
80 | with open(task_file, 'r', encoding='utf-8') as f:
81 | task = json.load(f)
82 |
83 | task.update(kwargs)
84 | task["updated_at"] = datetime.now().isoformat()
85 |
86 | with open(task_file, 'w', encoding='utf-8') as f:
87 | json.dump(task, f, ensure_ascii=False, indent=2)
88 |
89 | return task
90 |
91 | def get_task(self, task_id: str) -> Optional[Dict]:
92 | """获取任务详情"""
93 | task_file = self.tasks_dir / f"{task_id}.json"
94 | if not task_file.exists():
95 | return None
96 |
97 | with open(task_file, 'r', encoding='utf-8') as f:
98 | return json.load(f)
99 |
100 | def list_tasks(self, status: Optional[str] = None, priority: Optional[str] = None,
101 | type_: Optional[str] = None, assignee: Optional[str] = None,
102 | tags: Optional[List[str]] = None) -> List[Dict]:
103 | """列出任务"""
104 | tasks = []
105 | for task_file in self.tasks_dir.glob("*.json"):
106 | with open(task_file, 'r', encoding='utf-8') as f:
107 | task = json.load(f)
108 |
109 | # 应用过滤条件
110 | if status and task["status"] != status:
111 | continue
112 | if priority and task["priority"] != priority:
113 | continue
114 | if type_ and task["type"] != type_:
115 | continue
116 | if assignee and task["assignee"] != assignee:
117 | continue
118 | if tags and not all(tag in task["tags"] for tag in tags):
119 | continue
120 |
121 | tasks.append(task)
122 |
123 | # 按优先级和创建时间排序
124 | priority_order = {p: i for i, p in enumerate(self.config["task_priority_options"])}
125 | tasks.sort(key=lambda x: (priority_order[x["priority"]], x["created_at"]), reverse=True)
126 |
127 | return tasks
128 |
129 | def add_subtask(self, parent_id: str, title: str, **kwargs) -> Optional[Dict]:
130 | """添加子任务"""
131 | parent_task = self.get_task(parent_id)
132 | if not parent_task:
133 | return None
134 |
135 | subtask = {
136 | "id": f"{parent_id}-{len(parent_task['subtasks'])+1}",
137 | "title": title,
138 | "created_at": datetime.now().isoformat(),
139 | "status": "待处理",
140 | **kwargs
141 | }
142 |
143 | parent_task["subtasks"].append(subtask)
144 | self.update_task(parent_id, subtasks=parent_task["subtasks"])
145 |
146 | return subtask
147 |
148 | def add_note(self, task_id: str, content: str) -> Optional[Dict]:
149 | """添加任务笔记"""
150 | task = self.get_task(task_id)
151 | if not task:
152 | return None
153 |
154 | note = {
155 | "id": len(task["notes"]) + 1,
156 | "content": content,
157 | "created_at": datetime.now().isoformat()
158 | }
159 |
160 | task["notes"].append(note)
161 | self.update_task(task_id, notes=task["notes"])
162 |
163 | return note
164 |
165 | def link_tasks(self, task_id: str, related_task_id: str) -> bool:
166 | """关联任务"""
167 | task = self.get_task(task_id)
168 | related_task = self.get_task(related_task_id)
169 |
170 | if not task or not related_task:
171 | return False
172 |
173 | if related_task_id not in task["related_tasks"]:
174 | task["related_tasks"].append(related_task_id)
175 | self.update_task(task_id, related_tasks=task["related_tasks"])
176 |
177 | if task_id not in related_task["related_tasks"]:
178 | related_task["related_tasks"].append(task_id)
179 | self.update_task(related_task_id, related_tasks=related_task["related_tasks"])
180 |
181 | return True
182 |
183 | def get_task_stats(self) -> Dict:
184 | """获取任务统计信息"""
185 | stats = {
186 | "total_tasks": 0,
187 | "status_counts": {},
188 | "priority_counts": {},
189 | "type_counts": {},
190 | "assignee_counts": {},
191 | "tag_counts": {},
192 | "completion_rate": 0,
193 | "average_completion_time": 0
194 | }
195 |
196 | completed_tasks = []
197 | for task_file in self.tasks_dir.glob("*.json"):
198 | with open(task_file, 'r', encoding='utf-8') as f:
199 | task = json.load(f)
200 |
201 | stats["total_tasks"] += 1
202 |
203 | # 统计状态
204 | stats["status_counts"][task["status"]] = \
205 | stats["status_counts"].get(task["status"], 0) + 1
206 |
207 | # 统计优先级
208 | stats["priority_counts"][task["priority"]] = \
209 | stats["priority_counts"].get(task["priority"], 0) + 1
210 |
211 | # 统计类型
212 | stats["type_counts"][task["type"]] = \
213 | stats["type_counts"].get(task["type"], 0) + 1
214 |
215 | # 统计负责人
216 | if task["assignee"]:
217 | stats["assignee_counts"][task["assignee"]] = \
218 | stats["assignee_counts"].get(task["assignee"], 0) + 1
219 |
220 | # 统计标签
221 | for tag in task["tags"]:
222 | stats["tag_counts"][tag] = stats["tag_counts"].get(tag, 0) + 1
223 |
224 | # 收集已完成的任务
225 | if task["status"] == "已完成":
226 | completed_tasks.append(task)
227 |
228 | # 计算完成率
229 | if stats["total_tasks"] > 0:
230 | stats["completion_rate"] = \
231 | len(completed_tasks) / stats["total_tasks"] * 100
232 |
233 | # 计算平均完成时间(天)
234 | if completed_tasks:
235 | total_days = 0
236 | for task in completed_tasks:
237 | created = datetime.fromisoformat(task["created_at"])
238 | updated = datetime.fromisoformat(task["updated_at"])
239 | total_days += (updated - created).days
240 | stats["average_completion_time"] = total_days / len(completed_tasks)
241 |
242 | return stats
243 |
244 | project_manager = ProjectManager()
--------------------------------------------------------------------------------
/src/cursormind/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yagami1997/CursorMind/c85ceaa15e0371c4ec4ca426fdd9f2609287efe7/src/cursormind/utils/__init__.py
--------------------------------------------------------------------------------
/src/cursormind/utils/helpers.py:
--------------------------------------------------------------------------------
1 | """
2 | 辅助函数模块 - 提供常用的工具函数 🛠️
3 | """
4 | import os
5 | from datetime import datetime
6 | from pathlib import Path
7 | from typing import Optional, Union
8 | import pytz
9 | from ..config.settings import settings
10 |
11 | def get_timestamp(timezone: str = 'America/Los_Angeles') -> str:
12 | """
13 | 获取当前时间戳
14 | :param timezone: 时区名称
15 | :return: 格式化的时间戳字符串
16 | """
17 | tz = pytz.timezone(timezone)
18 | now = datetime.now(tz)
19 | return now.strftime("%Y-%m-%d %H:%M:%S %Z")
20 |
21 | def ensure_dir(path: Union[str, Path]) -> Path:
22 | """
23 | 确保目录存在,如果不存在则创建
24 | :param path: 目录路径(字符串或Path对象)
25 | :return: 目录路径
26 | """
27 | path_obj = Path(path) if isinstance(path, str) else path
28 | path_obj.mkdir(parents=True, exist_ok=True)
29 | return path_obj
30 |
31 | def format_path(path: str) -> Path:
32 | """
33 | 格式化路径字符串为Path对象
34 | :param path: 路径字符串
35 | :return: Path对象
36 | """
37 | return Path(os.path.expanduser(path))
38 |
39 | def get_relative_path(path: Path, base: Path) -> str:
40 | """
41 | 获取相对路径
42 | :param path: 目标路径
43 | :param base: 基准路径
44 | :return: 相对路径字符串
45 | """
46 | try:
47 | return str(path.relative_to(base))
48 | except ValueError:
49 | return str(path)
50 |
51 | def get_project_root() -> Path:
52 | """
53 | 获取项目根目录
54 |
55 | Returns:
56 | 项目根目录的Path对象
57 | """
58 | return Path(settings.get('project_root'))
59 |
60 | def load_template(template_name: str) -> str:
61 | """
62 | 加载模板文件内容
63 |
64 | Args:
65 | template_name: 模板文件名
66 |
67 | Returns:
68 | 模板文件内容
69 |
70 | Raises:
71 | FileNotFoundError: 模板文件不存在时抛出
72 | """
73 | template_path = get_project_root() / settings.get('templates_dir') / template_name
74 | if not template_path.exists():
75 | raise FileNotFoundError(f"模板文件不存在: {template_path}")
76 |
77 | with open(template_path, 'r', encoding='utf-8') as f:
78 | return f.read()
79 |
80 | def save_file(content: str, file_path: str) -> None:
81 | """
82 | 保存内容到文件
83 |
84 | Args:
85 | content: 文件内容
86 | file_path: 文件路径
87 | """
88 | path_obj = Path(file_path)
89 | path_obj.parent.mkdir(parents=True, exist_ok=True)
90 |
91 | with open(path_obj, 'w', encoding='utf-8') as f:
92 | f.write(content)
--------------------------------------------------------------------------------
/src/cursormind/utils/note_manager.py:
--------------------------------------------------------------------------------
1 | """
2 | 笔记管理工具 - 记录你的学习历程 📝
3 | """
4 | import os
5 | from datetime import datetime
6 | from pathlib import Path
7 | from typing import List, Dict
8 | import json
9 | from ..config.settings import settings
10 | from .helpers import get_timestamp, ensure_dir
11 |
12 | class NoteManager:
13 | """笔记管理类"""
14 |
15 | def __init__(self):
16 | self.notes_dir = Path(settings.get('notes_dir', 'learning_notes'))
17 | self.ensure_notes_structure()
18 |
19 | def ensure_notes_structure(self) -> None:
20 | """确保笔记目录结构完整"""
21 | ensure_dir(self.notes_dir)
22 | ensure_dir(self.notes_dir / 'daily')
23 | ensure_dir(self.notes_dir / 'projects')
24 | ensure_dir(self.notes_dir / 'ideas')
25 |
26 | def add_note(self, content: str, note_type: str = 'daily') -> Dict:
27 | """
28 | 添加新笔记
29 |
30 | Args:
31 | content: 笔记内容
32 | note_type: 笔记类型(daily/project/idea)
33 |
34 | Returns:
35 | 笔记信息字典
36 | """
37 | timestamp = get_timestamp()
38 | date_str = datetime.now().strftime('%Y-%m-%d')
39 |
40 | # 创建笔记数据
41 | note_data = {
42 | 'content': content,
43 | 'timestamp': timestamp,
44 | 'type': note_type,
45 | 'tags': self._extract_tags(content),
46 | 'project': settings.get('current_project', '')
47 | }
48 |
49 | # 保存笔记
50 | if note_type == 'daily':
51 | file_path = self.notes_dir / 'daily' / f'{date_str}.md'
52 | else:
53 | file_path = self.notes_dir / note_type / f'{date_str}_{self._generate_id()}.md'
54 |
55 | self._save_note(note_data, file_path)
56 | self._update_stats(note_data)
57 |
58 | return note_data
59 |
60 | def get_today_notes(self) -> List[Dict]:
61 | """获取今天的笔记列表"""
62 | date_str = datetime.now().strftime('%Y-%m-%d')
63 | daily_file = self.notes_dir / 'daily' / f'{date_str}.md'
64 |
65 | if not daily_file.exists():
66 | return []
67 |
68 | return self._read_notes(daily_file)
69 |
70 | def _save_note(self, note_data: Dict, file_path: Path) -> None:
71 | """保存笔记到文件"""
72 | # 确保目录存在
73 | file_path.parent.mkdir(parents=True, exist_ok=True)
74 |
75 | # 格式化笔记内容
76 | note_content = f"""
77 | ## {note_data['timestamp']}
78 |
79 | {note_data['content']}
80 |
81 | {'#' + ' #'.join(note_data['tags']) if note_data['tags'] else ''}
82 |
83 | ---
84 | """
85 | # 追加或创建文件
86 | mode = 'a' if file_path.exists() else 'w'
87 | with open(file_path, mode, encoding='utf-8') as f:
88 | f.write(note_content)
89 |
90 | def _extract_tags(self, content: str) -> List[str]:
91 | """从内容中提取标签"""
92 | tags = []
93 | words = content.split()
94 | for word in words:
95 | if word.startswith('#') and len(word) > 1:
96 | tags.append(word[1:])
97 | return tags
98 |
99 | def _generate_id(self) -> str:
100 | """生成笔记ID"""
101 | return datetime.now().strftime('%H%M%S')
102 |
103 | def _update_stats(self, note_data: Dict) -> None:
104 | """更新笔记统计信息"""
105 | settings.set('total_notes', settings.get('total_notes', 0) + 1)
106 |
107 | # TODO: 实现更多统计功能
108 | # - 按类型统计
109 | # - 按标签统计
110 | # - 生成学习热力图
111 |
112 | def _read_notes(self, file_path: Path) -> List[Dict]:
113 | """读取笔记文件内容"""
114 | if not file_path.exists():
115 | return []
116 |
117 | notes = []
118 | current_note = None
119 |
120 | with open(file_path, 'r', encoding='utf-8') as f:
121 | for line in f:
122 | line = line.strip()
123 | if line.startswith('## '):
124 | if current_note:
125 | notes.append(current_note)
126 | current_note = {
127 | 'timestamp': line[3:],
128 | 'content': '',
129 | 'tags': []
130 | }
131 | elif current_note and line and not line.startswith('---'):
132 | if line.startswith('#'):
133 | current_note['tags'] = [tag[1:] for tag in line.split()]
134 | else:
135 | current_note['content'] += line + '\n'
136 |
137 | if current_note:
138 | notes.append(current_note)
139 |
140 | return notes
141 |
142 | # 创建全局笔记管理器实例
143 | note_manager = NoteManager()
--------------------------------------------------------------------------------