← Back to blog
September 7, 2026Colm Byrne
Evidence boundary. Older posts may discuss prototype designs, patent claims, or planned integrations. The demonstrated v1 release is ccf-core/ccf-agent v1.0.1: hard min-gate coupling, QAC trust updates, and runtime certificates. Gate C exercised the computed runtime on Seed-class ARM hardware with driver-fed input. Unless a post cites a specific run, do not read it as proof of live sensors, mBot2 behaviour, Cognitum store validation, or production deployment.

Fifty green ticks on a parked robot

A real moment

Niamh Toner manages a Bramley orchard outside Loughgall in County Armagh. It is the second week of September, the picking crews are in, and twelve low tugs follow them down the rows. A tug takes a full bin from a picker, carries it to the trailer at the headland, and comes back for the next one. None of the tugs arrived with permission to do that. Each one holds a trust score, built up over the season from clean runs and knocked back by every scrape and near miss. The score decides how close a tug may run to a person, how fast it may move on wet grass, and whether it may enter a row with pickers in it or has to wait at the end.

Twice a minute each tug is handed the orchard's current profile for its block and moves its score part of the way toward it. How big a part depends on how steady its own sensors look right then. A tug whose lidar is clean takes a full step. A tug whose lidar is flickering takes a small one. And every step is checked: was that the right kind of move, along the path the rule allows, by no more than the tug was allowed? If so, the tick on the shed screen stays green.

At half past nine it rains. Tug seven's lidar reads the wet leaves as obstacles, its stability score drops to zero, and the gate closes. The tug rolls to the end of its row and parks. Its trust score is frozen; a step size of zero means "do not move the score". Fifty cycles go by. Fifty green ticks. The check runs each time, the score did not move, the check passes.

While tug seven is parked, the maintenance contractor pushes the firmware update that has been waiting all week. The update includes a new version of the trust-update code from the vendor. It blends the score toward the target with plain arithmetic, which is faster and looks the same on a whiteboard. It is not the filed rule, and nobody in the shed knows that, because during those fifty cycles the wrong rule and the right rule give the same answer: stay put.

The rain eases at a quarter past ten. The lidar clears, the gate opens, and tug seven goes back to work among the pickers with a trust rule nobody has vetted. On the first moving cycle the step is half masked by the gate change. On the second, the ordinary check sees a move of the wrong shape and closes the gate. That is cycle 151, fifty-one cycles after the update went in. At thirty seconds a cycle, that is twenty-five minutes. Later that afternoon tug seven is moved to the top block and handed that block's profile outright, a step size of one, and the same thing happens for three more cycles: every rule copies the target, the check passes, and the wrong rule is certified again on no evidence.

Why this matters

A runtime check on a trust update is a good idea. It says, every cycle, whether the thing that ran was the thing that was supposed to run, and it does that from the numbers alone: the state before, the state after, the target, and the step size. It does not need to trust the code.

That last part is also the problem. The check compares what was stored against what the rule would have stored. When the step size is zero, the rule would have stored the old state, and so would every other rule. When the step size is one, the rule would have stored the target, and so would every other rule. At those two settings the check has nothing to compare, and it passes for any code at all.

Those two settings are not rare. A robot that is suspended sits at step size zero for as long as it is suspended. A robot being commissioned, or moved to a new site, or handed a profile by a supervisor, sits at step size one. Those are the moments when authority is frozen or granted outright. They are exactly the moments when a check that only reads the numbers is blind. Any check that reads only the numbers has this property, and the filed design says so and says what to do instead. What was missing was a measurement of how blind, and of how well the fix sees.

What CCF does about it

Two more checks run on those endpoint steps.

The first is a path witness. The code that makes the update writes a short note when it runs: which kernel, which branch, the step size it was given, and a digest of the inputs and the output. The note is bound to that one step; a note from another step does not fit. A second piece of code reads the note and asks two things. Does it belong to this step? Does it name the filed branch? If the update code took a shortcut, or ran a different rule and said so, the note says so and the step is refused. The note costs about 250 nanoseconds and forty bytes.

The second is a tangent shadow. The same update code is run once more, on the same inputs, at a step size a little way inside the endpoint, say a tenth. At that setting a wrong rule does give a different answer from the right one, and the ordinary check works. So the trial step is checked, and if it comes back the wrong shape, the real endpoint step is refused too. The shadow costs one extra update, about 1.3 microseconds.

