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.
Files changed (71) hide show
  1. tapps_agents/__init__.py +2 -2
  2. tapps_agents/agents/enhancer/agent.py +2728 -2728
  3. tapps_agents/agents/implementer/agent.py +35 -13
  4. tapps_agents/agents/reviewer/agent.py +43 -10
  5. tapps_agents/agents/reviewer/scoring.py +59 -68
  6. tapps_agents/agents/reviewer/tools/__init__.py +24 -0
  7. tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -0
  8. tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -0
  9. tapps_agents/beads/__init__.py +11 -0
  10. tapps_agents/beads/hydration.py +213 -0
  11. tapps_agents/beads/specs.py +206 -0
  12. tapps_agents/cli/commands/health.py +19 -3
  13. tapps_agents/cli/commands/simple_mode.py +842 -676
  14. tapps_agents/cli/commands/task.py +227 -0
  15. tapps_agents/cli/commands/top_level.py +13 -0
  16. tapps_agents/cli/main.py +658 -651
  17. tapps_agents/cli/parsers/top_level.py +1978 -1881
  18. tapps_agents/core/config.py +1622 -1622
  19. tapps_agents/core/init_project.py +3012 -2897
  20. tapps_agents/epic/markdown_sync.py +105 -0
  21. tapps_agents/epic/orchestrator.py +1 -2
  22. tapps_agents/epic/parser.py +427 -423
  23. tapps_agents/experts/adaptive_domain_detector.py +0 -2
  24. tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +15 -15
  25. tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +19 -44
  26. tapps_agents/health/checks/outcomes.backup_20260204_064058.py +324 -0
  27. tapps_agents/health/checks/outcomes.backup_20260204_064256.py +324 -0
  28. tapps_agents/health/checks/outcomes.backup_20260204_064600.py +324 -0
  29. tapps_agents/health/checks/outcomes.py +134 -46
  30. tapps_agents/health/orchestrator.py +12 -4
  31. tapps_agents/hooks/__init__.py +33 -0
  32. tapps_agents/hooks/config.py +140 -0
  33. tapps_agents/hooks/events.py +135 -0
  34. tapps_agents/hooks/executor.py +128 -0
  35. tapps_agents/hooks/manager.py +143 -0
  36. tapps_agents/session/__init__.py +19 -0
  37. tapps_agents/session/manager.py +256 -0
  38. tapps_agents/simple_mode/code_snippet_handler.py +382 -0
  39. tapps_agents/simple_mode/intent_parser.py +29 -4
  40. tapps_agents/simple_mode/orchestrators/base.py +185 -59
  41. tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2667 -2642
  42. tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +2 -2
  43. tapps_agents/simple_mode/workflow_suggester.py +37 -3
  44. tapps_agents/workflow/agent_handlers/implementer_handler.py +18 -3
  45. tapps_agents/workflow/cursor_executor.py +2337 -2118
  46. tapps_agents/workflow/direct_execution_fallback.py +16 -3
  47. tapps_agents/workflow/message_formatter.py +2 -1
  48. tapps_agents/workflow/models.py +38 -1
  49. tapps_agents/workflow/parallel_executor.py +43 -4
  50. tapps_agents/workflow/parser.py +375 -357
  51. tapps_agents/workflow/rules_generator.py +337 -337
  52. tapps_agents/workflow/skill_invoker.py +9 -3
  53. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/METADATA +5 -1
  54. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/RECORD +58 -54
  55. tapps_agents/agents/analyst/SKILL.md +0 -85
  56. tapps_agents/agents/architect/SKILL.md +0 -80
  57. tapps_agents/agents/debugger/SKILL.md +0 -66
  58. tapps_agents/agents/designer/SKILL.md +0 -78
  59. tapps_agents/agents/documenter/SKILL.md +0 -95
  60. tapps_agents/agents/enhancer/SKILL.md +0 -189
  61. tapps_agents/agents/implementer/SKILL.md +0 -117
  62. tapps_agents/agents/improver/SKILL.md +0 -55
  63. tapps_agents/agents/ops/SKILL.md +0 -64
  64. tapps_agents/agents/orchestrator/SKILL.md +0 -238
  65. tapps_agents/agents/planner/story_template.md +0 -37
  66. tapps_agents/agents/reviewer/templates/quality-dashboard.html.j2 +0 -150
  67. tapps_agents/agents/tester/SKILL.md +0 -71
  68. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/WHEEL +0 -0
  69. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/entry_points.txt +0 -0
  70. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/licenses/LICENSE +0 -0
  71. {tapps_agents-3.5.39.dist-info → tapps_agents-3.5.41.dist-info}/top_level.txt +0 -0
