monoco-toolkit 0.3.12__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 (120) hide show
  1. monoco/core/automation/__init__.py +0 -11
  2. monoco/core/automation/handlers.py +108 -26
  3. monoco/core/config.py +28 -10
  4. monoco/core/daemon/__init__.py +5 -0
  5. monoco/core/daemon/pid.py +290 -0
  6. monoco/core/injection.py +86 -8
  7. monoco/core/integrations.py +0 -24
  8. monoco/core/router/__init__.py +1 -39
  9. monoco/core/router/action.py +3 -142
  10. monoco/core/scheduler/events.py +28 -2
  11. monoco/core/setup.py +9 -0
  12. monoco/core/sync.py +199 -4
  13. monoco/core/watcher/__init__.py +6 -0
  14. monoco/core/watcher/base.py +18 -1
  15. monoco/core/watcher/im.py +460 -0
  16. monoco/core/watcher/memo.py +40 -48
  17. monoco/daemon/app.py +3 -60
  18. monoco/daemon/commands.py +459 -25
  19. monoco/daemon/scheduler.py +1 -16
  20. monoco/daemon/services.py +15 -0
  21. monoco/features/agent/resources/en/AGENTS.md +14 -14
  22. monoco/features/agent/resources/en/skills/monoco_role_engineer/SKILL.md +101 -0
  23. monoco/features/agent/resources/en/skills/monoco_role_manager/SKILL.md +95 -0
  24. monoco/features/agent/resources/en/skills/monoco_role_planner/SKILL.md +177 -0
  25. monoco/features/agent/resources/en/skills/monoco_role_reviewer/SKILL.md +139 -0
  26. monoco/features/agent/resources/zh/skills/monoco_role_engineer/SKILL.md +101 -0
  27. monoco/features/agent/resources/zh/skills/monoco_role_manager/SKILL.md +95 -0
  28. monoco/features/agent/resources/zh/skills/monoco_role_planner/SKILL.md +177 -0
  29. monoco/features/agent/resources/zh/skills/monoco_role_reviewer/SKILL.md +139 -0
  30. monoco/features/hooks/__init__.py +61 -6
  31. monoco/features/hooks/commands.py +281 -271
  32. monoco/features/hooks/dispatchers/__init__.py +23 -0
  33. monoco/features/hooks/dispatchers/agent_dispatcher.py +486 -0
  34. monoco/features/hooks/dispatchers/git_dispatcher.py +478 -0
  35. monoco/features/hooks/manager.py +357 -0
  36. monoco/features/hooks/models.py +262 -0
  37. monoco/features/hooks/parser.py +322 -0
  38. monoco/features/hooks/universal_interceptor.py +503 -0
  39. monoco/features/im/__init__.py +67 -0
  40. monoco/features/im/core.py +782 -0
  41. monoco/features/im/models.py +311 -0
  42. monoco/features/issue/commands.py +65 -50
  43. monoco/features/issue/core.py +199 -99
  44. monoco/features/issue/domain_commands.py +0 -19
  45. monoco/features/issue/resources/en/AGENTS.md +17 -122
  46. monoco/features/issue/resources/hooks/agent/before-tool.sh +102 -0
  47. monoco/features/issue/resources/hooks/agent/session-start.sh +88 -0
  48. monoco/features/issue/resources/hooks/{post-checkout.sh → git/git-post-checkout.sh} +10 -9
  49. monoco/features/issue/resources/hooks/git/git-pre-commit.sh +31 -0
  50. monoco/features/issue/resources/hooks/{pre-push.sh → git/git-pre-push.sh} +7 -13
  51. monoco/features/issue/resources/zh/AGENTS.md +18 -123
  52. monoco/features/memo/cli.py +15 -64
  53. monoco/features/memo/core.py +6 -34
  54. monoco/features/memo/models.py +24 -15
  55. monoco/features/memo/resources/en/AGENTS.md +31 -0
  56. monoco/features/memo/resources/zh/AGENTS.md +28 -5
  57. monoco/main.py +5 -3
  58. {monoco_toolkit-0.3.12.dist-info → monoco_toolkit-0.4.0.dist-info}/METADATA +1 -1
  59. monoco_toolkit-0.4.0.dist-info/RECORD +170 -0
  60. monoco/core/automation/config.py +0 -338
  61. monoco/core/execution.py +0 -67
  62. monoco/core/executor/__init__.py +0 -38
  63. monoco/core/executor/agent_action.py +0 -254
  64. monoco/core/executor/git_action.py +0 -303
  65. monoco/core/executor/im_action.py +0 -309
  66. monoco/core/executor/pytest_action.py +0 -218
  67. monoco/core/router/router.py +0 -392
  68. monoco/features/agent/resources/atoms/atom-code-dev.yaml +0 -61
  69. monoco/features/agent/resources/atoms/atom-issue-lifecycle.yaml +0 -73
  70. monoco/features/agent/resources/atoms/atom-knowledge.yaml +0 -55
  71. monoco/features/agent/resources/atoms/atom-review.yaml +0 -60
  72. monoco/features/agent/resources/en/skills/monoco_atom_core/SKILL.md +0 -99
  73. monoco/features/agent/resources/en/skills/monoco_workflow_agent_engineer/SKILL.md +0 -94
  74. monoco/features/agent/resources/en/skills/monoco_workflow_agent_manager/SKILL.md +0 -93
  75. monoco/features/agent/resources/en/skills/monoco_workflow_agent_planner/SKILL.md +0 -85
  76. monoco/features/agent/resources/en/skills/monoco_workflow_agent_reviewer/SKILL.md +0 -114
  77. monoco/features/agent/resources/workflows/workflow-dev.yaml +0 -83
  78. monoco/features/agent/resources/workflows/workflow-issue-create.yaml +0 -72
  79. monoco/features/agent/resources/workflows/workflow-review.yaml +0 -94
  80. monoco/features/agent/resources/zh/roles/monoco_role_engineer.yaml +0 -49
  81. monoco/features/agent/resources/zh/roles/monoco_role_manager.yaml +0 -46
  82. monoco/features/agent/resources/zh/roles/monoco_role_planner.yaml +0 -46
  83. monoco/features/agent/resources/zh/roles/monoco_role_reviewer.yaml +0 -47
  84. monoco/features/agent/resources/zh/skills/monoco_atom_core/SKILL.md +0 -99
  85. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_engineer/SKILL.md +0 -94
  86. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_manager/SKILL.md +0 -88
  87. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_planner/SKILL.md +0 -259
  88. monoco/features/agent/resources/zh/skills/monoco_workflow_agent_reviewer/SKILL.md +0 -137
  89. monoco/features/artifact/resources/zh/skills/monoco_atom_artifact/SKILL.md +0 -278
  90. monoco/features/glossary/resources/en/skills/monoco_atom_glossary/SKILL.md +0 -35
  91. monoco/features/glossary/resources/zh/skills/monoco_atom_glossary/SKILL.md +0 -35
  92. monoco/features/hooks/adapter.py +0 -67
  93. monoco/features/hooks/core.py +0 -441
  94. monoco/features/i18n/resources/en/skills/monoco_atom_i18n/SKILL.md +0 -96
  95. monoco/features/i18n/resources/en/skills/monoco_workflow_i18n_scan/SKILL.md +0 -105
  96. monoco/features/i18n/resources/zh/skills/monoco_atom_i18n/SKILL.md +0 -96
  97. monoco/features/i18n/resources/zh/skills/monoco_workflow_i18n_scan/SKILL.md +0 -105
  98. monoco/features/issue/resources/en/skills/monoco_atom_issue/SKILL.md +0 -165
  99. monoco/features/issue/resources/en/skills/monoco_workflow_issue_creation/SKILL.md +0 -167
  100. monoco/features/issue/resources/en/skills/monoco_workflow_issue_development/SKILL.md +0 -224
  101. monoco/features/issue/resources/en/skills/monoco_workflow_issue_management/SKILL.md +0 -159
  102. monoco/features/issue/resources/en/skills/monoco_workflow_issue_refinement/SKILL.md +0 -203
  103. monoco/features/issue/resources/hooks/pre-commit.sh +0 -41
  104. monoco/features/issue/resources/zh/skills/monoco_atom_issue_lifecycle/SKILL.md +0 -190
  105. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_creation/SKILL.md +0 -167
  106. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_development/SKILL.md +0 -224
  107. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_management/SKILL.md +0 -159
  108. monoco/features/issue/resources/zh/skills/monoco_workflow_issue_refinement/SKILL.md +0 -203
  109. monoco/features/memo/resources/en/skills/monoco_atom_memo/SKILL.md +0 -77
  110. monoco/features/memo/resources/en/skills/monoco_workflow_note_processing/SKILL.md +0 -140
  111. monoco/features/memo/resources/zh/skills/monoco_atom_memo/SKILL.md +0 -77
  112. monoco/features/memo/resources/zh/skills/monoco_workflow_note_processing/SKILL.md +0 -140
  113. monoco/features/spike/resources/en/skills/monoco_atom_spike/SKILL.md +0 -76
  114. monoco/features/spike/resources/en/skills/monoco_workflow_research/SKILL.md +0 -121
  115. monoco/features/spike/resources/zh/skills/monoco_atom_spike/SKILL.md +0 -76
  116. monoco/features/spike/resources/zh/skills/monoco_workflow_research/SKILL.md +0 -121
  117. monoco_toolkit-0.3.12.dist-info/RECORD +0 -202
  118. {monoco_toolkit-0.3.12.dist-info → monoco_toolkit-0.4.0.dist-info}/WHEEL +0 -0
  119. {monoco_toolkit-0.3.12.dist-info → monoco_toolkit-0.4.0.dist-info}/entry_points.txt +0 -0
  120. {monoco_toolkit-0.3.12.dist-info → monoco_toolkit-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,102 @@
1
+ #!/bin/bash
2
+ # JIT Hook: before-tool for Issue workflow compliance
3
+ # Triggers: Bash, WriteFile tool calls
4
+ # Purpose: Check branch compliance before code modifications
5
+
6
+ ---
7
+ type: agent
8
+ provider: claude-code
9
+ event: before-tool
10
+ matcher: ["Bash", "WriteFile"]
11
+ priority: 10
12
+ description: "Check code modification compliance (branch, sync-files)"
13
+ ---
14
+
15
+ # Get current branch
16
+ CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
17
+
18
+ # Check if we're on a protected branch
19
+ if [[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]]; then
20
+ cat << 'EOF'
21
+ {
22
+ "decision": "ask",
23
+ "reason": "Protected branch detected",
24
+ "message": "🛑 You are currently on the main/master branch. Direct modifications are prohibited.",
25
+ "metadata": {
26
+ "additionalContext": {
27
+ "current_branch": "main",
28
+ "reminders": [
29
+ "Use 'monoco issue start <ID> --branch' to create a feature branch",
30
+ "Never modify code directly on main/master branch"
31
+ ]
32
+ }
33
+ }
34
+ }
35
+ EOF
36
+ exit 0
37
+ fi
38
+
39
+ # Check if branch name follows feature branch pattern (contains FEAT-, FIX-, CHORE-)
40
+ if [[ "$CURRENT_BRANCH" =~ (FEAT|FIX|CHORE)-[0-9]+ ]]; then
41
+ ISSUE_ID="${BASH_REMATCH[0]}"
42
+
43
+ # Check for uncommitted changes that might need sync-files
44
+ if git diff --quiet HEAD 2>/dev/null; then
45
+ # No uncommitted changes
46
+ cat << EOF
47
+ {
48
+ "decision": "allow",
49
+ "reason": "Branch check passed",
50
+ "message": "✅ Current in feature branch: $CURRENT_BRANCH",
51
+ "metadata": {
52
+ "additionalContext": {
53
+ "current_issue": "$ISSUE_ID",
54
+ "current_branch": "$CURRENT_BRANCH",
55
+ "reminders": [
56
+ "Run 'monoco issue sync-files' after modifying files",
57
+ "Run 'monoco issue submit $ISSUE_ID' when ready for review"
58
+ ]
59
+ }
60
+ }
61
+ }
62
+ EOF
63
+ else
64
+ # Has uncommitted changes
65
+ cat << EOF
66
+ {
67
+ "decision": "allow",
68
+ "reason": "Branch check passed with pending changes",
69
+ "message": "⚠️ You have uncommitted changes. Remember to run sync-files before submit.",
70
+ "metadata": {
71
+ "additionalContext": {
72
+ "current_issue": "$ISSUE_ID",
73
+ "current_branch": "$CURRENT_BRANCH",
74
+ "uncommitted_changes": true,
75
+ "reminders": [
76
+ "Run 'monoco issue sync-files' to update files field",
77
+ "Run 'monoco issue submit $ISSUE_ID' when ready for review"
78
+ ]
79
+ }
80
+ }
81
+ }
82
+ EOF
83
+ fi
84
+ else
85
+ # Not on a feature branch
86
+ cat << EOF
87
+ {
88
+ "decision": "ask",
89
+ "reason": "Not on feature branch",
90
+ "message": "⚠️ You are on '$CURRENT_BRANCH' which does not appear to be a feature branch.",
91
+ "metadata": {
92
+ "additionalContext": {
93
+ "current_branch": "$CURRENT_BRANCH",
94
+ "reminders": [
95
+ "Use 'monoco issue start <ID> --branch' to work on an Issue",
96
+ "Or ensure your branch name contains the Issue ID (e.g., FEAT-0123-xxx)"
97
+ ]
98
+ }
99
+ }
100
+ }
101
+ EOF
102
+ fi
@@ -0,0 +1,88 @@
1
+ #!/bin/bash
2
+ # JIT Hook: session-start for Issue context injection
3
+ # Triggers: At the beginning of agent session
4
+ # Purpose: Inject current Issue context into agent session
5
+
6
+ ---
7
+ type: agent
8
+ provider: claude-code
9
+ event: session-start
10
+ priority: 5
11
+ description: "Inject current Issue context into session"
12
+ ---
13
+
14
+ # Get current branch
15
+ CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
16
+
17
+ # Try to extract Issue ID from branch name
18
+ if [[ "$CURRENT_BRANCH" =~ (FEAT|FIX|CHORE|EPIC)-[0-9]+ ]]; then
19
+ ISSUE_ID="${BASH_REMATCH[0]}"
20
+
21
+ # Try to find the Issue file
22
+ ISSUE_FILE=$(find /Users/indenscale/Documents/Projects/Monoco/Toolkit/Issues -name "${ISSUE_ID}*.md" 2>/dev/null | head -1)
23
+
24
+ if [[ -n "$ISSUE_FILE" && -f "$ISSUE_FILE" ]]; then
25
+ # Extract issue metadata from front matter
26
+ ISSUE_STATUS=$(grep -E "^status:" "$ISSUE_FILE" | head -1 | cut -d: -f2 | tr -d ' ' || echo "unknown")
27
+ ISSUE_STAGE=$(grep -E "^stage:" "$ISSUE_FILE" | head -1 | cut -d: -f2 | tr -d ' ' || echo "unknown")
28
+ ISSUE_TITLE=$(grep -E "^title:" "$ISSUE_FILE" | head -1 | cut -d: -f2- | sed 's/^ *//' || echo "unknown")
29
+
30
+ cat << EOF
31
+ {
32
+ "decision": "allow",
33
+ "reason": "Issue context loaded",
34
+ "message": "📋 Active Issue: $ISSUE_ID - $ISSUE_TITLE",
35
+ "metadata": {
36
+ "additionalContext": {
37
+ "current_issue": "$ISSUE_ID",
38
+ "issue_title": "$ISSUE_TITLE",
39
+ "issue_status": "$ISSUE_STATUS",
40
+ "issue_stage": "$ISSUE_STAGE",
41
+ "current_branch": "$CURRENT_BRANCH",
42
+ "reminders": [
43
+ "Issue: $ISSUE_ID ($ISSUE_STATUS / $ISSUE_STAGE)",
44
+ "Run 'monoco issue sync-files' after file modifications",
45
+ "Run 'monoco issue submit $ISSUE_ID' when ready for review"
46
+ ]
47
+ }
48
+ }
49
+ }
50
+ EOF
51
+ else
52
+ # Issue file not found
53
+ cat << EOF
54
+ {
55
+ "decision": "allow",
56
+ "reason": "Partial context loaded",
57
+ "message": "📋 Detected Issue ID: $ISSUE_ID from branch",
58
+ "metadata": {
59
+ "additionalContext": {
60
+ "current_issue": "$ISSUE_ID",
61
+ "current_branch": "$CURRENT_BRANCH",
62
+ "reminders": [
63
+ "Working on: $ISSUE_ID",
64
+ "Run 'monoco issue sync-files' after file modifications"
65
+ ]
66
+ }
67
+ }
68
+ }
69
+ EOF
70
+ fi
71
+ else
72
+ # Not on a feature branch
73
+ cat << EOF
74
+ {
75
+ "decision": "allow",
76
+ "reason": "No active Issue detected",
77
+ "message": "ℹ️ No active Issue detected from branch name",
78
+ "metadata": {
79
+ "additionalContext": {
80
+ "current_branch": "$CURRENT_BRANCH",
81
+ "reminders": [
82
+ "To start working: monoco issue start <ID> --branch"
83
+ ]
84
+ }
85
+ }
86
+ }
87
+ EOF
88
+ fi
@@ -1,8 +1,10 @@
1
1
  #!/bin/sh
2
- # Issue Feature Post-Checkout Hook
3
- # Automatically syncs issue status when switching branches
4
-
5
- echo "[Monoco] Syncing issue status after branch checkout..."
2
+ # ---
3
+ # type: git
4
+ # event: post-checkout
5
+ # description: "Sync issue status and files after branch checkout"
6
+ # priority: 100
7
+ # ---
6
8
 
7
9
  # Get the previous and current HEAD
8
10
  PREVIOUS_HEAD="$1"
@@ -11,29 +13,28 @@ BRANCH_SWITCH="$3" # 1 if branch switch, 0 if file checkout
11
13
 
12
14
  # Only sync on actual branch switches, not file checkouts
13
15
  if [ "$BRANCH_SWITCH" != "1" ]; then
14
- echo "[Monoco] File checkout detected, skipping issue sync."
15
16
  exit 0
16
17
  fi
17
18
 
19
+ echo "[Monoco] Syncing issue status after branch checkout..."
20
+
18
21
  # Get current branch name
19
22
  CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "HEAD")