The two checks see different things, and this run measured that. The path witness catches any code that says what it did, and nothing that lies. The shadow catches any code whose rule is wrong in the interior, whatever it says. Put together they caught every wrong rule we built, with zero false alarms on the correct rule, except one construction: code that is correct everywhere in the interior, skips the kernel at the endpoints, and claims it did not. Nothing computed from the numbers and a self-report can see that one. Someone has to read the code, or the note has to come from somewhere the code cannot forge.

For the curious, the math is below. The short version for the shed screen: on an endpoint step, green now means the branch note fits and names the right rule, and a trial step inside the endpoint came back the right shape. It no longer means only that the score did not move.

The numbers

Everything here is from cargo run on the published ccf-core crate, on a small desktop CPU. Seven update rules, four checks, two number formats.

At the exact endpoints the value check accepted every wrong rule: 28 of 28 rows. The path witness refused 12, the shadow refused 12, and the two together refused 20, with the correct rule accepted on all 8 of its rows in every case.

Away from the endpoint, a wrong rule's residual shrinks in proportion to the distance to the endpoint, with a slope the run predicted in one line and matched to four figures. The value check loses it at a distance of about 1e-15 in double precision and 1e-7 on a device that stores its state in single precision.

On the 300-cycle run behind Niamh's story, the value check accepted all 53 endpoint steps of the swapped rule and first noticed at cycle 151. The combined check noticed at cycle 100, the first parked cycle, and accepted none. The cost per endpoint step: 594 nanoseconds for the value check alone, 849 with the path witness, 2728 with both.

What this doesn't solve

Code that is right in the interior, skips the endpoint, and lies about it, passes everything here. The note is a self-report. The run says so in its results rather than hiding the row.

The shadow needs something to work with. If the score already equals the target, a trial step inside the endpoint goes nowhere, and the shadow is as blind as the value check. Niamh's orchard profile moves through the day, so there was always a gap; a robot at rest against a still target would need the shadow to say "skipped", not "passed".

One detail that bit during the run: if you treat the shadow's step offset as a rounding error and widen the floor for it, the shadow never fires. The offset is chosen, not rounded; its floor is the platform's rounding term only.

And the published crate's own endpoint check, as of version 1.0.1, compares the stored numbers entry by entry against the endpoint value. It accepted every wrong rule in this run and refused a correct step that carried a harmless scaling. That is filed as a follow-up.

For the curious: the math

The filed update moves the log of the state along a straight line toward the log of the target: log A' = (1 - a) log A + a log R, up to a row and column scaling that the check ignores. The residual is the size of H (log A' - (1 - a) log A - a log R) H, where H removes row and column means. For the filed rule it is zero up to rounding; for any other rule it is positive, unless a is 0 or 1.

Write D = log R - log A. Arithmetic blending gives A' = (1 - a) A + a R, so its residual is the size of H (log((1 - a) + a e^D) - a D) H. Expand in a near zero and the leading term is a times the size of H (e^D - 1 - D) H. Near one, replace D by -D. That coefficient is the slope in the tables: 0.8656 and 1.533 for this fixture, and the measured residual divided by the distance sat on those values from a distance of 1e-5 down to 1e-12. Below the store's resolution the store cannot make the move at all, the output is A unchanged, and the residual becomes a times the distance between A and R, for every rule alike. So the near-endpoint residual stops measuring the rule and starts measuring the store, and it drops under the floor at a distance of floor divided by that gap.

The tangent shadow evaluates the same implementation at a = h (or 1 - h) and computes the same residual there. Its size is h times the slope, to first order. The floor for that trial is the platform term 2 n epsilon alone. The filed floor also carries a term proportional to the step-size rounding error times the gap; charging h as that error puts the floor at h times the gap, which is above h times the slope whenever the slope is smaller than the gap, and for small D the slope is second order while the gap is first. Measured: with the charged floor the shadow detected nothing at any offset. With the platform floor it detected down to 1e-14 in double and 1e-6 in single precision.

Where this fits

This is one night's run on the filed Prov6 (US 64/092,485), paragraphs [0016], [0035], [0064] to [0066], [0093] and [0117], which state the endpoint blind spot and name the branch witness and the tangent shadow as the answer. The run adds no new mathematics. It builds the two checks on the published ccf-core crate, measures the blind spot, measures what each check sees, finds the right floor for the shadow, and records the one thing neither check can see.

  • Research doc and code: https://github.com/Hulupeep/ccf, branch research/nightly/2026-09-07-endpoint-structural-trust-verification
  • Published core: https://crates.io/crates/ccf-core
  • Causation-trail lineage: https://github.com/Hulupeep/Specflow
  • Company: https://floutlabs.com
  • Product: https://theshyrobot.com

License & contact

BSL 1.1, converting to Apache 2.0 in 2032. Contact via floutlabs.com.