diff --git a/tests/test_api.py b/tests/test_api.py
index 80cfa04..c63e48b 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -2262,6 +2262,7 @@ def test_get_pipeline_logs_since_id_filters(client):
def test_get_pipeline_logs_not_found(client):
- """KIN-084: GET /api/pipelines/9999/logs → 404."""
+ """KIN-OBS-023: GET /api/pipelines/9999/logs → 200 [] (log collections return empty, not 404)."""
r = client.get("/api/pipelines/9999/logs")
- assert r.status_code == 404
+ assert r.status_code == 200
+ assert r.json() == []
diff --git a/web/api.py b/web/api.py
index 5f8a395..03bd387 100644
--- a/web/api.py
+++ b/web/api.py
@@ -761,12 +761,10 @@ def patch_task(task_id: str, body: TaskPatch):
@app.get("/api/pipelines/{pipeline_id}/logs")
def get_pipeline_logs(pipeline_id: int, since_id: int = 0):
- """Get pipeline log entries after since_id (for live console polling)."""
+ """Get pipeline log entries after since_id (for live console polling).
+ Returns [] if pipeline does not exist — consistent empty response for log collections.
+ """
conn = get_conn()
- row = conn.execute("SELECT id FROM pipelines WHERE id = ?", (pipeline_id,)).fetchone()
- if not row:
- conn.close()
- raise HTTPException(404, f"Pipeline {pipeline_id} not found")
logs = models.get_pipeline_logs(conn, pipeline_id, since_id=since_id)
conn.close()
return logs
diff --git a/web/frontend/src/api.ts b/web/frontend/src/api.ts
index 1071564..7c27ef9 100644
--- a/web/frontend/src/api.ts
+++ b/web/frontend/src/api.ts
@@ -199,6 +199,8 @@ export interface TaskFull extends Task {
pipeline_steps: PipelineStep[]
related_decisions: Decision[]
project_deploy_command: string | null
+ project_deploy_host: string | null
+ project_deploy_path: string | null
project_deploy_runtime: string | null
pipeline_id: string | null
}
diff --git a/web/frontend/src/views/TaskDetail.vue b/web/frontend/src/views/TaskDetail.vue
index bdaa8b7..2599a85 100644
--- a/web/frontend/src/views/TaskDetail.vue
+++ b/web/frontend/src/views/TaskDetail.vue
@@ -597,7 +597,7 @@ async function saveEdit() {
{{ resolvingManually ? 'Сохраняем...' : '✓ Решить вручную' }}
-