@photivra/engine 1.1.0 → 1.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 (236) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/CITATION.cff +1 -1
  3. package/NOTICE +29 -0
  4. package/README.md +6 -6
  5. package/THIRD_PARTY.md +10 -0
  6. package/dist/core/version.d.ts +1 -1
  7. package/dist/core/version.js +1 -1
  8. package/dist/index.d.ts +6 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +3 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/optics/complex-pupil-psf.d.ts +6 -0
  13. package/dist/optics/complex-pupil-psf.d.ts.map +1 -1
  14. package/dist/optics/complex-pupil-psf.js +10 -7
  15. package/dist/optics/complex-pupil-psf.js.map +1 -1
  16. package/dist/output/native-capture-sdr.d.ts +78 -0
  17. package/dist/output/native-capture-sdr.d.ts.map +1 -0
  18. package/dist/output/native-capture-sdr.js +171 -0
  19. package/dist/output/native-capture-sdr.js.map +1 -0
  20. package/dist/output/print-contrast-reference.d.ts +47 -0
  21. package/dist/output/print-contrast-reference.d.ts.map +1 -0
  22. package/dist/output/print-contrast-reference.js +95 -0
  23. package/dist/output/print-contrast-reference.js.map +1 -0
  24. package/dist/output/print-detail.d.ts +7 -0
  25. package/dist/output/print-detail.d.ts.map +1 -1
  26. package/dist/output/print-detail.js +20 -11
  27. package/dist/output/print-detail.js.map +1 -1
  28. package/dist/output/print-region-statistics.d.ts +92 -0
  29. package/dist/output/print-region-statistics.d.ts.map +1 -0
  30. package/dist/output/print-region-statistics.js +300 -0
  31. package/dist/output/print-region-statistics.js.map +1 -0
  32. package/docs/API_REFERENCE.md +52 -1
  33. package/docs/API_STYLE.md +1 -1
  34. package/docs/ARCHITECTURE.md +1 -1
  35. package/docs/AUTOMATION_COORDINATION.md +1 -1
  36. package/docs/CAPTURE_COLOR.md +1 -1
  37. package/docs/CAPTURE_CORRECTED_SDR.md +1 -1
  38. package/docs/CAPTURE_EXPORT_METADATA.md +1 -1
  39. package/docs/CAPTURE_SDR.md +3 -1
  40. package/docs/DEVELOPERS.md +6 -4
  41. package/docs/DIGITAL_OPTICS_FOUNDATION.md +1 -1
  42. package/docs/ENVIRONMENT_RAW_CAPTURE.md +1 -1
  43. package/docs/EXPORT_ACCEPTANCE.md +1 -1
  44. package/docs/GENERIC_TIER_PRESETS.md +1 -1
  45. package/docs/GEOMETRIC_PREPARATION_REUSE.md +1 -1
  46. package/docs/IMAGE_FORMATION.md +1 -1
  47. package/docs/LINEAR_CAPTURE_ENCODING.md +1 -1
  48. package/docs/MOTION_AND_SIGNAL.md +1 -1
  49. package/docs/NATIVE_CAPTURE_SDR.md +70 -0
  50. package/docs/NATIVE_CAPTURE_SDR_REVIEW.md +37 -0
  51. package/docs/NATIVE_CAPTURE_SDR_VALIDATION.md +34 -0
  52. package/docs/NUMERICAL_CORRECTNESS.md +1 -1
  53. package/docs/PERFORMANCE_BASELINE.md +1 -1
  54. package/docs/PHOTOGRAPHIC_EXPORT.md +1 -1
  55. package/docs/PHYSICS_FOUNDATION.md +1 -1
  56. package/docs/POC_API.md +1 -1
  57. package/docs/POC_PROJECTION_REUSE.md +1 -1
  58. package/docs/PRINT_195_196_REVIEW.md +93 -0
  59. package/docs/PRINT_196_ENGINE_ACCEPTANCE.md +45 -0
  60. package/docs/PRINT_CONTRAST_REFERENCE.md +43 -0
  61. package/docs/PRINT_DETAIL_ASSESSMENT.md +1 -1
  62. package/docs/PRINT_DETAIL_JPEG_EVIDENCE.md +36 -0
  63. package/docs/PRINT_DETAIL_VALIDATION.md +1 -1
  64. package/docs/PRINT_PLANNING.md +3 -1
  65. package/docs/PRINT_REGION_STATISTICS.md +38 -0
  66. package/docs/PROCESSED_OUTPUT.md +1 -1
  67. package/docs/PRODUCTION_COMPOSITION.md +1 -1
  68. package/docs/PRODUCTION_ENVIRONMENT_CAPTURE.md +1 -1
  69. package/docs/PROVENANCE.md +1 -1
  70. package/docs/PSF_FOUNDATION.md +11 -1
  71. package/docs/RAW_FRAME_ENVELOPE.md +1 -1
  72. package/docs/RAW_FRAME_RECONSTRUCTION.md +1 -1
  73. package/docs/RELEASE_1_2_0.md +51 -0
  74. package/docs/SCENE_RADIANCE_AND_ILLUMINATION.md +1 -1
  75. package/docs/SCENE_SENSOR_QUADRATURE.md +1 -1
  76. package/docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md +1 -1
  77. package/docs/SCIENTIFIC_ASSURANCE.md +1 -1
  78. package/docs/SCIENTIFIC_CONFORMANCE.md +1 -1
  79. package/docs/SDR_RENDERING.md +1 -1
  80. package/docs/SENSOR_ENVIRONMENT_QUERY.md +1 -1
  81. package/docs/SENSOR_EQE_LOCAL_EXPOSURE.md +1 -1
  82. package/docs/SENSOR_EQE_TEMPORAL_EXPOSURE.md +1 -1
  83. package/docs/SENSOR_PSF_QUADRATURE.md +1 -1
  84. package/docs/SENSOR_RAW_FRAME.md +1 -1
  85. package/docs/SENSOR_RAW_PRODUCER.md +1 -1
  86. package/docs/SIGNAL_CONFORMANCE.md +1 -1
  87. package/docs/SIMULATED_CAPTURE.md +1 -1
  88. package/docs/STABILIZATION.md +1 -1
  89. package/docs/TEMPORAL_PHOTO_RAW.md +1 -1
  90. package/docs/TIER_ACCEPTANCE.md +1 -1
  91. package/docs/TIER_PRESET_ACCEPTANCE.md +1 -1
  92. package/docs/USAGE.md +3 -1
  93. package/docs/V1_COMPOSITION_MAP.md +1 -1
  94. package/docs/V1_HELPER_REUSE_REVIEW.md +1 -1
  95. package/docs/V1_PERFORMANCE_DISPOSITION.md +1 -1
  96. package/docs/api/camera-equivalent-focal-length.md +1 -1
  97. package/docs/api/camera-field-of-view.md +1 -1
  98. package/docs/api/camera-projected-object-size.md +1 -1
  99. package/docs/api/capture-capture-export-metadata.md +1 -1
  100. package/docs/api/capture-environment-raw-producer.md +1 -1
  101. package/docs/api/capture-focus-control.md +1 -1
  102. package/docs/api/capture-linear-encoding.md +1 -1
  103. package/docs/api/capture-photographic-export.md +1 -1
  104. package/docs/api/capture-raw-frame-reconstruction.md +1 -1
  105. package/docs/api/capture-release-sequence.md +1 -1
  106. package/docs/api/capture-sensor-raw-frame.md +1 -1
  107. package/docs/api/capture-sensor-raw-producer.md +1 -1
  108. package/docs/api/capture-simulated-capture.md +1 -1
  109. package/docs/api/color-capture-color.md +1 -1
  110. package/docs/api/color-white-balance.md +1 -1
  111. package/docs/api/composition-image-formation-plan.md +1 -1
  112. package/docs/api/composition-plan-consumer.md +1 -1
  113. package/docs/api/core-calculation-result.md +1 -1
  114. package/docs/api/core-configuration-error.md +1 -1
  115. package/docs/api/core-image-formation.md +1 -1
  116. package/docs/api/core-scientific-assurance.md +1 -1
  117. package/docs/api/core-spectral-composition.md +1 -1
  118. package/docs/api/core-spectral.md +1 -1
  119. package/docs/api/core-validation.md +1 -1
  120. package/docs/api/core-version.md +2 -2
  121. package/docs/api/equipment-exposure-capabilities.md +1 -1
  122. package/docs/api/equipment-generic-tier-assets.md +1 -1
  123. package/docs/api/equipment-generic-tier-presets.md +1 -1
  124. package/docs/api/equipment-iso-capabilities.md +1 -1
  125. package/docs/api/equipment-metering-capabilities.md +1 -1
  126. package/docs/api/equipment-release-capabilities.md +1 -1
  127. package/docs/api/exports.json +152 -2
  128. package/docs/api/exposure-exposure-duration-control.md +1 -1
  129. package/docs/api/exposure-exposure-mode-resolver.md +1 -1
  130. package/docs/api/exposure-exposure.md +1 -1
  131. package/docs/api/exposure-flash.md +1 -1
  132. package/docs/api/exposure-metering-scene-radiance.md +1 -1
  133. package/docs/api/exposure-metering-target.md +1 -1
  134. package/docs/api/exposure-metering-temporal.md +1 -1
  135. package/docs/api/exposure-metering.md +1 -1
  136. package/docs/api/exposure-program-line.md +1 -1
  137. package/docs/api/motion-camera-rotation.md +1 -1
  138. package/docs/api/motion-capture-rotation-inverse-mapping.md +1 -1
  139. package/docs/api/motion-capture-rotation-temporal-quadrature.md +1 -1
  140. package/docs/api/motion-capture-rotation-trajectory.md +1 -1
  141. package/docs/api/motion-capture-translation-parallax-temporal-quadrature.md +1 -1
  142. package/docs/api/motion-extended-object-projection.md +1 -1
  143. package/docs/api/motion-projected-motion.md +1 -1
  144. package/docs/api/optics-aperture.md +1 -1
  145. package/docs/api/optics-circle-of-confusion.md +1 -1
  146. package/docs/api/optics-complex-pupil-psf.md +7 -1
  147. package/docs/api/optics-depth-of-field.md +1 -1
  148. package/docs/api/optics-diffraction.md +1 -1
  149. package/docs/api/optics-focus-breathing.md +1 -1
  150. package/docs/api/optics-focus-state.md +1 -1
  151. package/docs/api/optics-front-of-lens-filter.md +1 -1
  152. package/docs/api/optics-illumination-vignetting.md +1 -1
  153. package/docs/api/optics-lateral-chromatic-aberration.md +1 -1
  154. package/docs/api/optics-lens-psf-profile.md +1 -1
  155. package/docs/api/optics-polygon-diffraction.md +1 -1
  156. package/docs/api/optics-profile-contract.md +1 -1
  157. package/docs/api/optics-psf-foundation.md +1 -1
  158. package/docs/api/optics-radial-distortion.md +1 -1
  159. package/docs/api/optics-scene-to-sensor-irradiance.md +1 -1
  160. package/docs/api/optics-scene-to-sensor-quadrature.md +1 -1
  161. package/docs/api/optics-sensor-environment-query.md +1 -1
  162. package/docs/api/optics-sensor-psf-quadrature.md +1 -1
  163. package/docs/api/optics-stray-light.md +1 -1
  164. package/docs/api/optics-thin-lens.md +1 -1
  165. package/docs/api/output-capture-corrected-sdr.md +1 -1
  166. package/docs/api/output-capture-geometry.md +1 -1
  167. package/docs/api/output-capture-sdr.md +1 -1
  168. package/docs/api/output-crop.md +1 -1
  169. package/docs/api/output-geometric-transforms.md +1 -1
  170. package/docs/api/output-lens-corrections.md +1 -1
  171. package/docs/api/output-native-capture-sdr.md +150 -0
  172. package/docs/api/output-print-contrast-reference.md +82 -0
  173. package/docs/api/output-print-detail.md +1 -1
  174. package/docs/api/output-print-plan.md +1 -1
  175. package/docs/api/output-print-region-statistics.md +165 -0
  176. package/docs/api/output-sdr-rendering.md +1 -1
  177. package/docs/api/output-subject-framing-crop.md +1 -1
  178. package/docs/api/schema-camera.md +1 -1
  179. package/docs/api/schema-illumination-spectral.md +1 -1
  180. package/docs/api/schema-illumination-temporal.md +1 -1
  181. package/docs/api/schema-illumination.md +1 -1
  182. package/docs/api/schema-scene-radiance-temporal.md +1 -1
  183. package/docs/api/schema-scene-radiance.md +1 -1
  184. package/docs/api/schema-scene.md +1 -1
  185. package/docs/api/schema-validation.md +1 -1
  186. package/docs/api/sensor-accumulated-charge.md +1 -1
  187. package/docs/api/sensor-architecture.md +1 -1
  188. package/docs/api/sensor-camera-saturation-capacity.md +1 -1
  189. package/docs/api/sensor-capture-color-sampling-binding.md +1 -1
  190. package/docs/api/sensor-capture-mode-timing.md +1 -1
  191. package/docs/api/sensor-capture-mode.md +1 -1
  192. package/docs/api/sensor-color-sampling.md +1 -1
  193. package/docs/api/sensor-constant-rate-temporal-integration.md +1 -1
  194. package/docs/api/sensor-dark-current.md +1 -1
  195. package/docs/api/sensor-environment-photo-signal.md +1 -1
  196. package/docs/api/sensor-eqe-electron-rate.md +1 -1
  197. package/docs/api/sensor-eqe-local-exposure.md +1 -1
  198. package/docs/api/sensor-eqe-temporal-exposure.md +1 -1
  199. package/docs/api/sensor-exposure-window.md +1 -1
  200. package/docs/api/sensor-iso-signal-chain.md +1 -1
  201. package/docs/api/sensor-local-exposure-binding.md +1 -1
  202. package/docs/api/sensor-optical-stack.md +1 -1
  203. package/docs/api/sensor-photon-energy.md +1 -1
  204. package/docs/api/sensor-physical-charge-capacity.md +1 -1
  205. package/docs/api/sensor-pixel-pitch.md +1 -1
  206. package/docs/api/sensor-radiometry-readiness.md +1 -1
  207. package/docs/api/sensor-raw-readout.md +1 -1
  208. package/docs/api/sensor-raw-reconstruction.md +1 -1
  209. package/docs/api/sensor-readout-exposure-linkage.md +1 -1
  210. package/docs/api/sensor-readout-timing.md +1 -1
  211. package/docs/api/sensor-response-application-compatibility.md +1 -1
  212. package/docs/api/sensor-response-operating-range.md +1 -1
  213. package/docs/api/sensor-responsivity-photocurrent.md +1 -1
  214. package/docs/api/sensor-sampling-aperture.md +1 -1
  215. package/docs/api/sensor-scene-eqe-temporal-exposure.md +1 -1
  216. package/docs/api/sensor-sensor-geometry.md +1 -1
  217. package/docs/api/sensor-signal-noise.md +1 -1
  218. package/docs/api/sensor-spatial-sample-reduction.md +1 -1
  219. package/docs/api/sensor-spatial-sampling-quadrature.md +1 -1
  220. package/docs/api/sensor-spatio-spectral-reduction.md +1 -1
  221. package/docs/api/sensor-spectral-coverage.md +1 -1
  222. package/docs/api/sensor-spectral-quadrature.md +1 -1
  223. package/docs/api/sensor-spectral-response.md +1 -1
  224. package/docs/api/sensor-temporal-photo-signal.md +1 -1
  225. package/docs/api/simulation-poc-simulation.md +1 -1
  226. package/docs/api/stabilization-camera-shake.md +1 -1
  227. package/docs/api/stabilization-system.md +1 -1
  228. package/docs/licenses/castleCSF-MIT.txt +21 -0
  229. package/docs/validation/native-capture-sdr-darwin-arm64-node26-review.jsonl +4 -0
  230. package/docs/validation/native-capture-sdr-darwin-arm64.jsonl +3 -0
  231. package/docs/validation/print-196-candidate-capabilities.json +28 -0
  232. package/docs/validation/print-196-candidate-evidence.json +356 -0
  233. package/docs/validation/print-196-engine-acceptance.json +81 -0
  234. package/docs/validation/print-detail-capabilities.json +4 -1
  235. package/docs/validation/print-detail-jpeg-evidence.json +116 -0
  236. package/package.json +1 -1
