@mindfoldhq/trellis 0.3.9 → 0.3.10-beta.0

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 (172) hide show
  1. package/dist/cli/index.js +2 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/init.d.ts +1 -0
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +203 -31
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/update.d.ts.map +1 -1
  8. package/dist/commands/update.js +154 -6
  9. package/dist/commands/update.js.map +1 -1
  10. package/dist/configurators/workflow.d.ts +6 -2
  11. package/dist/configurators/workflow.d.ts.map +1 -1
  12. package/dist/configurators/workflow.js +88 -58
  13. package/dist/configurators/workflow.js.map +1 -1
  14. package/dist/migrations/index.d.ts +1 -0
  15. package/dist/migrations/index.d.ts.map +1 -1
  16. package/dist/migrations/index.js +2 -0
  17. package/dist/migrations/index.js.map +1 -1
  18. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  19. package/dist/templates/claude/agents/dispatch.md +1 -2
  20. package/dist/templates/claude/agents/implement.md +2 -3
  21. package/dist/templates/claude/commands/trellis/before-dev.md +29 -0
  22. package/dist/templates/claude/commands/trellis/check.md +25 -0
  23. package/dist/templates/claude/commands/trellis/create-command.md +2 -2
  24. package/dist/templates/claude/commands/trellis/onboard.md +13 -13
  25. package/dist/templates/claude/commands/trellis/parallel.md +1 -2
  26. package/dist/templates/claude/commands/trellis/record-session.md +1 -1
  27. package/dist/templates/claude/commands/trellis/start.md +8 -4
  28. package/dist/templates/claude/hooks/inject-subagent-context.py +21 -13
  29. package/dist/templates/claude/hooks/session-start.py +170 -2
  30. package/dist/templates/codex/skills/before-dev/SKILL.md +34 -0
  31. package/dist/templates/codex/skills/check/SKILL.md +30 -0
  32. package/dist/templates/codex/skills/create-command/SKILL.md +2 -2
  33. package/dist/templates/codex/skills/onboard/SKILL.md +11 -11
  34. package/dist/templates/codex/skills/record-session/SKILL.md +1 -1
  35. package/dist/templates/codex/skills/start/SKILL.md +8 -3
  36. package/dist/templates/cursor/commands/trellis-before-dev.md +29 -0
  37. package/dist/templates/cursor/commands/trellis-check.md +25 -0
  38. package/dist/templates/cursor/commands/trellis-create-command.md +2 -2
  39. package/dist/templates/cursor/commands/trellis-onboard.md +13 -13
  40. package/dist/templates/cursor/commands/trellis-record-session.md +1 -1
  41. package/dist/templates/cursor/commands/trellis-start.md +7 -16
  42. package/dist/templates/gemini/commands/trellis/before-dev.toml +33 -0
  43. package/dist/templates/gemini/commands/trellis/check.toml +29 -0
  44. package/dist/templates/gemini/commands/trellis/create-command.toml +2 -2
  45. package/dist/templates/gemini/commands/trellis/onboard.toml +2 -2
  46. package/dist/templates/gemini/commands/trellis/record-session.toml +1 -1
  47. package/dist/templates/gemini/commands/trellis/start.toml +9 -4
  48. package/dist/templates/iflow/agents/dispatch.md +1 -2
  49. package/dist/templates/iflow/agents/implement.md +2 -3
  50. package/dist/templates/iflow/commands/trellis/before-dev.md +29 -0
  51. package/dist/templates/iflow/commands/trellis/check.md +25 -0
  52. package/dist/templates/iflow/commands/trellis/create-command.md +2 -2
  53. package/dist/templates/iflow/commands/trellis/onboard.md +13 -13
  54. package/dist/templates/iflow/commands/trellis/parallel.md +1 -2
  55. package/dist/templates/iflow/commands/trellis/record-session.md +1 -1
  56. package/dist/templates/iflow/commands/trellis/start.md +8 -4
  57. package/dist/templates/iflow/hooks/inject-subagent-context.py +21 -13
  58. package/dist/templates/iflow/hooks/session-start.py +156 -1
  59. package/dist/templates/kilo/workflows/before-dev.md +29 -0
  60. package/dist/templates/kilo/workflows/check.md +25 -0
  61. package/dist/templates/kilo/workflows/create-command.md +2 -2
  62. package/dist/templates/kilo/workflows/onboard.md +13 -13
  63. package/dist/templates/kilo/workflows/parallel.md +1 -2
  64. package/dist/templates/kilo/workflows/record-session.md +1 -1
  65. package/dist/templates/kilo/workflows/start.md +8 -3
  66. package/dist/templates/kiro/skills/before-dev/SKILL.md +34 -0
  67. package/dist/templates/kiro/skills/check/SKILL.md +30 -0
  68. package/dist/templates/kiro/skills/create-command/SKILL.md +2 -2
  69. package/dist/templates/kiro/skills/onboard/SKILL.md +11 -11
  70. package/dist/templates/kiro/skills/record-session/SKILL.md +1 -1
  71. package/dist/templates/kiro/skills/start/SKILL.md +8 -3
  72. package/dist/templates/markdown/spec/backend/script-conventions.md +93 -0
  73. package/dist/templates/opencode/agents/dispatch.md +1 -2
  74. package/dist/templates/opencode/agents/implement.md +2 -2
  75. package/dist/templates/opencode/agents/research.md +1 -2
  76. package/dist/templates/opencode/commands/trellis/before-dev.md +29 -0
  77. package/dist/templates/opencode/commands/trellis/check.md +25 -0
  78. package/dist/templates/opencode/commands/trellis/create-command.md +2 -2
  79. package/dist/templates/opencode/commands/trellis/onboard.md +13 -13
  80. package/dist/templates/opencode/commands/trellis/parallel.md +1 -2
  81. package/dist/templates/opencode/commands/trellis/record-session.md +1 -1
  82. package/dist/templates/opencode/commands/trellis/start.md +8 -3
  83. package/dist/templates/opencode/plugin/inject-subagent-context.js +45 -18
  84. package/dist/templates/opencode/plugin/session-start.js +149 -1
  85. package/dist/templates/qoder/skills/before-dev/SKILL.md +34 -0
  86. package/dist/templates/qoder/skills/check/SKILL.md +30 -0
  87. package/dist/templates/qoder/skills/create-command/SKILL.md +2 -2
  88. package/dist/templates/qoder/skills/onboard/SKILL.md +13 -13
  89. package/dist/templates/qoder/skills/record-session/SKILL.md +1 -1
  90. package/dist/templates/qoder/skills/start/SKILL.md +8 -3
  91. package/dist/templates/trellis/config.yaml +20 -0
  92. package/dist/templates/trellis/index.d.ts +11 -0
  93. package/dist/templates/trellis/index.d.ts.map +1 -1
  94. package/dist/templates/trellis/index.js +22 -0
  95. package/dist/templates/trellis/index.js.map +1 -1
  96. package/dist/templates/trellis/scripts/add_session.py +52 -7
  97. package/dist/templates/trellis/scripts/common/cli_adapter.py +33 -45
  98. package/dist/templates/trellis/scripts/common/config.py +152 -0
  99. package/dist/templates/trellis/scripts/common/git.py +31 -0
  100. package/dist/templates/trellis/scripts/common/git_context.py +23 -586
  101. package/dist/templates/trellis/scripts/common/io.py +37 -0
  102. package/dist/templates/trellis/scripts/common/log.py +45 -0
  103. package/dist/templates/trellis/scripts/common/packages_context.py +233 -0
  104. package/dist/templates/trellis/scripts/common/paths.py +46 -0
  105. package/dist/templates/trellis/scripts/common/phase.py +50 -49
  106. package/dist/templates/trellis/scripts/common/registry.py +41 -72
  107. package/dist/templates/trellis/scripts/common/session_context.py +466 -0
  108. package/dist/templates/trellis/scripts/common/task_context.py +384 -0
  109. package/dist/templates/trellis/scripts/common/task_queue.py +27 -98
  110. package/dist/templates/trellis/scripts/common/task_store.py +534 -0
  111. package/dist/templates/trellis/scripts/common/task_utils.py +96 -6
  112. package/dist/templates/trellis/scripts/common/tasks.py +109 -0
  113. package/dist/templates/trellis/scripts/common/types.py +112 -0
  114. package/dist/templates/trellis/scripts/create_bootstrap.py +31 -26
  115. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  116. package/dist/templates/trellis/scripts/multi_agent/_bootstrap.py +17 -0
  117. package/dist/templates/trellis/scripts/multi_agent/cleanup.py +43 -48
  118. package/dist/templates/trellis/scripts/multi_agent/create_pr.py +336 -45
  119. package/dist/templates/trellis/scripts/multi_agent/plan.py +2 -26
  120. package/dist/templates/trellis/scripts/multi_agent/start.py +126 -57
  121. package/dist/templates/trellis/scripts/multi_agent/status.py +12 -753
  122. package/dist/templates/trellis/scripts/multi_agent/status_display.py +542 -0
  123. package/dist/templates/trellis/scripts/multi_agent/status_monitor.py +225 -0
  124. package/dist/templates/trellis/scripts/task.py +50 -975
  125. package/dist/templates/trellis/workflow.md +21 -34
  126. package/dist/types/migration.d.ts +3 -1
  127. package/dist/types/migration.d.ts.map +1 -1
  128. package/dist/utils/project-detector.d.ts +23 -0
  129. package/dist/utils/project-detector.d.ts.map +1 -1
  130. package/dist/utils/project-detector.js +364 -0
  131. package/dist/utils/project-detector.js.map +1 -1
  132. package/dist/utils/template-fetcher.d.ts +2 -2
  133. package/dist/utils/template-fetcher.d.ts.map +1 -1
  134. package/dist/utils/template-fetcher.js +5 -5
  135. package/dist/utils/template-fetcher.js.map +1 -1
  136. package/package.json +1 -1
  137. package/dist/templates/claude/commands/trellis/before-backend-dev.md +0 -13
  138. package/dist/templates/claude/commands/trellis/before-frontend-dev.md +0 -13
  139. package/dist/templates/claude/commands/trellis/check-backend.md +0 -13
  140. package/dist/templates/claude/commands/trellis/check-frontend.md +0 -13
  141. package/dist/templates/codex/skills/before-backend-dev/SKILL.md +0 -18
  142. package/dist/templates/codex/skills/before-frontend-dev/SKILL.md +0 -18
  143. package/dist/templates/codex/skills/check-backend/SKILL.md +0 -18
  144. package/dist/templates/codex/skills/check-frontend/SKILL.md +0 -18
  145. package/dist/templates/cursor/commands/trellis-before-backend-dev.md +0 -13
  146. package/dist/templates/cursor/commands/trellis-before-frontend-dev.md +0 -13
  147. package/dist/templates/cursor/commands/trellis-check-backend.md +0 -13
  148. package/dist/templates/cursor/commands/trellis-check-frontend.md +0 -13
  149. package/dist/templates/gemini/commands/trellis/before-backend-dev.toml +0 -17
  150. package/dist/templates/gemini/commands/trellis/before-frontend-dev.toml +0 -17
  151. package/dist/templates/gemini/commands/trellis/check-backend.toml +0 -17
  152. package/dist/templates/gemini/commands/trellis/check-frontend.toml +0 -17
  153. package/dist/templates/iflow/commands/trellis/before-backend-dev.md +0 -13
  154. package/dist/templates/iflow/commands/trellis/before-frontend-dev.md +0 -13
  155. package/dist/templates/iflow/commands/trellis/check-backend.md +0 -13
  156. package/dist/templates/iflow/commands/trellis/check-frontend.md +0 -13
  157. package/dist/templates/kilo/workflows/before-backend-dev.md +0 -13
  158. package/dist/templates/kilo/workflows/before-frontend-dev.md +0 -13
  159. package/dist/templates/kilo/workflows/check-backend.md +0 -13
  160. package/dist/templates/kilo/workflows/check-frontend.md +0 -13
  161. package/dist/templates/kiro/skills/before-backend-dev/SKILL.md +0 -18
  162. package/dist/templates/kiro/skills/before-frontend-dev/SKILL.md +0 -18
  163. package/dist/templates/kiro/skills/check-backend/SKILL.md +0 -18
  164. package/dist/templates/kiro/skills/check-frontend/SKILL.md +0 -18
  165. package/dist/templates/opencode/commands/trellis/before-backend-dev.md +0 -13
  166. package/dist/templates/opencode/commands/trellis/before-frontend-dev.md +0 -13
  167. package/dist/templates/opencode/commands/trellis/check-backend.md +0 -13
  168. package/dist/templates/opencode/commands/trellis/check-frontend.md +0 -13
  169. package/dist/templates/qoder/skills/before-backend-dev/SKILL.md +0 -18
  170. package/dist/templates/qoder/skills/before-frontend-dev/SKILL.md +0 -18
  171. package/dist/templates/qoder/skills/check-backend/SKILL.md +0 -18
  172. package/dist/templates/qoder/skills/check-frontend/SKILL.md +0 -18
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Multi-Agent Pipeline: Process monitoring and log parsing.
4
+
5
+ Provides:
6
+ tail_follow - Follow a file like 'tail -f'
7
+ get_last_tool - Get last tool call from agent log
8
+ get_last_message - Get last assistant text from agent log
9
+ cmd_watch - Watch agent log in real-time
10
+ cmd_log - Show recent log entries
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import time
17
+ from pathlib import Path
18
+
19
+ from common.log import Colors
20
+
21
+ from .status_display import find_agent
22
+
23
+
24
+ # =============================================================================
25
+ # Log Parsing
26
+ # =============================================================================
27
+
28
+ def tail_follow(file_path: Path) -> None:
29
+ """Follow a file like 'tail -f', cross-platform compatible."""
30
+ with open(file_path, "r", encoding="utf-8", errors="replace") as f:
31
+ # Seek to end of file
32
+ f.seek(0, 2)
33
+
34
+ while True:
35
+ line = f.readline()
36
+ if line:
37
+ print(line, end="", flush=True)
38
+ else:
39
+ time.sleep(0.1)
40
+
41
+
42
+ def get_last_tool(log_file: Path, platform: str = "claude") -> str | None:
43
+ """Get the last tool call from agent log.
44
+
45
+ Supports both Claude Code and OpenCode log formats.
46
+
47
+ Claude Code format:
48
+ {"type": "assistant", "message": {"content": [{"type": "tool_use", "name": "Read"}]}}
49
+
50
+ OpenCode format:
51
+ {"type": "tool_use", "tool": "bash", "state": {"status": "completed"}}
52
+ """
53
+ if not log_file.is_file():
54
+ return None
55
+
56
+ try:
57
+ lines = log_file.read_text(encoding="utf-8").splitlines()
58
+ for line in reversed(lines[-100:]):
59
+ try:
60
+ data = json.loads(line)
61
+
62
+ if platform == "opencode":
63
+ # OpenCode format: {"type": "tool_use", "tool": "bash", ...}
64
+ if data.get("type") == "tool_use":
65
+ return data.get("tool")
66
+ else:
67
+ # Claude Code format: {"type": "assistant", "message": {"content": [...]}}
68
+ if data.get("type") == "assistant":
69
+ content = data.get("message", {}).get("content", [])
70
+ for item in content:
71
+ if item.get("type") == "tool_use":
72
+ return item.get("name")
73
+ except json.JSONDecodeError:
74
+ continue
75
+ except Exception:
76
+ pass
77
+ return None
78
+
79
+
80
+ def get_last_message(log_file: Path, max_len: int = 100, platform: str = "claude") -> str | None:
81
+ """Get the last assistant text from agent log.
82
+
83
+ Supports both Claude Code and OpenCode log formats.
84
+
85
+ Claude Code format:
86
+ {"type": "assistant", "message": {"content": [{"type": "text", "text": "..."}]}}
87
+
88
+ OpenCode format:
89
+ {"type": "text", "text": "..."}
90
+ """
91
+ if not log_file.is_file():
92
+ return None
93
+
94
+ try:
95
+ lines = log_file.read_text(encoding="utf-8").splitlines()
96
+ for line in reversed(lines[-100:]):
97
+ try:
98
+ data = json.loads(line)
99
+
100
+ if platform == "opencode":
101
+ # OpenCode format: {"type": "text", "text": "..."}
102
+ if data.get("type") == "text":
103
+ text = data.get("text", "")
104
+ if text:
105
+ return text[:max_len]
106
+ else:
107
+ # Claude Code format: {"type": "assistant", "message": {"content": [...]}}
108
+ if data.get("type") == "assistant":
109
+ content = data.get("message", {}).get("content", [])
110
+ for item in content:
111
+ if item.get("type") == "text":
112
+ text = item.get("text", "")
113
+ if text:
114
+ return text[:max_len]
115
+ except json.JSONDecodeError:
116
+ continue
117
+ except Exception:
118
+ pass
119
+ return None
120
+
121
+
122
+ # =============================================================================
123
+ # Commands
124
+ # =============================================================================
125
+
126
+ def cmd_watch(target: str, repo_root: Path) -> int:
127
+ """Watch agent log in real-time."""
128
+ agent = find_agent(target, repo_root)
129
+ if not agent:
130
+ print(f"Agent not found: {target}")
131
+ return 1
132
+
133
+ worktree = agent.get("worktree_path", "")
134
+ log_file = Path(worktree) / ".agent-log"
135
+
136
+ if not log_file.is_file():
137
+ print(f"Log file not found: {log_file}")
138
+ return 1
139
+
140
+ print(f"{Colors.BLUE}Watching:{Colors.NC} {log_file}")
141
+ print(f"{Colors.DIM}Press Ctrl+C to stop{Colors.NC}")
142
+ print()
143
+
144
+ try:
145
+ tail_follow(log_file)
146
+ except KeyboardInterrupt:
147
+ print() # Clean newline after Ctrl+C
148
+ return 0
149
+
150
+
151
+ def cmd_log(target: str, repo_root: Path) -> int:
152
+ """Show recent log entries."""
153
+ agent = find_agent(target, repo_root)
154
+ if not agent:
155
+ print(f"Agent not found: {target}")
156
+ return 1
157
+
158
+ worktree = agent.get("worktree_path", "")
159
+ platform = agent.get("platform", "claude")
160
+ log_file = Path(worktree) / ".agent-log"
161
+
162
+ if not log_file.is_file():
163
+ print(f"Log file not found: {log_file}")
164
+ return 1
165
+
166
+ print(f"{Colors.BLUE}=== Recent Log: {target} ==={Colors.NC}")
167
+ print(f"{Colors.DIM}Platform: {platform}{Colors.NC}")
168
+ print()
169
+
170
+ lines = log_file.read_text(encoding="utf-8").splitlines()
171
+ for line in lines[-50:]:
172
+ try:
173
+ data = json.loads(line)
174
+ msg_type = data.get("type", "")
175
+
176
+ if platform == "opencode":
177
+ # OpenCode format
178
+ if msg_type == "text":
179
+ text = data.get("text", "")
180
+ if text:
181
+ display = text[:300]
182
+ if len(text) > 300:
183
+ display += "..."
184
+ print(f"{Colors.BLUE}[TEXT]{Colors.NC} {display}")
185
+ elif msg_type == "tool_use":
186
+ tool_name = data.get("tool", "unknown")
187
+ status = data.get("state", {}).get("status", "")
188
+ print(f"{Colors.YELLOW}[TOOL]{Colors.NC} {tool_name} ({status})")
189
+ elif msg_type == "step_start":
190
+ print(f"{Colors.CYAN}[STEP]{Colors.NC} Start")
191
+ elif msg_type == "step_finish":
192
+ reason = data.get("reason", "")
193
+ print(f"{Colors.CYAN}[STEP]{Colors.NC} Finish ({reason})")
194
+ elif msg_type == "error":
195
+ error_msg = data.get("message", "")
196
+ print(f"{Colors.RED}[ERROR]{Colors.NC} {error_msg}")
197
+ else:
198
+ # Claude Code format
199
+ if msg_type == "system":
200
+ subtype = data.get("subtype", "")
201
+ print(f"{Colors.CYAN}[SYSTEM]{Colors.NC} {subtype}")
202
+ elif msg_type == "user":
203
+ content = data.get("message", {}).get("content", "")
204
+ if content:
205
+ print(f"{Colors.GREEN}[USER]{Colors.NC} {content[:200]}")
206
+ elif msg_type == "assistant":
207
+ content = data.get("message", {}).get("content", [])
208
+ if content:
209
+ item = content[0]
210
+ text = item.get("text")
211
+ tool = item.get("name")
212
+ if text:
213
+ display = text[:300]
214
+ if len(text) > 300:
215
+ display += "..."
216
+ print(f"{Colors.BLUE}[ASSISTANT]{Colors.NC} {display}")
217
+ elif tool:
218
+ print(f"{Colors.YELLOW}[TOOL]{Colors.NC} {tool}")
219
+ elif msg_type == "result":
220
+ tool_name = data.get("tool", "unknown")
221
+ print(f"{Colors.DIM}[RESULT]{Colors.NC} {tool_name} completed")
222
+ except json.JSONDecodeError:
223
+ continue
224
+
225
+ return 0