日本語 · English · 简体中文 · 繁體中文 · 한국어 · Deutsch
This repository records why things are the way they are in comments in the source. The ones marked ★ are the load-bearing ones — what was measured, what went wrong, why it is built this way. This page is collected from them mechanically; the source is the single copy of record, so the two cannot drift apart.
Translation status: 619 of 681. Untranslated entries are shown in the original Japanese — falling back silently would look like a translation, so a missing translation is shown as missing.
accel_match.py
- L170 — ★The window must be larger than the template or the count of full-overlap positions goes to zero → r = T//2 + f(coarse error) + win.
acoustics.py
- L1173 — ★
med == 0 was unconditionally treated as inf —— it reported “an infinitely dominant peak” even when peak was also 0 (silence, nothing in the band). As the docstring says, these two numbers are an honesty indicator for “it returns a peak frequency even when there is nothing there”, yet it was swinging in the most dishonest direction. The answer for 0/0 is 0.0. (2026-09-05: surfaced on Linux / numpy 2.5.2. The old version merely had a slight filter residual left so med > 0; the bug was there all along.)
- L1181 — ★The global median reverses its order when you narrow the band (pure noise 11375 vs a real defect 9433; measured 2026-09-06, see the _local_prominence table). Use this one for a bandwidth-independent verdict. The existing two are kept with their meaning unchanged —— a same name whose content changes is more dangerous than adding one.
- L1789 — ★
med == 0 was unconditionally treated as inf —— it reported “an infinitely dominant peak” even when peak was also 0 (silence, nothing in the band). As the docstring says, these two numbers are an honesty indicator for “it returns a peak frequency even when there is nothing there”, yet it was swinging in the most dishonest direction. The answer for 0/0 is 0.0. (2026-09-05: surfaced on Linux / numpy 2.5.2. The old version merely had a slight filter residual left so med > 0; the bug was there all along.)
annotate.py
- L3095 — ★Punctuation (。、) should not be rotated but shifted to the upper right, but here we don’t shift it —— rather than silently approximating what we can’t do, we write it in the docstring and leave it. Characters (punctuation) that shift to the upper right in vertical writing. A dot that sits at the lower left of the glyph in horizontal setting comes to the upper right in vertical setting —— the typographic manner is to move the position, not to rotate. Windows’
@-prefixed fonts (the vertical-writing face GDI selects by face name) did this on the font side. Pillow opens a font by file path so it can’t reach the @ face, and HarfBuzz’s direction="ttb" also gives different results with and without Raqm installed (this machine’s Pillow 12.3.0 has features.check("raqm") False). Following the policy choose what is consistent across platforms, here we shift by composition.
api.py
- L587 — ★
annotate.overlay_mask is deliberately not exposed at the top level. The same-named imgio.overlay_mask is already public as fs.overlay_mask, and its arguments and meaning differ (imgio = raw RGB, mask>0.5, fill/margin / annotate = role-name colour, weights [0,1] allowed too, rejects a shape mismatch). Putting a different promise on the same name means the caller receives not an exception but a plausibly different picture. We don’t make breaking changes to the public API on our own, so retrieve the role-carrying one via fs.annotate.overlay_mask.
- L1346 — ★ There is currently no correct way to call this for colour images: passing them all at once mixes the colours, and calling three times per channel makes a self-normalizing op divide each channel by its own max, breaking the ratios between channels (the grey-edge angular error goes from 1.03 deg with our own Sobel -> 4.17 deg per image -> 27.86 deg per channel, 29.14 deg at the zero point). Which way to lean is a contract decision, so here we change not a single default value, refuse only when
on_error="raise", and by default record it in the ledger so it stays visible. Details and options in docs/KNOWN_ISSUES.md.
astrostack.py
- L156 — ★Hypothesis test: we predicted that “there is no value in moving as long as it fits in one cache line (64B)” but were wrong. For float32 the crossover is at K≈17-19, close to 64B (K=16), but for float64 the actual crossover is K≈23-25 (about 200B) against a predicted K=8. It is decided by the number of elements, not the byte count —— the per-element fetch cost dominates. Moving while there are only a few is actually slower (1.4x slower at float64 K=5), so the crossover point is essential.
-
| L379 — ★MAD collapsing to 0 while the image is not flat = quantization (2026-09-08, hit by poc_thermal_radiometry). With integer DN, |
x-med |
is also an integer, so the sigma we can return is only a multiple of 1.4826 —— 0.0 for a real-image equivalent of σ=0.5, and σ=1.0 and σ=1.983 both give the same 1.4826. Silently returning 0 makes the threshold equal to the background, and downstream (star_detect) finds nothing. This is an entry point that returns a value, so instead of raising it speaks up (the caller can pick method=”clip”). Refusing is the job of the side that produces the answer = star_detect. |
- L586 — ★ The sole entry point for shot noise. With photons_per_unit=1, “expected value = lambda”.
- L675 — ★ field_seed is fixed (the same sky), only seed is varied (a different observation).
- L746 — ★Until 2026-09-08 this gate’s comment said “perfectly flat = noise cannot be measured”. It was the premise that was wrong —— there is one more path by which σ becomes 0: when MAD collapses under integer DN (0.0 for a real image equivalent to σ=0.5). Returning empty for a non-flat image is not a conservative answer but a wrong answer; in fact, 2 point targets planted in a 200x200 integer frame were being returned as 0. We split the paths: if flat, return empty (no stars); if not flat, refuse.
- L1606 — ★On a tie, pick the bin with more raw votes. A 3x3 smoothing gives the same sum whether seen from the left or the right of the true peak, so taking argmax on the smoothed value alone can pick “an empty bin next to the peak” —— exactly that happened in measurement: the true shift (-0.087, +0.996) had its votes 7 + 4 split in two at the bin boundary, and its centre, off by one bin, ended up with 0 votes (frame_align wrongly fail-closed as “not overlapping”). A weight of 1e-6 is far smaller than the smoothed value’s step (1/9), so it does not change the ranking when there is a real difference.
- L1629 — ★2026-09-08: also return the height of the second-place peak. For a star field there is one peak, but for repetitive structures (halftone dots, gratings, textiles) peaks of the same height line up shifted by a lattice vector, and whichever you pick “everyone agrees” = inlier_ratio becomes 1.00. The agreement rate is not “the probability the answer is correct”, so we report whether there was a single peak as a separate number (0 = single peak, close to 1 = there are other equivalent candidates).
backend_safe.py
- L436 — ★A feature op returns a numpy SCALAR, not an ndarray, so the branch above never saw it: a NaN/Inf measurement (e.g. a 0/0 inside sk_blur_effect on a degenerate frame) used to flow straight out of api.apply. Scrub non-finite scalars to the sort fallback so the declared “finite, sort-valid” guarantee actually holds for feature/contour scalars too.
backends.py
- L23 — ★The _safe fallback is a LAST RESORT and it can MASK A DEAD OP. For out_sort==”image”
backend_safe.fallback returns the clipped INPUT, so a wrapper whose library call raises on every input looks to evolution / difftest / coverage like a working identity op instead of a failure. Runtime robustness is kept, but the degradation is DETECTABLE: every swallowed exception is recorded in the shared fallback ledger and strict mode re-raises instead. 2026-09-02: the ledger / strict switch moved DOWN into backend_safe so that the 23 other backend files (each with a private _safe) report to the SAME place — before, this module was the only one of 24 wrapper families that recorded anything. The names below are kept as thin aliases for callers and tests that import them from here.
- L812 — LBP encoding. ★Until 2026-09-08
b really did nothing, and method was fixed at 'default' (not rotation-invariant). Measuring on real textures (brick / grass / gravel), for anisotropic materials the amount moved by rotation is 9.64x the distance between materials, and switching to 'uniform' brings it down to 1.72x (examples/poc_real_texture_invariance.py). Without a choice there is no way to lower it, so we assigned b. It is made into a threshold table as the convention for when branches increase along the same axis (not nested ifs). b=0.5 (default) is 'default' as before.
- L1028 — ★Passing a bool array to cv2 makes
cv2.Laplacian corrupt the heap, and the process dies at a later unrelated op (2026-09-05 Fable review; I reproduced the SIGSEGV myself within 100 runs on Windows, exit 127). The facade coerces dtype to the contract, but the direct op.fn path (tests, coverage, evolution loop) passed it through. We coerce to float64 at the family’s entry.
backends_auto.py
- L594 — ★Do not change the canvas (reshape=False) + reflect outside the frame (mode=”reflect”). Angle is -45°..+45° (0° at a=0.5). The original image is folded back into the four corners, so this is not directly suited to uses that want to “fill outside the frame with a background colour” such as deskewing forms (this is a known design decision, not a bug — for details and how to choose, see the docstring of
ops._rotate_img).
- L617 — ★However, keep the return shape on the same canvas as the input. The image in this registry has a contract that it “connects unconditionally between stages”, so changing the shape makes the evaluator fail because it cannot match the target image (measured: the moment the target-size version returned (70,50),
test_evolve_is_reproducible_given_seed failed with “operands could not be broadcast together with shapes (70,50) (64,64)”). So we place the image resampled to Ht x Wt at the top-left of the canvas, pad the margin with 0, and crop the overflow —— the fact that “the image is now Ht x Wt pixels” stays visible as is.
- L1111 — ★2026-09-02: what it returned was the integer pixel coordinates of
np.where themselves, so despite calling itself sub_pix it had no sub-pixel precision. We added refinement along the normal via parabola fitting (the same shared helper as core ops._edges_sub_pix; a same-named op wins last in the registry, so this is what actually runs —— fixing only core has no effect). Measured (a synthetic step edge whose true position is column 20.37, a=0.2): the old implementation returned columns {20.0, 21.0} with mean absolute error 0.500 px, and after refinement {20.324, 20.370} with 0.0228 px (about 22x improvement). The number of points and how connected components are split are unchanged (coordinates just move less than 1 px).
- L1270 — ★At b >= 0.75 it averages over 4 directions (0/45/90/135 degrees). The default b=0.5 is only 0 degrees as before, so existing results do not change by a single bit. Whether it helps depends on a (co-occurrence distance) (poc_real_texture_invariance section 6, 3 real materials): it helps isotropic materials at short-to-medium distances, and helps anisotropic brick only at distance 4 (swing/resolution 3.13 -> 1.54). At distance 1, brick
- L1275 — conversely worsens (0.30 -> 0.56). ★The root cause is that extending the distance collapses the resolution itself, 0.0328 -> 0.0122.
- L1482 — ★2026-09-02: these two shared
{"kind": "zoom"} and were therefore a completely identical implementation, and neither used b (measured: max difference 0.0 for the same input, difference 0.0 between b=0 and b=1). In HALCON the factor version takes two scale factors and the size version takes a target size, which are different things, so we split the kind to match the reality to the names.
- L1555 — ★2026-09-02: the old spec was out_sort=feature / metric=”area”, but the reality was
np.mean(mask) = the area ratio occupied in the image. Since HALCON’s area_center is an op that returns (Area, Row, Column), there was a double discrepancy: (1) it does not return the centre, (2) the area is a ratio rather than a pixel count (= resolution-dependent). A single scalar cannot satisfy the name, so we make it the 1-D vector of the match sort, the same as ncc_locate, and return (area ratio, row, column). Both match and feature are terminal sorts (candidates are identity only), so the genome->op mapping does not move.
backends_decomp.py
- L142 — ★Apply the BLAS thread cap once outside the loop. This is where a square matrix capped at work_max=64 is SVD’d up to 60 times, using most of the decomposition time in this repo (30.7 s per suite run / 31.4 s total decomposition, svd 23,987 times = 98%). A 64x64 SVD is 3.9x slower with 24 threads than with 1 thread —— because the GEMM inside the decomposition is too small and the synchronization cost exceeds the computation (table in the docstring of fsthreads). Wrapping it each time pays the 2.4us of the mechanism 60 times, so we place it outside the loop.
- L206 — ★
ev[0] is the algebraically largest eigenvalue, not the one with the largest absolute value. On a bright ridge the principal curvature is negative, so ev[0] becomes the one with the smaller absolute value, giving the inverted response of 0 on the ridge and 1 on either side (2026-09-05 Fable review, measured [1, .64, 0, 0, 0, 0, .64, 1]). We take the largest absolute value as described.
backends_r3.py
- L46 — ★Until 2026-09-05 it was swallowing exceptions with
except Exception: out = None. At registration an outer backend_safe.guard is applied, but if the exception is erased inside, the outer sees nothing —— even in strict mode no exception is raised and nothing remains in the ledger. This was a miss of the 2026-09-02 audit of “only 1 of 24 families reached the ledger” (Fable’s adversarial review flagged it as the 5th family). Let the exception out as is: the outer guard records it, coerces it to a value matching the sort, and re-raises if strict.
backends_scipy.py
- L198 — ★At lambda >= ~12 scipy throws “boundary conditions did not converge”, and the guard’s fallback was the identity (the old 1+40a made 70% identity for a>=0.3, including the default 0.5. 2026-09-05 Fable review). We aligned the description to 1-11 as well.
backends_typed.py
- L505 — ★Until 2026-09-05 it read
tools/chain_fuzz (not shipped) via sys.path manipulation. It failed in the wheel, and since the build() below silently returned [], the tb_* 143 ops were disappearing.
blob2d.py
- L287 — ★Mind the sign: vertices are ordered as (row, col), so the orientation returned by
_monotone_chain is counter-clockwise (viewing row as x) = clockwise on screen. The inside is the side where the cross product is non-negative (writing <= 0 produced solidity 0 for all objects).
- L587 — ★Erosion alone produces only one side. An object with a smaller label, even when a larger-labelled object is adjacent, keeps itself as the neighbourhood minimum and is judged “interior” (2026-09-06 measured: at the column where 1 and 2 touch, the contour on the 1 side disappeared). Looking at both erosion and dilation gives the symmetric judgment of “there is a different label in the neighbourhood”.
calib.py
- L178 — ★On 2026-09-06 we measured that this gate does not fire on a real camera. On distortion-free synthetic data it works as designed (ratio 3.8e-14 at 0 degrees tilt, 8.6e-10 at 0.05 degrees, both refused). But with realistic barrel distortion k1=-0.18, the planar-homography model no longer fits in the first place, and the ratio sticks around 1.9e-06 regardless of tilt (0 degrees 1.916e-06 / 0.05 degrees 1.935e-06 / 0.2 degrees 2.005e-06).
- L184 — ★Only when two conditions are met together: that there is distortion and that the board moves sideways between viewpoints. With either one alone the gate rings as designed (the separation is the 3 in tests/test_calib.py). And an actual calibration session always has both, since you shoot while moving the board by hand. Nor is it enough to just raise the threshold —— with distortion, the gap between full degeneracy 1.92e-06 and 2 degrees tilt 4.42e-06 is only 2.3x, and no dividing line can be drawn. Therefore: * leave the threshold as is (it works correctly for distortion-corrected points) * return the ratio itself as
orientation_rank_ratio * let the later gate that actually stops things say “tilt the board” (below). Instead of fixing it, we hand the user the material for judgment.
caltab.py
- L188 — ★What this gate does not catch: errors in the intrinsic parameters for a single planar target (especially the fx/fy ratio). A single-plane homography places only two constraints on the intrinsics (Zhang 2000), so a wrong fy is mostly absorbed into the 6 DoF pose being solved here, and the residual can stay below the threshold. Measured 2026-09-05: even setting fy wrong from 500 -> 300 gives RMS 0.90 px on Linux/scipy 1.18 (0.14 px with the correct K). The same input becomes 6.39 px on Windows/old scipy, so it “detects or not” purely by the difference in where the optimization converges. If you want to verify the intrinsics, take 3 or more viewpoints or use a non-planar target. Where this works is inconsistencies that “cannot be absorbed by the pose” (wrong correspondences, a non-planar board).
champion_to_macro.py
- L193 — ★Enforce the headline honesty claim (“a DNA op is added only when it beats the hand baseline on a LOCKED holdout”) — previously this flag was printed but never gated, so a worse-than-hand macro could be registered and then selected by the next evolution. The gate refuses that unless it is explicitly overridden.
- L87 — ★Bit-exactness is not guaranteed (corrected 2026-09-05). The math is independent per row, but
U @ w is a BLAS GEMM, so the reduction splitting and vectorization path change with the row count M, and the rounding can change. Measured: the moment torch was added to CI’s py3.11 job (= the moment a different OpenMP runtime was loaded), the results diverged between chunked and non-chunked. What is guaranteed is numerical agreement (a few ULP), not bit-exactness.
demops.py
- L97 — ★We do not provide the option to fill with the median or the like. Filling creates a plain that does not exist and lets water through without raising an exception. But the size of the effect we record honestly. On the same real data (Tokyo bayfront 1024x1024, 3.83% missing), the max catchment cell count compared across 3 ways: outlet 312,108 (29.8%) / median fill 338,188 (32.3%) / wall 315,023 (30.0%). Filling inflates by about 8%, but the fact that “one cell gathers 30% of the whole” is itself the reality of this terrain (a flat reclaimed land really does converge to one spot). Writing at first, from looking only at the fill, “this figure is a product of filling” was an exaggeration; taking a control shrank the effect. We do not provide a fill option because it becomes impossible to distinguish where the terrain is real and where it is fill, not because the figure changes by orders of magnitude.
- L605 — ★We first noticed this slowness when the sky-view factor for 513^2 took 41.9 seconds in the PoC (examples/poc_dem_terrain.py). The tests used only small grids, so they confirmed it “works” but not that it is “usable”.
- L686 — ★Fixed 2026-09-08 (found by
poc_stockpile_volume). When a line-of-sight sample rounds via np.rint to the target cell itself, that cell’s height gets compared against itself as “intervening terrain”. Since t < 1 the denominator dist*t is small, and (z-eye)/(dist*t) > (z-eye)/dist is always true when z > eye —— so cells higher than eye level were self-occluding across the board. Measured (before fix): a 10 m column on flat ground was returned as “not visible” from 25 m away at eye 2 m, and only a 1 m column below eye level was “visible”. The highest point of a convex solid is always visible from outside, so this is geometrically wrong. We do not count the iterations where the sample landed on the target cell.
- L746 — ★The ledger declares
points = (N, 3). Passing a scalar yields (3,), which conflicts with the declaration, so we always fold to (N, 3) (surfaced by the fuzzer’s TYPEMISS on 2026-09-06; the fuzzer had not been run after adding the 6 geocentric-coordinate ops). When you want (H, W, 3) as a grid, use :func:dem_geocentric_grid.
-
| L795 — ★Inside the evolute the geodetic latitude is not unique -> instead of silently returning an out-of-range latitude, refuse. The evolute of the ellipse x²/a² + z²/b² = 1 is (a·x)^(2/3) + (b·z)^(2/3) = (a²-b²)^(2/3). Only outside the equality is the region where “the normal is uniquely determined” (since the 2/3 power is non-negative, the sign is |
z |
). |
evis_fullseye_bridge.py
- L152 — ★The sky is “infinitely” far (measured: 998 in a world whose animal is 0.3 across), and with the sky in view the 3rd/92nd percentiles straddle it, so the panel collapses to two flat colours — sky and everything-else. depth_max cuts the band at a distance that means something for this body, so the scene gets the colour range instead of the sky.
- L171 (ja) — ★ego_camera(モデル自身の目)でも eye パネルを出す。ここを ego>=0 だけで見ていたので、 ハエの複眼から描いたのに複眼の絵がコマに入らなかった(2026-09-14 実測)。
- L180 — ★drop frame 0: the event panel has no previous frame to difference against, so it is blank by construction. Keeping it makes the first thing a reader sees a black panel, which reads as “the events never fired” (measured: frame 0 has 960 lit pixels, frame 20 has 35,550). The stats below still count every frame that was rendered.
- L189 — ★distances carry the MODEL’s unit, not metres: the fly world is cm/g/s, so reporting “6.96m” for a 7 cm walk is a lie the caller cannot see.
unit names it honestly.
examplefig.py
- L139 — ★
colorize_depth returns float [0,1]. Receiving it with np.asarray(..., np.uint8) truncates every 0.x to 0 and turns it pitch black (hit on 2026-09-06).
- L171 — ★Do not drop the body of the example. It is a pity that the figure does not appear, but the numbers must be shown.
- L210 — ★Do not just hand off to :func:
_to_rgb8 here. That passes (H,W) to colorize_depth, but inside it each frame is normalized individually, so a frame that is all 0 and a frame that is all 1 come out the same colour (caught by a test on 2026-09-09). Only by passing the value range explicitly does the scale become a single one.
- L275 — ★Pillow folds a frame identical to the previous one into a single frame (that time is added to the previous frame’s display time, so the speed of motion does not change). We count after writing and, if it differs from the number passed, record both in the ledger —— so as not to silently pass off “a 72-frame GIF” whose content is 40 frames.
- L339 — ★2026-09-08: when the panel is small the title does not fit, and
annotate_figure_grid (correctly) refuses, so one figure was silently disappearing. A 29×19 core grid or a 24×24 reduced map appears routinely in PoCs, yet the error says “shorten the title” —— the actual fix is “enlarge the panel”. Two people fell into the same hole independently (there is a case where one scene figure on the signboard disappeared), so instead of making each caller write the enlargement, we do a nearest-neighbour enlargement once here. We use nearest neighbour so as not to create values by enlarging (interpolation would create intermediate values that do not exist on the figure, and the pseudo-colour would lie).
examples/acoustic_condition_monitoring.py
- L467 — ★Parabolic interpolation retains a bias that pulls toward integers (because the peak is sinc-like and cannot be fully approximated by a quadratic). We sweep from 0 to 1, measure the bias, and show that it forms an S-curve —— if we stop at “we could read down to the sub-sample”, this bias silently rides along in the result.
examples/annotate_paper_tour.py
- L51 — ★EXTEND: replace text and path with the text and polyline (x, y) of your own figure
examples/blas_thread_budget.py
- L117 — ★This is the key point. 96x96 is not “fast because it is small” — it is a size at which being small is exactly what makes multithreading a loss. Put it outside the loop once (wrapping it each iteration means paying the cost of the throttling mechanism itself 30 times).
examples/blob_split_tour.py
- L98 — ★Measured (honest): a seed also stands on a bar of height 2 < h. blob_seeds uses the residual
f - R > 0 as the seed, but when each component is reconstructed with background 0, a component whose peak height M < h gives R = M - h < 0, so the residual is positive across all pixels of the component and even a 1 px border of background (skimage’s h_maxima rejects with residual >= h). We report without fixing the implementation. Here we drop the bar’s seed and check the “seedless blob” path.
- L129 — ★Measured (honest): the split does not sit on the intersection line — the side of the higher-numbered seed bites in along the valley. blob_split, dilating stage by stage, assigns “a pixel touched by both regions” to the max of grey_dilation (= the larger number), so via 8-connected diagonal chaining the higher-numbered region intrudes several columns along the valley line. Swapping the seed numbers swaps the direction of intrusion too (a bias of numbering, not geometry). We report without fixing the implementation.
- L153 — ★Measured (honest): with textbook h-maxima, the seeds merge into one the moment h exceeds “the prominence of the lower peak (16 - saddle 10.07 = 5.93)”. blob_seeds uses residual > 0 as the seed, so residual = min(h, prominence) > 0 always holds and the lower peak’s seed never disappears at that h. The merge happens when h exceeds “the higher peak - saddle (22 - 10.07 = 11.93)” — the peak it references is the opposite one.
examples/coherence_scanning.py
- L166 — 6) ★ Cross-check against the phase-shifting method # —————————————————————— #
examples/dem_geodesy_tour.py
- L49 — ★Unless the repository root is on the path,
demops is not found (this example does not import fullseye, so the path hook does not kick in).
- L61 — ★EXTEND: replace with the north-west corner of your own tile (this is near Tokyo).
- L131 — ★Honest breakdown: a single Bowring iteration gives 1e-9 m on the ellipsoid surface, but the error grows with height (measured 8e-7 m at 8848 m, 4e-6 m at 20 km). The docstring’s “1e-12 deg / 1e-7 m” are near-surface values and do not hold at stratospheric heights. For terrain use (elevation < 9 km) it is 1e-6 m, and here we set the threshold at 1e-5 m.
- L160 — ★EXTEND: replace dem with real data (row 0 is north). This is a known slope.
examples/dem_terrain_analysis_tour.py
- L46 — ★Unless the repository root is on the path,
demops is not found (this example does not import fullseye, so the path hook does not kick in).
- L59 — ★EXTEND: cell size [m]. For real data, obtain it via dem_cell_size_webmercator(zoom, latitude).
- L158 — ★Honest observation: when there is a no-data cell partway down a slope, its northern neighbour, even as an outlet, does not drain into the no-data but goes south-west (the direction with a finite drop). The implementation is “drain into no-data only when there is nowhere else to descend”, narrower than the docstring’s “allows flow toward no-data”. Here we only print and do not assert.
examples/piv_flow_from_particles.py
- L27 — ★Since it imports a module (pivops) at the repo root, place the repo root at the front so it runs straight from a checkout. Same convention as the other examples. Without this,
py -3.11 examples/<name>.py fails with ModuleNotFoundError (measured 2026-09-09: of the 83 that had no gate to run them, only these 2 of this kind failed).
examples/poc_allsky_cloud_cover.py
- L104 — ★The last 3 are thin clouds (differing optical thickness). Raising the threshold drops them thinnest-first — that is what produces the staircase in Section 4.
- L142 — ★Solid-angle weight. dΩ/dA = sinθ/(f²θ) — the Jacobian of the equidistant projection.
- L524 — ★2026-09-08: “equidistant” came to match the 1-D
create_funct_1d_array (builds a function from evenly spaced samples) — a side effect of making ops1d retrievable via op_find, unrelated to the projection model. The word merely coincides; the gap is not filled, so we rewrote it to check “absence from the projection family” (not to judge by word match).
examples/poc_asbuilt_wall_deviation.py
- L497 — ★What was missing was not tilt but bulge. The quantity predict_bulge returns in closed form as the first-order coefficient becomes, as is, a spurious tilt and a spurious in-plane deflection.
- L555 — ★To the closed form we pass the effective tilt with the portion absorbed as bulge (§6) included. Without it, only the single point at f=0 is off by 1.2 mrad, making the prediction look wrong.
- L660 — ★A floor of noise only. Reading it the same way against a zero-bulge wall yields this.
examples/poc_astro_photometry.py
- L322 — ★ We got it wrong here once: thinking “scale=2 so brightness is also 1/4”, we wrote flux/4 and produced -74.89 %. The conservation law (6.1e-14 above) rejected it. The per-pixel brightness becomes 1/4, but the total sum of a star does not change.
- L423 — ★ We dropped an assert here once: the rms in the table above (one stack, 8 isolated stars) gave good-6-frames 0.306 % vs good-12-frames 0.324 % = 0.947x. This is not a refutation of the theoretical 1.414 — it meant that rms was the sum of “per-star systematic offset” and “noise”, and with 8 samples you cannot isolate the noise alone. As in stage 1, only after accumulating iterations and subtracting the per-star mean does noise alone remain.
examples/poc_barcode_1d.py
- L806 — (d) ★The edge count of measure_pos depends non-monotonically on sigma.
examples/poc_battery_ct_degradation.py
- L316 — ★
sdf_offset is scalar only, so to offset it as a field we warp the grid and evaluate.
- L334 — ★To keep the stack from punching through the can, we locally compress it to the height the deflected end plate allows (in real cells too the electrodes are pressurized and shrink). Without this, at tall gas voids the end layer gets eaten by the can and the layer-count comparison breaks (that is what happened at first).
- L612 — ★Count layers by the “number of rising edges”. Counting by
vol_wall_thickness pairs (rising -> falling), a single extra falling edge just inside the can’s inner surface throws the pairing off and drops even a healthy cell from 17 -> 16.
examples/poc_battery_electrode_tortuosity.py
- L136 — ★Processing not on a public path: a 6-neighbour adjacency graph in voxel space. fullseye has 3-D # connected components (vol_label) and a distance transform (vol_distance_transform), but # no entry point (geodesic distance, transport) for handling “a path passing through the void”. # ————————————————————————— #
- L248 — ★Passing a 64-voxel slice as is gives a panel only 64 px wide, so the title text does not fit and the whole figure fails (examplefig does not give up silently).
- L269 — ★Leaving the solid phase at 0 makes log10(dissipation) negative, so the solid phase is painted brightest (we produced exactly that once on 2026-09-08). We map the solid phase to the bottom 2 % of the void.
examples/poc_beam_modal_video.py
- L629 — ★Collision: at fps 48.5 the aliasing of the illumination lands exactly on f_1 = 3.00 Hz
examples/poc_bev_sensor_fusion.py
- L135 — It is placed. ★This is not decoration: * Putting a face on a cell boundary spills half of the face’s return into the neighbour as noise, dropping the fit rate to 0.5 by discretisation alone. * Putting a face at a cell centre makes the ground truth itself go in or out depending on floating-point rounding (actually hit: the returned column of the side wall fell off the ground truth, and most of the 133 falsely-occupied cells were that). Placing it in between makes neither happen.
h avoids multiples of 0.2 m — to show the height quantization. lx/ly are set to odd multiples of 0.1 m.
- L564 — ★The error is about the world z-axis (= same as place). Writing
R_wc @ rz turns it into a roll about the optical axis, and the reprojection error morphs to 1/5 (hit on 2026-09-07: it came out 0.98 px and did not match the geometric prediction f·tanθ, which is how it surfaced).
examples/poc_bilateral_asymmetry.py
- L585 — ★Keep it in a form that can pass the hole-D gate as is (the margin collapses first, the angle jumps afterward).
examples/poc_bump_coplanarity.py
- L147 — ★A genuine low-order defect (a die-attach void = the centre sinks gently). Deliberately not made exactly quadratic — if it were quadratic, the fit would by definition absorb 100 %, making the question “how much gets absorbed” trivial.
-
| L306 — ★Clip at ±SPEC_UM before passing. examplefig’s diverging colour map normalizes per panel by max |
v |
, so without clipping the colour meaning across the 3 panels does not line up. |
- L445 — 6. ★The harm of over-subtraction —— it absorbs genuine low-order defects # ————————————————————————— #
- L540 — (e) ★surface_form_error via the ledger returns only a PV float
examples/poc_cad_scan_deviation.py
- L434 — ★The ledger’s out adapter truncates the dict to (R, t), so rmse does not get through
- L893 — Chapter 6: ★The defect pulls the alignment —— predicted by projection onto the rigid-body 6-D # ————————————————————————— #
- L1099 — ★Do not add a defect —— if you do, Chapter 6’s datum shift (0.107 mm) becomes a pedestal on the point movement and mixes with “the amount broken by the initial angle”.
- L1252 — ★Producing a “%” for the control group whose ground truth is 0 gives a meaningless huge number from division by zero. Present the area in mm^2 as is, and append % only when the ground truth is meaningful.
- L1263 — ★Do not read the difference of a single run as “it worked” —— vary the seed and compare against the spread
- L1353 — ★An assert that fires once the gap is closed. It actually fired on 2026-09-07, and this line was rewritten: after the note that “cylindrical holes, chamfers, and fillets cannot be built”, plane / cylinder / torus / capsule were added. The note changed the tool, so we record it and move on.
examples/poc_camera_calibration.py
- L150 — ── Calibration (a hand-rolled minimal bundle adjustment. ★ Gap (e)) ──────────────────────────────────── #
- L176 — ★ Gap (d): the image points of camera_calibration are (row, col). project_points are (x, y).
- L304 — ★ Gap (b): reprojection_error does not know about distortion. Even passing the ground-truth values does not yield 0.
- L525 — 2. ★ The main point: the reprojection RMS is nearly the same, yet the fx error differs by more than an order of magnitude
- L533 — 3. ★ The cancellation mechanism: the ratio of fx matches the ratio of Z
- L539 — 4b. ★ An honest record of a loss: with a narrow field of view + 0.30 px noise, the zero-point B that pins the principal point to the image center is more correct than estimating it (a condition where you cannot do better really exists)
- L555 — ★ Gap (c): since the points are distorted, what stopped it was not the degeneracy gate but the later non-finite K gate. We even confirm that its message contains “tilt the board” (added 2026-09-06).
- L563 — 5b. ★ Gap (c3): the closed form is systematically off by the amount of distortion (initial-value only)
- L567 — 6. ★ Gap (b): reprojection_error does not know about distortion -> even passing the ground-truth values, it stays large
- L573 — 7. ★ Gap (a): the intrinsic parameter estimation is not visible from the facade
examples/poc_cell_counting.py
- L853 — ★The smallest h you can specify is 0.05 x max(distance transform). A single large cell in the image is enough to raise the lower bound of h for the whole image (a coupling imposed by the op’s spec).
- L1041 — ★The headline of this PoC. At the place where the bias line crosses 0, the segmentation error is not a valley.
- L1330 — ★Over-merging and missing are different things —— things that stick together have not “disappeared”
- L1358 — ★The optimal h moves with density (it always moves by either the bias criterion or the one-to-one criterion)
- L1361 — (5) ★A point where the count is correct yet the segmentation is entirely wrong really exists: the bias is under 3 %, yet many segmentation errors remain and the one-to-one correspondence is far from the best.
- L1387 — ★The smallest h you can specify rises with the size ratio (a scale coupling imposed by the tool’s spec)
- L1427 — (10) ★Mechanically confirm that the tool’s gap “still exists” (it fails once fixed = a good kind of failure) (a) the distance transform of the evolution op is normalized by its maximum value
examples/poc_change_detection_misreg.py
- L947 — ★A single graph: residual offset vs false positives (the sweep line + the registration-result points)
examples/poc_cold_chain_excursion.py
- L568 — ★The window for finding the peak goes only up to just before the next door opening/closing. If you make it too wide, at large τ it picks up the rising edge of the next pulse and makes it look as though “the cliff never comes” (stepped on this on 2026-09-08 with a 200-minute window: the measured y=53 stretched to 153 minutes).
- L947 — ★Make the line-of-sight direction (the D axis) the width. If you project with (t, y, x) as is, D = time 720, and you only get a thin (H, W) = (60, 12) image.
- L1006 — ★Distinguish whether a “hit” is thanks to the convention or mere chance: perturb each point by ±1 m and count.
examples/poc_colocalization_crosstalk.py
- L355 — ★Prediction of tail loss: the tail of the Gaussian below the threshold T does not enter the region. Of a peak-p point, the in-region fluorescence is 1 − (T − pedestal)/p (the closed form for the volume of a 2-D Gaussian). Pedestal = cytoplasm + background (+ the bleed-in), and p is squashed by the PSF by a factor of σ_ves²/(σ_ves²+σ_psf²).
examples/poc_colormap_readability.py
- L343 — ★The difference readable from a row of steps is Δ + a one-pixel-wide ramp —— forget this and you overestimate the cliff by 2x (I first wrote it that way and got 0.57 vs the measured 0.30)
- L406 — ★Divide by the true gradient. Without dividing, you end up counting “places where the field is steep” as boundaries
- L657 — ★Exceeding the number of colors is rejected by default (this PoC pointed it out and it became fail-closed the same day). Here the goal is to measure “what happens if you cycle”, so we set cycle=True explicitly —— forcing that explicitness is itself the countermeasure.
- L732 — ★Fixed the same day thanks to this PoC’s note. The roster’s criterion was only “monotonicity of lightness”, so cividis—monotonic in lightness but coarse in color-difference steps—was calling itself “safe”. Now uniformity of color difference is also part of the criterion, and cividis has moved to CVD_SAFE.
examples/poc_compound_eye.py
- L301 (ja) — ★PoC の門(tests/test_poc_scripts_run.py)は exit 0 に加えて “PASS” の印字を 要求する(合否を計算したのに捨てる門を防ぐ規約)。以前は “OK:” と書いていて、 台帳に登録した瞬間に「exit 0 だが PASS を印字していない」で落ちた。
examples/poc_crop_phenotyping.py
- L209 — ★Always draw the random numbers up front in the shape (n_plant, NESTED_MAX). If you change how many you draw per leaf count, the random sequence shifts, and increasing n_leaf by just 1 gives a different canopy (2026-09-07: the vegetation coverage stopped being monotonic in leaf count and the cliff could not be measured).
- L525 — ★
grid_coords places the voxel centers (center spacing = span/res, not span/(res-1)). At first I multiplied by span/(res-1) and produced errors of +12 % area and +18 % volume on a sphere —— a unit mix-up “is wrong in a plausible way”.
- L971 — ★Take both the ground truth and the leaf-angle distribution from the very canopy this section is looking at. Reusing the k of the reference condition (7 leaves) shifts the ground truth by the gradient of upper leaves standing more upright.
- L980 — ★The largest plane is not necessarily the ground (once the canopy closes, part of the crown becomes the largest). The version that took the first plane as the ground answered an elevation of 1.69 m (stepped on this 2026-09-07). It only stabilized once we added the rule to take the lowest plane.
- L1007 — ★Control group: apply the same formula to the true normals (which the buffer holds).
- L1136 — ★The axes of
occupancy_grid are (x, y, z). render_volume_projection collapses axis 0 as the line-of-sight direction, so if you want a nadir view, swap to (z, y, x). Calling it without swapping produces a “nadir view that was meant to be a side view” (a silently-wrong pattern).
examples/poc_ct_fidelity.py
- L342 — ★The headline of this PoC. You can see with your eyes where the FBP crosses zero-point A (the horizontal line) and zero-point B. The x-axis is the number of projections (sparse on the left). The x-axis is log —— the crossing happens on the sparse side (12–45 of them), and on a linear axis it collapses to the left edge, making the crucial part unreadable.
- L407 — ★Closed on 2026-09-06. Previously it pinned down the broken behavior = “doubling the detectors improves the mass deficit by more than 2x”. Now it pins two things: (1) mass is conserved in the first place, (2) it does not change with the number of detectors (since n_detectors is the width of the detector, not the fineness of sampling, so as long as the target fits, the added amount only adds empty bins).
examples/poc_ct_void_morphology.py
- L233 — ★Substituting with die occupancy, at coarse voxels a 50 µm-thick die falls between the voxel centers and the reference itself disappears (at 60 µm, phase 2/3, it actually became 0).
- L558 — ★Passing all-nan (nothing could be measured at any phase) to np.nanmean raises a warning. “Could not be measured” is not something to average, so we make it nan explicitly here.
- L634 — ★Drop the nan (unmeasurable points) before plotting —— the line-plot op rejects non-finite values.
- L808 — ★Fires once the gap is closed. It fired on 2026-09-07 and this section was rewritten —— after the note that “esdf accepts a length-3 voxel_size, yet the side that plots its output was cubic-only”, query_distance (and occupancy_grid) came to accept per-axis res.
- L917 — ★The volume fraction is preserved even with coarse voxels; what dies first is the shape metric (the side where the prediction was wrong)
examples/poc_datacenter_thermal_field.py
- L221 — ★2026-09-08: This PoC recorded that there was “no entry point to build a field from scattered points”, so
fs.interp_scattered was added. Points that fall outside the convex hull are returned by the op as a mask, so there is no need to guess with isfinite (it does not break even if fill_value is set to a finite value).
- L862 — ★Break the gate to check whether “false peaks 0” is really counting anything.
examples/poc_dem_terrain.py
- L42 — ★Unless the repository root is on the path,
demops is not found (this example does not import fullseye, so the path hook does not kick in).
examples/poc_dfm_thickness_overhang.py
- L284 — ★Orientation (front/back) is determined by winding order, but the winding order of marching cubes flips with the sign convention of the input. For a closed mesh it is uniquely determined by the signed volume —— decide it by formula, not by eye.
- L379 — ★Do not align the grid origin to the wall face. Cutting at 3.0 makes the wall face land exactly on the voxel boundary, giving an error of 0.000 mm at all 8 sweep points and producing the false conclusion “no quantization happens” (I once wrote that on 2026-09-07). A real mesher will not align the grid to the part’s faces, so use a non-aligned origin.
- L455 — ★Do not sweep h only at points where “T/h is an integer”. At integer ratios the number of occupied voxels is exactly T/h, so errors of 0.000 mm line up and it looks like “no quantization happens” (I once wrote that on 2026-09-07). Sweep h continuously.
- L705 — ★Do not include the exactly-45-degree tilt direction —— the 2349.7 mm^2 back of the plate also sticks to the threshold, and the table of “which orientation is best” gets hijacked by the story of the step.
- L824 — ★An assert that fires when a hole gets filled. It fired on 2026-09-07 and this line was rewritten —— in response to the observation “there is no per-face area”, face_areas / mesh_volume / boundary_vertices were added. Record that it was filled and move on.
examples/poc_dic_strain.py
- L104 — ★Normalize with a single constant fixed from the reference image. Dividing by each image’s maximum makes the overall brightness change with even a slight shift of the maximum under deformation, adding an unrelated error to estimators (Lucas-Kanade / Horn-Schunck) that assume brightness constancy.
- L211 — ★Pin the finding: since deformation is not interpolation but re-rendering of the speckles, an integer shift should match exactly. If this breaks, the “ground truth” from section 2 onward is no longer ground truth, and it becomes unclear whether we are measuring the estimator or our own interpolator.
- L247 — ★Pin the finding: all three must beat by an order of magnitude the zero point that merely answers “nothing moved”. If even one falls below a factor of 10, that estimator is not usable in this scenario.
- L282 — ★Pin the finding. (1) piv’s bias is smaller than lk / hs across the entire sweep. Note: “one order of magnitude smaller” holds only at the single point u=0.37 in section 2 (0.0002 vs 0.0042 = 21x); comparing the sweep maxima it is about 6x (piv 0.0015 / lk 0.0088). Here we pin the max-to-max comparison conservatively at 2x.
- L365 — ★Pin the finding. (1) lk and piv recover 100 µε to within ±30 µε (measured +9.1 / +0.4).
- L369 — (2) ★hs returns only 22 µε for 100 µε —— the above “the sign and order of magnitude come out” does not apply to hs (the regularization flattens the uniform strain itself). Since the claim disagrees with the measurement, we pin the measurement.
- L413 — ★Pin the finding. (1) A 2-degree rotation, under small-strain theory, produces a lie of around -609 µε as expected (the material has not stretched). That is 30% of steel’s yield strain of 2000 µε.
- L438 — ★It does not dull under a uniform gradient (ε linear in x) —— because the least squares of a symmetric window returns the slope of a linear function exactly. To see the window’s effect, a strain field with curvature is needed. The strain concentration at a notch tip is exactly that, so we build in a Gaussian-shaped concentration.
- L484 — ★Pin the finding. (1) The peak of lk decreases monotonically with window width (the limit of spatial resolution itself).
- L522 — ★Cutting and counting one corner shifts by 2x depending on the window choice. Use the average over all windows.
- L577 — ★Pin the finding: the bias decreases monotonically as the speckles are made thicker. The lk bias seen in section 3 is not a property of the estimator alone; undersampling of the speckle makes up half of it. If this stops being monotonic, one pillar of the “0.01 px” claim collapses.
examples/poc_die_tilt_tsv_overlay.py
- L167 — Grid extent. ★Unless the tail of the erf (±4σ) is included, on a tilted die the outer-ring vias get cut differently at each z, producing a false tilt.
- L241 — ★vol_label via the ledger, unlike the docstring, returns only labels (the n of
(labels, n) is dropped. section 9 (f)).
- L297 — ★Do not subtract MU_SI here. Outside the via the probe passes through air (0), so the raw value is directly proportional to the material’s occupancy. If you subtract and clip, the gently sloping edge collapses to 0, and the length goes 100.0 -> 98.1 µm (-1.9 %).
- L484 — ★Subtract the control group to extract only “the part the tilt added” (canceling the estimator’s systematic error).
- L634 — (f) ★The same op returns different content in its return value depending on the calling path.
examples/poc_dimensional_inspection.py
- L521 — ★Can we trust the rms —— adversarially move just one point outward.
- L1553 — ★On 2026-09-06 the “buried” state was resolved. Previously it was
n_reach == 0 (pinning that it does not reach). Now we pin that it does reach.
examples/poc_document_scan.py
- L271 — ★Applying sobel_dir directly to a binary mask quantizes the gradient direction to 0/90 degrees, and the one-point-one-vote directional Hough collapses onto those two lines (measured: 2 of the 4 lines are exactly 0.00 / 90.00 degrees). Blur first, then measure the direction.
examples/poc_fabric_defect.py
- L83 — ★The mask areas are deliberately kept comparable. The combined AUC is close to an average weighted by the number of positive pixels, so if one were an order of magnitude larger, “combining hides it” would not occur.
- L119 — ★The mask radius is set individually as a multiple of σ —— to equalize the areas. If the areas differ by an order of magnitude, “the combined AUC becomes the AUC of the larger area”, and what this PoC wants to measure, “combining hides it”, gets swapped for the different story “the larger area wins”.
examples/poc_fiber_orientation.py
- L376 — Section 2. ★★The naive average breaks with a 180-degree period # ————————————————————————— #
- L469 — Section 4. ★★Without choosing weights, the orientation degree always comes out small # ————————————————————————— #
- L499 — ★Because angle is a periodic quantity, coloring it with colorize_depth makes 0 degrees and 179 degrees opposite colors. fullseye has no name for a cyclic LUT, but passing (cos2θ, sin2θ) to colorize_flow gives a double-angle cyclic LUT (see “tool gaps” (f) at the end).
- L693 — ★The name “coherence” exists, but it is the two-signal coherence of signal processing (a different thing).
- L724 — (e) ★Two members of the same family disagree in their input checks.
examples/poc_fly_vision.py
- L623 (ja) — ★ラミナ段(DC 落とし)を省くと相関が落ちる、を固定する。落ちなくなったら fly_emd_response の側で DC が消えている(仕様変更)なので、この対照を見直す。
- L650 (ja) — ★PoC の門(tests/test_poc_scripts_run.py)は exit 0 に加えて “PASS” の印字を 要求する(合否を計算したのに捨てる門を防ぐ規約)。
examples/poc_focus_stacking.py
- L491 — 1. The picture works. ★The threshold is +3 dB — real semiconductor images are mostly smooth metal (die, leads), which is already in focus in a single frame, so the AIF gain is smaller than with a synthetic pattern that is high-frequency everywhere (the honest picture of the shop floor; the old full-texture field gave +14 dB).
examples/poc_forensics_roc.py
- L396 — ★Gap (a) is a “constant map”, so drawing it makes reading the numbers unnecessary.
- L523 — ★The headline of this PoC. The curve of the strongest detector drops to the diagonal (and below) with a single press of the save button.
- L677 — (4) ★Gap (a): the op’s argmin readout is essentially a constant map for a re-saved image. AUC is exactly 0.5 = indistinguishable from random.
- L704 — (9) ★Gap (b): 8-pixel grid. It only guesses right when the difference is a multiple of 8 (no re-saving).
examples/poc_gear_tooth_metrology.py
- L199 — Imaging-system blur. ★The 2-D Gaussian blur has no entry point to pass σ directly, so we back-compute σ = 0.3 + 2.7 a from the evolution op’s knob a and pass that (see “tool gaps” (c) at the end).
examples/poc_geodetic_height_frames.py
- L408 — ★A round trip cannot rule out “both wrong in the same direction”. Cross-check against an independent implementation.
-
| L437 — ★Prediction (printed before measuring): the slope is atan |
∇H |
. Using h it becomes atan |
∇H+∇N |
. |
- L464 — ★Split the max difference between prediction and measurement into ‘model error’ vs ‘discretisation’. Refine the cells.
-
| L584 — ★Prediction (closed form): the downhill direction turns by more than 90 degrees ⇔ ∇H·(∇H+∇N) < 0 ⇔ |
∇H |
^2 + ∇H·∇N < 0. Compute the rate before measuring. |
-
| L644 — ★The second (and the real) closed form. Since the line of sight is drawn through h at both ends, the linear part of N rides equally on both the line of sight and the ground and cancels. What remains is the amount N departs from the chord = |
N’’ |
d^2 / 8. Here N’’ is 2C(cos^2θ - sin^2θ), so |
N’’ |
<= 2C. |
- L1106 — ★Only for
vertical does op_find return 5 hits. Not one of them is relevant (stem matches like boundary_vertices) —— never claim it ‘exists’ from the count.
examples/poc_interferometry_step.py
- L159 — 3) ★Repeated measurement — separate bias from spread # —————————————————————— #
- L202 — 4) ★Comparison with the zero point (the max sample of the envelope) # —————————————————————— #
- L274 — 6) ★Noise sweep — where measurement breaks down # —————————————————————— #
- L314 — ★A small spread is no evidence of correctness
examples/poc_leak_localization.py
- L591 — ★Test of prediction C —— vary the leak position finely to scatter the fractional part
- L726 — ★Control group —— swap only the reflections left/right. If the direction of the bias reverses, we can say the cause is ‘the farther joint determines the direction of the bias’.
examples/poc_lidar_terrain_change.py
- L406 — ★The area of cores that could not be measured contributes nothing to the earth volume. Also return the value divided back by the effective rate —— without dividing back, you take the ‘silently missing earth volume’ for the correct value.
- L694 — ★A number close to the true value is not necessarily ‘correct’ —— count the two opposing errors separately
- L823 — ★When there are too few valid cores, do not treat the LoD as ‘measured’ (the standard deviation of 2 points is a number but carries no meaning).
- L826 — ★If you decimate here, C2C ends up measuring the ‘post-decimation point spacing’ and the density dependence vanishes (when I first wrote it aligned to 6000 points, it came out a constant 0.42 m at every density).
- L946 — — ★ Change vanishes exactly by the amount you align away ————————————– #
examples/poc_lightfield_depth.py
- L594 — 2b. ★ Gap (d): the docstring says 0-d but it is actually (1,)
- L610 — 6. ★ Gap (a): the default linear pulls 1.15 toward 1.0, cubic does not
- L634 — 10. ★ Gap (e) was closed on 2026-09-06. It has been rewritten toward pinning the closed state (previously it asserted that ‘a warning is raised’).
examples/poc_livestock_body_volume.py
- L1032 — ★3 cameras and 6 cameras give exactly the same set of tangents (in parallel projection two opposing cameras coincide)
- L1040 — ★An odd 13 cameras beat an even 16
- L1054 — ★A 3-D convex hull is no substitute for the ‘convex hull of the cross-section’ (it misses the chest girth by a wide margin)
- L1057 — ★Doubling law: the chest-girth error doubles with body weight (the residual is a 2nd-order term)
examples/poc_machine_condition_fusion.py
- L184 — Heat generation [W] of (coupling, bearing A, bearing B, whole machine). ★Normal, unbalance and looseness are made deliberately identical —— 3 modes that are fundamentally indistinguishable by heat.
- L202 — ★As hot as the bearings. The only difference is the spread (both bearings + whole machine).
- L1028 — ★2026-09-08: here we had hand-written numpy’s rfft —— because we read it as ‘no entry for a one-sided amplitude spectrum in the ledger’, but
fs.spectrum was there all along (it just did not show in the ledger). This is a case of deciding ‘it does not exist’ after looking at only one tier, so rewrite it to use the op.
- L1162 — ★2026-09-08: here we had written ‘no spectrum in the ledger’, but
fs.spectrum was there from the start (dsp’s 1-D tier). What was missing was only ‘showing in the ledger (fs.ledger)’ and ‘the per-op notes’; this PoC pulled from only one tier, decided ‘it does not exist’, and hand-wrote numpy’s rfft. Now that ops1d is wired into the ledger, both can be looked up.
examples/poc_mesh_quality_repair.py
- L602 — ★Show it saturated. The raw difference is at most %.2f mm, and painting it as-is makes 99 %% of the pixels 0, a pitch-black ‘it ran but nothing shows’ figure.
- L816 — ★Plot log-log. On linear axes the error collapses to a single point on the coarse side, giving a figure where the slope (= error law) cannot be read at all (I once plotted it that way on 2026-09-07).
- L832 — ★Overlaying the cumulative distributions as-is crushes all 4 above 0.9 and nothing is readable. What moves is the upper tail, so put quantiles 0.5–0.99 on the x-axis and plot ‘the curvature at that quantile’ on the y-axis (the upper half of the inverse cumulative).
- L568 — ★The measurement is slower than that. The fraction of grain-boundary pixels actually erased on the mask, f_eff, is smaller than f (the blur leaks the neighbouring black into the 1 px at both ends of the gap, and the local threshold picks it up), so compare against the prediction re-derived with f_eff, ΔG0 + 6.64 log10(1-f_eff).
examples/poc_multibeam_bathymetry.py
- L518 — The number of partial angles that synthesise the echo. ★Setting this to 61 makes, at 70 degrees, the arrival times of adjacent partial angles 330 µs apart, wider than the 64 µs pulse width, so the envelope becomes a comb and amplitude detection picks up one tooth (the detection offset came out as -1131 µs). It is more correct to build a histogram of the arrival-time density and convolve it with the pulse.
- L546 — ★Do not clip the lower bound at 0 —— the nadir beam then becomes one-sided and the illuminated band halves (stepped on this once, with the footprint coming out at half).
- L703 — ★Divide the x-axis by the beam’s own echo length. Overlaying in raw µs lets 70 degrees (21 ms) monopolise the axis, collapsing nadir and 45 degrees into a single vertical line.
- L706 — ★
plot_series rejects points outside xlim (because they stick to the frame and look like real data). Clipping is the caller’s job, so clip first.
- L1125 — ★Do not look at the middle of the overlap —— there both survey lines have the same swing angle, so the same error rides on both and the difference goes to zero. Take the maximum over the whole band.
- L1196 — ★Make the y-axis height (= −depth). Plotting depth as-is flips top and bottom, making a ‘smiling’ shape look like a ‘frown’.
- L1267 — ★The y-axis is −depth. Plotting depth as-is gives an upside-down figure with the sea surface at the bottom and the seabed at the top.
- L1301 — ★
op_find matches on partial stems, so even when the count is non-zero the contents can be irrelevant (“footprint” → sk_median_disk). Look all the way to the top-level name before saying ‘it does not exist’.
- L1428 — ★The cliff of the all-paths case is earlier than predicted. The difference is the bias of amplitude detection (a quantity absent from the closed form)
examples/poc_nuclei_ploidy.py
- L686 — ★There really exist rows where two opposing failures cancel and masquerade as ‘exactly the true value’
examples/poc_pallet_load_utilization.py
- L232 — ★Deck points float up to +3σ from noise, so cut them with a floor threshold. Without it, even a load with zero overhang gets a spurious 0.006 m3 of “overhang”.
- L479 — ★When g = w exactly, it comes down to “whether the grid happens to line up”.
examples/poc_panorama_drift.py
- L108 — ★Gap (a): none of the following 4 appear in the fs facade or in fs.op
examples/poc_particle_sizing.py
- L213 — ★With only a single seed, the ups and downs of this curve become just noise. Use 4 seeds to separate the mean from the spread before saying it “crossed over”.
- L428 — ★Control group —— match only blobs that are neither merged nor split, one-to-one against the very particle that blob images. If the ground-truth side is all particles, the selection bias that “bigger particles merge more easily” creeps in and becomes indistinguishable from sampling bias (I first wrote it that way and got it wrong).
examples/poc_particle_tracking.py
- L702 — ★The return is not a mask but (N, 3) (z, y, x) coordinates (the 2-D
local_max / sk_local_maxima return an image, so the family is inconsistent. Section 10 gap (g)). At first I counted with count_nonzero and got the order of magnitude wrong.
- L777 — ★To fit 3.4× up and 0.93× down on one plot, the vertical axis is the log10 ratio. 0 is “exactly the ground truth”. Kept linear, downward deviations get crushed and become invisible.
- L792 — ★Overlaying the raw MSD, the 4Dτ line dominates everything and the differences are invisible. Taking the ratio divided by the ground truth, the departure from 1.0 (= how it breaks) can be read from the shape.
examples/poc_photoelasticity.py
- L160 — ★Pin the finding: this is an exact cross-check against fullseye’s Mueller op, agreeing to machine precision even sweeping δ once around in 15-degree steps and θ over 5 values (measured 2.2e-16). If this loosens, what Section 3 onward measures is not the “readout procedure” but a bug in the op.
- L181 — ★Pin the cross-check of the stress field itself too. If the integrated force does not match the load it is not the “ground truth”, and the central value should be algebraically identical to the closed form 8P/(πDh).
- L207 — ★Pin the level of the zero point. Every subsequent “N×” uses this 1.09 MPa as the denominator, so if it moves the meaning of the comparison changes.
- L231 — ★Pin the finding: the naive procedure of reading only integer fringes from a single dark-field image cannot even beat the zero point by 2×. Because the resolution is rate-limited by the fσ/h = 1.78 MPa step. The contrast with Section 4’s phase shift (whose error drops to machine precision) is the backbone of this PoC.
- L286 — ★Since we invert from the same intensity equation with zero noise, θ should come back exactly (the algebra that produces 4θ from the 4 plane-polarization images is itself the inverse map).
- L308 — ★Pin the finding. (1) The agreement exceeds 95 % but never reaches 100 %. The rest are pixels sign-flipped by the (δ,θ) ↔ (-δ,θ+90°) ambiguity, which cannot in principle be removed by a single measurement at one wavelength. Pin the finding as-is: neither “nearly matches” nor “fully matches”.
- L371 — ★Pin the finding. (1) There is no depolarization (the Stokes magnitude is exactly 1). This is the basis for Section 5’s claim that what drops in the modulation is not the light level but the phase sensitivity.
- L377 — (2) ★★The measurement says the opposite of the naive expectation that “passing a mask fixes it”: no mask 97.0 % / excluding undersampling 97.1 % / excluding low modulation as well drops to 81.9 %. Because removing the low-modulation pixels fragments the region and skimage’s unwrap picks a different 2π offset per island. “Both can be excluded by a mask” is correct as a forecast but wrong as a prescription. Pin the measured value.
- L442 — ★Pin the finding. (1) With neither noise nor quantization, δ comes back exactly from the bright-field/dark-field ratio.
- L445 — (2) ★The error from 8 bit quantization “alone” is the same order as the error from noise σ=0.002 alone (measured 0.00277 vs 0.00305). The camera’s bit depth weighs as heavily as noise.
examples/poc_pigment_unmixing.py
- L860 — ★The very basis for “do not collapse into a single number”. Within the same row, 1.000 and 0.013 sit side by side.
- L1082 — ★Record the failure to win in the figure too. Not a single reconstruction comes below the zero-point line.
examples/poc_pipe_wall_loss.py
- L423 — ★For the sound region, choose a “z where not a single defect falls”. At first I wrote z=20..60 as the sound region, but that was right above the bottom-of-tube corrosion (wall thickness 4.5 mm).
- L471 — ★r_in/r_out are in pixel (voxel) units. Passing them in mm samples outside the field of view and makes the return all 0 (silently. At first this produced a pitch-black figure).
- L817 — ★It is normalized per panel, so clip to the same range before passing (without clipping, only E0 gets painted at ±4 mm and the others at ±1 mm, and they can’t be compared).
- L1040 — ★Rings when the gap is closed. It rang on 2026-09-07 and I rewrote this section —— following the note that “passing in mm returns all 0 with no exception”, it became fail-closed when the ring is outside the field of view. Record that it changed from returning empty and staying silent to rejecting and telling.
examples/poc_print_registration.py
- L151 — Halftone screen ruling [lpi] (a conventional value in commercial printing). ★Deliberately avoiding an integer ratio: at 1200/150 = 8.00 px every halftone dot falls at the same fractional position, the sampling phase aligns and the compositor produces artifacts (measured, the centroid jumped by 1.4 px per fractional offset). In real scans, too, the resolution is almost never an integer multiple of the screen ruling.
- L405 — ★The ledger’s port discards info to match the declared out type, so use
.raw (a pitfall documented with measurements in the comment of fullseye/init.py).
- L855 — ★On the FM side, do not narrow the search range (narrowing doesn’t change the result, but it forecloses the excuse that “AM’s aliasing is due to the search range”).
- L1242 — ★A point where the two-stage broke is always a point where the coarse exceeded the cell radius (pin the inclusion relation)
- L1277 (ja) — ★2026-09-13: ‘lattice’ だけ例外を 1 つ許す。flyvision 族の
fly_hex_lattice(複眼の六角格子)が この語を含んで CI で鳴った(run 34751219513)。あれは網点の格子ではないので印刷の穴は 残ったまま —— 例外は名指しで 1 件に限り、それ以外が現れたら今までどおり鳴る。 「語で引く穴の固定」は、無関係の族が同じ語を使った瞬間に偽陽性になる、という実例。
- L1316 — ★Add noise to the reference too —— with a zero-noise image, star_detect gives “0 stars” and a ValueError (which is itself a correct fail-closed).
- L1339 — ★2026-09-08: Following this PoC’s note, I fixed the op side. I wrote “cannot be used on repetitive structures” with measured numbers in the docstring, and made it return the runner-up peak / top peak of the vote as
vote_margin. This number can distinguish two cases that the approval rate cannot.
examples/poc_print_warpage_risk.py
- L364 — ★A newly born layer is placed “on the surface that is already warped at that time” (element birth is done in the deformed configuration). Forget to initialize this, and only the later-grown layers stay at zero displacement, and the warp measured by column average becomes 1/4 (stepped on it 2026-09-07). The mechanics (K and f) are on the nominal grid, so they are unchanged.
- L808 — ★The neck vanishes entirely. The part splits into two, so it must not be solved.
examples/poc_pv_thermal_survey.py
- L381 — ★MOD_SHELTER is a module that is sound but not exposed to wind. In Section 3 it turns into a “fault” under the whole-average criterion.
- L482 — ★Decide the module number by area fraction per number. Rounding the average of the numbers turns boundary pixels into a neighboring number (or 0) and breaks the per-module processing.
- L711 — ★The cost of the module median —— blind to a whole-module anomaly
- L1169 — ★
apply_cmap normalizes by that array’s min/max if vmin/vmax are not passed (making the color’s meaning change per condition), so always pass them.
examples/poc_real_coin_metrology.py
- L136 — ★Even if the counts match, you are not necessarily counting the same thing. Verify that one circle fits exactly into one component (one-to-one) —— without this, “24 = 24” holds even by chance (one blob of two stuck together + one piece of garbage, still 24).
examples/poc_real_deblur_honesty.py
- L199 — ★What we protect is not “which one wins” but that the winner differs per metric. Fix the method name, and it becomes a gate that fails merely because the implementation improved.
examples/poc_real_defect_floor.py
- L156 — Amplitude step. ★This itself is a knob. If coarse, the limit rounds to the same grid point, and one misreads a difference created by the step, like “the larger σ, the wider the gap”, as real (2026-09-09; at 34 levels the median of σ=1.5 and σ=3.0 both rounded to 3.20).
examples/poc_recycling_sorting.py
- L520 — ★Before the sweep, form a prediction from the algebra and print it.
examples/poc_registration_basin.py
- L656 — ★When the user explicitly passes
estimate_normals, thinking “but the normals do exist”. This is the remainder of the gap, 14 orders of magnitude worse than the default.
- L836 — ★Gap 1 was closed on 2026-09-06. This assert has been rewritten to pin the closed state (previously it pinned the broken state:
d_fixed < 1e-6 < d_default = broken). If the breakage returns, this fails.
- L847 — ★Gap 2 was closed on 2026-09-06. Previously it was
< 0.9 * len(ka) (pinning the broken state). Now it pins that the default gives an exact match.
examples/poc_rotation_invariance_audit.py
- L115 — ★HALCON-style region moment invariants. Different from
moment_invariants for 3-D point clouds (choosing by name alone will demand (N,3) and fail).
- L208 — ★Relative variation loses meaning when the denominator is near 0. For near-circular shapes the true value of Hu[1] is near 0, so silently reporting it in % turns into “off by 30 %”.
- L220 — ★Where the prediction was wrong. When writing it I thought “interpolating the grey and re-thresholding is rougher”, but for the perimeter it was the opposite.
- L262 — ★Since the background is monochrome, the contour is drawn in a saturated color. Grey has no saturation, so a saturated color is distinguishable from any tone by hue – more reliable than an inverted color, and it is instantly clear that “this is an overlaid line”. Inverted colors come into their own when the background is colored and “any chosen color could collide”.
examples/poc_safety_clearance.py
- L114 — ★The torso is built by placing two capsules side by side. A single cylinder makes the cross-section circular, and the shoulders (±0.19 m from the trunk center) fall outside the torso’s shadow – the real torso has a flat cross-section 0.50 m wide / 0.30 m deep, and an outstretched arm is hidden by the torso when seen from behind.
- L126 — ★X0 and the speed are chosen so that “the true separation distance stays positive in every trial (no contact)” and “it stays in the danger band long enough” – walking fast passes through the danger band in a few frames, leaving too few samples to count missed detections.
- L673 — ★If you vary the density while occlusion is left in, the occlusion bias (+0.12 m) rides on every row and hides the effect of density. The control group’s job is to turn off one factor at a time.
- L683 — ★With a single draw of noise and decimation, the miss rate swings by a few %. Run it 3 times and average.
- L840 — ★Evaluate row by row in bulk (a per-cell Python loop would run 15000 times).
- L1079 — ★Volume ops are (depth,row,col). grid_coords is (nx,ny,nz), so transpose it.
examples/poc_scan_to_bim_asbuilt.py
- L658 — ★Applying trim keeps selecting only “the well-fitting points” and falls into another solution with RMSE 0.13 mm (measured: the pulled-in angle is 0.17 mrad at trim=0.9, 0.62 mrad without trim). In as-built inspection the defect itself is the large residual, so trim throws the defect away.
- L950 — ★The headline claim in one image: an intact ceiling appears tilted purely from how it is aligned
examples/poc_sea_ice_concentration.py
- L232 — 2. ★Zero baseline vs linear mixture decomposition # ————————————————————————— #
- L252 — 3. ★★The blob size (perimeter) determines the bias # ————————————————————————— #
- L291 — 4. ★★The bias sign flips with closeness (cancellation point) # ————————————————————————— #
- L353 — 6. ★When the endmember is off by 5 % # ————————————————————————— #
- L380 — 7. ★★Third component (thin ice) # ————————————————————————— #
- L490 — (b) spec_unmix did exist (★checked 3 tiers before writing “not present”)
examples/poc_search_sweep_width.py
- L829 — ★The way shape matters differs by search type. Match the sweep width and compare only the curve shape.
- L869 — ★Plot the miss rate 1-P. P itself sticks to the top-right and hides behind the legend box, invisible (I actually hid it once and noticed). Decide the figure after checking whether it “can be read” – even if the numbers are right, a hidden plot conveys nothing.
- L1089 — ★Reproducibility check: since both the seed and the frame count differ from §3, how much it moves under the same conditions.
- L1266 — ★That it exceeds the zero baseline (with the false-positive rate matched). The gain is modest – “even the zero baseline reaches 174 m” is the finding of this section, so that is what gets pinned.
- L1272 — ★A missed prediction: subtracting the global background is an affine transform, so effectively the same as the zero baseline
- L1286 — ★A missed prediction: with the measured p, the parallel search does not reach 1.000 at C=1
- L1290 — ★Shape matters only for the parallel search: with the sweep width matched, random agrees while parallel splits
- L1293 — ★A missed prediction: the flat curve was supposed to be stronger, but was weaker instead (because of its long tail)
- L1296 — (6) ★Doubling W and doubling t are equivalent
- L1304 — (8) ★Watchdog: false positives concentrate directly below. W moves a lot with the threshold alone
- L1322 — ★The gate on the filled-in side (2026-09-08). Since a Japanese-text tier was added to op_find and domain-neutral descriptive terms were written into star_detect’s docstring, it pins that it ranks near the top for Japanese queries. If it regresses, this fires.
- L1327 — ★Only “point detection” still does not surface – the single character “point” inevitably appears in the descriptions of contour ops like cv_canny / frei_amp too, so ties line up and push it out. It does not hide the limitation that the Japanese-text tier only helps when “words of two or more characters take effect”.
examples/poc_solar_el_inspection.py
- L366 — ★The calibration line is also passed through the same imaging system (blur). A calibration line pasted without blurring responds 2.4x stronger than a real crack and pulled the cliff toward the thick side (stepped on this on 2026-09-07).
examples/poc_solar_limb_darkening.py
- L317 — 2. ★Zero baseline (50 % method) vs max gradient vs attenuation model # ————————————————————————— #
- L367 — 3. ★★Sweeping the attenuation coefficient u – it bends rather than scaling proportionally # ————————————————————————— #
- L391 — ★Control group – with the blur turned off, all that remains is the geometry (the position of the 50 % surface)
- L427 — 4. ★★The sign of the blur’s effect changes with the threshold (cancellation point) # ————————————————————————— #
- L488 — 5. ★Black spots – 3 % outlier points move the radius # ————————————————————————— #
examples/poc_star_astrometry.py
- L264 — Image synthesis (★ gap: fullseye has no public op that places a star at specified coordinates) # ————————————————————————- #
- L1243 — ★ “small per run” and “small in aggregate” are different claims.
- L1348 — ★ The bias of “uniform/isolated” being 0.0000 is a given – the plate solution was fit to those 24, so least squares drives the mean of the residuals to 0. To see the error on unused stars, leave one out at a time and re-solve.
examples/poc_stockpile_volume.py
- L698 — ★The winner flips depending on the yardstick: volume uses a horizontal base plane, the centroid uses a plane fit
- L714 — ★A prediction that missed: interpolation is not under- but overestimating
- L717 — ★Cancellation: with the interpolated perimeter the error looks small, and with only the visible points it comes back
- L726 — ★A gap in the tooling. This spot will fire once dem_viewshed is fixed (that’s the intent)
- L728 — ★2026-09-08: the op was fixed on the strength of this PoC’s finding, so being visible now is correct. We pin that it matches our own line-of-sight test and is close to the closed form (it will fire again if it breaks).
examples/poc_strain_history.py
- L507 — ★Closed-form prediction. Central = (w²-1)/24 x d²(velocity)/dt² (the blunting from smoothing), causal = returns the velocity delayed by (w-1)/2.
- L578 — ★Do not make a plot that overlays the histories themselves – truth, cumulative, and direct are indistinguishable to the eye (the error is 0.1-3 % of the truth), and it becomes a plot that merely looks “well matched”. Only produce plots where what was measured is visible.
examples/poc_structure_4d_deterioration.py
- L349 — ★Occlusion is judged by the design shape (
p_nom). If degradation of a few mm to a few tens of mm pushes the surface inside the self-occluding box, the deepest part of the defect goes entirely unmeasured, creating the false scene of “the deeper the defect, the less visible” (hit on 2026-09-07: the core of the defect trough at -21 mm all went NaN).
- L437 — ★The normal of
fit_plane_3d has an arbitrary sign. Align it to the true outward direction (on the scanner side).
- L507 — ★Going through the ledger returns only the declared out type (pose), so receive everything via
.raw.
- L696 — ★Actually try “if differing density is the problem, then just make it uniform” (voxel_grid_downsample)
- L1257 — ★Count the observable information content itself from the point cloud (the diagonal of the normal equations)
- L1299 — ★First take the floor of the measurement method itself – just measure twice with no degradation and no pose error.
examples/poc_surface_roughness.py
- L272 — ★The truth is defined only after declaring the band. Not the roughness component itself, but “the roughness component after cutting at λc” is the truth. If you make this the raw rough_true, even measuring by the correct procedure is off by -23%, and that 23% mixes with the sampling error. There is no “roughness truth” that does not include a band – this is also the claim of Section 2.
examples/poc_template_tracking.py
- L93 — ★ Gap (a): there is no public op that returns a correlation map, so we borrow a private one. Use it only after verifying in Chapter 0 that it matches the public op
fs.op.ncc_locate.
- L326 — ★ Gap (d): a public op would silently return [0,0,0] here. Return an explicit failure instead.
- L1138 — (2) The zero point has a floor – quantization of integer coordinates (★ gap b)
- L1168 — (9) ★ Theme: the confidence’s strengths and weaknesses reverse with conditions
- L1172 — ★ The cliffs each is good at are opposite = you cannot pick either one as the confidence
examples/poc_thermal_radiometry.py
- L507 — ★Forward is direct integration, inverse is a calibration table. Round-tripping through the same table trivially yields error 0 and does not count as measuring the floor.
- L528 — ★Case-0 being exactly 0 is because 350.0 K happens to land on a table node. Move off the node and the interpolation error shows – calling 0 the floor is a lie.
- L757 — ★The x-axis is the rise above the surroundings. Left as T_obj, the divergence collapses into a single vertical line at the left edge, and the crucial “where it jumps from” cannot be read.
- L767 — ★
plot_series rejects points outside the frame (because they stick to the frame and look like real data). The caller clips the diverging side first.
- L821 — ★The x-axis is the absolute Δε. Plotted as relative Δε/ε the three curves overlap exactly (because ε drops out of the equation, per §2) – the plot says nothing.
- L1154 — ★What the guard band uses is the upper overhang. Since what we want to assert as a pass is that “the truth is not above the threshold”, we clip at the upper end of the interval. Using the lower off[0] clips too shallow (by however much the distribution is right-skewed) – wrote it that way once and noticed because the false passes did not decrease.
- L1257 — ★For the same mix-up, on the ε=0.10 surface L_obj drops negative and raises an exception. In other words, “halt or fail silently” is decided not by the mix-up but by the scene.
- L1331 — ★Make the heat source a flat plateau. As a peak, “the bolt and its surroundings at the same temperature” does not hold, and you cannot separate whether the apparent trough is due to emissivity or to temperature.
- L1378 — ★The correction removes the bias but multiplies the noise by 1/ε. That is why only the bolt is grainy in figure (d).
- L1450 — ★
op_find matches on partial stems. blackbody returns 4 hits, but their contents are morphology such as cv_blackhat and have nothing to do with thermal radiation. Reading “it exists” from the count misses. Say it only after looking at the leading name.
- L1600 — 3. ★A prediction that missed: the absolute error is larger at higher temperature
- L1602 — ★Even changing the yardstick, the emissivity error does not diverge with the rise ratio (it plateaus in Δε/ε)
- L1605 — ★What diverges is the reflected apparent temperature (the smaller the rise, the more it jumps)
- L1618 — 6. ★★Coverage rate. At the floor (ρ=0) both RSS and MC are 95 %; adding correlation makes RSS drop
- L1622 — ★The MC side settles at 94.4-94.6 % (not exactly 95 %). The interval ends are set by percentiles over 40000 trials, so there is sampling error, and in reality quantization is mixed in too. Say “MC hits” including all of that.
- L1638 — 7. ★The misses lean to one side (symmetric ±k·u misses a skewed distribution)
- L1642 — 8. ★★guard band: false passes are ignore > RSS > MC, false fails the reverse
- L1662 — ★The correction removes the bias but in exchange multiplies the noise by 1/ε (close to the ε ratio of 9.5)
examples/poc_thermography_ndt.py
- L61 — ★Take the observation time long enough — beyond the healthy part’s t* (6.8 s). Too short and the healthy part’s knee goes outside the window, and TSR answers the healthy part as “the depth at the window edge” (in practice it stuck at 2.82 mm).
- L126 — ★This part alone is an approximation. Since the 1-D solution has no lateral diffusion, at each time we blur in-plane with a Gaussian of diffusion length σ(t)=√(2αt). The physical scaling law is correct, but it does not satisfy mass conservation at the boundary.
- L142 — The range over which TSR searches for t*. ★Excluding the ends is not decoration —— the 2nd derivative of a high-order polynomial always blows up at the ends (Runge). Without it the argmax sticks to the first or last frame, and depth sticks to the 2 values at the window ends (measured, 2026-09-06). We swept degrees 4–11 and settled on 8 (at 4–5, depths beyond 1.5 mm stuck to the ends; 8 and above give the same answer as 9/11).
- L177 — ★Rounding t* to the grid step quantizes depth into staircase steps (with 64 points, 5 % steps). We fit a parabola to 3 points to recover the sub-grid position of ln t.
- L235 — ★Pin down the observation. This is a near-zero sanity check, so if it breaks the implementation is broken.
- L249 — ★The bias of the estimator itself. Without passing through any image, we apply
tsr_depth to an exact 1-D curve. The error here is the “floor of the polynomial fit,” and only what remains after subtracting it from the deviations in Section 3 onward is the contribution of lateral diffusion and noise.
- L267 — ★Pin down the observation: the floor is not zero but small. We bound it on both sides —— if it became zero, the reinterpretation in Section 3 (“even a curve that doesn’t pass through an image deviates by a few %”; ±5 % is roughly the same as the floor) would no longer hold, and if it grew large we could no longer attribute the deviations from Section 3 onward to lateral diffusion.
- L302 — ★Pin down the observation. That these 2 lines hold simultaneously is the very claim of this section. (1) When the 16 items are collapsed into a single average, TSR loses to the null baseline that “always answers 1.50 mm.”
- L332 — ★Pin down the observation. (1) The lower-right triangle, where the diameter is 4 times or more the depth, is hit within a few % (roughly the same as the floor in Section 1).
- L362 — ★Control group: the same scene with lateral diffusion turned off. This separates “blame lateral diffusion” from “blame insufficient pixels / a mask that can’t be extracted.” Looking at only one side and blaming physics is the most common mistake in this kind of experiment.
- L409 — ★Pin down the control group’s observation: with lateral diffusion off, all 16 fall within ±8 %. This one line is the evidence that “the only cause of breakage is lateral diffusion, not pixel coarseness nor how the mask is taken.” Loosen it and the conclusion of Section 3 reverts to the misreading that ‘raising the resolution fixes it’.
- L419 — ★If the reasoning above (the diffusion length at the end of the window matters) is correct, then cutting the window fixes it. When you form a hypothesis, always place one experiment shaped to disprove it. —————————————————————— #
- L440 — ★Pin down the heaviest observation of this PoC —— the “aspect-ratio limit” was not physics but how the fitting time window is chosen. (1) With a 4-second window, all 8 small ones fall within ±20 % (measured worst case -14 %).
- L528 — ★Pin down the observation: if heating is uniform, the raw single frame detects the most, while the 2nd derivative of TSR detects none. “It works for depth estimation but is unsuited to detection” = the same tool does not necessarily work for both, which is exactly this section’s claim.
- L575 — ★Lamp reflection. This is the one with structure at the same scale as the defect.
- L602 — ★Pin down the observation. (1) The only thing that breaks it is (c)’s unevenness at the same scale as the defect. (b)’s gentle gradient barely breaks the raw single frame —— since this is where “the prediction was off,” we explicitly confirm that (b) does not undercut (a).
- L683 — ★Put NETD into the default cube as well. With zero noise, the in-plane variation of the sound region becomes exactly 0 and the SNR turns into a meaningless number like 1e9 (measured and fixed).
examples/poc_timelapse_growth.py
- L472 — ★Vary the grid phase in 5 ways and count separating bias (mean) from spread (width).
- L610 — 2) ★Y-shape —— slice the volume along the row passing through the center of the merging pair
examples/poc_traffic_counting.py
- L256 — ★Rows cut off at the left or right of the frame have their centroid pulled. We also measure the version with them dropped.
examples/poc_tree_ring_dendro.py
- L229 — ★Reading the pixel map diagonally makes the numbers flicker as k, k+1, k, k+1 at the boundary (nearest-neighbor staircase). Short runs of fewer than 5 samples (1.25 px) are absorbed into the preceding value —— left alone, the ground-truth boundaries increase by 1–2 and it became “18 in the direction where the year count matches + 13 that don’t = 31 > 24.”
- L336 — ★Take everything with threshold=0 and measure the step height yourself. The amplitude of measure_pos (the difference between the two ends of the gradient lobe) stops midway up the step when the grain makes the gradient non-monotonic, returning a 0.14 step as 0.05 (counted in Section 8).
- L345 — ★The outer-edge radius used to convert back to px is that of the measured row. Using the median over the whole 15° sector makes the outer edge move by more than 10 px within the sector due to eccentric growth, so all the outer rings shift (I first wrote it that way and dropped rings 18–35 entirely).
- L543 — ★Is the width correlation high even in the direction where the year count is wrong —— the year count and the width correlation are separate quantities
examples/poc_vegetation_cover.py
- L320 — so here we reduce it to the 2 bands green and red to solve it. ★A gap in the tooling.
- L543 — ★Whether it lies on the diagonal is precisely “whether it can answer in fractions.” The line of a binary method becomes a staircase and departs far from the diagonal in the band of mixed pixels.
- L755 — ★Show “only the numbers match” as a picture. The 3rd and 2nd frames share almost no common pixels, yet only the count of white pixels is balanced.
- L953 — (7) ★PPI breaks under noise —— even with 60 % or more pure pixels it fails to pick up the leaf. Meanwhile with zero noise it hits on the same scene = the cause of the cliff is not a shortage of pure pixels.
- L993 — (11) ★A gap this PoC found and fixed in fullseye 0.1.10. Three Otsus were returning different answers for the same input —— merely multiplying the same image by 4095 shifted the verdict by otsu 13.34 pp / cv_otsu 13.92 pp, and only sk_otsu was affine-invariant. The cause was the
np.clip(v, 0, 1) in ops._otsu and backends._u8 (floats in 0..255 saturate every pixel, making it “all foreground”). Now all three are invariant to scaling. The remaining 0.5 pp in cv_otsu is because OpenCV internally quantizes to 8 bit, which is behavior as documented in the docstring. The gate is tests/test_value_range_saturation.py.
- L1007 — (12) ★A gap in the tooling: spec_unmix rejects B=3 (color images) = there is no path to solve RGB
- L1013 — (12b) ★There really exist scenes where only the coverage-ratio number matches while not a single pixel is hit. This one line is the strongest evidence for “do not round down to a single number.”
examples/poc_veiling_glare.py
- L229 — ★Cross-check on the fullseye side: Airy pattern → does psf_to_mtf agree with the closed form
examples/poc_vessel_network.py
- L263 — ★Add the fluctuation after blurring. Adding it first lets the PSF smooth it out, leaving the threshold boundary clean (I first wrote it that way, and even raising the amplitude to 0.35 produced not a single whisker).
- L452 — Section 2-3. ★★Where do the whiskers come from / the pruning threshold depends on resolution # ————————————————————————— #
- L560 — Section 4. ★★Diameter estimation —— always overestimated near branches # ————————————————————————— #
- L620 — Section 5. ★★Murray’s exponent —— a 10 % in diameter becomes a 1 in the exponent # ————————————————————————— #
- L751 — Section 6. ★Control group for crossings / branches lost to resolution # ————————————————————————— #
- L890 — (c) ★skeleton_prune3d does not “prune short branches” but “shortens all branches”
- L903 — (d) ★fs.skeleton_nodes returns only endpoints even though its docstring says “coordinates”
examples/poc_warehouse_flow.py
- L145 — ★”Waiting for people” 4 cases x (7.5 + slow-down 2.5) and “aisle interference” 8 cases x (2.5 + slow-down 2.5) both add 40.0 seconds to the null baseline —— deliberately matched. It won’t necessarily agree with reality, but that “the same number arises from different causes” can be shown with one example.
- L160 — The null baseline’s “stationary” threshold [m/s]. ★Unless it is placed well above the apparent speed created by noise (σ√2/Δt = 0.085 m/s @ Δt=0.25 s), stationary people are misjudged as moving and the null baseline shrinks (at 0.15 m/s the null baseline halves at Δt=0.25 s, yielding the false conclusion that “the finer you sample, the less dwell there is”).
- L239 — ★Since it is visible if even one of the cameras can see it, entering the blind spot means the height at which all cameras are blocked = the maximum of each camera’s limit. I had this as min and the prediction was off by 0.5 m.
- L329 — ★Derive the arrival time of the people queuing from the time work actually starts (deriving it from an estimate was off by 20 seconds, and the waiting bar did not overlap the working bar).
- L342 — ★The meeting place must be right alongside a row of shelves. A cross-aisle that is not between two shelves is open on both sides with a clearance of 1.9 m and is not classified as a “narrow aisle” (the first implementation had them meet at the level of the main aisle, and 4 of 10 fell into “other”).
- L435 — ★It is a merge, not a swap —— a swap does not break the temporal nesting that “within the same bar, the one that started later is the waiter” (only the roles swap, and both roles are filled correctly). What breaks it is when two people look like one.
- L594 — ★Keep only the stationary core. A bar spans 1.8 m from two people’s footprints, so the center of a passing person also falls inside the bar for 2-3 frames (in measurements this created “an interference with only one person” and dropped 8 of 10). Take the longest run that stayed within :data:
CORE_R of the median as the core.
- L846 — ★Counting by multi-person components makes “a column where 10 people passed through the aisle” thick and mixed, so compare “while waiting” and “while walking” within the same single person.
- L1257 — Marker size. ★Since “awaiting restock” and “out of stock” happen in front of the same shelf, draw from the largest marker and layer the smaller ones on top. Drawn at the same size, the later-drawn one completely hides the earlier one, and on the figure 5 looked like 2.
examples/poc_water_level.py
- L346 — 2. ★Zero point vs homography # ————————————————————————— #
- L389 — 3. ★The sign changes with the anchor position # ————————————————————————— #
- L422 — 4. ★Ripple —— robustness only helps when there are outliers # ————————————————————————— #
- L459 — 5. ★★Reflection —— comes out systematically low # ————————————————————————— #
- L622 — (d) The caliper existed (★I started to write “it does not exist” but pulled 3 tiers and found it)
examples/poc_web_roll_periodicity.py
- L123 — ★The circumference difference between the 1st nip and the 2nd nip is deliberately only 15.7 mm (for the cliff in section 6).
- L158 — Raise the number of trials only for section 6 (the cliff). ★With 24 trials the report rate was non-monotonic — 100 % at 12000 mm and 88 % at 14000 mm — and the position of the “detection cliff” moved with small-sample fluctuation (with 120 trials 12000 mm settled at 93 %, and 100 % holds only at 17000 mm and above). Only the section that claims the cliff position is measured at a trial count where the floor does not wobble.
- L253 — ★The op returns the vertex without rounding (exceeding ±0.5 is the information that “that is not a maximum there”). Since this PoC also evaluates the comb’s harmonic bins, we round explicitly here.
- L802 — ★The floor is not 0. With 24 trials the longest 2 points happened to be 0 % and the judgment “the shortest L that holds 0 %” passed, but with 120 trials even the longest 20000 mm leaves 2 %. Measure the floor first, then decide at what multiple of the floor to call it a cliff (do not use 0 % in the judgment).
- L1057 — ★With 120 trials it was no longer exactly 100 % (97 / 98 %). The “100 %” of 24 trials was just a small denominator. Look at the floor and set it at 95 %.
examples/poc_weld_bead_scan_angle.py
- L485 — ★Candidates are “points that returned to the height of the base-metal surface,” so all the flat base metal outside the groove also becomes a candidate. Only after confirming that weld metal (a drop of at least CHECK_DEV from the base-metal surface) exists within the inner CHECK_IN mm is it accepted as a toe —— without this gate, candidates slide down onto the base metal and the leg length flies out by 1.7 mm.
- L489 — ★Take the gate depth deeper than the deepest groove. Setting it first at -0.6 mm let a groove of depth 0.45 mm (0.74 mm vertically) pass the gate, and 1 of the 16 cross-sections was off by 2.2 mm.
- L572 — ★The mean of true values for only the surviving cross-sections. See what dropped out of the aggregation.
- L999 — ★Only the convexity deviated from the prediction. The cause is the creep of the toe (because τ is an absolute-value threshold).
- L1193 — ★How the groove disappears with angle (viewed by the drop from the base-metal surface)
examples/profile_shape_inspection.py
- L25 — ★Since it imports a module directly under the repo (profileops), put the repo root at the front so it runs straight from a checkout. Same convention as the other examples. Without this,
py -3.11 examples/<name>.py fails with ModuleNotFoundError (measured 2026-09-09: of the 83 that had no gate to run them, only 2 of this type failed).
examples/representation_roundtrip.py
- L175 — (c) Gaussian -> voxel mass. ★A number I got wrong once
examples/shape2d_morph_descriptor_tour.py
- L64 — ★EXTEND: replace with your own contour-extraction result (
{"shape": (H,W), "cs": [ (N,2) (row,col), ... ]})
examples/shapestat_landmark_tour.py
- L71 — ★EXTEND: put your own landmarks (N,3) into s (the point ordering must correspond)
- L123 — ★EXTEND: put your own group (K,N,3) into scrambled (position, orientation, and size may be scattered)
- L221 — ★EXTEND: arrange your own landmarks as “all of the left, then the right in the same order” and put them into lm
- L276 — ★EXTEND: make surf your own surface points (mesh vertices, point cloud) and normals their oriented normals
- L299 — ★EXTEND: replace with your own group (K,N,3) (the point ordering must correspond across individuals)
examples/voxel_labels_color.py
- L81 — 1) ★Color stability —— the reason this family exists # —————————————————————— #
- L152 — 4) ★Anisotropic spacing # —————————————————————— #
examples_3d/alpha_shape_topology.py
- L149 — ★Discriminative assert: the alpha shape preserves holes = it barely contains the axis probe. The null method (convex hull) FAILs this condition with containment ≈1 (= discriminative).
examples_3d/ct_hand_radiograph.py
- L34 — Actually call it and verify. ★Until 2026-09-05, this example wrote “matches np.sum(axis=0) when azimuth=elevation=0” but had never once verified it. Moreover, because the op → example index mistook the hasattr string for a call, “ops with not a single example” were hidden inside 100% coverage.
examples_3d/geometry_metrology.py
- L186 — ★Output the difference from the infinite-line version as a number (the same 2 segments)
examples_3d/hull_bounds.py
- L237 — — Panel C: ★new min_enclosing_sphere (tight) vs naive sphere (oversized) —
- L272 — ★(1) new op — min_enclosing_sphere: radius recovery on a known sphere + contains all points + nearly minimal ============================================================
- L296 — ★(2) beat-null of the new op — on an asymmetric point cloud, smaller than the naive sphere, nearly minimal, on the safe side ============================================================
examples_3d/mesh_props.py
- L404 — ★Flipping the winding order reverses the sign of the volume = the sign is itself an orientation check
examples_3d/metrics_eval.py
- L234 — ★Nearest-neighbor distance lies when it is “just re-measured with zero change.” Re-taking the same slope at a different density or position makes the nearest neighbor grab an adjacent point along the surface, producing a spurious change on the order of the point spacing. M3C2 projects onto the normal direction, so that component drops out. (The prediction before writing this PoC, “C2C also comes out too large under a normal shift,” was wrong —— moving parallel surfaces along the normal direction alone keeps the nearest-neighbor distance nearly at the true value. The lie appeared in the re-taking along the surface instead.)
examples_3d/sdf_csg.py
- L167 — ★Trap: even as a scalar,
res is the number of voxels per axis, so if bounds are anisotropic the voxel is not a cube (here x,y is 0.125 and z is 0.0625). Computing the volume with h**3 is off by exactly a factor of 2 —— in this example it actually gave 295.00, a 99 % error against the closed form 148.03, and the assert below fired.
examples_3d/space_carving.py
- L117 — ★Use
carve_look_at (2026-09-08). Same implementation as look_at, but the name reachable from the public layer is this one —— fs.look_at is a different thing, render3d’s gluLookAt version (4x4, −Z forward), and passing its M[:3,:3], M[:3,3] drops all points behind the camera and returns an empty hull without raising an exception.
examples_3d/structured_light_scan.py
- L122 — ★ Coordinate-system pitfall:
look_at builds the pose in the gluLookAt convention (camera looks down -Z, +Y is up), but render_mesh first rewrites that Vc to (x, -y, -z) before multiplying by K (= the same CV convention as depth_to_points / K, depth is +Z forward). Triangulation is closed on the CV-convention side, so the pose must also have FLIP applied before it is composed. Skip this and the projector faces behind the camera, and the depth stays at a ‘plausible magnitude’ while being entirely wrong (the very first run did exactly this: RMSE 78 mm = indistinguishable from zero).
fast.py
- L254 — ★Do not ship the uint8 gaussian. The 8U path of
cv2.GaussianBlur uses an 8-bit fixed-point kernel, so its difference from the float64 core is 1.174/255 (measured, the max over this module’s 6 gate images x 5 PARITY_AB points), which does not meet ‘agreement to 1/255’. box is 0.494/255, and median / morphology are 0.000/255, so only those are shipped. If a fast uint8 gaussian is needed, add it explicitly under a separate contract of ‘to 2/255’.
- L294 — ★Everything listed here has passed the :func:
parity gate. When adding, always follow the order ‘implement -> run the gate -> ship it if it passes’.
- L320 — ★Do not ship
edges_image (as a HALCON name, the same as canny). That name in the registry is backends_auto’s skimage canny (with real hysteresis), a different algorithm from the core canny. Mismatch rate 1.0 (measured). – HALCON-name twin (an op registered in the registry under an alias with an identical implementation) ———- same idea as accel._TWIN_ALIASES. The gate runs against the implementation under that name in the registry, so if the implementation diverges it fails and is not shipped.
- L372 — ★Do not decide by ‘was the observed output {0,1}’ – even a continuous op produces all-0 output on a constant image, which is misjudged as binary and silently tightens the criterion (hit during implementation). Decide by the declared out_sort in the registry.
feat_fpfh.py
- L304 — ★2026-09-07: The pose computation is numpy (FPFH, RANSAC, and Kabsch are all numpy), and torch was used only to wrap the return value. Because of that, on CI without torch (py3.10 / 3.12) this op became a whole-op ImportError and the PoC failed. If torch is present it returns a Tensor as before; if not it returns numpy with the same values (values unchanged).
flyvision.py
- L187 — ★ The cap is on the product, not on either factor, because the accident it prevents is the cross term: a modest 900-ommatidium eye and a modest 512x512 image are each unremarkable and together are 236M float64 = 1.9 GB.
fscript.py
- L1269 (ja) — ★2026-09-14: ここは
FsTypeError だけを捕まえていた。逆さの区間と未知の feature を契約どおり FsValueError(= FS_E_INVALID_ARG)にした結果、 fscript の利用者には Python の生の例外が漏れるようになっていた —— 例外の種類を増やしたら、それを言語境界で受けている場所を必ず一掃する ([[feedback_same_bug_class_recurs_check_siblings]])。
fslib.py
- L559 (ja) — ★2026-09-14: ここは長らく borderType 既定 =
BORDER_REFLECT_101 (d c b | a b c d — 境界の画素を重複させない折り返し)だった。numpy backend の ndi.gaussian_filter の既定は mode='reflect' = d c b a | a b c d (境界の上で折り返す)で、同じ「reflect」という語が別物を指す。 実測(512x512, sigma=1.0, 乱数): 内部は 4.6e-08 まで一致するのに、端の画素だけ 最大 0.13 = 値域の 13% ずれていた。内部しか見ない検査では原理的に出ない。 connection の 4/8 連結と同じクラスの欠陥(兄弟コードを一掃した 2 件目)。 契約は numpy 側(既存の進化レシピのオラクル)に合わせて BORDER_REFLECT。
- L615 (ja) — ★2026-09-14: ここは長らく
ndi.label(mask) = 4 連結の既定だった。 cv2 backend は connectedComponentsWithStats(..., 8, ...) で 8 連結なので、 同じ op が backend によって違う物体数を返していた —— 8x8 の市松模様で numpy 32 個 / cv2 1 個。レシピの答えが「どちらの backend が選ばれたか」で 変わるという、いちばん静かな壊れ方。C ABI を Rust で 2 度目に実装して 突き合わせたときに見つかった(fullseye_abi.h の fs_connection に 8 連結と明記した)。回帰は tests/test_fslib.py が backend 横断で見る。
- L630 (ja) — ★2026-09-14: ここは
(mask, 8, cv2.CV_32S) と位置引数で書いてあった。 読むと「8 連結を明示している」ように見えるが、cv2 5.0.0 で実測すると connectedComponentsWithStats(a, 4, CV_32S) も (a, 8, CV_32S) も同じ答え を返す —— 位置引数は connectivity として解釈されておらず、既定の 8 に たまたま一致していただけ。既定が変われば黙って 4 連結になる。 コードが主張している意図を API が守っていない形なので、キーワードで固定する。 (差分ファジングの変異解析で 4 連結を注入したのに一切検出されず、掘ったら 注入のほうが効いていなかった、という経路で見つかった。)
- L723 (ja) — ★契約 R-1(fullseye_abi.h): 失敗した演算子は「何も見つからなかった」演算子と 区別できなければならない。逆さの区間は呼び手の間違いであって、「空を寄こせ」 という正当な指定ではない —— 黙って空の Region を返すと、しきい値の計算を 間違えたレシピが「不良ゼロ」として通る。2026-09-14、同じ契約の Rust 実装が FS_E_INVALID_ARG を返すのにこちらは空を返す、という差分で見つかった。
- L743 (ja) — ★契約 R-1:
threshold で直したのと同じ欠陥が兄弟に残っていた。逆さの区間は 呼び手の間違いであって「空を寄こせ」という指定ではない —— 黙って 0 個を返すと、 面積の下限と上限を取り違えたレシピが「該当なし = 良品」として通る。 2026-09-14、Rust 実装が FS_E_INVALID_ARG を返すのにこちらは 0 個を返す差分で発見。
fsruntime.py
- L284 — ★A judging recipe may use ONLY the curated fslib-backed builtins, under EVERY profile (not just industrial). Any other call is a 650-op evolution-registry op resolved through fscript._call_registry_op → api.RT, whose _safe wrapper is fail-OPEN (it swallows an op failure and returns a benign “no defects” value). That surface must never be a recipe’s operator — a studio/reference runtime judges parts too — so a recipe that uses it is rejected at load (docs/FSCRIPT_DECISION.md 1.6b).
fullseye/__init__.py
- L531 — ★The adapter that conforms to the declared out type discards everything from the 2nd element onward of an op that returns a tuple (
wht of drizzle_resample, info of piv_cross_correlate). When the discarded side is needed, it was unreachable through the ledger’s entrance. On 2026-09-06, a super-resolution PoC wrote flow, info = fs.ledger.piv_cross_correlate(...), unpacked the (2,R,C) along the 1st axis, used the 2nd row of dy as dx, and turned the shift estimate from 0.12 -> 0.74 px (no exception raised). Use .raw to reach the bare return: fs.ledger.piv_cross_correlate.raw(a, b).
fullseye/mcp/catalog.py
- L104 (ja) — ★5 層。最初は 4 層で組み、「索引にもレジストリにも facade にも無いノート」が 480 枚残った。残骸かと思ったら 480 / 480 が
fullseye.ledger で解決した (型付き台帳。レジストリでは tb_project、台帳では project のように接頭辞が 違う)。「無い」と言う前に全層を引く —— 4 層目まで引いて止めていたら、実在する 480 個の機能を残骸と呼んでいた。
- L318 (ja) — ★同点の割り方は
api.find_op と同じにする: 別名を複数 op が共有するとき name == halcon の正典を先に。次に層が多い(実行もノートもある)方。 実測 2026-09-15: “gauss” で gauss_filter(正典)と gaussian が同点になり、 名前順だと _ < i で前者が先に来た —— 偶然そうなっていたのを規則にした。
fullseye/mcp/diagnose.py
- L87 (ja) — ★順序が答えを変える(2026-09-15 実測):
ones + inf は有限部の std が 0 なので 「定数」が先に当たり、0..715 の配列は 99.9 % が ≥ 1 なので「飽和」が先に当たった。 より根本的な異常を先に言う: 非有限 → 定数 → 範囲外 → 飽和 → 平坦。
- L106 (ja) — ★飽和・平坦は image / color だけ。region は 0/1 が契約なので「飽和」ではない —— リファクタで region を含めてしまい、
--demo で otsu の出力が「飽和」と判定されて 小図が昇格した(2026-09-15 実測)。region の定数(空 / 全面)は上で拾う。
fullseye/mcp/handles.py
- L47 (ja) — ★thumb_dir を渡されたときに作っていなかった(mkdtemp のときだけ存在する)。 小図の保存が FileNotFoundError で落ち、テスト 4 件で発覚(2026-09-15)。
g1_policy_bridge.py
- L33 — ★Do not bake a local absolute path into the distribution (in the 2026-09-05 audit, a private sibling project name was riding in the PyPI wheel). Give the default via an environment variable. The scene XML of the Unitree G1. Points to MuJoCo Menagerie’s
unitree_g1/scene.xml.
- L61 — ★Security boundary.
pickle can call an arbitrary callable during load, so passing find_class through means just opening a checkpoint runs code. An RL checkpoint is an artifact meant to be received from others, so this is a realistic threat. (Measured 2026-09-05: the pass-through version returned os.system / subprocess.Popen / builtins.eval directly and could actually create a file during load().) Only the numeric classes actually referenced by a brax PPO checkpoint are listed here. When something is missing, add it to this list (the exception message prints the module name).
honest_summary.py
- L58 — ★Exclude auto ops that FAILED the functional gate from the headline — they were previously only [warn]-printed while still counted, inflating the “functionally gated” parity number with ops the gate rejects.
- L77 — ★2026-09-08: This line read – “= %d evolvable registry ops + %d n-ary capability ops (disjoint).” Measured, 979 + 17 = 979, i.e. the 17 n-ary ops are a subset of
reg_counted (nary_names - reg_counted is empty). The heading’s 979 is correct, but the breakdown line alone looks like ‘addition’, and a reader adding it gets 996. The numbers agree yet the explanation lies, so it was fixed. Whether the breakdown holds as a sum is checked every time by tests/test_honest_summary_arithmetic.py.
imgevolve.py
- L50 — ★Do not swallow it (adversarial review 2026-09-06).
imgops_nary is a primary module needing only numpy and scipy, so a failed import means a ‘broken checkout’, not ‘a feature absent in that environment’. Previously it was except Exception: pass, and because this function serves as both generator and checker, CI could publish an index with all 17 ops vanished while staying green.
imgio.py
- L99 — ★Two criteria (2026-09-08, fixed within the same day). At first the choice used only ‘CIE L* has 0 reversals’, but
poc_colormap_readability measured that cividis raises a colour-difference ridge despite 0 reversals. Even with monotone lightness, if the colour-difference spacing is uneven a nonexistent boundary appears in a smooth field – it had claimed to be ‘safe’ on a one-sided criterion. Measured (512 steps, max / median of adjacent colour difference, and the count of local maxima exceeding 1.6x the median): ========== ========== ============== ========== Map / L* reversals / dE max/median / ridge count ========== ========== ============== ========== gray 0 1.33 0 viridis 0 1.38 0 plasma 0 1.38 0 magma 0 1.48 0 inferno 0 1.50 0 cividis 0 2.23 1 turbo 1 1.78 1 ========== ========== ============== ========== cividis was dropped because this repo’s approximate LUT is coarse, not a problem with the published cividis itself (its 6 control points are the fewest among the sequential maps). For those who want to choose with colour-vision deficiency in mind, :data:CVD_SAFE is provided. tests/test_pseudocolour_family.py measures both criteria every time.
- L124 — Maps said to keep their order readable even with colour-vision deficiency (P/D type). ★
cividis’s approximate LUT has 6 control points and a coarse colour-difference spacing, and does not meet the :data:PERCEPTUAL_SAFE criterion (measured dE max/median 2.23). Adding control points would let it enter both – since hand-copying primary-source values has a prior record of typos, this is held until the source can be confirmed.
matappear.py
- L167 — ★Passing a 0-dimensional (scalar) value made
r.shape[-1] throw a bare IndexError (caught in the adversarial audit of 2026-09-04). A spectral reflectance has at least a wavelength axis – a scalar is not ‘a value per wavelength’, so the guard explicitly refuses it.
- L296 — ★A real grating diffracts on both sides (if the grooves are symmetric, the +/-m efficiencies are nearly equal). If you do not include both +/-, then depending on the geometry of light source and line of sight all solutions can be negative, and the ‘keep only positive lambda’ filter drops everything and goes pitch black. Measured: a CD illuminated perpendicular to the grooves (delta-sin = -0.55) had m=+1,+2 all vanish at lambda<0, and the 440 nm of m=-2 was the real answer.
match3d.py
- L297 — ★2026-09-07: Replaced with numpy’s FFT. The formula is the same (float32 fftn -> phase only -> real part of ifftn -> argmax), and there was nowhere it needed torch. On CI without torch (py3.10 / 3.12) this op became an ImportError and the PoC failed.
- L1633 — ★2026-09-07: Rewrote the body in numpy. This ICP is nearest-neighbour search by cKDTree and pose update by a 3x3 SVD, with not a single task for torch, yet it made torch mandatory. On CI without torch (py3.10 / 3.12), 4 PoCs fell with
ImportError: this operator needs the optional 'torch' backend and it surfaced (with torch present locally it went unnoticed – a case of ‘put the gate where the accident happens’). The numbers are the same float64 formula, so the result does not change with the environment. The return type is kept for compatibility: torch.Tensor if torch is present, numpy.ndarray if not (values identical). If a device other than “cpu” is requested, fail-closed.
- L1848 — ★2026-09-07: Rewrote the body in numpy. Nearest-neighbour search, the 6x6 normal equations, and Rodrigues are all small CPU linear algebra with no need for torch, yet it had been made mandatory. On CI without torch (py3.10 / 3.12) the PoC fell with an ImportError and it surfaced. The formula is the same float64, so the result is unchanged (the difference from the torch version was measured as 0 in R/t and 0 in RMSE).
- L2810 — ★2026-09-07: fail-closed if the ring is outside the image.
r_in/r_out are in pixels, so passing them in mm reads outside the field of view and returns all 0 with no exception (surfaced when poc_pipe_wall_loss produced one pitch-black figure). If not a single radius is inside the maximum distance from the centre to the image’s four corners, the return can only be empty.
- L2821 — ★2026-09-07: Replaced grid_sample (bilinear, align_corners=True, zeros padding) with scipy’s map_coordinates(order=1, mode=”constant”, cval=0) – the same bilinear interpolation, and it runs even on CI without torch (py3.10 / 3.12). The measured difference is at most 6.0e-06 (random image over the range 0..1; the rounding difference between float32 and float64).
- L2866 — ★2026-09-07: Replaced with map_coordinates for the same reason as polar_unwrap (bilinear, out-of-range 0). Runs even without torch. The measured difference is at most 7.6e-06.
- L3117 — ★2026-09-07: Replaced affine_grid + grid_sample (align_corners=False, zeros padding) with numpy coordinate computation + scipy’s map_coordinates(order=1). torch was used only for the bilinear resampling, and in an environment without torch (CI py3.10 / 3.12) this op became an ImportError. The convention was carried over verbatim: the normalized coordinate of an output voxel (d,h,w) is ((i+0.5)/N)2-1, and after rotation it is mapped back to input pixel coordinates by (g+1)/2N-0.5 (the align_corners=False definition). The last axis of grid is in the order (x, y, z) = (W, H, D). The measured difference from the torch version is at most 7.6e-06.
- L624 (ja) — ★ここを「もう片端が次数 3 以上」と書いていた最初の版は、実測で 一度も発火しなかった: ヒゲの根元が枝の端点クラスタと 26 近傍で 融合して次数 2 になる配置が普通にあり、その場合に素通りしていた (「刈った」と報告しながら 0 本という、いちばん静かな失敗)。
occupancy.py
- L223 — ★2026-09-07: Made
res accept per-axis values (length 3 allowed too). Restricted to cubic, a flat volume like a bird’s-eye grid (thin z x wide xy) is forced to use the same spacing even on the unneeded axis (poc_bev_sensor_fusion measured: of 4.096 million voxels only 8.1 % are used). The same-family grid_coords had accepted per-axis res from the start – the mismatch where the contract’s breadth differs at the entrance and the exit was aligned. Existing callers passing a scalar are unaffected.
- L317 — ★2026-09-07: Made
res accept per-axis values (length 3 allowed too). Previously int(res) allowed only a cubic grid, and while esdf accepts a length-3 anisotropic voxel_size, this side – which subtracts its output in world coordinates – was restricted to cubic, a contract narrow on only one side. It jams outright on a grid like CT’s thin junction layer (30,180,180) (measured in poc_ct_void_morphology). Existing callers passing a scalar are unaffected.
opassist.py
- L50 — ★2026-09-08: ops1d (dsp 16 + funct1d 23) was registered yet appeared neither in docs nor in op_run / op_assist / op_find – ‘registered’ and ‘reachable’ are different. Adding them to opdocs made this gate ring on the unreachable side.
- L242 — ★Design (2026-09-04, user: ‘It’s better to handle various container types, but consistency matters too’): At first
kind mixed in “seq” and “matrix” – that is, the value type (numeric, integer, or choice) and the container shape (single, vector, or matrix) competed in one field. From the UI’s view an ‘int 3-vector’ could not be expressed, and only matrices had their structure under the seq key, so handling was scattered. This was made orthogonal: kind holds only the value type, and the container always goes into container. A scalar is not made an exception either ({"form": "scalar", "shape": ()}), so the UI can write its branching as a single path.
- L357 — ★Longest match. Scanning shortest-first,
sigma_per_mm matches _mm and becomes “mm” (it is actually 1/mm). Get the unit wrong and the UI’s number silently becomes something else.
- L454 — ★The key point: some arguments do not have their default given as a tuple.
center=None (an optional (row,col)), the required trans (3-vector), k_cam (3x3 matrix)… looking at the default alone they appear to be ‘a single number’, and the UI breaks by showing one spin box. Supplement the structure by name.
- L610 — ★Found by measurement: passing a generic 0..1 signal into the wavelength input of
prism_min_deviation_deg gets rejected by ‘wavelength must be positive’, making it an op whose sample does not run. If the unit is known, seeding it with a range plausible for that quantity is closer to ‘runs when you press it’.
- L730 — A run of Japanese (CJK) text. ★
_WORD_RE is [a-z0-9]+, so a Japanese query yields not a single word (_WORD_RE.findall(...) == [] on the Japanese input). The stemming stage dies, and because partial match searches for a string that includes the whitespace, a multi-word Japanese query was structurally always 0 hits – in a product whose docstrings are mostly Japanese and that ships in 6 languages. Surfaced on 2026-09-08 when poc_search_sweep_width hit it (the Japanese queries for ‘point detection’ / ‘spot detection’ / ‘small target’ via op_find were all 0 hits, and although sub-pixel-centroid point-target detection is only star_detect, it could not be reached from Japanese).
- L783 — The common-prefix length treated as a stem match. ★At 4, “median”/”medial” and “contrast”/”contour” get linked; cutting at 5, “correlation”/”correlate” (8), “segmentation”/”segment” (7), “rotation”/”rotate” (5), and “gaussian”/”gauss” (5) are picked up while the two pairs above are not.
- L793 — The suffix allowed after the common prefix. ★Deciding by prefix length alone links “median”/”medial” (they share a 5-character “media”). Judging whether the suffix looks like an inflectional ending, “correlation”/”correlate” (ion / e) passes, while “median”/”medial” (n / l) and “corner”/”cornea” (r / a) fall out.
- L889 — ★Floor. Without it, “zzz-nothing-matches” returns
histogram_match (because “matches” stem-matches match_*). If the weight of the matched words is under 15 % of the whole query, it is treated as ‘no match’. Measured: “digital image correlation” is 0.19 (passes), “zzz-nothing-matches” is 0.10 (dropped).
ops.py
- L628 — ★Pad the edges with the edge value. Previously it was
np.convolve(x, k, "same"), which averages the w points at both ends with zero – the start and end of a contour got dragged toward the origin (0,0) by up to 50 px or more, producing a figure where the red streaks of 140 contours converged to the upper left (found 2026-09-06 when per-op figures were first made; in numerical tests the mean deviation was 0.3 px and it was invisible).
- L1498 — ★A ledger of ops that crash the whole process on the native side with a degenerate input (2026-09-05).
guard can only catch Python exceptions. Once something is written out of bounds inside C/C++, it is over there, and the user’s whole pipeline vanishes – the worst way for fail-soft to break. There is no recourse but to reject at the entrance, so list it here with a reason and set a barrier at registration time. Behaviour differs by platform – that is the reason this ledger exists. The 3 below crash on Linux (Ubuntu 24.04 / Python 3.12 / PyPI wheel), but on Windows not one reproduced with the same input. A different native build means the boundary breaks differently, so a fine line of ‘this kind of input is fine’ cannot be trusted – reject degenerate inputs wholesale. Not ‘remove it once fixed’ but remove it once the upstream can be confirmed fixed (this is not our own code, so the removal condition differs).
ops3d.py
- L375 — ★out is not image2d but rgbimage (measured 2026-09-02). Both the docstring and the implementation say ‘RGB (size, size, 3) float [0,1]’, and only this line claimed a 2-D luminance image. This op only ran once a mesh seed was supplied, and the type predicate surfaced it with a TYPEMISS: “declared ‘image2d’ but returned ndarray(512,512,3)” (until then, because of the shape that splits (V,F) into 2 positional arguments, it had never run once). The other 3 render_* ops (ambient_occlusion / cast_shadow / supersample_mesh) are 2-D as measured, so image2d is fine for them – the lie was only this one line.
- L465 (ja) — ★新しい sort は作らない: ノード表と枝表は「単位も意味も違う 2 つの表」で、 タプルで返して adapter に
r[0] と書くと 枝表を黙って捨てる (pose_error / m3c2_distance で繰り返した失敗の型)。1 つの dict に 両方を入れれば宣言 ‘table’ が実返りと一致し、捨てるものが無い。
- L616 — ★Added 2026-09-08. Until then the pose helper for carving (visualhull.look_at) could not be reached from any public layer, and grabbing the same-named render3d.look_at (gluLookAt, -Z forward) resulted in an empty hull without exception (poc_livestock_body_volume).
- L637 (ja) — ★ out は image2d ではなく keypoints(2026-09-15 実測)。実返りは 像面上の (N,2) 画素座標で、入力 (160,3) に対し (160,2) が出る —— 画像ではない。同じ型の嘘を “render” 節の
project_points で 2026-09-02 に既に直しているのに(「旧宣言 ‘image2d’ は型の嘘で、 pnp3d 側の ‘image2d’ 宣言と噛み合って PnP を壊していた」)、 この 1 行だけが兄弟一掃から取り残されていた。 例外にならないのは _sort_ok が image に ndim == 2 しか求めず、 (N,2) が「幅 2 の画像」として黙って通るから。値域も画素座標 (実測 16.0 .. 47.9)で [0,1] ではなく、image を名乗る限り 下流の閾値 op に渡ると意味を失う。
- L727 — ★The reason (a) for holding it back – ‘the points candidate list gets shorter and silently overwrites the existing champion’ – is gone now that backends_typed.TYPE_TO_SORT folds coordgrid -> points: the 2-D bridges tb_sphere_sdf / tb_box_sdf carry INPUT_ADAPTERS._points_to_grid and actually build a coordinate field from the point cloud, so their “points” declaration is not a lie (measured: passing (64,3) returns (16,16,16) = alive). The lie was only on the 3-D ledger side.
- L882 — ★axis=1. The canonical form of
pairs is (N,2) (measured: the 6 consuming ops explicitly reject (2,N)). While the predicate was lambda v: True, this produced (2,n) and declared as its type ‘a shape no consumer can accept’
- L920 — ★The canonical form of position is 3 components [z, y, x]. Decided not by majority vote but by running the consumers: refine_translation_lk / refine_lm fail-closed with “init_pos must have exactly 3 components [z, y, x] (got 4)” when passed 4 components (measured). The generator is also 3 components (8.0, 8.0, 8.0). But the match_* family returns 4 components [score, d, h, w] as per docstring, so flowing it with a declared out of “position” wipes out the downstream refinement ops = a type lie. Since score itself is honest information, the function side is not trimmed (get() stays at 4 components), and the coordinates alone are extracted on the call() side that claims the ledger’s type (the same treatment as project_points).
opsastrostack.py
- L85 — ★ Instead, we explicitly reject a raw (N,H,W) ndarray. A 3-D array passes the same structural check whether it is video (T,H,W) / voxel (D,H,W) / histcube (H,W,T) / zscan, so a mix-up raises no exception and returns a “plausibly wrong composite” —— this is exactly the same danger as the photon family separating histcube from voxel. Here, however, we obtained the same defense not by adding a type but by requiring that it “be a list”. The moment you write list(volume), the caller has declared that “the leading axis is the frame axis”. * image2d —— composite, drizzle output, single frame. All are 2-D float64, so existing 2-D ops (filter, threshold, morphology, psf_to_mtf) can be used with their meaning intact. It is not even non-negative (residuals of κ-σ combining and negative fringes of spline interpolation appear), so calling it counts would instead be a lie. * keypoints —— the return of
star_detect is (N, 2) as (row, col). The keypoints in TYPE_CHECKS is “(N,3) or any 2-D array”, so it applies directly and is consumed by psf_fit / aperture_photometry.
-
L101 — ★ This is not pairs: the canon of pairs is the “(x, y) pair” fixed by the 6 ops on the reprconv side, whereas this is (row, col) in image coordinates, following the same convention as fit_transform / mosaic. Mixing them swaps rows and columns (the same shape as this repo’s known trap where features.match_keypoints returns (x,y) while fit_transform requires (row,col)). Calling it keypoints at least shares the promise of “a point on the image”. * indices —— the indices (1-D int) of the adopted frames returned by lucky_select. Exactly the existing vocabulary. [frames[i] for i in idx] returns to images. * measurement —— noise_sigma is a single real scalar. * matrix —— the (3,3) homogeneous transform from frame_align. It is the same thing that transforms / fit_transform / mosaic handle, so there is no reason to invent a dedicated term. * table —— dict / list of dict (quality, PSF fit, photometry). The table in TYPE_CHECKS is list |
dict, so both apply. The cost of not separating (honest): if a non-astronomical image sequence enters the images pool, frame_align finds no stars and halts with ValueError. Since this is fail-closed, it is not “zero findings” but “reached and correctly rejected”, yet from a chained fuzzer’s view the 2 align ops may end up being nothing but CONTRACT. Since the same symptom can appear as the reason the photon family separated counts (7/17 are never executed), if measurement shows this to be the case, then the decision to put “image sequences containing point images” in a separate pool is justified —— we do not preemptively add a type (in this repo the order is: add a type only after evidence emerges that “mixing makes it a lie”). |
opsdem.py
- L35 — ★ Honest limitation: the
depth pool can also include depth from a camera’s perspective projection. In perspective depth, how many ground meters 1 px corresponds to changes with depth, so a slope computed with a constant cell_size is plausibly wrong. So why not separate the type —— this is not a type mix-up but the same kind of error as giving cell_size wrongly, and cell_size is already a required argument (no default is set). Adding a type cannot prevent non-orthographic depth (the predicate can only see up to “a 2-D real array”), and instead a dem pool with not a single op that has a seed would be created, making all 13 ops permanently unexecuted. Rather than pretending a type prevents what it cannot, we made it explicit with a required argument and docstring, and chose to actually run it in the fuzzer. * only the output of dem_fill_sinks is depth —— the result of filling sinks is still an elevation grid and goes straight into dem_flow_direction. Declaring it image2d here would sever the in-family chain (fill -> flow) by type. * dem_flow_direction is labels —— the return is int8 0-7 and -1 (no outflow target), a sign with no ordering meaning. Calling it mask would treat it as binary, and calling it image2d would make the average of 3 and 4 meaningful. It applies directly to the labels predicate (integer dtype, 1-3 dimensions). * dem_stream_network is binary but image2d —— its content is float64 with 0.0/1.0 plus nan for missing data, and does not satisfy the mask predicate (bool or integer dtype). Making it bool would make “not a channel” and “no value at all” indistinguishable, so we matched the type to the implementation. * everything else is image2d —— slope[deg], aspect[deg], curvature[1/m], hillshade[0,1], relief[m], horizon elevation angle[deg], sky view factor[0,1], visibility[0/1]. All are 2-D real fields, so existing 2-D ops (smoothing, threshold, morphology, pseudo-color, annotation) can be used with meaning intact. The value range is not necessarily [0,1], but that is the same standing as the composite of astrostack: in this repo image2d is used not as a promise of brightness but as a promise of “a 2-D real field”. category -> [(op name, module, [input types], output type)]
opsflyvision.py
- L62 (ja) — ★ 重みは公開しない:
fly_hex_resample の個眼×画素の重み行列は functools.lru_cache で内部にだけ保持し、op の入出力型には現さない —— 出すと「画素座標系に依存する巨大な派生物」が型プールを汚し、下流の 2-D op が それを画像と取り違えて黙って処理してしまう(zscan を video に渡すと通る、と 同じ事故の型)。出さないことでこの取り違えを構造的に不可能にする。
opsimgforensics.py
- L206 — ★ In the predicate of
phash, checking the dtype is the essence. With only ndim == 1 it completely overlaps the existing signal and the point of separating is lost.
- L208 — ★ The predicate of
fingerprint cannot be distinguished from image2d by shape. It can only be cut by zero-mean-ness, which is a statistical guess at runtime, so the predicate carries the same weakness (that is why we separate by type). Leave this weakness noted in the predicate’s comment.
- L224 — ★ The seed of
fingerprint must always be made through sensor_fingerprint. If you place rng.standard_normal((H, W)) directly, that is white noise, not a fingerprint, and matching will always return “uncorrelated” = you think you added a check surface but you did not.
- L227 — ★ The seeds of
images must be the same shape and 2 or more. With only 1, sensor_fingerprint keeps failing closed and never runs.
- L242 — ★
qualities=None of jpeg_ghost_quality assumes “12 entries of 40..95 step 5”, so unless the seed of images is 12 entries it will always raise ValueError. This is the intended fail-closed (it does not return a map where indices and qualities are misaligned), so match the count on the fuzzer side.
- L246 — ★ The
bits of watermark_* must be at most the capacity (number of 8x8 blocks of LL). A 64x64 image2d + level 1 LL is 32x32 = 16 blocks.
opsinterferometry.py
- L96 — ★ Not piggybacking on the existing
signal was the result of measurement. At first we judged “since csi_signal_simulate ([] -> signal) pours a genuine interference signal into the pool, it is reachable”, but running the chained fuzzer with that wiring, over 600 chains (300 x length 6 + 300 x length 8), csi_peak_position and chromatic_confocal_height were never executed once (only 7 CONTRACT records). The cause is that the signal seed is a sinusoid with negative values, and the probability that the entry op is drawn earlier in the same chain is low. It is exactly the same trap that opsphoton stepped on with counts, and as a result of fail-closed working perfectly, “zero findings” looks like robustness. In a re-measurement under the same conditions with sweep as a dedicated pool, all 9 ops were executed. That mixing the 2 types does not silently pass a mix-up is guaranteed by each having a dedicated discriminator (both thresholds measured in closed form): - passing a spectrum to csi_peak_position -> carrier_tolerance. An interference signal has its carrier at 2/λ (Nyquist’s 0.333), while a confocal peak is at 0.010. The same check catches even a 1000x unit error in measurement. - passing an interference signal to chromatic_confocal_height -> max_carrier_fraction. The AC component of the confocal response is low-frequency only (measured 0.010 / 0.010 / 0.015), while the interference signal is 0.333. Entry = csi_signal_simulate / chromatic_confocal_simulate (both produce with no arguments), exit = csi_envelope (-> signal) and the 2 measurement ops.
opsoptics.py
- L125 (ja) — ★ pupil_blur は「画像 × カーネル」の一般畳み込み(filters_freq.convol_fft) ではない —— PSF の標本間隔 λN/oversample を検出器ピッチへ面積積分して から畳む、その単位合わせが本体。だから PSF を作る側に置く。
- L140 — ★ Not normals (the (N,3) normals of a point cloud) but normalmap. The two are similar in shape, but passing (N,3) is rejected by _normal_map with ValueError. Declaring it normals here would be a lie that “you may pass point-cloud normals”, and the chained fuzzer would end in CONTRACT every time and never execute this family (= it turns into zero findings).
opsphoton.py
- L85 — ★ Note that since counts is a 1-D float64 array itself, nothing prevents “calling” dsp / funct1d (the type vocabulary is for the chained fuzzer’s pool separation, not for Python’s callability). For the reverse bridge = the path that non-negates a signal into counts, see the “bridge” note below. * countrate — the count rate sequence (Hz) of a SPAD (1-D, non-negative). It is the same “non-negative 1-D” as counts, but a different quantity, so we put it in a separate pool. There are 2 reasons, both based on measurement: (a) the unit differs by 7 orders of magnitude. The value range of the counts pool is around 0-250 counts, and passing this to spad_deadtime_apply(dead_time_ns=50) gives 250 Hz x 50 ns = 1.25e-5 -> a value infinitesimally close to the identity map is returned without exception. The op “reaches” but the physics of dead time (saturation, 1/tau fail-closed, the non-injectivity of the paralyzable type) is never stepped on. This is the same “plausibly wrong pass” as when histcube piggybacked on voxel, with neither CONTRACT nor TYPEMISS emitted. (b) the physics differs. Dead time acts on the detector’s rate stream, not applied per bin to a TCSPC time-bin histogram (the correct distortion model for a histogram is Coates = tcspc_coates_correct). Making them the same vocabulary would make the evolutionary search learn the physically wrong chain “applying a dead-time correction to a histogram” as a legitimate type connection. countrate is a narrow sort knowingly separated with only 2 ops, apply <-> correct (on par with jones having 2 ops and stokes having 3 ops). However, these 2 ops are strictly inverse to each other, so a round-trip invariant circulates within the pool. * histcube — the arrival-time histogram cube per pixel (H, W, T), time axis last. The existing
voxel is a “3-D array” and TYPE_CHECKS is also only ndim == 3, so structurally it passes. But voxel is a (D, H, W) spatial grid with different axis meaning: passing a (D,H,W) volume as histcube makes dtof_cube_depth read W as the time axis and return not an exception but a “plausibly wrong depth map” (measured: 0.0075 m for all pixels with a uniform volume). Note that a flat histcube is also judged empty on the dtof_cube_depth side and silently not passed (double defense). Bridge (measure against narrow sorts, implementation pending = awaiting the parent’s judgment): what could become a signal -> counts bridge is an op that “regards an arbitrary real 1-D as a non-negative photon rate profile and Poisson-samples it” (a 1-D version of photon_sample). Making the handling of negative values an explicit argument avoids silent rectification and does not break discipline. Existing non-negative-output 1-D ops (funct1d.abs_funct_1d measured min 0.0023, dsp.envelope measured min 0.749, both guaranteed non-negative) would, if that bridge exists, be a natural front stage for signal -> counts. See the report for details.
opspiv.py
- L25 — * ★ We newly established
flow2d. The existing flow_dense has the predicate ndim == 4 and shape[0] == 3 (3-D scene flow), so 2-D (2, h, w) does not apply in the first place. Borrowing the name would mean the ledger declares “it returns 3 components” while returning 2 components, making the declaration a lie. It satisfies this repo’s condition for adding a type (“if there is no op that has a seed, it becomes permanently unexecuted”): 7 generating ops (cross_correlate / multipass / deform_pass / ensemble_correlate / replace_outliers / to_velocity / sample_at_windows) and 13 consuming ops (including overlap of 8 field quantities, 2 visualizations, 2 tests, 3 evaluations), so generation and consumption are closed within the family.
- L35 — ★ We always give it an exit (the 2 ops of
visualise) —— a type that can be made but not seen becomes a dead end mid-chain and produces a “narrow sort”. Fail-closed in both directions is also confirmed by measurement: passing a 2-D flow to reprconv.flow_magnitude raises ValueError (rejecting by name with “takes (3, D, H, W)”), and passing a 3-D scene flow to piv_vorticity raises ValueError. * the input image pair is image2d —— particle images are 2-D real fields themselves, so existing 2-D ops (smoothing, threshold, background subtraction, annotation) can be used with meaning intact. There is no guarantee brightness fits in [0,1], but that is the same standing as the composite of astrostack. * piv_outlier_mask is mask —— bool 2-D, as the predicate says. Unlike dem_stream_network, which could not call itself mask because it has nan, here missing data is folded to the True (outlier) side, so it is closed as bool. * statistics are table (dict). piv_error_stats / piv_peak_locking. * the output of the velocity conversion piv_to_velocity is also flow2d —— the unit changes from px/frame to m/s but the type is the same. Here we write honestly: the type cannot protect the unit. So we made both scales required arguments (the same judgment as cell_size of demops). We also considered separating the unit by type, but that would be a type where only 1 op makes m/s and no op consumes it —— contrary to the order “add after evidence emerges”, so we did not adopt it.
opsrangedoppler.py
- L108 — ★ Record of correction: the first draft of this module wrote “in real, the sign of velocity is lost”, but that was wrong (it is correct for a 1-D real signal of the range axis alone, but once 2 axes are present the sign is preserved). A test broke first and revealed it. What is actually lost is “which of the pair is real”, half the amplitude, and half the unambiguous ranging range.
_as_beat_cube rejects at the dtype stage and names the fix (explicitly build an analytic signal). ————————————————————————– Entry and exit to avoid a narrow sort (dealing with a measured lesson) ————————————————————————– This repo has actually stepped on 2 traps: (1) a type with no op that produces it is permanently unreachable (the case where score was the only 1 blocked among 434 ops), (2) piggybacking on an existing pool gets rejected fail-closed every time and looks like “zero findings” (the case where 7/17 of the photon family were unexecuted). beatcube is treated for both: entry (ops that produce beatcube) : fmcw_beat_simulate (arguments only, no input type) fmcw_window_apply (beatcube -> beatcube) exit (ops that return to an existing sort) : range_doppler_map -> image2d (largest pool) fmcw_range_profile -> signal beamform_delay_sum -> signal beamform_doa -> table The point that the entry is an “argument-only source” is the same form as tcspc_simulate (no input type -> counts), so the chained fuzzer needs a dedicated generator just like counts (a hand-off item for the parent; the actual generator is included in the report with execution confirmed). The exit falls into image2d and signal, 2 of the largest pools in this repo, so it does not become a closed narrow sort like jones (2 ops) or countrate (2 ops).
opsreprconv.py
- L257 — ★
flow cannot be written with a single predicate. Because dense (3,D,H,W) and scattered (N,3) coexist under the same type name, a predicate that passes both protects nothing, and deciding on one necessarily makes one of the existing 4 ops a TYPEMISS. Separating is correct (the same judgment as separating video from voxel), but that is work to rewrite the declarations of existing ops and is outside this module’s scope, so here we only leave the proposal.
opsvolcolor.py
- L63 — ★ However, the existing
labels predicate is ndim >= 1, and a 2-D label image and a 3-D label volume coexist. The 11 ops of this module all raise ValueError (fail-closed) when passed 2-D, so a mix-up never silently passes. The danger is the reverse: in a pool with only 2-D seeds it looks like “zero findings” while never being executed —— the same form as the trap opsphoton stepped on with counts. Be sure to pour 3-D label seeds on the wiring side (see “when the parent wires” below). * voxel — the source grey volume that vol_label_overlay overlays, and the binary volume that vol_label_color_flicker receives. Both are the existing voxel vocabulary of (D,H,W) itself, so there is no reason to make a new term. * rgbimage — the return of cross-sections and projections (H,W,3). Existing rgbimage-consuming ops (specular separation, color conversion, save) can be used with meaning intact. This is the exit of the rgbvolume vocabulary, so the new vocabulary is not a dead end. * matrix — the return of vol_label_palette (n+1, 3). A 2-D real matrix itself. * table — a set of shape statistics / legend / flicker measurement / colored mesh.
- L77 — ★ Not making a new vocabulary for “a set of colored meshes” was the result of measurement. At first we intended to add
colormeshes, but when we swept all existing table-consuming ops and passed the return of vol_labels_to_meshes (measured 2026-09-02, across ops3d / ops1d / opsmath / opsoptics / opslightfield / opsphoton / opsacoustics / opsinterferometry / opscadmap), the ops that consume table are only 3 (abcd_matrix / wavefront_stats / istft), and all 3 fail-closed with ValueError. That is, it does not meet the condition “mixing makes it silently wrong”. Adding a vocabulary to something that does not meet it just adds one new consumer-zero vocabulary = one dead end (the decision criterion of docs/OP_COMBINATION_MATRIX.md). Note that when you want to flow individual meshes downstream as the mesh sort, strip them with [(m["vertices"], m["faces"]) for m in result] —— since this discards color, do not do it implicitly in an adapter. ————————————————————————– One new vocabulary and its reason (measurement-based) ————————————————————————– * rgbvolume — a (D, H, W, 3) colored volume. The existing lightfield predicate is only ndim == 4, so a color volume fully satisfies lightfield. Measured (2026-09-02, passing a (8, 16, 16, 3) color volume to lightfield ops): - lf_refocus / lf_subaperture / lf_epi / lf_depth_from_focus, these 4 ops return a finite (16, 3) result with neither exception nor NaN (each claiming “refocused image”, “sub-aperture image”, “EPI”, “depth”). Meaningless finite values, read with the z-axis as angular axis V and the y-axis as angular axis U. - only lf_all_in_focus gives a TypeError from insufficient arguments (not a type matter). The reverse (a light field to vol_label_slice_rgb) fails closed with shape[3] != 3. Only one side is safe, so runtime checks cannot be relied on. The same judgment as separating zscan from video. Entry = vol_colorize_labels (labels -> rgbvolume) and vol_label_overlay (voxel + labels -> rgbvolume), exit = vol_label_slice_rgb / vol_label_mpr_rgb (-> rgbimage). Produced 2, consumed 2, so no dead end.
pcseg.py
- L448 — ★
full_matrices=True (default) allocates the (N, N) U and throws it away. Measured 2026-09-06: for 20000 points, 3.73 s / 3.2 GB, whereas full_matrices=False is 0.876 ms (4263x) with Vt bit-identical. For 100k points it dies at 80 GB. The same pattern was in pcseg.fit_plane / measure / ops / camera / pnp3d (all throwing away U). The static gate is tests/test_svd_full_matrices.py.
pivops.py
- L470 — ★ A window where the correlation peak does not stand (no texture, uniform everywhere) returns nan —— we do not return 0 so as not to mix “not moving” with “unknown”. But what fraction is nan can only be known from the return value, and the form was such that you only notice when
flow.mean() becomes nan (2026-09-06). We count it here. Measured: an image with only a 16x16 square on a uniform background has only 16 of 98 windows finite (0.163). Full texture gives 1.000.
ppf.py
- L126 — ★ Raw PCA normals have an arbitrary sign, and under rotation flip on 40% of points. Since PPF features are angles between normals, if they flip the key changes. Measured (400 points, about the z-axis): with raw normals the key match rate at 0/37/90/143 degrees is 100 / 73.6 / 69.4 / 67.2 %, with oriented normals all 100 %. The same hole that
pointcloud.fpfh had stepped on, fixed together the same day.
problems.py
- L147 — ★A deterministic global shuffle (fixed base, so train/holdout/locked index the SAME permutation) split into three DISJOINT bands keyed by the seed’s role (evolve.run draws train=seed, holdout=seed+10000, locked=seed+20000, so seed//10000 mod 3 picks the band). The old
off = seed % pool collapsed all three windows to the SAME frames whenever pool divided 10000 — a silent train↔holdout↔locked leak that made a train-overfit champion look like it “beat hand on a pure holdout”. A pure 3-way split needs pool >= 3n; a smaller pool cannot yield a clean holdout, so we refuse rather than leak silently.
profileops.py
- L269 — ★ At first we wrote it as “the one with larger curvature” and judged the trailing edge as the leading edge on NACA 2412. The curvature of the 3-point circle comes out larger at the trailing edge, where the upper and lower surfaces nearly touch, than at the roundness of the leading edge —— the intuition “the leading edge is round” reverses when measured with 3 points on the contour.
- L276 — ★ When the trailing edge is open, the 2 farthest points pick one of the corners of the trailing edge and the chord tilts. We re-take it at the midpoint of the gap, then decide the leading edge as “the point farthest from that midpoint”. Without doing this, even a symmetric airfoil shows camber by the half-gap of the trailing edge (measured 0.001257).
- L642 — ★ Before comparing, re-take by the same method. The chord frame (especially the trailing-edge midpoint) depends slightly on the placement of points, so matching a raw contour against a re-taken contour injects a 0.02 degree rotation and 7.8e-4 translation even for an identical shape —— that itself became the floor of the deviation (measured rms 6.05e-4). Put what you compare on the same footing.
- L653 — ★ Measure not point-to-point but point-to-polyline. Even after re-taking at equal arc length, the phases of the two do not coincide, so taking correspondence by index makes the phase shift become the deviation directly (measured: comparing the same shape against itself gives rms 6.05e-4 —— the same order as the defect we want to detect).
realdata.py
- L38 — ★ Only those whose
public column is true may be used in figures to be published. Those limited to cited use for research and education purposes carry cite.
- L90 — ★ skimage only holds a bundled subset; the rest it fetches at runtime via pooch. Whatever it cannot fetch we do not use in this repo (if a PoC depends on the connection, it becomes unclear whether a failure was the implementation or the network).
reprconv.py
- L149 — ★ For conversion to an integer dtype, inspect the raw value before the cast. A hole found by adversarial inspection (2026-09-02):
np.asarray(nan, dtype=int64) raises no exception and returns INT_MIN, and after the cast dtype.kind == 'i' so it slips past the non-finite check below. A non-integer like 3.7 is also silently truncated to 3 —— a result off by 1 in the index is returned with no exception. This is exactly the lie of a conversion op.
- L1080 — ★ Regression point of a real bug. At first this was
np.maximum(sigma, finfo.tiny). At a duplicate point sigma = 2.2e-308, and sigma ** 3 in gaussians_to_voxel underflows to 0, causing division by zero -> NaN. What was meant to “avoid 0” was replaced with a value that produces NaN downstream (part of the volume becomes NaN with no exception = the textbook silent error). Since a duplicate point means “the spacing cannot be measured”, fail-closed instead of padding with a sentinel.
rust/fullseye_core/examples/python_ctypes.py
- L42 (ja) — ★第 5 引数 fs_dtype_t。2026-09-14 までヘッダにだけ在って実装と FFI 宣言に 無かった引数。ctypes は引数の数を検査しないので、抜けても黙って動く。
sample_data.py
- L147 — ★ Reason for adding it: in exhibits 111-113 it re-emerged that “synthesis can only produce the breakage it already knows” (a precedent where 9 defects appeared in 6 real shots). The PoC stays closed offline, and we place only the entry that swaps in real data in the ledger. For commercial=”check” and above, read the source’s page before using.
scene_registry.py
- L19 (ja) — ★配布物にローカル絶対パスを焼き込まない。ここは自分のマシンの作業物を指していた ので、他人が pip install した環境では黙って落ちる(しかも「場面が無い」ではなく 「その場面だけ静かに欠ける」形で)。環境変数で受け、未設定ならその場面を登録しない = 在ると偽らない。
loco_mujoco は入っていれば自分で在り処を知っているので探す。
sdf_ops.py
- L293 — ★ Reason for adding it, based on measurement:
poc_dfm_thickness_overhang and poc_cad_scan_deviation reported that # “a machine part is made of cylindrical holes, chamfers, and fillets, but since the primitives are only sphere and # box, it cannot be assembled with CSG”, and both wrote per-face analytic formulas themselves. The 4 here are all closed-form and exact (outside is the # Euclidean distance to the nearest surface, inside is the negative to the nearest face), so a synthetic part with # ground truth can now be assembled with CSG alone. # ————————————————————————— #
specops.py
- L810 — ★ This is a value that depends on both the staining and the imaging system and is not a universal constant —— if you quantify on your own slides, shoot a single-stain slide and re-measure it with :func:
stain_vectors_from_patches.
- L842 — ★ The 3rd vector is “the remainder”. With only 2, a 2x3 has no inverse, and using the pseudo-inverse silently distributes the residual to the 2. Set up an orthogonal 3rd vector and gather the density with no place to go into it (= it can be read later as the residual).
studio.py
- L273 — ★ Right-click on the figure itself (user 2026-09-06: “it would be nice to be able to right-click what is shown as a figure and copy it to the clipboard”). A Studio UI convention of this repo —— the display side must let you do everything from a right-click too. It can do the same as the button row below (do not make it one or the other).
- L6119 — ★ The receptacle for figures. The examples write a PNG here via
examplefig. In runs that pass no environment variable (CLI), not a single one is written, so a picture appears only when run from the gallery (the example’s numbers and speed do not change).
- L6275 — ★ The receptacle for figures. The examples write a PNG here via
examplefig. In runs that pass no environment variable (CLI), not a single one is written, so a picture appears only when run from the gallery (the example’s numbers and speed do not change).
tests/conftest.py
- L28 — ★ Escape Studio’s settings to a disposable ini for the whole session. # ————————————————————————— #
QSettings("Fullseye", "Studio") writes to the native store (on Windows, the registry HKCU\Software\Fullseye\Studio). We had placed the isolation in individual test files, so a file where it was forgotten polluted the user’s real registry. An audit on 2026-09-05 confirmed actual harm: 8 of the 10 recent_files were pytest temp paths, and real values like system\operator_timeout_ms also remained. (Isolation was in only 2 of 3 files, and test_studio_params.py passed through.) Stop adding it individually and place just one, here, as a session autouse. The environment variable is the only entrance that studio._settings() looks at, so this covers all tests.
- L44 — ★ Declaration of tests that need an optional backend. # ————————————————————————— # The CI note long said “do not install torch/kornia (corresponding tests graceful skip)”, but a measurement on 2026-09-05 showed that was not true —— the target tests did not skip but failed with
ImportError: this operator needs the optional 'torch' backend (14 of them). There was only a note, and no mechanism to verify it mechanically. Here we consolidate the declaration into a single entrance. The aim is both directions: * an environment without the backend -> skip (make the note true) * an environment where the backend should be present -> do not allow skip, make it fail (FULLSEYE_REQUIRE_OPTIONAL=1. The CI py3.11 job sets this) With only one direction, a genuine regression quietly turns into a skip (the same form as feedback_failsoft_hides_permanently_dead_ops).
- L192 (ja) — ★2026-09-14 追加。ここまで探針バンクは 6 sort しか無く、901 op のうち 151 本 (16.8 %)が契約ゲート 3 本(例外を投げない / 非有限を出さない / 決定的)を 一度も実行されていなかった ——
PROBELESS_OPS_BUDGET = 151 というラチェットで 本数だけ凍結し、「本来の直しは BANKS を全 in_sort へ広げること」と自分で書いて あった。その本来の直しをここで入れる。 形の出どころは推測ではない: backends_bridge._EMPTY_OF が 12 sort すべての 正準の最小値を宣言しており(そこが sort の定義そのもの)、problems.py の _points_stack / _signal_stack などが実データの作り方を持っている。 各バンクは既存の作法に合わせ、普通の値・定数 0・定数 1・退化形を混ぜる (定数と退化形が「走った」と「意味のある出力」を分ける —— [[feedback_ran_is_not_meaningful_output]])。 ————————————————————————— #
- L215 (ja) — ★点群は連結なものと非連結なものの両方を置く。
tb_geodesic_distances が 不達を inf で表すのは契約どおりで、ops.NONFINITE_IS_MEANINGFUL に 「1.0 に潰すと『届かない』が『近い』に化ける」と宣言済み。 ここで一度 normal をわざと連結にして有限性ゲートを緑にしかけたが、 それは欠陥を隠す方向だった —— 直すべきは門が台帳を見ていないこと。 normal は橋でつないだ現実的な形、two_clusters は非連結を撃つ探針。
- L263 (ja) — ★特異行列は必ず置く。 一度ここから外しかけたが、それは誤りだった ——
tb_mat_cond が特異行列で inf を返すのは契約どおりで、ops.py の NONFINITE_IS_MEANINGFUL に「厳密に特異な行列は s_min=0 なので inf が 正しい答え。有限に潰すと『十分に良条件』と読めてしまう」と既に宣言済み だった。落ちていたのは op ではなく、有限性ゲートがその台帳を見ていない こと。探針を削って緑にするのは、欠陥を隠す行為。 (同じ註に 2026-09-05 の教訓が書いてある ——「自分の probe では特異行列を 作っていなかったので tb_mat_cond を取りこぼした」。探針から外すのは その取りこぼしをわざと再現することになる。)
- L381 (ja) — ★新規(2026-09-14): ここまで探針が無く、契約ゲートを一度も通っていなかった 5 sort = 101 op。残る 6 sort(video / qimage / cimage / lightfield / beatcube = 50 op)は形が複素・4-D で退化形の設計に手間が要るため、 一度に全部入れて切り分け不能にしないよう次の段で足す。
tests/test_abi_apply.py
- L78 (ja) — ★target dir は 別に切る。最初は
target/release(既定)に建ててそこから直接ロードして いたが、同じプロセスで後に走る test_rust_abi_parity.py が cargo build --release (feature なし)で同じ DLL を書き換えようとし、ロード済みでロックされているので ビルドに失敗 → 36 件が黙って SKIP になった([[feedback_zero_findings_may_mean_never_executed]])。 建てる場所を分け、ロードは tmp へのコピーから行う。
- L49 (ja) — ★このパーサは「タグから最初の
; まで」を宣言とみなす。だからタグと 宣言のあいだに ; を含む散文があると、宣言が見つからず collection 中に 死ぬ —— そして pytest はファイル 1 つの collection エラーで スイート全体を中断する(2026-09-14 実測: Interrupted: 1 error during collection で 12,000 件が 1 件も走らず、それでも runner の exit code は 0)。 [[feedback_test_import_kills_collection]] と同じ族なので、何が悪くて どう直すかをここで言う。黙って「malformed」とだけ言うと、壊した本人が ヘッダの書式規則に気づけない。
- L234 (ja) — ★2026-09-14:
FsValueError を足した。それまで例外は 2 種しか無く、 種の違う失敗が同じ status に潰れていた —— 逆さの区間は契約では FS_E_INVALID_ARG なのに FsTypeError(= FS_E_TYPE)を投げていた。 差分テストが「どちらも拒否した」までしか見ていなかったので素通りした。
tests/test_abi_signatures_match.py
- L82 (ja) — ★
[A] + [B] * 3 のような式で書かれた argtypes がある。最初この形を 数えられず fs_measure_all を「1 引数」と誤読して門が 3 件赤になった —— 門のパーサが弱いのを実装の欠陥と読まない。 行末までを 1 宣言として 取り、[...] の各塊の要素数に * N の倍数を掛けて合計する。
- L180 (ja) — ★
cl に .h を直接渡してはいけない —— MSVC は拡張子で言語を決めるので 「ソースファイルの種類は認識できません」と警告だけ出して rc=0 を返す。 検査が 1 行も走っていないのに緑になる、最悪の形 ([[feedback_ran_is_not_meaningful_output]]。2026-09-14 に実際そう読みかけた)。 #include する小さな .c / .cpp を作って /Zs(構文検査のみ)を掛ける。
- L190 (ja) — ★引用は 1 段も挟まない。
subprocess にリストで渡すと Python が 引数を再クォートし、内側の " が \" に化けて cmd に届く (実測のエラー: '\"C:\Program Files...\vcvars64.bat\"' は認識されて いません)。バッチファイルに書き出して、それを叩くのが確実。
tests/test_annotate_bold_italic.py
- L59 — ★ Overstriking only thickens sideways. An outline that thickens up and down fills in the counters of CJK text (measured 2026-09-09: 11pt “quantity value area” became a black blob).
tests/test_astrostack.py
- L1053 — ★ 2026-09-08: a 3rd return value, vote_margin (2nd-place peak / 1st-place), was added. For a starfield the peak should be single and thus small —— fix that here too.
tests/test_backends_typed_liveness.py
- L57 — ★ For this one, there were 3 records —— here,
gen_op_figures.DOMAIN_MISMATCH, and the op’s own measured 0/60. Even so, the state of “registered yet never runs” continued. Knowing something and using it in a decision are different (KNOWN_ISSUES §42).
tests/test_blob2d.py
- L442 — ★All three objects must have different shapes. A seed of the same shape lined up makes circularity and holes all return the same value, hiding an “op that returns the same number for any knob”.
tests/test_caltab.py
- L121 — ★Whether the gate fires is environment-dependent, so do not assert it. Only check that the value is returned without being hidden.
tests/test_ci_wheel_check_paths.py
- L68 — ★Do not look at returncode. What this check targets is argument resolution, not the contents of the wheel. Judging the contents depends on the environment —— measured 2026-09-05: in an environment that exposes the source via PYTHONPATH, because the script drops the repo root from sys.path, some modules cannot be imported and it fails (this does not happen in a pip-installed environment). Because returncode was being looked at here, on Linux this check was failing in a way that made it look like a “path resolution problem”.
tests/test_collection_sizes.py
- L64 — ★OPS3D is a flat table of {op name: metadata dict}. Counting it as
sum(len(v) for v in values()) yields the total number of metadata keys across all ops (2,492), which would have carved a meaningless number into the ledger (2026-09-08; I noticed by looking at the structure before writing).
- L85 — ★Added 2026-09-08: two ledgers that accumulate descriptions. Descriptions are what quietly shrink most, so count them here (the source of docs/CAPABILITIES.md and docs/HARDENING.md).
- L260 — ★What makes this tricky is that the defect this test guards against does not reproduce on Windows. Measured 2026-09-05: on Linux (Ubuntu 24.04 / py3.12 / PyPI wheel) 3 ops SIGSEGV on degenerate input. Feeding the same input to Windows crashed none of them. So “local is green” is no evidence, and it must be kept in a form where you can verify that the ledger is actually taking effect on both environments. ————————————————————————— #
- L267 — ★The counterpart to
ops.NATIVE_CRASHES_ON_DEGENERATE. It must match the main table 1:1. Changing only one side fails —— removing from the main table, or adding to it, requires rewriting here at the same time (= a human confirms the intent). Why a counterpart is needed: in gate mutation testing (2026-09-05), even after removing cv_cc_count from the main table, the test checking “every op in the ledger has a guard” still passed. An op removed from the ledger also drops out of the loop’s targets, so the entire check path disappears with it. The SIGSEGV being guarded is Linux-only, and on Windows a decent value happens to come back, so the last line of defense also fails to work. Only equivalence with an independent source (this set) catches both directions even on Windows. Same shape as test_the_two_nonfinite_ledgers_agree.
tests/test_demops.py
- L440 — ★The return is always (N, 3). Even passing a scalar yields (1, 3), not (3,) —— because the ledger declares points = (N, 3) (2026-09-06; the fuzzer’s TYPEMISS exposed the mismatch and the implementation was aligned to the declaration).
tests/test_docs_index_numbers.py
- L37 — ★The op set changes with the environment (Linux CI lacks torch/kornia/mahotas/xfeatures2d and has 859 ops; locally 885). A check comparing the locally generated docs against the live registry is only meaningful in a full environment —— same convention as test_opdocs: skip if not complete (the missing backend name appears in the reason). On the 2026-09-07 CI, 22 items failed on this. Environment-independent checks (file existence, content volume, figure existence) still run.
tests/test_docs_index_reachable.py
- L42 — ★The op set changes with the environment (Linux CI lacks torch/kornia/mahotas/xfeatures2d and has 859 ops; locally 885). A check comparing the locally generated docs against the live registry is only meaningful in a full environment —— same convention as test_opdocs: skip if not complete (the missing backend name appears in the reason). On the 2026-09-07 CI, 22 items failed on this. Environment-independent checks (file existence, content volume, figure existence) still run.
- L80 — ★Looking only at Markdown syntax falls short.
docs/GALLERY.md uses <img src="..."> in 14 places inside tables, and a naive scan for ]( sees none of them (found in Codex’s adversarial review, 2026-09-06). Also look at raw HTML.
- L189 — ★Allowing duplicate markers lets an old table stay behind while still going green. The generator only rewrites the first start–end, so the second stays forever old and keeps getting published (Codex’s adversarial review, 2026-09-06).
- L210 — ★It used to pass on “there are 20 lines and 4 dimension names are visible”, but that goes green even if hundreds of ops drop (Codex’s adversarial review, 2026-09-06). Reconcile against the actual count per dimension, down to the last one.
- L249 — ★Output where they differ. Without it, you cannot chase order-dependent failures (like registry pollution) that only fail in the full suite.
- L312 — ★With only counts and names, the type contract (in_sort/out_sort), category, HALCON correspondence, and tier all stay stale while going green (Codex’s adversarial review, 2026-09-06). RAG reads in_sort/out_sort to pick type-connectable ops, so if that is stale it confidently proposes a chain that does not connect. Reconcile including the contents.
- L457 — ★Check that the output “has content” —— a gate that only checks agreement goes green even when both are empty # ————————————————————————— # Measured 2026-09-06. Falls below it and it fails (raising it is fine).
tests/test_dsp.py
- L338 — ★The maximum is the harmonic: period / (1/f_max_bin) lands near an integer
tests/test_example_scripts_run.py
- L48 — ★2026-09-09, on the first CI after adding this gate, 7 failed on py3.12 (py3.11 was green). CI deliberately installs torch / kornia / mahotas / opencv-contrib only on py3.11 and not on other versions. The test side already had a declaration mechanism called
requires_backend, yet the gate that runs the examples did not have it —— that a mechanism exists and that every path goes through it are different things. gallery2d_* is a gallery that “runs all ops of that family”, so its very contract depends on which backends are installed (it hard-codes op names and reconciles against the registry, failing with “extra in OPS” if even one is missing). So declare per family. The remaining 2 use torch directly (fit_zernike / match_logpolar_z). In a full environment (CI’s py3.11, FULLSEYE_REQUIRE_OPTIONAL=1) a skip becomes a failure, so both over-declaring and forgetting to declare fail in both directions.
- L87 — ★Do not pass PYTHONPATH (the whole point of this gate). Users do not set environment variables.
tests/test_flyvision.py
- L328 — ★ The MTF identity is a small-footprint approximation and is NOT claimed
- L329 — ★ far from the optical axis: at ~35 deg elevation the measured transfer
- L330 — ★ already departs from exp(-…) by more than the on-axis tolerance. This
- L331 — ★ assert pins that hole so a future “curvature-corrected” resample has a
- L332 — ★ failing test to turn green rather than a silent regression to argue about.
tests/test_fslib.py
- L330 (ja) — backend 横断の一致 —— ★2026-09-14 に実際に壊れていたところ ————————————————————————— #
tests/test_fullseye_3dgs.py
- L78 (ja) — ★道具の有無と資産の有無は別。ここは mujoco の有無だけを見ていたので、 Menagerie が無い環境では
scene_registry.resolve() が返す None を掴んで TypeError になった。同ファイルの test_scene_resolution_via_registry は 既に資産の skip を持っており、作法が兄弟に適用されていなかった。
tests/test_gaits.py
- L99 (ja) — ★2026-09-14: ここは
resolve() の戻りを検査せず spec["xml"] を引いていた。 scene_registry が実在しない場面に None を返す設計(資産が無い環境では 正しい振る舞い)なので、資産チェックアウトが無いと TypeError で落ちる。 同じファイル群の test_fullseye_3dgs.py は既にこの skip 作法を持っていた —— 作法が兄弟に適用されていなかった ([[feedback_same_bug_class_recurs_check_siblings]])。
tests/test_glassmirror.py
- L91 — ★It was counterintuitive: thinking “copper is redder than gold”, I wrote cu[2] < au[2] and it failed. Even by published values, against Au’s R(450 nm) ≈ 0.40, Cu ≈ 0.56, so copper has more blue (= gold is the more saturated yellow). It was this preconception, not the table, that was wrong.
- L175 — ★The reason wavelength was made the first argument (the ledger’s “data comes first” convention). Passing an array to the apex angle used to raise a bare TypeError.
tests/test_honest_summary_arithmetic.py
- L41 — Make it “skip with a reason if absent” —— ★the 2026-09-08 CI went red here: assuming what you have locally is also present in CI makes only local green (same pattern as
feedback_gate_computed_a_verdict_then_discarded_it).
tests/test_mcp_images.py
- L312 (ja) — ★最初
ones + inf にしていて、有限部が定数なので免除 op でも「定数」判定になり 落ちた —— それは診断器が正しい。確かめたいのは「免除 op なら非有限を異常と 言わない」だけなので、有限部に変化のある入力にする。
tests/test_mcp_server.py
- L57 (ja) — ★引数名を
name にしていて _call(4, "fullseye_op_help", name="gaussian") が TypeError になり、subprocess の実 stdio 往復が 1 度も走らないまま 23 件が緑だった(2026-09-15)。走らなかった検査は無いのと同じ。
- L105 (ja) — ★最初
gaussian が先頭と決めつけて落ちた。gauss_filter と gaussian は同じ HALCON 別名を共有する別 op で、api.find_op は name == halcon の正典を優先する。 検索もその規約に揃えたので、正典が先頭・gaussian が上位に居ることを見る。
- L249 (ja) — ★以前の被験者は台帳経由で索引に入ったこと(= 索引が台帳を数えている)も見る
- L316 (ja) — ★同日実測: 4 層で 480 枚が「どこにも無いノート」に見えたが、5 層目(ledger)で 480 / 480 が解決した。ここが 0 でなくなったら、まず引き忘れた層を疑うこと ([[feedback_search_all_tiers_before_declaring_a_gap]])。ノートの残骸と決めつけない。
tests/test_no_local_paths_in_shipped_code.py
- L22 — ★
tomllib is from Python 3.11. A bare import at the module top aborts collection on 3.10, and not a single test runs —— right after stepping on the same thing with hypothesis on 2026-09-05, I reproduced it in this check (CI py3.10 collection error). Always drop import failures to skip.
- L53 (ja) — ★2026-09-14 追加: MSVC の標準インストール先。
fullseye_3dgs._find_cl_dir() が cl.exe を探すための候補として持っている。これは「私のマシンの作業物を 指している」のではなく「Visual Studio インストーラが決める場所」なので、 環境変数に追い出しても他人の環境で当たりやすくはならない(むしろ探索が 効かなくなる)。glob で実在を確かめてから使い、無ければ None を返す作りに なっていることを確認済み。 ※ _WIN_ABS は空白入りの語を 2 つ目までしか拾わないので、切り出される断片は C:\Program Files\Microsoft までになる。許可文字列は実際に切り出される形に 合わせる —— 正規表現の結果を見ずに「あるべき文字列」を書いて外した(2026-09-14)。
tests/test_op_contract_property.py
- L32 — ★In an environment without hypothesis, an import failure in this one file stops the whole thing —— pytest aborts on the collection error without running the rest (2026-09-05; CI died in 2 minutes and not a single test ran). Drop to skip so it does not drag others down.
tests/test_op_contracts.py
- L52 (ja) — ★2026-09-14 実測: 901 op 中 151 本(16.8 %) がこの状態で、空ループを 1 周 しただけで緑を返していた —— 「門が判定を計算した直後に捨てる」の親戚で、 こちらは 判定を一度も計算しない。まず skip で見えるようにし、
test_probeless_ops_do_not_grow で本数を台帳に固定する(減る分には通る)。
- L56 (ja) — ★2026-09-14: 本来の直しを入れて 151 → 0 にした。 上に「本来の直しは
conftest.BANKS を全 in_sort へ広げること」と自分で書いておきながら、 ラチェットで本数を凍結したまま 9 日が過ぎていた —— 台帳は免罪符になりやすい ([[feedback_never_weaken_the_probe_to_get_green]])。 足したのは 11 sort: points(56) / signal(27) / video(16) / qimage(11) / cimage(9) / counts(8) / lightfield(8) / rgbimage(6) / matrix(4) / beatcube(4) / keypoints(2) = 151 op。形は推測ではなく backends_bridge._EMPTY_OF (12 sort すべての正準の最小値)と problems.py の入力生成器から取った。 これで 901 op すべてが 3 つの契約ゲートを実際に通る。 0 になった以上、このラチェットの役目は「増えたら落とす」に変わった。 新しい in_sort を足した人は conftest.BANKS に探針も足すこと —— 足さないと その op たちは「登録されているのに一度も実行されない」状態に戻る。
- L98 (ja) — ★非有限がその op の意味を運んでいるものは、この門の対象外。判断は ここで持たず
ops.NONFINITE_IS_MEANINGFUL を単一の正本として引く (test_backends_typed_liveness.KNOWN_NONFINITE_BY_CONTRACT が同じ表の 写しで、一致は別の検査が見ている。3 つ目の写しを作らない)。 2026-09-14: 探針バンクを 6 sort 広げたとき、ここで tb_mat_cond(特異行列の 条件数 = inf)と tb_geodesic_distances(不達 = inf)が落ちた。一度 探針から特異行列と非連結点群を外して緑にしかけたが、それは誤り —— 台帳は「inf が正しい答え」と既に宣言しており、落ちていたのは門がその 台帳を見ていないことだった。探針を削って緑にするのは欠陥を隠す行為で、 しかも同じ台帳の註に「自分の probe では特異行列を作っていなかったので tb_mat_cond を取りこぼした」という 2026-09-05 の教訓が書いてある。
tests/test_op_discovery.py
-
| L229 — ★It is not even a pass-through: the fallback returns after clamping to the image contract [0,1]. A signal whose negative half became 0 looks like a “filtered signal”, so this lies silently. max |
diff |
= 1.0, minimum -1.0 -> 0.0. |
tests/test_op_example_coverage.py
- L58 — ★A ratchet that counts the population from the shipped-artifact side (2026-09-06) # ————————————————————————— # Measured 2026-09-06. A stopper to not make it worse than this number, not a target. Of the ledger’s 1,002 ops, only 349 are in the example index, and the two “100 %” above held only because the population had 2 of 3 layers. History and per-family breakdown = docs/KNOWN_ISSUES.md §38.
- L32 — ★The op set changes with the environment (Linux CI lacks torch/kornia/mahotas/xfeatures2d and has 859 ops; locally 885). A check comparing the locally generated docs against the live registry is only meaningful in a full environment —— same convention as test_opdocs: skip if not complete (the missing backend name appears in the reason). On the 2026-09-07 CI, 22 items failed on this. Environment-independent checks (file existence, content volume, figure existence) still run.
- L203 — ★2026-09-08: exclude from the ledger and count separately any op that depends on the version of a third-party backend. This ledger is written in “the environment that made the figures” and verified in “the environment that runs the tests”. cv2 implementations change with the version, so a knob that does not work locally (opencv 5.0) works in CI (opencv-contrib 4.x) —— measured,
xcv_grabcut’s b was exactly that. The ledger may only assert things that hold in any environment. Do not assert version-dependent parts (a narrow but correct ledger is better than a lying one).
tests/test_op_probe_ledger.py
- L76 — ★Added 2026-09-08. Until then this gate only built inputs for the 4 of image / region / color / volume, letting
contour 65 / points 57 / signal 26 / video 16 … 217 ops (24 % of the 901-op registry) pass through as “uncallable”. That “the gate stands in the right place” and that “the gate passes everything” are different —— on the first widening, it surfaced that tb_angle_3points can never run under the probe (registered as points->feature, but the actual entity takes 3 vectors).
- L192 — ★The 2026-09-08 CI (py3.10 / py3.12, no torch) went red here —— because widening the probe to all sorts first reached an op that needs torch (
tb_points_to_voxel). “Broken” and “absent in this environment” are different verdicts, and mixing them turns an environmental difference into an implementation bug. In a full environment (FULLSEYE_REQUIRE_OPTIONAL=1), keep it as a failure as before.
tests/test_opdocs.py
- L212 — ★2026-09-03: since every backend’s _safe was consolidated into backend_safe.guard, judge by the structured marker the guard raises, not by string match on qualname (the guard also leaves “_safe(…)” in qualname, but that is for display).
- L1178 — ★Why it was not found:
ops.REGISTRY (899) and the 2-D notes (899) agree, so as long as you count from the registry side it looks like “zero missing”. I once concluded that and was wrong. So this gate counts from the tier-spanning index side (memory: feedback_search_all_tiers_before_declaring_a_gap). ————————————————————————— #
tests/test_packaging_foundation.py
- L170 — ★2026-09-07: the local wheel had sample_sources_ai adding 42 MB (96 MB). The cause was a stale build/lib/ cache (leftovers from before it was removed from package-data get repacked). It is an accident a config-reading check cannot catch, so the actual wheel is checked by tools/ci_wheel_check.py (unshipped_present) and the size cap in ci.yml. The directory was also moved outside the package (tools/fops_article/). Here we require the exclusion to be explicit (as insurance).
tests/test_pivops.py
- L621 — ★Looking only at the name-level
PARAM_HINTS makes the gate narrower than the fuzzer. chain_fuzz._bind_args also consults OP_PARAM_HINTS, which targets by op name, so look at both here too (2026-09-06: after putting dic’s window / method into OP_PARAM_HINTS, it was actually bindable yet only here it failed).
tests/test_poc_scripts_run.py
- L57 — ★2026-09-08: drop the fixed 6 and match the CPU count. On shared runners (2–4 vCPU) 6-way parallelism only slows each one, without shrinking the total time, and once the PoCs grew to 84, each job hit pytest’s 900-second timeout (py3.10 / 3.12). Locally (12 cores) it runs as before at 6 or more.
- L73 — ★Do not pass
PYTHONPATH (2026-09-09). For a long time PYTHONPATH=<repo> was passed, but that is a setting users do not make, and it meant the gate stood one step away from where the accident happens —— by the same blind spot, examples/piv_flow_from_particles.py and others stayed as “ModuleNotFoundError when run straight from a checkout” (that side did not even have a gate that runs it, so it went unnoticed. test_example_scripts_run.py). On the PoC side, 108 of 116 add the repo root to sys.path themselves, and the remaining 8 only import fullseye, so all pass even after removing it (measured).
- L91 — ★On failure, also return the tail of stdout. A PoC prints its findings and “which check failed” to stdout before SystemExit(1), so with stderr alone you only learn “exit 1” with nothing else (2026-09-07 CI, py3.10 poc_ct_fidelity).
- L100 — ★2026-09-07: this long returned 0, passing straight through the
assert code == 0 below —— a gate that discards its verdict right after computing it (measured: 3 PoCs never print PASS —— poc_dic_strain / poc_photoelasticity / poc_thermography_ndt). Return -2 so it fails.
- L122 — ★This gate runs the 84 PoCs in one batch (session fixture). That time is charged to the first test, so pyproject’s default timeout (900 seconds) fails on shared runners. Widen only here —— relaxing the default would also dull hang detection for other tests.
tests/test_public_reachability.py
- L71 (ja) — ★2026-09-14: この 13 本は 2026-09-05 から wheel に入っていなかったもので、 py-modules へ足した結果ここに現れた。演算子としては
unified._3DGS_OPS が _lazy_call(モジュール名, 関数名) で文字列から登録しているので、利用者には fullseye.op.<名前> 経由で届く。ここに残る 1〜6 本は各モジュールのデモ入口 (render_*_gif など)で、op ではなく絵を作る側。だから内部専用に置く。 —— 「配布から消えていた」を直すと「公開経路から見えない」が現れる、という 二段構えだった([[feedback_registered_only_gates_miss_unregistered]])。
- L88 (ja) — ★2026-09-15: 33 行すべてが公開経路(fullseye.<名前> / .ledger / .op)に届くように なっており、2 番目の検査が「この表から行を消すこと」と 33 件を挙げた。 消した 33: transforms / mosaic / fit_transform / tools_geom / matrix / shapematch / objmodel3d / matching3d / matching / calib / caltab / calibration3d / contours_xld / contours_xld2 / image_channels / filters_freq / filters_flow / regions_setops / regions_gen / region_morph / morph_minkowski / segmentation / image_gen / image_paint / misc_vision / imgops_nary / scattered / inspection / pipeline3d / watershed3d / mesh_decimate / sample_data / scale。 表は空でも残す —— 「出すべきなのに出ていない」ものが次に現れたときの器。名前>
tests/test_raster.py
- L26 — ★A bare import aborts the whole collection in an environment where it is absent (measured 2026-09-05).
tests/test_rust_abi_parity.py
- L402 (ja) — ★契約では FS_E_INVALID_ARG(引数が定義域の外)であって FS_E_TYPE ではない。
FsValueError を足すまでは両方 FsTypeError で、Rust が 1 を返すのに Python は 2 相当を投げる、という状態コードの食い違いが残っていた。
tests/test_shapestats.py
- L196 — ★Free the plane, and a uniform spread on one side gets entirely absorbed (measured 4.9e-35). The midpoint moves only halfway and the plane moves there too, so it does not remain as a left-right difference. This is a limit of this definition, not a defect —— if you want to see it, give the plane from outside, or add a landmark on the midline.
tests/test_studio.py
- L920 — ★
setDefaultFormat only affects the no-argument constructor, and Studio’s QSettings("Fullseye", "Studio") was fixed to the registry —— this fixture isolated nothing (2026-09-05; pytest’s paths were left in the registry). Point the main-side entry studio._settings() at an ini via an environment variable.
- L2029 — ★Building
QSettings("Fullseye", "Studio") directly bypasses the isolation and writes into the user’s registry (real harm confirmed in the 2026-09-05 audit). Keep the settings entry point to one.
tests/test_studio_logic.py
- L22 — ★The old setDefaultFormat approach had no effect on Studio’s QSettings(org, app). Point the main entry point studio._settings() at the ini (for the whole session).
tests/test_studio_ops_browser.py
- L11 — ★A plain import aborts the whole collection in an environment without matplotlib (pytest won’t run the rest after a single import failure). Measured 2026-09-05.
tests/test_videostream.py
-
| L319 — ★Collins (VSAM 2000): both are relative to the current frame. Until 2026-09-05 this test expected the consecutive pair |
f[t-1]-f[t-2] |
, freezing an implementation bug as the spec (always all-zero for a uniform object moving at constant velocity – the regression test below). |
- L43 — ★The catalog, hints and adapters have the shipped module
typed_catalog as the source of truth (2026-09-05). They used to live here, and backends_typed read them by adding tools/ to sys.path – as a result tb_* 143 op silently vanished in the wheel. The direction was reversed.
- L256 — Event positions (point process) – the entry point of point_spectrum. ★Don’t use uniform random only: without a periodic component you never once exercise the meaningful behavior of an “op that finds periods”, so seed it with structured data mixing 12 unrelated events into a series with period 17.0 (this repo’s discipline that random-only tests hide structural defects).
- L864 — ★A point cloud with non-finite values crashes the KD-tree construction itself with a raw ValueError (scipy: “data must be finite”). The pool is designed to record NONFINITE and keep the values, so a dirty point cloud arriving here is expected – the side that builds it must guard. Hit for real on 2026-09-06: a new family was added, the way chains are walked changed, and at seed 3_000_0xx this path was struck and the fuzzer itself halted (not a defect of the op but a defect of the tool. The promise is that unbindable input is skipped, not raised).
- L1557 — ★Until 2026-09-02 it was
lambda v: True = since the predicate is counted as “present”, it’s worse than absent (the inspection script also counts it as “has a predicate”). Measured, it let through even None / 42 / a string / a dict. The canon was decided by running all of the 6 consuming op (reprconv’s pairs_to_signal / pairs_to_image2d / pairs_to_table / angles_to_normals / shape_index_to_curvature / polar_to_cscalar): all 6 op accept only the two shapes above, and everything else becomes a named fail-closed with “pairs: must be (N, 2) or a 2-tuple of equal-length 1-D arrays” (measured). Since (2,N) is not accepted, the 3 adapters that were collapsing a 2-tuple into (2,N) with np.stack were fixed to axis=1. Two arrays of differing length (histogram’s counts/edges) are also not a “pair” and are rejected.
- L1667 — ★”Exactly 2 elements” is deliberately different from pose (which allows info via
len >= 2). Measured 2026-09-02: the 4 existing consumers that take a mesh as one argument (face_normals / vertex_normals / mesh_area / vertex_curvature) emit “mesh must be a 2-element tuple (vertices, faces)” for a 3-tuple, and cadmap’s _mesh and render3d._mesh_arrays also accept only 2 elements. In other words the canon for this repo’s mesh sort is a 2-tuple, and an extra element is not “more information” but a type-level lie that wipes out everything downstream. The sole exception voxel_to_mesh (which returns (v, f, n)) now has the canonical order extracted in ops3d.RESULT_ADAPTERS (treated the same as gicp / vol_label).
- L25 — ★Remove this script’s own location from sys.path. Python puts the script’s directory on sys.path[0], so launching from the checkout’s
tools/ lets things under tools/ (the non-bundled chain_fuzz etc.) be imported even in the wheel’s venv, and you end up counting in a state where “things not in the wheel are visible”. In the 2026-09-05 review, this is exactly why this gate missed the absence of tb_* 143 op. Together with that, move cwd to an empty temporary directory as well (the same thing happens if cwd is the checkout).
- L34 — ★Before moving cwd, remember the original cwd and resolve all argument paths against it from then on. Measured 2026-09-05: preflight passes absolute paths so it passed locally, while ci.yml passes relative paths so the dump was written away into a temp dir and compare failed with FileNotFoundError – the gate never once ran the comparison on the production call path. The 3rd time for “stand the gate where the accident happens”. Rather than fixing the caller, make it work correctly even when called with relative paths, closing off this whole type.
- L139 — ★2026-09-08: look at the editable side too. Until then
a["failed_backends"] was only collected and no one read it – caught in the same round as a hole of the same type as examplefig’s figure failures. The editable venv has many optional dependencies, so a backend can fail to import due to a version mismatch. In that case the wheel side merely “isn’t there from the start because the dependency is absent”, records no failure, and this comparison passes green. The op of the fallen backend silently vanish from the registry.
- L92 — ★This can be gotten wrong twice. The fuzzer’s
run_chain (1) treats the input type any as “always available” (drawing arbitrarily from the pool), and (2) op registered in OP_ARG_BUILDERS build their arguments themselves. Without counting these two, an op that actually runs every time gets reported as “structurally unreachable” (it did misreport fuse_to_voxel / register_cross). Reachability is not determined by “type alone” – part of the reachability path is on the code side.
- L89 (ja) — ★2026-09-14 追加。45,000 ケースを 3 秒で「食い違いなし」と言われたとき、 信じるのではなく自分が printf で挙げた「踏んでいない座標」を足す。 一致したときこそ探針を疑う([[feedback_one_probe_input_is_not_coverage]])。
- L185 (ja) — ★2026-09-14: ここは長らく値域だけを振って画素は 0..1 のままだった。相対しきい値は 値域を通して解決されるので、値域 (100,300) では絶対値 100〜300 と比べられ、 100% が空になっていた(実測: (100,300) は 780/780 が 0 画素、全体でも 63% が 物体 0 個)。4000 ケースが 0.6 秒で「食い違いなし」だったのは頑健だからではなく、 connection も measure_all もほとんど踏んでいなかったから ([[feedback_zero_findings_may_mean_never_executed]])。値域を名乗らせるなら 画素もその値域で描く。
- L198 (ja) — ★しきい値は画像に実在する値から引く。独立に引いていたときは 41% が 「選択 0 画素」で、物体が 2 個以上あるのは 14% だけだった ——
connection の 分岐(斜め接触・入れ子・多数)をほとんど踏んでいない。乱数で撒くと空ばかりに なるのは、しきい値も探針の一部だから ([[feedback_one_probe_input_is_not_coverage]]: 探針は入力画像だけではない)。 2 割は「当てずっぽう」のまま残す —— 空・全面・範囲外という端も要る。
- L236 (ja) — ★R-3 の相対→絶対の写像と画像の形。契約の関数なのに観測していなかった。
- L265 (ja) — ★
fs_region_runs は契約が「領域表現の唯一の窓」と呼ぶもの。それを 観測していなかった —— 面積と本数が合っていても、run の切り方が違えば run-length と dense mask は別物として振る舞う(隣接 run を結合するか、 行内の並びは昇順か)。観測していない性質はケース数では出ない。
- L295 (ja) — ★並びそのものを観測する。
sorted して比べていたので、物体の順序を逆にする 変異が 3,000 ケースで 1 件も殺せなかった(2026-09-14 の変異解析)。契約は 「最初の run の (row, col) 昇順」と明記しているのに、門がどこにも無かった —— 観測していないものは、どれだけケースを撒いても出てこない。
- L337 (ja) — ★R-3 の相対→絶対の写像そのものを観測する(契約
fs_image_absolute)。
- L351 (ja) — ★種別を捨てない。ここは長らく固定値 1 だったので、
_status_of を 書いて compare にコード比較まで足したのに、Python 側が常に 1 を 名乗るせいで状態コードの食い違いが構造的に出なかった(変異 m8 が 3,000 ケースで殺せなかった正体)。観測を足したつもりで足しきれて いない、という [[feedback_gate_computed_a_verdict_then_discarded_it]] の型。
- L381 (ja) — ★コードの値まで見る。「どちらも拒否した」で止めていたので、 契約が FS_E_INVALID_ARG(1)と決めている所で Python が FS_E_TYPE(2) 相当を投げていても素通りしていた(2026-09-14 に実際そうだった)。
- L390 (ja) — ★許容差は値域に対する相対で取る。絶対値で 1e-5 と決めていたら、 値域 (100,300) の画像で 1.04e-05 の差が「食い違い」として報告された —— が、切り分けると Rust vs scipy は float64 のままなら 8.53e-14、 float32 を経由した途端 1.04e-05。つまり
fslib の astype(np.float32) の丸めで、欠陥ではなく私の測り方の欠陥だった(値域比で見ると どの値域でも一様に 1.4〜5.2e-08 = float32 の相対精度)。 [[feedback_second_instance_artifact_not_physics]] と同じ型 —— 驚く結果は物理(実装の違い)で説明する前に道具を疑う。
tools/gen_blas_article_figs.py
- L93 — ★Lay down the range where 1 thread was fastest in semi-transparency. Place it first so it doesn’t hide the lines, and keep alpha low (if the band itself asserts too much, comparing the lines gets hard to read).
- L37 — English names of the categories. ★Even in the English version only the headings stayed in Japanese (measured 7 lines) – the body was translated with
title_en / _summary_en, but the headings were forgotten, making it a textbook “switched but Japanese is mixed in” case. Categories not present here are emitted as-is (don’t invent translations).
- L45 — ★The translation table lives in a separate file from the op docs. Using
opdocs.T would register every source string in opdocs.SEEN_STRINGS, and the existing “holes in the frame translations” gate would count all 604 of them as holes and turn CI red — that gate exists to keep frame strings complete in all five languages, while this one is a fill-as-you-go collection. Mixing them into one table lets one discipline break the other.
- L79 — ★One block = a run of
# comment lines that starts from a line containing ★ and continues at the same indentation. Sphinx-style #: comments are also picked up. Stripping only # and whitespace leaves a : at the front
- L81 — left behind, and “: ★…” appears in the output artifact (it actually did). Strip
: here as well.
- L105 — ★When the next ★ arrives, cut it as a separate block (keep one claim per block).
- L197 — ★Don’t translate the marker; fix it to
_(ja)_. Translating it per language makes it uncountable by machine – tools/i18n_status.py is a tool that counts “Japanese without a marker”, so if the marker changes per language, 593 lines turn into “hidden Japanese” (it actually did). ja is a language code and also conveys to the reader “this is Japanese”.
- L280 — ★Take the set of notes from the ledger (don’t enumerate files). In the 2026-09-06 adversarial review (Codex), a version that globs files and counts stems mixed in one
docs/ops/SAMPLES.md (not an op note), and the index said 1,842 while the RAG guide said 1,843, publishing conflicting counts at the same time. Notes are generated 1:1 from records, so a name in records is itself the definition of “a name that has a note”. Agreement with the files is checked separately by tests/test_docs_index_reachable.py (detecting missing / surplus).
- L290 — ★
__all__, not dir(fullseye). dir includes module attributes (os / sys / warnings / annotations) and moreover increases by one after another test imports (1094 → 1095), so the drift gate fell only in the full suite (2026-09-06). The public surface is the 1,091 names the facade declares in __all__.
- L339 — ★The index is not only for humans but also AI’s search surface (the user’s 2026-09-06 remark “the index is also the part used as RAG, right?”). Since op notes double as the search corpus for AI coding assistance, make the machine-read entry point explicit in the index. Writing “all op” for something that has only half will make the RAG confidently wrong about the other half – that’s why the measured lines from
_honest() are not removed from this section.
- L490 (ja) — ★2026-09-14: 長らく かな だけを見ていたので、「Studio 北極星」「実測記録」 のように 漢字だけで書かれた題に印が付かなかった —— 非日本語版の読者は それを英語の題だと思ってクリックする(印を付けないのは「読めない」という 事実を隠すことで、無訳より悪い、というのがこの関数の趣旨そのもの)。 題は常に日本語版ファイルから取る(
_doc_title(rel))ので、漢字を足しても 中国語の題を誤って日本語と呼ぶことは起きない。
- L655 (ja) — ★Qiita 投稿用の frontmatter(— で挟んだ YAML)は題ではない。中の
title: 行は 下の走査では見出しにも読み飛ばし対象にも当たらず、そのまま索引の見出しになって しまう(「title: ‘…’」と並ぶ)。挟まれた範囲ごと読み飛ばす。
- L94 — ★Don’t let through status=fixed with no gate – so that this ledger itself doesn’t create a state where only the record of having fixed it remains while recurrence can’t be stopped.
- L194 — ★The link targets (
docs/hardening/*.md) are written in Japanese. Replacing them with an English title would be a lie, so emit the title as-is and attach (ja) – what a non-Japanese-version reader needs is not a “translated title” but the fact “this is unreadable”. Fix the marker to the form that tools/i18n_status.py counts.
- L41 — ★This is not “just a constant”: once the line integral p = Σ μ·Δx exceeds 10, exp(-p) drops below a photon count of 1, the logarithm saturates and p hits a ceiling (photon starvation). The first version placed μ at 0.55–1.0 “per pixel”, so p reached 30 and the reconstructed μ came out 50–84% low. The zero baseline (plain back-projection) won on Dice, and that’s when it was noticed.
- L166 — ★The per-material numbers are recall. They are “the fraction picked up within that material’s label”, not Dice (since false positives falling outside the label aren’t counted, calling it Dice would always drift toward 1.0). The overall misses / over-picking are given separately below as precision / recall.
- L65 — ★The winding order is outward. Reverse it and the normals point inward, and render_beauty returns pure black without raising an exception (the first version was like that, and only the thin-film sphere was black).
- L153 — ★This is a lower bound. Since it only looks at whether the op name appears as a literal in
tests/, sweep-type tests that scan the ledger and run all op (for name in ledger: ...) aren’t counted. Read it as “no named test”, not “no test”.
- L105 — ★2026-09-08:
tb_angle_3points and tb_indices_to_labels, which were in this table, were not “outside the figure’s domain” but op that must not be put on the bridge. The former takes 3 vectors so it can’t be called with a single point cloud, and the latter returns 1-D yet declares out as labels (→ volume = ndim 3). Both, while registered, had never once run, and fail-soft was returning plausible values. Moved to backends_typed._OP_BRIDGE_SKIP and removed from this table – there was a record that no figure came out, yet nowhere a record of the inability to run itself (there were two gates, and only one had noticed).
- L115 (ja) — ★2026-09-13: op が evolute 検証を得て厳格化。ECEF は地球表面(中心から ~6.4M m)の 座標を要るが、画像由来の合成点は原点付近で必ず楕円体の evolute 内に落ちるため 正しく拒否される(実データでは動く。合成入力では図を作れない恒久的な定義域ミスマッチ)。
- L127 — ★2026-09-07 (user instruction “there’s no need to consolidate into one image; things that are stepwise or have multiple conditions should be split out”, “for some things a pseudo-color is easier to understand”, “complex ones may even be an animated GIF”). In addition to the main figure
<op>.png: <op>.a.jpg / <op>.b.jpg — 3 images with the knob swept to 0.1 / 0.5 / 0.9 (only when the output changes; if it doesn’t change, the reason goes in the manifest) <op>.chain.jpg — a stepwise figure for an op that has a preceding op (image → intermediate → output) <op>.gif — when the output is video / light field / volume, showing frames / viewpoints / slices in sequence (the still <op>.png is the finished form and the GIF is additional; Studio’s QTextBrowser shows the first frame). Apply pseudo-color only to the output of a field of quantity (distance, phase, orientation, depth, curvature …), and write (viridis) in the caption. Filter types stay gray (don’t present them as a color-changing op).
- L730 — ★”It ran” and “a meaningful output came out” are different (2026-09-07, user’s remark “what’s with the pure-black out?”). If an empty array is counted as “has a figure”, a black slab becomes a figure. Record empty as empty and write the reason in the note.
- L592 — ★2026-09-02: highpass / bandpass_image now follow the convention of returning “[0,1] with 0 mapped to 0.5”. Previously they returned a signed array called an image, and on save / inter-stage clip the negative half (about 50% of pixels) was silently crushed to 0. Record the fix by measurement, not conjecture: the minimum value and the fraction of negative pixels.
- L727 — ★2026-09-02: estimate_noise now returns in units of σ (previously it stuck at 1.0 for σ>=0.08, returning the same value for σ that differed by 3×). Lay down the line y=x so you can visually confirm “whether the return value is σ itself”.
- L840 — ★_panel_grid labels don’t wrap, and once they exceed the width they collide with the neighbor and become unreadable (with tile 262px / font 19-17px, one line ≈ 12 full-width characters at most). Push the meaning of the scale factor into the title and subtitle, and place only a short name and number on the panel.
- L1184 — ★2026-09-02:
area_center now returns, as its name says, the 3 components (area ratio, row, column) (until then it was just the single scalar area ratio and didn’t return the center). All 3 components are [0,1]-normalized so as not to depend on resolution, so to get back to pixels: row ×(H-1) / column ×(W-1). Here we plot the restored center onto the picture so you can see that the return value really is the center.
- L1712 — ★Calling apply_cmap point by point normalizes within that single point so everything comes out the same color. Build a LUT spanning 0..1 once and look up from it.
- L1950 — ★2026-09-02: gabor now uses a fixed scale dividing by the kernel’s L1 norm, returning an absolute value comparable across op. Previously it divided by “the maximum absolute value in that image”, dividing by a different divisor per orientation, which crushed the magnitude of the response itself = the discriminative power across orientations. In exchange the return value falls in a narrow band at the low end of [0,1] (mean 0.007–0.030 for these 3 patterns), so pasting it as-is makes all 3 pure black. Show the picture stretched to the 1–99%tile, and put the pre-stretch measured values in the label numbers (the same convention as freq_sweep’s highpass panel).
- L2065 — ★2026-09-02: the 3 op became separate implementations. Previously all 3 rode on geom “zoom” with a mutual maximum difference of 0.0 / 4.9e-14 (= identical), and moreover b was dead in all 3. Now zoom_image_factor = 2 scale factors (height/width) / zoom_image_size = target size / rescale_img = isotropic scale factor + interpolation order. The canvas shape stays as the input for all.
- L411 — ★Measure noise with :func:
astrostack.noise_sigma (a robust background σ). Using “RMS of the residual against the ground truth” lets even PSF shifts enter the residual – this experiment deliberately varies FWHM per frame, so changing the selection changes the post-stack PSF, and you can no longer tell whether the increased residual is due to noise or to the image changing (measured, the value moved 25.2 -> 61.3, but most of that was not noise). The background σ does not depend on the shape of the stars.
- L471 — ★The “maximum difference” doesn’t move for a single frame – because as long as recall is below 1, one missed pixel holds down the maximum as-is. How many pixels remain largely off from the ground truth and the total amount of deviation reflect the effect of the removal directly.
- L713 — ★ Laid out at native size, “2 detected” cannot be confirmed by eye (within 44x44, a pair 1.6 px apart is only a blob a few pixels wide). To avoid a figure that forces the reader to trust the detector’s claim alone, crop the same physical extent around each pair and zoom in.
- L844 — ★ The error map colors magnitude, not sign. The first version used a diverging colormap, but the error in this experiment is always positive, so “positive = the blue of right” resulted, giving the reverse meaning where a broken state is painted with the “correct” color. What we want to convey here is not direction but “how wrong it is,” so vary only the intensity of a single wrong color (and, so that meaning is not carried by color alone, also show symbols and numbers).
- L573 — 5. ★A full loop across representations (the chain of conversions is exactly where lies appear) # ————————————————————————— #
- L599 — ★ “A shell, not a solid” must not be argued with a maximum-intensity projection —— MIP is the maximum along the depth direction, so even a thin shell looks filled inside (indeed we once drew it that way and nearly reported the barely-different numbers “volume 5768 -> shell 5608”). Whether the interior remains is stated by the central cross-section and the interior fill ratio.
- L896 — ★ The physical size of the image plane the bars span. When set to 1.0 mm, 208 samples/mm = Nyquist 104 cyc/mm, so a 200 cyc/mm bar turned into a thick 8 cyc/mm stripe (the figure was aliasing itself). At 0.25 mm, 832 samples/mm, and even at the top frequency of 200 cyc/mm one period is 4.16 px, which is enough.
- L1151 — ★ Overlaying two quantities on one figure means that depending on how the scales are chosen, the two curves can coincide exactly by chance (the first version did exactly that, looking like the opposite of the claim of “two independent axes”). Tweaking the scales to separate them is a fudge, so split the panels vertically — the very structure of the figure says “these are different axes.”
- L1299 — ★ Take the peak from the entire row. It used to be written
line[c - s : c + s + 1], and when s exceeds c, the start becomes a negative index, so Python sliced out only the last 56 pixels and returned 0.6167 as the “peak” (the actual maximum is 0.9834). Normalization broke, the curve capped at 1.0, and dip/peak also came out wrongly as 0.0067 at 1.9x Rayleigh.
- L1581 — ★ The range of “blur within 1 pixel” is not picked from the grid. The sweep step is 3.9 mm while the depth of field is only 0.74 mm, so not a single point falls on the grid (the first version crashed there because min() went empty). Solve for the boundary itself by bisection.
- L1600 — ★ The exaggeration factor is vertical pixels/mm ÷ horizontal pixels/mm. The first version wrote the reciprocal and displayed “0.13x” on a figure stretched 8x (conveying the exact opposite to the reader).
- L2090 — ★ Split into two rows, top and bottom. Overlaid on one figure, the two lines with different units (pixel count and detection rate) read as if they sit on the same vertical axis (which is how it actually looked).
- L42 — ★ While this was missing, :func:
_called called :func:_strip_prose for every combination of (op name × example), each time re-parsing the whole source with ast.parse + tokenize. Measured 2026-09-05: 2-D 881 op × 73 examples + 3-D 347 op × 118 examples + ledger 494 op × 73 examples = about 140,000 full parses, so a single opdocs.py md took 10 minutes (toc and html rebuild the same index too, so a full regeneration is on the order of 30 minutes). Prose stripping needs to happen only once per source —— since it does not depend on the op name.
- L105 — ★2026-09-08: ops1d (dsp 16 + funct1d 23) was registered yet had not a single note under docs/ops —— it appears in OP_CATALOG, but with no per-op note (type contract, pitfalls, related ops) it was entirely missing from the RAG corpus. We noticed when
poc_web_roll_periodicity added 2 to dsp.
- L790 — ★The n-ary (multi-input) tier. Until 2026-09-09 17 operators had no note at all (
add_image, sub_image, bit_and, reduce_domain, union2…). They appear in OP_INDEX.json as tier nary, but with no note under docs/ops/ they could never be retrieved from the RAG corpus. The reason it went unnoticed is plain: this code walked only ops.REGISTRY, and ops.REGISTRY (899) matches the 2-D note count (899) — so counting from the registry side it looked complete. It only shows when you count across tiers.
- L832 — ★2026-09-07:
OPS3D[...]["doc"] is, at registration time, just the first line of the docstring cut out (ops3d._build). Using it for a note’s “usage” turns it into a single line no matter how many paragraphs the implementation writes —— the 3-D share of “494 ops with a one-line usage” was caused by this truncation (many ops have long docstrings themselves). Read the function’s docstring in full, as for the ledger dim.
- L855 — ★ A bridging op (
tb_<name>) has the same implementation as the ledger’s <name>, and examples are written under the ledger name. Until 2026-09-06, 147 of them were “zero examples,” but that only meant we had not counted that examples calling the same implementation exist under a different name. Inherit the ledger-side examples and note explicitly in the note that they are “examples of the original op” (so as not to lie).
- L1075 — ★An n-ary operator cannot be called through
fullseye.apply — that is the one-image model. Writing the one-image call form here makes the note lie, and telling the reader how to call the operator is the note’s only job, so a wrong call form is worse than none. The public route is fullseye.FullseyeGraph.
- L1094 — ★2026-09-07: Write the public path first. This only wrote a direct import of the implementation module and did not surface
fullseye.ledger.<name>, which users actually use (all 1,244 ops other than 2-D). The reason PoCs repeatedly reported “not in fs." was not that the name was missing but that **the entry point was not written**.
- L1455 — ★ Surface the entry points in 6 languages (2026-09-09). The leaves (Studio’s op help) have 10,191 pages across 6 languages, yet the index leading there was Japanese only —— a gap of the form where the translations exist but cannot be reached. The frame’s wording goes into
T(), so holes in the parallel translations are watched by the existing gate (test_chrome_translation_table_has_no_holes).
- L1500 — ★ For a long time this pointed only at
2d/guides/ and never once sent readers to the guides of the 30 families such as optics, PIV, and tomography (fixed 2026-09-09).
- L119 — ★ If a previous staging copy remains in
build/lib, setuptools packs it into the wheel as-is (measured 2026-09-05: a module removed from py-modules stayed in the wheel, and the gate’s mutation test passed). Same reason release.yml builds from a clean checkout. Here too, always discard it before building.
- L313 — ★ Calling
--only suite without --full yields 0 items, and it used to say “all PASS” and return with rc=0 (measured in the 2026-09-05 review). A gate that passes while checking nothing is worse than no gate.
- L54 — ★The only generated artifact outside
tools/. That is exactly why it was missed — as long as you look for generators under tools/*.py, this one is never found.
- L77 — * ★ And dangerous: an article right after generation writes images with relative paths. The published version has them changed to absolute URLs on
raw.githubusercontent.com (with a relative path Qiita does not show images —— memory feedback_qiita_svg_path_and_cache). Running only the generator rolls those absolute URLs back by 42 lines. If you run it, carry it all the way through the article’s publishing steps. Write exclusions by file name. Summarizing them in prose (“the 10 of wing*_gallery”) cannot be matched by machine, and the unclassified() below stops working.
- L167 — ★A generated artifact outside
tools/. Walking tools/*.py can never find it, and in fact docs/OP_INDEX.json was being missed.
typed_catalog.py
- L217 — ★ The case where the default itself is heavy is handled separately —— we wrote a cost table in the docstring and left it in docs/KNOWN_ISSUES.md as “unsolved.” Making it lighter here is to pass the check, not to hide the slowness. The keep of fourier_smooth(points, keep) is a required argument with no default. If it cannot be bound, it is skipped forever as “cannot assemble arguments” and appears in the coverage table only as unreached (in the first measurement on 2026-09-06, only this one of 13 ops fell out). Surface roughness. Constraints are 2dx <= lambda_lo < lambda_hi <= ndx / 0<hurst<1 / sq>0 / n>=8. Subpixel measurement. The measurement-line generation op takes no input, so every argument needs a hint.
- L271 — ★ Without this, surface_params is rejected fail-closed every time, and by the single coverage number it looks “callable” while in reality it is never executed.
- L459 — ★ Do not make the normal parallel to an axis. If it is axis-parallel, the distance field varies along only one axis, and the “GIF of stacked slices” the figure generator makes collapses into a single frame (measured 2026-09-08). With a tilted normal, every slice changes. The length has no effect (the op normalizes), so pass an unnormalized vector to also show that spec.
visionlab.py
- L53 — ★
float("50") succeeds, so merely passing through float() lets a string slip through as millimeters. The visiondesign side rejects it, but converting to float first here means it becomes a number before it reaches that validation (measured under adversarial testing: VisionSystem(focal_mm=”50”) passed). Hold the same discipline on the container side too.
visualhull.py
- L123 — ★ Every single point behind the camera = almost certainly a convention mismatch in the pose (2026-09-08, hit by poc_livestock_body_volume). This function requires the OpenCV convention (+Z forward), but what bears the name
look_at in the public layer is render3d’s gluLookAt version (−Z forward, a 4x4). Passing its M[:3,:3], M[:3,3] makes every voxel judged as behind, and an empty silhouette without exception is returned, giving an empty hull. Silently returning empty is indistinguishable from “fully carved,” so here alone we raise our voice (there are valid cases —— the object being behind the field of view —— so keep it to a warning rather than a raise).
world_render.py
- L69 (ja) — ★
resolve() は実在しない場面に None を返す(資産が無い環境では正しい)。 検査せずに spec["xml"] を引くと TypeError: 'NoneType' object is not subscriptable という、原因を何も語らない例外になる —— 呼び手には 「何が無いのか」と「どう直すのか」を返す。
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.