@@ -257,8 +257,15 @@ class DirectExecutionFallback:
257
257
  if skill_command.startswith("@"):
258
258
  skill_command = skill_command[1:]
259
259
 
260
- # Split into parts
261
- parts = skill_command.split()
260
+ # Split into parts, preserving quoted strings
261
+ # Use shlex.split() to handle complex quotes properly
262
+ # Use posix=True to properly handle quote removal (even on Windows)
263
+ try:
264
+ parts = shlex.split(skill_command, posix=True)
265
+ except ValueError as e:
266
+ # Provide helpful error message with truncated command
267
+ cmd_preview = skill_command[:200] + "..." if len(skill_command) > 200 else skill_command
268
+ raise ValueError(f"Invalid skill command (malformed quotes): {cmd_preview}") from e
262
269
 
263
270
  if not parts:
264
271
  raise ValueError(f"Invalid skill command: {skill_command}")
@@ -282,7 +289,13 @@ class DirectExecutionFallback:
282
289
  if command_name:
283
290
  cli_parts.append(command_name)
284
291
 
285
- cli_parts.extend(remaining_args)
292
+ # Safely quote arguments that may contain spaces or special characters
293
+ for arg in remaining_args:
294
+ # Check if arg needs quoting (contains spaces, quotes, or special chars)
295
+ if ' ' in arg or '"' in arg or "'" in arg:
296
+ cli_parts.append(shlex.quote(arg))
297
+ else:
298
+ cli_parts.append(arg)
286
299
 
287
300
  return " ".join(cli_parts)
288
301
 
@@ -103,9 +103,10 @@ class MessageFormatter:
103
103
  """
104
104
  emoji = self._get_emoji("block") if self.config.use_emoji else ""
105
105
  intent_display = user_intent or "Implement feature"
106
+ path_display = Path(file_path).as_posix()
106
107
 
107
108
  lines = [
108
- f"{emoji}Direct file edit blocked: {file_path}".strip(),
109
+ f"{emoji}Direct file edit blocked: {path_display}".strip(),
109
110
  "",
110
111
  f"Detected intent: {workflow.value} (confidence: {confidence:.0f}%)",
111
112
  "",
@@ -5,7 +5,7 @@ Workflow models - Data structures for workflow definitions.
5
5
  from dataclasses import dataclass, field
6
6
  from datetime import datetime
7
7
  from enum import Enum
8
- from typing import Any
8
+ from typing import Any, Literal
9
9
 
10
10
 
11
11
  class WorkflowType(Enum):
@@ -95,6 +95,43 @@ class StepExecution:
95
95
  error: str | None = None
96
96
 
97
97
 
98
+ @dataclass
99
+ class StepResult:
100
+ """Result of step execution with proper error handling.
101
+
102
+ This class represents the outcome of executing a workflow step,
103
+ including success/failure status, error details, and artifacts created.
104
+ Used by CursorExecutor to properly track step outcomes and halt
105
+ workflows when required steps fail.
106
+ """
107
+
108
+ step_id: str
109
+ status: Literal["completed", "failed", "skipped"]
110
+ success: bool
111
+ duration: float
112
+ started_at: datetime
113
+ completed_at: datetime
114
+ error: str | None = None
115
+ error_traceback: str | None = None
116
+ artifacts: list[str] = field(default_factory=list)
117
+ skip_reason: str | None = None
118
+
119
+ def to_dict(self) -> dict[str, Any]:
120
+ """Convert to dictionary for serialization."""
121
+ return {
122
+ "step_id": self.step_id,
123
+ "status": self.status,
124
+ "success": self.success,
125
+ "duration": self.duration,
126
+ "started_at": self.started_at.isoformat(),
127
+ "completed_at": self.completed_at.isoformat(),
128
+ "error": self.error,
129
+ "error_traceback": self.error_traceback,
130
+ "artifacts": self.artifacts,
131
+ "skip_reason": self.skip_reason,
132
+ }
133
+
134
+
98
135
  @dataclass
99
136
  class WorkflowState:
100
137
  """Workflow execution state."""
@@ -127,21 +127,60 @@ class ParallelStepExecutor:
127
127
  """
