zorya-classifier 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +31 -17
  2. package/dist/app/classifier-config.d.ts +30 -0
  3. package/dist/app/classifier-config.js +46 -0
  4. package/dist/app/classifier-contracts.d.ts +32 -0
  5. package/dist/app/classifier-contracts.js +1 -0
  6. package/dist/app/classifier-runtime.d.ts +7 -0
  7. package/dist/app/classifier-runtime.js +71 -0
  8. package/dist/app/classifier-spatial.d.ts +31 -0
  9. package/dist/app/classifier-spatial.js +78 -0
  10. package/dist/app/cli-arguments.d.ts +2 -2
  11. package/dist/app/composed-classifier.d.ts +17 -0
  12. package/dist/app/composed-classifier.js +1 -0
  13. package/dist/app/create-classifier.d.ts +9 -33
  14. package/dist/app/create-classifier.js +53 -245
  15. package/dist/cli.js +1 -1
  16. package/dist/entities/classification.d.ts +83 -0
  17. package/dist/entities/classification.js +28 -0
  18. package/dist/entities/contracts.d.ts +6 -475
  19. package/dist/entities/contracts.js +6 -97
  20. package/dist/entities/decision.d.ts +211 -0
  21. package/dist/entities/decision.js +33 -0
  22. package/dist/entities/geometry.d.ts +37 -0
  23. package/dist/entities/geometry.js +26 -0
  24. package/dist/entities/image.d.ts +30 -0
  25. package/dist/entities/image.js +12 -0
  26. package/dist/entities/localization.d.ts +110 -0
  27. package/dist/entities/localization.js +13 -0
  28. package/dist/entities/object-proposals.d.ts +1 -1
  29. package/dist/entities/representation.d.ts +0 -183
  30. package/dist/entities/representation.js +1 -33
  31. package/dist/entities/segmentation-metadata.d.ts +70 -0
  32. package/dist/entities/segmentation-metadata.js +21 -1
  33. package/dist/entities/segmentation-verification.d.ts +1 -1
  34. package/dist/entities/segmentation.d.ts +5 -20
  35. package/dist/entities/validation.d.ts +2 -0
  36. package/dist/entities/validation.js +9 -0
  37. package/dist/entities/whole-object.d.ts +6 -21
  38. package/dist/features/choice-beam-layout.js +2 -7
  39. package/dist/features/proposals/presentation.d.ts +21 -0
  40. package/dist/features/proposals/presentation.js +122 -0
  41. package/dist/features/proposals/validation.d.ts +138 -0
  42. package/dist/features/proposals/validation.js +125 -0
  43. package/dist/features/segmentation/box-check.js +10 -23
  44. package/dist/features/segmentation/mask.js +2 -7
  45. package/dist/features/segmentation/region-result.d.ts +18 -0
  46. package/dist/features/segmentation/region-result.js +171 -0
  47. package/dist/features/segmentation/source-mask.d.ts +6 -0
  48. package/dist/features/segmentation/source-mask.js +32 -0
  49. package/dist/features/segmentation/validation.d.ts +9 -0
  50. package/dist/features/segmentation/validation.js +94 -0
  51. package/dist/infrastructure/decision-transport/errors.d.ts +8 -0
  52. package/dist/infrastructure/decision-transport/errors.js +34 -0
  53. package/dist/infrastructure/decision-transport/images.d.ts +1 -0
  54. package/dist/infrastructure/decision-transport/images.js +52 -0
  55. package/dist/infrastructure/{openrouter-common.d.ts → decision-transport/request.d.ts} +6 -15
  56. package/dist/infrastructure/decision-transport/request.js +162 -0
  57. package/dist/infrastructure/decision-transport/response.d.ts +1 -0
  58. package/dist/infrastructure/decision-transport/response.js +72 -0
  59. package/dist/infrastructure/decision-transport/route-identity.d.ts +11 -0
  60. package/dist/infrastructure/decision-transport/route-identity.js +23 -0
  61. package/dist/infrastructure/openrouter-vision.js +1 -1
  62. package/dist/infrastructure/openrouter.js +7 -19
  63. package/dist/infrastructure/raster.js +3 -8
  64. package/dist/infrastructure/segmentation/grabcut/index.d.ts +2 -2
  65. package/dist/infrastructure/segmentation/grabcut/index.js +3 -5
  66. package/dist/infrastructure/segmentation/grabcut/masks.d.ts +49 -0
  67. package/dist/infrastructure/segmentation/grabcut/masks.js +89 -0
  68. package/dist/infrastructure/segmentation/grabcut/model-asset.d.ts +4 -0
  69. package/dist/infrastructure/segmentation/grabcut/model-asset.js +4 -0
  70. package/dist/infrastructure/segmentation/grabcut/runtime.d.ts +70 -0
  71. package/dist/infrastructure/segmentation/grabcut/runtime.js +96 -0
  72. package/dist/infrastructure/segmentation/grabcut/worker-inference.d.ts +4 -43
  73. package/dist/infrastructure/segmentation/grabcut/worker-inference.js +4 -187
  74. package/dist/infrastructure/segmentation/mobile-sam/index.d.ts +3 -66
  75. package/dist/infrastructure/segmentation/mobile-sam/index.js +2 -478
  76. package/dist/infrastructure/segmentation/mobile-sam/input.d.ts +46 -0
  77. package/dist/infrastructure/segmentation/mobile-sam/input.js +83 -0
  78. package/dist/infrastructure/segmentation/mobile-sam/model-assets.d.ts +8 -0
  79. package/dist/infrastructure/segmentation/mobile-sam/model-assets.js +8 -0
  80. package/dist/infrastructure/segmentation/mobile-sam/object-proposals.d.ts +7 -0
  81. package/dist/infrastructure/segmentation/mobile-sam/object-proposals.js +124 -0
  82. package/dist/infrastructure/segmentation/mobile-sam/options.d.ts +43 -0
  83. package/dist/infrastructure/segmentation/mobile-sam/options.js +19 -0
  84. package/dist/infrastructure/segmentation/mobile-sam/proposal-masks.d.ts +26 -0
  85. package/dist/infrastructure/segmentation/mobile-sam/proposal-masks.js +71 -0
  86. package/dist/infrastructure/segmentation/mobile-sam/segmentation-masks.d.ts +112 -0
  87. package/dist/infrastructure/segmentation/mobile-sam/segmentation-masks.js +230 -0
  88. package/dist/infrastructure/segmentation/mobile-sam/segmenter.d.ts +22 -0
  89. package/dist/infrastructure/segmentation/mobile-sam/segmenter.js +268 -0
  90. package/dist/infrastructure/segmentation/mobile-sam/worker-expand.d.ts +7 -0
  91. package/dist/infrastructure/segmentation/mobile-sam/worker-expand.js +188 -0
  92. package/dist/infrastructure/segmentation/mobile-sam/worker-inference.d.ts +6 -149
  93. package/dist/infrastructure/segmentation/mobile-sam/worker-inference.js +6 -845
  94. package/dist/infrastructure/segmentation/mobile-sam/worker-models.d.ts +14 -0
  95. package/dist/infrastructure/segmentation/mobile-sam/worker-models.js +72 -0
  96. package/dist/infrastructure/segmentation/mobile-sam/worker-proposals.d.ts +7 -0
  97. package/dist/infrastructure/segmentation/mobile-sam/worker-proposals.js +159 -0
  98. package/dist/infrastructure/segmentation/mobile-sam/worker-segment.d.ts +4 -0
  99. package/dist/infrastructure/segmentation/mobile-sam/worker-segment.js +126 -0
  100. package/dist/infrastructure/segmentation/native-protocol.d.ts +59 -34
  101. package/dist/infrastructure/segmentation/native-protocol.js +26 -16
  102. package/dist/infrastructure/segmentation/proposal-presentation-input.d.ts +20 -0
  103. package/dist/infrastructure/segmentation/proposal-presentation-input.js +107 -0
  104. package/dist/infrastructure/segmentation/proposal-presentation-pixels.d.ts +8 -0
  105. package/dist/infrastructure/segmentation/proposal-presentation-pixels.js +93 -0
  106. package/dist/infrastructure/segmentation/proposal-presentation.js +10 -201
  107. package/dist/infrastructure/vision-chat/options.d.ts +62 -0
  108. package/dist/infrastructure/vision-chat/options.js +46 -0
  109. package/dist/infrastructure/vision-chat/request.d.ts +23 -0
  110. package/dist/infrastructure/vision-chat/request.js +109 -0
  111. package/dist/infrastructure/vision-chat/response.d.ts +3 -0
  112. package/dist/infrastructure/vision-chat/response.js +105 -0
  113. package/dist/infrastructure/vision-chat.d.ts +4 -61
  114. package/dist/infrastructure/vision-chat.js +8 -271
  115. package/dist/openai-compatible.js +1 -1
  116. package/dist/processes/extract-from-region.js +11 -216
  117. package/dist/processes/extract.d.ts +2 -8
  118. package/dist/processes/extract.js +12 -128
  119. package/dist/processes/proposal-location.js +5 -251
  120. package/docs/README.ru.md +50 -33
  121. package/docs/acceptance.md +6 -4
  122. package/docs/agents.ru.md +97 -0
  123. package/docs/api.md +4 -4
  124. package/docs/architecture.md +33 -7
  125. package/docs/architecture.ru.md +146 -0
  126. package/docs/benchmarks.md +3 -1
  127. package/docs/development.ru.md +141 -0
  128. package/docs/migrations/experimental-text-image-removal.ru.md +9 -0
  129. package/docs/provenance.json +288 -1
  130. package/docs/publishing.md +5 -3
  131. package/docs/refactoring-plan.ru.md +183 -0
  132. package/docs/v02-usage.md +8 -8
  133. package/docs/vision-results.md +1 -1
  134. package/package.json +5 -3
  135. package/dist/infrastructure/boundary-view.d.ts +0 -2
  136. package/dist/infrastructure/boundary-view.js +0 -263
  137. package/dist/infrastructure/openrouter-common.js +0 -317
  138. package/dist/infrastructure/text-representation.d.ts +0 -23
  139. package/dist/infrastructure/text-representation.js +0 -226