20
23
 
21
24
  echo "[Monoco] Switched to branch: $CURRENT_BRANCH"
22
25
 
23
26
  # Try to extract issue ID from branch name
24
- # Common patterns: FEAT-123, feat/FEAT-123, feature/FEAT-123, fix/FEAT-123
25
27
  ISSUE_ID=$(echo "$CURRENT_BRANCH" | grep -oE '[A-Z]+-[0-9]+' | head -1)
26
28
 
27
29
  if [ -n "$ISSUE_ID" ]; then
28
30
  echo "[Monoco] Detected issue ID from branch: $ISSUE_ID"
29
-
30
31
  # Check if issue exists and update its isolation ref if needed
31
- $MONOCO_CMD issue sync-isolation "$ISSUE_ID" --branch "$CURRENT_BRANCH" 2>/dev/null || true
32
+ monoco issue sync-isolation "$ISSUE_ID" --branch "$CURRENT_BRANCH" 2>/dev/null || true
32
33
  fi
33
34
 
34
35
  # Run general sync to ensure files field is up to date
35
36
  echo "[Monoco] Running issue file sync..."
36
- $MONOCO_CMD issue sync-files 2>/dev/null || true
37
+ monoco issue sync-files 2>/dev/null || true
37
38
 
38
39
  echo "[Monoco] Issue sync complete."
