# release_check — Release Gate

**Єдиний оркестрований job для перевірки готовності до релізу**  
Нода: NODE2 (dev) + NODA1 (production)

---

## Що це?

`release_check` — internal task у Job Orchestrator, який послідовно запускає всі release gates і повертає єдиний структурований verdict `pass/fail`.

Замінює ручне запускання кожного gate окремо.

---

## Gates (послідовно)

| # | Gate | Tool | Умова блокування |
|---|------|------|-----------------|
| 1 | **PR Review** | `pr_reviewer_tool` (mode=`blocking_only`) | blocking_count > 0 |
| 2 | **Config Lint** | `config_linter_tool` (strict=true) | blocking_count > 0 |
| 3 | **Contract Diff** | `contract_tool` (fail_on_breaking=true) | breaking_count > 0 |
| 4 | **Threat Model** | `threatmodel_tool` (risk_profile) | unmitigated_high > 0 |
| 5 | **Smoke** *(optional)* | `job_orchestrator_tool` → `smoke_gateway` | job fail |
| 6 | **Drift** *(optional)* | `job_orchestrator_tool` → `drift_check_node1` | job fail |

Gates 1–4 завжди виконуються (якщо є вхідні дані).  
Gates 5–6 виконуються тільки при `run_smoke=true` / `run_drift=true`.

---

## Як запустити

### Через job_orchestrator_tool (рекомендовано)

```json
{
  "action": "start_task",
  "agent_id": "sofiia",
  "params": {
    "task_id": "release_check",
    "inputs": {
      "service_name": "router",
      "diff_text": "<unified diff>",
      "openapi_base": "<base OpenAPI spec>",
      "openapi_head": "<head OpenAPI spec>",
      "risk_profile": "agentic_tools",
      "fail_fast": false,
      "run_smoke": true,
      "run_drift": false
    }
  }
}
```

### Через Sofiia (OpenCode/Telegram)

```
"Запусти release_check для сервісу router з цим diff: ..."
"Зроби release gate перевірку"
```

### Dry run (тільки валідація)

```json
{
  "action": "start_task",
  "params": {
    "task_id": "release_check",
    "dry_run": true,
    "inputs": {"service_name": "router"}
  }
}
```

---

## Вхідні параметри (inputs_schema)

| Параметр | Тип | Обов'язковий | Опис |
|----------|-----|:---:|------|
| `service_name` | string | ✅ | Назва сервісу |
| `diff_text` | string | — | Unified diff (git diff) |
| `openapi_base` | string | — | OpenAPI base spec (text) |
| `openapi_head` | string | — | OpenAPI head spec (text) |
| `risk_profile` | enum | — | `default` / `agentic_tools` / `public_api` (default: `default`) |
| `fail_fast` | boolean | — | Зупинитись на першому fail (default: `false`) |
| `run_smoke` | boolean | — | Запустити smoke tests (default: `false`) |
| `run_drift` | boolean | — | Запустити drift check (default: `false`) |

---

## Вихідний формат

```json
{
  "pass": true,
  "gates": [
    {
      "name": "pr_review",
      "status": "pass",
      "blocking_count": 0,
      "summary": "No blocking issues found",
      "score": 95
    },
    {
      "name": "config_lint",
      "status": "pass",
      "blocking_count": 0,
      "total_findings": 2
    },
    {
      "name": "contract_diff",
      "status": "skipped",
      "reason": "openapi_base or openapi_head not provided"
    },
    {
      "name": "threat_model",
      "status": "pass",
      "unmitigated_high": 0,
      "risk_profile": "default"
    }
  ],
  "recommendations": [],
  "summary": "✅ RELEASE CHECK PASSED in 1234ms. Gates: ['pr_review', 'config_lint', 'threat_model'].",
  "elapsed_ms": 1234.5
}
```

### Gate statuses

| Status | Значення |
|--------|----------|
| `pass` | Gate пройшов |
| `fail` | Gate не пройшов (блокує реліз) |
| `skipped` | Вхідних даних не було (не блокує) |
| `error` | Внутрішня помилка gate |

---

## Інтерпретація результату

### `pass: true`
Всі mandatory gates пройшли → **можна випускати реліз**.

### `pass: false`
Хоча б один gate має `status: fail` → **реліз заблоковано**.  
Дивись `gates[].status == "fail"` та `recommendations` для деталей.

### `status: error`
Gate не зміг виконатись (internal error). Не є `fail`, але потребує уваги.

---

## Risk Profiles для Threat Model

| Профіль | Коли використовувати |
|---------|---------------------|
| `default` | Звичайний внутрішній сервіс |
| `agentic_tools` | Сервіс з tool-викликами, prompt injection ризики |
| `public_api` | Публічний API (rate limiting, WAF, auth hardening) |

---

## Необхідні Entitlements

Для запуску `release_check` агент повинен мати:
- `tools.pr_review.gate`
- `tools.contract.gate`
- `tools.config_lint.gate`
- `tools.threatmodel.gate`

Тільки агенти з роллю `agent_cto` (sofiia, yaromir) мають ці entitlements.

---

## Приклади сценаріїв

### Швидка перевірка PR (без openapi, без smoke)

```json
{
  "service_name": "gateway-bot",
  "diff_text": "...",
  "fail_fast": true
}
```

### Повний release pipeline для публічного API

```json
{
  "service_name": "router",
  "diff_text": "...",
  "openapi_base": "...",
  "openapi_head": "...",
  "risk_profile": "public_api",
  "run_smoke": true,
  "run_drift": true
}
```

### Тільки threat model (без diff)

```json
{
  "service_name": "auth-service",
  "risk_profile": "agentic_tools"
}
```

---

## Внутрішня архітектура

```
job_orchestrator_tool.start_task("release_check")
  → _job_orchestrator_tool() виявляє runner="internal"
  → release_check_runner.run_release_check(tool_manager, inputs, agent_id)
    → Gate 1: _run_pr_review()
    → Gate 2: _run_config_lint()
    → Gate 3: _run_dependency_scan()
    → Gate 4: _run_contract_diff()
    → Gate 5: _run_threat_model()
    → [Gate 6: _run_smoke()]
    → [Gate 7: _run_drift()]
    → Gate 8: _run_followup_watch()  (policy: off/warn/strict)
    → Gate 9: _run_privacy_watch()   (policy: off/warn/strict)
    → Gate 10: _run_cost_watch()     (always warn)
    → _build_report()
  → ToolResult(success=True, result=report)
```

Кожен gate викликає відповідний tool через `tool_manager.execute_tool()`.  
Governance middleware (RBAC, limits, audit) застосовується до кожного gate-виклику.

---

## Файли

| Файл | Призначення |
|------|-------------|
| `ops/task_registry.yml` | Реєстрація `release_check` task |
| `services/router/release_check_runner.py` | Internal runner (gates logic) |
| `config/release_gate_policy.yml` | Gate strictness profiles (dev/staging/prod) |
| `config/slo_policy.yml` | SLO thresholds per service |
| `tests/test_tool_governance.py` | Тести (включно з release_check fixtures) |
| `tests/test_release_check_followup_watch.py` | Follow-up watch gate tests |
