monoco-toolkit 0.1.1__py3-none-any.whl → 0.2.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. monoco/cli/__init__.py +0 -0
  2. monoco/cli/project.py +87 -0
  3. monoco/cli/workspace.py +46 -0
  4. monoco/core/agent/__init__.py +5 -0
  5. monoco/core/agent/action.py +144 -0
  6. monoco/core/agent/adapters.py +129 -0
  7. monoco/core/agent/protocol.py +31 -0
  8. monoco/core/agent/state.py +106 -0
  9. monoco/core/config.py +212 -17
  10. monoco/core/execution.py +62 -0
  11. monoco/core/feature.py +58 -0
  12. monoco/core/git.py +51 -2
  13. monoco/core/injection.py +196 -0
  14. monoco/core/integrations.py +242 -0
  15. monoco/core/lsp.py +68 -0
  16. monoco/core/output.py +21 -3
  17. monoco/core/registry.py +36 -0
  18. monoco/core/resources/en/AGENTS.md +8 -0
  19. monoco/core/resources/en/SKILL.md +66 -0
  20. monoco/core/resources/zh/AGENTS.md +8 -0
  21. monoco/core/resources/zh/SKILL.md +65 -0
  22. monoco/core/setup.py +96 -110
  23. monoco/core/skills.py +444 -0
  24. monoco/core/state.py +53 -0
  25. monoco/core/sync.py +224 -0
  26. monoco/core/telemetry.py +4 -1
  27. monoco/core/workspace.py +85 -20
  28. monoco/daemon/app.py +127 -58
  29. monoco/daemon/models.py +4 -0
  30. monoco/daemon/services.py +56 -155
  31. monoco/features/config/commands.py +125 -44
  32. monoco/features/i18n/adapter.py +29 -0
  33. monoco/features/i18n/commands.py +89 -10
  34. monoco/features/i18n/core.py +113 -27
  35. monoco/features/i18n/resources/en/AGENTS.md +8 -0
  36. monoco/features/i18n/resources/en/SKILL.md +94 -0
  37. monoco/features/i18n/resources/zh/AGENTS.md +8 -0
  38. monoco/features/i18n/resources/zh/SKILL.md +94 -0
  39. monoco/features/issue/adapter.py +34 -0
  40. monoco/features/issue/commands.py +343 -101
  41. monoco/features/issue/core.py +384 -150
  42. monoco/features/issue/domain/__init__.py +0 -0
  43. monoco/features/issue/domain/lifecycle.py +126 -0
  44. monoco/features/issue/domain/models.py +170 -0
  45. monoco/features/issue/domain/parser.py +223 -0
  46. monoco/features/issue/domain/workspace.py +104 -0
  47. monoco/features/issue/engine/__init__.py +22 -0
  48. monoco/features/issue/engine/config.py +172 -0
  49. monoco/features/issue/engine/machine.py +185 -0
  50. monoco/features/issue/engine/models.py +18 -0
  51. monoco/features/issue/linter.py +325 -120
  52. monoco/features/issue/lsp/__init__.py +3 -0
  53. monoco/features/issue/lsp/definition.py +72 -0
  54. monoco/features/issue/migration.py +134 -0
  55. monoco/features/issue/models.py +46 -24
  56. monoco/features/issue/monitor.py +94 -0
  57. monoco/features/issue/resources/en/AGENTS.md +20 -0
  58. monoco/features/issue/resources/en/SKILL.md +111 -0
  59. monoco/features/issue/resources/zh/AGENTS.md +20 -0
  60. monoco/features/issue/resources/zh/SKILL.md +138 -0
  61. monoco/features/issue/validator.py +455 -0
  62. monoco/features/spike/adapter.py +30 -0
  63. monoco/features/spike/commands.py +45 -24
  64. monoco/features/spike/core.py +6 -40
  65. monoco/features/spike/resources/en/AGENTS.md +7 -0
  66. monoco/features/spike/resources/en/SKILL.md +74 -0
  67. monoco/features/spike/resources/zh/AGENTS.md +7 -0
  68. monoco/features/spike/resources/zh/SKILL.md +74 -0
  69. monoco/main.py +91 -2
  70. monoco_toolkit-0.2.8.dist-info/METADATA +136 -0
  71. monoco_toolkit-0.2.8.dist-info/RECORD +83 -0
  72. monoco_toolkit-0.1.1.dist-info/METADATA +0 -93
  73. monoco_toolkit-0.1.1.dist-info/RECORD +0 -33
  74. {monoco_toolkit-0.1.1.dist-info → monoco_toolkit-0.2.8.dist-info}/WHEEL +0 -0
  75. {monoco_toolkit-0.1.1.dist-info → monoco_toolkit-0.2.8.dist-info}/entry_points.txt +0 -0
  76. {monoco_toolkit-0.1.1.dist-info → monoco_toolkit-0.2.8.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,134 @@
1
+ import os
2
+ import re
3
+ import yaml
4
+ import hashlib
5
+ import secrets
6
+ from pathlib import Path
7
+ from typing import List, Dict, Any
8
+ from datetime import datetime
9
+ from .models import generate_uid
10
+
11
+ # Migration Mappings
12
+ DIR_MAP = {
13
+ "STORIES": "Features",
14
+ "Stories": "Features",
15
+ "TASKS": "Chores",
16
+ "Tasks": "Chores",
17
+ "BUGS": "Fixes",
18
+ "Bugs": "Fixes",
19
+ "EPICS": "Epics",
20
+ "Epics": "Epics",
21
+ "features": "Features",
22
+ "chores": "Chores",
23
+ "fixes": "Fixes",
24
+ "epics": "Epics"
25
+ }
26
+
27
+ TYPE_MAP = {
28
+ "story": "feature",
29
+ "task": "chore",
30
+ "bug": "fix"
31
+ }
32
+
33
+ ID_PREFIX_MAP = {
34
+ "STORY": "FEAT",
35
+ "TASK": "CHORE",
36
+ "BUG": "FIX"
37
+ }
38
+
39
+ def migrate_issues_directory(issues_dir: Path):
40
+ """
41
+ Core migration logic to upgrade an Issues directory to the latest Monoco standard.
42
+ """
43
+ if not issues_dir.exists():
44
+ return
45
+
46
+ # 1. Rename Directories
47
+ for old_name, new_name in DIR_MAP.items():
48
+ old_path = issues_dir / old_name
49
+ if old_path.exists():
50
+ new_path = issues_dir / new_name
51
+
52
+ # Case sensitivity check for some filesystems
53
+ same_inode = False
54
+ try:
55
+ if new_path.exists() and os.path.samefile(old_path, new_path):
56
+ same_inode = True
57
+ except OSError:
58
+ pass
59
+
60
+ if same_inode:
61
+ if old_path.name != new_path.name:
62
+ old_path.rename(new_path)
63
+ continue
64
+
65
+ if new_path.exists():
66
+ import shutil
67
+ for item in old_path.iterdir():
68
+ dest = new_path / item.name
69
+ if dest.exists() and item.is_dir():
70
+ for subitem in item.iterdir():
71
+ shutil.move(str(subitem), str(dest / subitem.name))
72
+ shutil.rmtree(item)
73
+ else:
74
+ shutil.move(str(item), str(dest))
75
+ shutil.rmtree(old_path)
76
+ else:
77
+ old_path.rename(new_path)
78
+
79
+ # 2. Rename Files and Update Content
80
+ for subdir_name in ["Features", "Chores", "Fixes", "Epics"]:
81
+ subdir = issues_dir / subdir_name
82
+ if not subdir.exists():
83
+ continue
84
+
85
+ for file_path in subdir.rglob("*.md"):
86
+ content = file_path.read_text(encoding="utf-8")
87
+ new_content = content
88
+
89
+ # Replace Type in Frontmatter
90
+ for old_type, new_type in TYPE_MAP.items():
91
+ new_content = re.sub(rf"^type:\s*{old_type}", f"type: {new_type}", new_content, flags=re.IGNORECASE | re.MULTILINE)
92
+
93
+ # Replace ID Prefixes
94
+ for old_prefix, new_prefix in ID_PREFIX_MAP.items():
95
+ new_content = new_content.replace(f"[[{old_prefix}-", f"[[{new_prefix}-")
96
+ new_content = re.sub(rf"^id: {old_prefix}-", f"id: {new_prefix}-", new_content, flags=re.MULTILINE)
97
+ new_content = re.sub(rf"^parent: {old_prefix}-", f"parent: {new_prefix}-", new_content, flags=re.MULTILINE)
98
+ new_content = new_content.replace(f"{old_prefix}-", f"{new_prefix}-")
99
+
100
+ # Structural Updates (UID, Stage)
101
+ match = re.search(r"^---(.*?)---", new_content, re.DOTALL | re.MULTILINE)
102
+ if match:
103
+ yaml_str = match.group(1)
104
+ try:
105
+ data = yaml.safe_load(yaml_str) or {}
106
+ changed = False
107
+
108
+ if 'uid' not in data:
109
+ data['uid'] = generate_uid()
110
+ changed = True
111
+
112
+ if 'stage' in data and data['stage'] == 'todo':
113
+ data['stage'] = 'draft'
114
+ changed = True
115
+
116
+ if changed:
117
+ new_yaml = yaml.dump(data, sort_keys=False, allow_unicode=True)
118
+ new_content = new_content.replace(match.group(1), "\n" + new_yaml)
119
+ except yaml.YAMLError:
120
+ pass
121
+
122
+ if new_content != content:
123
+ file_path.write_text(new_content, encoding="utf-8")
124
+
125
+ # Rename File
126
+ filename = file_path.name
127
+ new_filename = filename
128
+ for old_prefix, new_prefix in ID_PREFIX_MAP.items():
129
+ if filename.startswith(f"{old_prefix}-"):
130
+ new_filename = filename.replace(f"{old_prefix}-", f"{new_prefix}-", 1)
131
+ break
132
+
133
+ if new_filename != filename:
134
+ file_path.rename(file_path.parent / new_filename)
@@ -1,5 +1,5 @@
1
1
  from enum import Enum
2
- from typing import List, Optional, Any
2
+ from typing import List, Optional, Any, Dict
3
3
  from pydantic import BaseModel, Field, model_validator
4
4
  from datetime import datetime
5
5
  import hashlib
@@ -61,7 +61,7 @@ class IssueStatus(str, Enum):
61
61
  BACKLOG = "backlog"
62
62
 
63
63
  class IssueStage(str, Enum):
64
- TODO = "todo"
64
+ DRAFT = "draft"
65
65
  DOING = "doing"
66
66
  REVIEW = "review"
67
67
  DONE = "done"
@@ -78,19 +78,30 @@ class IsolationType(str, Enum):
78
78
  WORKTREE = "worktree"
79
79
 
80
80
  class IssueIsolation(BaseModel):
81
- type: IsolationType
81
+ type: str
82
82
  ref: str # Git branch name
83
83
  path: Optional[str] = None # Worktree path (relative to repo root or absolute)
84
84
  created_at: datetime = Field(default_factory=current_time)
85
85
 
86
+ class IssueAction(BaseModel):
87
+ label: str
88
+ target_status: Optional[str] = None
89
+ target_stage: Optional[str] = None
90
+ target_solution: Optional[str] = None
91
+ icon: Optional[str] = None
92
+
93
+ # Generic execution extensions
94
+ command: Optional[str] = None
95
+ params: Dict[str, Any] = {}
96
+
86
97
  class IssueMetadata(BaseModel):
87
98
  model_config = {"extra": "allow"}
88
99
 
89
100
  id: str
90
101
  uid: Optional[str] = None # Global unique identifier for cross-project identity
91
- type: IssueType
92
- status: IssueStatus = IssueStatus.OPEN
93
- stage: Optional[IssueStage] = None
102
+ type: str
103
+ status: str = "open"
104
+ stage: Optional[str] = None
94
105
  title: str
95
106
 
96
107
  # Time Anchors
@@ -101,17 +112,39 @@ class IssueMetadata(BaseModel):
101
112
 
102
113
  parent: Optional[str] = None
103
114
  sprint: Optional[str] = None
104
- solution: Optional[IssueSolution] = None
115
+ solution: Optional[str] = None
105
116
  isolation: Optional[IssueIsolation] = None
106
117
  dependencies: List[str] = []
107
118
  related: List[str] = []
108
119
  tags: List[str] = []
120
+ files: List[str] = []
121
+ path: Optional[str] = None # Absolute path to the issue file
122
+
123
+ # Proxy UI Actions (Excluded from file persistence)
124
+ # Modified: Remove exclude=True to allow API/CLI inspection. Must be manually excluded during YAML Dump.
125
+ actions: List[IssueAction] = Field(default=[])
109
126
 
110
127
 
111
128
  @model_validator(mode='before')
112
129
  @classmethod
113
130
  def normalize_fields(cls, v: Any) -> Any:
114
131
  if isinstance(v, dict):
132
+ # Handle common capitalization variations for robustness
133
+ field_map = {
134
+ "ID": "id",
135
+ "Type": "type",
136
+ "Status": "status",
137
+ "Stage": "stage",
138
+ "Title": "title",
139
+ "Parent": "parent",
140
+ "Solution": "solution",
141
+ "Sprint": "sprint",
142
+ }
143
+ for old_k, new_k in field_map.items():
144
+ if old_k in v and new_k not in v:
145
+ v[new_k] = v[old_k] # Don't pop yet to avoid mutation issues if used elsewhere, or pop if safe.
146
+ # Pydantic v2 mode='before' is usually a copy if we want to be safe, but let's just add it.
147
+
115
148
  # Normalize type and status to lowercase for compatibility
116
149
  if "type" in v and isinstance(v["type"], str):
117
150
  v["type"] = v["type"].lower()
@@ -122,30 +155,19 @@ class IssueMetadata(BaseModel):
122
155
  # Stage normalization
123
156
  if "stage" in v and isinstance(v["stage"], str):
124
157
  v["stage"] = v["stage"].lower()
158
+ if v["stage"] == "todo":
159
+ v["stage"] = "draft"
125
160
  return v
126
161
 
127
162
  @model_validator(mode='after')
128
163
  def validate_lifecycle(self) -> 'IssueMetadata':
129
164
  # Logic Definition:
130
- # status: backlog -> stage: null
165
+ # status: backlog -> stage: freezed
131
166
  # status: closed -> stage: done
132
- # status: open -> stage: todo | doing | review (default todo)
133
-
134
- if self.status == IssueStatus.BACKLOG:
135
- self.stage = IssueStage.FREEZED
136
-
137
- elif self.status == IssueStatus.CLOSED:
138
- # Enforce stage=done for closed issues
139
- if self.stage != IssueStage.DONE:
140
- self.stage = IssueStage.DONE
141
- # Auto-fill closed_at if missing
142
- if not self.closed_at:
143
- self.closed_at = current_time()
167
+ # status: open -> stage: draft | doing | review | done (default draft)
144
168
 
145
- elif self.status == IssueStatus.OPEN:
146
- # Ensure valid stage for open status
147
- if self.stage is None or self.stage == IssueStage.DONE:
148
- self.stage = IssueStage.TODO
169
+ # NOTE: We do NOT auto-correct state here anymore to allow Linter to detect inconsistencies.
170
+ # Auto-correction should be applied explicitly by 'create' or 'update' commands via core logic.
149
171
 
150
172
  return self
151
173
 
@@ -0,0 +1,94 @@
1
+ import re
2
+ import asyncio
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import Callable, Awaitable, Any, Optional
6
+
7
+ from watchdog.observers import Observer
8
+ from watchdog.events import FileSystemEventHandler
9
+
10
+ logger = logging.getLogger("monoco.features.issue.monitor")
11
+
12
+ class IssueEventHandler(FileSystemEventHandler):
13
+ def __init__(self, loop, on_upsert: Callable[[dict], Awaitable[None]], on_delete: Callable[[dict], Awaitable[None]]):
14
+ self.loop = loop
15
+ self.on_upsert = on_upsert
16
+ self.on_delete = on_delete
17
+
18
+ def _process_upsert(self, path_str: str):
19
+ if not path_str.endswith(".md"):
20
+ return
21
+ asyncio.run_coroutine_threadsafe(self._handle_upsert(path_str), self.loop)
22
+
23
+ async def _handle_upsert(self, path_str: str):
24
+ try:
25
+ from monoco.features.issue.core import parse_issue
26
+ path = Path(path_str)
27
+ if not path.exists():
28
+ return
29
+ issue = parse_issue(path)
30
+ if issue:
31
+ await self.on_upsert(issue.model_dump(mode='json'))
32
+ except Exception as e:
33
+ logger.error(f"Error handling upsert for {path_str}: {e}")
34
+
35
+ def _process_delete(self, path_str: str):
36
+ if not path_str.endswith(".md"):
37
+ return
38
+ asyncio.run_coroutine_threadsafe(self._handle_delete(path_str), self.loop)
39
+
40
+ async def _handle_delete(self, path_str: str):
41
+ try:
42
+ filename = Path(path_str).name
43
+ match = re.match(r"([A-Z]+-\d{4})", filename)
44
+ if match:
45
+ issue_id = match.group(1)
46
+ await self.on_delete({"id": issue_id})
47
+ except Exception as e:
48
+ logger.error(f"Error handling delete for {path_str}: {e}")
49
+
50
+ def on_created(self, event):
51
+ if not event.is_directory:
52
+ self._process_upsert(event.src_path)
53
+
54
+ def on_modified(self, event):
55
+ if not event.is_directory:
56
+ self._process_upsert(event.src_path)
57
+
58
+ def on_deleted(self, event):
59
+ if not event.is_directory:
60
+ self._process_delete(event.src_path)
61
+
62
+ def on_moved(self, event):
63
+ if not event.is_directory:
64
+ self._process_delete(event.src_path)
65
+ self._process_upsert(event.dest_path)
66
+
67
+ class IssueMonitor:
68
+ """
69
+ Monitor the Issues directory for changes using Watchdog and trigger callbacks.
70
+ """
71
+ def __init__(self, issues_root: Path, on_upsert: Callable[[dict], Awaitable[None]], on_delete: Callable[[dict], Awaitable[None]]):
72
+ self.issues_root = issues_root
73
+ self.on_upsert = on_upsert
74
+ self.on_delete = on_delete
75
+ self.observer = Observer()
76
+ self.loop = None
77
+
78
+ async def start(self):
79
+ self.loop = asyncio.get_running_loop()
80
+ event_handler = IssueEventHandler(self.loop, self.on_upsert, self.on_delete)
81
+
82
+ if not self.issues_root.exists():
83
+ logger.warning(f"Issues root {self.issues_root} does not exist. creating...")
84
+ self.issues_root.mkdir(parents=True, exist_ok=True)
85
+
86
+ self.observer.schedule(event_handler, str(self.issues_root), recursive=True)
87
+ self.observer.start()
88
+ logger.info(f"Issue Monitor started (Watchdog). Watching {self.issues_root}")
89
+
90
+ def stop(self):
91
+ if self.observer.is_alive():
92
+ self.observer.stop()
93
+ self.observer.join()
94
+ logger.info(f"Issue Monitor stopped for {self.issues_root}")
@@ -0,0 +1,20 @@
1
+ # Issue Management (Agent Guidance)
2
+
3
+ ## Issue Management
4
+
5
+ System for managing tasks using `monoco issue`.
6
+
7
+ - **Create**: `monoco issue create <type> -t "Title"` (types: epic, feature, chore, fix)
8
+ - **Status**: `monoco issue open|close|backlog <id>`
9
+ - **Check**: `monoco issue lint` (Must run after manual edits)
10
+ - **Lifecycle**: `monoco issue start|submit|delete <id>`
11
+ - **Sync Context**: `monoco issue sync-files [id]` (Update file tracking)
12
+ - **Structure**: `Issues/{CapitalizedPluralType}/{lowercase_status}/` (e.g. `Issues/Features/open/`). Do not deviate.
13
+ - **Rules**:
14
+ 1. **Heading**: Must have `## {ID}: {Title}` (matches metadata).
15
+ 2. **Checkboxes**: Min 2 using `- [ ]`, `- [x]`, `- [-]`, `- [/]`.
16
+ 3. **Review**: `## Review Comments` section required for Review/Done stages.
17
+ 4. **Environment Policies**:
18
+ - Must use `monoco issue start --branch`.
19
+ - 🛑 **NO** direct coding on `main`/`master` (Linter will fail).
20
+ - Must update `files` field after coding (via `sync-files` or manual).
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: monoco-issue
3
+ description: Official skill for Monoco Issue System. Treats Issues as Universal Atoms, managing the lifecycle of Epic/Feature/Chore/Fix.
4
+ ---
5
+
6
+ # Issue Management
7
+
8
+ Use this skill to create and manage **Issues** (Universal Atoms) in Monoco projects.
9
+
10
+ ## Core Ontology
11
+
12
+ ### 1. Strategy Layer
13
+
14
+ - **🏆 EPIC**: Grand goals, vision containers. Mindset: Architect.
15
+
16
+ ### 2. Value Layer
17
+
18
+ - **✨ FEATURE**: Value increments from user perspective. Mindset: Product Owner.
19
+ - **Atomicity Principle**: Feature = Design + Dev + Test + Doc + i18n. They are one.
20
+
21
+ ### 3. Execution Layer
22
+
23
+ - **🧹 CHORE**: Engineering maintenance, no direct user value. Mindset: Builder.
24
+ - **🐞 FIX**: Correcting deviations. Mindset: Debugger.
25
+
26
+ ## Workflow Policies
27
+
28
+ ### 1. Strict Git Workflow
29
+
30
+ Monoco enforces a **Feature Branch** model.
31
+
32
+ - **Start**: Must use `monoco issue start <ID> --branch` to start working. This creates a `feat/<ID>-<slug>` branch.
33
+ - **Protected Main**: **NO** direct modification on `main`, `master`, or `production` branches. Linter will block this.
34
+ - **Submit**: Run `monoco issue submit <ID>` before PR to clean up and validate.
35
+
36
+ ### 2. File Tracking
37
+
38
+ Agents must track modified files to maintain Self-Contained Context.
39
+
40
+ - **Mechanism**: Issue Ticket Front Matter contains a `files: []` field.
41
+ - **Automated (Recommended)**: Run `monoco issue sync-files` inside the Feature Branch. It diffs against the base branch.
42
+ - **Manual (Fallback)**: If working without branches, Agent MUST **actively** append modified paths to the `files` list.
43
+
44
+ ## Guidelines
45
+
46
+ ### Directory Structure & Naming
47
+
48
+ `Issues/{CapitalizedPluralType}/{lowercase_status}/`
49
+
50
+ - **Types**: `Epics`, `Features`, `Chores`, `Fixes`
51
+ - **Statuses**: `open`, `backlog`, `closed`
52
+
53
+ ### Structural Integrity
54
+
55
+ Issues are validated via `monoco issue lint`. key constraints:
56
+
57
+ 1. **Mandatory Heading**: `## {ID}: {Title}` must match front matter.
58
+ 2. **Min Checkboxes**: At least 2 checkboxes (AC/Tasks).
59
+ 3. **Review Protocol**: `## Review Comments` required for `review` or `done` stages.
60
+
61
+ ### Path Transitions
62
+
63
+ Use `monoco issue`:
64
+
65
+ 1. **Create**: `monoco issue create <type> --title "..."`
66
+ - Params: `--parent <id>`, `--dependency <id>`, `--related <id>`, `--sprint <id>`, `--tags <tag>`
67
+
68
+ 2. **Transition**: `monoco issue open/close/backlog <id>`
69
+
70
+ 3. **View**: `monoco issue scope`
71
+
72
+ 4. **Validation**: `monoco issue lint`
73
+
74
+ 5. **Modification**: `monoco issue start/submit/delete <id>`
75
+
76
+ 6. **Sync**: `monoco issue sync-files [id]` (Sync code changes to Issue file)
77
+
78
+ 7. **Validation**: `monoco issue lint` (Enforces compliance)
79
+
80
+ ## Validation Rules (FEAT-0082)
81
+
82
+ To ensure data integrity, all Issue tickets must follow these strict rules:
83
+
84
+ ### 1. Structural Consistency
85
+
86
+ - Must contain a Level 2 Heading matching exactly: `## {ID}: {Title}`.
87
+ - Example: `## FEAT-0082: Issue Ticket Validator`
88
+
89
+ ### 2. Content Completeness
90
+
91
+ - **Checkboxes**: Minimum of 2 checkboxes required (one for AC, one for Tasks).
92
+ - **Review Comments**: If `stage` is `review` or `done`, a `## Review Comments` section is mandatory and must not be empty.
93
+
94
+ ### 3. Checkbox Syntax & Hierarchy
95
+
96
+ - Use only `- [ ]`, `- [x]`, `- [-]`, or `- [/]`.
97
+ - **Inheritance**: If nested checkboxes exist, the parent state must reflect child states (e.g., if any child is `[/]`, parent must be `[/]`; if all children are `[x]`, parent must be `[x]`).
98
+
99
+ ### 4. State Matrix
100
+
101
+ The `status` (folder) and `stage` (front matter) must be compatible:
102
+
103
+ - **open**: Draft, Doing, Review, Done
104
+ - **backlog**: Draft, Doing, Review
105
+ - **closed**: Done
106
+
107
+ ### 5. Environment Policy
108
+
109
+ Linter includes environment-aware guardrails:
110
+
111
+ - 🛑 **Dirty Main Protection**: Fails if uncommitted changes are detected on protected branches (`main`/`master`).
@@ -0,0 +1,20 @@
1
+ # Issue 管理 (Agent 指引)
2
+
3
+ ## Issue 管理
4
+
5
+ 使用 `monoco issue` 管理任务的系统。
6
+
7
+ - **创建**: `monoco issue create <type> -t "标题"` (类型: epic, feature, chore, fix)
8
+ - **状态**: `monoco issue open|close|backlog <id>`
9
+ - **检查**: `monoco issue lint` (手动编辑后必须运行)
10
+ - **生命周期**: `monoco issue start|submit|delete <id>`
11
+ - **上下文同步**: `monoco issue sync-files [id]` (更新文件追踪)
12
+ - **结构**: `Issues/{CapitalizedPluralType}/{lowercase_status}/` (如 `Issues/Features/open/`)。
13
+ - **强制规则**:
14
+ 1. **标题**: 必须包含 `## {ID}: {Title}` 标题(与 Front Matter 一致)。
15
+ 2. **内容**: 至少 2 个 Checkbox,使用 `- [ ]`, `- [x]`, `- [-]`, `- [/]`。
16
+ 3. **评审**: `review`/`done` 阶段必须包含 `## Review Comments` 章节且内容不为空。
17
+ 4. **环境策略**:
18
+ - 必须使用 `monoco issue start --branch` 创建 Feature 分支。
19
+ - 🛑 **禁止**直接在 `main`/`master` 分支修改代码 (Linter 会报错)。
20
+ - 修改代码后**必须**更新 `files` 字段(通过 `sync-files` 或手动)。
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: monoco-issue
3
+ description: Monoco Issue System 的官方技能定义。将 Issue 视为通用原子 (Universal Atom),管理 Epic/Feature/Chore/Fix 的生命周期。
4
+ ---
5
+
6
+ # 自我管理 (Monoco Issue System)
7
+
8
+ 使用此技能在 Monoco 项目中创建和管理 **Issue** (通用原子)。该系统参考 Jira 表达体系,同时保持 "建设者 (Builder)" 和 "调试者 (Debugger)" 思维模式的隔离。
9
+
10
+ ## 核心本体论 (Core Ontology)
11
+
12
+ Monoco 不仅仅复刻 Jira,而是基于 **"思维模式 (Mindset)"** 重新定义工作单元。
13
+
14
+ ### 1. 战略层 (Strategy)
15
+
16
+ #### 🏆 EPIC (史诗)
17
+
18
+ - **Mindset**: _Architect_ (架构师)
19
+ - **定义**: 跨越多个周期的宏大目标。它不是单纯的"大任务",而是"愿景的容器"。
20
+ - **产出**: 定义了系统的边界和核心价值。
21
+
22
+ ### 2. 价值层 (Value)
23
+
24
+ #### ✨ FEATURE (特性)
25
+
26
+ - **Mindset**: _Product Owner_ (产品负责人)
27
+ - **定义**: 用户视角的价值增量。必须是可独立交付 (Shippable) 的垂直切片。
28
+ - **Focus**: "Why" & "What" (用户想要什么?)。
29
+ - **Prefix**: `FEAT-`
30
+
31
+ ### 3. 执行层 (Execution)
32
+
33
+ #### 🧹 CHORE (杂务)
34
+
35
+ - **Mindset**: _Builder_ (建设者)
36
+ - **定义**: **不产生**直接用户价值的工程性事务。
37
+ - **场景**: 架构升级、写构建脚本、修复 CI/CD 流水线。
38
+ - **Focus**: "How" (为了支撑系统运转,必须做什么)。
39
+ - **Prefix**: `CHORE-`
40
+
41
+ > 注: 取代了传统的 Task 概念。
42
+
43
+ #### 🐞 FIX (修复)
44
+
45
+ - **Mindset**: _Debugger_ (调试者)
46
+ - **定义**: 预期与现实的偏差。它是负价值的修正。
47
+ - **Focus**: "Fix" (恢复原状)。
48
+ - **Prefix**: `FIX-`
49
+
50
+ > 注: 取代了传统的 Bug 概念。
51
+
52
+ ---
53
+
54
+ **关系链**:
55
+
56
+ - **主要**: `EPIC` (愿景) -> `FEATURE` (价值交付单元)
57
+ - **次要**: `CHORE` (工程维护/支撑) - 通常独立存在。
58
+ - **原子性原则**: Feature = Design + Dev + Test + Doc + i18n。它们是一体的。
59
+
60
+ ## 工作流策略 (Workflow Policies)
61
+
62
+ ### 1. 严格 Git 工作流 (Strict Git Workflow)
63
+
64
+ Monoco 强制采用 **Feature Branch** 模式。
65
+
66
+ - **Start**: 必须使用 `monoco issue start <ID> --branch` 启动任务。这会自动创建 `feat/<ID>-<slug>` 分支。
67
+ - **禁止主干开发**: **严禁** 直接在 `main`, `master`, `production` 分支上修改代码。Linter 会拦截此类行为。
68
+ - **Submit**: 在提交 PR 前,运行 `monoco issue submit <ID>` 进行清理和预发布检查。
69
+
70
+ ### 2. 文件追踪 (File Tracking)
71
+
72
+ 为了保证上下文的自包含性 (Self-Contained Context),Agent 必须记录修改过的文件。
73
+
74
+ - **机制**: Issue Ticket 的 Front Matter 包含 `files: []` 字段。
75
+ - **自动化 (推荐)**: 在 Feature Branch 中运行 `monoco issue sync-files`。它会自动对比当前分支与 Base 分支的差异并更新列表。
76
+ - **手动 (备选)**: 如果进行非分支开发,Agent 必须**主动**将修改的文件路径写入 `files` 列表。
77
+
78
+ ## 准则 (Guidelines)
79
+
80
+ ### 目录结构
81
+
82
+ `Issues/{CapitalizedPluralType}/{lowercase_status}/`
83
+
84
+ - `{TYPE}`: `Epics`, `Features`, `Chores`, `Fixes`
85
+ - `{STATUS}`: `open`, `backlog`, `closed`
86
+
87
+ ### 路径流转
88
+
89
+ 使用 `monoco issue`:
90
+
91
+ 1. **Create**: `monoco issue create <type> --title "..."`
92
+ - Params: `--parent <id>`, `--dependency <id>`, `--related <id>`, `--sprint <id>`, `--tags <tag>`
93
+
94
+ 2. **Transition**: `monoco issue open/close/backlog <id>`
95
+
96
+ 3. **View**: `monoco issue scope`
97
+
98
+ 4. **Validation**: `monoco issue lint`
99
+
100
+ 5. **Modification**: `monoco issue start/submit/delete <id>`
101
+
102
+ 6. **Sync**: `monoco issue sync-files [id]` (同步代码变更到 Issue 文件)
103
+
104
+ 7. **Validation**: `monoco issue lint` (强制执行合规性检查)
105
+
106
+ ## 合规与结构校验 (Validation Rules)
107
+
108
+ 为了确保数据严谨性,所有 Issue Ticket 必须遵循以下强制规则:
109
+
110
+ ### 1. 结构一致性 (Structural Consistency)
111
+
112
+ - 必须包含一个二级标题 (`##`),内容必须与 Front Matter 中的 ID 和 Title 严格匹配。
113
+ - 格式: `## {ID}: {Title}`
114
+ - 示例: `## FEAT-0082: Issue Ticket Validator`
115
+
116
+ ### 2. 内容完整性 (Content Completeness)
117
+
118
+ - **Checkbox 数量**: 每个 Ticket 必须包含至少 2 个 Checkbox(通常代表 AC 和 Tasks)。
119
+ - **评审记录**: 当 `stage` 为 `review` 或 `done` 时,必须包含 `## Review Comments` 标题且内容不能为空。
120
+
121
+ ### 3. Checkbox 语法与层级 (Checkbox Matrix)
122
+
123
+ - 仅限使用: `- [ ]`, `- [x]`, `- [-]`, `- [/]`。
124
+ - **层级继承**: 若存在嵌套 Checkbox,父项状态必须正确反映子项的聚合结果(例如: 任一子项为 `[/]` 则父项必为 `[/]`;子项全选则父项为 `[x]`)。
125
+
126
+ ### 4. 状态矩阵 (State Matrix)
127
+
128
+ `status` (物理存放目录) 与 `stage` (Front Matter 字段) 必须兼容:
129
+
130
+ - **open**: Draft, Doing, Review, Done
131
+ - **backlog**: Draft, Doing, Review
132
+ - **closed**: Done
133
+
134
+ ### 5. 环境策略 (Environment Policy)
135
+
136
+ Linter 包含环境感知防护:
137
+
138
+ - 🛑 **Dirty Main Protection**: 当检测到处于受保护分支 (`main`/`master`) 且存在未提交变更时,Lint 将失败并阻止操作。