tapps-agents 3.5.39__py3-none-any.whl → 3.5.41__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.
- tapps_agents/__init__.py +2 -2
- tapps_agents/agents/enhancer/agent.py +2728 -2728
- tapps_agents/agents/implementer/agent.py +35 -13
- tapps_agents/agents/reviewer/agent.py +43 -10
- tapps_agents/agents/reviewer/scoring.py +59 -68
- tapps_agents/agents/reviewer/tools/__init__.py +24 -0
- tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -0
- tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -0
- tapps_agents/beads/__init__.py +11 -0
- tapps_agents/beads/hydration.py +213 -0
- tapps_agents/beads/specs.py +206 -0
- tapps_agents/cli/commands/health.py +19 -3
- tapps_agents/cli/commands/simple_mode.py +842 -676
- tapps_agents/cli/commands/task.py +227 -0
- tapps_agents/cli/commands/top_level.py +13 -0
- tapps_agents/cli/main.py +658 -651
- tapps_agents/cli/parsers/top_level.py +1978 -1881
- tapps_agents/core/config.py +1622 -1622
- tapps_agents/core/init_project.py +3012 -2897
- tapps_agents/epic/markdown_sync.py +105 -0
- tapps_agents/epic/orchestrator.py +1 -2
- tapps_agents/epic/parser.py +427 -423
- tapps_agents/experts/adaptive_domain_detector.py +0 -2
- tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +15 -15
- tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +19 -44
- tapps_agents/health/checks/outcomes.backup_20260204_064058.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +324 -0
- tapps_agents/health/checks/outcomes.py +134 -46
- tapps_agents/health/orchestrator.py +12 -4
- tapps_agents/hooks/__init__.py +33 -0
- tapps_agents/hooks/config.py +140 -0
- tapps_agents/hooks/events.py +135 -0
- tapps_agents/hooks/executor.py +128 -0
- tapps_agents/hooks/manager.py +143 -0
- tapps_agents/session/__init__.py +19 -0
- tapps_agents/session/manager.py +256 -0
- tapps_agents/simple_mode/code_snippet_handler.py +382 -0
- tapps_agents/simple_mode/intent_parser.py +29 -4
- tapps_agents/simple_mode/orchestrators/base.py +185 -59
- tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2667 -2642
- tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +2 -2
- tapps_agents/simple_mode/workflow_suggester.py +37 -3
- tapps_agents/workflow/agent_handlers/implementer_handler.py +18 -3
- tapps_agents/workflow/cursor_executor.py +2337 -2118
- tapps_agents/workflow/direct_execution_fallback.py +16 -3
- tapps_agents/workflow/message_formatter.py +2 -1
- tapps_agents/workflow/models.py +38 -1
- tapps_agents/workflow/parallel_executor.py +43 -4
- tapps_agents/workflow/parser.py +375 -357
- tapps_agents/workflow/rules_generator.py +337 -337
- tapps_agents/workflow/skill_invoker.py +9 -3
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/METADATA +5 -1
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/RECORD +58 -54
- tapps_agents/agents/analyst/SKILL.md +0 -85
- tapps_agents/agents/architect/SKILL.md +0 -80
- tapps_agents/agents/debugger/SKILL.md +0 -66
- tapps_agents/agents/designer/SKILL.md +0 -78
- tapps_agents/agents/documenter/SKILL.md +0 -95
- tapps_agents/agents/enhancer/SKILL.md +0 -189
- tapps_agents/agents/implementer/SKILL.md +0 -117
- tapps_agents/agents/improver/SKILL.md +0 -55
- tapps_agents/agents/ops/SKILL.md +0 -64
- tapps_agents/agents/orchestrator/SKILL.md +0 -238
- tapps_agents/agents/planner/story_template.md +0 -37
- tapps_agents/agents/reviewer/templates/quality-dashboard.html.j2 +0 -150
- tapps_agents/agents/tester/SKILL.md +0 -71
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/WHEEL +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/licenses/LICENSE +0 -0
- {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Task management CLI: create, list, show, update, close, hydrate, dehydrate, run.
|
|
3
|
+
|
|
4
|
+
Manages task specs in .tapps-agents/task-specs/ and sync with Beads (bd).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from ..feedback import get_feedback
|
|
13
|
+
from .common import format_json_output
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def handle_task_command(args: object) -> None:
|
|
17
|
+
"""Dispatch to task subcommand handler."""
|
|
18
|
+
cmd = getattr(args, "task_command", None)
|
|
19
|
+
if not cmd:
|
|
20
|
+
print("task: subcommand required (create, list, show, update, close, hydrate, dehydrate, run)", file=sys.stderr)
|
|
21
|
+
sys.exit(2)
|
|
22
|
+
handlers = {
|
|
23
|
+
"create": _handle_create,
|
|
24
|
+
"list": _handle_list,
|
|
25
|
+
"show": _handle_show,
|
|
26
|
+
"update": _handle_update,
|
|
27
|
+
"close": _handle_close,
|
|
28
|
+
"hydrate": _handle_hydrate,
|
|
29
|
+
"dehydrate": _handle_dehydrate,
|
|
30
|
+
"run": _handle_run,
|
|
31
|
+
}
|
|
32
|
+
handler = handlers.get(cmd)
|
|
33
|
+
if not handler:
|
|
34
|
+
print(f"task: unknown subcommand {cmd!r}", file=sys.stderr)
|
|
35
|
+
sys.exit(2)
|
|
36
|
+
handler(args)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _project_root() -> Path:
|
|
40
|
+
return Path.cwd()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _handle_create(args: object) -> None:
|
|
44
|
+
from ...beads.specs import TaskSpec, save_task_spec
|
|
45
|
+
from ...beads.hydration import hydrate_to_beads
|
|
46
|
+
|
|
47
|
+
task_id = getattr(args, "id", "").strip()
|
|
48
|
+
title = getattr(args, "title", "").strip()
|
|
49
|
+
if not task_id or not title:
|
|
50
|
+
print("task create: id and --title are required", file=sys.stderr)
|
|
51
|
+
sys.exit(2)
|
|
52
|
+
root = _project_root()
|
|
53
|
+
spec = TaskSpec(
|
|
54
|
+
id=task_id,
|
|
55
|
+
title=title,
|
|
56
|
+
description=getattr(args, "description", "") or "",
|
|
57
|
+
workflow=getattr(args, "workflow", "build") or "build",
|
|
58
|
+
)
|
|
59
|
+
save_task_spec(spec, root)
|
|
60
|
+
print(f"Created task spec: {spec.id} ({root / '.tapps-agents' / 'task-specs' / f'{spec.id}.yaml'})")
|
|
61
|
+
if getattr(args, "beads", False):
|
|
62
|
+
report = hydrate_to_beads(project_root=root)
|
|
63
|
+
if report.bd_unavailable:
|
|
64
|
+
print("Beads (bd) not available; spec created without Beads issue.", file=sys.stderr)
|
|
65
|
+
else:
|
|
66
|
+
print(f"Hydration: created={report.created}, skipped={report.skipped}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _handle_list(args: object) -> None:
|
|
70
|
+
from ...beads.specs import load_task_specs
|
|
71
|
+
|
|
72
|
+
root = _project_root()
|
|
73
|
+
specs = load_task_specs(root)
|
|
74
|
+
status_filter = getattr(args, "status", None)
|
|
75
|
+
if status_filter:
|
|
76
|
+
specs = [s for s in specs if s.status == status_filter]
|
|
77
|
+
out_fmt = getattr(args, "format", "text")
|
|
78
|
+
if out_fmt == "json":
|
|
79
|
+
format_json_output([s.model_dump() for s in specs])
|
|
80
|
+
return
|
|
81
|
+
if not specs:
|
|
82
|
+
print("No task specs found.")
|
|
83
|
+
return
|
|
84
|
+
for s in specs:
|
|
85
|
+
beads = f" [bd:{s.beads_issue}]" if s.beads_issue else ""
|
|
86
|
+
print(f" {s.id} {s.status} {s.title or ''}{beads}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _handle_show(args: object) -> None:
|
|
90
|
+
from ...beads.specs import load_task_spec
|
|
91
|
+
|
|
92
|
+
task_id = getattr(args, "id", "").strip()
|
|
93
|
+
if not task_id:
|
|
94
|
+
print("task show: id required", file=sys.stderr)
|
|
95
|
+
sys.exit(2)
|
|
96
|
+
root = _project_root()
|
|
97
|
+
spec = load_task_spec(task_id, root)
|
|
98
|
+
if not spec:
|
|
99
|
+
print(f"Task not found: {task_id}", file=sys.stderr)
|
|
100
|
+
sys.exit(1)
|
|
101
|
+
print(f"id: {spec.id}")
|
|
102
|
+
print(f"title: {spec.title}")
|
|
103
|
+
print(f"status: {spec.status}")
|
|
104
|
+
print(f"workflow: {spec.workflow or 'build'}")
|
|
105
|
+
if spec.beads_issue:
|
|
106
|
+
print(f"beads_issue: {spec.beads_issue}")
|
|
107
|
+
if spec.description:
|
|
108
|
+
print(f"description: {spec.description}")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _handle_update(args: object) -> None:
|
|
112
|
+
from ...beads.specs import load_task_spec, save_task_spec
|
|
113
|
+
|
|
114
|
+
task_id = getattr(args, "id", "").strip()
|
|
115
|
+
status = getattr(args, "status", None)
|
|
116
|
+
if not task_id:
|
|
117
|
+
print("task update: id required", file=sys.stderr)
|
|
118
|
+
sys.exit(2)
|
|
119
|
+
if not status:
|
|
120
|
+
print("task update: --status required", file=sys.stderr)
|
|
121
|
+
sys.exit(2)
|
|
122
|
+
root = _project_root()
|
|
123
|
+
spec = load_task_spec(task_id, root)
|
|
124
|
+
if not spec:
|
|
125
|
+
print(f"Task not found: {task_id}", file=sys.stderr)
|
|
126
|
+
sys.exit(1)
|
|
127
|
+
spec = spec.model_copy(update={"status": status})
|
|
128
|
+
save_task_spec(spec, root)
|
|
129
|
+
print(f"Updated {task_id} status to {status}")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _handle_close(args: object) -> None:
|
|
133
|
+
from ...beads.specs import load_task_spec, save_task_spec
|
|
134
|
+
|
|
135
|
+
task_id = getattr(args, "id", "").strip()
|
|
136
|
+
if not task_id:
|
|
137
|
+
print("task close: id required", file=sys.stderr)
|
|
138
|
+
sys.exit(2)
|
|
139
|
+
root = _project_root()
|
|
140
|
+
spec = load_task_spec(task_id, root)
|
|
141
|
+
if not spec:
|
|
142
|
+
print(f"Task not found: {task_id}", file=sys.stderr)
|
|
143
|
+
sys.exit(1)
|
|
144
|
+
spec = spec.model_copy(update={"status": "done"})
|
|
145
|
+
save_task_spec(spec, root)
|
|
146
|
+
print(f"Closed {task_id}")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _handle_hydrate(args: object) -> None:
|
|
150
|
+
from ...beads.hydration import hydrate_to_beads
|
|
151
|
+
|
|
152
|
+
root = _project_root()
|
|
153
|
+
report = hydrate_to_beads(project_root=root)
|
|
154
|
+
if report.bd_unavailable:
|
|
155
|
+
print("Beads (bd) not available. Install to tools/bd or add bd to PATH.", file=sys.stderr)
|
|
156
|
+
sys.exit(1)
|
|
157
|
+
print(f"created={report.created} skipped={report.skipped} failed={report.failed} deps_added={report.deps_added}")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _handle_dehydrate(args: object) -> None:
|
|
161
|
+
from ...beads.hydration import dehydrate_from_beads
|
|
162
|
+
|
|
163
|
+
root = _project_root()
|
|
164
|
+
updated = dehydrate_from_beads(project_root=root)
|
|
165
|
+
print(f"Updated {updated} spec(s) from Beads.")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _handle_run(args: object) -> None:
|
|
169
|
+
from ...beads.specs import load_task_spec, save_task_spec
|
|
170
|
+
|
|
171
|
+
task_id = getattr(args, "id", "").strip()
|
|
172
|
+
if not task_id:
|
|
173
|
+
print("task run: id required", file=sys.stderr)
|
|
174
|
+
sys.exit(2)
|
|
175
|
+
root = _project_root()
|
|
176
|
+
spec = load_task_spec(task_id, root)
|
|
177
|
+
if not spec:
|
|
178
|
+
print(f"Task not found: {task_id}", file=sys.stderr)
|
|
179
|
+
sys.exit(1)
|
|
180
|
+
workflow_name = (spec.workflow or "build").strip().lower()
|
|
181
|
+
# Map task workflow name to preset
|
|
182
|
+
preset_map = {"build": "rapid", "fix": "fix", "review": "quality", "test": "quality", "full": "full"}
|
|
183
|
+
preset = preset_map.get(workflow_name, "rapid")
|
|
184
|
+
# Update spec to in-progress
|
|
185
|
+
spec = spec.model_copy(update={"status": "in-progress"})
|
|
186
|
+
save_task_spec(spec, root)
|
|
187
|
+
# Run workflow via CLI workflow path (simplified: invoke workflow preset)
|
|
188
|
+
try:
|
|
189
|
+
from ...workflow.executor import WorkflowExecutor
|
|
190
|
+
from ...workflow.preset_loader import PresetLoader
|
|
191
|
+
from ..base import run_async_command
|
|
192
|
+
|
|
193
|
+
loader = PresetLoader()
|
|
194
|
+
workflow = loader.load_preset(preset)
|
|
195
|
+
if not workflow:
|
|
196
|
+
print(f"Workflow preset not found: {preset}", file=sys.stderr)
|
|
197
|
+
spec = spec.model_copy(update={"status": "todo"})
|
|
198
|
+
save_task_spec(spec, root)
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
executor = WorkflowExecutor(auto_detect=False, auto_mode=True)
|
|
201
|
+
executor.user_prompt = spec.title or spec.description or spec.id
|
|
202
|
+
target_file = (spec.files or [None])[0] if spec.files else None
|
|
203
|
+
final_state = run_async_command(
|
|
204
|
+
executor.execute(workflow=workflow, target_file=target_file)
|
|
205
|
+
)
|
|
206
|
+
if final_state.status == "completed":
|
|
207
|
+
spec = spec.model_copy(update={"status": "done"})
|
|
208
|
+
save_task_spec(spec, root)
|
|
209
|
+
print(f"Task {task_id} completed.")
|
|
210
|
+
elif final_state.status == "blocked":
|
|
211
|
+
# BUG-003B fix: Set status to "blocked" when workflow fails
|
|
212
|
+
spec = spec.model_copy(update={"status": "blocked"})
|
|
213
|
+
save_task_spec(spec, root)
|
|
214
|
+
print(f"Workflow blocked: {final_state.error or 'Required step failed'}", file=sys.stderr)
|
|
215
|
+
sys.exit(1)
|
|
216
|
+
else:
|
|
217
|
+
# Other statuses (paused, etc.) - set to todo for retry
|
|
218
|
+
spec = spec.model_copy(update={"status": "todo"})
|
|
219
|
+
save_task_spec(spec, root)
|
|
220
|
+
print(f"Workflow ended with status: {final_state.status}", file=sys.stderr)
|
|
221
|
+
sys.exit(1)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
# BUG-003B fix: Set status to "blocked" on exception
|
|
224
|
+
spec = spec.model_copy(update={"status": "blocked"})
|
|
225
|
+
save_task_spec(spec, root)
|
|
226
|
+
print(f"Error running workflow: {e}", file=sys.stderr)
|
|
227
|
+
sys.exit(1)
|
|
@@ -1454,6 +1454,18 @@ def _print_init_results(results: dict[str, Any]) -> None:
|
|
|
1454
1454
|
print(" - .cursorignore")
|
|
1455
1455
|
else:
|
|
1456
1456
|
print(" .cursorignore: Skipped or already exists")
|
|
1457
|
+
|
|
1458
|
+
if results.get("hooks"):
|
|
1459
|
+
if results.get("hooks_templates"):
|
|
1460
|
+
print(" Hooks: Created from templates (all disabled)")
|
|
1461
|
+
print(" - .tapps-agents/hooks.yaml")
|
|
1462
|
+
if results.get("context_created"):
|
|
1463
|
+
print(" - .tapps-agents/context/")
|
|
1464
|
+
else:
|
|
1465
|
+
print(" Hooks: Minimal hooks.yaml created")
|
|
1466
|
+
print(" - .tapps-agents/hooks.yaml")
|
|
1467
|
+
else:
|
|
1468
|
+
print(" Hooks: Skipped or already exists")
|
|
1457
1469
|
|
|
1458
1470
|
# Show MCP config (will be shown in dedicated section)
|
|
1459
1471
|
# MCP status is now shown in _print_mcp_status() function
|
|
@@ -2194,6 +2206,7 @@ def handle_init_command(args: object) -> None:
|
|
|
2194
2206
|
backup_before_reset=not getattr(args, "no_backup", False),
|
|
2195
2207
|
reset_mcp=getattr(args, "reset_mcp", False),
|
|
2196
2208
|
preserve_custom=getattr(args, "preserve_custom", True),
|
|
2209
|
+
include_hooks_templates=getattr(args, "hooks", False),
|
|
2197
2210
|
)
|
|
2198
2211
|
|
|
2199
2212
|
# Offer interactive Context7 setup if API key is missing
|