39
40
  exit 0
@@ -0,0 +1,31 @@
1
+ #!/bin/sh
2
+ # ---
3
+ # type: git
4
+ # event: pre-commit
5
+ # matcher:
6
+ # - "Issues/**/*.md"
7
+ # description: "Lint staged Issue files for integrity"
8
+ # priority: 100
9
+ # ---
10
+
11
+ echo "[Monoco] Checking Issue integrity..."
12
+
13
+ # Get the list of staged Issue files
14
+ STAGED_ISSUES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^Issues/.*\.md$' || true)
15
+
16
+ if [ -z "$STAGED_ISSUES" ]; then
17
+ exit 0
18
+ fi
19
+
20
+ # Run lint on staged Issue files
21
+ echo "[Monoco] Running lint on staged Issue files..."
22
+
23
+ for file in $STAGED_ISSUES; do
24
+ monoco issue lint "$file"
25
+ if [ $? -ne 0 ]; then
26
+ exit 1
27
+ fi
28
+ done
29
+
30
+ echo "[Monoco] Issue lint passed."
31
+ exit 0
@@ -1,20 +1,15 @@
1
1
  #!/bin/sh
2
- # Issue Feature Pre-Push Hook
3
- # Checks for incomplete critical issues before pushing
2
+ # ---
3
+ # type: git
4
+ # event: pre-push
5
+ # description: "Check for incomplete critical issues before pushing"
6
+ # priority: 100
7
+ # ---
4
8
 