128
128
  Find steps that are ready to execute (dependencies met).
129
129
 
130
+ This method respects the workflow's sequential 'next:' chain to prevent
131
+ premature step execution. A step is only ready if:
132
+ 1. It's the 'next:' step from a completed step, OR it's the first step
133
+ 2. All its artifact dependencies are met
134
+
135
+ This ensures workflows follow the intended sequence (enhance→planning→
136
+ implementation→review→testing→complete) instead of jumping to the final
137
+ step prematurely.
138
+
139
+ Fix for: Workflow Auto-Continuation Issue (BUG - Workflow stops after 1 step)
140
+ Root cause: Previous logic only checked artifact dependencies, allowing
141
+ 'complete' step to execute immediately after 'enhance' because it had
142
+ no 'requires' dependencies.
143
+
130
144
  Args:
131
145
  workflow_steps: All workflow steps
132
146
  completed_step_ids: Set of completed step IDs
133
147
  running_step_ids: Set of currently running step IDs
134
148
  available_artifacts: Set of available artifact names (from state.artifacts)
135
- Returns:
136
- List of steps ready to execute
149
+
150
+ Returns:
151
+ List of steps ready to execute
137
152
  """
138
153
  ready: list[WorkflowStep] = []
139
154
  artifacts = available_artifacts or set()
140
155
 
156
+ # Build set of next steps from completed steps' next: fields
157
+ next_step_ids: set[str] = set()
158
+ for step in workflow_steps:
159
+ if step.id in completed_step_ids and step.next:
160
+ next_step_ids.add(step.next)
161
+
162
+ # If no completed steps yet, first step is ready
163
+ if not completed_step_ids:
164
+ first_step = workflow_steps[0] if workflow_steps else None
165
+ if first_step and first_step.id not in running_step_ids:
166
+ # Still check artifact dependencies for first step
167
+ if first_step.requires:
168
+ all_met = all(req in artifacts for req in first_step.requires)
169
+ if all_met:
170
+ return [first_step]
171
+ else:
172
+ return [first_step]
173
+ return []
174
+
175
+ # Find steps that are in the next_step_ids set (sequential progression)
141
176
  for step in workflow_steps:
142
177
  if step.id in completed_step_ids or step.id in running_step_ids:
143
178
  continue
144
179
 
180
+ # Must be in the next_step_ids set (respects sequential workflow chain)
181
+ if step.id not in next_step_ids:
182
+ continue
183
+
145
184
  # Check if all required artifacts exist and are available
146
185
  if step.requires:
147
186
  all_met = all(req in artifacts for req in step.requires)
@@ -342,7 +381,7 @@ class ParallelStepExecutor:
342
381
  tasks_map[task] = step
343
382
 
344
383
  # All tasks completed successfully - collect results
345
- for task, step in tasks_map.items():
384
+ for task in tasks_map:
346
385
  result = await task
347
386
  results.append(result)
348
387
 
@@ -416,7 +455,7 @@ class ParallelStepExecutor:
416
455
 
417
456
  # Re-raise the first exception for upstream handling
418
457
  if eg.exceptions:
419
- raise eg.exceptions[0]
458
+ raise eg.exceptions[0] from None
420
459
 
421
460
  # Sort by step.id for deterministic ordering
422
461
  results.sort(key=lambda r: r.step.id)