@@ -0,0 +1,70 @@
1
+ # Bounded native capture SDR execution
2
+
3
+ `calculateNativeCaptureSdrPlan` and `createNativeCaptureSdrTask` are additive schema 0.1.0 APIs for authoritative external linear RGB manifests. They do not widen the unchanged `calculateCaptureSdr` or `calculateSdrRendering` reference guards. This is engine-declared tiling, with whole-capture identity and explicit ownership, rather than consumer request splitting.
4
+
5
+ ## Supported domain
6
+
7
+ The selected `SimulatedCapture` plane must already be color-transformed linear sRGB/D65, exact profile version 0.1.0, co-sited RGB with resolved upstream WB or no WB required. All planes in the manifest must use external float32/float64 storage. The provider decodes declared little-endian bytes to the matching native typed numeric array. Precision is preserved; float32 is not promoted to a claim of original float64 fidelity. Reference white, signed values, headroom, capture saturation and source dynamic-range history stay distinct.
8
+
9
+ XYZ, unresolved sensor/virtual RGB, pending WB, HDR, resampling, lens corrections and RAW generation are unsupported here. Complete color/WB through the engine-owned upstream contract before handing over this master. This executor never applies WB twice or generates a source from a preview. The upstream renderer/source still needs qualification; structural metadata is not proof of correct pixels or calibration.
10
+
11
+ Coordinates are absolute top-left, +X right/+Y down in the plane's declared `oriented-active-capture` or `output` raster. Crop and physical orientation are already committed in the capture geometry and represented by the provider's plane. The executor preserves them without re-cropping, rotating, padding image edges or resampling. The output dimensions exactly equal the selected plane. Geometry includes later output intent even when the selected active-capture plane precedes that intent; this call does not execute that later crop.
12
+
13
+ ## Limits and ownership
14
+
15
+ Maximum raster is 24,000,000 pixels, each dimension at most 16,384. Every tile is at most 256 × 32 pixels; right/bottom tiles use their actual remaining dimensions. A tile has RGB row stride in component samples, at least width × 3. Its length must exactly equal stride × height. Padding is ignored. The entire backing buffer, including offset/slack, is bounded to 32,768 components in the declared float precision. SharedArrayBuffer is rejected; provider must not mutate, detach or reuse its returned tile. No tile/output network, persistence or decoder is built into the engine.
16
+
17
+ A task allocates one tightly packed Uint8Array or Uint16Array output only after admission planning. `maximumOutputBytes` must admit the exact width × height × 3 × bytes-per-code. The maximum retained output is 72 MB at 8 bits or 144 MB at 16 bits, decimal units. The input master remains external and is not retained/copied wholesale. At most one tile read is in flight.
18
+
19
+ `maximumScratchPayloadBytes` is 1,441,792 bytes: one maximum float64 provider payload plus six bounded double-array payloads (packed input, parsed input, tone, gamut, transfer, codes). This counts logical numeric payloads, not JS array headers, temporary validation booleans, GC retention, decoder/GPU memory or platform overhead. It is **not** a heap/process/device peak guarantee. Callers must budget output plus measured runtime/decoder/source retention and reject unsupported devices before starting. No full-size floating-point diagnostic arrays are retained.
20
+
21
+ ## Processing and identity
22
+
23
+ Each tile delegates to the unchanged bounded SDR reference. Exposure normalization → selected tone curve → gamut policy → sRGB transfer → nearest-ties-up integer quantization is pointwise, so tiling adds no halo, seam, altered rounding or second camera-science implementation. Counts are aggregated over actual image components; capture saturation is preserved in the plan and remains `not-consumed` in downstream rendering diagnostics. The reference's output encoding and external display-adaptation declaration accompany the output.
24
+
25
+ The frozen plan retains the full parsed capture: creator/schema, source artifact/hash/history, scene/time, seed/noise/model/evidence, exposure/focus/WB, geometry/plane/color/transform identities, new output state ID and complete rendering profile. Every request and response must match capture ID, plane ID, source artifact/hash and exact rectangle. A digest match is an identity declaration, not verification of sample bytes: the provider owns authenticating the external artifact against its whole-file hash before decoding. No partial-file hash is relabeled as a full source hash.
26
+
27
+ ## Task lifecycle
28
+
29
+ `ready → running → completed → transferred` is single-use. `run()` resolves without publishing a buffer. `takeOutput()` transfers the retained buffer once, along with its plan/encoding/diagnostics. Caller owns the returned mutable integer array; an immutable capture manifest does not make output bytes immutable. Dispose/cancel cannot revoke a transferred buffer.
30
+
31
+ Before transfer, cancel/dispose aborts the provider signal, clears/releases any engine output, and prevents publication. `run()` rejects after a pending read/yield settles; providers must honor abort and release their resources. A non-cooperative pending callback cannot be forcibly stopped by this API. Caller must await settlement before reclaiming shared provider resources or launching replacement work on them. Failed tasks release partial output and abort the provider signal. A fresh admitted task is the recovery path; no automatic retry/fallback exists.
32
+
33
+ The provider's required `yieldControl(signal)` must yield to the host event loop between tiles (for example an abort-aware timer, scheduler or worker handoff). A resolved promise alone does not let browser input/timer cancellation run. Host scheduling is external to the scientific package. Check current application capture identity before transferring/installing a completed output; a disposed older task cannot publish late.
34
+
35
+ ## Acceptance and release
36
+
37
+ `test/native-capture-sdr.test.ts` compares the unchanged capture reference across tile edges, row padding, 8/16-bit encoding, upstream WB and all four committed orientations/off-center crops. It checks invalid/stale/oversized domains, finite image data, float precision, pending-read cancellation, between-tile cancellation, disposal, ownership transfer and recovery, plus independently predicted pixels in a 1.2 MP synthetic raster.
38
+
39
+ See [the validation record](NATIVE_CAPTURE_SDR_VALIDATION.md) for measured host-specific evidence and [the technical review](NATIVE_CAPTURE_SDR_REVIEW.md) for the remaining human/source certification gates. Run `node --expose-gc scripts/benchmark-native-capture-sdr.mjs` after build for deterministic 6 MP/24 MP timing and sampled process memory at both 8 and 16 bits. Measurements are host-specific and use owned analytic samples, not licensed photographs or calibration. The packed example below runs through the real root package during consumer acceptance.
40
+
41
+ ```ts
42
+ import { createSimulatedCapture, createNativeCaptureSdrTask, LINEAR_CAPTURE_RGB_PROFILE, resolveCaptureColorModel } from "@photivra/engine";
43
+ const capture = createSimulatedCapture({
44
+ captureId: "native-example", sceneStateId: "analytic-scene", sceneTimeSeconds: 0,
45
+ geometry: { imagingArea: { widthMm: 36, heightMm: 24 }, nativeRaster: { pixelWidth: 2, pixelHeight: 1 }, orientation: "landscape" },
46
+ exposure: { focalLengthMm: 50, aperture: 4, shutterSeconds: .01, iso: 100 }, focus: { kind: "infinity" },
47
+ noise: { seedUint32: 0, realizationId: "none", model: { id: "analytic-noise-zero", version: "1" } },
48
+ source: { kind: "color-transformed-linear-master", artifactId: "analytic-source", sha256: "a".repeat(64), dynamicRangeHistory: "no-loss-declared" },
49
+ whiteBalanceIntent: null, adoptedWhiteXyz: null,
50
+ models: [{ profile: LINEAR_CAPTURE_RGB_PROFILE, scientificStatus: "calculated", publicEvidenceIds: ["photivra:analytic-example"] }],
51
+ planes: [{ id: "rgb", imageStateId: "linear-state", imageState: "color-transformed-linear-rgb", rasterBinding: "oriented-active-capture",
52
+ pixelWidth: 2, pixelHeight: 1, channelIds: ["red", "green", "blue"], colorProfile: LINEAR_CAPTURE_RGB_PROFILE,
53
+ encodingReferenceWhiteXyz: resolveCaptureColorModel().referenceWhiteXyz, referenceWhiteValue: 1, whiteBalanceApplication: "not-applicable",
54
+ captureSaturation: { kind: "not-modeled" }, appliedTransforms: [{ kind: "linear-color", profile: LINEAR_CAPTURE_RGB_PROFILE }],
55
+ storage: { kind: "external-float64", byteOrder: "little-endian", artifactId: "analytic-rgb", sha256: "b".repeat(64), sampleCount: 6 } }]
56
+ }).value;
57
+ // Digests here are synthetic identity placeholders, not verified artifacts.
58
+ const task = createNativeCaptureSdrTask({ capture, sourcePlaneId: "rgb", outputImageStateId: "sdr-state", maximumOutputBytes: 6,
59
+ profile: { schemaVersion: "0.1.0", profileId: "neutral", profileVersion: "1", renderingExposureEv: 0, toneCurve: "identity",
60
+ gamutHandling: "clip-components", outputDynamicRange: "sdr", transferFunction: "srgb", bitDepth: 8, rounding: "nearest-ties-up", dither: "none" }
61
+ }, {
62
+ async readTile(request) { return { ...request, rowStrideSamples: 6, samples: new Float64Array([0, .5, 1, 1, .5, 0]) }; },
63
+ async yieldControl() { await new Promise<void>(resolve => setTimeout(resolve, 0)); }
64
+ });
65
+ await task.run();
66
+ const output = task.takeOutput();
67
+ if (output.integerSamples.join(",") !== "0,188,255,255,188,0") throw new Error("Native SDR example failed");
68
+ ```
69
+
70
+ Human review, merge, version/tag and npm publication are separate release steps. Consumer activation requires the published reviewed contract, a qualified native producer and measured device budgets. This API does not activate a production plan or qualify app fixtures, Print/JPEG delivery, GPU rendering or devices.
@@ -0,0 +1,37 @@
1
+ # Native capture SDR candidate review
2
+
3
+ Technical review date: 2026-10-03. Initial PR #216 head: `1bfdb87c6111299dda4649b03d787e6aff60cf15`; base: `a57bdecd73e1b64ab404415ae95494423756286a`. This record and its follow-up tests are AI-assisted draft material. They support, but do not supply, the substantive human review required by [repository instructions](../AGENTS.md) and [provenance policy](PROVENANCE.md#ai-assisted-work).
4
+
5
+ ## Scientific and execution assessment
6
+
7
+ The new executor calls the existing `calculateSdrRendering` for every tile. Its supported exposure normalization, tone curve, gamut policy, transfer and quantization are component-local; no operation needs neighboring pixels or full-frame statistics. Consequently a tile partition preserves the reference arithmetic. The reference implementation and its 262,144-component guard are unchanged. New parity tests compare every integer component and aggregate diagnostics across 256-column/32-row boundaries using both declared float precisions, both bit depths, both tone curves and both gamut policies. Float32 comparisons use the actual float32-rounded source values; they do not assert float64 fidelity. Independent endpoint/tie and megapixel-coordinate tests supplement shared-implementation parity.
8
+
9
+ The source parser enforces RGB channel order, plane dimensions/binding, transform history, external layout, finite positive reference white and capture identities. Planning adds the exact linear-sRGB/D65 profile/reference white, completed WB state, fresh output state, representable rendering scale, raster caps and output admission. A valid capture containing pending WB intent is deliberately rejected. Four oriented off-center active-capture cases now compare actual reference pixels as well as retained geometry. Later output crop intent stays in the capture; this API does not execute that crop on an active-capture plane.
10
+
11
+ The [ICC sRGB registry](https://registry.color.org/rgb-registry/srgb), checked on the review date, supports the unchanged transfer constants, primary/white coordinates and 80 cd/m² encoding reference. These are mathematical/encoding facts, not a calibrated camera, perceptual gamut mapping or a display measurement. Exposure is post-capture rendering scale; positive per-channel Reinhard can alter chromaticity. Capture saturation, noise, source range history and physical exposure are retained separately from output clipping. No new physical equation, WB estimator, serializer, correction/resampler or production stage is introduced.
12
+
13
+ ## Source and resource assessment
14
+
15
+ The change introduces no runtime dependency or copied third-party image, profile binary, calibration dataset or implementation. The benchmark generates a coordinate ramp directly into bounded tiles. Its source SHA declarations are explicitly synthetic placeholders. The ICC reference is used to check numerical facts; no reference prose/code/data is incorporated by this review. These observations do not certify original authorship, rights to distribute or absence of patent claims. Contributor review and DCO remain required.
16
+
17
+ Admission precedes retained output allocation and tile acquisition. Provider backing storage is bounded, not just its visible view. Precision/rectangle/source identifiers and exact stride length are checked; padding is ignored and nonfinite image values fail. SharedArrayBuffer rejection now has a regression. Logical scratch is provider storage plus packed input, parser copy and four reference output arrays: `32768 × 8 + 256 × 32 × 3 × 8 × 6 = 1,441,792` bytes. JS allocation/GC overhead and provider/device memory are excluded. Retained output limits are 72 MB at 8 bits and 144 MB at 16 bits.
18
+
19
+ The task keeps partial output private, clears it on failure/cancel/dispose, and transfers it once. Activity is checked after both acquisition and host yield. Added tests cover disposal while a yield is pending, late settlement, and real timer cancellation. A provider that ignores abort can still delay settlement; caller resource reuse requires draining the pending run. Host scheduling, artifact authentication and source/device admission remain caller responsibilities. Identity declarations do not authenticate supplied samples.
20
+
21
+ ## Compatibility and release assessment
22
+
23
+ Package, lock root, citation and engine API are aligned at 1.2.0. Schema, model, POC and plan identities remain independent. The runtime diff adds a root module/export and version increment; it does not alter existing rendering equations or API contracts. Archived JPEG fixtures, manifest bytes/hashes and independent decoder evidence are unchanged. Golden replay uses the recorded creator, while a separate current-creator regression checks current exports and identical integer pixels.
24
+
25
+ The follow-up corrects 49 current release-context headers to 1.2.0 and links them to the current release procedure. Historical introduction/measurement values are retained. The additional 24 MP/16-bit benchmark measures the maximum retained code buffer; see [validation evidence](NATIVE_CAPTURE_SDR_VALIDATION.md). No universal performance threshold follows from those measurements.
26
+
27
+ Full local check and coverage passed with 1,739 tests on Node 26.8.1. Coverage: statements 91.94%, branches 88.36%, functions 99.62%, lines 91.89%. Build, generated reference/docs, packed typed consumers, package surface and image-formation benchmark passed. Local HTTP tests required port access outside the sandbox; package dry-run used a writable temporary npm cache. The original head passed all four Node CI jobs. Follow-up-head CI must also pass before merge. Repository search found no other open engine PR requiring version reconciliation. Public npm lists 1.1.0 as its newest version and no 1.2.0; the remote `v1.2.0` tag is absent as of this review.
28
+
29
+ ## Remaining owner gates
30
+
31
+ - Substantive human scientific/source review of the final diff, supported domains, provider obligations and evidence. No human review submission was present during the initial inspection.
32
+ - Contribution-specific DCO certification. Neither original PR commit contains `Signed-off-by`; this AI-assisted follow-up does not assert the contributor's certification. Resolve the complete candidate's certification before inclusion, without fabricating or silently rewriting sign-offs.
33
+ - Green supported Node CI at the final reviewed head, then mark ready and merge through repository protections.
34
+ - Verify final-main CI/tree, main/tag protections and npm trusted-publishing configuration before separately approved tagging/publication. Repository workflow checks those release prerequisites; this review does not verify account-side configuration.
35
+ - Keep #215 publication acceptance and downstream producer/device activation pending until the reviewed distribution exists and their separate evidence is supplied.
36
+
37
+ No merge, tag or publication is authorized by this review record. Follow [the release procedure](RELEASE_1_2_0.md) after the required owner gates.
@@ -0,0 +1,34 @@
1
+ # Native capture SDR validation
2
+
3
+ This is owned synthetic mathematical/resource evidence for schema 0.1.0. It is not device/backend qualification, calibrated camera accuracy, source artifact authentication or human review. Public contract and limitations are in [bounded native SDR](NATIVE_CAPTURE_SDR.md).
4
+
5
+ On 2026-10-03, Node 24.19.0 on darwin/arm64, the repository benchmark produced these sampled values. It yields with setImmediate and evaluates an analytic RGB ramp directly into bounded float64 tiles, so it does not allocate a full-size linear source. Source/digest declarations are synthetic placeholders. Baseline process memory is sampled before each raster; GC runs between cases but does not necessarily return resident memory to the OS. These are sequential runs in one process, not clean-start comparisons.
6
+
7
+ | Raster | Codes | Elapsed | Output payload | Largest provider tile | Sampled peak RSS | Sampled peak heap |
8
+ | --- | --- | --- | --- | --- | --- | --- |
9
+ | 3000 × 2000 | 8-bit | 2.310 s | 18.0 MB | 196,608 bytes | 229.49 MB | 84.28 MB |
10
+ | 6000 × 4000 | 8-bit | 9.120 s | 72.0 MB | 196,608 bytes | 317.54 MB | 93.44 MB |
11
+ | 3000 × 2000 | 16-bit | 2.335 s | 36.0 MB | 196,608 bytes | 312.49 MB | 83.21 MB |
12
+
13
+ Raw measurements, baseline values and output hashes are retained in [the machine-readable record](validation/native-capture-sdr-darwin-arm64.jsonl). Earlier development-candidate runs produced the same 8/16-bit output hashes; the retained record is from the aligned 1.2.0 candidate. The 16-bit hash describes typed-array backing bytes in this host's endian order, not a portable serialized format. No peak-allocation guarantee or CPU/device threshold is inferred from sampling. The 1,441,792-byte logical tile scratch bound excludes JS object/array/GC overhead; the measurements visibly exceed it. Provider/master/GPU/encoder retained costs remain external caller obligations.
14
+
15
+ Regression acceptance compares exact integer pixels, encoding and aggregate clipping diagnostics against the unchanged reference for 259 × 33 rasters crossing all tile boundaries, at 8/16 bits. Additional tests cover upstream engine-resolved WB, all four oriented off-center capture geometries, ignored stride padding, float32/float64, Reinhard, independent sRGB rounding/tie endpoints, 1.2 MP global pixel coordinates, rejected source/color/state/resource inputs, stale rectangles/identities, oversized backing buffers and nonfinite image samples. Lifecycle tests cover pending-read and between-tile aborts, late completion, explicit output transfer, failed host yield, cancellation/disposal of ready/completed tasks, immutable setup/callback commitments and fresh-task recovery.
16
+
17
+ Initial candidate validation: 1,735 tests passed under full coverage; statements 91.94%, branches 88.36%, functions 99.62%, lines 91.89%. Static/security/license/SPDX/identity/browser gates, build, generated documentation and packed consumer acceptance passed. The packed acceptance executes the new typed root-import example independently of the source checkout. Package dry-run passed with root exports only. CI repeats standard acceptance on Node 22.13/22/24/26 and the native-raster benchmark on Node 24.
18
+
19
+ ## Technical review follow-up
20
+
21
+ The [review record](NATIVE_CAPTURE_SDR_REVIEW.md) documents scientific/source/execution assessment and outstanding human/DCO gates. The follow-up adds exact float32/float64 parity across both tone/gamut policies and code depths, reference pixels for all four off-center orientations, valid-container pending WB rejection, shared backing-buffer rejection, pending-yield disposal and actual timer cancellation. Full local checks and coverage passed with 1,739 tests on Node 26.8.1; the coverage percentages above are unchanged.
22
+
23
+ On 2026-10-03, Node 26.8.1 on the same darwin/arm64 host, a sequential benchmark run after the test/consumer checks completed produced:
24
+
25
+ | Raster | Codes | Elapsed | Output payload | Largest provider tile | Sampled peak RSS | Sampled peak heap |
26
+ | --- | --- | --- | --- | --- | --- | --- |
27
+ | 3000 × 2000 | 8-bit | 2.346 s | 18.0 MB | 196,608 bytes | 190.64 MB | 90.03 MB |
28
+ | 6000 × 4000 | 8-bit | 9.114 s | 72.0 MB | 196,608 bytes | 258.82 MB | 80.96 MB |
29
+ | 3000 × 2000 | 16-bit | 2.294 s | 36.0 MB | 196,608 bytes | 280.15 MB | 93.14 MB |
30
+ | 6000 × 4000 | 16-bit | 9.167 s | 144.0 MB | 196,608 bytes | 412.14 MB | 80.92 MB |
31
+
32
+ The [follow-up machine-readable record](validation/native-capture-sdr-darwin-arm64-node26-review.jsonl) preserves baselines, sampled peaks and hashes. All three earlier raster/code-depth hashes agree with the original Node 24 record. The new maximum 24 MP/16-bit backing-byte hash is `b4ab10fe9f6b8f083c5637561aa2a61fe447774b86504a8551b8cc784c815626`. Its host-endian interpretation and all earlier resource/source qualification limitations apply. Earlier measurements are retained; differences across runtimes/runs do not establish a performance improvement.
33
+
34
+ The package/root candidate identity is 1.2.0, aligned with lock/citation and regenerated references. npm registry verification on 2026-10-03 found 1.1.0 as the latest published version and no 1.2.0 distribution. Follow [the 1.2.0 release procedure](RELEASE_1_2_0.md) after human review to run exact tag/publish gates. No existing published version is overwritten; implementation, human review, merge and publication are separate. #215's publication acceptance remains pending until that reviewed distribution exists. A consumer still requires a qualified authoritative RGB producer and measured device budgets before production activation.
@@ -1,6 +1,6 @@
1
1
  # Numerical Correctness and Physical Units
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  Photivra is a scientific engine. Numerical behavior and physical-unit meaning are public-contract concerns, not implementation details.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Measured-performance baseline: #43 / #45
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  This independent first slice records merged main `83a99a4c1ec525fd1add7cccff134fcee0f5159b`, root API 0.93.0, POC API 0.20.0, in `docs/benchmarks/2026-10-01-main-baseline.json`. No pending capture/output/correction/preset implementation is consumed. It does not close either issue or justify an optimization by itself.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Simulated Sensor RAW DNG / JPEG export
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  Current producer-derived files and external closure gates are recorded in
6
6
  [Export acceptance](EXPORT_ACCEPTANCE.md). The new reproducible generator uses
@@ -1,6 +1,6 @@
1
1
  # Physics Foundation
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  Photivra starts with analytical models that can be independently tested and whose assumptions can be stated explicitly.
6
6
 
package/docs/POC_API.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Local POC Simulation API
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  Photivra includes a minimal Node HTTP transport for proof-of-concept development and integration testing.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Request-local defocus projection reuse: #45
2
2
 
3
- Release context: **package 1.1.0 candidate / root API 1.1.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_1_0.md).
3
+ Release context: **package 1.2.0 candidate / root API 1.2.0**. Subsystem/model versions and dated introduction or measurement records below are independent historical identities; they are not distribution versions. See [developer navigation](DEVELOPERS.md) and [release contract](RELEASE_1_2_0.md).
4
4
 