5
9
  echo "[Monoco] Checking critical issues before push..."
6
10
 
7
- # Get the list of commits being pushed
8
- # $1 = remote name, $2 = remote url (if available)
9
- REMOTE="$1"
10
- URL="$2"
11
-
12
- # Check for high/critical issues that are not closed
13
- # This uses monoco issue query to find open issues with high/critical criticality
14
- echo "[Monoco] Scanning for incomplete critical issues..."
15
-
16
11
  # Run the check using monoco command
17
- $MONOCO_CMD issue check-critical --fail-on-warning
12
+ monoco issue check-critical --fail-on-warning
18
13
  CHECK_EXIT=$?
19
14
 
20
15
  if [ $CHECK_EXIT -eq 2 ]; then
@@ -27,7 +22,6 @@ elif [ $CHECK_EXIT -eq 1 ]; then
27
22
  echo "[Monoco] ⚠️ High priority issues found."
28
23
  echo "[Monoco] Use --force-push to bypass this warning (not recommended)."
29
24
  # For now, we allow the push but warn
30
- # To block, change the exit code to 1
31
25
  exit 0
32
26
  fi
33
27
 
@@ -1,131 +1,26 @@
1
- # Issue 管理 (Agent 指引)
1
+ # Issue 管理
2
2
 
