monoco-toolkit 0.3.11__py3-none-any.whl → 0.4.0__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 (132) hide show
  1. monoco/core/automation/__init__.py +40 -0
  2. monoco/core/automation/field_watcher.py +296 -0
  3. monoco/core/automation/handlers.py +805 -0
  4. monoco/core/config.py +29 -11
  5. monoco/core/daemon/__init__.py +5 -0
  6. monoco/core/daemon/pid.py +290 -0
  7. monoco/core/git.py +15 -0
  8. monoco/core/hooks/context.py +74 -13
  9. monoco/core/injection.py +86 -8
  10. monoco/core/integrations.py +0 -24
  11. monoco/core/router/__init__.py +17 -0
  12. monoco/core/router/action.py +202 -0
  13. monoco/core/scheduler/__init__.py +63 -0
  14. monoco/core/scheduler/base.py +152 -0
  15. monoco/core/scheduler/engines.py +175 -0
  16. monoco/core/scheduler/events.py +197 -0
  17. monoco/core/scheduler/local.py +377 -0
  18. monoco/core/setup.py +9 -0
  19. monoco/core/sync.py +199 -4
  20. monoco/core/watcher/__init__.py +63 -0
  21. monoco/core/watcher/base.py +382 -0
  22. monoco/core/watcher/dropzone.py +152 -0
  23. monoco/core/watcher/im.py +460 -0
  24. monoco/core/watcher/issue.py +303 -0
  25. monoco/core/watcher/memo.py +192 -0
  26. monoco/core/watcher/task.py +238 -0
  27. monoco/daemon/app.py +3 -60
  28. monoco/daemon/commands.py +459 -25
  29. monoco/daemon/events.py +34 -0
  30. monoco/daemon/scheduler.py +157 -201
  31. monoco/daemon/services.py +42 -243
  32. monoco/features/agent/__init__.py +25 -7
  33. monoco/features/agent/cli.py +91 -57
  34. monoco/features/agent/engines.py +31 -170
  35. monoco/features/agent/resources/en/AGENTS.md +14 -14
  36. monoco/features/agent/resources/en/skills/monoco_role_engineer/SKILL.md +101 -0
  37. monoco/features/agent/resources/en/skills/monoco_role_manager/SKILL.md +95 -0
  38. monoco/features/agent/resources/en/skills/monoco_role_planner/SKILL.md +177 -0
  39. monoco/features/agent/resources/en/skills/monoco_role_reviewer/SKILL.md +139 -0
  40. monoco/features/agent/resources/zh/skills/monoco_role_engineer/SKILL.md +101 -0
  41. monoco/features/agent/resources/zh/skills/monoco_role_manager/SKILL.md +95 -0
  42. monoco/features/agent/resources/zh/skills/monoco_role_planner/SKILL.md +177 -0
  43. monoco/features/agent/resources/zh/skills/monoco_role_reviewer/SKILL.md +139 -0
  44. monoco/features/agent/worker.py +1 -1
  45. monoco/features/hooks/__init__.py +61 -6
  46. monoco/features/hooks/commands.py +281 -271
  47. monoco/features/hooks/dispatchers/__init__.py +23 -0
  48. monoco/features/hooks/dispatchers/agent_dispatcher.py +486 -0
  49. monoco/features/hooks/dispatchers/git_dispatcher.py +478 -0
  50. monoco/features/hooks/manager.py +357 -0
  51. monoco/features/hooks/models.py +262 -0
  52. monoco/features/hooks/parser.py +322 -0
  53. monoco/features/hooks/universal_interceptor.py +503 -0
  54. monoco/features/im/__init__.py +67 -0
  55. monoco/features/im/core.py +782 -0
  56. monoco/features/im/models.py +311 -0
  57. monoco/features/issue/commands.py +133 -60
  58. monoco/features/issue/core.py +385 -40
  59. monoco/features/issue/domain_commands.py +0 -19
  60. monoco/features/issue/resources/en/AGENTS.md +17 -122
  61. monoco/features/issue/resources/hooks/agent/before-tool.sh +102 -0
  62. monoco/features/issue/resources/hooks/agent/session-start.sh +88 -0
  63. monoco/features/issue/resources/hooks/{post-checkout.sh → git/git-post-checkout.sh} +10 -9
  64. monoco/features/issue/resources/hooks/git/git-pre-commit.sh +31 -0
  65. monoco/features/issue/resources/hooks/{pre-push.sh → git/git-pre-push.sh} +7 -13
  66. monoco/features/issue/resources/zh/AGENTS.md +18 -123
  67. monoco/features/memo/cli.py +15 -64
  68. monoco/features/memo/core.py +6 -34
  69. monoco/features/memo/models.py +24 -15
  70. monoco/features/memo/resources/en/AGENTS.md +31 -0
  71. monoco/features/memo/resources/zh/AGENTS.md +28 -5
  72. monoco/features/spike/commands.py +5 -3
  73. monoco/main.py +5 -3
  74. {monoco_toolkit-0.3.11.dist-info → monoco_toolkit-0.4.0.dist-info}/METADATA +1 -1
  75. monoco_toolkit-0.4.0.dist-info/RECORD +170 -0
  76. monoco/core/execution.py +0 -67
  77. monoco/features/agent/apoptosis.py +0 -44
  78. monoco/features/agent/manager.py +0 -127
  79. monoco/features/agent/resources/atoms/atom-code-dev.yaml +0 -61
  80. monoco/features/agent/resources/atoms/atom-issue-lifecycle.yaml +0 -73
  81. monoco/features/agent/resources/atoms/atom-knowledge.yaml +0 -55
  82. monoco/features/agent/resources/atoms/atom-review.yaml +0 -60
  83. monoco/features/agent/resources/en/skills/monoco_atom_core/SKILL.md +0 -99
  84. monoco/features/agent/resources/en/skills/monoco_workflow_agent_engineer/SKILL.md +0 -94
  85. monoco/features/agent/resources/en/skills/monoco_workflow_agent_manager/SKILL.md +0 -93
  86. monoco/features/agent/resources/en/skills/monoco_workflow_agent_planner/SKILL.md +0 -85
  87. monoco/features/agent/resources/en/skills/monoco_workflow_agent_reviewer/SKILL.md +0 -114
  88. monoco/features/agent/resources/workflows/workflow-dev.yaml +0 -83
  89. monoco/features/agent/resources/workflows/workflow-issue-create.yaml +0 -72
  90. monoco/features/agent/resources/workflows/workflow-review.yaml +0 -94
  91. monoco/features/agent/resources/zh/roles/monoco_role_engineer.yaml +0 -49
  92. monoco/features/agent/resources/zh/roles/monoco_role_manager.yaml +0 -46
  93. monoco/features/agent/resources/zh/roles/monoco_role_planner.yaml +0 -46
  94. monoco/features/agent/resources/zh/roles/monoco_role_reviewer.yaml +0 -47
  95. monoco/features/agent/resources/zh/skills/monoco_atom_core/SKILL.md +0 -99
  96. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_engineer/SKILL.md +0 -94
  97. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_manager/SKILL.md +0 -88
  98. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_planner/SKILL.md +0 -259
  99. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_reviewer/SKILL.md +0 -137
  100. monoco/features/agent/session.py +0 -169
  101. monoco/features/artifact/resources/zh/skills/monoco_atom_artifact/SKILL.md +0 -278
  102. monoco/features/glossary/resources/en/skills/monoco_atom_glossary/SKILL.md +0 -35
  103. monoco/features/glossary/resources/zh/skills/monoco_atom_glossary/SKILL.md +0 -35
  104. monoco/features/hooks/adapter.py +0 -67
  105. monoco/features/hooks/core.py +0 -441
  106. monoco/features/i18n/resources/en/skills/monoco_atom_i18n/SKILL.md +0 -96
  107. monoco/features/i18n/resources/en/skills/monoco_workflow_i18n_scan/SKILL.md +0 -105
  108. monoco/features/i18n/resources/zh/skills/monoco_atom_i18n/SKILL.md +0 -96
  109. monoco/features/i18n/resources/zh/skills/monoco_workflow_i18n_scan/SKILL.md +0 -105
  110. monoco/features/issue/resources/en/skills/monoco_atom_issue/SKILL.md +0 -165
  111. monoco/features/issue/resources/en/skills/monoco_workflow_issue_creation/SKILL.md +0 -167
  112. monoco/features/issue/resources/en/skills/monoco_workflow_issue_development/SKILL.md +0 -224
  113. monoco/features/issue/resources/en/skills/monoco_workflow_issue_management/SKILL.md +0 -159
  114. monoco/features/issue/resources/en/skills/monoco_workflow_issue_refinement/SKILL.md +0 -203
  115. monoco/features/issue/resources/hooks/pre-commit.sh +0 -41
  116. monoco/features/issue/resources/zh/skills/monoco_atom_issue_lifecycle/SKILL.md +0 -190
  117. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_creation/SKILL.md +0 -167
  118. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_development/SKILL.md +0 -224
  119. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_management/SKILL.md +0 -159
  120. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_refinement/SKILL.md +0 -203
  121. monoco/features/memo/resources/en/skills/monoco_atom_memo/SKILL.md +0 -77
  122. monoco/features/memo/resources/en/skills/monoco_workflow_note_processing/SKILL.md +0 -140
  123. monoco/features/memo/resources/zh/skills/monoco_atom_memo/SKILL.md +0 -77
  124. monoco/features/memo/resources/zh/skills/monoco_workflow_note_processing/SKILL.md +0 -140
  125. monoco/features/spike/resources/en/skills/monoco_atom_spike/SKILL.md +0 -76
  126. monoco/features/spike/resources/en/skills/monoco_workflow_research/SKILL.md +0 -121
  127. monoco/features/spike/resources/zh/skills/monoco_atom_spike/SKILL.md +0 -76
  128. monoco/features/spike/resources/zh/skills/monoco_workflow_research/SKILL.md +0 -121
  129. monoco_toolkit-0.3.11.dist-info/RECORD +0 -181
  130. {monoco_toolkit-0.3.11.dist-info → monoco_toolkit-0.4.0.dist-info}/WHEEL +0 -0
  131. {monoco_toolkit-0.3.11.dist-info → monoco_toolkit-0.4.0.dist-info}/entry_points.txt +0 -0
  132. {monoco_toolkit-0.3.11.dist-info → monoco_toolkit-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,67 +0,0 @@
1
- """
2
- Feature adapter for Git Hooks management.
3
-
4
- Integrates with Monoco's feature loading system.
5
- """
6
-
7
- from pathlib import Path
8
- from typing import Dict
9
-
10
- from monoco.core.loader import FeatureModule, FeatureMetadata
11
- from monoco.core.feature import IntegrationData
12
-
13
- from .core import GitHooksManager, HookConfig
14
-
15
-
16
- class HooksFeature(FeatureModule):
17
- """Git Hooks management feature module."""
18
-
19
- @property
20
- def metadata(self) -> FeatureMetadata:
21
- return FeatureMetadata(
22
- name="hooks",
23
- version="1.0.0",
24
- description="Git hooks management for Monoco development workflow",
25
- dependencies=["core"],
26
- priority=5, # Load early to be available for other features
27
- )
28
-
29
- def _on_mount(self, context: "FeatureContext") -> None: # type: ignore
30
- """Initialize hooks feature with workspace context."""
31
- # Hooks are installed on-demand via CLI commands
32
- pass
33
-
34
- def integrate(self, root: Path, config: Dict) -> IntegrationData:
35
- """Provide integration data for agent environment."""
36
- # Read hooks-specific prompts if available
37
- base_dir = Path(__file__).parent / "resources"
38
- prompt_file = base_dir / "AGENTS.md"
39
-
40
- content = ""
41
- if prompt_file.exists():
42
- content = prompt_file.read_text(encoding="utf-8").strip()
43
-
44
- return IntegrationData(system_prompts={"Git Hooks": content})
45
-
46
- def create_manager(self, project_root: Path, config: Dict) -> GitHooksManager:
47
- """
48
- Create a GitHooksManager instance from configuration.
49
-
50
- Args:
51
- project_root: Project root directory
52
- config: Configuration dictionary (from workspace.yaml)
53
-
54
- Returns:
55
- Configured GitHooksManager instance
56
- """
57
- hooks_config = config.get("hooks", {})
58
- hook_config = HookConfig(
59
- enabled=hooks_config.get("enabled", True),
60
- enabled_features=hooks_config.get("features", {}),
61
- enabled_hooks=hooks_config.get("hooks", {
62
- "pre-commit": True,
63
- "pre-push": False,
64
- "post-checkout": False,
65
- }),
66
- )
67
- return GitHooksManager(project_root, hook_config)
@@ -1,441 +0,0 @@
1
- """
2
- Core logic for Git Hooks management.
3
-
4
- Implements the distributed hooks + aggregator pattern:
5
- - Each Feature stores its hooks in resources/hooks/{hook-type}.sh
6
- - This module discovers, sorts by priority, and generates final hooks
7
- """
8
-
9
- import os
10
- import stat
11
- from dataclasses import dataclass, field
12
- from enum import Enum
13
- from pathlib import Path
14
- from typing import Dict, List, Optional, Tuple
15
-
16
- from rich.console import Console
17
-
18
- console = Console()
19
-
20
-
21
- class HookType(str, Enum):
22
- """Supported git hook types."""
23
-
24
- PRE_COMMIT = "pre-commit"
25
- PRE_PUSH = "pre-push"
26
- POST_CHECKOUT = "post-checkout"
27
- PRE_REBASE = "pre-rebase"
28
- COMMIT_MSG = "commit-msg"
29
-
30
-
31
- @dataclass
32
- class HookDeclaration:
33
- """
34
- Metadata for a hook script contributed by a Feature.
35
-
36
- Attributes:
37
- hook_type: Type of git hook (pre-commit, pre-push, etc.)
38
- script_path: Path to the hook script file
39
- feature_name: Name of the contributing Feature
40
- priority: Execution priority (lower = earlier, default 100)
41
- """
42
-
43
- hook_type: HookType
44
- script_path: Path
45
- feature_name: str
46
- priority: int = 100
47
-
48
-
49
- @dataclass
50
- class HookConfig:
51
- """Configuration for hooks feature."""
52
-
53
- enabled: bool = True
54
- enabled_features: Dict[str, bool] = field(default_factory=dict)
55
- # Global hook enable/disable by type
56
- enabled_hooks: Dict[str, bool] = field(default_factory=lambda: {
57
- "pre-commit": True,
58
- "pre-push": False, # Disabled by default
59
- "post-checkout": False,
60
- })
61
-
62
-
63
- class GitHooksManager:
64
- """
65
- Manages discovery, aggregation, and installation of git hooks.
66
-
67
- This class implements the aggregator pattern in the distributed hooks architecture:
68
- 1. Discovers hooks from all Features in resources/hooks/
69
- 2. Sorts them by priority
70
- 3. Generates combined hook scripts
71
- 4. Installs them to .git/hooks/
72
- """
73
-
74
- # Header marker to identify Monoco-managed hooks
75
- MONOCO_MARKER = "# Monoco Managed Hook - Auto-generated. Do not edit manually."
76
-
77
- def __init__(self, project_root: Path, config: Optional[HookConfig] = None):
78
- """
79
- Initialize the hooks manager.
80
-
81
- Args:
82
- project_root: Root directory of the project (contains .git/)
83
- config: Optional hooks configuration
84
- """
85
- self.project_root = project_root
86
- self.config = config or HookConfig()
87
- self.git_dir = project_root / ".git"
88
- self.hooks_dir = self.git_dir / "hooks"
89
-
90
- def is_git_repo(self) -> bool:
91
- """Check if project root is a git repository."""
92
- return self.git_dir.exists() and self.git_dir.is_dir()
93
-
94
- def collect_hooks(
95
- self, features_dir: Optional[Path] = None
96
- ) -> Dict[HookType, List[HookDeclaration]]:
97
- """
98
- Discover all hook scripts from Features.
99
-
100
- Scans features/{feature}/resources/hooks/ for hook scripts.
101
-
102
- Args:
103
- features_dir: Root directory containing features (defaults to monoco/features/)
104
-
105
- Returns:
106
- Dictionary mapping hook types to sorted list of hook declarations
107
- """
108
- if features_dir is None:
109
- # Default to monoco/features/ relative to this file
110
- features_dir = Path(__file__).parent.parent
111
-
112
- hooks_by_type: Dict[HookType, List[HookDeclaration]] = {
113
- hook_type: [] for hook_type in HookType
114
- }
115
-
116
- if not features_dir.exists():
117
- return hooks_by_type
118
-
119
- for feature_dir in features_dir.iterdir():
120
- if not feature_dir.is_dir() or feature_dir.name.startswith("_"):
121
- continue
122
-
123
- feature_name = feature_dir.name
124
-
125
- # Check if this feature is enabled in config
126
- if self.config.enabled_features.get(feature_name, True) is False:
127
- continue
128
-
129
- hooks_dir = feature_dir / "resources" / "hooks"
130
- if not hooks_dir.exists():
131
- continue
132
-
133
- # Discover hook scripts
134
- for hook_script in hooks_dir.iterdir():
135
- if not hook_script.is_file():
136
- continue
137
-
138
- # Parse hook type from filename (e.g., pre-commit.sh -> pre-commit)
139
- hook_type = self._parse_hook_type(hook_script.name)
140
- if hook_type is None:
141
- continue
142
-
143
- # Check if this hook type is globally enabled
144
- if not self.config.enabled_hooks.get(hook_type.value, True):
145
- continue
146
-
147
- # Get feature priority from adapter if available
148
- priority = self._get_feature_priority(features_dir, feature_name)
149
-
150
- declaration = HookDeclaration(
151
- hook_type=hook_type,
152
- script_path=hook_script,
153
- feature_name=feature_name,
154
- priority=priority,
155
- )
156
- hooks_by_type[hook_type].append(declaration)
157
-
158
- # Sort each list by priority
159
- for hook_type in hooks_by_type:
160
- hooks_by_type[hook_type].sort(key=lambda h: h.priority)
161
-
162
- return hooks_by_type
163
-
164
- def _parse_hook_type(self, filename: str) -> Optional[HookType]:
165
- """Parse hook type from filename (e.g., 'pre-commit.sh' -> HookType.PRE_COMMIT)."""
166
- # Remove extension
167
- name = filename
168
- for ext in [".sh", ".py", ".bash"]:
169
- if name.endswith(ext):
170
- name = name[: -len(ext)]
171
- break
172
-
173
- try:
174
- return HookType(name)
175
- except ValueError:
176
- return None
177
-
178
- def _get_feature_priority(self, features_dir: Path, feature_name: str) -> int:
179
- """Get feature priority from its adapter metadata."""
180
- adapter_path = features_dir / feature_name / "adapter.py"
181
- if not adapter_path.exists():
182
- return 100
183
-
184
- try:
185
- # Import the adapter module
186
- import importlib.util
187
-
188
- spec = importlib.util.spec_from_file_location(
189
- f"monoco.features.{feature_name}.adapter", adapter_path
190
- )
191
- if spec is None or spec.loader is None:
192
- return 100
193
-
194
- module = importlib.util.module_from_spec(spec)
195
- spec.loader.exec_module(module)
196
-
197
- # Look for Feature class with metadata
198
- for attr_name in dir(module):
199
- attr = getattr(module, attr_name)
200
- if hasattr(attr, "metadata"):
201
- metadata = attr.metadata
202
- if hasattr(metadata, "priority"):
203
- return metadata.priority
204
- except Exception:
205
- pass
206
-
207
- return 100
208
-
209
- def generate_hook_script(self, declarations: List[HookDeclaration]) -> str:
210
- """
211
- Generate a combined hook script from multiple declarations.
212
-
213
- Args:
214
- declarations: List of hook declarations to combine
215
-
216
- Returns:
217
- Generated shell script content
218
- """
219
- lines = [
220
- "#!/bin/sh",
221
- self.MONOCO_MARKER,
222
- "# Generated by Monoco Toolkit",
223
- "",
224
- "# Store the original exit code",
225
- "OVERALL_EXIT=0",
226
- "",
227
- ]
228
-
229
- # Add virtual environment detection
230
- lines.extend([
231
- "# Detect virtual environment",
232
- 'if [ -n "$VIRTUAL_ENV" ]; then',
233
- ' PYTHON_CMD="$VIRTUAL_ENV/bin/python"',
234
- 'elif [ -f "./.venv/bin/python" ]; then',
235
- ' PYTHON_CMD="./.venv/bin/python"',
236
- 'elif [ -f "./venv/bin/python" ]; then',
237
- ' PYTHON_CMD="./venv/bin/python"',
238
- 'else',
239
- ' PYTHON_CMD="python3"',
240
- 'fi',
241
- '',
242
- "# Detect monoco command",
243
- 'MONOCO_CMD="$PYTHON_CMD -m monoco"',
244
- "",
245
- ])
246
-
247
- for decl in declarations:
248
- lines.extend([
249
- f"# --- Hook from {decl.feature_name} (priority: {decl.priority}) ---",
250
- f'echo "[Monoco] Running {decl.hook_type.value} hook: {decl.feature_name}"',
251
- ])
252
-
253
- # Read and include the hook script content
254
- try:
255
- content = decl.script_path.read_text(encoding="utf-8")
256
- # Remove shebang if present since we're in a combined script
257
- lines_content = content.splitlines()
258
- if lines_content and lines_content[0].startswith("#!/"):
259
- lines_content = lines_content[1:]
260
-
261
- for line in lines_content:
262
- lines.append(line)
263
- except Exception as e:
264
- lines.append(f'echo "[Monoco] Error reading hook: {e}" >&2')
265
-
266
- lines.extend([
267
- "# Capture exit code",
268
- "HOOK_EXIT=$?",
269
- 'if [ $HOOK_EXIT -ne 0 ]; then',
270
- ' echo "[Monoco] Hook failed with exit code $HOOK_EXIT"',
271
- " OVERALL_EXIT=$HOOK_EXIT",
272
- "fi",
273
- "",
274
- ])
275
-
276
- lines.extend([
277
- "# Exit with the first non-zero exit code",
278
- "exit $OVERALL_EXIT",
279
- "",
280
- ])
281
-
282
- return "\n".join(lines)
283
-
284
- def install(self, features_dir: Optional[Path] = None) -> Dict[HookType, bool]:
285
- """
286
- Install all discovered hooks to .git/hooks/.
287
-
288
- Args:
289
- features_dir: Root directory containing features
290
-
291
- Returns:
292
- Dictionary mapping hook types to success status
293
- """
294
- results = {}
295
-
296
- if not self.is_git_repo():
297
- console.print("[yellow]Warning: Not a git repository. Skipping hook installation.[/yellow]")
298
- return results
299
-
300
- self.hooks_dir.mkdir(exist_ok=True)
301
-
302
- # Collect all hooks
303
- hooks_by_type = self.collect_hooks(features_dir)
304
-
305
- for hook_type, declarations in hooks_by_type.items():
306
- if not declarations:
307
- continue
308
-
309
- # Check if hook type is enabled
310
- if not self.config.enabled_hooks.get(hook_type.value, True):
311
- continue
312
-
313
- hook_path = self.hooks_dir / hook_type.value
314
-
315
- # Check for existing non-monoco hook
316
- if hook_path.exists():
317
- try:
318
- content = hook_path.read_text(encoding="utf-8")
319
- if self.MONOCO_MARKER not in content:
320
- console.print(
321
- f"[yellow]Warning: {hook_type.value} already exists and is not managed by Monoco. Skipping.[/yellow]"
322
- )
323
- results[hook_type] = False
324
- continue
325
- except Exception as e:
326
- console.print(
327
- f"[yellow]Warning: Cannot read existing {hook_type.value}: {e}. Skipping.[/yellow]"
328
- )
329
- results[hook_type] = False
330
- continue
331
-
332
- # Generate and write hook script
333
- script_content = self.generate_hook_script(declarations)
334
-
335
- try:
336
- hook_path.write_text(script_content, encoding="utf-8")
337
- # Make executable
338
- hook_path.chmod(hook_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
339
- console.print(f"[green]✓ Installed {hook_type.value} hook ({len(declarations)} scripts)[/green]")
340
- results[hook_type] = True
341
- except Exception as e:
342
- console.print(f"[red]✗ Failed to install {hook_type.value}: {e}[/red]")
343
- results[hook_type] = False
344
-
345
- return results
346
-
347
- def uninstall(self) -> Dict[HookType, bool]:
348
- """
349
- Uninstall all Monoco-managed hooks from .git/hooks/.
350
-
351
- Returns:
352
- Dictionary mapping hook types to success status
353
- """
354
- results = {}
355
-
356
- if not self.is_git_repo():
357
- console.print("[yellow]Warning: Not a git repository.[/yellow]")
358
- return results
359
-
360
- for hook_type in HookType:
361
- hook_path = self.hooks_dir / hook_type.value
362
-
363
- if not hook_path.exists():
364
- continue
365
-
366
- try:
367
- content = hook_path.read_text(encoding="utf-8")
368
- if self.MONOCO_MARKER in content:
369
- hook_path.unlink()
370
- console.print(f"[green]✓ Removed {hook_type.value} hook[/green]")
371
- results[hook_type] = True
372
- else:
373
- console.print(
374
- f"[dim]Skipping {hook_type.value}: not managed by Monoco[/dim]"
375
- )
376
- results[hook_type] = False
377
- except Exception as e:
378
- console.print(f"[red]✗ Failed to remove {hook_type.value}: {e}[/red]")
379
- results[hook_type] = False
380
-
381
- return results
382
-
383
- def get_status(self, features_dir: Optional[Path] = None) -> Dict[str, any]:
384
- """
385
- Get current hooks installation status.
386
-
387
- Args:
388
- features_dir: Root directory containing features
389
-
390
- Returns:
391
- Status dictionary with installed hooks and discovered scripts
392
- """
393
- status = {
394
- "is_git_repo": self.is_git_repo(),
395
- "hooks_dir": str(self.hooks_dir) if self.is_git_repo() else None,
396
- "installed": {},
397
- "discovered": {},
398
- "config": {
399
- "enabled": self.config.enabled,
400
- "enabled_features": self.config.enabled_features,
401
- "enabled_hooks": self.config.enabled_hooks,
402
- },
403
- }
404
-
405
- if not self.is_git_repo():
406
- return status
407
-
408
- # Check installed hooks
409
- for hook_type in HookType:
410
- hook_path = self.hooks_dir / hook_type.value
411
- if hook_path.exists():
412
- try:
413
- content = hook_path.read_text(encoding="utf-8")
414
- is_monoco = self.MONOCO_MARKER in content
415
- status["installed"][hook_type.value] = {
416
- "exists": True,
417
- "managed_by_monoco": is_monoco,
418
- }
419
- except Exception:
420
- status["installed"][hook_type.value] = {
421
- "exists": True,
422
- "managed_by_monoco": False,
423
- "error": "Cannot read file",
424
- }
425
- else:
426
- status["installed"][hook_type.value] = {"exists": False}
427
-
428
- # Discover available hooks
429
- hooks_by_type = self.collect_hooks(features_dir)
430
- for hook_type, declarations in hooks_by_type.items():
431
- if declarations:
432
- status["discovered"][hook_type.value] = [
433
- {
434
- "feature": d.feature_name,
435
- "path": str(d.script_path),
436
- "priority": d.priority,
437
- }
438
- for d in declarations
439
- ]
440
-
441
- return status
@@ -1,96 +0,0 @@
1
- ---
2
- name: monoco_atom_i18n
3
- description: Internationalization quality control for documentation. Ensures multi-language documentation stays synchronized.
4
- type: atom
5
- version: 1.0.0
6
- ---
7
-
8
- # Documentation I18n
9
-
10
- Manage internationalization for Monoco project documentation.
11
-
12
- ## Overview
13
-
14
- The I18n feature provides:
15
-
16
- - **Automatic scanning** for missing translations
17
- - **Standardized structure** for multi-language documentation
18
- - **Quality control** to maintain documentation parity
19
-
20
- ## Key Commands
21
-
22
- ### Scan for Missing Translations
23
-
24
- ```bash
25
- monoco i18n scan
26
- ```
27
-
28
- Scans the project for markdown files and reports missing translations.
29
-
30
- **Output**:
31
-
32
- - Lists source files without corresponding translations
33
- - Shows which target languages are missing
34
- - Respects `.gitignore` and default exclusions
35
-
36
- ## Configuration
37
-
38
- I18n settings are configured in `.monoco/config.yaml`:
39
-
40
- ```yaml
41
- i18n:
42
- source_lang: en # Source language code
43
- target_langs: # Target language codes
44
- - zh
45
- - ja
46
- ```
47
-
48
- ## Documentation Structure
49
-
50
- ### Root Files (Suffix Pattern)
51
-
52
- For files in the project root:
53
-
54
- - Source: `README.md`
55
- - Chinese: `README_ZH.md`
56
- - Japanese: `README_JA.md`
57
-
58
- ### Subdirectory Files (Directory Pattern)
59
-
60
- For files in `docs/` or other directories:
61
-
62
- ```
63
- docs/
64
- ├── en/
65
- │ ├── guide.md
66
- │ └── api.md
67
- ├── zh/
68
- │ ├── guide.md
69
- │ └── api.md
70
- └── ja/
71
- ├── guide.md
72
- └── api.md
73
- ```
74
-
75
- ## Exclusion Rules
76
-
77
- The following are automatically excluded from i18n scanning:
78
-
79
- - `.gitignore` patterns (respected automatically)
80
- - `.references/` directory
81
- - Build artifacts (`dist/`, `build/`, `node_modules/`)
82
- - `Issues/` directory
83
-
84
- ## Best Practices
85
-
86
- 1. **Create English First**: Write documentation in the source language first
87
- 2. **Follow Naming Convention**: Use the appropriate pattern (suffix or directory)
88
- 3. **Run Scan Regularly**: Use `monoco i18n scan` to verify coverage
89
- 4. **Commit All Languages**: Keep translations in version control
90
-
91
- ## Workflow
92
-
93
- 1. Write documentation in source language (e.g., English)
94
- 2. Create translation files following the naming convention
95
- 3. Run `monoco i18n scan` to verify all translations exist
96
- 4. Fix any missing translations reported by the scan
@@ -1,105 +0,0 @@
1
- ---
2
- name: monoco_workflow_i18n_scan
3
- description: I18n Scan Workflow (Flow Skill). Defines the standard operational process from scanning missing translations to generating translation tasks, ensuring multilingual documentation quality.
4
- type: workflow
5
- domain: i18n
6
- version: 1.0.0
7
- ---
8
-
9
- # I18n Scan Workflow
10
-
11
- Standardized workflow for I18n scanning, ensuring the "Scan → Identify → Generate Tasks" process.
12
-
13
- ## Workflow State Machine
14
-
15
- ```mermaid
16
- stateDiagram-v2
17
- [*] --> Scan: Trigger scan
18
-
19
- Scan --> Identify: Scan completed
20
- Scan --> Scan: Configuration error<br/>(fix configuration)
21
-
22
- Identify --> GenerateTasks: Missing found
23
- Identify --> [*]: No missing<br/>(completed)
24
-
25
- GenerateTasks --> [*]: Task generation completed
26
- ```
27
-
28
- ## Execution Steps
29
-
30
- ### 1. Scan (Scanning)
31
-
32
- - **Goal**: Scan all documents in the project, identify translation coverage
33
- - **Input**: Project files, i18n configuration
34
- - **Output**: Scan report
35
- - **Checkpoints**:
36
- - [ ] Check i18n configuration in `.monoco/config.yaml`
37
- - [ ] Run `monoco i18n scan`
38
- - [ ] Confirm source and target language settings are correct
39
- - [ ] Verify exclusion rules (.gitignore, build directories, etc.)
40
-
41
- ### 2. Identify (Identify Missing)
42
-
43
- - **Goal**: Analyze scan results, identify specific missing translations
44
- - **Strategy**: Compare source and target files
45
- - **Checkpoints**:
46
- - [ ] List all source files with missing translations
47
- - [ ] Identify missing target languages
48
- - [ ] Assess impact scope of missing translations
49
- - [ ] Sort by priority (core documents first)
50
-
51
- ### 3. Generate Tasks (Generate Tasks)
52
-
53
- - **Goal**: Create tracking tasks for missing translations
54
- - **Strategy**: Create Issue or memo based on missing status
55
- - **Checkpoints**:
56
- - [ ] Create Feature Issue for core document missing translations
57
- - [ ] Create Memo reminder for secondary document missing translations
58
- - [ ] Annotate file paths requiring translation in the Issue
59
- - [ ] Set reasonable priority and deadline
60
-
61
- ## Decision Branches
62
-
63
- | Condition | Action |
64
- |-----------|--------|
65
- | Configuration error | Fix `.monoco/config.yaml`, rescan |
66
- | No missing translations | Process completed, no further action needed |
67
- | Large amount missing | Create Epic, split into multiple Features |
68
- | Critical document missing | High priority, create Issue immediately |
69
-
70
- ## Compliance Requirements
71
-
72
- - **Required**: Verify i18n configuration is correct before scanning
73
- - **Required**: All core documents must have corresponding translations
74
- - **Recommended**: Run scans regularly (e.g., weekly)
75
- - **Recommended**: Bind translation tasks with feature development
76
-
77
- ## Related Commands
78
-
79
- ```bash
80
- # Scan for missing translations
81
- monoco i18n scan
82
-
83
- # Create translation task
84
- monoco issue create feature -t "Translate {filename} to {lang}"
85
-
86
- # Add memo
87
- monoco memo add "Needs translation: {filepath}"
88
- ```
89
-
90
- ## Output Example
91
-
92
- After scanning completes, a report like the following should be generated:
93
-
94
- ```
95
- I18n Scan Report
96
- ================
97
- Source Language: en
98
- Target Languages: zh, ja
99
-
100
- Missing Translations:
101
- - docs/guide.md → zh/guide.md [MISSING]
102
- - docs/api.md → ja/api.md [MISSING]
103
-
104
- Coverage: 85%
105
- ```