monoco-toolkit 0.2.5__py3-none-any.whl → 0.2.6__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 (44) hide show
  1. monoco/core/agent/adapters.py +24 -1
  2. monoco/core/config.py +63 -1
  3. monoco/core/integrations.py +8 -0
  4. monoco/core/lsp.py +7 -0
  5. monoco/core/output.py +8 -1
  6. monoco/core/setup.py +8 -0
  7. monoco/features/agent/commands.py +73 -2
  8. monoco/features/agent/core.py +48 -0
  9. monoco/features/agent/resources/en/critique.prompty +16 -0
  10. monoco/features/agent/resources/en/develop.prompty +16 -0
  11. monoco/features/agent/resources/en/investigate.prompty +16 -0
  12. monoco/features/agent/resources/en/refine.prompty +14 -0
  13. monoco/features/agent/resources/en/verify.prompty +16 -0
  14. monoco/features/agent/resources/zh/critique.prompty +18 -0
  15. monoco/features/agent/resources/zh/develop.prompty +18 -0
  16. monoco/features/agent/resources/zh/investigate.prompty +18 -0
  17. monoco/features/agent/resources/zh/refine.prompty +16 -0
  18. monoco/features/agent/resources/zh/verify.prompty +18 -0
  19. monoco/features/issue/commands.py +133 -35
  20. monoco/features/issue/core.py +142 -119
  21. monoco/features/issue/domain/__init__.py +0 -0
  22. monoco/features/issue/domain/lifecycle.py +126 -0
  23. monoco/features/issue/domain/models.py +170 -0
  24. monoco/features/issue/domain/parser.py +223 -0
  25. monoco/features/issue/domain/workspace.py +104 -0
  26. monoco/features/issue/engine/__init__.py +22 -0
  27. monoco/features/issue/engine/config.py +189 -0
  28. monoco/features/issue/engine/machine.py +185 -0
  29. monoco/features/issue/engine/models.py +18 -0
  30. monoco/features/issue/linter.py +32 -11
  31. monoco/features/issue/lsp/__init__.py +3 -0
  32. monoco/features/issue/lsp/definition.py +72 -0
  33. monoco/features/issue/models.py +8 -8
  34. monoco/features/issue/validator.py +181 -65
  35. monoco/features/spike/core.py +5 -22
  36. monoco/main.py +0 -15
  37. {monoco_toolkit-0.2.5.dist-info → monoco_toolkit-0.2.6.dist-info}/METADATA +1 -1
  38. {monoco_toolkit-0.2.5.dist-info → monoco_toolkit-0.2.6.dist-info}/RECORD +41 -22
  39. monoco/features/pty/core.py +0 -185
  40. monoco/features/pty/router.py +0 -138
  41. monoco/features/pty/server.py +0 -56
  42. {monoco_toolkit-0.2.5.dist-info → monoco_toolkit-0.2.6.dist-info}/WHEEL +0 -0
  43. {monoco_toolkit-0.2.5.dist-info → monoco_toolkit-0.2.6.dist-info}/entry_points.txt +0 -0
  44. {monoco_toolkit-0.2.5.dist-info → monoco_toolkit-0.2.6.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,9 @@ from pathlib import Path
6
6
  from monoco.core.lsp import Diagnostic, DiagnosticSeverity, Range, Position
7
7
  from monoco.core.config import get_config
8
8
  from monoco.features.i18n.core import detect_language
9
- from .models import IssueMetadata, IssueStatus, IssueStage, IssueType
9
+ from .models import IssueMetadata, IssueType
10
+ from .domain.parser import MarkdownParser
11
+ from .domain.models import ContentBlock
10
12
 
11
13
  class IssueValidator:
12
14
  """
@@ -20,14 +22,41 @@ class IssueValidator:
20
22
  def validate(self, meta: IssueMetadata, content: str, all_issue_ids: Set[str] = set()) -> List[Diagnostic]:
21
23
  diagnostics = []
22
24
 
25
+ # Parse Content into Blocks (Domain Layer)
26
+ # Handle case where content might be just body (from update_issue) or full file
27
+ if content.startswith("---"):
28
+ try:
29
+ issue_domain = MarkdownParser.parse(content)
30
+ blocks = issue_domain.body.blocks
31
+ has_frontmatter = True
32
+ except Exception:
33
+ # Fallback if parser fails (e.g. invalid YAML)
34
+ # We continue with empty blocks or try partial parsing?
35
+ # For now, let's try to parse blocks ignoring FM
36
+ lines = content.splitlines()
37
+ # Find end of FM
38
+ start_line = 0
39
+ if lines[0].strip() == "---":
40
+ for i in range(1, len(lines)):
41
+ if lines[i].strip() == "---":
42
+ start_line = i + 1
43
+ break
44
+ blocks = MarkdownParser._parse_blocks(lines[start_line:], start_line_offset=start_line)
45
+ has_frontmatter = True
46
+ else:
47
+ # Assume content is just body
48
+ lines = content.splitlines()
49
+ blocks = MarkdownParser._parse_blocks(lines, start_line_offset=0)
50
+ has_frontmatter = False
51
+
23
52
  # 1. State Matrix Validation
24
53
  diagnostics.extend(self._validate_state_matrix(meta, content))
25
54
 
26
- # 2. Content Completeness (Checkbox check)
27
- diagnostics.extend(self._validate_content_completeness(meta, content))
55
+ # 2. State Requirements (Strict Verification)
56
+ diagnostics.extend(self._validate_state_requirements(meta, blocks))
28
57
 
29
- # 3. Structure Consistency (Headings)
30
- diagnostics.extend(self._validate_structure(meta, content))
58
+ # 3. Structure Consistency (Headings) - Using Blocks
59
+ diagnostics.extend(self._validate_structure_blocks(meta, blocks))
31
60
 
32
61
  # 4. Lifecycle/Integrity (Solution, etc.)
33
62
  diagnostics.extend(self._validate_integrity(meta, content))
@@ -38,8 +67,8 @@ class IssueValidator:
38
67
  # 6. Time Consistency
39
68
  diagnostics.extend(self._validate_time_consistency(meta, content))
40
69
 
41
- # 7. Checkbox Syntax
42
- diagnostics.extend(self._validate_checkbox_logic(content))
70
+ # 7. Checkbox Syntax - Using Blocks
71
+ diagnostics.extend(self._validate_checkbox_logic_blocks(blocks))
43
72
 
44
73
  # 8. Language Consistency
45
74
  diagnostics.extend(self._validate_language_consistency(meta, content))
@@ -97,56 +126,102 @@ class IssueValidator:
97
126
  diagnostics = []
98
127
 
99
128
  # Check based on parsed metadata (now that auto-correction is disabled)
100
- if meta.status == IssueStatus.CLOSED and meta.stage != IssueStage.DONE:
129
+ if meta.status == "closed" and meta.stage != "done":
101
130
  line = self._get_field_line(content, "status")
102
131
  diagnostics.append(self._create_diagnostic(
103
- f"State Mismatch: Closed issues must be in 'Done' stage (found: {meta.stage.value if meta.stage else 'None'})",
132
+ f"State Mismatch: Closed issues must be in 'Done' stage (found: {meta.stage if meta.stage else 'None'})",
104
133
  DiagnosticSeverity.Error,
105
134
  line=line
106
135
  ))
107
136
 
108
- if meta.status == IssueStatus.BACKLOG and meta.stage != IssueStage.FREEZED:
137
+ if meta.status == "backlog" and meta.stage != "freezed":
109
138
  line = self._get_field_line(content, "status")
110
139
  diagnostics.append(self._create_diagnostic(
111
- f"State Mismatch: Backlog issues must be in 'Freezed' stage (found: {meta.stage.value if meta.stage else 'None'})",
140
+ f"State Mismatch: Backlog issues must be in 'Freezed' stage (found: {meta.stage if meta.stage else 'None'})",
112
141
  DiagnosticSeverity.Error,
113
142
  line=line
114
143
  ))
115
144
 
116
145
  return diagnostics
117
146
 
118
- def _validate_content_completeness(self, meta: IssueMetadata, content: str) -> List[Diagnostic]:
147
+ def _validate_state_requirements(self, meta: IssueMetadata, blocks: List[ContentBlock]) -> List[Diagnostic]:
119
148
  diagnostics = []
120
- # Checkbox regex: - [ ] or - [x] or - [-] or - [/]
121
- checkboxes = re.findall(r"-\s*\[([ x\-/])\]", content)
122
149
 
123
- if len(checkboxes) < 2:
124
- diagnostics.append(self._create_diagnostic(
125
- "Content Incomplete: Ticket must contain at least 2 checkboxes (AC & Tasks).",
126
- DiagnosticSeverity.Warning
127
- ))
128
-
129
- if meta.stage in [IssueStage.REVIEW, IssueStage.DONE]:
130
- # No empty checkboxes allowed
131
- if ' ' in checkboxes:
132
- # Find the first occurrence line
133
- lines = content.split('\n')
134
- first_line = 0
135
- for i, line in enumerate(lines):
136
- if re.search(r"-\s*\[ \]", line):
137
- first_line = i
138
- break
139
-
140
- diagnostics.append(self._create_diagnostic(
141
- f"Incomplete Tasks: Issue in {meta.stage} cannot have unchecked boxes.",
142
- DiagnosticSeverity.Error,
143
- line=first_line
144
- ))
150
+ # 1. Map Blocks to Sections
151
+ sections = {"tasks": [], "ac": [], "review": []}
152
+ current_section = None
153
+
154
+ for block in blocks:
155
+ if block.type == "heading":
156
+ title = block.content.strip().lower()
157
+ if "technical tasks" in title:
158
+ current_section = "tasks"
159
+ elif "acceptance criteria" in title:
160
+ current_section = "ac"
161
+ elif "review comments" in title:
162
+ current_section = "review"
163
+ else:
164
+ current_section = None
165
+ elif block.type == "task_item":
166
+ if current_section and current_section in sections:
167
+ sections[current_section].append(block)
168
+
169
+ # 2. Logic: DOING -> Must have defined tasks
170
+ if meta.stage in ["doing", "review", "done"]:
171
+ if not sections["tasks"]:
172
+ # We can't strictly point to a line if section missing, but we can point to top/bottom
173
+ # Or just a general error.
174
+ diagnostics.append(self._create_diagnostic(
175
+ "State Requirement (DOING+): Must define 'Technical Tasks' (at least 1 checkbox).",
176
+ DiagnosticSeverity.Warning
177
+ ))
178
+
179
+ # 3. Logic: REVIEW -> Tasks must be Completed ([x]) or Cancelled ([~], [+])
180
+ # No [ ] (ToDo) or [-]/[/] (Doing) allowed.
181
+ if meta.stage in ["review", "done"]:
182
+ for block in sections["tasks"]:
183
+ content = block.content.strip()
184
+ # Check for explicit illegal states
185
+ if re.search(r"-\s*\[\s+\]", content):
186
+ diagnostics.append(self._create_diagnostic(
187
+ f"State Requirement ({meta.stage.upper()}): Technical Tasks must be resolved. Found Todo [ ]: '{content}'",
188
+ DiagnosticSeverity.Error,
189
+ line=block.line_start
190
+ ))
191
+ elif re.search(r"-\s*\[[-\/]]", content):
192
+ diagnostics.append(self._create_diagnostic(
193
+ f"State Requirement ({meta.stage.upper()}): Technical Tasks must be finished (not Doing). Found Doing [-]: '{content}'",
194
+ DiagnosticSeverity.Error,
195
+ line=block.line_start
196
+ ))
197
+
198
+ # 4. Logic: DONE -> AC must be Verified ([x])
199
+ if meta.stage == "done":
200
+ for block in sections["ac"]:
201
+ content = block.content.strip()
202
+ if not re.search(r"-\s*\[[xX]\]", content):
203
+ diagnostics.append(self._create_diagnostic(
204
+ f"State Requirement (DONE): Acceptance Criteria must be passed ([x]). Found: '{content}'",
205
+ DiagnosticSeverity.Error,
206
+ line=block.line_start
207
+ ))
208
+
209
+ # 5. Logic: DONE -> Review Checkboxes (if any) must be Resolved ([x] or [~])
210
+ for block in sections["review"]:
211
+ content = block.content.strip()
212
+ # Must be [x], [X], [~], [+]
213
+ # Therefore [ ], [-], [/] are invalid blocking states
214
+ if re.search(r"-\s*\[[\s\-\/]\]", content):
215
+ diagnostics.append(self._create_diagnostic(
216
+ f"State Requirement (DONE): Actionable Review Comments must be resolved ([x] or [~]). Found: '{content}'",
217
+ DiagnosticSeverity.Error,
218
+ line=block.line_start
219
+ ))
220
+
145
221
  return diagnostics
146
222
 
147
- def _validate_structure(self, meta: IssueMetadata, content: str) -> List[Diagnostic]:
223
+ def _validate_structure_blocks(self, meta: IssueMetadata, blocks: List[ContentBlock]) -> List[Diagnostic]:
148
224
  diagnostics = []
149
- lines = content.split('\n')
150
225
 
151
226
  # 1. Heading check: ## {issue-id}: {issue-title}
152
227
  expected_header = f"## {meta.id}: {meta.title}"
@@ -156,19 +231,25 @@ class IssueValidator:
156
231
  review_header_found = False
157
232
  review_content_found = False
158
233
 
159
- for i, line in enumerate(lines):
160
- line_stripped = line.strip()
161
- if line_stripped == expected_header:
162
- header_found = True
163
-
164
- if line_stripped == "## Review Comments":
165
- review_header_found = True
166
- # Check near lines for content
167
- # This is a naive check (next line is not empty)
168
- if i + 1 < len(lines) and lines[i+1].strip():
169
- review_content_found = True
170
- elif i + 2 < len(lines) and lines[i+2].strip():
171
- review_content_found = True
234
+ review_header_index = -1
235
+
236
+ for i, block in enumerate(blocks):
237
+ if block.type == 'heading':
238
+ stripped = block.content.strip()
239
+ if stripped == expected_header:
240
+ header_found = True
241
+
242
+ if stripped == "## Review Comments":
243
+ review_header_found = True
244
+ review_header_index = i
245
+
246
+ # Check content after review header
247
+ if review_header_found:
248
+ # Check if there are blocks after review_header_index that are NOT empty
249
+ for j in range(review_header_index + 1, len(blocks)):
250
+ if blocks[j].type != 'empty':
251
+ review_content_found = True
252
+ break
172
253
 
173
254
  if not header_found:
174
255
  diagnostics.append(self._create_diagnostic(
@@ -176,7 +257,7 @@ class IssueValidator:
176
257
  DiagnosticSeverity.Warning
177
258
  ))
178
259
 
179
- if meta.stage in [IssueStage.REVIEW, IssueStage.DONE]:
260
+ if meta.stage in ["review", "done"]:
180
261
  if not review_header_found:
181
262
  diagnostics.append(self._create_diagnostic(
182
263
  "Review Requirement: Missing '## Review Comments' section.",
@@ -191,7 +272,7 @@ class IssueValidator:
191
272
 
192
273
  def _validate_integrity(self, meta: IssueMetadata, content: str) -> List[Diagnostic]:
193
274
  diagnostics = []
194
- if meta.status == IssueStatus.CLOSED and not meta.solution:
275
+ if meta.status == "closed" and not meta.solution:
195
276
  line = self._get_field_line(content, "status")
196
277
  diagnostics.append(self._create_diagnostic(
197
278
  f"Data Integrity: Closed issue {meta.id} missing 'solution' field.",
@@ -221,6 +302,42 @@ class IssueValidator:
221
302
  DiagnosticSeverity.Error,
222
303
  line=line
223
304
  ))
305
+
306
+ # Body Reference Check
307
+ # Regex for generic issue ID: (EPIC|FEAT|CHORE|FIX)-\d{4}
308
+ # We scan line by line to get line numbers
309
+ lines = content.split('\n')
310
+ # Skip frontmatter for body check to avoid double counting (handled above)
311
+ in_fm = False
312
+ fm_end = 0
313
+ for i, line in enumerate(lines):
314
+ if line.strip() == '---':
315
+ if not in_fm: in_fm = True
316
+ else:
317
+ fm_end = i
318
+ break
319
+
320
+ for i, line in enumerate(lines):
321
+ if i <= fm_end: continue # Skip frontmatter
322
+
323
+ # Find all matches
324
+ matches = re.finditer(r"\b((?:EPIC|FEAT|CHORE|FIX)-\d{4})\b", line)
325
+ for match in matches:
326
+ ref_id = match.group(1)
327
+ if ref_id != meta.id and ref_id not in all_ids:
328
+ # Check if it's a namespaced ID? The regex only catches local IDs.
329
+ # If users use MON::FEAT-0001, the regex might catch FEAT-0001.
330
+ # But all_ids contains full IDs (potentially namespaced).
331
+ # Simple logic: if ref_id isn't in all_ids, check if any id ENDS with ref_id
332
+
333
+ found_namespaced = any(known.endswith(f"::{ref_id}") for known in all_ids)
334
+
335
+ if not found_namespaced:
336
+ diagnostics.append(self._create_diagnostic(
337
+ f"Broken Reference: Issue '{ref_id}' not found.",
338
+ DiagnosticSeverity.Warning,
339
+ line=i
340
+ ))
224
341
  return diagnostics
225
342
 
226
343
  def _validate_time_consistency(self, meta: IssueMetadata, content: str) -> List[Diagnostic]:
@@ -249,21 +366,20 @@ class IssueValidator:
249
366
 
250
367
  return diagnostics
251
368
 
252
- def _validate_checkbox_logic(self, content: str) -> List[Diagnostic]:
369
+ def _validate_checkbox_logic_blocks(self, blocks: List[ContentBlock]) -> List[Diagnostic]:
253
370
  diagnostics = []
254
- lines = content.split('\n')
255
371
 
256
- for i, line in enumerate(lines):
257
- stripped = line.lstrip()
258
-
259
- # Syntax Check: - [?]
260
- if stripped.startswith("- ["):
261
- match = re.match(r"- \[([ x\-/])\]", stripped)
372
+ for block in blocks:
373
+ if block.type == 'task_item':
374
+ content = block.content.strip()
375
+ # Syntax Check: - [?]
376
+ # Added supported chars: /, ~, +
377
+ match = re.match(r"- \[([ x\-/~+])\]", content)
262
378
  if not match:
263
379
  # Check for Common errors
264
- if re.match(r"- \[.{2,}\]", stripped): # [xx] or [ ]
265
- diagnostics.append(self._create_diagnostic("Invalid Checkbox: Use single character [ ], [x], [-], [/]", DiagnosticSeverity.Error, i))
266
- elif re.match(r"- \[([^ x\-/])\]", stripped): # [v], [o]
267
- diagnostics.append(self._create_diagnostic("Invalid Checkbox Status: Use [ ], [x], [-], [/]", DiagnosticSeverity.Error, i))
380
+ if re.match(r"- \[.{2,}\]", content): # [xx] or [ ]
381
+ diagnostics.append(self._create_diagnostic("Invalid Checkbox: Use single character [ ], [x], [-], [/]", DiagnosticSeverity.Error, block.line_start))
382
+ elif re.match(r"- \[([^ x\-/~+])\]", content): # [v], [o]
383
+ diagnostics.append(self._create_diagnostic("Invalid Checkbox Status: Use [ ], [x], [/], [~]", DiagnosticSeverity.Error, block.line_start))
268
384
 
269
385
  return diagnostics
@@ -1,12 +1,12 @@
1
1
  import os
2
2
  import shutil
3
3
  import subprocess
4
- import yaml
4
+
5
5
  from pathlib import Path
6
6
  from typing import Dict, Optional, List, Any
7
7
  from rich.console import Console
8
8
 
9
- from monoco.core.config import get_config
9
+ from monoco.core.config import get_config, load_raw_config, save_raw_config, ConfigScope
10
10
 
11
11
  console = Console()
12
12
 
@@ -29,26 +29,10 @@ def run_git_command(cmd: List[str], cwd: Path) -> bool:
29
29
  console.print("[red]Error:[/red] git command not found.")
30
30
  return False
31
31
 
32
- def get_config_file_path(root: Path) -> Path:
33
- """Determine the config file to update."""
34
- # Standard: .monoco/project.yaml
35
- hidden = root / ".monoco" / "project.yaml"
36
-
37
- # Ensure parent exists
38
- hidden.parent.mkdir(exist_ok=True)
39
- return hidden
40
-
41
32
  def update_config_repos(root: Path, repo_name: str, repo_url: str, remove: bool = False):
42
33
  """Update the repos list in the config file."""
43
- config_path = get_config_file_path(root)
44
-
45
- data = {}
46
- if config_path.exists():
47
- try:
48
- with open(config_path, "r") as f:
49
- data = yaml.safe_load(f) or {}
50
- except Exception:
51
- data = {}
34
+ # Use core config utils
35
+ data = load_raw_config(ConfigScope.PROJECT, project_root=str(root))
52
36
 
53
37
  # Ensure structure exists
54
38
  if "project" not in data:
@@ -62,8 +46,7 @@ def update_config_repos(root: Path, repo_name: str, repo_url: str, remove: bool
62
46
  else:
63
47
  data["project"]["spike_repos"][repo_name] = repo_url
64
48
 
65
- with open(config_path, "w") as f:
66
- yaml.dump(data, f, sort_keys=False, default_flow_style=False)
49
+ save_raw_config(ConfigScope.PROJECT, data, project_root=str(root))
67
50
 
68
51
  def ensure_gitignore(root: Path, target_dir_name: str):
69
52
  """Ensure the target directory is in .gitignore."""
monoco/main.py CHANGED
@@ -167,20 +167,5 @@ app.add_typer(agent_cmd.app, name="agent", help="Delegate tasks to Agent CLIs")
167
167
  from monoco.daemon.commands import serve
168
168
  app.command(name="serve")(serve)
169
169
 
170
- @app.command()
171
- def pty(
172
- host: str = "127.0.0.1",
173
- port: int = 3124,
174
- cwd: Optional[str] = None
175
- ):
176
- """
177
- Start the Monoco PTY Daemon (WebSocket).
178
- """
179
- from monoco.features.pty.server import run_pty_server
180
- from pathlib import Path
181
-
182
- path = Path(cwd) if cwd else None
183
- run_pty_server(host, port, path)
184
-
185
170
  if __name__ == "__main__":
186
171
  app()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: monoco-toolkit
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Agent Native Toolkit for Monoco - Task Management & Kanban for AI Agents
5
5
  Project-URL: Homepage, https://monoco.io
6
6
  Project-URL: Repository, https://github.com/IndenScale/Monoco
@@ -1,18 +1,18 @@
1
- monoco/main.py,sha256=MhS-vdL05KGZeEYU4XNbJEFXuNyRUyTFiZ1hrmxNCMs,6098
1
+ monoco/main.py,sha256=dM6UutWW2OJBG3yAUuYSXuw5pBfD1216PzwEWweY-lY,5761
2
2
  monoco/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  monoco/cli/project.py,sha256=w4oUWzOV42qh34g4klyzZfTUg6ux0oEdSinMCzmhH3E,2786
4
4
  monoco/cli/workspace.py,sha256=vhRsbjgO6ek6PWYdmhk9EeYW_xWRV196yl7-xPfcRAI,1305
5
5
  monoco/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- monoco/core/config.py,sha256=WJvYtLCLG4sRYcg46-fD7D5Uv32Ex1KQXD-i257hZGs,10781
6
+ monoco/core/config.py,sha256=_0S-ogCAwP5FKpJiAGV2O5_v2fnJoU21NpNYnSse7_0,12767
7
7
  monoco/core/execution.py,sha256=rySL0ueJvTEQ1JhdpumsNBQHJpj08nfaHQMlX-1uh6k,1846
8
8
  monoco/core/feature.py,sha256=oAtQWUHMuqIFbq2gj8sPfYBlJZvMMXZqyUlCMrIVGUE,2007
9
9
  monoco/core/git.py,sha256=i_NKT9_n57S9EKeb8kF2yTEdw70FZ88-lpMqW4lzVds,8228
10
10
  monoco/core/injection.py,sha256=4BuQ5RVozyU99uSOzPwgc6MFMZUcECerTik5lF39I9A,7078
11
- monoco/core/integrations.py,sha256=QRZjCwHb6xudIoxrFSE_gvQKNWlIOXGn-SxZelqqrWw,7667
12
- monoco/core/lsp.py,sha256=aif3iMgfpyCrBL1qlbakJerjT--ePwoWnRa-5CCMMkY,1844
13
- monoco/core/output.py,sha256=9JbCxqxHZlviNJXpUorGVxv_gAn4q72FPgjwBQrPiCI,3502
11
+ monoco/core/integrations.py,sha256=MGw6dCipX2S5GtnboFwVxpkuWMGa_I6T9s0owsIjU4o,7885
12
+ monoco/core/lsp.py,sha256=23OxtVomvvE0GgAbdw_8-DclIac1SzjJGt8urbPKXEA,2006
13
+ monoco/core/output.py,sha256=S5jbOBRuLleBPfypS5nUUoNIUAdub4zJO63RePLb0LU,3787
14
14
  monoco/core/registry.py,sha256=xix21TDeJgRiZ2kvHitnac4RsqMdp1aERpYGSrwfIpY,1180
15
- monoco/core/setup.py,sha256=gx_jrSlRpHxIisuA3JUG-dnHTzIpq4Jq5zz_5Y2MkNY,9313
15
+ monoco/core/setup.py,sha256=5fAsj4HZAC1sG-pEn5hKTZ6JsCAqNa8-eWOs739wpqs,9657
16
16
  monoco/core/skills.py,sha256=5qK-0YlOnNQLqyo6-T4GVBrkjsbrszb5ugXeXRRcQ00,16597
17
17
  monoco/core/state.py,sha256=KlmOn0KXO8g9S_KUIrUylAKdBpyH_1AOBvrYSj_khdE,1884
18
18
  monoco/core/sync.py,sha256=s0qQ5PsVn_IWGWUNThdvNFS-CncztDzsTM3QLupC6Og,8514
@@ -20,7 +20,7 @@ monoco/core/telemetry.py,sha256=DZQGOhvpe0XL34RCDaTZEUhmkD4abBTZumZJQlALzpY,2923
20
20
  monoco/core/workspace.py,sha256=0RWx8H_Kx56TYVrAURTSJW4aWOUylXofkvXBhRNjP_E,3074
21
21
  monoco/core/agent/__init__.py,sha256=tBCm6PDqPFo81yO949nW897INjl7ot46CPup9IrXExE,108
22
22
  monoco/core/agent/action.py,sha256=HpOLzp-mttJY0SDVbRlstDVqjFKozIAdjQdJ4Gp3xiY,5161
23
- monoco/core/agent/adapters.py,sha256=3M6-8uz_WOxXY1bMdu3epQ15v9dc-8Bolq00-mwLxwM,3517
23
+ monoco/core/agent/adapters.py,sha256=s8dzeXZY-m1pb8re5U5O1ED4d6MT9WNFWIeSpHBcmRg,4391
24
24
  monoco/core/agent/protocol.py,sha256=E7y_i2JzYGpzSCRCUIuzu1ATav-Xu1K01ka6Zncm4-o,831
25
25
  monoco/core/agent/state.py,sha256=sRav6uwkXao8yPl08CEB-cqK1EfiDyMnVxoSYxvYcis,3523
26
26
  monoco/core/resources/en/AGENTS.md,sha256=3TpCLNC1s_lIbDfJJBRmmROMoy9sZXu8BOag8M9NXI0,327
@@ -35,8 +35,19 @@ monoco/daemon/reproduce_stats.py,sha256=Q_zAj0Yj8l-77QDdtsLz1kWr68HeO7f1T6xC6VP4
35
35
  monoco/daemon/services.py,sha256=dMhy2ddzGtBBWTGtI14R-2aikENAgPsphxDkno1JAPU,5377
36
36
  monoco/daemon/stats.py,sha256=r-L0k6CdxkAkwLZV3V-jW7PldB9S3uNklQGLCEKA3Sc,4563
37
37
  monoco/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- monoco/features/agent/commands.py,sha256=p2wc05pzEeyPEYpfkHo2-X89IdnDp7hO1LCc2JBTCuI,5898
38
+ monoco/features/agent/commands.py,sha256=31P1_vtg19YZZd7Z5uaDtwzGSpWLzI0sMfCp7Xppt-U,8572
39
+ monoco/features/agent/core.py,sha256=w_zZFsrZNFfV7nEP7HatvsMt_xsJlB8SCFGCCbXPUKo,1704
39
40
  monoco/features/agent/doctor.py,sha256=qqUu_rUjVp7ur1sYpL4VSpw8vwbwbjvXAFvXQP-lbNQ,924
41
+ monoco/features/agent/resources/en/critique.prompty,sha256=lB1jkMsnufrelAzdo2FPD-pQ5agj6atBDnU_kvJNLK0,470
42
+ monoco/features/agent/resources/en/develop.prompty,sha256=T2vOYzf6xoTkImhT8ZmZSYRHev_DnG2mSF8LGji5vsU,480
43
+ monoco/features/agent/resources/en/investigate.prompty,sha256=l4DH4BUU-OCascYNC7rvqArA0COgAAPCLjJCPLV28Io,628
44
+ monoco/features/agent/resources/en/refine.prompty,sha256=PX2V1gUqs7McX_woPMlSVXKabyV0ly6ysBr35pGLa60,422
45
+ monoco/features/agent/resources/en/verify.prompty,sha256=-gb_HxhtdsJZ3_P3TtrhBjTRASkcKtr9v3c8jTQ4DtE,564
46
+ monoco/features/agent/resources/zh/critique.prompty,sha256=lNuQ_9Jl5LasJRwogh_JUM5WK0GNzJI6ZSI0Jy8HY7Y,485
47
+ monoco/features/agent/resources/zh/develop.prompty,sha256=-Mzqye5LZ_IMcNsDQY4xo97zncXaIe-tk9VK9fIxgME,477
48
+ monoco/features/agent/resources/zh/investigate.prompty,sha256=bHCVOxtL68iT8wg06sC0cTwvKCt27YF8CYu5LHMVxWY,650
49
+ monoco/features/agent/resources/zh/refine.prompty,sha256=YSC08M3k4KyN1KcfmSXqxjvzfC3m-GKTzO0LRBpeRFA,469
50
+ monoco/features/agent/resources/zh/verify.prompty,sha256=85yPcrvcaJW31-RD4G2lgXd2CJUTJFAnHlSIUpzApyg,629
40
51
  monoco/features/config/commands.py,sha256=PQaSq81zH4h8d1bFa4B2ANSXSdyjBFqVm_nBvEq1rNE,4889
41
52
  monoco/features/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
53
  monoco/features/i18n/adapter.py,sha256=M9iSEKykEiUe1YobHKmvfEjv7x7KgGuh-6yhgUJuN_s,973
@@ -47,31 +58,39 @@ monoco/features/i18n/resources/en/SKILL.md,sha256=Z8fAAqeMvpLDw1D_9AzZIykS5-HLVM
47
58
  monoco/features/i18n/resources/zh/AGENTS.md,sha256=lKkwLLCADRH7UDq9no4eQY2sRfJrb64JoZ_HNved8vA,175
48
59
  monoco/features/i18n/resources/zh/SKILL.md,sha256=y2UuwhZmCBy0pXGxWLNrhxb94zcNfGEMBA_imJgDqVg,1894
49
60
  monoco/features/issue/adapter.py,sha256=Y-ghwRoSEgm_A-cqY8Un-5srxydXdb9ytlKHLm89eJQ,1265
50
- monoco/features/issue/commands.py,sha256=LjBKplstvSAPxQ-PSvxe1y2sP-6wPrc8O9wGiXNpH_E,32189
51
- monoco/features/issue/core.py,sha256=cAPmJVLMCPMkfMe2WNZVdSQr0Pg6s8sN-SMU7LlhtR0,47108
52
- monoco/features/issue/linter.py,sha256=g98_NKXZFGw0ewBX7g-80CAKvPE0zdazQw1hT2uFtcU,11117
61
+ monoco/features/issue/commands.py,sha256=SUq49ue2KElEe_I6WSADIoYj6-v54NKzOxInOjGsWvk,35495
62
+ monoco/features/issue/core.py,sha256=A-mWDg8aO19G8pibFagY-_6wAVu8bIn0CVCAyabhzB8,46365
63
+ monoco/features/issue/linter.py,sha256=-S3-DK0HKP_3EhSC69za8MyB-bVU4vOkNGM_Ajmjxoo,12056
53
64
  monoco/features/issue/migration.py,sha256=9gtgFi1V1pzwXo0-H4cIoBvSBERIWopXLCB4oSxTQLc,4715
54
- monoco/features/issue/models.py,sha256=pMBLvcGrqO0tpf-7TMnt9VAIzgkq5P79-hqfH8T_EBw,5044
65
+ monoco/features/issue/models.py,sha256=bcQoCyzdgHIQ71tsZzdnxH4-5HgHaF_RlE2Fvg-lVdg,4968
55
66
  monoco/features/issue/monitor.py,sha256=QEN0mqZ3tKwBfMjN87-LdrVoIEe0prA-uMHOBGy1VZk,3476
56
- monoco/features/issue/validator.py,sha256=oFKl3xG0tM0A33LVCHoLbsCK5PE-GlTTfJNcWnVDOPY,11373
67
+ monoco/features/issue/validator.py,sha256=6Q8LyjGpHXOf97q0-3bXvrWFqk7iO6fHhoGemkPTbps,17172
68
+ monoco/features/issue/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
+ monoco/features/issue/domain/lifecycle.py,sha256=-WreIDCeEQPjD82Q4wJMs_S5-9SQHCvGlPgtMllvXGw,4943
70
+ monoco/features/issue/domain/models.py,sha256=pjeb_Lp0zykNzAfrRma26IMkdlxYDQ0IdvNmM_7tepU,5720
71
+ monoco/features/issue/domain/parser.py,sha256=HfJh9uBN7Q7KyeXz1tk3tBjszu8ffStfZf9IS27v0K8,8770
72
+ monoco/features/issue/domain/workspace.py,sha256=AOv7H_he39UnYplCaEex6mdFgpAlGk6T8cDMxKwQLz0,3833
73
+ monoco/features/issue/engine/__init__.py,sha256=bWONZnIb0IkAhw09_pMbyqrDh-oUOLTrNvlQfypHXYw,785
74
+ monoco/features/issue/engine/config.py,sha256=6zGLmnswEAGfYrneG8a0GeA3qr8_BIv_n3Dta8Z7dlU,6420
75
+ monoco/features/issue/engine/machine.py,sha256=8wr5txLlzv0QO2sAlPl7JSPN-VkxJUpRNK25F7L7DVI,7530
76
+ monoco/features/issue/engine/models.py,sha256=u8Z7ilB702Jj6Imv4_vXpP8QTSWEnQdPxv8JA_9g1GU,579
77
+ monoco/features/issue/lsp/__init__.py,sha256=8bl8-WzSj3C4SkPKgVGnCeyemmvHVWBsuMZsJuJggG8,77
78
+ monoco/features/issue/lsp/definition.py,sha256=Y4dX7MmrEfYbWuh85W0djwUj_qed7cDpGadtiXEZDh4,3107
57
79
  monoco/features/issue/resources/en/AGENTS.md,sha256=OjEnkXCqwfMArJfJQhldrQYXqoregfGthyhJeyx7MPw,715
58
80
  monoco/features/issue/resources/en/SKILL.md,sha256=p0vhVpe3xLKg0iXSNofoLNvsq8j2pmv5CD1B2mUeIGk,2732
59
81
  monoco/features/issue/resources/zh/AGENTS.md,sha256=2MLIZ5-i-oBnl7_YAZBBoKkNqANpHj73iw18QQbSm5c,759
60
82
  monoco/features/issue/resources/zh/SKILL.md,sha256=_aXDThhsJag9OLK2X5LRVhaFyMcl4DcZvcSj1_UUkx8,3828
61
- monoco/features/pty/core.py,sha256=eM1EvHQrgExSnatO15pyfhh1VZoz0BBTfNYdXqG8HZ8,5711
62
- monoco/features/pty/router.py,sha256=7h80EPpOuE7hX5ifkxkzffcLZGecd5X8OmNvOji5ToI,5078
63
- monoco/features/pty/server.py,sha256=kw2csMZ_R4_Xx6ta2dbznWtgNZLfrWOAkMp8NjlZYBc,1920
64
83
  monoco/features/skills/__init__.py,sha256=L8YNGPWyyFWq5WqNossfeB0AKHJF_omrn1VzJBrRFcM,23
65
84
  monoco/features/skills/core.py,sha256=mpd0Cq-k2MvHRTPq9saFvZgYXUBGJ9pnK5lUmzUfZbY,3418
66
85
  monoco/features/spike/adapter.py,sha256=npJ4J775Df0DDi-LH-3u2jCuKjTIXyZUbLD0KNvHlcc,1062
67
86
  monoco/features/spike/commands.py,sha256=ctC2Kbe0fgpeDfw5106P0rsKEBDue0rFI4eMNRpXMDw,3880
68
- monoco/features/spike/core.py,sha256=vGMA3Tzuy0tB6r-FjnqcDalpiFWNw9CANSfQ5uV7Hg4,4589
87
+ monoco/features/spike/core.py,sha256=oP1yAalOnoA5fHpf2o4gteKx73XGwZ6G0WrO86z2iWE,4174
69
88
  monoco/features/spike/resources/en/AGENTS.md,sha256=NG3CMnlDk_0J8hnRUcueAM9lgIQr_dZ42R_31-LC48E,306
70
89
  monoco/features/spike/resources/en/SKILL.md,sha256=qKDcVh0D3pDRvfNLh1Bzo4oQU3obpl4tqdlzxeiWYMk,1911
71
90
  monoco/features/spike/resources/zh/AGENTS.md,sha256=5RHNl7fc3RdYYTFH483ojJl_arGPKkyYziOuGgFbqqg,290
72
91
  monoco/features/spike/resources/zh/SKILL.md,sha256=boGPgAfTHbEzdwomRh-qVEveWSgvYaPUdi_4YZVXGHI,1714
73
- monoco_toolkit-0.2.5.dist-info/METADATA,sha256=k2Bb7dwO7fDCUisJeMwmH53rJ7Gx4f44_8VHJF1O30A,3743
74
- monoco_toolkit-0.2.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
75
- monoco_toolkit-0.2.5.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
76
- monoco_toolkit-0.2.5.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
77
- monoco_toolkit-0.2.5.dist-info/RECORD,,
92
+ monoco_toolkit-0.2.6.dist-info/METADATA,sha256=QjAPSxnTtN_ebkZlnWqqDP-xolO1d38oTLhT3LAMlMY,3743
93
+ monoco_toolkit-0.2.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
94
+ monoco_toolkit-0.2.6.dist-info/entry_points.txt,sha256=iYj7FWYBdtClU15-Du1skqD0s6SFSIhJvxJ29VWp8ng,43
95
+ monoco_toolkit-0.2.6.dist-info/licenses/LICENSE,sha256=ACAGGjV6aod4eIlVUTx1q9PZbnZGN5bBwkSs9RHj83s,1071
96
+ monoco_toolkit-0.2.6.dist-info/RECORD,,