3
- ## Issue 管理
3
+ 使用 `monoco issue` 管理任务。
4
4
 
5
- 使用 `monoco issue` 管理任务的系统。
6
-
7
- - **创建**: `monoco issue create <type> -t "标题"` (类型: epic, feature, chore, fix)
5
+ - **创建**: `monoco issue create <type> -t "标题"`
8
6
  - **状态**: `monoco issue open|close|backlog <id>`
9
- - **检查**: `monoco issue lint` (手动编辑后必须运行)
7
+ - **检查**: `monoco issue lint`
10
8
  - **生命周期**: `monoco issue start|submit|delete <id>`
11
- - **上下文同步**: `monoco issue sync-files [id]` (更新文件追踪)
12
- - **结构**: `Issues/{CapitalizedPluralType}/{lowercase_status}/` (如 `Issues/Features/open/`)
13
- - **强制规则**:
14
- 1. **先有 Issue**: 在进行任何调研、设计或 Draft 之前,必须先使用 `monoco issue create` 创建 Issue。
15
- 2. **标题**: 必须包含 `## {ID}: {Title}` 标题(与 Front Matter 一致)。
16
- 3. **内容**: 至少 2 个 Checkbox,使用 `- [ ]`, `- [x]`, `- [-]`, `- [/]`。
17
- 4. **评审**: `review`/`done` 阶段必须包含 `## Review Comments` 章节且内容不为空。
18
- 5. **环境策略**:
19
- - 必须使用 `monoco issue start --branch` 创建 Feature 分支。
20
- - 🛑 **禁止**直接在 `main`/`master` 分支修改代码 (Linter 会报错)。
21
- - **清理时机**: 环境清理仅应在 `close` 时执行。**禁止**在 `submit` 阶段清理环境。
22
- - 修改代码后**必须**更新 `files` 字段(通过 `sync-files` 或手动)。
23
-
24
- ## Git 合并策略 (Merge Strategy)
25
-
26
- ### 核心原则
27
-
28
- 为确保 Feature 分支安全合并到主线,避免"旧状态污染主线"问题,必须遵循以下合并策略:
29
-
30
- #### 1. 禁止手动 Merge
31
-
32
- - **🛑 严禁** Agent 手动执行 `git merge` 合并 Feature 分支
33
- - **🛑 严禁** 使用 `git pull origin main` 后直接提交
34
- - **✅ 唯一权威途径**: 必须使用 `monoco issue close` 进行闭环
35
-
36
- #### 2. 安全合并流程 (Safe Merge Flow)
37
-
38
- 正确的 Issue 关闭流程如下:
39
-
40
- ```bash
41
- # 1. 确保当前在 main/master 分支,且代码已合并
42
- $ git checkout main
43
- $ git pull origin main
44
-
45
- # 2. 确认 Feature 分支的变更已合并到主线
46
- # (通过 PR/MR 或其他代码审查流程)
47
-
48
- # 3. 使用 monoco issue close 关闭 Issue (默认执行 prune)
49
- $ monoco issue close FEAT-XXXX --solution implemented
50
-
51
- # 4. 如需保留分支,使用 --no-prune
52
- $ monoco issue close FEAT-XXXX --solution implemented --no-prune
53
- ```
54
-
55
- #### 3. 冲突处理原则
56
-
57
- 当 Feature 分支与主线产生冲突时:
58
-
59
- 1. **自动合并停止**: 如果 `touched files` (Issue `files` 字段) 与主线产生冲突,自动化工具**必须立即停止合并**,并抛出明确错误。
60
-
61
- 2. **手动 Cherry-Pick 模式**:
62
- - 错误信息会指示 Agent 转入手动 Cherry-Pick 模式
63
- - **核心原则**: 仅挑选属于本 Feature 的有效变更,严禁覆盖主线上无关 Issue 的更新
64
- - 使用 `git cherry-pick <commit>` 逐个应用有效提交
65
-
66
- 3. **Fallback 策略**:
67
- ```bash
68
- # 1. 创建临时分支用于解决冲突
69
- $ git checkout main
70
- $ git checkout -b temp/FEAT-XXXX-resolve
71
-
72
- # 2. 逐个 Cherry-Pick 有效提交
73
- $ git cherry-pick <commit-hash-1>
74
- $ git cherry-pick <commit-hash-2>
75
-
76
- # 3. 如有冲突,仅保留本 Feature 的变更
77
- # 放弃任何会覆盖主线上其他 Issue 更新的修改
78
-
79
- # 4. 完成后合并临时分支
80
- $ git checkout main
81
- $ git merge temp/FEAT-XXXX-resolve
82
-
83
- # 5. 关闭 Issue
84
- $ monoco issue close FEAT-XXXX --solution implemented
85
- ```
86
-
87
- #### 4. 基于 files 字段的智能合并 (Smart Atomic Merge)
88
-
89
- Issue 的 `files` 字段记录了 Feature 分支的真实影响范围 (Actual Impact Scope):
90
-
91
- - **生成方式**: `monoco issue sync-files` 使用 `git diff --name-only base...target` 逻辑
92
- - **作用**: 作为合并白名单,仅合并列表中的文件,过滤因"旧版本基线"导致的隐性覆盖
93
- - **限制**: 无法防御显式的误操作修改(如无意中格式化其他 Issue 文件)
94
-
95
- **未来增强**: 基于 `files` 列表实现选择性合并逻辑:
96
- ```bash
97
- # 选择性合并(规划中)
98
- $ git checkout main
99
- $ git checkout feature/FEAT-XXXX -- <files...>
100
- ```
101
-
102
- #### 5. 清理策略
103
-
104
- - **默认清理**: `monoco issue close` 默认执行 `--prune`,删除 Feature 分支/Worktree
105
- - **保留分支**: 如需保留分支,显式使用 `--no-prune`
106
- - **强制清理**: 使用 `--force` 强制删除未完全合并的分支(谨慎使用)
107
-
108
- ```bash
109
- # 默认清理分支
110
- $ monoco issue close FEAT-XXXX --solution implemented
111
- # ✔ Cleaned up: branch:feat/feat-XXXX-xxx
112
-
113
- # 保留分支
114
- $ monoco issue close FEAT-XXXX --solution implemented --no-prune
9
+ - **上下文同步**: `monoco issue sync-files [id]`
10
+ - **结构**: `Issues/{CapitalizedPluralType}/{lowercase_status}/` (如 `Issues/Features/open/`)
115
11
 
116
- # 强制清理(谨慎)
117
- $ monoco issue close FEAT-XXXX --solution implemented --force
118
- ```
12
+ ## 标准工作流
119
13
 
