zorya-classifier 0.2.2 → 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 (37) hide show
  1. package/README.md +30 -16
  2. package/dist/app/classifier-contracts.d.ts +8 -8
  3. package/dist/app/composed-classifier.d.ts +17 -0
  4. package/dist/app/composed-classifier.js +1 -0
  5. package/dist/app/create-classifier.d.ts +7 -1
  6. package/dist/app/create-classifier.js +24 -16
  7. package/dist/cli.js +1 -1
  8. package/dist/entities/classification.d.ts +2 -17
  9. package/dist/entities/image.d.ts +2 -11
  10. package/dist/entities/image.js +1 -4
  11. package/dist/entities/localization.d.ts +6 -21
  12. package/dist/entities/object-proposals.d.ts +1 -1
  13. package/dist/entities/representation.d.ts +0 -183
  14. package/dist/entities/representation.js +1 -33
  15. package/dist/entities/segmentation-verification.d.ts +1 -1
  16. package/dist/entities/segmentation.d.ts +5 -20
  17. package/dist/entities/whole-object.d.ts +6 -21
  18. package/dist/infrastructure/segmentation/grabcut/index.d.ts +2 -2
  19. package/dist/infrastructure/segmentation/grabcut/index.js +1 -1
  20. package/dist/infrastructure/segmentation/mobile-sam/object-proposals.d.ts +1 -1
  21. package/dist/infrastructure/segmentation/mobile-sam/object-proposals.js +1 -1
  22. package/dist/infrastructure/segmentation/mobile-sam/options.d.ts +2 -2
  23. package/dist/infrastructure/segmentation/mobile-sam/segmenter.d.ts +1 -1
  24. package/dist/infrastructure/segmentation/mobile-sam/segmenter.js +1 -1
  25. package/docs/README.ru.md +37 -23
  26. package/docs/acceptance.md +6 -4
  27. package/docs/agents.ru.md +14 -12
  28. package/docs/api.md +4 -4
  29. package/docs/architecture.md +2 -2
  30. package/docs/architecture.ru.md +10 -10
  31. package/docs/migrations/experimental-text-image-removal.ru.md +9 -0
  32. package/docs/provenance.json +283 -0
  33. package/docs/v02-usage.md +8 -8
  34. package/docs/vision-results.md +1 -1
  35. package/package.json +2 -2
  36. package/dist/app/classifier-representation.d.ts +0 -5
  37. package/dist/app/classifier-representation.js +0 -33
@@ -1,33 +1 @@
1
- import { pixelRectSchema } from './contracts.js';
2
- import { z } from 'zod';
3
- export const representationLimits = Object.freeze({
4
- totalBytes: 64 * 1024,
5
- partCharacters: 64000,
6
- maxSide: 64,
7
- maxViews: 9,
8
- });
9
- export const preparedTextSchema = z
10
- .object({
11
- state: z.array(z.string().min(1).max(representationLimits.partCharacters)).min(1).max(64),
12
- metadata: z
13
- .object({
14
- profile: z.string().min(1).max(128),
15
- bytes: z.number().int().nonnegative().max(representationLimits.totalBytes),
16
- views: z
17
- .array(z
18
- .object({
19
- id: z.string().min(1).max(256),
20
- sourceRegion: pixelRectSchema,
21
- width: z.number().int().positive().max(16384),
22
- height: z.number().int().positive().max(16384),
23
- scaleX: z.number().finite().positive(),
24
- scaleY: z.number().finite().positive(),
25
- content: pixelRectSchema.optional(),
26
- })
27
- .strict())
28
- .min(1)
29
- .max(representationLimits.maxViews),
30
- })
31
- .strict(),
32
- })
33
- .strict();
1
+ export {};
@@ -16,7 +16,7 @@ export interface SegmentationBoxCheckResult {
16
16
  selection: ChoiceSelection;
17
17
  metadata: DecisionMetadata;
18
18
  }
