5. Работа с Synthesis++ (IPSM v2)

Выгрузка для ИИ (JSON)

Synthesis++ — канонический интерпретационный слой поверх numerology/astrology/bodygraph/forecast. Он нужен, чтобы интеграции работали со стабильным контрактом (summary/explain/export), а не парсили сырой профиль модулей.

# 5. Работа с Synthesis++ (IPSM v2)

# Работа с Synthesis++

List

  • Добавляйте "synthesis" в systems, если нужен устойчивый слой аналитики для UI, BI и внешних моделей.
  • Используйте view=summary как основной прод-контракт: это минимальный, стабильный и дешёвый по объёму ответ.
  • Используйте view=explain только там, где нужно объяснение причин результата: доменные вклады, конфликты и топ-факторы.
  • Используйте view=raw только для диагностики, аудита и проверки изменений модели.
  • Для BI/витрин не парсите raw_profile вручную — используйте export_result с row_type.

Этапы жизненного цикла

1

Клиент POST create_task

Передайте api_key, user и systems с "synthesis". При необходимости добавьте forecast/current_location/response.

2

Клиент GET get_result&view=summary

Получите стабильный результат: scales, superpower, quality_score, conflicts_count и health.

3

Клиент GET get_result&view=explain

При запросе объяснимости получите domain_components, breakdown_short, conflicts, reliability_summary и model_health.

4

Клиент GET export_result

Для BI-слоя выгружайте NDJSON/CSV: summary, domain_component и breakdown_item без дополнительного парсинга.

# Режимы выдачи synthesis

Поле / ПараметрТипОписание
summaryрежимРежим по умолчанию. Канонический слой: schema/calculation/weights версии, summary.scales, summary.superpower, summary.quality_score, summary.conflicts_count, health.
explainрежимРасширенный слой причин: domain_components по шкалам, breakdown_short (top 3+/3-), conflicts с evidence, reliability_summary, model_health.
rawрежимОтладочный режим. Возвращает полный raw_profile synthesis для внутренних проверок. Не использовать как внешний стабильный контракт.

# Параметры верхнего уровня

Поле / ПараметрТипОписание
summary.scalesobjectПять шкал IPSM v2 в диапазоне около -100..100: dynamics/control/cognition/focus/social.
summary.superpowerstringВедущая шкала по формальному правилу max|score|; при конфликте HIGH возможен формат dual_mode_.
summary.quality_scorenumberИнтегральная оценка качества данных 0..100.
domain_componentsobjectНормализованные вклады доменов по шкалам в том же пространстве, что и финальные score.
breakdown_shortobjectКороткое объяснение: топ-положительные и топ-отрицательные факторы по каждой шкале.
conflictsarrayДоменные конфликты с severity и доказательствами (evidence).
reliability_summaryobjectМетрики надёжности: simulated/status/missing, канонизация полей, удалённые дубли наблюдений, drift-флаги.
model_healthobjectДиагностика консистентности модели и инвариантов агрегации.

# Практические рекомендации

List

  • Всегда храните и проверяйте schema_version, calculation_version и weights_hash: это защита от тихих изменений логики.
  • Считайте summary единственным стабильным источником для ранжирования/фильтрации в интерфейсах.
  • Показывайте explain по требованию пользователя: это снижает объём трафика и сложность клиента.
  • Если quality_score низкий, учитывайте reliability_summary перед выводом жёстких рекомендаций.
  • Если нужно только темпоральное обновление, используйте response.omit_portrait_payload=true.

Bash (cURL)

Полный цикл: create_task с Synthesis++, затем чтение summary и explain.

Фрагмент кодаbash
# 1) Создание задачи
TASK=$(curl -s -X POST "https://digihash.ru/datacollector/api.php?action=create_task" \
  -H "Content-Type: application/json" \
  -H "X-Calc-Profile: A" \
  -d '{
    "api_key": "655351024",
    "user": {
      "first_name": "Иван",
      "last_name": "Иванов",
      "birth_date": "1990-01-01",
      "birth_time": "12:00",
      "birth_city": "Москва"
    },
    "systems": ["forecast", "transits", "synthesis"],
    "forecast": {
      "period_type": "day",
      "period_start_date": "2026-02-14"
    },
    "response": {
      "omit_portrait_payload": true
    }
  }')

REQUEST_ID=$(echo "$TASK" | jq -r '.request_id')

# 2) Канонический слой summary
curl -s "https://digihash.ru/datacollector/api.php?action=get_result&request_id=$REQUEST_ID&view=summary"

# 3) Слой объяснимости explain
curl -s "https://digihash.ru/datacollector/api.php?action=get_result&request_id=$REQUEST_ID&view=explain"

PHP

Пример опроса до success и безопасного переключения между view=summary и view=explain.

Фрагмент кодаphp
<?php
$api = 'https://digihash.ru/datacollector/api.php';
$requestId = 'task_xxx';

for ($i = 0; $i < 60; $i++) {
    sleep(2);
    $summary = json_decode(file_get_contents($api . '?action=get_result&view=summary&request_id=' . urlencode($requestId)), true);

    if (($summary['status'] ?? '') === 'success') {
        $scales = $summary['summary']['scales'] ?? [];
        $superpower = $summary['summary']['superpower'] ?? null;

        // Explain запрашиваем только по требованию
        $explain = json_decode(file_get_contents($api . '?action=get_result&view=explain&request_id=' . urlencode($requestId)), true);
        $conflicts = $explain['conflicts'] ?? [];

        print_r(['scales' => $scales, 'superpower' => $superpower, 'conflicts' => count($conflicts)]);
        exit;
    }

    if (($summary['status'] ?? '') === 'error') {
        throw new RuntimeException('Ошибка расчёта: ' . json_encode($summary['error'] ?? null, JSON_UNESCAPED_UNICODE));
    }
}

throw new RuntimeException('Таймаут ожидания результата');
?>

JavaScript (Fetch)

Экспорт NDJSON в BI и разбор row_type без привязки к raw_profile.

Фрагмент кодаjavascript
async function exportSynthesisNdjson(requestId) {
  const url = `https://digihash.ru/datacollector/api.php?action=export_result&request_id=${encodeURIComponent(requestId)}&format=ndjson`;
  const response = await fetch(url);
  const text = await response.text();

  const rows = text.trim().split('\n').map(line => JSON.parse(line));
  const summary = rows.find(r => r.row_type === 'summary');
  const domainRows = rows.filter(r => r.row_type === 'domain_component');
  const breakdownRows = rows.filter(r => r.row_type === 'breakdown_item');

  return { summary, domainRows, breakdownRows };
}