120
- ### 总结
14
+ 1. **创建**: `monoco issue create feature -t "标题"`
15
+ 2. **启动**: `monoco issue start FEAT-XXX --branch`
16
+ 3. **实现**: 正常编码与测试。
17
+ 4. **同步**: `monoco issue sync-files` (更新 `files` 字段)。
18
+ 5. **提交**: `monoco issue submit FEAT-XXX`。
19
+ 6. **合规合并**: `monoco issue close FEAT-XXX --solution implemented` (合并到主线的唯一途径)。
121
20
 
122
- | 操作 | 命令 | 说明 |
123
- |------|------|------|
124
- | 创建 Issue | `monoco issue create feature -t "标题"` | 先创建 Issue 再开发 |
125
- | 启动开发 | `monoco issue start FEAT-XXXX --branch` | 创建 Feature 分支 |
126
- | 同步文件 | `monoco issue sync-files` | 更新 files 字段 |
127
- | 提交评审 | `monoco issue submit FEAT-XXXX` | 进入 Review 阶段 |
128
- | 关闭 Issue | `monoco issue close FEAT-XXXX --solution implemented` | 唯一合并途径 |
129
- | 保留分支 | `monoco issue close ... --no-prune` | 关闭但不删除分支 |
21
+ ## Git 合并策略
130
22
 
