zorya-classifier 0.0.0-stage → 0.2.0

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 (369) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +13 -0
  3. package/README.md +139 -2
  4. package/dist/app/cli-arguments.d.ts +40 -0
  5. package/dist/app/cli-arguments.js +67 -0
  6. package/dist/app/cli-route.d.ts +3 -0
  7. package/dist/app/cli-route.js +40 -0
  8. package/dist/app/create-classifier.d.ts +33 -0
  9. package/dist/app/create-classifier.js +312 -0
  10. package/dist/app/extraction-files.d.ts +9 -0
  11. package/dist/app/extraction-files.js +28 -0
  12. package/dist/cli.d.ts +2 -0
  13. package/dist/cli.js +77 -0
  14. package/dist/entities/boundary-view.d.ts +29 -0
  15. package/dist/entities/boundary-view.js +1 -0
  16. package/dist/entities/contracts.d.ts +471 -0
  17. package/dist/entities/contracts.js +97 -0
  18. package/dist/entities/cutout-raster.d.ts +7 -0
  19. package/dist/entities/cutout-raster.js +1 -0
  20. package/dist/entities/errors.d.ts +7 -0
  21. package/dist/entities/errors.js +16 -0
  22. package/dist/entities/object-proposals.d.ts +53 -0
  23. package/dist/entities/object-proposals.js +8 -0
  24. package/dist/entities/representation.d.ts +225 -0
  25. package/dist/entities/representation.js +33 -0
  26. package/dist/entities/segmentation-metadata.d.ts +11 -0
  27. package/dist/entities/segmentation-metadata.js +1 -0
  28. package/dist/entities/segmentation-verification.d.ts +30 -0
  29. package/dist/entities/segmentation-verification.js +1 -0
  30. package/dist/entities/segmentation.d.ts +159 -0
  31. package/dist/entities/segmentation.js +5 -0
  32. package/dist/entities/whole-object.d.ts +128 -0
  33. package/dist/entities/whole-object.js +7 -0
  34. package/dist/features/choice-beam-layout.d.ts +18 -0
  35. package/dist/features/choice-beam-layout.js +136 -0
  36. package/dist/features/choice.d.ts +4 -0
  37. package/dist/features/choice.js +83 -0
  38. package/dist/features/prompts.d.ts +8 -0
  39. package/dist/features/prompts.js +56 -0
  40. package/dist/features/segmentation/box-check.d.ts +10 -0
  41. package/dist/features/segmentation/box-check.js +299 -0
  42. package/dist/features/segmentation/mask.d.ts +6 -0
  43. package/dist/features/segmentation/mask.js +89 -0
  44. package/dist/features/segmentation/packed-mask.d.ts +5 -0
  45. package/dist/features/segmentation/packed-mask.js +53 -0
  46. package/dist/features/uniform-grid.d.ts +3 -0
  47. package/dist/features/uniform-grid.js +35 -0
  48. package/dist/index.d.ts +10 -0
  49. package/dist/index.js +2 -0
  50. package/dist/infrastructure/boundary-view.d.ts +2 -0
  51. package/dist/infrastructure/boundary-view.js +263 -0
  52. package/dist/infrastructure/openrouter-common.d.ts +130 -0
  53. package/dist/infrastructure/openrouter-common.js +317 -0
  54. package/dist/infrastructure/openrouter-vision.d.ts +11 -0
  55. package/dist/infrastructure/openrouter-vision.js +17 -0
  56. package/dist/infrastructure/openrouter.d.ts +19 -0
  57. package/dist/infrastructure/openrouter.js +207 -0
  58. package/dist/infrastructure/raster.d.ts +11 -0
  59. package/dist/infrastructure/raster.js +216 -0
  60. package/dist/infrastructure/segmentation/box-presentation.d.ts +2 -0
  61. package/dist/infrastructure/segmentation/box-presentation.js +136 -0
  62. package/dist/infrastructure/segmentation/cutout-raster.d.ts +3 -0
  63. package/dist/infrastructure/segmentation/cutout-raster.js +79 -0
  64. package/dist/infrastructure/segmentation/grabcut/index.d.ts +13 -0
  65. package/dist/infrastructure/segmentation/grabcut/index.js +118 -0
  66. package/dist/infrastructure/segmentation/grabcut/worker-inference.d.ts +47 -0
  67. package/dist/infrastructure/segmentation/grabcut/worker-inference.js +260 -0
  68. package/dist/infrastructure/segmentation/index.d.ts +2 -0
  69. package/dist/infrastructure/segmentation/index.js +2 -0
  70. package/dist/infrastructure/segmentation/mobile-sam/index.d.ts +58 -0
  71. package/dist/infrastructure/segmentation/mobile-sam/index.js +472 -0
  72. package/dist/infrastructure/segmentation/mobile-sam/worker-inference.d.ts +149 -0
  73. package/dist/infrastructure/segmentation/mobile-sam/worker-inference.js +845 -0
  74. package/dist/infrastructure/segmentation/native-child.d.ts +23 -0
  75. package/dist/infrastructure/segmentation/native-child.js +297 -0
  76. package/dist/infrastructure/segmentation/native-protocol.d.ts +923 -0
  77. package/dist/infrastructure/segmentation/native-protocol.js +242 -0
  78. package/dist/infrastructure/segmentation/native-worker.d.ts +1 -0
  79. package/dist/infrastructure/segmentation/native-worker.js +93 -0
  80. package/dist/infrastructure/segmentation/probe-backend.d.ts +1 -0
  81. package/dist/infrastructure/segmentation/probe-backend.js +31 -0
  82. package/dist/infrastructure/segmentation/proposal-presentation.d.ts +3 -0
  83. package/dist/infrastructure/segmentation/proposal-presentation.js +371 -0
  84. package/dist/infrastructure/segmentation/verify-asset.d.ts +4 -0
  85. package/dist/infrastructure/segmentation/verify-asset.js +32 -0
  86. package/dist/infrastructure/text-representation.d.ts +23 -0
  87. package/dist/infrastructure/text-representation.js +226 -0
  88. package/dist/infrastructure/vision-chat.d.ts +64 -0
  89. package/dist/infrastructure/vision-chat.js +318 -0
  90. package/dist/openai-compatible.d.ts +8 -0
  91. package/dist/openai-compatible.js +11 -0
  92. package/dist/openrouter.d.ts +4 -0
  93. package/dist/openrouter.js +2 -0
  94. package/dist/processes/boundary-state.d.ts +12 -0
  95. package/dist/processes/boundary-state.js +196 -0
  96. package/dist/processes/classify.d.ts +3 -0
  97. package/dist/processes/classify.js +39 -0
  98. package/dist/processes/extract-from-region.d.ts +19 -0
  99. package/dist/processes/extract-from-region.js +415 -0
  100. package/dist/processes/extract.d.ts +25 -0
  101. package/dist/processes/extract.js +223 -0
  102. package/dist/processes/locate.d.ts +3 -0
  103. package/dist/processes/locate.js +274 -0
  104. package/dist/processes/proposal-location.d.ts +19 -0
  105. package/dist/processes/proposal-location.js +396 -0
  106. package/dist/processes/whole-object.d.ts +7 -0
  107. package/dist/processes/whole-object.js +272 -0
  108. package/dist/segmentation.d.ts +10 -0
  109. package/dist/segmentation.js +4 -0
  110. package/dist/shared/choice-mass.d.ts +2 -0
  111. package/dist/shared/choice-mass.js +19 -0
  112. package/dist/shared/gate.d.ts +11 -0
  113. package/dist/shared/gate.js +52 -0
  114. package/dist/shared/input-budget.d.ts +7 -0
  115. package/dist/shared/input-budget.js +21 -0
  116. package/dist/shared/scope.d.ts +12 -0
  117. package/dist/shared/scope.js +29 -0
  118. package/docs/0.2.0-plan.md +190 -0
  119. package/docs/README.ru.md +258 -0
  120. package/docs/acceptance.md +144 -0
  121. package/docs/api.md +49 -0
  122. package/docs/architecture.md +45 -0
  123. package/docs/benchmarks.md +63 -0
  124. package/docs/categorical-presence-port.md +26 -0
  125. package/docs/evidence/current-linux-check.json +15 -0
  126. package/docs/evidence/decisions-completion-v1-manifest.json +96 -0
  127. package/docs/evidence/decisions-completion-v1-report.json +1205 -0
  128. package/docs/evidence/decisions-selection-v1-manifest.json +96 -0
  129. package/docs/evidence/decisions-selection-v1-report.json +1457 -0
  130. package/docs/evidence/jev-pricing-2026-10-18.json +69 -0
  131. package/docs/evidence/linux-check.json +20 -0
  132. package/docs/evidence/linux-check.txt +205 -0
  133. package/docs/evidence/live-release-smoke-manifest.json +82 -0
  134. package/docs/evidence/live-release-smoke-provenance.json +9 -0
  135. package/docs/evidence/live-release-smoke-report.json +2136 -0
  136. package/docs/evidence/live-v1-manifest.json +84 -0
  137. package/docs/evidence/live-v1-provenance.json +9 -0
  138. package/docs/evidence/live-v1-report.json +15555 -0
  139. package/docs/evidence/luna-decisions-fine-probe.json +19 -0
  140. package/docs/evidence/luna-decisions-locator-smoke-manifest.json +39 -0
  141. package/docs/evidence/luna-decisions-locator-smoke-report.json +149 -0
  142. package/docs/evidence/pack-check.json +26 -0
  143. package/docs/evidence/protocol-probes.json +61 -0
  144. package/docs/evidence/rejected-vision-selection-v1-qwen-photo-dev-01.json +42 -0
  145. package/docs/evidence/rejected-vision-selection-v1-qwen-photo-dev-17.json +42 -0
  146. package/docs/evidence/rejected-vision-selection-v1-qwen-photo-heldout-09.json +42 -0
  147. package/docs/evidence/rejected-vision-selection-v2-haiku-photo-dev-16.json +42 -0
  148. package/docs/evidence/rejected-vision-selection-v2-haiku-support-heldout-016.json +42 -0
  149. package/docs/evidence/v02/baseline.json +1043 -0
  150. package/docs/evidence/v02/boundary-variants.md +17 -0
  151. package/docs/evidence/v02/box-confirmation-dev40/README.md +15 -0
  152. package/docs/evidence/v02/box-confirmation-dev40/component-refinement.json +246 -0
  153. package/docs/evidence/v02/box-confirmation-dev40/evaluation.json +1663 -0
  154. package/docs/evidence/v02/box-confirmation-dev40/provenance.json +130 -0
  155. package/docs/evidence/v02/box-confirmation-dev40/report.json +127 -0
  156. package/docs/evidence/v02/box-confirmation-dev40-freeze-20261020-v1.json +230 -0
  157. package/docs/evidence/v02/box-confirmation-method-selection-20261020-v1.json +85 -0
  158. package/docs/evidence/v02/box-heldout-cancelled-before-dispatch-20261021-v1.json +32 -0
  159. package/docs/evidence/v02/box-heldout-combined-seal-20261021-v1.json +89 -0
  160. package/docs/evidence/v02/box-heldout-evaluator-truth-seal-20261021-v1.json +61 -0
  161. package/docs/evidence/v02/box-heldout-exclusion-audit-20261020-v1.json +81 -0
  162. package/docs/evidence/v02/box-heldout-map-seal-20261021-v1.json +48 -0
  163. package/docs/evidence/v02/box-heldout-photo-seal-20261020-v1.json +62 -0
  164. package/docs/evidence/v02/box-heldout-run-freeze-20261021-v1.json +61 -0
  165. package/docs/evidence/v02/box-heldout-source-review-20261020-v1.json +134 -0
  166. package/docs/evidence/v02/box-heldout-ui-seal-20261020-v1.json +44 -0
  167. package/docs/evidence/v02/calculator-proof-root-review-20261020-v1.json +63 -0
  168. package/docs/evidence/v02/categorical-dev40-freeze.json +94 -0
  169. package/docs/evidence/v02/categorical-dev40-preserve.json +460 -0
  170. package/docs/evidence/v02/categorical-dev40-target-only.json +460 -0
  171. package/docs/evidence/v02/categorical-heldout-admission-20261020-v3.json +215 -0
  172. package/docs/evidence/v02/categorical-heldout-admission-20261020-v4.json +270 -0
  173. package/docs/evidence/v02/categorical-heldout-dispatch-authorization-20261020-v4.json +79 -0
  174. package/docs/evidence/v02/categorical-heldout-predispatch-20261020-v3.json +57 -0
  175. package/docs/evidence/v02/categorical-heldout-producer-source-map-v4.json +262 -0
  176. package/docs/evidence/v02/categorical-heldout-producer-source-map.json +263 -0
  177. package/docs/evidence/v02/categorical-heldout-run-freeze-20261020-v3.json +35 -0
  178. package/docs/evidence/v02/categorical-heldout-run-freeze-20261020-v4.json +35 -0
  179. package/docs/evidence/v02/categorical-heldout-v4/README.md +35 -0
  180. package/docs/evidence/v02/categorical-heldout-v4/candidate-evaluation.json +2812 -0
  181. package/docs/evidence/v02/categorical-heldout-v4/candidate-physical-receipts.json +15261 -0
  182. package/docs/evidence/v02/categorical-heldout-v4/candidate-provenance.json +131 -0
  183. package/docs/evidence/v02/categorical-heldout-v4/control-evaluation.json +855 -0
  184. package/docs/evidence/v02/categorical-heldout-v4/control-physical-receipts.json +4402 -0
  185. package/docs/evidence/v02/categorical-heldout-v4/control-provenance.json +31 -0
  186. package/docs/evidence/v02/categorical-heldout-v4/mask-normalized-exploratory.json +682 -0
  187. package/docs/evidence/v02/categorical-heldout-v4/paired-qualification.json +21 -0
  188. package/docs/evidence/v02/categorical-heldout-v4/report.json +258 -0
  189. package/docs/evidence/v02/categorical-presence-dev6.json +144 -0
  190. package/docs/evidence/v02/categorical-presence-dev6.md +18 -0
  191. package/docs/evidence/v02/categorical-vision-method-selection.json +90 -0
  192. package/docs/evidence/v02/checked-region-component-v1/README.md +7 -0
  193. package/docs/evidence/v02/checked-region-component-v1/evidence.json +311 -0
  194. package/docs/evidence/v02/checked-region-resource-interrupted-2b0d09f.json +102 -0
  195. package/docs/evidence/v02/checked-region-segmentation-resource-4df544c-receipt.json +167 -0
  196. package/docs/evidence/v02/checked-region-segmentation-resource-4df544c-root-review.json +58 -0
  197. package/docs/evidence/v02/checked-region-segmentation-resource-987ac32-receipt.json +158 -0
  198. package/docs/evidence/v02/ci-012b935.json +17 -0
  199. package/docs/evidence/v02/ci-0c365cb.json +372 -0
  200. package/docs/evidence/v02/ci-185bde8.json +32 -0
  201. package/docs/evidence/v02/ci-24f849f.json +95 -0
  202. package/docs/evidence/v02/ci-25c19cd.json +375 -0
  203. package/docs/evidence/v02/ci-2922caf.json +375 -0
  204. package/docs/evidence/v02/ci-29357d7.json +29 -0
  205. package/docs/evidence/v02/ci-32aa90d.json +24 -0
  206. package/docs/evidence/v02/ci-35e3064.json +376 -0
  207. package/docs/evidence/v02/ci-4331b1b.json +384 -0
  208. package/docs/evidence/v02/ci-43b7426.json +376 -0
  209. package/docs/evidence/v02/ci-450439c.json +373 -0
  210. package/docs/evidence/v02/ci-46283fe.json +29 -0
  211. package/docs/evidence/v02/ci-4c9c09f.json +34 -0
  212. package/docs/evidence/v02/ci-5579646.json +27 -0
  213. package/docs/evidence/v02/ci-6f9cc15.json +127 -0
  214. package/docs/evidence/v02/ci-7c1051f.json +27 -0
  215. package/docs/evidence/v02/ci-9837888.json +34 -0
  216. package/docs/evidence/v02/ci-987ac32.json +29 -0
  217. package/docs/evidence/v02/ci-9d00fe5.json +25 -0
  218. package/docs/evidence/v02/ci-9f85acc.json +127 -0
  219. package/docs/evidence/v02/ci-be275a6.json +201 -0
  220. package/docs/evidence/v02/ci-c107ddf.json +372 -0
  221. package/docs/evidence/v02/ci-c35f67d.json +127 -0
  222. package/docs/evidence/v02/ci-c5eddd8.json +32 -0
  223. package/docs/evidence/v02/ci-d2042e0.json +372 -0
  224. package/docs/evidence/v02/ci-d684259.json +375 -0
  225. package/docs/evidence/v02/ci-e0c190b.json +127 -0
  226. package/docs/evidence/v02/ci-e551253.json +372 -0
  227. package/docs/evidence/v02/ci-f9d4633.json +29 -0
  228. package/docs/evidence/v02/dev1-proposal-evaluation.md +13 -0
  229. package/docs/evidence/v02/dev2-mobile-sam-proposal-oracle.md +21 -0
  230. package/docs/evidence/v02/dev2-proposal-evaluation.md +21 -0
  231. package/docs/evidence/v02/fresh-development.md +16 -0
  232. package/docs/evidence/v02/fresh-native-numeric/artifact-hashes.json +9 -0
  233. package/docs/evidence/v02/fresh-native-numeric/evaluation-root-v1.json +568 -0
  234. package/docs/evidence/v02/fresh-native-numeric/run-manifest.json +342 -0
  235. package/docs/evidence/v02/fresh-native-numeric/summary.json +5654 -0
  236. package/docs/evidence/v02/fresh-native-outline-axis/artifact-hashes.json +9 -0
  237. package/docs/evidence/v02/fresh-native-outline-axis/evaluation-root-v1.json +568 -0
  238. package/docs/evidence/v02/fresh-native-outline-axis/run-manifest.json +378 -0
  239. package/docs/evidence/v02/fresh-native-outline-axis/summary.json +5605 -0
  240. package/docs/evidence/v02/fresh-text/README.md +23 -0
  241. package/docs/evidence/v02/fresh-text/ascii-contours-v1/classify-followup-run-manifest.json +405 -0
  242. package/docs/evidence/v02/fresh-text/ascii-contours-v1/classify-followup-summary.json +1646 -0
  243. package/docs/evidence/v02/fresh-text/ascii-contours-v1/evaluation.json +568 -0
  244. package/docs/evidence/v02/fresh-text/ascii-contours-v1/original-run-manifest.json +404 -0
  245. package/docs/evidence/v02/fresh-text/ascii-contours-v1/original-summary.json +4416 -0
  246. package/docs/evidence/v02/fresh-text/ascii-luma-v1/classify-followup-run-manifest.json +405 -0
  247. package/docs/evidence/v02/fresh-text/ascii-luma-v1/classify-followup-summary.json +1646 -0
  248. package/docs/evidence/v02/fresh-text/ascii-luma-v1/evaluation.json +568 -0
  249. package/docs/evidence/v02/fresh-text/ascii-luma-v1/original-run-manifest.json +404 -0
  250. package/docs/evidence/v02/fresh-text/ascii-luma-v1/original-summary.json +4647 -0
  251. package/docs/evidence/v02/fresh-text/ascii-svg-layered-v1/classify-followup-run-manifest.json +405 -0
  252. package/docs/evidence/v02/fresh-text/ascii-svg-layered-v1/classify-followup-summary.json +846 -0
  253. package/docs/evidence/v02/fresh-text/ascii-svg-layered-v1/evaluation.json +568 -0
  254. package/docs/evidence/v02/fresh-text/ascii-svg-layered-v1/original-run-manifest.json +404 -0
  255. package/docs/evidence/v02/fresh-text/ascii-svg-layered-v1/original-summary.json +1789 -0
  256. package/docs/evidence/v02/fresh-text/no-image-control/evaluation.json +568 -0
  257. package/docs/evidence/v02/fresh-text/no-image-control/original-run-manifest.json +404 -0
  258. package/docs/evidence/v02/fresh-text/no-image-control/original-summary.json +3953 -0
  259. package/docs/evidence/v02/fresh-text/palette-grid-v1/classify-followup-run-manifest.json +405 -0
  260. package/docs/evidence/v02/fresh-text/palette-grid-v1/classify-followup-summary.json +1646 -0
  261. package/docs/evidence/v02/fresh-text/palette-grid-v1/evaluation.json +568 -0
  262. package/docs/evidence/v02/fresh-text/palette-grid-v1/original-run-manifest.json +404 -0
  263. package/docs/evidence/v02/fresh-text/palette-grid-v1/original-summary.json +3974 -0
  264. package/docs/evidence/v02/fresh-text/pixel-rle-v1/classify-followup-run-manifest.json +405 -0
  265. package/docs/evidence/v02/fresh-text/pixel-rle-v1/classify-followup-summary.json +1646 -0
  266. package/docs/evidence/v02/fresh-text/pixel-rle-v1/evaluation.json +568 -0
  267. package/docs/evidence/v02/fresh-text/pixel-rle-v1/original-run-manifest.json +404 -0
  268. package/docs/evidence/v02/fresh-text/pixel-rle-v1/original-summary.json +4945 -0
  269. package/docs/evidence/v02/fresh-text/report.json +284 -0
  270. package/docs/evidence/v02/fresh-text/svg-contours-v1/classify-followup-run-manifest.json +405 -0
  271. package/docs/evidence/v02/fresh-text/svg-contours-v1/classify-followup-summary.json +846 -0
  272. package/docs/evidence/v02/fresh-text/svg-contours-v1/evaluation.json +568 -0
  273. package/docs/evidence/v02/fresh-text/svg-contours-v1/original-run-manifest.json +404 -0
  274. package/docs/evidence/v02/fresh-text/svg-contours-v1/original-summary.json +2189 -0
  275. package/docs/evidence/v02/heldout-evaluation-20261020.md +37 -0
  276. package/docs/evidence/v02/heldout-input-derivation.md +18 -0
  277. package/docs/evidence/v02/integration-0c365cb.json +90 -0
  278. package/docs/evidence/v02/integration-25c19cd.json +52 -0
  279. package/docs/evidence/v02/integration-35e3064.json +41 -0
  280. package/docs/evidence/v02/integration-4331b1b.json +42 -0
  281. package/docs/evidence/v02/integration-4c9c09f.json +46 -0
  282. package/docs/evidence/v02/integration-8010aad.json +48 -0
  283. package/docs/evidence/v02/integration-c1aa640.json +41 -0
  284. package/docs/evidence/v02/integration-eea1790.json +46 -0
  285. package/docs/evidence/v02/integration-fa82e65.json +42 -0
  286. package/docs/evidence/v02/jpeg-transport-offline.json +268 -0
  287. package/docs/evidence/v02/jpeg-transport-offline.md +7 -0
  288. package/docs/evidence/v02/local-archive-cleanup.json +59 -0
  289. package/docs/evidence/v02/native-base64-after.json +30 -0
  290. package/docs/evidence/v02/native-base64-before.json +32 -0
  291. package/docs/evidence/v02/native-checked-region-windows-46283fe.json +248 -0
  292. package/docs/evidence/v02/native-checked-region-windows-987ac32.json +141 -0
  293. package/docs/evidence/v02/native-grabcut-windows-4c494a3-run2.json +148 -0
  294. package/docs/evidence/v02/native-grabcut-windows-4c494a3-run3.json +148 -0
  295. package/docs/evidence/v02/native-grabcut-windows-4c494a3.json +56 -0
  296. package/docs/evidence/v02/native-proposal-windows-0c365cb.json +148 -0
  297. package/docs/evidence/v02/native-proposal-windows-450439c.json +156 -0
  298. package/docs/evidence/v02/native-proposal-windows-4c9c09f-retry1.json +147 -0
  299. package/docs/evidence/v02/native-proposal-windows-4c9c09f.json +52 -0
  300. package/docs/evidence/v02/native-region-windows-efc9318.json +163 -0
  301. package/docs/evidence/v02/native-windows-eea1790-baseline.json +198 -0
  302. package/docs/evidence/v02/native-windows-eea1790.json +228 -0
  303. package/docs/evidence/v02/ordinary-luna-axis/run-manifest.json +99 -0
  304. package/docs/evidence/v02/ordinary-luna-axis/summary.json +811 -0
  305. package/docs/evidence/v02/owned-temp-cleanup-20261020-v1.json +28 -0
  306. package/docs/evidence/v02/presentation-paired-20261020.json +1438 -0
  307. package/docs/evidence/v02/proposal-resource-soak-261dc23.json +201 -0
  308. package/docs/evidence/v02/proposal-resource-soak-261dc23.md +15 -0
  309. package/docs/evidence/v02/proposal-resource-soak-450439c-receipt.md +13 -0
  310. package/docs/evidence/v02/reconstructed-c03-box.json +41 -0
  311. package/docs/evidence/v02/region-seeded-dev-v1/README.md +17 -0
  312. package/docs/evidence/v02/region-seeded-dev-v1/evaluation.json +260 -0
  313. package/docs/evidence/v02/region-seeded-dev-v2/README.md +15 -0
  314. package/docs/evidence/v02/region-seeded-dev-v2/evaluation.json +232 -0
  315. package/docs/evidence/v02/region-seeded-dev-v3-candidate-only/README.md +9 -0
  316. package/docs/evidence/v02/region-seeded-dev-v3-candidate-only/control-identity-failure.json +22 -0
  317. package/docs/evidence/v02/region-seeded-dev-v3-candidate-only/evaluation.json +160 -0
  318. package/docs/evidence/v02/region-seeded-dev-v3-control-r2/README.md +9 -0
  319. package/docs/evidence/v02/region-seeded-dev-v3-control-r2/attempt-accounting.json +55 -0
  320. package/docs/evidence/v02/region-seeded-dev-v3-control-r2/evaluation.json +136 -0
  321. package/docs/evidence/v02/region-seeded-development-control-r2-freeze-20261021.json +132 -0
  322. package/docs/evidence/v02/region-seeded-development-freeze-20261021-v1.json +167 -0
  323. package/docs/evidence/v02/region-seeded-development-freeze-20261021-v2.json +186 -0
  324. package/docs/evidence/v02/region-seeded-development-freeze-20261021-v3.json +205 -0
  325. package/docs/evidence/v02/region-seeded-heldout-cancelled-before-dispatch-20261021-v2.json +20 -0
  326. package/docs/evidence/v02/region-seeded-heldout-dispatch-authorization-20261021-v3.json +47 -0
  327. package/docs/evidence/v02/region-seeded-heldout-readiness-audit-20261021-v3.json +125 -0
  328. package/docs/evidence/v02/region-seeded-heldout-run-freeze-20261021-v2.json +234 -0
  329. package/docs/evidence/v02/region-seeded-heldout-run-freeze-20261021-v3.json +357 -0
  330. package/docs/evidence/v02/region-seeded-heldout-v3/README.md +19 -0
  331. package/docs/evidence/v02/region-seeded-heldout-v3/evaluation-summary.json +445 -0
  332. package/docs/evidence/v02/region-seeded-method-selection-20261021-v2.json +66 -0
  333. package/docs/evidence/v02/region-seeded-method-selection-20261021-v3.json +120 -0
  334. package/docs/evidence/v02/region-segmentation-resource-0ba4c87-receipt.json +156 -0
  335. package/docs/evidence/v02/resource-soak-linux-8010aad.json +125 -0
  336. package/docs/evidence/v02/screen-v2-terminal-evaluation.md +22 -0
  337. package/docs/evidence/v02/seed-outline/run-manifest.json +59 -0
  338. package/docs/evidence/v02/seed-outline/summary.json +487 -0
  339. package/docs/evidence/v02/seed-unbounded/run-manifest.json +80 -0
  340. package/docs/evidence/v02/seed-unbounded/summary.json +730 -0
  341. package/docs/evidence/v02/segmentation/README.md +21 -0
  342. package/docs/evidence/v02/segmentation/component-comparison-summary.json +240 -0
  343. package/docs/evidence/v02/segmentation/provenance/MOBILE-SAM-LICENSE.txt +201 -0
  344. package/docs/evidence/v02/segmentation/provenance/OPENCV-LICENSE.txt +202 -0
  345. package/docs/evidence/v02/segmentation/provenance/mobile-sam-download-receipt.json +29 -0
  346. package/docs/evidence/v02/segmentation/provenance/mobile-sam-graph-audit.json +214 -0
  347. package/docs/evidence/v02/segmentation/provenance/mobile-sam-model-metadata.json +166 -0
  348. package/docs/evidence/v02/split-choice-noul-dev6.json +72 -0
  349. package/docs/evidence/v02/split-choice-noul-dev6.md +11 -0
  350. package/docs/evidence/v02/supported-vision-screen-20261020.md +65 -0
  351. package/docs/evidence/v02/wesnoth-1.16.11-minimap-projection-source-audit.md +56 -0
  352. package/docs/evidence/v02/wesnoth-proof-root-review-20261020-v1.json +76 -0
  353. package/docs/evidence/vision-cost-reconciliation.json +37 -0
  354. package/docs/evidence/vision-model-summary.json +562 -0
  355. package/docs/evidence/vision-selection-v1-manifest.json +95 -0
  356. package/docs/evidence/vision-selection-v1-report.json +4598 -0
  357. package/docs/evidence/vision-selection-v2-manifest.json +95 -0
  358. package/docs/evidence/vision-selection-v2-report.json +1139 -0
  359. package/docs/evidence/windows-native.json +73 -0
  360. package/docs/evidence/windows-secrets.json +46 -0
  361. package/docs/operations.md +21 -0
  362. package/docs/plan.md +27 -0
  363. package/docs/provenance.json +32 -0
  364. package/docs/publishing.md +30 -0
  365. package/docs/research/text-transport-audit.md +66 -0
  366. package/docs/results.md +69 -0
  367. package/docs/v02-usage.md +162 -0
  368. package/docs/vision-results.md +78 -0
  369. package/package.json +114 -4
