Files
ss-tools/docs/adr/ADR-0014-agent-source-copy-strategy.md
busya 24d3b7d1f9 refactor(task-manager): implement task resilience and execution lifecycle improvements
Enhance the reliability and observability of the task execution engine
by introducing retry mechanisms, idempotency, and structured progress
tracking.

- Implement centralized retry logic with exponential backoff support
  in `JobLifecycle`.
- Add `retry_task` API endpoint and `TaskManager` method for manual
  task restarts.
- Introduce task idempotency using `_idempotency_key` to prevent
  duplicate executions.
- Add `retry_count`, `max_retries`, `last_error`, and `progress` fields
  to the `Task` model and ensure persistence via `TaskPersistenceService`.
- Upgrade `SchedulerService` to use differential synchronization with
  the persistent `SQLAlchemyJobStore` for better job durability.
- Implement structured heartbeat logging to support real-time progress
  updates.
- Update project documentation and ADRs to reflect the new plugin
  runtime and task resilience patterns.
- Add comprehensive unit and integration tests for the new task
  lifecycle features.
2026-07-12 15:31:56 +03:00

2.6 KiB

[DEF:ADR-0014:ADR]

@STATUS SUPERSEDED

@PURPOSE Historical source-copy strategy for the former backend-embedded agent. Superseded by ADR-0015 after extracting agent/ and shared/ into independent packages.

@SUPERSEDED_BY [ADR-0015:ADR]

@RELATION BINDS_TO -> [docker/Dockerfile.agent]

@RELATION CALLS -> [ADR-0001:ADR]

@RATIONALE The agent image (Dockerfile.agent) previously copied only src/core/cot_logger.py under the principle that core source in the agent must be stdlib-only to minimise image size and dependency surface. However, src/agent/run.py imports from src.core.logger import logger, which requires logger.py and its transitive dependency ws_log_handler.py (both depend on pydantic, not stdlib-only). This violated the copy contract silently — the bug only manifested at runtime when the image was (re)built.

@REJECTED Refactor run.py to use cot_logger directly — rejected because run.py needs the full structured logger (MarkerLogger protocol) with trace_id propagation, not the bare cot_log. Refactoring would duplicate business logic.

@REJECTED Copy the entire src/core/ — rejected because core/ contains route helpers, middleware, and other services the agent must never import. Blind bulk copy would violate container isolation.

Decision

The agent Dockerfile copies exactly these src/core/ files:

src/core/__init__.py
src/core/cot_logger.py      # stdlib-only, no business logic
src/core/logger.py           # requires pydantic + ws_log_handler
src/core/ws_log_handler.py   # requires pydantic

These files are infrastructure, not business logic — they provide logging, tracing, and structured output that the agent shares with the backend. The pydantic dependency is already satisfied by the agent's own requirements (requirements-agent.txt).

Do NOT add:

  • src/core/superset_client.py — business logic
  • src/core/task_manager.py — business logic
  • src/core/plugin_loader.py — business logic
  • Any src/api/, src/services/, src/models/ — backend-only

Consequences

  • Positive: Agent has working structured logging (trace_id, span_id, JSON output) matching the backend format.
  • Positive: No refactoring of run.py import chain needed.
  • Negative: Agent image carries logger.py (383 lines) and ws_log_handler.py which are not pure stdlib. The size impact is negligible (~5 KB for both files).
  • Risk: If logger.py or ws_log_handler.py gain new imports from business-logic modules, the agent image breaks at runtime. Mitigation: all src/core/ files imported by the agent are covered by the CI build smoke test for the agent image.