Date: Jun 12, 2026. Criteria:
tasks/chain10_criteria.md (pre-registered).
Method: read-only evidence; every claim carries its
file:line.
dx_ds)?The FD tangent is built at GNC/guidance/orbit_path.py:48
(and the resmooth site, :53):
self.dx_ds = np.gradient(self.x_surf, self.s_samples, axis=0) # (N,3) arclength derivative
It leaves the class only through eval()
(orbit_path.py:56-59), which returns
(x, dx).
eval has exactly ONE call site in all of
GNC (rg -n "\.eval\(" GNC):
GNC/guidance/ee_guidance.py:620: x_surf, _ = self.orbit_path.eval(s_aim)
The tangent return is bound to _ —
discarded. The anchor-mode branch added in Phase 00 T4
uses orbit.sample_analytic (the COM helix), not
OrbitPath.eval, so it introduces no second consumer.
The planned consumers do not exist.
parameters.yaml carries
ff_route: none # none|A|B|AB analytic feedforward (consumed in Task 4/5)
— but rg -n "ff_route" GNC returns
nothing: no code reads the knob in any mode. The “Task
4/5” analytic-feedforward routes were never built. (Housekeeping ALERT
for the user: ff_route is a dead config key whose comment
promises consumers that don’t exist — candidate for removal or a
# Legacy/dormant annotation; not this chain’s edit.)
Criteria text (verbatim): “H1 killed if the code
audit shows dx inert in the adopted config, OR tangent
ripple at aim points is uncorrelated with peak locations (|Spearman r|
< 0.3).”
H1 KILLED by code audit (inert consumer) — and
stronger than the condition anticipated: the FD tangent is discarded at
its only call site and its planned consumers were never built, so it is
inert in every config, not just the adopted one. No
noise in dx_ds can reach any pose, command, or score.
Per the plan, the harness’s fd_ripple driver is now
documentation-only (computed and tabulated, clearly
labeled non-causal). Scope note: this audit kills the tangent
hypothesis as stated; the surface path x_surf itself
(ray-cast, savgol-smoothed, linearly interpolated) remains in the causal
chain through its position values — that geometry-quality
channel is covered by the T4 curvature/geometry drivers, not by H1.
rg -n "curvature" GNC finds curvature consumed ONLY from
the COM orbit generator (utils/curvature
helpers; orbit.curvature → kappa_window in
GNC/base_guidance.py, kappa_vec in
GNC/com_guidance.py, kappa_cd in
GNC/guidance/guidance_rollout.py). The surface
path’s curvature is never computed or read anywhere in GNC.
Consequence for H2 (recorded as the plan expects):
there is no direct code path from target-surface curvature to a pose
command. If target geometry drives κ peaks, the route must be indirect —
x_surf position → camera pose → arm reach demand — which is
exactly what the T4 correlator tests (path_curv / reach drivers). H2
stays alive for the correlator, with its causal route now pinned to the
indirect channel.
Context note (not a new hypothesis): the COM-orbit
curvature DOES feed the COM feedforward (kappa_vec,
com_guidance.py), and the helix’s curvature varies
pole-to-pole — so the schedule changes when the vehicle
traverses high-curvature latitudes. Adjacent to H3’s phase-alignment
story; the reach/phase drivers in T4 will see it if it matters.
| Question | Finding | Effect |
|---|---|---|
| FD tangent consumers | one call site, discarded (ee_guidance.py:620);
ff_route dead key |
H1 KILLED (all configs) |
| Surface curvature in pose path | none — indirect channel only | H2 alive, route pinned for T4 |