package/docs/README.ru.md CHANGED
@@ -1,42 +1,56 @@
1
1
  # Zorya Classifier: руководство
2
2
 
3
- Версия 0.2 добавляет прозрачный PNG, бинарную маску, её рамку и центр. Прежний поиск области служит подсказкой для сегментации всего исходного изображения. Затем decision проверяет рамку; допускаются одно расширение маски и повторная проверка. [Руководство](v02-usage.md) описывает API, CLI и владение ресурсами.
3
+ > **В этом пилоте H8a дал более полные рамки без дообучения: 7/9 против 3/9 у встроенного Jev 1.14**
4
+ >
5
+ > Это один открытый пилот DEV12: 12 задач на 9 исходных изображениях (четыре цели интерфейса используют один скриншот), 9 задач с объектом и 3 без. Сравниваются исторический результат H8a и один новый прогон Jev. Конвейер сегментации формирует маски-кандидаты, а явно настроенная модель OpenAI **gpt-6-luna** выбирает одну из них; рамка строится по пикселям выбранной маски. Дополнительного обучения для этого сравнения не было. Встроенный Jev 1.14 использует Box+Noul и возвращает рамку, а не маску. Для строгого зачёта одна и та же рамка-кандидат должна иметь IoU ≥0,5 с рамкой эталонного объекта и покрывать не менее 90% этой эталонной рамки. Это не проверка на отложенной выборке и не квалификация точности.
6
+ >
7
+ > | Показатель | H8a | Jev 1.14 |
8
+ > | -------------------------------------------------------- | ---------------- | ------------- |
9
+ > | Строгий критерий рамки | 7/9 | 3/9 |
10
+ > | IoU ≥0,5 без проверки покрытия (вспомогательная метрика) | 7/9 | 8/9 |
11
+ > | Ложные обнаружения, когда объекта нет (меньше — лучше) | 2/3 (Bowl, Undo) | 1/3 (Fighter) |
12
+ >
13
+ > [Полный отчёт](https://github.com/zoomplus/zorya-classifier/blob/v0.2.3/docs/research/v03-jev-native-box-results.ru.md) · [JSON-доказательная база](https://github.com/zoomplus/zorya-classifier/blob/v0.2.3/docs/evidence/v03/jev-native-box-dev12-20261025.json) · [Скачать визуальное сравнение ZIP](https://github.com/zoomplus/zorya-classifier/releases/download/v0.2.3/jev-native-box-dev12-comparison.zip)
14
+ >
15
+ > H8a здесь — только исследовательский рецепт: он не является стандартным путём `locate`/`extract` и не поставляется в npm как стратегия H8. Эти результаты не доказывают общую точность.
16
+
17
+ Версия 0.2 добавляет прозрачный PNG, бинарную маску, её рамку и центр. Прежний поиск области служит подсказкой для сегментации всего исходного изображения. Затем порт решений проверяет рамку; допускаются одно расширение маски и повторная проверка. [Руководство](v02-usage.md) описывает API, CLI и владение ресурсами.
4
18
 
5
19
  [Независимый тест 80 случаев](evidence/v02/region-seeded-heldout-v3/README.md) прошёл согласованные критерии, но показал ограниченную полноту: 26/60 попаданий в область объекта и 8/60 полных рамок, без ложных выделений на 20 отрицательных случаях. Из 30 эталонных масок восемь достигли IoU 0,8, три не достигли, для 19 предсказание отсутствовало. Это результаты одной явно настроенной комбинации Luna/OpenAI и MobileSAM, а не гарантия для любой модели или игры.
6
20
 
7
- Сравнение шести способов передачи изображения текстом завершено на свежих фотографиях и реальном интерфейсе: ни один не прошёл требования локализации. [Результаты и ограничения](evidence/v02/fresh-text/README.md) сохранены, публичный экспериментальный режим явно возвращает `UNSUPPORTED`.
21
+ Сравнение шести способов передачи изображения текстом завершено на свежих фотографиях и реальном интерфейсе: ни один не прошёл требования локализации. [Результаты и ограничения](evidence/v02/fresh-text/README.md) сохранены; публичный селектор IMAGE-AS-TEXT удалён — запросы с ним отклоняются на этапе валидации (`INVALID_INPUT`). Кодеки остаются только в `benchmarks/experiments/`.
8
22
 
9
- Zorya Classifier — библиотека для Node.js и TypeScript с поддерживаемой классификацией по тексту и изображениям и экспериментальной, не квалифицированной для общего применения пространственной локализацией и извлечением объектов. Библиотека не выбирает и не подключает модель за приложение: клиент получает явно переданный `DecisionPort` — готовый адаптер с выбранными настройками или собственную реализацию. Модель и провайдер в примерах — лишь варианты интеграции, не значения по умолчанию. Код распространяется по MIT; веса модели в поставку не входят, запросы удалённых моделей оплачиваются отдельно; можно подключить и свой локальный сервер. Совместимость и качество зависят от выбранного маршрута. Более мощная модель может помочь, но улучшение точности не гарантировано. Проверенные комбинации и результаты перечислены в [таблице моделей](vision-results.md).
23
+ Zorya Classifier — библиотека для Node.js и TypeScript с поддерживаемой классификацией по тексту и изображениям и реализованными API пространственной локализации и извлечения объектов (модель, провайдер и нативные ресурсы — на стороне вызывающего). Библиотека не выбирает и не подключает модель за приложение: клиент получает явно переданный `DecisionPort` — готовый адаптер с выбранными настройками или собственную реализацию. Модель и провайдер в примерах — лишь варианты интеграции, не значения по умолчанию. Код распространяется по MIT; веса модели в поставку не входят, запросы удалённых моделей оплачиваются отдельно; можно подключить и свой локальный сервер. Совместимость и качество зависят от выбранного маршрута. Более мощная модель может помочь, но улучшение точности не гарантировано. Проверенные комбинации и результаты перечислены в [таблице моделей](vision-results.md).
10
24
 
11
25
  Это самостоятельная библиотека: ей не нужны Zorya Games, Electron, база данных или игровой процесс. Её можно встроить в сервер, бота, инструмент обработки фотографий или собственный HTTP-сервис. Готовый постоянно работающий HTTP-сервер в пакет не входит.
12
26
 
13
27
  ## Статус возможностей
14
28
 
15
- Дальнейшие эксперименты по точности пространственных сценариев остановлены; ни одна стратегия локализации, извлечения или предложений масок не продвигается для общего использования. Исторические метрики в `docs/evidence/**` сохранены без переинтерпретации.
29
+ Пространственные API реализованы и документированы; сравнение рамок [H8a vs Jev на DEV12](https://github.com/zoomplus/zorya-classifier/blob/v0.2.3/docs/research/v03-jev-native-box-results.ru.md) — один исследовательский рецепт, не default библиотеки. Исторические метрики в `docs/evidence/**` сохранены без переинтерпретации. Сквозной ordinary-vision профиль H8a на DEV12 также описан в [базовом отчёте](https://github.com/zoomplus/zorya-classifier/blob/v0.2.3/docs/research/v03-h8a-development-baseline.ru.md).
16
30
 
17
- | Возможность | Статус | Примечание |
18
- | --------------------------------------------- | ---------------- | ------------------------------------------------------------------------------ |
19
- | `classify` с явным `DecisionPort` | Поддерживается | Один закрытый ID класса; без заявления об универсальной точности модели |
20
- | `locate` (сетка регионов) | Экспериментально | Гипотеза по ячейке, не геометрия целого объекта и не доказательство отсутствия |
21
- | `RefinementPort` | Экспериментально | Без общей квалификации качества |
22
- | `locate({ mode: 'whole-object' })` | Экспериментально | Интервалы или сегментация вызывающего; без квалификации |
23
- | `extract`, `SegmentationPort`, проверка рамки | Экспериментально | Структурный успех ≠ семантическая точность маски |
24
- | `objectProposals`, нативные фабрики | Экспериментально | На стороне вызывающего; без квалификации |
25
- | `experimental-text` | Отклонено | `UNSUPPORTED`, пока профиль не пройдёт отбор |
31
+ | Возможность | Статус | Примечание |
32
+ | --------------------------------------------- | -------------- | ------------------------------------------------------------------------------ |
33
+ | `classify` с явным `DecisionPort` | Поддерживается | Один закрытый ID класса; без заявления об универсальной точности модели |
34
+ | `locate` (сетка регионов) | Доступно | Гипотеза по ячейке, не геометрия целого объекта и не доказательство отсутствия |
35
+ | `RefinementPort` | Доступно | Опциональный legacy-хук на стороне вызывающего |
36
+ | `locate({ mode: 'whole-object' })` | Доступно | Интервалы или сегментация вызывающего |
37
+ | `extract`, `SegmentationPort`, проверка рамки | Доступно | Структурный успех ≠ семантическая точность маски |
38
+ | `objectProposals`, нативные фабрики | Доступно | На стороне вызывающего; ресурсы модели/runtime не поставляются библиотекой |
39
+ | `experimental-text` | Удалено из API | `INVALID_INPUT`; исследовательские кодеки только в benchmarks |
26
40
 
27
41
  Heldout region-seeded (один задокументированный рецепт): 26/60 попаданий seed на позитивах; 8/60 полных рамок объекта; на 30 эталонных масках — 8 с IoU 0,8, 3 неудачи, 19 без предсказания. H8 DEV: 7/9 позитивов и 2/3 ложных выхода, без квалификации. Узкий исторический admission — не общая пространственная квалификация.
28
42
 
29
43
  ## Что умеет
30
44
 
31
- | Задача | Статус | API | Результат |
32
- | ---------------------------------------------------------- | ---------------- | ----------------------------------- | --------------------------------------------------------------------------------- |
33
- | Распределить обращения по отделам, определить намерение | Поддерживается | `classify` с текстом | Один из заданных классов и ранжирование вариантов |
34
- | Проверить наличие объекта или выбрать категорию фотографии | Поддерживается | `classify` с изображением | Один из заданных классов |
35
- | Оценить изображение с текстовым условием | Поддерживается | `classify` с текстом и изображением | Класс с учётом обоих входов |
36
- | Найти примерную область предмета, значка или указателя | Экспериментально | `locate` | Ячейка в координатах исходного изображения либо явная неопределённость/отсутствие |
37
- | Получить маску, рамку, центр и прозрачный вырез предмета | Экспериментально | `extract` с явным сегментатором | Геометрия и вырез, выведенные из пикселей маски |
45
+ | Задача | Статус | API | Результат |
46
+ | ---------------------------------------------------------- | -------------- | ----------------------------------- | --------------------------------------------------------------------------------- |
47
+ | Распределить обращения по отделам, определить намерение | Поддерживается | `classify` с текстом | Один из заданных классов и ранжирование вариантов |
48
+ | Проверить наличие объекта или выбрать категорию фотографии | Поддерживается | `classify` с изображением | Один из заданных классов |
49
+ | Оценить изображение с текстовым условием | Поддерживается | `classify` с текстом и изображением | Класс с учётом обоих входов |
50
+ | Найти примерную область предмета, значка или указателя | Доступно | `locate` | Ячейка в координатах исходного изображения либо явная неопределённость/отсутствие |
51
+ | Получить маску, рамку, центр и прозрачный вырез предмета | Доступно | `extract` с явным сегментатором | Геометрия и вырез, выведенные из пикселей маски |
38
52
 
39
- Для `extract` после сегментации модель получает исходную картинку с рамкой маски и отметкой прежней найденной области. Она выбирает один ответ: весь видимый объект внутри, нужно расширение или определить не удалось. При необходимости сегментатор один раз ищет внешнюю маску, содержащую прежние пиксели; её рамка проверяется повторно. Максимум получается пять модельных запросов: три на поиск области и два на проверку. Если подтверждения нет, библиотека возвращает неопределённость без частичного выреза. `verification` сохраняет проверки и результат расширения. Рамка и центр всегда вычисляются из маски; проверка рамки не гарантирует точности каждого пикселя. Своя модель подключается через `DecisionPort`, отдельная проверка — через `segmentationBoxCheck`.
53
+ Для `extract` после сегментации порт решений получает полный исходник с рамкой из маски и исходной подсказкой `seed`. Ответ закрыт: `complete` (можно вернуть результат и опциональный вырез), `needs-expansion` (не более одного расширения охватывающей маски и одной финальной проверки; повторный `complete` после финальной проверки тоже допускает результат) или `unknown` (неразрешённая проверка, нет поддержки расширения, нет действительной охватывающей маски или провал финальной проверки — второго расширения нет). Внутри одного `extract` со встроенным `locate` — до трёх запросов на поиск области и до двух закрытых проверок рамки. Без подтверждения библиотека возвращает неопределённость и не публикует частичный вырез. Рамка и центр только из пикселей маски; успешная проверка рамки не доказывает идеальную сегментацию по пикселям. Порт решений подключается через `DecisionPort`; сегментатор остаётся на стороне вызывающего.
40
54
 
41
55
  Сконфигурированный `DecisionPort` выполняет запросы по контракту библиотеки. `classify` делает один запрос, а `locate` — до трёх последовательных запросов: крупная сетка → уточнение в четырёх выбранных областях → сравнение четырёх увеличенных кандидатов. Проверки присутствия входят в те же запросы. Порт отвечает за ответы, координаты вычисляет код.
42
56
 
@@ -44,7 +58,7 @@ Heldout region-seeded (один задокументированный реце
44
58
 
45
59
  ## Установка и ключ
46
60
 
47
- Нужен Node.js 22.12 или новее. Windows и Linux проверены; macOS отдельно не проверялась. Зависимости исполнения — Zod и Sharp, включая подходящий платформе нативный модуль Sharp.
61
+ Нужен Node.js 22.12 или новее. Сводка измеренных контрольных точек рефакторинга (Linux Node 22/24, Windows, интерпретатор Python) и статус волн 1–9 — в [плане рефакторинга](refactoring-plan.ru.md); здесь не дублируется. Зависимости среды выполнения — Zod и Sharp, включая платформенный нативный модуль Sharp.
48
62
 
49
63
  Исходники: [zoomplus/zorya-classifier](https://github.com/zoomplus/zorya-classifier). Пакет: [zorya-classifier в npm](https://www.npmjs.com/package/zorya-classifier). Установка из реестра:
50
64
 
@@ -52,7 +66,7 @@ Heldout region-seeded (один задокументированный реце
52
66
  npm install zorya-classifier
53
67
  ```
54
68
 
55
- Для локального/релизного архива также работает `npm install ./zorya-classifier-0.1.0.tgz`.
69
+ Для локального/релизного архива также работает `npm install ./zorya-classifier-0.2.3.tgz` (имя архива соответствует версии в `package.json`).
56
70
 
57
71
  Скопируйте пример конфигурации в локальный `.env` и заполните значение `OPENROUTER_API_KEY` своим ключом. В репозитории `.env` исключён из Git; в своём проекте тоже добавьте это исключение. Не помещайте ключ в браузерный React-код, приложение клиента или публичный репозиторий. Вызовы модели выполняйте на доверенном сервере.
58
72
 
@@ -127,9 +141,9 @@ const result = await client.classify({
127
141
 
128
142
  Для одной картинки поле `text` можно опустить. Принимаются `Uint8Array` и `Buffer` с одним PNG/JPEG/WebP: до 16 MiB и 16 777 216 декодированных пикселей. Ссылки на изображения публичный API не загружает — скачивание, права доступа и ограничения внешних URL остаются у вызывающего приложения.
129
143
 
130
- ## Поиск объекта и координаты (экспериментально)
144
+ ## Поиск объекта и координаты
131
145
 
132
- Обычный `locate` экспериментален и не квалифицирован для общего применения. Также внутри `try`:
146
+ Локализация и обычный `locate` доступны в публичном API. Региональный `locate` по умолчанию возвращает гипотетическую ячейку сетки, а не точную рамку объекта, маску, центр, доказательство отсутствия или универсальную точность. Пример внутри `try`:
133
147
 
134
148
  ```js
135
149
  const result = await client.locate({
@@ -158,9 +172,9 @@ if (result.status === 'located') {
158
172
  | `unknown` | Неуверенность, противоречие, отсутствие цели среди кандидатов или невозможная сетка | Уточнить цель, взять более подходящее изображение или вернуть пользователю неопределённость |
159
173
  | Исключение `ClassifierError` | Ошибка входа, сети, протокола, бюджета или жизненного цикла | Обработать код ошибки; не показывать её как отсутствие объекта |
160
174
 
161
- Если нужны маска, рамка или центр объекта, используйте `extract` с явно созданным сегментатором. Обычный `locate` сначала находит регион-кандидат; затем сегментатор получает seed-подсказку на всём ориентированном исходном изображении. Рамка и центр вычисляются по реальным пикселям маски, без отдельного поиска границ или подтверждения рамки языковой моделью. Пример и детали владения ресурсами приведены в [руководстве 0.2](v02-usage.md). Это технический путь обработки, а не гарантия точности на всех фото.
175
+ Если нужны маска, рамка или центр объекта, используйте `extract` с явно созданным сегментатором. Обычный `locate` сначала находит регион-кандидат; затем сегментатор получает подсказку `seed` на всём ориентированном исходном изображении. Рамка и центр вычисляются по реальным пикселям маски. После сегментации **текущий** основной поток выполняет до **двух** закрытых проверок рамки на полном исходнике (`complete` / `needs-expansion` / `unknown`) через `DecisionPort`, с не более чем одним расширением маски и финальной проверкой; обрезка, масштаб и поля вокруг изображения сохраняют соответствие исходника и маски, а подготовка вида для проверки идёт через `RasterPort.imageState` на полном холсте. Пример и владение ресурсами — [руководство 0.2](v02-usage.md), [architecture.ru.md](architecture.ru.md). Это технический путь, а не гарантия точности на всех фото.
162
176
 
163
- В проверенном сценарии v2 приложение сначала вызывает `classify` для наличия цели и запускает `extract` только после ответа `present`. Это явная композиция приложения: один запрос классификации плюс до трёх запросов поиска. Сам `extract` дополнительную классификацию не вставляет. Ошибку классификации нельзя выдавать за отсутствие цели; обе операции должны использовать общий сигнал отмены и абсолютный срок выполнения.
177
+ В типичной композиции приложение сначала вызывает `classify` для наличия цели и запускает `extract` только после ответа `present`. Это **явная** композиция: **1** запрос классификации + до **3** запросов `locate` + до **2** запросов проверки рамки внутри `extract` — **до 6** запросов порта решений суммарно. Сам `extract` отдельную классификацию не подставляет. Ошибку классификации нельзя выдавать за отсутствие цели. Вызывающий **может** передать один `AbortSignal` или общий предельный срок на **несколько** вызовов в своём сценарии, но библиотека держит **один абсолютный предельный срок на каждую отдельную операцию**, включая ожидание в очереди; **два** отдельных вызова **не** делят один предельный срок автоматически.
164
178
 
165
179
  Встроенный MobileSAM получает точку в центре найденной области и обрабатывает весь исходник; текст названия предмета он не понимает. Поэтому иногда он выделяет деталь, например фару вместо автомобиля. Успешный `extracted` подтверждает корректность маски и файлов, а точность распознавания оценивается отдельно. На полном DEV40 для v2 было 18/30 попаданий области в рамку цели, 5/30 совпадений рамки маски и 0 ложных вырезок на 10 отрицательных примерах. Это разные метрики. [Независимый отчёт](evidence/v02/region-seeded-dev-v2/README.md) сохраняет ошибки и ограничения; другой сегментатор подключается через тот же `SegmentationPort`.
166
180
 
@@ -168,7 +182,7 @@ if (result.status === 'located') {
168
182
 
169
183
  Переиспользуйте один `client` на жизненный цикл сервиса. По умолчанию одновременно выполняются две операции, в очереди допускается 16, общий тайм-аут — 45 секунд, включая ожидание очереди и обработку картинки. Параметры можно задать в `createClassifier`; максимумы — 4 операции, 32 ожидающих и 120 секунд. При переполнении возвращается `CAPACITY`, вместо неограниченного накопления задач.
170
184
 
171
- Для отмены передайте `signal`. Например, этот вызов завершается не позднее тайм-аута сигнала с учётом физического освобождения нативных ресурсов:
185
+ Для отмены передайте `signal`. Операция перестаёт принимать результат после отмены или тайм-аута, но **может** удерживать слот и завершать физическую работу (HTTP, Sharp, принадлежащий нативный дочерний процесс) до фактического завершения — момент возврата из вызова по календарному времени **не** обещает мгновенного освобождения всех нативных ресурсов. Пример:
172
186
 
173
187
  ```js
174
188
  const result = await client.classify({
@@ -252,7 +266,7 @@ const client = createClassifier({ decision })
252
266
 
253
267
  [Таблица проверенных моделей](vision-results.md) содержит названия, провайдеров, число примеров, ошибки, точность, задержки и цену. Там отдельно указаны полноценная проверка на корпусе, короткий screening и тесты адаптера с искусственным сервером. Необозначенная модель не считается автоматически проверенной.
254
268
 
255
- Исторический Jev-прогон дал 55/60 на фото и 30/30 на авторских текстовых примерах. Это baseline прежнего адаптера, а не доказательство качества или превосходства другой модели. Результаты не позволяют предполагать, что более мощная модель обязательно повысит точность. Подробности и исходные ошибки сохранены в [исторических результатах](results.md). Локализация остаётся экспериментальной; ячейка не является точной маской или центром объекта.
269
+ Исторический Jev-прогон дал 55/60 на фото и 30/30 на авторских текстовых примерах. Это исходный эталон прежнего адаптера, а не доказательство качества или превосходства другой модели. Результаты не позволяют предполагать, что более мощная модель обязательно повысит точность. Подробности и исходные ошибки сохранены в [исторических результатах](results.md). Локализация доступна; выбранная ячейка не является точной маской, центром объекта, сегментацией или гарантией универсальной точности карты.
256
270
 
257
271
  ## Разработка и следующие документы
258
272
 
@@ -264,11 +278,14 @@ npm run pack:check
264
278
  npm run format:check
265
279
  ```
266
280
 
267
- `check` включает секреты, TypeScript, ESLint, границы слоёв, неиспользуемый код, тесты и сборку. Husky проверяет добавленные в Git версии файлов. `pack:check` устанавливает архив в независимый проект, проверяет его файлы и API. Эти проверки не вызывают реальную модель.
281
+ `check` включает секреты, TypeScript, ESLint, границы слоёв, неиспользуемый код, тесты и сборку. Husky проверяет добавленные в Git версии файлов. `pack:check` устанавливает архив в независимый проект-потребитель, проверяет его файлы и API. Эти проверки не вызывают реальную модель.
268
282
 
269
283
  - [Полный контракт API](api.md): типы, лимиты, формат метаданных, округление баллов.
270
- - [Архитектура](architecture.md): слои, порты, отмена и владение ресурсами.
284
+ - [Архитектура](architecture.md) / [architecture.ru.md](architecture.ru.md): слои, порты, согласованность координат изображения и маски, жизненный цикл.
285
+ - [Разработка](development.ru.md): установка, каталог тестов (`H5`, `H10` и группа `local-evidence`), секреты, архив пакета.
286
+ - [Агенты и Composer](agents.ru.md): роли главного оркестратора, координатора и исполнителя Composer; видимость волн рефакторинга.
287
+ - [План рефакторинга](refactoring-plan.ru.md): волны 1–9 и платформенные журналы/отчёты.
271
288
  - [Эксплуатация](operations.md): интеграция в сервис, расходы и завершение работы.
272
- - [Воспроизведение benchmark](benchmarks.md): лицензированные фотографии и отдельный запуск платных проверок.
289
+ - [Воспроизведение каталога `benchmarks`](benchmarks.md): лицензированные фотографии и отдельный запуск платных проверок.
273
290
  - [Безопасность](https://github.com/zoomplus/zorya-classifier/blob/main/SECURITY.md): ключи, Git, npm-архивы и ограничения сканирования.
274
- - [Подготовка публикации](publishing.md): GitHub/npm и необходимая авторизация владельца.
291
+ - [Подготовка публикации](publishing.md): реестры `GitHub` и `npm` и необходимая авторизация владельца.
@@ -1,6 +1,8 @@
1
1
  # Acceptance: standalone library
2
2
 
3
- This acceptance concerns the extracted MIT Node.js library, not the Zorya desktop application, installer, microphone or game session. The caller supplies a `DecisionPort` or explicitly configures an adapter; model/provider recipes below are examples, not library defaults. Closed `classify` and explicitly configured provider/transport adapters are supported integration paths. Region `locate`, whole-object location, extraction, `RefinementPort`, segmentation/box-check composition, `objectProposals`, and native segmentation factories are experimental and unqualified; public API symbols carry `@experimental`. Further spatial accuracy experiments are stopped; no strategy is promoted. Jev is optional historical compatibility.
3
+ This acceptance concerns the extracted MIT Node.js library, not the Zorya desktop application, installer, microphone or game session. The caller supplies a `DecisionPort` or explicitly configures an adapter; model/provider recipes are examples, not library defaults. Closed `classify` and explicitly configured provider/transport adapters are supported integration paths.
4
+
5
+ Region `locate`, whole-object location, extraction, `RefinementPort`, segmentation/box-check composition, `objectProposals` and native segmentation factories are implemented public APIs. A region cell is a search hypothesis, not a whole-object box; box checks and pixel-mask quality are separate measurements. One exposed DEV12 pilot compared historical H8a output with a single native Jev 1.14 run: H8a passed the strict same-instance box criterion on 7/9 positive tasks, Jev on 3/9. This is a research result, not a default `locate`/`extract` strategy or a general accuracy claim. See the [full comparison](research/v03-jev-native-box-results.ru.md) and [evidence](evidence/v03/jev-native-box-dev12-20261025.json). Jev remains optional historical compatibility.
4
6
 
5
7
  ## Current 0.2 acceptance
6
8
 
@@ -75,7 +77,7 @@ A separate [reconstructed C03 diagnostic](evidence/v02/reconstructed-c03-box.jso
75
77
  | Two-hour resource soak | Old snapshot passed; fresh `450439c` two-thread run is active, no result yet |
76
78
  | First frozen blind vision candidate | Failed both false-location and paired-bootstrap gates |
77
79
  | Second frozen blind vision candidate | Failed: 1/60 whole boxes; paired lower bound zero; new development required |
78
- | Text-only encoders | None qualified; public experimental image selector returns `UNSUPPORTED` |
80
+ | Text-only encoders | None qualified; public experimental image selector removed (`INVALID_INPUT` on strict parse) |
79
81
  | Publication | Pending all mandatory gates |
80
82
 
81
83
  ## 0.2 development snapshot, 2026-10-20
@@ -103,7 +105,7 @@ Hosted CI for source `32aa90d` passed every Windows/Linux × Node 22/24 job, inc
103
105
 
104
106
  The subsequent [CI run for `9d00fe5`](evidence/v02/ci-9d00fe5.json) passed all four Windows/Linux × Node 22/24 jobs with 316 offline tests and the installed-archive checks. Earlier platform-path and formatting failures remain preserved. This verifies that source snapshot, not a later untested release or real-provider accuracy.
105
107
 
106
- All six text-image encoders remain research-only. The [fresh independent comparison](evidence/v02/fresh-text/README.md) is complete for photographs and real UI: every encoder has zero correct whole-object matches, and some violate the negative-case gate. None qualifies for heldout promotion. The initial classification harness defect and corrected classification-only follow-ups are preserved separately; they do not overwrite the localization runs. Failed protocol/rate-limit/truncated-generation diagnostics remain recorded. The public experimental image selector rejects explicitly. Historical controlled map/UI renders with model-assisted labels remain an exploratory supplement: their source licensing and split are recorded, but they do not close the independent-ground-truth gate.
108
+ All six text-image encoders remain research-only. The [fresh independent comparison](evidence/v02/fresh-text/README.md) is complete for photographs and real UI: every encoder has zero correct whole-object matches, and some violate the negative-case gate. None qualifies for heldout promotion. The initial classification harness defect and corrected classification-only follow-ups are preserved separately; they do not overwrite the localization runs. Failed protocol/rate-limit/truncated-generation diagnostics remain recorded. The public experimental image selector was removed; strict input validation rejects it with `INVALID_INPUT`. Historical controlled map/UI renders with model-assisted labels remain an exploratory supplement: their source licensing and split are recorded, but they do not close the independent-ground-truth gate.
107
109
 
108
110
  Subsequent [whole-object prompt/presentation experiments](evidence/v02/boundary-variants.md) found one correctly bounded Car example after removing the separate seed crop and outlining that seed on the original. Boat still returned unknown; this is development evidence, not qualification. A [controlled real-UI oracle](https://github.com/zoomplus/zorya-classifier/blob/main/benchmarks/v02/corpus/dev-independent-ui/README.md) now independently derives seven button boxes from GTK accessibility allocations and verifies all painted edges in the captured pixels. Its three negatives are scoped to the completely inventoried visible toolbar. It is one controlled source family, not a diverse natural-UI benchmark.
109
111
 
@@ -135,7 +137,7 @@ Historical native Windows/source and secret-scan receipts remain under docs/evid
135
137
 
136
138
  Luna Decisions matches the historical Jev photo/text counts on this corpus; this is not proof of statistical non-inferiority, calibration or universal superiority. Two disjoint native sessions cover the full90 classification cases without replay or prompt changes. Public photographs may overlap training; text cases are authored fixtures, not customer traffic. No independent annotation/duplicate audit was performed.
137
139
 
138
- Localization is experimental. The first native smoke failed at its195-option/nine-image fine request; an explicit replay returned HTTP502 with provider refusal. The original error and diagnostic remain preserved. A separate fixed flower-image smoke completed all three native stages in4.75s; its reviewed receipt is in docs/evidence, and it does not replace a full localization evaluation. A selected cell is not segmentation, an exact object center, tracking or a universal map/minimap guarantee. Offline fixtures are not real-model quality evidence.
140
+ Region `locate` is an implemented public API. By default it returns a hypothesized grid cell, not an exact object box, mask, center or proof of absence. It makes no universal accuracy guarantee. This section also records an older native-model smoke: its first attempt failed on a fine-grained request with 195 options and nine images; a separate replay returned HTTP 502 with a provider refusal. The original error and diagnostic remain preserved. A fixed flower-image smoke completed all three native stages in 4.75 seconds, but it is not a full localization evaluation and does not qualify general `locate` quality. A selected cell is not segmentation, an exact object center, tracking or a universal map/minimap guarantee. Offline fixtures are not real-model quality evidence.
139
141
 
140
142
  Paid comparison accounting is separate from the historical337-call Jev work. The owner expanded the comparison limit to1000 calls while retaining the$0.50 ceiling. Reported costs are reconciled only from retained numeric receipts; failed classifications remain failures, unknown charges retain conservative reservations. Local admission accounting is not a provider-side account cap or a verified invoice. The comparison finished at332 calls, known cost$0.03456876 and four unknown costs; conservative accounted exposure is$0.23456876. Exact receipts are in the model evidence/release manifest.
141
143
 
@@ -0,0 +1,97 @@
1
+ # Правила для агентов (Zorya Classifier)
2
+
3
+ Независимая MIT-библиотека. Технический контракт на английском: [AGENTS.md](https://github.com/zoomplus/zorya-classifier/blob/main/AGENTS.md). Архитектура и разработка: [архитектура](architecture.ru.md), [разработка](development.ru.md). Статус волн: [план рефакторинга](refactoring-plan.ru.md).
4
+
5
+ ## Глобальные правила владельца
6
+
7
+ Cursor **не** подгружает автоматически файлы из `/root/.cursor/rules/`. **Главный оркестратор** и **каждый** порождённый подагент Codex должны прочитать все три канонических файла:
8
+
9
+ | Файл | Назначение |
10
+ | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
11
+ | `repository-cleanliness.mdc` (`/root/.cursor/rules/repository-cleanliness.mdc`) | Уборка только артефактов текущей задачи; сохранять чужие ветки, блокировки и журналы проверок |
12
+ | `context7.mdc` (`/root/.cursor/rules/context7.mdc`) | Внешняя документация SDK, API и CLI по запросу; **не** для внутреннего рефакторинга и документации репозитория |
13
+ | `text-authorship.mdc` (`/root/.cursor/rules/text-authorship.mdc`) | Постоянный пользовательский текст пишет `gpt-6-luna` / `high` / `fork_turns=none`, если владелец явно не разрешил иное |
14
+
15
+ **Координатор** **включает** применимые пункты глобальных правил и [контракт участников](https://github.com/zoomplus/zorya-classifier/blob/main/AGENTS.md) в текст каждой задачи для исполнителя Composer. Не дублировать глобальные правила в [правила проекта](https://github.com/zoomplus/zorya-classifier/blob/main/.cursor/rules/zorya-classifier.mdc).
16
+
17
+ ## Роли
18
+
19
+ | Роль | Модель / исполнитель | Обязанности |
20
+ | ------------------------ | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | **Главный оркестратор** | Выбирает **человек** (нет модели главного по умолчанию) | По умолчанию: анализ, исследование, проверка изменений, планирование, прогон тестов, интеграция в Git после проверки; **никогда** не запускает и не владеет Cursor CLI; технические правки передаёт Composer, а прозу — автору Luna согласно отдельному правилу |
22
+ | **Автор текста Luna** | **`gpt-6-luna`**, рассуждение **`high`**, **`fork_turns=none`** | Пишет пользовательский и постоянный текст: документацию, описания, сообщения CLI/интерфейса и прозу в комментариях. Может править только текст; не меняет исполняемую логику, тесты или конфигурацию времени выполнения. В смешанной задаче передаёт точную формулировку Composer |
23
+ | **Координатор** | **`gpt-6-luna`**, рассуждение **`high`**, **`fork_turns=none`** (иначе — только явная инструкция человека) | Владелец **каждого** процесса Cursor CLI; предварительная проверка CLI перед первым запуском; постановка задач Composer; проверка фактических изменений и журналов; передача владения — только явно |
24
+ | **Исполнитель Composer** | **`composer-2.5-fast`** | Выполняет технические изменения в исходниках, тестах и конфигурации; в смешанной задаче вставляет предоставленный Luna текст без переписывания. **Не** запускает `cursor-agent`, не делегирует и не запускает вложенных агентов |
25
+
26
+ **Каждый** подагент Codex любой роли (включая координацию, автора текста и явно запрошенные исследование или проверку изменений) порождается как **`gpt-6-luna` / `high` / `fork_turns=none`**, если человек не указал иное. Владелец уже дал постоянное разрешение на такую роль, поэтому не нужно спрашивать отдельно для каждой задачи. Если главный оркестратор сам работает на Luna, он может написать текст напрямую; не нужно менять выбранную человеком модель или создавать дублирующую роль.
27
+
28
+ Отдельные подагенты для исследования или проверки изменений — **только по явному запросу** человека и остаются **только для чтения**. Иначе исследование и проверку изменений выполняет главный оркестратор.
29
+
30
+ Координатор **не обязан** работать в том же OS-процессе, что и главный оркестратор; важно явное владение процессом Cursor и передача владения.
31
+
32
+ ## Видимость плана (не повторное согласование)
33
+
34
+ Перед **любым** запуском реализации или перепланированием главный оркестратор **показывает пользователю** нумерованные волны в порядке зависимостей. Для каждой волны: роли (главный / координатор / Composer), идентификаторы моделей и `fork_turns`, конкретные пути в зоне ответственности, входы и предварительные условия, параллелизм (не более 3 процессов Composer глобально, отдельные рабочие деревья Git при параллели), артефакты (журналы в **корне артефактов вне репозитория**), проверки и критерии выхода; рядом — краткое русское «зачем».
35
+
36
+ Уже данной в сессии авторизации достаточно для реализации, проверки изменений, исправлений, тестов и интеграции в разрешённых границах — не изобретать повторные циклы согласования. При реальной нехватке модели, доступа, аутентификации или квоты — сообщить фактически, **без** подстановки другой модели или режима Auto.
37
+
38
+ Проверка изменений опирается на **фактические изменения в файлах и вывод тестов**, а не на пересказ модели.
39
+
40
+ ## Запуск Composer (координатор)
41
+
42
+ Перед **первым** запуском:
43
+
44
+ ```sh
45
+ cursor-agent --version
46
+ cursor-agent status
47
+ cursor-agent models
48
+ ```
49
+
50
+ Запуск **только** с моделью **`composer-2.5-fast`**. Запрещены Auto и скрытая подстановка `composer-2.5` или других семейств — остановиться и сообщить блокер.
51
+
52
+ **Один координатор на один процесс Cursor.** Глобально **не более 3** процессов Composer. Параллель: отдельные **рабочие деревья Git**, непересекающееся владение файлами; слияние после проверки изменений и тестов; общие файлы — явная координация.
53
+
54
+ Пример из корня репозитория (без секретов в тексте задачи):
55
+
56
+ ```sh
57
+ cursor-agent \
58
+ --workspace "$PWD" \
59
+ --print \
60
+ --force \
61
+ --output-format stream-json \
62
+ --model composer-2.5-fast \
63
+ "…текст задачи: пути в зоне ответственности, ограничения, запрет рекурсивного запуска agent…"
64
+ ```
65
+
66
+ ## Инварианты кода (кратко)
67
+
68
+ Слои: [архитектура](architecture.ru.md), `npm run boundaries`.
69
+
70
+ - Строгий TypeScript и Zod на границах; без подстановки провайдера.
71
+ - Байты входа — до первого `await`; один абсолютный предельный срок с очередью; слоты до фактического завершения работы; `dispose` дожидается завершения.
72
+ - v0.2 `extract`: геометрия из маски, закрытая проверка рамки, не более одного расширения маски и финальной проверки; без координат от модели.
73
+ - Ранг не равен вероятности; один финальный ID против четырёх кандидатов пространственной стадии луча.
74
+ - Каталог `benchmarks`: `hashCanonical` = `SHA-256`(`JSON.stringify`) с фиксированным порядком полей.
75
+ - Исследования в `benchmarks/experiments/` — вне дистрибутива npm; публичный селектор IMAGE-AS-TEXT удалён (`INVALID_INPUT`); benchmark-only композиция через `createResearchClassifier`.
76
+
77
+ ## Тесты
78
+
79
+ | Набор | Команда |
80
+ | ----------------------- | ---------------------------------------------------------------------------------------------------------- |
81
+ | Переносимый каталог | `npm test` |
82
+ | Локальные свидетельства | `npm run test:local-evidence` (H5, `grounded-mask`, минимальный H10 — см. [разработку](development.ru.md)) |
83
+ | Группа `python-native` | `npm run test:python-native` (см. [разработку](development.ru.md)) |
84
+
85
+ Единый раннер: `scripts/run-classified-tests.mjs`. Не ссылаться на удалённый `run-portable-tests.mjs`.
86
+
87
+ Измеренные счётчики переносимого каталога и платформы — [план рефакторинга](refactoring-plan.ru.md). На измеренном Linux-хосте Python **3.12.3**: установлены `PIL`/`Pillow`; **`numpy`**, **`torch`** и **`transformers`** **отсутствуют**; набор `python-native` **не запускался**. Переносимый каталог: **772** успешных, **0** пропущенных (необязательные тесты без ресурсов могут пропускаться). Узкие проверки исполнителя Composer под встроенным Linux Node 24 **не** равны полным проверкам главного оркестратора на Node 24.
88
+
89
+ ## Секреты, платные прогоны, публикация
90
+
91
+ `npm run secrets:check`, сканирование **версий файлов, добавленных в индекс Git** (Husky), `npm run pack:check`. Ключ каталога `benchmarks`: `OPENROUTER_API_KEY` или явный `--env-file` **только** в `run-region-seeded-dev.ts` / `run-quality-pilot.ts` — [разработку](development.ru.md).
92
+
93
+ Не коммитить `.env`, частные медиа, журналы чатов. Платные прогоны, GPU и публикация — явная область работ и бюджеты.
94
+
95
+ ## Уборка
96
+
97
+ Только рабочие деревья, временные каталоги и кэш, созданные текущей задачей. Сохранять ранее существующие изменения, неудачные журналы проверок (артефакты **вне** репозитория), посторонние ветки. См. `repository-cleanliness.mdc`.
package/docs/api.md CHANGED
@@ -1,22 +1,22 @@
1
1
  # Public API
2
2
 
3
- Spatial localization, whole-object location, extraction, `RefinementPort`, caller-owned segmentation/box-check composition, `objectProposals`, and native segmentation factories are **experimental and unqualified** for general use (TypeScript `@experimental` on the corresponding public types and methods). Closed `classify` and explicitly configured `DecisionPort`/transport adapters remain supported; they do not imply universal model accuracy. Further spatial accuracy experiments are stopped; no strategy is promoted.
3
+ Spatial localization, whole-object location, extraction, `RefinementPort`, caller-owned segmentation/box-check composition, `objectProposals`, and native segmentation factories are implemented public APIs. Grid cells from default `locate` are not whole-object boxes; mask-derived geometry and box-check verdicts measure different things; model, provider and native assets remain caller-supplied. Closed `classify` and explicitly configured `DecisionPort`/transport adapters remain supported; they do not imply universal model accuracy. The [H8a vs Jev DEV12 box comparison](research/v03-jev-native-box-results.ru.md) is a research recipe, not a library default.
4
4
 
5
5
  `createClassifier({ decision, timeoutMs?, concurrency?, maxQueue?, maxInputBytes?, refinement?, segmentation?, objectProposals? })` creates an owned client. Defaults: 45,000ms absolute budget including queue/image work/provider work; two active operations; sixteen waiters; 64 MiB total admitted input bytes, reserved before copying. Configured maxima: 120s, four active,32 queued,256 MiB admitted input. Input images are at most16MiB and16,777,216 decoded pixels, with source sides at most16,384; single PNG/JPEG/WebP only. The vision adapter accepts prepared PNG/JPEG with sides280..1568 and a32MiB total request cap. Byte inputs are copied before the first await, including Buffer views.
6
6
 
7
7
  The caller supplies the `DecisionPort`; the library never chooses a model, provider or endpoint. You may inject a port directly or explicitly construct one of the adapters below. Their model/provider values are examples or benchmark recipes, not defaults, and stronger models do not guarantee higher accuracy. Optional segmentation adapters are configured separately and require caller-installed runtime packages and caller-supplied local assets.
8
8
 
9
- The [0.2 guide](v02-usage.md) documents `extract`, mask-derived `locate({ mode: 'whole-object', ... })`, optional native adapters and the reserved experimental representation selector. Default region behavior is unchanged. The primary object flow runs the original region locator, then prompts the caller-configured segmenter on the full oriented source image; the actual mask determines bounds, center and cutout. A closed containment check then sees the full source with the actual mask-derived box and seed anchor. An incomplete box can trigger one optional `SegmentationPort.expand(input, previousMask)` and one final check; missing support or unresolved verification returns `unknown/segmentation-uncertain`. The previous mask is full-source binary-u8. `segmentationBoxCheck` can inject a custom checker; otherwise the same caller-supplied `decision` is reused. `verification.checks` retains each closed decision and `verification.expansion` records the correction path; all decision receipts contribute to localization metadata. This checks box containment separately from pixel-mask quality, without an extent search. Native factories are exported from `zorya-classifier/segmentation`; the caller supplies and disposes the segmenter separately. `objectProposals` and interval-based whole-object location remain optional legacy strategies. The segmentation entry also exports `packBinaryMask`/`unpackBinaryMask` for custom adapters.
9
+ The [0.2 guide](v02-usage.md) documents `extract`, mask-derived `locate({ mode: 'whole-object', ... })`, optional native adapters and public `representation: { type: 'vision' }` compatibility. The former experimental text-image selector was removed from public input. Default region behavior is unchanged. The primary object flow runs the original region locator, then prompts the caller-configured segmenter on the full oriented source image; the actual mask determines bounds, center and cutout. A closed containment check then sees the full source with the actual mask-derived box and seed anchor. An incomplete box can trigger one optional `SegmentationPort.expand(input, previousMask)` and one final check; missing support or unresolved verification returns `unknown/segmentation-uncertain`. The previous mask is full-source binary-u8. `segmentationBoxCheck` can inject a custom checker; otherwise the same caller-supplied `decision` is reused. `verification.checks` retains each closed decision and `verification.expansion` records the correction path; all decision receipts contribute to localization metadata. This checks box containment separately from pixel-mask quality, without an extent search. Native factories are exported from `zorya-classifier/segmentation`; the caller supplies and disposes the segmenter separately. `objectProposals` and interval-based whole-object location remain optional legacy strategies. The segmentation entry also exports `packBinaryMask`/`unpackBinaryMask` for custom adapters.
10
10
 
11
11
  `classify({ input, classes, instructions?, signal? })`: input is a string or `{ text?, image? }` with at least one field. Classes are2..255 distinct IDs plus descriptions. IDs match `[a-zA-Z][a-zA-Z0-9_-]*`; descriptions at most300 chars. Text is at most32,000 chars, custom instructions4,000. Define explicit none/other behavior in your classes. With ordinary vision models the result contains `choice` (first ranked ID), `ranking`, `probabilities: null`, `nativeChoice: null`, empty `tied`, and metadata. No rank is converted to a fabricated probability. Optional native integrations instead retain raw probabilities, stable maximum/ties, native choice/confidence and optional quantization annotation. Confidence is never a calibrated spatial guarantee.
12
12
 
13
- `locate({ image, target, exclusions?, roi?, signal? })` (**experimental**): target at most2,000 chars; up to16 exclusions of500 chars. ROI uses integer `left/top/width/height` in EXIF-oriented source pixels. Return coordinates reference that oriented image; metadata names this space and dimensions. Rectangles include left/top and exclude right/bottom. Normalized rectangle fields are divided by image dimensions. Tiny/impossible bounded grids return `unknown/layout-limit`.
13
+ `locate({ image, target, exclusions?, roi?, signal? })` (available): target at most2,000 chars; up to16 exclusions of500 chars. ROI uses integer `left/top/width/height` in EXIF-oriented source pixels. Return coordinates reference that oriented image; metadata names this space and dimensions. Rectangles include left/top and exclude right/bottom. Normalized rectangle fields are divided by image dimensions. Tiny/impossible bounded grids return `unknown/layout-limit`.
14
14
 
15
15
  `located` from default region mode returns a selected grid region, normalized region, third-stage selection evidence and optional refinement. `not-found/absent-in-evaluated-region` is based on the initial independent presence check. A target missing from later shortlisted cells yields `unknown/candidate-union-empty`, not global absence. Ordinary models return present/absent/unknown as an independent categorical predicate. Legacy Noul0.5 abstains; contradictory presence/selection returns unknown. Multiple physical matching objects are permitted; this is an any-instance locator. With an explicit `segmentation` port, `locate({ mode: 'whole-object' })` and `extract` use the region seed plus full-source segmentation; reported bounds and center come from the valid mask.
16
16
 
17
17
  The algorithm searches4×4 coarse cells, keeps four source-distinct maxima, pads each by half a coarse cell within ROI, partitions each into at most49 fine cells (global≤196, side≤256), then compares the four best fine cells as enlarged A–D/none. Edges count as matches. Scores/rank hints are not sent to the final comparison. No cell-center correction is presented as object segmentation.
18
18
 
19
- `RefinementPort.refine({ image, target, region, signal })` (**experimental**) is optional trusted code. It receives a private oriented-source byte copy. A returned refined rectangle must fit the source and intersect the selected cell. It does not replace the original area evidence. No built-in heavy refiner is downloaded.
19
+ `RefinementPort.refine({ image, target, region, signal })` (available) is optional trusted code. It receives a private oriented-source byte copy. A returned refined rectangle must fit the source and intersect the selected cell. It does not replace the original area evidence. No built-in heavy refiner is downloaded.
20
20
 
21
21
  `dispose()` cancels current/queued work, rejects further calls and waits for physical settlement. Injected ports must honor cancellation. Native image work retains its concurrency slot until completion, even if cancellation has already been requested.
22
22
 
@@ -1,12 +1,36 @@
1
1
  # Architecture and lifecycle
2
2
 
3
- Closed `classify` and injected `DecisionPort`/adapter transport are supported integration paths. Region `locate`, whole-object location, extraction, `RefinementPort`, caller-owned segmentation and box-check composition, `ObjectProposalPort`, and explicit native segmentation factories are experimental and unqualified; they are labeled `@experimental` on the public API. No spatial or extraction strategy is promoted; evidence under `docs/evidence/**` remains historical.
3
+ Russian guide with layer map, SOLID notes and current paths: [architecture.ru.md](architecture.ru.md). Development onboarding: [development.ru.md](development.ru.md).
4
4
 
5
- The public factory composes the caller-supplied `DecisionPort` and a Sharp-backed `RasterPort`. The library does not select a model, provider or endpoint; applications either inject an existing port or explicitly build one with a supported adapter. Processes orchestrate classify/locate; features contain pure Choice interpretation, grid geometry and prompt construction; entities define validated public contracts; infrastructure owns provider HTTP and image processing. No application runtime, game-state schema or workspace import is required.
5
+ Closed `classify` and injected `DecisionPort`/adapter transport are supported integration paths. Region `locate`, whole-object location, extraction, `RefinementPort`, caller-owned segmentation and box-check composition, `ObjectProposalPort`, and explicit native segmentation factories are implemented public APIs (grid cells ≠ whole-object boxes; masks and box checks differ). Evidence under `docs/evidence/**` remains historical; the DEV12 H8a vs Jev box comparison is documented separately as research, not a shipped default strategy.
6
+
7
+ The public factory composes the caller-supplied `DecisionPort` and a Sharp-backed `RasterPort`. The library exposes four package entries (`.`, `./openrouter`, `./openai-compatible`, `./segmentation`); the CLI is a separate bin, not a fifth library export. The library does not select a model, provider or endpoint; applications either inject an existing port or explicitly build one with a supported adapter. **Import layers:** `app` composes `processes` and `infrastructure`; `processes` depend on `features`, `entities`, and `shared` port contracts only (no direct `processes` → `infrastructure` imports); `infrastructure` implements ports and may use `features`/`entities`/`shared`. Runtime calls reach HTTP, raster, and native work through injected port instances wired in `app`. Processes orchestrate classify/locate; features contain pure Choice interpretation, grid geometry and prompt construction; entities define validated public contracts. Benchmark runners live under `benchmarks/v02/`, `benchmarks/v03/`, and the repo root as well as helpers in `benchmarks/experiments/`; not all runners are under `experiments/`. No application runtime, game-state schema or workspace import is required.
6
8
 
7
9
  The primary 0.2 object path preserves the original region locator. Its selected seed prompts an explicitly configured segmenter on the full oriented source image; actual mask pixels determine bounds, center and the optional cutout. A generic closed containment checker receives the full source with the mask-derived box and original seed anchor. It uses the injected decision port and a presentation port; the process allows at most one actual enclosing-mask correction and a final check. The segmenter can implement optional `expand`; corrected foreground must strictly contain the old visible foreground and grow the real box within the hard ROI. The process rejects unresolved checks without publishing a partial cutout. Its absolute deadline, cancellation and byte ownership cover every stage. No additional extent search or model-generated coordinates are used. `locate({ mode: 'whole-object' })` and `extract` use the same mask-derived geometry when a segmenter is configured. Boundary-interval location and `ObjectProposalPort` remain optional legacy strategies with their own request flows.
8
10
 
9
- Extraction composes the selected locator with a caller-owned `SegmentationPort` and a `CutoutRasterPort`; processes import neither Sharp nor native inference. Explicitly created native adapters own their workers and queues, while the caller supplies and manages their optional runtime packages and local model assets. No weights are selected, installed or downloaded by the library. [Operation and ownership details](v02-usage.md) are explicit; no experimental text-image profile is publicly qualified yet.
11
+ Extraction composes the selected locator with a caller-owned `SegmentationPort` and a `CutoutRasterPort`; processes import neither Sharp nor native inference. Explicitly created native adapters own their workers and queues, while the caller supplies and manages their optional runtime packages and local model assets. No weights are selected, installed or downloaded by the library. [Operation and ownership details](v02-usage.md) are explicit; the former experimental text-image selector was removed from public input (strict `INVALID_INPUT`). Research encoders remain benchmark-only.
12
+
13
+ ```mermaid
14
+ flowchart TB
15
+ subgraph appLayer [app]
16
+ APP[create-classifier]
17
+ end
18
+ subgraph procLayer [processes]
19
+ PROC[classify / locate / extract]
20
+ end
21
+ subgraph featLayer [features + entities + shared]
22
+ FEAT[choice / grid / contracts / gate]
23
+ end
24
+ subgraph infraLayer [infrastructure]
25
+ INF[decision-transport / raster / native segmentation]
26
+ end
27
+ APP --> PROC
28
+ APP --> INF
29
+ PROC --> FEAT
30
+ INF --> FEAT
31
+ ```
32
+
33
+ Runtime orchestration (same primary extract semantics as below):
10
34
 
11
35
  ```mermaid
12
36
  flowchart LR
@@ -16,12 +40,14 @@ flowchart LR
16
40
  L --> S[Caller-owned segmenter on full source with seed prompt]
17
41
  S --> M[Validate mask and derive visible bounds / center]
18
42
  M --> B[Closed box check on full source and seed anchor]
19
- B -->|complete| X[Optional transparent cutout]
43
+ B -->|complete| X[Result / optional transparent cutout]
20
44
  B -->|unknown| U[Explicit unresolved result]
21
- B -->|needs expansion| E[At most one actual enclosing-mask correction]
22
- E --> R[Validate foreground containment and recheck actual box]
45
+ B -->|needs-expansion| E[At most one actual enclosing-mask correction]
46
+ E -->|success| P[Preserve every prior visible foreground pixel]
47
+ E -->|no expand / no valid enclosing mask| U
48
+ P --> R[Final check on actual box]
23
49
  R -->|complete| X
24
- R -->|unresolved / no parent| U
50
+ R -->|unknown / needs-expansion| U
25
51
  ```
26
52
 
27
53
  One deadline covers the whole operation, including queue time. AbortSignal passes through every boundary; guards after awaits reject late results. Physical Sharp/provider work retains its slot until its promise settles. Timers/listeners are cleared in finally. There is no import-time worker, automatic retry, persistent image cache, database or background polling loop.