5
5
  The measured candidate reuses the focus-plane image distance already calculated
6
6
  inside `simulatePocCamera()` for its subject and defocus sweep. It is a small
@@ -0,0 +1,93 @@
1
+ # Print #195 / #196 candidate evidence and release review
2
+
3
+ Historical candidate record, retained without relabeling its original evidence. PR #217 subsequently received owner approval and was merged; see the [current engine acceptance audit](PRINT_196_ENGINE_ACCEPTANCE.md) for approval identity, additional native-capture evidence and engine/app gate ownership.
4
+
5
+ This record accompanies the 1.2.0 candidate. It preserves the full #196 acceptance gate: bounded computational conformance does not close the device/backend, proof UI or natural-image perception obligations of the full new-UI release. Engine publication precedes dependent app integration; app acceptance is not treated as an engine dependency cycle. No tag or distribution is created. Historical 1.1.0 diagnostic ledgers and JPEG artifacts remain unchanged.
6
+
7
+ ## Planning acceptance (#195)
8
+
9
+ The existing public planner is tested against an independent exhaustive sample-count search for stamp, book, home, gallery, billboard and distant large-sign conditions on one immutable retained source. Heavy off-center crops expose insufficient native sampling. Smaller-size alternatives recover only within the original exact integer aspect family. Zero physical dimensions are rejected and a corrected request recovers. Enlarged delivery dimensions do not create native sampling. These are planning checks, not source-quality claims. See `test/print-plan-acceptance.test.ts` and [the planning contract](PRINT_PLANNING.md).
10
+
11
+ ## New diagnostics and independent references
12
+
13
+ The [linear statistics protocol](PRINT_REGION_STATISTICS.md) separates paired processing changes from independent-repeat temporal sample variance. The [contrast reference](PRINT_CONTRAST_REFERENCE.md) exposes a restricted static neutral D65 Gabor model estimate with explicit luminance and reference-observer conditions. It does not label a photograph visible, sharp or printable.
14
+
15
+ | Experiment | Executed backend | Independent reference | Supported meaning |
16
+ | --- | --- | --- | --- |
17
+ | Registered differences and repeats | New bounded scalar statistics | Exact binary64 rational arithmetic / high precision RMS | Finite arithmetic and sample statistics, not acquisition calibration |
18
+ | PSF/aperture detail | Public local PSF + spatial/spectral quadrature | Sparse complex transfer, midpoint aperture sum and continuous sinc | Owned neutral periodic signal; finite kernels; all orientations; off-center ROIs |
19
+ | Photocharge noise | Public accumulated-charge / seeded realization | Poisson mean and variance-of-sample-variance moments | Independent seeded ideal photocharge, 4 sites, 32–256 repeats; no ADC/read noise |
20
+ | Electronic noise and clipping stages | Public native RAW producer, including dark/photo Poisson, storage capacity, read noise and 12-bit ADC | Exact rational charge-injection stage predictions; compound Poisson/Gaussian moments; deterministic half-code error bound | Owned 2×2 electronic reference; independent repeats at 32–256 counts; signed pre-ADC signal and unsigned code clamp; no source radiometry or device calibration |
21
+ | Source-to-capture handoff | Public production environment capture + native RAW + processed-output path | Independent 80-digit SI radiance-to-photoelectron arithmetic | Owned uniform 540–560 nm band; QE 0.4; transmission 0.85; 8 ms; 2×2 native; four radiance scales; no real source/device calibration |
22
+ | JPEG processing changes | Public SDR/JPEG exporter, archived independent Pillow/libjpeg decode | Exact decoded neutral scalar paired differences | Exact preserved JPEG bytes, orientation, stage and source hashes; no automatic artifact classifier |
23
+ | Subject depth / intentional defocus | Shared thin-lens geometry + public complex-pupil propagation + owned visible-plane provider | Separate finite complex DFT and ray-plane reference | 2/5/10 m overlapping static planes; 5 m focus; f/8,16,32; 500 nm; 9×9 ideal pupil; interior ROIs |
24
+ | Pupil sampling pilot | Public finite complex-pupil propagation with separately varied pupil resolution and padding | Independently factored finite DFT; continuous shifted-pupil overlap integral; analytic focused circular-pupil transfer | 25 cycles/mm; 500 nm; 2/5/10 m; f/8,16,32; final padded 61×61 grid below 0.01 absolute transfer error; no all-frequency or device certificate |
25
+ | Translation motion | Public local exposure timing + translation/parallax nodes + owned periodic plane accumulation | Closed finite geometric transfer and continuous exposure sinc | Constant depth/visibility; 2/5/10 m; camera/subject velocity 0/1 m/s; 20 ms; 2–32 nodes |
26
+ | Changing source visibility | Public production environment capture + native RAW + processed-output path, with owned moving two-plane provider | Exact rational ray/interval occupancy and continuous-exposure visibility fraction | Foreground 2 m / background 10 m; static camera; point optics; 8 ms; native X/Y motion; 2–128 midpoint nodes; no PSF/depth-edge blur or device qualification |
27
+ | Physical proof reference | Owned PDF wrapper around exact archived JPEG streams; existing public Print planner | Exact Fraction physical-unit/ROI reference; separate pypdf graphics-state/DCT inspection; rendered visual inspection | Same retained crop at two enlargements and same-scale q1/q32 comparison; nominal A4 geometry/ruler only; no actual printer/UI/device or perception qualification |
28
+ | Static contrast reference | Restricted castleCSF equation adapter | Independent 80-digit Decimal arithmetic | Numerical model conformance only; no new psychophysics or individual observer calibration |
29
+
30
+ All generator inputs and JSON expected outputs are committed under `test/fixtures/print-detail/`; tests pin reference SHA-256. References never import the engine or derive expected values from its output. Every new scene/provider is owned draft material, not a private app fixture or camera dataset. These test adapters execute the named public backend; they do not qualify an unnamed renderer or device by association.
31
+
32
+ ## Finite-focus propagation correction
33
+
34
+ The depth experiment exposed that the complex-pupil reference used nominal focal length for image sample pitch even when finite focus metadata was present. Model 1.1.0 adds explicit `propagationDistanceMm` and returns the distance/source. Omission preserves all legacy kernel values. The owned principal-plane fixture explicitly passes the shared thin-lens image distance. Real exit-pupil geometry needs separate evidence. No blur-diameter-to-PSF approximation or duplicate camera equation is introduced. See [PSF foundation](PSF_FOUNDATION.md).
35
+
36
+ The new depth test is a finite scalar pupil conformance test. Its 9×9 pupil grid is **not** a continuum convergence certificate. The new independent pilot demonstrates intensity aliasing in that unpadded reference, including absolute transfer errors above 0.14 at f/32. A separately padded 61×61 grid satisfies a candidate 0.01 transfer-error criterion only at the declared 25 cycles/mm frequency and nine depth/aperture combinations; see [the pupil sampling pilot](PSF_FOUNDATION.md). Existing 9×9 outputs are not retrospectively certified. All finite taps for every selected ROI must hit the same visible surface. Depth-edge diffraction/occlusion composition, moving visibility, lens distortion and corrections are unsupported by that experiment. A background explicitly marked intentional defocus never becomes failed source quality.
37
+
38
+ The motion reference checks continuous-exposure convergence and separately composes camera and subject velocities. It does not use an endpoint chord as a PSF, change exposure from readout duration, or authorize one homography across depths. PSF/aperture tests independently check spatial quadrature convergence. Stochastic repeat-count checks use predeclared broad moment bands; random sample estimates need not converge monotonically and these bands are not confidence intervals for a photograph.
39
+
40
+ ### Linear/high-bit electronic readout qualification
41
+
42
+ `test/print-region-readout-backend.test.ts` invokes `simulateSensorRawFrame()` with an owned 2×2 native reference and 12-bit ADC in the existing 16-bit container. Exact deterministic charge-injection experiments independently isolate storage saturation, pre-ADC upper saturation, final digital saturation and rounding without clipping. The Python rational oracle includes threshold contact and half-code ties; successful output at a boundary alone is not interpreted as an unknown clipping mechanism. Backend flags and exact stage values must match the independent declared experiment. Source radiometry stays explicitly unverified.
43
+
44
+ The stochastic experiment uses photo mean 200 electrons, dark mean 8 electrons and read-noise RMS 0 or 2 electrons, with predeclared 32/64/128/256 repeats and independent capture/representation/realization IDs. For unclipped pre-ADC signal, the independent compound variance is `photoMean + darkMean + readRms²`; the fourth central moment is `photoMean + darkMean + 3 variance²`. Those moments determine the broad sample-mean/sample-variance conformance bands. After the 12-bit ADC, each decoded sample's rounding error is bounded by half a code times the declared gain; the RMS change is bounded deterministically without assuming independent uniform quantization noise. All observed upper/lower clipping flags must be false for that unclipped experiment.
45
+
46
+ A separate zero-photo/zero-dark, 8-electron read-noise experiment verifies that negative electronic signal survives the pre-ADC stage. With zero black pedestal, the final unsigned code clamp produces a positive bias consistent with independent rectified-normal mean `sigma/sqrt(2 pi)`. The before/after comparison uses the same immutable capture and noise realization. Changing draws cannot stand in for a processing effect.
47
+
48
+ The scalar diagnostic encoding is an explicit ideal neutral relative signal scaled by electrons per reference unit. It is conditional electronic model conformance, not a calibrated radiance/luminance transform or a claim that charge injection photographed a scene. Spatial texture, CFA color interpretation, real sensor read noise, temporal correlations, actual photo-source transport and display/render clipping remain separately unassessed. The native RAW producer's `upstreamRadiometryVerified: false` is preserved. This extends the public model evidence; it does not close actual capture/device qualification or certify the private app noise fixture.
49
+
50
+ ### Source-to-capture qualification and artifact identity
51
+
52
+ `test/print-region-capture-backend.test.ts` executes the actual public production environment-capture plan, rather than injecting all photocharge directly. An owned uniform-radiance variant of the existing basic reference supplies a constant 540–560 nm spectral band. The independent Decimal SI oracle predicts generated photoelectrons from declared radiance, working f-number, transmission, native geometric aperture, wavelength, QE and duration at four radiance scales. The plan executes 32 frozen provider queries, binds actual RAW to processed output, preserves source transport/radiometry as unverified, and deterministically replays the same capture. A paired pre-ADC/decoded-16-bit diagnostic checks the half-code rounding bound with the same noise realization. Changing physical print dimensions leaves captured samples unchanged. This is bounded public computational backend qualification; it does not establish physical calibration, a megapixel producer, source headroom, or actual visibility transport.
53
+
54
+ The PSF orientation references now hash the complete actual oriented scalar raster and give each orientation a distinct representation identity. Depth references hash a complete 200×200 Float64LE scalar artifact and extract the tested ROI from it. That artifact continues the selected ideal plane outside its qualified interior region; no depth-edge or other-surface rendering claim is made for those pixels. Every finite PSF tap for the selected ROI must still resolve to its declared visible surface. The ideal field-invariant pupil records the selected field coordinate explicitly. These are owned analytic references, not a reconstructed full 3D photograph or an actual-device calibration.
55
+
56
+ ### Changing-visibility source qualification
57
+
58
+ `test/print-region-visibility-backend.test.ts` drives the actual public production capture path with an owned nearest-surface provider. A foreground half-plane at 2 m translates along world X or Y; its edge starts at −0.5 m and moves at 125 m/s during the 8 ms exposure. A uniform farther plane at 10 m supplies radiance wherever the near plane is absent. The two spectral radiance levels are 0.5 and 1.5 times the previously independently predicted flat-band source. Engine-owned outgoing rays drive metric near-plane intersections; the provider does not introduce a second camera projection or an endpoint blur kernel.
59
+
60
+ A separate exact Fraction oracle derives source-aperture ray slopes, native-Y inversion, visibility transition times, finite midpoint occupancies and continuous-exposure source means. Tests use 2/4/8/16/32/64/128 time nodes and both motion axes. The 128-node cases exposed a Node 24 coverage timeout. Every query is checked with direct fail-fast conditions, and replay compares a SHA-256 digest of all finite serializable scientific results. After those harness improvements, both full capture/replay cases still took 6.5–6.7 seconds in CI coverage; the fixture therefore has an explicit 15-second deadline. It is a numerical qualification fixture, not a performance gate. All cases, independent bounds and replay checks remain; the regular suite retains its default five-second deadline. The finite/continuous source-scale error is bounded by the unit radiance step divided by node count; it need not decrease monotonically for a discontinuous edge. All 16N callbacks per complete native 2×2 capture must execute. Actual photoelectron expectations, RAW/processed-output binding and deterministic replay are checked. Each execution has an explicit capture identity, and its snapshot commits the selected time-node count.
61
+
62
+ This qualifies only this owned moving-source provider and the named public integration path. The engine's `sceneVisibilityCalculated: false`, `providerTransportVerified: false` and `upstreamRadiometryVerified: false` remain unchanged: the engine has not acquired a general scene/transport solver. Point optics and the stated rectangular aperture are explicit. PSF/defocus at moving depth edges, rolling readout, camera translation/rotation, corrections, edge-grazing semantics, other geometry, source calibration and private renderer/device behavior require separate evidence. It does not certify full #196 or a printable depth proof.
63
+
64
+ ### Physical proof artifact and independent inspection
65
+
66
+ The committed [two-page physical proof reference](../output/pdf/print-proof-reference.pdf) reuses the exact existing post-encoding JPEG streams and selected native 16×8 crop. Page 1 prints the same JPEG/crop at full-source widths of 1 and 4 inches. Page 2 compares quantizer-step 1 and 32 representations of the same capture and crop at identical physical scale. No fixture family, new source per print size, resampling or interpolation uplift is introduced. The older JPEG bytes, hashes, capture IDs and 1.1.0 creator identity remain unchanged.
67
+
68
+ An offline ReportLab generator derives millimeters/PDF points using exact Fraction arithmetic. A separate pypdf inspector reads actual MediaBox, graphics transforms, clip rectangles, embedded image dimensions, original DCT bytes, default interpolation policy and the nominal 100 mm calibration line. It maps native top-down ROI corners through the actual PDF transform and compares independent physical-unit expectations at less than 0.0001 PDF point serialization tolerance. Public-root tests bind the pinned PDF/inspection/manifest hashes and compare the existing Print planner's retained raster, crop geometry and PPI to the independently inspected reference. The 16×8 crop remains 16×8 at both enlargements. Generator reproduction is deterministic, with image resources based on byte content rather than checkout paths. Both final pages were rendered and visually inspected.
69
+
70
+ This is public artifact/geometry evidence, not a new runtime PDF exporter or a qualified product proof workflow. The source is the existing owned post-ADC grating, not physical source/optics qualification. PDF DeviceRGB appearance, viewing luminance, substrate, actual printer scale and user/device handling remain unqualified. The calibration line's actual printed length must be measured. There is no embedded font program, added runtime dependency or private code/asset. The independent inspector is an optional offline pypdf tool; normal Node CI verifies committed artifact/record integrity and engine geometry without requiring Python packages. Human/source review and full #196/#307 physical proof integration remain open.
71
+
72
+ ## Source and reuse review
73
+
74
+ The castleCSF numeric model material is pinned to upstream `f4b0b722af83001d7af979281e06ca642d36e4e8`. MIT notices are retained in [the license](licenses/castleCSF-MIT.txt), `NOTICE` and `THIRD_PARTY.md`. No observational CSV or separately licensed dataset is incorporated. The public [primary paper](https://pmc.ncbi.nlm.nih.gov/articles/PMC10996938/) supplies scientific context; upstream numerical conformance does not supply a new observer experiment. Quadratic paraxial pupil phase and finite propagation are consistent with the scalar diffraction framework described by [Braat and colleagues](https://nijboerzernike.nl/_PDF/BraatProgOpt2007OwnVersion20080515.pdf); no text, figures, tables or implementation from that source are copied.
75
+
76
+ Substantive human scientific/source and contribution-specific DCO review remains pending for this new change. Approval of PR #216 does not certify these new coefficients, adapter, protocols or owned test material.
77
+
78
+ ## Candidate checks
79
+
80
+ On Node 26.8.1, all 2,065 tests in 159 files pass; the full suite also passes with coverage on Node 24.19.0. Coverage is 92.04% statements, 88.55% branches, 99.63% functions and 92.04% lines. Build, static/license/SPDX/identity/browser checks, generated references, documentation links, 67 strict packed documentation consumers and the 810-file package surface pass. The [evidence inventory](validation/print-196-candidate-evidence.json) pins generator/artifact and reviewed upstream source hashes. These observations do not replace supported Node CI or substantive human review of the exact candidate commit.
81
+
82
+ ## Engine and full new-UI release gates
83
+
84
+ The [candidate capability ledger](validation/print-196-candidate-capabilities.json) records bounded support and missing qualification separately. The engine owns the bounded interpretation contract and publicly runnable qualification. The app owns production capture, physical proof, accessibility and device integration and consumes published engine APIs. The full new-UI acceptance below remains in scope, but cannot logically precede publication of its required engine contract. The requested release after completion still requires resolving the engine acceptance and human review gates; product gates remain explicitly outstanding:
85
+
86
+ - Independently qualified active capture/backend evidence for the claimed source detail domain, including lens/field, source headroom and continuum/support convergence. Owned finite reference execution cannot certify a private production renderer or actual capture device.
87
+ - Qualified actual-source high-bit/linear evidence for the claimed physical noise and tonal domain. The public electronic reference now covers modeled photo/dark/read noise, storage/pre-ADC/digital saturation, signed shadows and 12-bit rounding. Actual source transport, physical calibration and display/render clipping remain unassessed.
88
+ - Backend evidence for subject/depth/occlusion across the actual supported coordinate/correction/viewpoint domain, and temporal visibility changes where claimed. Interior finite-plane references exclude depth-boundary composition.
89
+ - A perception application whose actual stimulus, luminance, contrast, area and observer conditions match the supported model. A rectangular coherent grating or natural-image ROI is not automatically a Gaussian-envelope Gabor stimulus. Color, aliasing, halos and natural-image visibility remain independently unassessed.
90
+ - Exact physical proof/comparison scale and immutable capture/region/output binding in the product integration required by #196/#307. The standalone engine tests cannot certify private UI scale, accessibility or device rendering.
91
+ - Human scientific/source review, contribution DCO certification, exact-head CI, final-main release gates and explicit publication approval.
92
+
93
+ Do not close #196, downgrade these gates, or describe the release as ready because computational tests pass. #195 can be closed on acceptance of its planning audit. #215 remains open until the approved distribution is published.
@@ -0,0 +1,45 @@
1
+ # Engine #196 acceptance audit
2
+
3
+ This audit follows merged [PR #217](https://github.com/Photivra/photivra/pull/217), commit `c58d9eb9dcba807f020df45be1ed5ec4f6c081e4`. Owner approval of that contribution's scientific/source and DCO gate is recorded in its squash commit and PR. The old candidate ledgers retain their historical pending-review observations; they are not current approval records. The additional patterned-source reference below requires its own substantive human review and contribution-specific DCO certification.
4
+
5
+ ## Engine contract and full product scope
6
+
7
+ [Engine #196](https://github.com/Photivra/photivra/issues/196) requires documented, independently supported bounded assessment, with other dimensions explicitly qualified or unassessed. It does not require a universal quality score, automatic natural-image visibility verdict, named-device calibration or printer ICC/substrate simulation. The engine APIs preserve those exclusions. Their scientific meaning remains conditional on a declared source, registration, model and stage; successful parsing never authenticates a supplied artifact.
8
+
9
+ The issue also requires the full new-UI print feature. Its app acquisition, proof workflow, accessibility and actual-device gates remain required under [app #307](https://github.com/Photivra/photivra-apps/issues/307) and its linked owners. They consume the published engine contract. They cannot be prerequisites for publishing that same prerequisite contract. Engine acceptance does not close those tickets, certify a private renderer, or make the complete new-UI release ready. The earlier candidate's combined `fullAssessmentAcceptance: blocked` remains true for that complete product scope; it must not be mistaken for proof that every engine requirement lacks evidence.
10
+
11
+ ## Requirement-to-evidence audit
12
+
13
+ | Engine requirement | Authoritative evidence | Qualified scope / retained limit |
14
+ | --- | --- | --- |
15
+ | Model, supported domain, independent protocol and reuse review before implementation | `PRINT_DETAIL_ASSESSMENT.md`, `PRINT_DETAIL_VALIDATION.md`, `PRINT_REGION_STATISTICS.md`, `PRINT_CONTRAST_REFERENCE.md`, retained MIT license/NOTICE/THIRD_PARTY, #217 owner review | Bounded coherent scalar and linear-statistic models; separate population contrast reference; no general photograph classifier |
16
+ | Reuse optics, sampling and processing; no second diffraction/defocus/motion stack | `print-detail-psf-backend.test.ts`, `print-detail-depth-backend.test.ts`, `print-depth-pupil-convergence.test.ts`, `print-detail-motion-backend.test.ts`; shared public functions | Finite local kernels, declared pupil grid and support, supported temporal nodes; no blur-diameter-to-PSF conversion or named-lens calibration |
17
+ | Exact source stage, region, field, subject/focus, print/viewing geometry and contrast assumptions | `print-detail.test.ts`, `print-region-statistics.test.ts`, model/input contracts | Explicit selected ROI, orientation/crop and relative-linear domain; absolute print luminance is not inferred; unqualified correction/warp blocked |
18
+ | Directional versus isotropic blur and equal-PPI/different-detail sources | `print-detail.test.ts`, `print-detail-psf-backend.test.ts`, new `print-detail-native-capture.test.ts` | Owned periodic sources and named public backend; no universal MTF or real-camera claim |
19
+ | Actual capture backend, target truth and independently predicted source response | New `print-detail-native-capture.test.ts` and `native-detail-reference.json`; existing `print-region-capture-backend.test.ts` | Complete 4×4 native provider→optics→EQE→photo/dark/noise→ADC execution, two axes/phases and four aperture node counts; declared angular source, point optics, no private renderer/device calibration |
20
+ | Selected subject, intentional background defocus, visible depth/occlusion | `print-detail-depth-backend.test.ts`, `print-region-visibility-backend.test.ts` | Known metric nearest-surface provider; finite PSF support restricted to one visible plane; point-optics changing visibility; depth-edge PSF and unqualified viewpoint/corrections unsupported |
21
+ | Directional subject/camera motion | `print-detail-motion-backend.test.ts`, `print-region-visibility-backend.test.ts` | Independently predicted finite/continuous exposure on declared trajectories; no single homography across depths or endpoint chord substituted for a PSF |
22
+ | Noise, clipping and processing halos tested separately | `print-region-statistics.test.ts`, `print-region-noise-backend.test.ts`, `print-region-readout-backend.test.ts`, new native-capture test | Same-realization paired differences versus independent-repeat temporal variance; known range overshoot/undershoot; explicit electronic clipping stages; no automatic halo attribution or physical sensor calibration |
23
+ | Post-encode assessment bound to exact representation | `print-detail-jpeg-integration.test.ts`, committed JPEG/decoder manifests and independent references | Actual archived JPEG bytes, independent decoded neutral samples and exact capture/ROI identity; pre-encode does not certify post-encode; no automatic compression-quality verdict |
24
+ | Physical enlargement distinct from resampling; same-scale proof binding | `print-proof-reference.test.ts`, separate pypdf inspection and committed PDF; native-capture enlargement check | Actual PDF operators, original DCT streams, retained crop, physical-unit reference and nominal ruler; actual printer and product proof workflow remain app gates |
25
+ | Contrast/perception only through an evidence-backed model | `print-contrast-reference.test.ts`, 80-digit independent reference, pinned castleCSF revision and exact MIT terms | Declared static D65 Gabor population-model estimate only; measured rectangular ROI is not a matched Gabor; natural-image visibility, individual observer, physical print stimulus and uncertainty remain unassessed |
26
+ | Aliasing, halos, compression and color independently inspectable; no overall score | Public result contracts and unsupported/unknown-state tests | These dimensions are unassessed unless an explicit bounded protocol supplies a numerical quantity; no combined quality uplift, pass/fail or interpolation claim |
27
+ | Identity/version compatibility and independent public usefulness | Source/ROI/hash tests; historical JPEG replay; root-only browser/package/docs/packed consumers | Explicit engine/model/protocol identity; no private scene, device dataset, runtime dependency or changed historical creator identity |
28
+
29
+ ## Patterned-source native capture qualification
30
+
31
+ The additional reference extends the existing owned flat-band scene variant; it adds no chart family or target per print size. A declared angular neutral sinusoid has modulation 0.5 and one cycle across the native 4×4 raster. At the stipulated ideal image distance, the two angular periods are `36 × 0.0198` and `24 × 0.0198` in look-ray slope. The source definition consumes engine-generated outgoing rays. It does not calculate a replacement camera projection. All sites use the explicit existing 800×600 µm geometric aperture, 540–560 nm band, equal effective QE 0.4, f/4 transmission 0.85 and 8 ms exposure.
32
+
33
+ An independently authored 80-digit Decimal cosine series predicts every native photo expectation, fundamental modulation and continuous rectangular-aperture response for both axes, phases 0 and 0.37, and 1/2/4/8 midpoint aperture nodes. The midpoint-rule absolute modulation error bound is `0.5 (2 pi apertureWidth / imageExtent)^2 / (24 nodeCount^2)`, declared from the second-derivative bound before evaluating runtime output. Expected photoelectron units reuse the independently derived SI reference from `generate_capture_reference.py`. Neither generator imports the engine or reads observed samples. Tests pin both source artifact hashes and require every expected provider callback.
34
+
35
+ The named `simulateEnvironmentSensorRawFrame()` path executes the complete native raster, including source optics/EQE, actual seeded noise and ADC. The reference first qualifies expected photo transfer, then separately binds and assesses the actual noisy, quantized relative scalar representation. Same-realization pre/post-ADC differences must satisfy half-code rounding bounds. A photo expectation is never relabeled as measured noisy captured-system MTF. Complete scalar artifacts are hashed, and physical enlargement changes print geometry without changing captured measurements.
36
+
37
+ This is conditional modeled neutral signal, not measured cd/m², a photographic observer experiment, CFA color calibration, private renderer qualification or actual hardware evidence. Existing transport/radiometry verification flags remain false. The reference's point-optics domain is explicit. The older finite-pupil pilot's one-frequency convergence limits remain unchanged.
38
+
39
+ The [new evidence record](validation/print-196-engine-acceptance.json) pins these additional artifacts and records local test/package observations separately from scientific approval. The generator was replayed against its pinned SHA-256; normal CI uses the committed reference without requiring Python.
40
+
41
+ ## Acceptance decision and remaining gates
42
+
43
+ The requirement audit is review material, not self-issued scientific certification. The existing #217 contribution was approved and merged. The new generator, artifact, tests and this ownership audit must receive substantive human scientific/source review and DCO certification, with green exact-head checks, before engine #196 is accepted. Acceptance must explicitly retain the supported domains above and the complete new-UI obligations; it must not be described as natural-image or device calibration.
44
+
45
+ After engine acceptance, the requested engine release still requires final-main checks, version/distribution availability checks, configured publishing protections and explicit tagging/publication approval. No tag or package is created by this work. Full new-UI release readiness remains blocked until its acquisition, source/target headroom, physical proof, accessibility and device gates have qualified evidence in the app owners. This audit neither defers nor removes them.
@@ -0,0 +1,43 @@
1
+ # Static neutral Print contrast reference — model 0.1.0
2
+
3
+ `calculatePrintContrastReference()` evaluates a restricted static, foveal, neutral D65 Gabor reference from castleCSF. This is an **estimated population-model reference**, separate from measured regional detail and sampling sufficiency. It does not classify a photograph, promise invisibility, establish personal acuity or produce an overall Print verdict. Actual stimulus matching remains unassessed.
4
+
5
+ ## Model and source review
6
+
7
+ The numerical source is [castleCSF revision f4b0b722af83001d7af979281e06ca642d36e4e8](https://github.com/gfxdisp/castleCSF/tree/f4b0b722af83001d7af979281e06ca642d36e4e8), including `CSF_castleCSF.m`, `CSF_stelaCSF_lum_peak.m`, `CSF_castleCSF_chrom.m` and `CSF_base.m`. These code files contain the model equations, numerical parameters, neutral D65 background and mechanism projections. The repository license is MIT, copyright 2023 Graphics and Displays group, University of Cambridge. Retain the [exact license](licenses/castleCSF-MIT.txt), copyright in source and `NOTICE`, and the inventory in `THIRD_PARTY.md`. The scalar TypeScript adapter and independent high-precision evaluator are newly authored; the numerical model material is third-party material, not asserted to be Photivra-owned calibration.
8
+
9
+ The [primary paper, Ashraf et al. (2024)](https://pmc.ncbi.nlm.nih.gov/articles/PMC10996938/) describes sensitivity as a function of stimulus conditions and reports population-model validation. Its fixed-size static achromatic Gabor reference is relevant to this restricted stimulus. We do not reproduce the paper, tables, figures or observational datasets. No CSV from the combined historical datasets is included; their reuse/collection history is not inferred from the code license. Source/license review of this new numerical material remains a substantive human release gate.
10
+
11
+ ## Explicit conditions and quantities
12
+
13
+ Every input must explicitly identify the stimulus and published binocular/natural-pupil reference assumption. The implemented numerical envelope is mean luminance **1–1000 cd/m²**, carrier frequency **0.25–16 cycles/degree**, Gaussian envelope sigma **exactly 1.5 degrees**, temporal frequency **zero** and eccentricity **zero**. These are model-evaluation limits, not a calibration certificate covering every observer or combination. Positive values outside this envelope yield `unsupported`, not extrapolation. Michelson modulation is a supplied fraction in `[0,1]`; luminance is not inferred from capture exposure, a display percentage, paper whiteness or image RGB.
14
+
15
+ The luminance input is the uniform D65 background/carrier mean used by the upstream model. The supplied modulation is the neutral sinusoidal carrier fractional amplitude before its Gaussian envelope. It is not a finite image ROI average, arbitrary image extrema ratio, Fourier residual or noise RMS. A Gaussian window changes the spatial stimulus; rectangular-grating equivalence is not established by the scalar adapter. The primary paper discusses aperture-equivalence assumptions and their limitations. Its individual datasets use different envelopes at some frequencies, so the adapter’s numerical envelope must not be presented as a uniformly measured empirical calibration grid.
16
+
17
+ Equal fractional modulation of the upstream neutral D65 LMS background is selected. Retain the achromatic sustained/transient responses and both opponent-mechanism projections; the neutral background has small nonzero opponent projections. Static temporal response and the Gaussian effective area `pi sigma²` follow the pinned model. Evaluate luminance-dependent hyperbolic terms using log1p/expm1 to retain the small saturation term. This is scalar evaluation of the mathematical equations, rather than bit-for-bit emulation of MATLAB's cancellation in `1 - power(...)`.
18
+
19
+ Return sensitivity, its reciprocal threshold modulation, and supplied modulation divided by that threshold. They remain continuous model quantities. The API offers no `visible`, `invisible`, `pass`, personal-vision score or automatic print-quality recommendation. It neither combines independent image-quality dimensions nor maps a Fourier residual/noise RMS into a Gabor contrast. Fitted population variation and upstream fit errors do not supply an individual confidence interval. Uncertainty remains explicitly unquantified.
20
+
21
+ ## Independent numerical protocol
22
+
23
+ The committed [reference generator](../test/fixtures/print-detail/generate_contrast_reference.py) evaluates the scalar equations with Python standard-library Decimal at 80 digits, using direct hyperbolic powers, an independently arranged area term and exact decimal parameters. It imports no engine output. The [reference artifact](../test/fixtures/print-detail/contrast-reference.json) covers 35 luminance/frequency points. SHA-256, source revision, protocol and conditions are checked by the public-root test. Compare sensitivity and threshold with relative arithmetic tolerance `1e-12`; this is numerical conformance, not an observer-accuracy claim. Tests also cover domain boundaries, immutable copied input, explicit zero contrast, malformed conditions and absence of a visibility verdict.
24
+
25
+ Neither the upstream MATLAB runtime nor new observer experiments have been executed by this protocol. Upstream empirical results provide a research basis, and the independent Decimal reference qualifies this scalar evaluation only. Actual photographic/printed-stimulus transfer, masking, age/ocular differences, absolute print luminance, color, glare, eccentricity, temporal presentation and viewing-device qualification remain separate. The coherent rectangular grating diagnostic is not a Gaussian-envelope stimulus; its modulation cannot be passed off as matched Gabor evidence. #196's full scoped acquisition/perceptual acceptance remains open until the capability ledger records the missing evidence and substantive human review.
26
+
27
+ ## Complete public example
28
+
29
+ ```ts
30
+ import { calculatePrintContrastReference } from "@photivra/engine";
31
+ const reference = calculatePrintContrastReference({
32
+ referenceId: "example-population-reference", stimulus: "static-neutral-d65-gabor",
33
+ observer: "published-binocular-natural-pupil-reference",
34
+ meanLuminanceCdPerSquareMeter: 50, spatialFrequencyCyclesPerDegree: 4,
35
+ gaussianEnvelopeSigmaDegrees: 1.5, temporalFrequencyHz: 0,
36
+ eccentricityDegrees: 0, modulationMichelson: 0.01
37
+ }).value;
38
+ if (reference.status !== "model-estimate" || !reference.estimate) throw new Error("Unexpected reference domain");
39
+ if (reference.naturalImageVisibility !== "unassessed" || reference.overallPrintVerdict !== "not-offered") throw new Error("Unexpected quality claim");
40
+ console.log(reference.estimate, reference.observerApplicability);
41
+ ```
42
+
43
+ This evaluates a declared reference stimulus. It is not evidence that an actual photograph or print meets those stimulus/observer conditions.
@@ -1,6 +1,6 @@
1
1
  # Regional Print detail diagnostic — model specification 0.1.0
2
2
 
3
- This is the bounded mathematical first slice of #196, stacked on the unpublished [Print geometry candidate](PRINT_PLANNING.md). Geometry must be reviewed and published before downstream integration. This diagnostic is not full #196 acceptance, a natural-image sharpness evaluator, a visibility threshold or an overall print pass. The [validation protocol](PRINT_DETAIL_VALIDATION.md) and [capability ledger](validation/print-detail-capabilities.json) identify what is tested and what remains blocked.
3
+ This is the bounded mathematical first slice of #196, using the [Print geometry contract published in 1.1.0](PRINT_PLANNING.md). This diagnostic is not full #196 acceptance, a natural-image sharpness evaluator, a visibility threshold or an overall print pass. The [validation protocol](PRINT_DETAIL_VALIDATION.md) and [capability ledger](validation/print-196-candidate-capabilities.json) identify what is tested and what remains blocked. The additive [regional statistics protocols](PRINT_REGION_STATISTICS.md) separately measure processing differences and repeat-capture sample variance; they do not change this diagnostic's qualification or exclusions.
4
4
 
5
5
  ## Supported model and domain
6
6
 
@@ -0,0 +1,36 @@
1
+ # Regional detail paired-export JPEG evidence 0.1.0
2
+
3
+ This addendum to [the regional diagnostic protocol](PRINT_DETAIL_VALIDATION.md) qualifies only a bounded execution test: owned post-ADC RAW codes → public paired-export reconstruction/color/SDR/JPEG → independently recorded JPEG decode → neutral relative-linear luminance → regional fundamental. It extends [the capture-SDR execution evidence](PRINT_DETAIL_SDR_EVIDENCE.md) without changing the metric, public API, dependencies or historical records. Human scientific/source review remains pending; full #196 acceptance remains blocked.
4
+
5
+ ## Owned source and target truth
6
+
7
+ `test/helpers/print-detail-jpeg-fixture.ts` supplies a native 20 × 16 periodic Bayer frame. Every complete 2 × 2 tile has one neutral post-ADC code from repeating `[640,448,256,448]`. Black is 64 and white is 1023, so linear tile levels are `[576,384,192,384]/959`. Source mean is `384/959`; the two-sample-held eight-pixel period has fundamental modulation `0.5 cos(pi/8)`. This follows the discrete hold's half-sample phase and cosine attenuation. The target contains known higher harmonics and is not a pure continuous optical sinusoid. Only its declared coherent Fourier fundamental is assessed; its residual cannot be classified as noise or a compression artifact.
8
+
9
+ This is owned synthetic draft post-ADC data, not a renderer-acquired optical target or noise realization. The existing declared ideal test color profile and tile-average reconstruction are reused. Neither becomes physical calibration. The source's placeholder float plane does not supply JPEG pixels: the public export develops the committed RAW codes. The independent Python check derives expected neutral pre-encode codes from the source codes and explicit orientation permutation, with no engine imports. It separately verifies the source's fundamental identity.
10
+
11
+ ## Exact stage and independent reference
12
+
13
+ Eight committed JPEGs cover all four orientations at constant quantization steps 1 and 32. These are scalar encoder parameters, not manufacturer's quality scores. Each orientation has a distinct capture ID; its quantization variants retain that same capture identity, with unique document/instance IDs for each exported file. The public exporter executes orientation itself, writes already oriented JPEG pixels, and declares EXIF orientation 1. Native 20 × 16 becomes 20 × 16 or 16 × 20. Partial eight-pixel coding blocks exercise the encoder's edge padding without changing the declared raster. The selected off-center half-open ROI begins at `(2,2)` and is 16 × 8 in landscape or 8 × 16 in portrait; it spans two target periods and JPEG block boundaries.
14
+
15
+ `export-manifest.json` records actual source codes, pre-encode RGB, JPEG SHA-256, raster, target and ROI identities. `independent-reference.json` binds to its exact bytes and records installed Pillow/libjpeg/Python versions, independently decoded RGB bytes/hash, ROI float64 little-endian bytes/hash and separately calculated pre-encode/decoded coefficients. The verifier requires neutral equal decoded RGB channels; each inverse-transferred channel is then relative linear luminance. It does not define a colored RGB luminance extractor, ICC transform or generic decoder policy.
16
+
17
+ The independent reference calculates mean, cosine/sine coefficients, amplitude, modulation and residual using Python `math.fsum`, independently of the engine accumulator. Every Node test regenerates actual paired-export JPEG bytes and requires exact agreement with the committed JPEG, manifest hash and independent decoded-byte record. It converts the recorded neutral pixels to linear values, compares each ROI sample within absolute 1e-12, and compares all regional measurements within 1e-10. These are numerical tolerances for 128 positive bounded samples, not perceptual thresholds. Integer bytes, raster identities and hashes are exact checks. Node CI consumes committed independent decode evidence; it does **not** execute Pillow anew.
18
+
19
+ The actual runtime linear luminance plane receives a separate float64 little-endian SHA-256 carried unchanged through the diagnostic input/result. It is linked by the test to the exact JPEG and decoder record. The public diagnostic still returns `caller-declared-unverified`, unknown scientific assurance and `not-offered` overall verdict; it performs no IO or automatic provenance upgrade.
20
+
21
+ ## Reproduction and invalidation
22
+
23
+ ```sh
24
+ node scripts/generate-print-detail-jpeg.mjs /tmp/photivra-print-jpeg-reproduction
25
+ python scripts/verify-print-detail-jpeg.py /tmp/photivra-print-jpeg-reproduction --record
26
+ python scripts/verify-print-detail-jpeg.py test/fixtures/print-detail/jpeg
27
+ npx vitest run test/print-detail-jpeg-integration.test.ts
28
+ ```
29
+
30
+ Generation uses the repository's existing development compiler. Python QA uses an existing installed Pillow; no engine/runtime/development dependency or CI install is added. A missing Pillow fails the independent check rather than silently passing. `--record` writes a new candidate reference for review; verification without it requires the committed decoder versions and results to agree. Preserve old records when the source, reconstruction, color model, renderer, encoder, registration, target, ROI, metric or decoder changes. Regeneration is evidence collection, not human approval. [The separate evidence ledger](validation/print-detail-jpeg-evidence.json) pins source hashes and the finite execution envelope.
31
+
32
+ Fine quantization preserves this target's measured regional modulation within numerical tolerance. Coarse quantization changes it and may increase the fundamental or residual. An increased transfer coefficient does not imply restored detail, improved quality, invisibility or a compression pass. Source RAW, pre-encode RGB and native raster remain unchanged between quantization variants; only the exact encoded representation and its diagnostic differ.
33
+
34
+ ## Remaining qualification
35
+
36
+ This evidence covers one owned neutral stepped grating, one source/processing policy, one selected ROI per orientation and one recorded independent decoder configuration. It does not qualify optical acquisition/MTF, spectral color calibration, other targets/frequencies/depths, noise/aliasing/halos/compression classifiers, generic image codecs or decoder variants, resampling/warp, native-resolution production, UI/GPU/device/display execution, observer perception or printer/substrate response. No JPEG quality verdict is introduced. Full scoped new-UI acceptance remains blocked until the missing evidence and substantive human review are complete.
@@ -1,6 +1,6 @@
1
1
  # Regional Print detail independent validation protocol 0.1.0
2
2
 
3
- This protocol tests the mathematical domain in [the model specification](PRINT_DETAIL_ASSESSMENT.md). Passing does not qualify arbitrary photographed targets, renderers, lenses, printers or perceptual decisions. [The capability ledger](validation/print-detail-capabilities.json) must retain these limits.
3
+ This protocol tests the mathematical domain in [the model specification](PRINT_DETAIL_ASSESSMENT.md). Passing does not qualify arbitrary photographed targets, renderers, lenses, printers or perceptual decisions. [The capability ledger](validation/print-196-candidate-capabilities.json) must retain these limits.
4
4
 
5
5
  ## Public analytic evidence
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Native-only Print planning
2
2
 
3
- Release candidate: package/root API **1.1.0**, Print model **0.1.0**. This standalone browser-safe API answers native sampling sufficiency and the minimum compatible printer-file raster. It generates no pixels or files. See [API conventions](API_STYLE.md), [staged geometry](PHYSICS_FOUNDATION.md), [processed output](PROCESSED_OUTPUT.md) and [release review](RELEASE_1_1_0.md).
3
+ Published in package/root API **1.1.0**, Print model **0.1.0**; retained in the **1.2.0** candidate. This standalone browser-safe API answers native sampling sufficiency and the minimum compatible printer-file raster. It generates no pixels or files. See [API conventions](API_STYLE.md), [staged geometry](PHYSICS_FOUNDATION.md), [processed output](PROCESSED_OUTPUT.md) and the [historical 1.1.0 release review](RELEASE_1_1_0.md).
4
4
 
5
5
  ## Authority and units
6
6
 
@@ -71,3 +71,5 @@ For untrusted requests use `parsePrintPlanInput()`. Calculation functions also p
71
71
  - [University of Iowa acuity testing](https://webeye.ophth.uiowa.edu/eyeforum/video/Refraction/Visual-Acuity-Testing/index.htm): optotype critical stroke detail is distinct from a whole optotype. This motivates explicitly declared conventions; it supplies no universal print sampling/quality guarantee.
72
72
 
73
73
  Implementation, prose and tests are original. References informed terminology and equations; no source tables, calibration, datasets or protected expression were incorporated. Independent tests cover the 160-PPI identity, high-precision angular reference, all orientations/off-center crop, ignored preview enlargement, unit and one-pixel boundaries, exact-ratio minimum search with fixed seed, lab conflicts, manual overrides, semantic bounds and invalid/extreme finite JSON. Human scientific/source/DCO review remains required before release. Advanced captured-detail/quality assessment remains separate (#196).
74
+
75
+ The 1.2.0 acceptance audit additionally exercises stamp, book, home, gallery, billboard and half-mile dimensions/distances through the same source and explicit criterion, plus a heavy retained crop and recovery after invalid edits. These are geometric examples, not claims about eyesight, text readability, substrate or file-export readiness. The core #195 contract was delivered in PR #210 and published in 1.1.0; historical references to an unpublished geometry candidate are superseded. Actual UI/task/device and JPEG-delivery acceptance belongs to the consuming product and its exporter evidence, rather than this pixel-free planning API.
@@ -0,0 +1,38 @@
1
+ # Regional linear Print statistics — model and protocol 0.1.0
2
+
3
+ These additive browser-safe protocols separate a registered processing difference from repeat-capture temporal sample variance. They extend #196's evidence work; they do not complete its acquisition, perception, subject/depth, motion or full release acceptance. The coherent detail diagnostic remains model 0.1.0 with its existing behavior.
4
+
5
+ ## Source and applicability
6
+
7
+ Each frame uses the existing Print source, explicit scalar relative-linear luminance domain, actual represented raster, half-open oriented retained ROI, capture/representation/content/processing identity, evidence and noise-realization identity. Source/ROI parsing shares the coherent diagnostic boundary. Arrays must be dense and finite. The total request contains at most 65,536 scalar samples, including every repeat or both members of a pair. A noise ensemble has 2 to 256 frames. This is a work bound, not a device performance claim.
8
+
9
+ The represented raster must preserve retained native aspect and cannot exceed either native axis. Native-stage rasters must match the retained native crop. Unqualified warps and non-linear/unknown domains are blocked. Registration compares the full parsed geometry, ROI and Print conditions conservatively. It does not resample or invent a correspondence. Different physical units expressing the same conditions must be normalized by the caller for a paired comparison. Insufficient native sampling or conflicting lab conditions remain visible in the returned Print plan; a sample statistic cannot repair delivery.
10
+
11
+ Hashes, numeric provenance, acquisition stationarity and independent repeats remain caller declarations. Successful parsing/calculation never verifies file contents, decoding, a license or physical calibration. Results freeze copied inputs, retain engine/model identity and explicitly return unassessed acquisition, unquantified uncertainty and no overall verdict. Changing any source, ROI, processing, acquisition or viewing condition requires a new assessment identity downstream.
12
+
13
+ ## Paired processing difference
14
+
15
+ `calculatePrintRegionDifference()` compares identical sample sites belonging to one immutable capture. Select either a declared deterministic reference (both noise IDs null) or the same explicitly named non-null noise realization. Distinct or unknown noise draws cannot be compared as processing-only change. No single noisy frame supplies a noise variance. A decoded-file comparison requires the pre-encode `post-resampling-linear` stage and the exact `post-encoding-decoded-linear` stage. The same representation ID with contradictory hash, stage or processing identity is blocked.
16
+
17
+ For differences `d_i = after_i - before_i`, return signed mean, `sqrt(sum(d_i²)/N)` and maximum absolute difference in relative-linear luminance. This measures the net change between supplied representations; it does not automatically attribute it to JPEG compression, classify artifacts or establish visibility. Exact pre/post-encode artifact binding and independent decoder qualification remain external evidence obligations. Comparisons at different rasters require an independently registered reference on identical sample sites; this protocol does no resizing.
18
+
19
+ An optional declared increasing reference signal range supplies below/above-range counts and maximum excursions for both representations separately. It can quantify known step-response undershoot/overshoot in an independently designed experiment. It is not an automatic halo detector. Existing source excursions remain visible. Range endpoints are neither sensor full well nor ADC/render clipping thresholds; boundary contact or excursions cannot establish a clipping mechanism. Color channels, gamut error, printer texture and natural-image quality remain unassessed.
20
+
21
+ ## Temporal repeat statistics
22
+
23
+ `calculatePrintRegionNoise()` consumes a declared stationary scene and independent capture repeats at identical registered sites, geometry and processing stage. Each repeat has its own capture, representation and non-null noise-realization identity. Reused identities, stage/processing differences and missing noise IDs block the calculation. Equal bytes in separate repeats are allowed: zero noise and quantized repeated values are valid observations. IDs cannot themselves prove independence or stationarity.
24
+
25
+ At each sample site compute the temporal mean and sample variance `sum((v_j - mean)²)/(n-1)`. Return those arrays, the mean of per-site temporal variances and its RMS, and the average site mean. The spatial variance of a textured image is deliberately not called temporal noise. Fixed-pattern variation, drift, correlations and nonstationarity need separate models. This protocol reports sample statistics, not an ensemble expectation, sensor SNR, a confidence interval or an uncertainty bound. It makes no Gaussian, Poisson or independent-pixel assumption for the statistic itself.
26
+
27
+ Normalize each site's values by the maximum absolute magnitude. Calculate the mean of offsets from the first repeat and center those offsets before restoring units. A rounded large-DC mean must not add false variance. Compensated accumulation and hypot norms reduce avoidable overflow/cancellation. Reject nonzero inputs/differences lost by normalization, nonfinite restored statistics and nonzero variance/RMS underflow. Supported numeric results are finite; unsupported numeric ranges return no measurement rather than zero or a fabricated uncertainty. No epsilon changes a measurement or sampling verdict.
28
+
29
+ ## Independent qualification protocol and rights
30
+
31
+ 1. Use an independently authored Python standard-library oracle with exact rational arithmetic for finite paired signals and repeat statistics. Commit its inputs, expected values and SHA-256. The reference must not import the engine or compute expected values from runtime outputs.
32
+ 2. Cover positive/signed/zero levels, correlated spatial texture with zero temporal noise, asymmetric/directional step overshoot, tiny values, large DC with representably small fluctuations, same/different realization policies, malformed inputs, missing/mismatched stages and the total work bound. Numeric tolerances qualify arithmetic on that bounded domain only.
33
+ 3. Execute the existing production charge/readout and image-formation functions for additional backend evidence. Preserve raw/linear/SDR/JPEG stage identity. Seed schedules and sample counts must be predeclared. Compare realizations against an independent distribution/processing reference; a synthetic target name alone does not qualify an active backend.
34
+ 4. Measure repeat-count and quadrature convergence independently before any physical or statistical claim. Record reference/backend/analysis versions and hashes, ROI, units, domain, source dimensions, conditions and pass/fail/unassessed state in the capability ledger. Publish observed conformance separately from human scientific/source review.
35
+
36
+ The [candidate review](PRINT_195_196_REVIEW.md#linearhigh-bit-electronic-readout-qualification) records actual public native RAW execution with an independently predicted 12-bit electronic reference. It separates storage/pre-ADC/digital clipping and signed read noise, and bounds decoded quantization effects without treating quantization as independent uniform noise. Its conditional neutral scalar encoding and declared electronic inputs do not establish physical photometry or sensor calibration.
37
+
38
+ All new equations are elementary paired differences and sample statistics, authored independently. New procedural signals and reference code are Photivra draft material under Apache-2.0, subject to human scientific/source and DCO review. No external numeric curve, camera profile, dataset, runtime dependency or private scene is incorporated. The researched [castleCSF primary paper](https://pmc.ncbi.nlm.nih.gov/articles/PMC10996938/) and [upstream repository](https://github.com/gfxdisp/castleCSF) describe a possible later perceptual model; neither its code, coefficients nor observations are included by these protocols. A perceptual application needs its own license/source audit, stimulus/observer/luminance/area/eccentricity matching and independent validation. These statistics cannot supply that qualification.