19
- /** @experimental Closed box containment check; verdicts are unqualified for general spatial accuracy. */
19
+ /** Closed box containment check; verdicts are not universal spatial accuracy guarantees. */
20
20
  export interface SegmentationBoxCheckPort {
21
21
  check(input: SegmentationBoxCheckInput): Promise<SegmentationBoxCheckResult>;
22
22
  }
@@ -25,22 +25,13 @@ export declare const extractSchema: z.ZodObject<{
25
25
  width: number;
26
26
  height: number;
27
27
  }>>;
28
- representation: z.ZodOptional<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
28
+ representation: z.ZodOptional<z.ZodObject<{
29
29
  type: z.ZodLiteral<"vision">;
30
30
  }, "strict", z.ZodTypeAny, {
31
31
  type: "vision";
32
32
  }, {
33
33
  type: "vision";
34
- }>, z.ZodObject<{
35
- type: z.ZodLiteral<"experimental-text">;
36
- profile: z.ZodLiteral<"text-image-v1">;
37
- }, "strict", z.ZodTypeAny, {
38
- type: "experimental-text";
39
- profile: "text-image-v1";
40
- }, {
41
- type: "experimental-text";
42
- profile: "text-image-v1";
43
- }>]>>;
34
+ }>>;
44
35
  boxTolerancePx: z.ZodDefault<z.ZodNumber>;
45
36
  maxExtentPasses: z.ZodDefault<z.ZodNumber>;