131
- > ⚠️ **警告**: 任何绕过 `monoco issue close` 的手动合并操作都可能导致主线状态污染,违反工作流合规要求。
23
+ - **禁止手动合并**: 严禁在 `main`/`master` 分支执行 `git merge` 或直接 `git pull`。
24
+ - **原子合并**: `monoco issue close` 仅根据 Issue 的 `files` 列表合并变更。
25
+ - **冲突处理**: 若产生冲突,请遵循 `close` 命令产生的指引进行手动 Cherry-Pick。
26
+ - **清理策略**: `monoco issue close` 默认执行清理(删除分支/Worktree)。需保留请指定 `--no-prune`。
@@ -4,7 +4,7 @@ from typing import Optional
4
4
  from rich.console import Console
5
5
  from rich.table import Table
6
6
  from monoco.core.config import get_config
7
- from .core import add_memo, load_memos, delete_memo, update_memo, get_inbox_path, validate_content_language
7
+ from .core import add_memo, load_memos, delete_memo, get_inbox_path, validate_content_language
8
8
 
9
9
  app = typer.Typer(help="Manage memos (fleeting notes).")
10
10
  console = Console()
@@ -70,38 +70,33 @@ def add_command(
70
70
 
71
71
  @app.command("list")
72
72
  def list_command(
73
- status: Optional[str] = typer.Option(None, "--status", help="Filter by status (pending, tracked, resolved)."),
74
73
  limit: int = typer.Option(None, "--limit", "-n", help="Limit number of memos shown.")
75
74
  ):
76
75
  """
77
76
  List all memos in the inbox.
77
+
78
+ Signal Queue Model: Shows current pending signals.
79
+ Once consumed (file cleared), memos are no longer listed here.
80
+ Use git history to see consumed memos.
78
81
  """
79
82
  issues_root = get_issues_root()
80
83
 
81
84
  memos = load_memos(issues_root)
82
-
83
- if status:
84
- memos = [m for m in memos if m.status == status]
85
85
 
86
86
  if not memos:
87
- console.print("No memos found.")
87
+ console.print("No memos in inbox. (Consumed memos are in git history)")
88
88
  return
89
89
 
90
- # Reverse sort by timestamp (newest first) usually?
91
- # But file is appended. Let's show newest at bottom (log style) or newest at top?
92
- # Usually list shows content. Newest at bottom is standard for logs, but for "Inbox" maybe newest top?
93
- # Let's keep file order (oldest first) unless user asks otherwise, or maybe reverse it for "Inbox" feel?
94
- # Let's reverse it to see latest first.
90
+ # Reverse to show newest first
95
91
  memos.reverse()
96
92
 
97
93
  if limit:
98
94
  memos = memos[:limit]
99
95
 
100
- table = Table(title="Memo Inbox")
96
+ table = Table(title="Memo Inbox (Pending Signals)")
101
97
  table.add_column("ID", style="cyan", no_wrap=True)
102
- table.add_column("Stat", style="yellow", width=4)
103
98
  table.add_column("Type", style="magenta", width=8)
104
- table.add_column("Ref", style="blue")
99
+ table.add_column("Source", style="blue", width=10)
105
100
  table.add_column("Content")
106
101
 
107
102
  for memo in memos:
@@ -109,21 +104,17 @@ def list_command(
109
104
  content_preview = memo.content.split("\n")[0]
110
105
  if len(content_preview) > 50:
111
106
  content_preview = content_preview[:47] + "..."
112
-
113
- status_icon = " "
114
- if memo.status == "pending": status_icon = "P"
115
- elif memo.status == "tracked": status_icon = "T"
116
- elif memo.status == "resolved": status_icon = "✔"
117
107
 
118
108
  table.add_row(
119
109
  memo.uid,
120
- status_icon,
121
110
  memo.type,
122
- memo.ref or "",
111
+ memo.source,
123
112
  content_preview
124
113
  )
125
114
 
126
115
  console.print(table)
116
+ console.print(f"\n[yellow]Note:[/yellow] Memos are consumed (deleted) when processed by Architect.")
117
+ console.print("[dim]Use `git log --follow Memos/inbox.md` to see consumed memos.[/dim]")
127
118
 
128
119
 
129
120
  @app.command("open")
@@ -147,6 +138,9 @@ def delete_command(
147
138
  ):
148
139
  """
149
140
  Delete a memo from the inbox by its ID.
141
+
142
+ Signal Queue Model: This is a manual delete operation.
143
+ Normally memos are consumed automatically by the MemoThresholdHandler.
150
144
  """
151
145
  issues_root = get_issues_root()
152
146
 
@@ -157,49 +151,6 @@ def delete_command(
157
151
  raise typer.Exit(code=1)
158
152
 
159
153
 
160
- @app.command("link")
161
- def link_command(
162
- memo_id: str = typer.Argument(..., help="Memo ID"),
163
- issue_id: str = typer.Argument(..., help="Issue ID to link to")
164
- ):
165
- """
166
- Link a memo to an issue (Traceability).
167
- Sets status to 'tracked'.
168
- """
169
- issues_root = get_issues_root()
170
-
171
- updates = {
172
- "status": "tracked",
173
- "ref": issue_id
174
- }
175
-
176
- if update_memo(issues_root, memo_id, updates):
177
- console.print(f"[green]✔ Memo {memo_id} linked to {issue_id}.[/green]")
178
- else:
179
- console.print(f"[red]Error: Memo {memo_id} not found.[/red]")
180
- raise typer.Exit(code=1)
181
-
182
-
183
- @app.command("resolve")
184
- def resolve_command(
185
- memo_id: str = typer.Argument(..., help="Memo ID")
186
- ):
187
- """
188
- Mark a memo as resolved.
189
- """
190
- issues_root = get_issues_root()
191
-
192
- updates = {
193
- "status": "resolved"
194
- }
195
-
196
- if update_memo(issues_root, memo_id, updates):
197
- console.print(f"[green]✔ Memo {memo_id} resolved.[/green]")
198
- else:
199
- console.print(f"[red]Error: Memo {memo_id} not found.[/red]")
200
- raise typer.Exit(code=1)
201
-
202
-
203
154
 
204
155
 
205
156
 
@@ -39,6 +39,11 @@ def generate_memo_id() -> str:
39
39
  def parse_memo_block(block: str) -> Optional[Memo]:
40
40
  """
41
41
  Parse a text block into a Memo object.
42
+
43
+ Signal Queue Model (FEAT-0165):
44
+ - No status field parsing (file existence is the state)
45
+ - No ref field parsing (traceability via git history)
46
+
42
47
  Block format:
43
48
  ## [uid] YYYY-MM-DD HH:MM:SS
44
49
  - **Key**: Value
@@ -90,17 +95,6 @@ def parse_memo_block(block: str) -> Optional[Memo]:
90
95
  content_lines.append(line)
91
96
 
92
97
  content = "\n".join(content_lines).strip()
93
-
94
- # Map metadata to model fields
95
- # Status map reverse
96
- status_raw = metadata.get("status", "[ ] Pending")
97
- status = "pending"
98
- if "[x] Tracked" in status_raw:
99
- status = "tracked"
100
- elif "[x] Resolved" in status_raw:
101
- status = "resolved"
102
- elif "[-] Dismissed" in status_raw:
103
- status = "dismissed"
104
98
 
105
99
  return Memo(
106
100
  uid=uid,
@@ -109,9 +103,7 @@ def parse_memo_block(block: str) -> Optional[Memo]:
109
103
  author=metadata.get("from", "User"),
110
104
  source=metadata.get("source", "cli"),
111
105
  type=metadata.get("type", "insight"),
112
- status=status,
113
- ref=metadata.get("ref"),
114
- context=metadata.get("context") # Note: context might need cleanup if it was wrapped in code blocks
106
+ context=metadata.get("context")
115
107
  )
116
108
 
117
109
  def load_memos(issues_root: Path) -> List[Memo]:
@@ -195,26 +187,6 @@ def add_memo(
195
187
 
196
188
  return uid
197
189
 
198
- def update_memo(issues_root: Path, memo_id: str, updates: dict) -> bool:
199
- """
200
- Update a memo's fields.
201
- """
202
- memos = load_memos(issues_root)
203
- found = False
204
- for i, m in enumerate(memos):
205
- if m.uid == memo_id:
206
- # Apply updates
207
- updated_data = m.model_dump()
208
- updated_data.update(updates)
209
- memos[i] = Memo(**updated_data) # Re-validate
210
- found = True
211
- break
212
-
213
- if found:
214
- save_memos(issues_root, memos)
215
-
216
- return found
217
-
218
190
  def delete_memo(issues_root: Path, memo_id: str) -> bool:
219
191
  """
220
192
  Delete a memo by its ID.