Measured, not asserted

Does obfuscation break spec limits and guard bands?

A dimensional check is arithmetic anyone can do in their head: is the measurement between the two limits? What decides whether a marginal part ships is not that comparison. It is the WINDOW the comparison is made against, and that window is assembled from three separate property names.

The window is not the same thing as the limits

A bore is drawn at 12.500 mm with an asymmetric tolerance of plus 0.030 and minus 0.010, so the drawing limits are 12.4900 and 12.5300. Two parts come off the machine. One measures 12.5260, four microns inside the upper limit. The other measures 12.4930, three microns inside the lower limit. Both readings are inside the drawing.

Neither reading demonstrates that the part is inside the drawing, because the measurement itself carries an uncertainty of 0.0060 mm. That is what a guard band is for: it pulls the accept boundary in by k times the uncertainty, so a reading only counts as conformance if it clears the limit by more than the instrument can be wrong. With k = 1 the accept window becomes 12.4960 to 12.5240, and both of these parts fall outside it -- one to rework, one to scrap.

The guard band is the only control in this area that stops either part. It is also the one that is easiest to lose, because it lives in the options object rather than on the part record, and a library that cannot read the key you passed does not complain. It substitutes its own default, and the sensible default for a library that cannot know your measurement system is k = 0.

What renaming the guard band did

The measurement was run under member renaming with the pattern ^(guardBandK)$. The engine renamed the property in the caller's configuration object; the installed inspection library, which is not rebuilt with the bundle, went on reading guardBandK and did not find it. It fell back to zero.

Both parts were then dispositioned ACCEPT. The output line carries the measurement, the accept window and the drawing limits, and all three are correct: bore-A=ACCEPT(measured 12.526 window 12.49..12.53 drawing 12.49..12.53). Nothing is missing, nothing is NaN, nothing looks odd. The window simply equals the drawing now, which is exactly what a window looks like when there is no guard band, and exactly what an inspector would expect to see if guard banding had never been configured in the first place.

This is the shape worth internalising. A range check on the measurement would pass. A plausibility bound on the disposition would pass. A reconciliation of accepted counts against measured counts would pass. The only thing that changed is a decision boundary that is not printed anywhere except as the window itself, and the window is self-consistent either way.

The provenance check that moved with its own subject

The caller in this test does not trust the library blindly. It supplies an inspection rule that asserts PROVENANCE rather than plausibility: the band the engine actually used must equal the band published on the drawing. That is the mitigation the previous pass in this series found to be worth having, and it is a good one.

Renaming ^(bandMm)$ -- the field on the characteristic record that carries the drawing's published band -- produced a result worth sitting with. The library's own printout went to band-on-drawing undefined, and the caller's rule still reported checked by band-provenance-check(band matches the drawing).

The reason is structural. The caller WRITES that field and the caller's rule READS it, so a rename moves the write and the read together and the check compares two values that both moved. Only the library's read broke, and the library's read is the one that ends up in the report. A guard written by the same party that writes the data it inspects is invisible to this class of change by construction; a guard is only load-bearing across a boundary if the value it reads was written on the far side of that boundary.

What failed loudly, which is most of it

The honest negatives matter as much as the finding. Renaming ^(nominalMm)$, ^(plusTolMm)$ or ^(minusTolMm)$ each produced INSPECTED=false non-finite-limit(refused before inspection). Renaming ^(measuredMm)$ refused the same way, and so did ^(uncertaintyMm)$. Every quantity on the record fails closed and says so on the first line of output.

That is not luck. The engine in this test requires each computed limit to be finite before it compares anything, which is the one-line defence this series has recommended for several passes and which keeps paying for itself. It is worth having whatever your build does, because a hand-edited process sheet and a dropped key over a serialisation hop produce the same undefined.

What that defence cannot see is the option key, because an option key never becomes unreadable: the library replaces it with a value of its own that is finite, plausible and wrong for you. Losing the VALUE fails closed and loud. Losing the RULE the value expresses fails open and silent, and the finite check is structurally unable to tell the difference.

How to keep this from mattering

Member renaming is opt-in and you write the pattern. Nothing in this article happens under the default configuration, and nothing in it happens to code you did not aim a regexp at. Keep the pattern anchored to names your own code owns on both sides, and keep the keys of any options object that crosses into an installed library out of scope.

Then make the guard band survivable on its own merits. Print the accept window AND the guard band that produced it as separate values, so a boundary that has quietly moved is visible without recomputing it. Assert that k is what the quality plan says it is, in the same place you assert the tolerance, rather than reading it off a configuration screen that shows entries exist rather than that anything found them.

And put the assertion where the rename cannot reach both halves. A rule that compares a value the library computed with a value the drawing published only works if the drawing's value comes from a source that is not rebuilt with your bundle -- a fetched process sheet, a database read, a signed release manifest. That is a design property, not an obfuscation property, and it is the difference between a check and a rehearsal.

Frequently asked questions

Does obfuscation change how a part is dispositioned?

Not on its own. Across five presets and five areas measured this pass, protection alone left every output identical to the unprotected run -- twenty-five comparisons, no differences. What changed behaviour here was member renaming, a separate opt-in option whose pattern you write.

What actually went wrong in the measurement?

Renaming the option key that carries the guard band multiplier. The installed inspection library could not read it, substituted its own default of zero, and two parts that had been held for rework and scrap were both accepted. Every printed number stayed correct.

Why did a finite check not catch it?

Because nothing became non-finite. An option key a library cannot read is replaced by the library's own default, which is a real number. Requiring a value to be finite catches a lost measurement; it cannot catch a lost rule, because the substituted rule produces perfectly good numbers.

Did anything fail loudly?

Most of it. Renaming the nominal size, either tolerance, the measurement or the measurement uncertainty each refused the whole inspection on the first line, because the engine requires every computed limit to be finite before it compares anything.

Why did the caller's own provenance check pass?

Because the caller writes the field and the caller's rule reads it, so a rename moved both sides together. Only the installed library's read broke. A check is only load-bearing across a boundary when the value it reads was written on the far side of that boundary.

Is this specific to obfuscation?

No. A dropped key over a serialisation hop, a library upgrade that renamed an option, or a hand-edited configuration file produce the same result. Renaming is a fast, repeatable way to find out which of your controls are load-bearing and which only look like they are.

What is the smallest useful change to make?

Print the accept window and the guard band as separate values rather than inferring one from the other, and assert the guard band multiplier against the quality plan in the same place you assert the tolerance. Both are worth doing whether or not you obfuscate.

Related reading