{
  "schemaVersion": 1,
  "id": "P50-C05",
  "title": "Текстовые накладные: проверка сумм до сравнения парсеров",
  "author": {
    "id": "P50",
    "name": "Вячеслав Фомин"
  },
  "specialty": "Стоимость и скорость ИИ-сервисов",
  "projectStatus": "concept",
  "source": {
    "document": "catalogue_60_personas.md",
    "briefId": "P50-C05",
    "title": "Обработка входящих PDF",
    "kind": "editorial_concept",
    "data": "synthetic"
  },
  "context": "Быстрый разбор бесполезен, если 12,50 превращается в 12. Исходная работа была про PDF, но без настоящего PDF-движка я ограничил результат текстовым слоем и сохранил все документы.",
  "decision": "Baseline использует parseFloat напрямую. Revised нормализует десятичную запятую и сверяет сумму строк с явно заданным итогом. Ошибка не маскируется округлением или заявлением о скорости.",
  "constraint": "PDF и OCR не вызываются. Замер относится к разбору приложенных текстовых накладных.",
  "steps": [
    "Зафиксировать полный вход и два режима обработки.",
    "Проверить правильность результата до сравнения времени.",
    "Выполнить 50 прогревочных запусков и 30 серий по 100 повторов; сохранить все сводные времена."
  ],
  "inspection": [
    "Исправленный парсер принимает три документа, N4 оставляет расхождение 1 — проверено.",
    "Baseline теряет дробь и принимает только N1 — проверено.",
    "Исправление источника N4 на итог 30 закрывает конкретное расхождение — проверено."
  ],
  "sample": {
    "headers": [
      "Документ",
      "Сумма",
      "Итог",
      "Разница",
      "Приемка"
    ],
    "rows": [
      [
        "N1",
        "85",
        "85",
        "0",
        "Принято"
      ],
      [
        "N2",
        "85",
        "85",
        "0",
        "Принято"
      ],
      [
        "N3",
        "50",
        "50",
        "0",
        "Принято"
      ],
      [
        "N4",
        "30",
        "31",
        "-1",
        "Расхождение"
      ]
    ]
  },
  "sampleNote": "Авторский набор. В timings.json записан фактически выполненный локальный замер кода; тариф модели и сеть в него не входят.",
  "caseStudy": {
    "role": "Разработчик стендов измерения обработки данных",
    "contribution": "Я сравнил два разбора денежных строк, исправил десятичную запятую и сохранил отрицательный контроль итоговой суммы.",
    "objective": "Два парсера читают полные документы с точкой и запятой в цене; ошибочная дробь обнаруживается контрольным итогом.",
    "problem": "Быстрый разбор бесполезен, если 12,50 превращается в 12. Исходная работа была про PDF, но без настоящего PDF-движка я ограничил результат текстовым слоем и сохранил все документы.",
    "result": "Оба парсера выполнены на четырех полных документах. Прямой parseFloat прошел один, нормализация запятой — три; четвертый остался отклонен из-за ошибочного итога в самом документе. Время сравнивается рядом с этим различием правильности.",
    "deliverables": [
      "index.html",
      "source.json",
      "source.csv",
      "result.json",
      "result.csv",
      "engine.js",
      "checks.json",
      "style.css",
      "timings.json"
    ],
    "blocks": [
      {
        "type": "text",
        "title": "Исправленная запятая не исправляет неверный итог",
        "text": "Замена разбора десятичной запятой поднимает число успешных примеров с одного до трёх из четырёх. N4 остаётся ошибкой: там неверна итоговая сумма, а не формат числа. Я сохранил этот отказ, чтобы улучшение одного правила не выглядело универсальным исправлением любых финансовых данных."
      }
    ]
  },
  "deliverable": {
    "type": "analysis",
    "entry": "/catalogue/deliverables/p50-c05/index.html",
    "label": "Открыть работающий материал",
    "files": [
      {
        "path": "/catalogue/deliverables/p50-c05/index.html",
        "name": "index.html",
        "mimeType": "text/html"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/source.json",
        "name": "source.json",
        "mimeType": "application/json"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/source.csv",
        "name": "source.csv",
        "mimeType": "text/csv"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/result.json",
        "name": "result.json",
        "mimeType": "application/json"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/result.csv",
        "name": "result.csv",
        "mimeType": "text/csv"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/engine.js",
        "name": "engine.js",
        "mimeType": "text/javascript"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/verify.cjs",
        "name": "verify.cjs",
        "mimeType": "text/javascript"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/checks.json",
        "name": "checks.json",
        "mimeType": "application/json"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/style.css",
        "name": "style.css",
        "mimeType": "text/css"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/benchmark.cjs",
        "name": "benchmark.cjs",
        "mimeType": "text/javascript"
      },
      {
        "path": "/catalogue/deliverables/p50-c05/timings.json",
        "name": "timings.json",
        "mimeType": "application/json"
      }
    ],
    "summary": "Оба парсера выполнены на четырех полных документах. Прямой parseFloat прошел один, нормализация запятой — три; четвертый остался отклонен из-за ошибочного итога в самом документе. Время сравнивается рядом с этим различием правильности."
  },
  "takeaway": "Оба парсера выполнены на четырех полных документах. Прямой parseFloat прошел один, нормализация запятой — три; четвертый остался отклонен из-за ошибочного итога в самом документе. Время сравнивается рядом с этим различием правильности.",
  "capabilities": [
    "completed_analysis"
  ],
  "externalConnections": []
}