46
37
  } & {
@@ -53,9 +44,6 @@ export declare const extractSchema: z.ZodObject<{
53
44
  maxExtentPasses: number;
54
45
  representation?: {
55
46
  type: "vision";
56
- } | {
57
- type: "experimental-text";
58
- profile: "text-image-v1";
59
47
  } | undefined;
60
48
  roi?: {
61
49
  left: number;
@@ -69,9 +57,6 @@ export declare const extractSchema: z.ZodObject<{
69
57
  target: string;
70
58
  representation?: {
71
59
  type: "vision";
72
- } | {
73
- type: "experimental-text";
74
- profile: "text-image-v1";
75
60
  } | undefined;
76
61
  exclusions?: string[] | undefined;
77
62
  roi?: {
@@ -84,7 +69,7 @@ export declare const extractSchema: z.ZodObject<{
84
69
  boxTolerancePx?: number | undefined;
85
70
  maxExtentPasses?: number | undefined;
86
71
  }>;
87
- /** @experimental Region-seeded extraction input; unqualified for general object or mask accuracy. */
72
+ /** Region-seeded extraction input; structural success does not guarantee semantic object or mask quality. */
88
73
  export type ExtractInput = z.input<typeof extractSchema> & {
89
74
  signal?: AbortSignal;
90
75
  };
@@ -118,7 +103,7 @@ export type SegmentationResult = {
118
103
  };
119
104
  /**
120
105
  * Caller-owned. settle joins physical work; dispose closes this adapter only.
121
- * @experimental Caller-owned segmentation; structural validation does not establish semantic object or mask quality.
106
+ * Structural validation does not establish semantic object or mask quality.
122
107
  */
123
108
  export interface SegmentationPort {
124
109
  segment(input: SegmentationInput): Promise<SegmentationResult>;
@@ -127,7 +112,7 @@ export interface SegmentationPort {
127
112
  settle(): Promise<void>;
128
113
  dispose(): Promise<void>;
129
114
  }
130
- /** @experimental Extraction outcome; `extracted` reflects validation, not guaranteed semantic correctness. */
115
+ /** Extraction outcome; `extracted` reflects validation, not guaranteed semantic correctness. */
131
116
  export type ExtractionResult = {
132
117
  status: 'extracted';
133
118
  location: WholeObjectLocated;
@@ -22,22 +22,13 @@ export declare const wholeObjectSchema: z.ZodObject<{
22
22
  width: number;
23
23
  height: number;
24
24
  }>>;
25
- representation: z.ZodOptional<z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
25
+ representation: z.ZodOptional<z.ZodObject<{
26
26
  type: z.ZodLiteral<"vision">;
27
27
  }, "strict", z.ZodTypeAny, {
28
28
  type: "vision";
29
29
  }, {
30
30
  type: "vision";
31
- }>, z.ZodObject<{
32
- type: z.ZodLiteral<"experimental-text">;
33
- profile: z.ZodLiteral<"text-image-v1">;
34
- }, "strict", z.ZodTypeAny, {
35
- type: "experimental-text";
36
- profile: "text-image-v1";
37
- }, {
38
- type: "experimental-text";
39
- profile: "text-image-v1";
40
- }>]>>;
31
+ }>>;
41
32
  } & {
42
33
  mode: z.ZodLiteral<"whole-object">;
43
34
  boxTolerancePx: z.ZodDefault<z.ZodNumber>;
@@ -51,9 +42,6 @@ export declare const wholeObjectSchema: z.ZodObject<{
51
42
  maxExtentPasses: number;
52
43
  representation?: {
53
44
  type: "vision";
54
- } | {
55
- type: "experimental-text";
56
- profile: "text-image-v1";
57
45
  } | undefined;
58
46
  roi?: {
59
47
  left: number;
@@ -67,9 +55,6 @@ export declare const wholeObjectSchema: z.ZodObject<{
67
55
  mode: "whole-object";
68
56
  representation?: {
69
57
  type: "vision";
70
- } | {
71
- type: "experimental-text";
72
- profile: "text-image-v1";
73
58
  } | undefined;
74
59
  exclusions?: string[] | undefined;
75
60
  roi?: {
@@ -81,13 +66,13 @@ export declare const wholeObjectSchema: z.ZodObject<{
81
66
  boxTolerancePx?: number | undefined;
82
67
  maxExtentPasses?: number | undefined;
83
68
  }>;
84
- /** @experimental Same unqualified coarse region search as default {@link LocateInput}. */
69
+ /** Same coarse region search as default {@link LocateInput}. */
85
70
  export type RegionLocateInput = LocateInput;
86
- /** @experimental Whole-object localization (interval or caller segmentation); unqualified for general use. */
71
+ /** Whole-object localization (interval or caller segmentation). */
87
72
  export type WholeObjectLocateInput = z.input<typeof wholeObjectSchema> & {
88
73
  signal?: AbortSignal;
89
74
  };
90
- /** @experimental Region or whole-object locate input; spatial paths are experimental. */
75
+ /** Region or whole-object locate input. */
91
76
  export type AnyLocateInput = RegionLocateInput | WholeObjectLocateInput;
92
77
  export interface BoundaryInterval {
93
78
  start: number;
@@ -127,6 +112,6 @@ export type WholeObjectFailure = LocalizationFailure | {
127
112
  metadata: LocalizationMetadata;
128
113
  verification?: SegmentationVerification;
129
114
  };
130
- /** @experimental Whole-object localization outcome; passing structural checks does not establish mask or box accuracy. */
115
+ /** Whole-object localization outcome; passing structural checks does not establish mask or box accuracy. */
131
116
  export type WholeObjectLocalizationResult = WholeObjectLocated | WholeObjectFailure;
132
117
  export {};
@@ -7,11 +7,11 @@ declare const optionsSchema: z.ZodObject<{
7
7
  }, {
8
8
  assetPath: string;
9
9
  }>;
10
- /** @experimental Options for the unqualified GrabCut segmentation factory. */
10
+ /** Options for the GrabCut segmentation factory (caller-supplied pinned assets). */
11
11
  export type GrabCutSegmenterOptions = z.input<typeof optionsSchema>;
12
12
  /**
13
13
  * Explicit pinned OpenCV GrabCut adapter. The supplied native asset is never downloaded.
14
- * @experimental Native segmentation adapter; unqualified for general mask or object accuracy.
14
+ * Structural validation does not establish semantic mask or object quality.
15
15
  */
16
16
  export declare function createGrabCutSegmenter(options: GrabCutSegmenterOptions): Promise<SegmentationPort>;
17
17
  export {};
@@ -10,7 +10,7 @@ import { grabcutOpenCvArtifact } from './model-asset.js';
10
10
  const optionsSchema = z.object({ assetPath: z.string().min(1).max(4096) }).strict();
11
11
  /**
12
12
  * Explicit pinned OpenCV GrabCut adapter. The supplied native asset is never downloaded.
13
- * @experimental Native segmentation adapter; unqualified for general mask or object accuracy.
13
+ * Structural validation does not establish semantic mask or object quality.
14
14
  */
15
15
  export async function createGrabCutSegmenter(options) {
16
16
  const checked = optionsSchema.safeParse(options);
@@ -2,6 +2,6 @@ import type { ObjectProposalPort } from '../../../entities/object-proposals.js';
2
2
  import { type MobileSamObjectProposalsOptions } from './options.js';
3
3
  /**
4
4
  * Explicit CPU-only proposals: historical 3x3/36 default or opt-in seed-center/four.
5
- * @experimental Native proposal adapter; unqualified for general spatial or mask accuracy.
5
+ * Native proposal adapter; no general spatial or mask quality is implied.
6
6
  */
7
7
  export declare function createMobileSamObjectProposals(options: MobileSamObjectProposalsOptions): Promise<ObjectProposalPort>;
@@ -10,7 +10,7 @@ import { proposalOptionsSchema } from './options.js';
10
10
  import { snapshotProposalInput } from './input.js';
11
11
  /**
12
12
  * Explicit CPU-only proposals: historical 3x3/36 default or opt-in seed-center/four.
13
- * @experimental Native proposal adapter; unqualified for general spatial or mask accuracy.
13
+ * Native proposal adapter; no general spatial or mask quality is implied.
14
14
  */
15
15
  export async function createMobileSamObjectProposals(options) {
16
16
  const checked = proposalOptionsSchema.safeParse(options);
@@ -18,7 +18,7 @@ export declare const optionsSchema: z.ZodObject<{
18
18
  deviceId?: number | undefined;
19
19
  threads?: number | undefined;
20
20
  }>;
21
- /** @experimental Options for the unqualified MobileSAM segmentation factory. */
21
+ /** Options for the MobileSAM segmentation factory (caller-supplied pinned assets). */
22
22
  export type MobileSamSegmenterOptions = z.input<typeof optionsSchema>;
23
23
  export declare const proposalOptionsSchema: z.ZodObject<{
24
24
  encoderPath: z.ZodString;
@@ -39,5 +39,5 @@ export declare const proposalOptionsSchema: z.ZodObject<{
39
39
  threads?: number | undefined;
40
40
  sampling?: "seed-grid" | "seed-center" | undefined;
41
41
  }>;
42
- /** @experimental Options for the unqualified MobileSAM object-proposal factory. */
42
+ /** Options for the MobileSAM object-proposal factory (caller-supplied pinned assets). */
43
43
  export type MobileSamObjectProposalsOptions = z.input<typeof proposalOptionsSchema>;
@@ -14,7 +14,7 @@ type SerializedTask = (Omit<Extract<NativeSegmentationRequest, {
14
14
  });
15
15
  /**
16
16
  * Explicit pinned MobileSAM inference in a separately owned Node child process.
17
- * @experimental Native segmentation adapter; unqualified for general mask or object accuracy.
17
+ * Structural validation does not establish semantic mask or object quality.
18
18
  */
19
19
  export declare function createMobileSamSegmenter(options: MobileSamSegmenterOptions): Promise<SegmentationPort>;
20
20
  /** Internal adapter seam: pool ownership stays with the caller. */
@@ -10,7 +10,7 @@ import { snapshotInput, snapshotPreviousMask } from './input.js';
10
10
  import { packFullSourceBinaryMask, unpackFullSourceBinaryMask, validateMobileSamPreviousMask, } from './segmentation-masks.js';
11
11
  /**
12
12
  * Explicit pinned MobileSAM inference in a separately owned Node child process.
13
- * @experimental Native segmentation adapter; unqualified for general mask or object accuracy.
13
+ * Structural validation does not establish semantic mask or object quality.
14
14
  */
15
15
  export async function createMobileSamSegmenter(options) {
16
16
  const checked = optionsSchema.safeParse(options);
package/docs/README.ru.md CHANGED
@@ -1,40 +1,54 @@
1
1
  # Zorya Classifier: руководство
2
2
 
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
+
3
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
53
  Для `extract` после сегментации порт решений получает полный исходник с рамкой из маски и исходной подсказкой `seed`. Ответ закрыт: `complete` (можно вернуть результат и опциональный вырез), `needs-expansion` (не более одного расширения охватывающей маски и одной финальной проверки; повторный `complete` после финальной проверки тоже допускает результат) или `unknown` (неразрешённая проверка, нет поддержки расширения, нет действительной охватывающей маски или провал финальной проверки — второго расширения нет). Внутри одного `extract` со встроенным `locate` — до трёх запросов на поиск области и до двух закрытых проверок рамки. Без подтверждения библиотека возвращает неопределённость и не публикует частичный вырез. Рамка и центр только из пикселей маски; успешная проверка рамки не доказывает идеальную сегментацию по пикселям. Порт решений подключается через `DecisionPort`; сегментатор остаётся на стороне вызывающего.
40
54
 
@@ -52,7 +66,7 @@ Heldout region-seeded (один задокументированный реце
52
66
  npm install zorya-classifier
53
67
  ```
54
68
 
55
- Для локального/релизного архива также работает `npm install ./zorya-classifier-0.2.0.tgz` (имя следует версии в `package.json`; это не заявление о новой публикации в npm).
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({
@@ -252,7 +266,7 @@ const client = createClassifier({ decision })
252
266
 
253
267
  [Таблица проверенных моделей](vision-results.md) содержит названия, провайдеров, число примеров, ошибки, точность, задержки и цену. Там отдельно указаны полноценная проверка на корпусе, короткий screening и тесты адаптера с искусственным сервером. Необозначенная модель не считается автоматически проверенной.
254
268
 
255
- Исторический Jev-прогон дал 55/60 на фото и 30/30 на авторских текстовых примерах. Это исходный эталон прежнего адаптера, а не доказательство качества или превосходства другой модели. Результаты не позволяют предполагать, что более мощная модель обязательно повысит точность. Подробности и исходные ошибки сохранены в [исторических результатах](results.md). Локализация остаётся экспериментальной; ячейка не является точной маской или центром объекта.
269
+ Исторический Jev-прогон дал 55/60 на фото и 30/30 на авторских текстовых примерах. Это исходный эталон прежнего адаптера, а не доказательство качества или превосходства другой модели. Результаты не позволяют предполагать, что более мощная модель обязательно повысит точность. Подробности и исходные ошибки сохранены в [исторических результатах](results.md). Локализация доступна; выбранная ячейка не является точной маской, центром объекта, сегментацией или гарантией универсальной точности карты.
256
270
 
257
271
  ## Разработка и следующие документы
258
272
 
@@ -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
 
package/docs/agents.ru.md CHANGED
@@ -4,24 +4,26 @@
4
4
 
5
5
  ## Глобальные правила владельца
6
6
 
7
- Cursor **не** подгружает автоматически файлы из `/root/.cursor/rules/`. **Главный оркестратор** и **каждый** порождённый подагент Codex должны прочитать оба канонических файла:
7
+ Cursor **не** подгружает автоматически файлы из `/root/.cursor/rules/`. **Главный оркестратор** и **каждый** порождённый подагент Codex должны прочитать все три канонических файла:
8
8
 
9
- | Файл | Назначение |
10
- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
11
- | `repository-cleanliness.mdc` (`/root/.cursor/rules/repository-cleanliness.mdc`) | Уборка только артефактов текущей задачи; сохранять чужие ветки, блокировки и журналы проверок |
12
- | `context7.mdc` (`/root/.cursor/rules/context7.mdc`) | Внешняя документация SDK, API и CLI по запросу; **не** для внутреннего рефакторинга и документации репозитория |
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`, если владелец явно не разрешил иное |
13
14
 
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).
15
16
 
16
17
  ## Роли
17
18
 
18
- | Роль | Модель / исполнитель | Обязанности |
19
- | ------------------------ | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
- | **Главный оркестратор** | Выбирает **человек** (нет модели главного по умолчанию) | По умолчанию: анализ, исследование, проверка изменений, планирование, прогон тестов, интеграция в Git после проверки; **никогда** не запускает и не владеет Cursor CLI; **не** подменяет Composer при правках исходников, тестов и документации в разрешённых границах |
21
- | **Координатор** | **`gpt-6-luna`**, рассуждение **`high`**, **`fork_turns=none`** (иначе — только явная инструкция человека) | Владелец **каждого** процесса Cursor CLI; предварительная проверка CLI перед первым запуском; постановка задач Composer; проверка фактических изменений и журналов; передача владения — только явно |
22
- | **Исполнитель Composer** | **`composer-2.5-fast`** | Редактирует разрешённые пути **сам**; **не** запускает `cursor-agent`, не делегирует и не запускает вложенных агентов |
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`, не делегирует и не запускает вложенных агентов |
23
25
 
24
- **Каждый** подагент Codex любой роли (включая координацию и явно запрошенные исследование или проверку изменений) порождается как **`gpt-6-luna` / `high` / `fork_turns=none`**, если человек не указал иное.
26
+ **Каждый** подагент Codex любой роли (включая координацию, автора текста и явно запрошенные исследование или проверку изменений) порождается как **`gpt-6-luna` / `high` / `fork_turns=none`**, если человек не указал иное. Владелец уже дал постоянное разрешение на такую роль, поэтому не нужно спрашивать отдельно для каждой задачи. Если главный оркестратор сам работает на Luna, он может написать текст напрямую; не нужно менять выбранную человеком модель или создавать дублирующую роль.
25
27
 
26
28
  Отдельные подагенты для исследования или проверки изменений — **только по явному запросу** человека и остаются **только для чтения**. Иначе исследование и проверку изменений выполняет главный оркестратор.
27
29
 
@@ -70,7 +72,7 @@ cursor-agent \
70
72
  - v0.2 `extract`: геометрия из маски, закрытая проверка рамки, не более одного расширения маски и финальной проверки; без координат от модели.
71
73
  - Ранг не равен вероятности; один финальный ID против четырёх кандидатов пространственной стадии луча.
72
74
  - Каталог `benchmarks`: `hashCanonical` = `SHA-256`(`JSON.stringify`) с фиксированным порядком полей.
73
- - Исследования в `benchmarks/experiments/` — вне дистрибутива npm; публичный профиль `experimental-text` явно отклоняет не квалифицированные запросы.
75
+ - Исследования в `benchmarks/experiments/` — вне дистрибутива npm; публичный селектор IMAGE-AS-TEXT удалён (`INVALID_INPUT`); benchmark-only композиция через `createResearchClassifier`.
74
76
 
75
77
  ## Тесты
76
78
 
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
 
@@ -2,13 +2,13 @@
2
2
 
3
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
- 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.
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
6
 
7
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.
8
8
 
9
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.
10
10
 
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; 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
12
 
13
13
  ```mermaid
14
14
  flowchart TB