@@ -0,0 +1,73 @@
1
+ {
2
+ "status": "PASS",
3
+ "scope": "Final explicit-rounding runtime native Windows source/package offline qualification; no inference, game, app or installer",
4
+ "createdAt": "2026-10-17T21:47:43.642962+00:00",
5
+ "rawReceiptSha256": "86f9d51e043883e7e8f7c804f6ef64037d84adb548fedc8b121be8a79298df49",
6
+ "platform": {
7
+ "platform": "win32",
8
+ "node": "v24.19.0",
9
+ "arch": "x64",
10
+ "osType": "Windows_NT",
11
+ "osRelease": "10.0.26200",
12
+ "osVersion": "Windows 11 Pro"
13
+ },
14
+ "npm": "11.17.0",
15
+ "steps": [
16
+ {
17
+ "step": "check-final",
18
+ "durationMs": 11737.6716,
19
+ "exitCode": 0,
20
+ "timedOut": false,
21
+ "physicalCloseObserved": true,
22
+ "stdoutSha256": "1a02d2081e7b52e7d16c252627caa7d2427aaf93c5defc2aea541b18c86487e7",
23
+ "stderrSha256": "bdd8e52cff96a1a2de65f7c89c275f8eb847c4cb3c4e80298775e92dc8853ba8"
24
+ },
25
+ {
26
+ "step": "pack-check-final",
27
+ "durationMs": 6953.8477,
28
+ "exitCode": 0,
29
+ "timedOut": false,
30
+ "physicalCloseObserved": true,
31
+ "stdoutSha256": "975c81cf847d6360b2199e518f17f84e2570210a46e4759409f8ec319f57fdcc",
32
+ "stderrSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
33
+ }
34
+ ],
35
+ "tests": {
36
+ "tests": 142,
37
+ "pass": 142,
38
+ "fail": 0,
39
+ "cancelled": 0,
40
+ "skipped": 0
41
+ },
42
+ "consumer": {
43
+ "independentConsumer": "passed",
44
+ "declarations": "compiled",
45
+ "sharp": "0.34.5",
46
+ "vips": "8.17.3",
47
+ "classification": "yes",
48
+ "localization": "located",
49
+ "controlledDecisionCalls": 4,
50
+ "providerHttpCalls": 0
51
+ },
52
+ "testedSnapshotPackage": {
53
+ "files": 47,
54
+ "unpackedSize": 109715,
55
+ "sha256": "9029ed25c0c5f2ecc638d87d69d0dbefe1024181ccbe19bfe6f5513e85da0426",
56
+ "runtimeDistFiles": 34,
57
+ "runtimeDistSha256": "62d5a0075e5ccca6627ba81f8ca8be427f499ded7508570171c00520bcf369ca",
58
+ "consumerDeclarationFiles": 184,
59
+ "npmTransport": "node npm-cli.js; shell:false"
60
+ },
61
+ "runtimeDistEqualLinuxWindows": true,
62
+ "sourceMismatchCounts": {
63
+ "immutable": 0,
64
+ "staged": 0
65
+ },
66
+ "limitations": [
67
+ "Offline fake-fetch/DecisionPort checks do not qualify live Jev accuracy or performance",
68
+ "No Windows app/installer/game executed",
69
+ "Source docs may evolve after this immutable runtime snapshot",
70
+ "No OS-wide process/network trace claimed"
71
+ ],
72
+ "note": "Host-specific temporary paths removed from this public summary; original receipt retained locally. Final release docs/evidence can change archive SHA without changing tested dist."
73
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "status": "PASS",
3
+ "scope": "Native Windows offline secrets guard qualification only; not a repeat of runtime suite",
4
+ "createdAt": "2026-10-17T22:05:25.617601+00:00",
5
+ "probe": {
6
+ "node": "v24.19.0",
7
+ "arch": "x64",
8
+ "platform": "win32",
9
+ "osRelease": "10.0.26200",
10
+ "osVersion": "Windows 11 Pro"
11
+ },
12
+ "gitVersion": "git version 2.52.0.windows.1",
13
+ "tests": {
14
+ "tests": 16,
15
+ "pass": 15,
16
+ "fail": 0,
17
+ "cancelled": 0,
18
+ "skipped": 1
19
+ },
20
+ "expectedSkipped": "POSIX FIFO creation regression; unavailable on Win32; Linux passed this case",
21
+ "worktreeScan": {
22
+ "status": "PASS",
23
+ "mode": "--worktree",
24
+ "scanned": 5,
25
+ "skippedBinary": 0,
26
+ "totalBytes": 154472
27
+ },
28
+ "stagedScan": {
29
+ "status": "PASS",
30
+ "mode": "--staged",
31
+ "scanned": 5,
32
+ "skippedBinary": 0,
33
+ "totalBytes": 154472
34
+ },
35
+ "sourceGuardPinsUnchanged": true,
36
+ "stagedPinsUnchanged": true,
37
+ "otherSourceChanges": [],
38
+ "limitations": [
39
+ "Heuristic text scanner does not guarantee detection of all credentials",
40
+ "Binary contents skipped explicitly after filename checks",
41
+ "Parent-directory replacement is not an atomic filesystem sandbox boundary",
42
+ "No model HTTP, private-key modification, application or installer execution",
43
+ "Npm registry installation used pinned lock and --ignore-scripts; no OS-wide network trace"
44
+ ],
45
+ "rawReceiptSha256": "271c48e4f6f149b195fd6e8c6d385d69f11bd41764cfa4ff52ce2a0b0ff9eaea"
46
+ }
@@ -0,0 +1,21 @@
1
+ # Operations
2
+
3
+ Configure a trusted model endpoint or the optional OpenRouter route. SDK factories receive endpoint/model/key explicitly; the core knows only DecisionPort. Keep server-specific credentials separate from OpenRouter credentials. Store keys in ignored local files or a secret manager. No startup request is made.
4
+
5
+ CLI requires `ZORYA_MODEL` and defaults to `ZORYA_MODE=decisions`. For ordinary vision models/custom chat servers choose `ZORYA_MODE=chat`. OpenRouter mode requires `OPENROUTER_API_KEY` and `ZORYA_PROVIDER`; direct mode uses a full `ZORYA_ENDPOINT` with optional separate `ZORYA_API_KEY`, and never forwards the OpenRouter key. In chat mode, optional `ZORYA_REASONING_EFFORT` and `ZORYA_RESPONSE_FORMAT` must be supported by the chosen endpoint. Use `zorya-classifier --help`. Commands: classify-text text classes.json; classify-image image classes.json; locate image target. CLI calls real paid models. Native images are decoded locally through Sharp; external requests send prepared text/images to the configured route. The library neither writes nor logs media by default.
6
+
7
+ Choose a finite timeout based on your UI needs. Default 45s includes queue time; no latency SLA is asserted. Handle CAPACITY by applying upstream backpressure rather than creating more clients. Explicitly cancel superseded application requests and call dispose on shutdown. A cancelled native job may finish before its slot is released; this prevents unbounded physical concurrency.
8
+
9
+ Unknown cost remains unknown. Budget your own calls or use the benchmark's conservative reservations. Do not implement retries around locate without accounting for all prior physical calls and potential charges. Screenshots can become stale while analysis runs; acquiring current frames and deciding whether results are still relevant belongs to the application.
10
+
11
+ Build release locally with npm run check and npm run pack:check. Produce npm pack only after those gates. Review LICENSE/NOTICE/acceptance and archive contents before publishing. Publication destinations are GitHub `zoomplus/zorya-classifier` and npm `zorya-classifier` under owner `zoomplus`. Authentication stays outside the repository. Check the remote release/registry and external receipt for actual publication state.
12
+
13
+ Owner handoff and authentication steps are in [publishing](publishing.md). Secret scanning commands and their limits are in [SECURITY](../SECURITY.md); they run in Husky, source checks and the archive check. Release manifests live next to the prepared archives, outside Git/npm contents.
14
+
15
+ Compatibility with another image-capable model does not imply tested accuracy or support for all structured-output parameters. Choose prompt/JSON-object/JSON-schema mode according to server capabilities, inspect explicit failures and consult docs/vision-results.md. Never label generated ranks as calibrated probabilities.
16
+
17
+ # 0.2 additions
18
+
19
+ Whole-object location, explicit extraction backends, CLI artifacts and ownership are described in [the 0.2 guide](v02-usage.md). The core input reservation is bounded across active and queued work; native admission rejects before expensive snapshots/base64. Keep a shared segmenter or object-proposal adapter alive until all owning clients have disposed. The optional CPU proposal adapter rejects sources above 2,097,152 pixels and packs at most 36 masks into a 10 MiB batch; it does not silently resize. Proposal selection is currently an API composition; the CLI retains the explicit interval/segmenter path. Raw native scores are uncalibrated diagnostics, never probability thresholds. Native calls currently start a fresh owned child each time; session reuse is not implemented. Do not extrapolate cold synthetic smoke timings into production latency or photo quality.
20
+
21
+ The [native resource harness](../benchmarks/v02/NATIVE-SMOKE.md) records independent parent samples, short-child memory, idle/busy phases, cancellation and child ownership without forcing garbage collection. A short harness verification is separate from the required two-hour resource run. Use an explicit corpus/asset manifest and preserve unsuccessful results.
package/docs/plan.md ADDED
@@ -0,0 +1,27 @@
1
+ # Accepted open-source extraction plan
2
+
3
+ Current implementation: [accepted 0.2 plan](0.2.0-plan.md), whole-object bounds, extraction and comparative text-only image experiments. The first-release plan below is retained as history.
4
+
5
+ First deliver an independent MIT Node.js/TypeScript library with classify(text/image/both) and locate(image,target), powered by Jev 1.14/TypeSafe. Preserve three Choice stages for localization, stable maxima/ties and source coordinates; no implicit model/provider fallback or retries. Classification is one native Choice. Separate heavy optional refinement and game/application dependencies.
6
+
7
+ Prepare public contracts, strict schemas, source rules, architecture/API/operations documentation, examples/CLI, offline regressions and Windows/Linux CI. Package into a clean npm archive and test installation outside the repository. Scan release contents for secrets, private paths and unwanted assets. Prepare a clean source repository; public GitHub/npm publishing is a separate action.
8
+
9
+ Evaluate 60 licensed real photographs (20 development/40 heldout) and 30 authored text fixtures (10/20). Separate raw producer inputs from ground truth. Compare classification against an independently called identical native Choice; evaluate one/two-stage locator prefix ablations from the three-stage run. Record mistakes, errors, latency, costs, true unknowns and visual overlays. No universal superiority claim without evidence.
10
+
11
+ Acceptance requires executed source checks, clean independent consumer install, an honest real-provider report and complete release documentation. Configured CI is not evidence of execution. Historical gaming/microphone checks and installer work remain separate.
12
+
13
+ ## Owner revision: universal vision classification before first npm publication
14
+
15
+ The owner replaced the Jev-centered release design after initial GitHub creation and before npm publication. Ordinary image-capable language models must work without a native classification/Decisions API. Implement an OpenRouter chat-completions adapter that requests closed ranked IDs and explicit present/absent/unknown predicates, validates all outputs and rejects invented IDs, extra questions, truncation, refusals and malformed JSON. Do not manufacture probabilities from ranks. Keep the original native adapter only as an optional compatibility/benchmark integration, never an implicit dependency/fallback.
16
+
17
+ Preserve the three grid stages, source-pixel geometry, input ownership, bounded queues, cancellation, byte caps, no retries/model fallback and route accountability. Extend the internal/public result contract with explicit rank-only evidence. The selected class is the first ranked ID; only genuine provider probability distributions remain probability-valued. Update examples, CLI, docs and rules to the generic adapter.
18
+
19
+ Compare cheap general vision candidates under a newly authorized bounded paid run before recommending the cheapest tested route that meets the recorded baseline. Preserve historical Jev reports as historical evidence, not a qualification for a different backend. A pending separate paid-run request does not authorize dispatch until approved. npm publication waits for updated code, independent archive checks, Windows/Linux CI and honest current-model evidence.
20
+
21
+ The first hosted Windows CI exposed a temporary-directory alias problem in the declaration-isolation check. Resolve Windows 8.3 aliases with the native filesystem canonicalizer; do not broaden allowed declaration roots or skip archive verification. Preserve the failed run and verify the corrected check in hosted Windows CI.
22
+
23
+ Additional owner requirement: provide a direct OpenAI-compatible endpoint adapter (including anonymous local servers/custom authentication) and a public custom port. OpenRouter is optional. README must explicitly distinguish configurable vision-model support from models/routes actually tested, with per-model accuracy, error, latency and price data.
24
+
25
+ ## Latest owner priority: native decision models except Jev
26
+
27
+ Prioritize Luna Decisions through the typed Decisions API. Keep model/provider explicit and implement a generic native adapter; retain ordinary vision-chat support as an alternative, and Jev only as an optional historical integration. Do not silently fall back between protocols. Native probabilities remain genuine values; quantization assumptions require explicit model-specific evidence/configuration. Reallocate the remaining approved comparison budget without exceeding290 total calls/$0.50. Current ordinary runs and their failures remain preserved.
@@ -0,0 +1,32 @@
1
+ {
2
+ "upstreamCommit": "97fca38ef027f0c83c63bd069248e6299619abd2",
3
+ "algorithm": "coarse4x4 -> four padded regions/fine<=49 each -> four enlarged candidate Choice",
4
+ "copiedOrAdaptedFiles": [
5
+ {
6
+ "source": "packages/screen-locator-service/src/features/grid/uniform-grid.ts",
7
+ "sourceSha256": "c4ed5506218e93a79eade528942fdc35f9197b2ea5f1af2027cba21b6e18b847",
8
+ "destination": "src/features/uniform-grid.ts"
9
+ },
10
+ {
11
+ "source": "packages/screen-locator-service/src/features/grid/choice-beam-layout.ts",
12
+ "sourceSha256": "4a2a22efc43ef69313da5cacb41425c336186e8602fb168dfdef5572586ee6c8",
13
+ "destination": "src/features/choice-beam-layout.ts"
14
+ },
15
+ {
16
+ "source": "tools/eslint-plugin-element-guard/no-discarded-interval.js",
17
+ "sourceSha256": "321c43b61b673515571c969ba4ff75e307c0eefaccad308c414c5736174d260e",
18
+ "destination": "tools/no-discarded-interval.mjs"
19
+ }
20
+ ],
21
+ "changes": [
22
+ "Standalone ports and lifecycle; no game/application dependencies",
23
+ "Multiple targets allowed, returning one candidate",
24
+ "Stable supplied-order tie selection",
25
+ "Compact grid rendering and generic prompts require independent new quality evidence",
26
+ "45-second default for standalone operations; original gaming deadline unchanged",
27
+ "Provider-independent ordinary vision chat protocol with closed ranks and separate presence; no invented probabilities",
28
+ "Direct OpenAI-compatible endpoint and optional OpenRouter wrapper; native Jev retained as optional historical integration",
29
+ "One winner for single-label/final selection; four ranks only for coarse/fine beam stages"
30
+ ],
31
+ "originalRepositoryModified": false
32
+ }
@@ -0,0 +1,30 @@
1
+ # Publishing handoff
2
+
3
+ The owner has authorized publication under GitHub account `zoomplus` and npm account `zoomplus`. The selected destinations are the public repository `zoomplus/zorya-classifier` and public package `zorya-classifier`. These names were available at the preflight check. Check the actual repository/registry and release receipt for completion; this document describes the release process rather than asserting remote state.
4
+
5
+ ## Owner and authentication
6
+
7
+ The supplied account profiles are https://github.com/zoomplus and https://www.npmjs.com/~zoomplus. The owner requested creation of the repository and publication without manually preparing either destination. MIT was already selected for the extracted code. No private email address is added to package metadata. A local package name is not a registry reservation; recheck availability and identity before dispatch.
8
+
9
+ Send account names and URLs, not passwords, API keys, recovery codes or authentication files. GitHub can be authenticated locally with `gh auth login --web`; the owner completes the browser flow. npm can use local `npm login` followed by the required browser/2FA publication confirmation. See [GitHub CLI authentication](https://cli.github.com/manual/gh_auth_login) and [npm publication authentication](https://docs.npmjs.com/requiring-2fa-for-package-publishing-and-settings-modification/).
10
+
11
+ For later CI releases, configure [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) with the actual GitHub repository/workflow. It uses OIDC rather than a long-lived npm token. Configure this after the package ownership and repository are known; a generic workflow would otherwise name an invented owner. Do not place tokens in a workflow or issue.
12
+
13
+ ## Maintainer release sequence
14
+
15
+ 1. Recheck package-name availability, author rights, MIT/third-party notices, acceptance limits and the desired public destination.
16
+ 2. Set the final package name/scope and repository/homepage/bugs metadata. Update imports/examples if the name changes, then rerun source and installed-archive checks. Existing archive hashes apply only to the original name/content.
17
+ 3. Run `npm run check`, `npm run pack:check`, `npm run format:check` and a redacted independent secret scan. Inspect actual staged blobs and the produced archive, not only `.gitignore`.
18
+ 4. Create/push only the clean standalone history, enable secret scanning/push protection and inspect the CI matrix. Raw runs, environment files, personal media and upstream history stay local. Public corpus downloads retain source licenses.
19
+ 5. Pack the reviewed version, verify its SHA256, then publish with the authorized account. Require the owner's authentication confirmation when prompted. Record registry integrity, Git tag/commit and release evidence.
20
+ 6. Verify the published version and `latest` dist-tag with the registry. Add the matching version tag and GitHub release notes. Keep the package's `repository`, `homepage` and `bugs` links correct, link npm prominently from GitHub, and update npm keywords plus GitHub Topics for the capabilities actually shipped. Examples include classification, object localization, whole-object bounding boxes, optional segmentation/cutouts, TypeScript and provider-independent model integration. Do not advertise an unqualified text-image research profile as supported.
21
+
22
+ Both GitHub and npm publication are authorized for this project. A local archive remains useful for pre-release installation, but does not complete the requested release.
23
+
24
+ ## 0.2 release evidence
25
+
26
+ Use the original-region/full-source-segmentation workflow in the current usage guide. Older interval/proposal experiments and their failed reports remain historical evidence; do not relabel them as measurements of the new flow. Record region hits separately from mask-derived object boxes and pixel-mask quality. The image-free control produces regions only.
27
+
28
+ Before release, match every runtime file in the final archive to the bytes covered by native/resource acceptance, and require green Windows/Linux × Node 22/24 CI for the release source. A later documentation-only archive can have a different package SHA while retaining the tested runtime; record both complete archive hashes and the explicit runtime-file parity proof. Keep a final independently installed consumer check for the actual release archive.
29
+
30
+ Keep the final release manifest outside its own archives to avoid self-reference. It records the clean source commit, archive hashes/integrities, model recipe and corpus seals, preserved failures, native/resource receipts, CI run and redacted secret scan. Publish those exact archive bytes, verify the registry response and dist-tag, then attach the matching source and npm artifact to the GitHub release. Do not replace failed accuracy or resource gates with an offline test count.
@@ -0,0 +1,66 @@
1
+ # Text-only transport audit for 0.2
2
+
3
+ Audited on 2026-10-20 against baseline `b6e562d`. This is a protocol audit, not a paid model evaluation or a claim that text-encoded photographs can be reliably recognized.
4
+
5
+ ## Existing behavior to retain
6
+
7
+ `src/infrastructure/vision-chat.ts` already implements a generic non-streaming Chat Completions transport. Images are optional: strings become text content parts, the final `CLASSIFICATION_TASK` follows all data, and a single strict output parser handles categorical rankings and independent presence answers. It does not require a native classifier API.
8
+
9
+ The transport owns a bounded JSON snapshot before the first await. It forwards the caller's cancellation signal, disables redirects, reads a bounded response, and releases/cancels its reader through `readResponse`. There is one physical request and no transport retry or provider/model fallback. Model aliases in responses are accepted only through explicit identities or validated date snapshots. Missing `usage.cost` remains `null`; a response with ranking IDs never acquires invented probabilities.
10
+
11
+ `src/infrastructure/openrouter-vision.ts` pins the Chat Completions endpoint and requires an explicit provider. Its request contains `provider.only`, `allow_fallbacks: false`, and `require_parameters: true`. `src/openai-compatible.ts` accepts an explicit trusted HTTP(S) endpoint and optional credentials, with no OpenRouter dependency.
12
+
13
+ ## Minimal additive implementation
14
+
15
+ 1. Factor the existing implementation into an internal chat factory with an explicit modality argument, `vision` or `text`. Retain `createVisionChat` as a compatible wrapper. Add `createTextChat` with the same transport/parser/options. No caller-controlled or extra wire field is necessary.
16
+ 2. In text mode, inspect the validated, owned request before fetch and reject every non-string state part with `UNSUPPORTED`. Do not silently strip images, stringify them, or accept their URLs as an alternative protocol. This check happens after plain-value snapshot validation, so accessors/proxies do not execute during modality validation.
17
+ 3. Select an accurate system introduction for text mode: a closed-set classifier interpreting supplied text representations, rather than a visual evidence ranker. Keep the untrusted-data warning, final closed task schema, independent presence semantics, and exact rank cardinality unchanged.
18
+ 4. Add `createOpenAICompatibleText` beside the existing direct vision wrapper and `createOpenRouterText` beside the OpenRouter vision wrapper. Public exports/types are coordinated by A0. Text and vision wrappers share schemas and transport implementation, rather than maintaining a second response parser.
19
+ 5. Keep existing per-part validation intact. The representation layer, rather than this transport, owns normalization, view de-duplication, grid geometry, and the stricter aggregate representation budget. The transport should not infer an image codec or select models.
20
+
21
+ These changes do not depend on new whole-object or segmentation contracts and need no runtime dependency. The old vision code path must produce the same request body for the same input/options.
22
+
23
+ ## Existing limits and integration implications
24
+
25
+ | Boundary | Current limit | Consequence |
26
+ | -------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
27
+ | State parts | 1–64 | Account for codec grammar, metadata, and all views together. |
28
+ | Each state string | 1–64,000 UTF-16 code units | A single 64 KiB ASCII payload may exceed this; split on meaningful complete view boundaries within this limit. |
29
+ | Prepared image parts | At most 9 | A library policy, not the provider's universal maximum. Text mode allows zero. |
30
+ | Decision questions | 1–16 | Four extent questions fit in one call. |
31
+ | Choice options | 2–255 | Closed interval IDs and `unknown` fit. |
32
+ | Request body | At most 32 MiB | Includes task schema, escaping, headers excluded; text representation has its own tighter 64 KiB budget. |
33
+ | Response body | At most 1 MiB | Bounded reading also applies to error responses. |
34
+ | Ranking size | Exactly 1 or 4, capped at option count | Whole-object sides need rank 1; spatial beam needs rank 4. |
35
+
36
+ The 64 KiB representation budget is a UTF-8 byte budget and includes all textual image views, not arbitrary task text. It must not be confused with the current 64,000-code-unit individual string schema. No byte truncation should attempt to repair an over-budget view: reduce and declare its resolution before serialization, or return a representation-limit result.
37
+
38
+ ## Required offline regressions
39
+
40
+ - A real local HTTP server receives text parts only from the new direct adapter, without any key or OpenRouter route.
41
+ - Both new factories reject a valid prepared `image_url` part before fetch; test images appearing at the beginning, middle, and end of mixed state.
42
+ - Malformed, proxy, and accessor inputs remain rejected before transport. Raw image-like strings stay ordinary untrusted strings, not decoded images.
43
+ - Input mutation after invocation cannot change the emitted payload. A rejected image cannot be replaced with a text-only request through silent filtering.
44
+ - Text factory preserves explicit model/provider routing and all response-format options, body/response caps, cancellation, abort cleanup, route identity checks, closed ID/cardinality checks, and unknown cost semantics.
45
+ - Existing vision payload snapshots and behavior remain unchanged. Rank-only output still produces `probabilities: null` through the classifier.
46
+ - The textual codec grammar precedes its encoded views, and the final `CLASSIFICATION_TASK` stays last. No ground truth or model-specific expected answer enters either part.
47
+ - Experimental request preparation has a negative assertion over the serialized payload: no `image_url`, `input_image`, binary/base64 media, or media URL part. This assertion belongs to tests/benchmark capture, not a heuristic transport scan of all ordinary strings.
48
+
49
+ ## Public metadata availability check
50
+
51
+ The following requests were unauthenticated metadata reads, with no inference dispatch and no key access. Retrieved at 2026-10-20 07:20 UTC:
52
+
53
+ - `GET https://openrouter.ai/api/v1/models?output_modalities=decisions&input_modalities=image` returned `openai/gpt-6-luna-decisions`, input text/image, output decisions, context 1,050,000. Catalog pricing was $0.10 per million prompt tokens and zero completion charge. This does not verify its current inference route or success rate.
54
+ - `GET https://openrouter.ai/api/v1/models` returned `deepseek/deepseek-v4.1-flash`, input text/image, output text. The benchmark may intentionally send text only even when the selected model also supports images; report payload modality separately from model capability.
55
+ - `GET https://openrouter.ai/api/v1/models/deepseek/deepseek-v4.1-flash/endpoints` contained the exact `together` tag, display name `Together`, status `0`, and supported parameters including `response_format`, `structured_outputs`, and `reasoning_effort`. That endpoint advertised $0.30 per million prompt tokens and $1.20 per million completion tokens. The cheaper model-level aggregate price belongs to other endpoints and must not be used to price the pinned Together route.
56
+
57
+ Default model catalog queries do not list all Decisions output models. An omitted Luna entry in the unfiltered text-output list is not evidence of removal. The guessed `/api/alpha/decisions/models` path returned 404 and must not be used as a catalog.
58
+
59
+ ## Primary references
60
+
61
+ - [OpenRouter provider routing](https://openrouter.ai/docs/guides/routing/provider-selection): explicit provider allow-list, disabling fallback, and parameter support.
62
+ - [OpenRouter structured outputs](https://openrouter.ai/docs/guides/features/structured-outputs): strict JSON schema support is endpoint-specific; `require_parameters` is required when relying on it.
63
+ - [OpenRouter multimodal Decisions](https://openrouter.ai/docs/guides/community/multimodal-decisions): image parts go directly in `state`; text items are strings; filter the Models API by output modality.
64
+ - [OpenRouter API overview](https://openrouter.ai/docs/api_reference/overview): Chat Completions text content and response envelopes.
65
+
66
+ The official documentation allows considerably more images on Luna than this library's conservative nine-image bound. Raising that bound is unnecessary for this extension. Documentation also lists model-specific truncation behavior for other routes; do not add them as automatic text-encoding fallbacks.
@@ -0,0 +1,69 @@
1
+ # Recorded model results
2
+
3
+ This report is historical evidence for the optional Jev integration. Current native Luna Decisions and ordinary vision model comparisons are in [tested models](vision-results.md); these figures do not qualify a different backend.
4
+
5
+ These are measured outcomes, including mistakes and failures. They are not a claim that the wrapper improves Jev's classification accuracy, that photographic accuracy transfers to games, or that a selected cell is a segmented object.
6
+
7
+ ## Full corpus: live-v1
8
+
9
+ The run completed on 2026-10-17 UTC with the source hashes in the [manifest](evidence/live-v1-manifest.json). It used the original strict probability-sum validator. The [complete report](evidence/live-v1-report.json) retains every sample, split, error, timing and joined ground-truth result. Corpus preparation and attribution are described in [benchmarks](benchmarks.md).
10
+
11
+ The corpus contains 60 licensed photographs (20 dev / 40 heldout; 25 requested object classes) and 30 authored text-intent fixtures (10 dev / 20 heldout). The text fixtures are not real customer conversations. Public heldout can overlap provider training; it was only held out from local development. There was no independent human re-annotation or perceptual duplicate audit.
12
+
13
+ | Classification | Library | Independent native Jev Choice |
14
+ | --------------------- | --------------- | ----------------------------- |
15
+ | Photographs correct | 55/60 (91.67%) | 55/60 (91.67%) |
16
+ | Photograph macro-F1 | 0.84367 | 0.84367 |
17
+ | Text fixtures correct | 30/30 | 30/30 |
18
+ | Photograph p50 / p95 | 2.835 / 4.287 s | 2.615 / 3.804 s |
19
+ | Text p50 / p95 | 0.283 / 0.323 s | 0.293 / 0.333 s |
20
+
21
+ Photo presence classification: TP 48, FN 2, TN 7, FP 3. Dev 18/20, heldout 37/40. Text dev 10/10, heldout 20/20. The chosen class agreed across all 90 library/native pairs. The native baseline makes a separate provider call with an identical request; it is not a copied answer. Values can vary between calls.
22
+
23
+ ## Locator and stage trade-off
24
+
25
+ A positive hit means the **selected cell's center** lies in at least one annotated bounding box. This evaluates an area hypothesis, not the object's center or segmentation; a source bounding box can include background. Multiple matching instances are allowed. Prefix results reuse the same stage answers and are correlated ablations without the final candidate check.
26
+
27
+ | Metric | First-stage prefix | Two-stage prefix | Full three stages |
28
+ | --------------------------------------- | ------------------ | ----------------- | ----------------- |
29
+ | Successful, including correct negatives | 46/60 | 31/60 | 27/60 |
30
+ | Hits over all positive photos | 39/50 | 24/50 | 20/50 |
31
+ | Protocol failures | 1 | 22 | 23 |
32
+ | Unknown outcomes | 0 | 0 | 7 |
33
+ | False coordinates on absent targets | 3/10 | 2/10 | 1/10 |
34
+ | p50 / p95 | 5.189 / 7.437 s | 11.654 / 18.930 s | 13.642 / 22.229 s |
35
+ | Median selected image-area fraction | 6.25% | 0.418% | 0.513% |
36
+
37
+ For the full locator, 20 of 21 returned regions on positive photos hit a reference box. That conditional 95.24% excludes failures and abstentions; the result over **all 50 positives is 20/50**. Do not market the conditional percentage as overall accuracy. A larger first-stage region can achieve easier containment and does not offer the same spatial granularity.
38
+
39
+ | Stratum (10 photos each) | Classification correct | First stage success | Two stages | Three stages |
40
+ | ------------------------ | ---------------------- | ------------------- | ---------- | ------------ |
41
+ | Baseline | 9 | 10 | 4 | 2 |
42
+ | Repeated instances | 9 | 9 | 6 | 5 |
43
+ | Edge truncation | 10 | 9 | 8 | 7 |
44
+ | Absent target | 7 | 7 | 7 | 7 |
45
+ | Occlusion | 10 | 8 | 4 | 3 |
46
+ | Small target | 10 | 3 | 2 | 3 |
47
+
48
+ ## Protocol correction and final smoke
49
+
50
+ All 321 full-run HTTP responses were 200, with no timeouts. The strict adapter rejected 23 answers (`INVALID_RESPONSE`: stage 1 = 1, stage 2 = 21, stage 3 = 1). Their original raw rejected bodies were not saved. Therefore the cause of every rejection cannot be established retrospectively.
51
+
52
+ Two later diagnostic calls on saved request inputs produced one 153-option response whose 0.01-rounded values sum to 0.99, and one valid five-option response. They are new independent responses, not recovered original failures. The final adapter preserves raw scores and accepts only explicitly annotated quantization whose half-step intervals admit unit probability mass. No prompts, crops, rankings or geometry were changed. The exact 153-option response is covered by a regression. See [API](api.md) and [probe evidence](evidence/protocol-probes.json).
53
+
54
+ The final corrected runtime then completed a separate [smoke run](evidence/live-release-smoke-report.json): 2 dev photos + 2 dev texts, 14 HTTP calls, zero protocol failures. Photo classification was 1/2 for both library/native, texts 2/2 for both; localization returned one valid box hit and one `unknown`. This checks the corrected integration, **not a new full-corpus accuracy estimate**. The old failures remain unchanged. A full final-version quality benchmark remains future work within an explicitly funded run.
55
+
56
+ ## Calls, route and cost
57
+
58
+ | Run | HTTP calls | Known reported cost | Calls with unknown cost |
59
+ | ----------------- | ---------- | ------------------- | ----------------------- |
60
+ | Full live-v1 | 321 | $0.073546662 | 23 |
61
+ | Diagnostic probes | 2 | $0.001420734 | 0 |
62
+ | Final smoke | 14 | $0.004080510 | 0 |
63
+ | Total | 337 | $0.079047906 | 23 |
64
+
65
+ Adding the local $0.02 reservation for each unknown-cost call gives accounted exposure **$0.539047906**, not the actual final provider bill. The aggregate remains within the authorized 360-call / $1 diagnostic envelope. Local reservations do not enforce an account-wide spending cap.
66
+
67
+ The 298 accepted full-run responses and all 14 smoke responses report `typesafe/jev-1.14-20261014` / TypeSafe; the adapter requests `typesafe/jev-1.14`, only TypeSafe, without fallback/retry. The two probes also used the fixed route. Missing metadata is never silently assumed to prove routing or zero cost. Pricing was checked against the [dated primary-source snapshot](evidence/jev-pricing-2026-10-18.json).
68
+
69
+ Latencies include image preparation and benchmark artifact writes; measurements of the HTTP response headers alone are stored separately. They are not a service-level guarantee or evidence of sub-second localization.
@@ -0,0 +1,162 @@
1
+ # Region-seeded masks and extraction (0.2)
2
+
3
+ The [accepted plan](0.2.0-plan.md) and [acceptance status](acceptance.md) distinguish implementation, offline checks, live quality and platform qualification. The frozen caller recipe passed admission with only 8/60 complete positive object boxes; 19/30 mask references had no prediction. Configure and test the model and segmenter for your own data. No text-image encoder qualified.
4
+
5
+ The library does not select or connect a model. Supply a `DecisionPort` to `createClassifier`, either by implementing the port or explicitly constructing a provider adapter. The Luna examples below are reproducible integration recipes, not defaults or a claim that one model is always more accurate; stronger model capability does not guarantee monotonic accuracy gains. Optional local segmenters and proposal generators are configured separately, and their runtime packages and model assets remain the caller's responsibility.
6
+
7
+ ## Choose the operation
8
+
9
+ | Operation | Result | Model requests |
10
+ | ------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------- |
11
+ | `classify` | One supplied class | One |
12
+ | `locate` (default / `mode: 'region'`) | A grid cell that may contain an object fragment | Up to three |
13
+ | `locate` with `mode: 'whole-object'` and `segmentation` | Visible bounds and center derived from a mask | Up to five, plus local segmentation/correction |
14
+ | `extract` with `segmentation` | Mask-derived bounds, center, transparent PNG, cropped mask and source offset | Up to five, plus local segmentation/correction |
15
+
16
+ The primary object workflow is the unchanged region locator followed by an explicitly configured segmenter. Segmentation receives the locator's seed prompt on the full EXIF-oriented source image; it does not receive a seed crop or treat the seed as an object box. Bounds and center come from actual foreground mask pixels. After the initial mask, a closed decision checks the original image with the actual mask box and original seed anchor: `complete`, `needs-expansion`, or `unknown`. It reuses the caller-supplied `DecisionPort`. An incomplete box permits one actual enclosing-mask correction and one final check; there is no separate extent search or generated model geometry. Default `locate` behavior remains compatible.
17
+
18
+ ## Primary workflow: region seed to mask-derived result
19
+
20
+ Configure the caller's `DecisionPort` and local segmenter, then call `extract`:
21
+
22
+ ```ts
23
+ const client = createClassifier({ decision, segmentation: segmenter })
24
+ try {
25
+ const result = await client.extract({ image, target: 'the backpack' })
26
+ if (result.status === 'extracted') {
27
+ console.log(result.region, result.center, result.offset)
28
+ // result.png is transparent; result.mask contains the matching cropped binary mask.
29
+ } else {
30
+ console.log(result.status, result.reason)
31
+ }
32
+ } finally {
33
+ try {
34
+ await client.dispose()
35
+ } finally {
36
+ await segmenter.dispose()
37
+ }
38
+ }
39
+ ```
40
+
41
+ `result.region` is the mask-derived half-open rectangle in source coordinates. `result.center` is its pixel center, and `result.offset` maps the cropped mask and PNG back to the source. Empty or seed-ungrounded masks return `unknown/segmentation-uncertain`; a locator rectangle is never substituted. The same unknown is returned when containment cannot be confirmed, expansion is unavailable, or the corrected mask still fails its check. Successful primary results use `method: 'region-checked-segmentation-v1'`. `verification.checks` retains the one or two closed decisions with raw scores/ranks and actual request metadata; `verification.expansion` reports `not-needed`, `unsupported`, `no-enclosing-mask`, `rejected-mask`, or `expanded`. Verification decision costs are included in `location.metadata`. A confirmed box is separate from pixel-perfect mask quality. Native and resource errors remain typed failures. `locate({ mode: 'whole-object' })` uses the same mask path when a segmenter is explicitly configured.
42
+
43
+ The decision port, optional custom `segmentationBoxCheck`, and segmenter remain caller-owned. The classifier cancels and joins its operations but does not dispose an injected segmenter. Dispose both resources when the application owns both. Model/provider selection is also explicit; examples below show one caller-configured route, not a library default or accuracy guarantee.
44
+
45
+ ### Optional caller presence guard
46
+
47
+ The tested v3 caller composition first classifies the target as `present` or `absent`, then calls `extract` only for `present`. This is caller logic: direct `extract` uses up to three region requests plus one or two containment checks; the guard adds one classification request. The [complete heldout comparison](evidence/v02/region-seeded-heldout-v3/README.md) preserves all errors and unknown outputs. Earlier v2 results predate containment checks and remain historical. A classification error remains an error; it must not be converted to absence. Keep both calls under one caller-owned absolute deadline and abort signal.
48
+
49
+ ```ts
50
+ // image, target and signal are owned by this application's operation.
51
+ const presence = await client.classify({
52
+ input: { image, text: target },
53
+ classes: [
54
+ { id: 'present', description: 'The target is visible in this image.' },
55
+ { id: 'absent', description: 'The target is not visible in this image.' },
56
+ ],
57
+ signal,
58
+ })
59
+ if (presence.choice === 'present') {
60
+ const result = await client.extract({ image, target, signal })
61
+ // Handle the actual result; do not substitute the seed for a failed mask.
62
+ console.log(result.status)
63
+ }
64
+ ```
65
+
66
+ This illustrates caller composition rather than a new package default. Exact benchmark tasks, prompts, timeouts, route and preserved failures are pinned in the historical [v2 development evidence](evidence/v02/region-seeded-dev-v2/README.md) and current [checked-flow v3 comparison](evidence/v02/region-seeded-dev-v3-control-r2/README.md). The latter records 6/30 positive whole-object box matches and 1/7 passing exact-canvas masks; it does not guarantee accurate cutouts for every object. Changing the caller's model, segmenter or prompt requires its own quality measurement.
67
+
68
+ A baseline Linux CPU wiring smoke with the pinned MobileSAM assets used a synthetic 192×128 image. A colored rectangle produced a 2,800-pixel mask with bounds `[70, 34, 120, 90]`; an all-transparent input produced a full-size empty mask. Three child starts matched three closes. This verifies adapter wiring only, not photo accuracy.
69
+
70
+ ## Legacy interval and proposal strategies
71
+
72
+ The earlier boundary-interval `whole-object` strategy and `objectProposals` mask-choice strategy remain optional legacy/research paths. They are not required by the primary seed-region segmentation workflow and have their own model-confirmation steps and historical evidence. The interval strategy asks closed Choices over integer boundaries after the region seed. Each axis has at most sixteen intervals plus `unknown`; up to three passes refine the intervals. It returns interval-derived geometry, not a segmented mask.
73
+
74
+ The optional `objectProposals` adapter computes packed MobileSAM masks from nine seed points, then asks the configured model to select a supplied candidate and confirm its rectangle. Its box checks and mask quality are separate from direct seed-prompt segmentation. Default region and classification operations are unchanged.
75
+
76
+ ## Extract with an explicit local backend
77
+
78
+ Core runtime dependencies remain Sharp and Zod. MobileSAM requires the optional peer:
79
+
80
+ ```sh
81
+ npm install onnxruntime-node@1.23.2
82
+ ```
83
+
84
+ Obtain the exact licensed assets yourself; [pinned sizes, SHA256 and provenance](evidence/v02/segmentation/README.md) are recorded separately. Asset files, optional ONNX Runtime installation and backend availability are caller-owned prerequisites; importing or configuring the package does not fetch model weights. Imports never download models or start workers. CPU is the default provider within this explicitly constructed adapter; `executionProvider: 'dml'` is an opt-in Windows route and fails when unavailable. No CPU/model fallback is attempted.
85
+
86
+ ```ts
87
+ import { readFile, writeFile } from 'node:fs/promises'
88
+ import { createClassifier } from 'zorya-classifier'
89
+ import { createOpenRouterDecisions } from 'zorya-classifier/openrouter'
90
+ import { createMobileSamSegmenter } from 'zorya-classifier/segmentation'
91
+
92
+ const apiKey = process.env.OPENROUTER_API_KEY
93
+ const encoderPath = process.env.MOBILE_SAM_ENCODER
94
+ const decoderPath = process.env.MOBILE_SAM_DECODER
95
+ if (!apiKey || !encoderPath || !decoderPath)
96
+ throw new Error('Configure credentials and asset paths')
97
+ const segmenter = await createMobileSamSegmenter({
98
+ encoderPath,
99
+ decoderPath,
100
+ executionProvider: 'cpu',
101
+ threads: 2,
102
+ })
103
+ const client = createClassifier({
104
+ decision: createOpenRouterDecisions({
105
+ apiKey,
106
+ model: 'openai/gpt-6-luna-decisions',
107
+ provider: 'openai',
108
+ }),
109
+ segmentation: segmenter,
110
+ })
111
+ try {
112
+ const result = await client.extract({
113
+ image: await readFile('photo.jpg'),
114
+ target: 'the backpack',
115
+ })
116
+ if (result.status === 'extracted') {
117
+ await writeFile('backpack.png', result.png, { flag: 'wx' })
118
+ await writeFile('backpack.mask.u8', result.mask.data, { flag: 'wx' })
119
+ console.log(result.region, result.offset, result.mask.width, result.mask.height)
120
+ } else console.log(result.status, result.reason)
121
+ } finally {
122
+ try {
123
+ await client.dispose()
124
+ } finally {
125
+ await segmenter.dispose()
126
+ }
127
+ }
128
+ ```
129
+
130
+ The mask is cropped to its visible bounds, row-major, one byte per pixel (`0` or `1`), with its own width/height and `format: 'binary-u8'`. `offset` maps its origin back to the source. PNG pixels inside the mask preserve source RGBA; pixels outside have zero RGBA. Transparent source pixels cannot substantiate an object. Invalid dimensions, nonbinary values, hard-ROI escape and masks missing the visible seed fail validation. Empty or ungrounded masks return `unknown/segmentation-uncertain`; a rectangle is never substituted for a mask. Protocol, native and resource errors remain typed failures.
131
+
132
+ `createGrabCutSegmenter({ assetPath })` selects the separately supplied pinned OpenCV 4.13.0 JS asset. It does not require ONNX Runtime. This is an explicit alternate algorithm. A custom `SegmentationPort` can integrate other backends with the same validation.
133
+
134
+ The caller owns a segmenter and may share it between clients. `client.dispose()` cancels and joins that client's operations without disposing the segmenter. Each `segment()` promise must remain pending until its own physical work settles, including cancellation. `segmenter.settle()` joins admitted work; `segmenter.dispose()` closes its own resources. Dispose both when the application owns both.
135
+
136
+ Built-in adapters probe the backend on explicit factory calls and run each admitted inference in a fresh owned child. They currently do not reuse sessions: measured inference includes cold child/model startup. One active task and two waiters bound native work. Cancellation retains the slot through child close, with 250 ms grace before owned-child termination; each task has a 10-second native limit inside the client's absolute deadline. Consult measured evidence for latency-sensitive deployment.
137
+
138
+ MobileSAM uses the seed region's center as a positive point on the full source and selects the mask with the greatest finite native quality score, using stable ties. It is a geometric point-prompt model; it does not interpret the target's text. Its raw quality score estimates a mask, not target identity or completeness. In the exposed development set it sometimes selected a part, such as a car's headlight, rather than the whole car. `status: 'extracted'` means that the returned mask and artifacts passed structural/source validation; it is not a semantic correctness guarantee. The [independent quality report](evidence/v02/region-seeded-dev-v2/README.md) measures that distinction. A caller-owned `SegmentationPort` can supply a different or text-guided backend without changing region search or connecting a model inside the library.
139
+
140
+ ## CLI
141
+
142
+ Set explicit model/provider variables as in the [main guide](../README.md). Arguments are validated before native composition or model dispatch.
143
+
144
+ ```sh
145
+ # Optional legacy interval-boundary location without an explicit segmenter.
146
+ zorya-classifier locate photo.jpg 'the backpack' --mode whole-object
147
+ # Primary region-seeded segmentation and cutout flow.
148
+ zorya-classifier extract photo.jpg 'the backpack' --output backpack \
149
+ --backend mobile-sam --encoder /models/encoder.onnx --decoder /models/decoder.onnx
150
+ zorya-classifier extract photo.jpg 'the backpack' --output backpack \
151
+ --backend grabcut --opencv /models/opencv.js
152
+ ```
153
+
154
+ Successful extraction writes `<prefix>.png`, `<prefix>.mask.u8` and `<prefix>.json`. Destinations are reserved exclusively before writing; existing files are preserved. JSON contains dimensions, source geometry, metadata and file paths rather than serialized binary arrays. Output failure removes only destinations created by that operation. Parent directories must exist. SIGINT/SIGTERM cancels work and disposes CLI-owned resources.
155
+
156
+ ## Experimental text-only images
157
+
158
+ The reserved selector is `representation: { type: 'experimental-text', profile: 'text-image-v1' }`. Public composition currently rejects image operations with `UNSUPPORTED` before dispatch because no encoder is qualified. Ordinary text classification remains usable.
159
+
160
+ Research candidates compare normalized luma ASCII, color palette grids, SVG color runs, strict pixel RLE, binary/edge ASCII, and layered ASCII + SVG. No OCR, semantic helper or hidden vision call supplies object facts. Text adapters reject image parts rather than silently dropping them. Complete encoded views and metadata have a 64 KiB UTF-8 budget, allocated before encoding; output is never truncated to fit. Indistinguishable geometry returns a named unknown.
161
+
162
+ Only a candidate that passes development selection and frozen independent heldout qualification may be promoted. Other candidates, bulk images and model weights stay outside npm. A grammar roundtrip or syntactically valid LLM answer alone does not qualify photo localization.