Skip to content

HAND_PORT_HASHES hashes only the upstream side, so a stale hand-port is green from birth — all 9 alp_cli entries #778

Description

@alpCaner

Summary

HAND_PORT_HASHES in python/tests/gates/test_planner_relocation_freshness.py
hashes only the upstream side of each hand-port. It therefore proves that
the alp-sdk file has not moved — never that tan's counterpart implements what
was pinned. A hand-port that was already stale when its entry was added is green
from birth, and stays green forever.

This is not hypothetical. It shipped.

The instance that proved it

scripts/alp_cli/model.py is pinned at
a51be0a8d3a16bd408bb57d01f049175406b73cc48ab9346d39555c3aa5b1925
(test_planner_relocation_freshness.py:647).

  • alp-sdk fixed alp-sdk#1271 on 2026-08-08 in 7f7417c1, restricting
    compile-option path resolution to
    _PATH_OPT_KEYS = {"config", "calibration", "images", "spec"}.
  • The pin was added after that fix, already carrying the post-fix hash:
    git show d00dbdc1:scripts/alp_cli/model.py | sha256sum and the same at
    a3173305 both equal a51be0a8…, which also equals origin/dev today.
  • tan's _resolve_compile was still pre-#1271 the whole time, resolving every
    string compile option to a filesystem path.

So tan model build corrupted DRP-AI's input_shape ("1,3,224,224"),
input_name ("images") and product ("V2N") into absolute paths, in a
shipped release, with this gate green throughout. Fixed in #777; the underlying
blindness is not.

The gate file's own comment at line 620 says the hash was "verified unchanged
across the a3173305..d00dbdc1 range" — which is true, and is exactly the point:
verifying the upstream side says nothing about ours.

Why it is a class, not one entry

Seven more scripts/alp_cli/* entries were frozen in the same commit on the same
reasoning (test_planner_relocation_freshness.py:641-648):

diagnostic_format.py · validate.py · new_som.py · doctor.py ·
explain.py · monitor.py · validator.py

Any future upstream fix to any of them can ship to tan users unported, with CI
green, for exactly the same reason. faultdecode.py is in the same table.

Note the contrast with PINNED_HASHES: those modules are 3-way merged by
python/scripts/planner_resync.py, so upstream movement produces a real diff to
resolve. HAND_PORT_HASHES is flagged, never merged — by design, because the
counterparts are restructured, renamed or split and there is no base/ours/theirs
triple a merge could be correct over. That design decision is sound; the gap is
that nothing replaced the missing assurance on tan's side.

What would actually close it

Options, roughly in increasing order of cost and strength:

  1. Record an audit fact per entry. Store, alongside the upstream hash, the
    tan-side commit at which a human last verified equivalence, plus the tan file's
    own hash at that moment. A tan-side edit after that point invalidates the audit
    and reds the gate until re-affirmed. Cheap; catches "tan drifted", still not
    "tan was never right".
  2. Behavioural parity tests for the hand-ported surface. For each entry, a
    test that runs the same inputs through both implementations and asserts equal
    output. This is what actually caught #1271: review extracted both
    _resolve_compile implementations by AST and ran 24 inputs through each,
    finding 0 divergences post-fix. That method generalises and is the strongest
    option; it needs an alp-sdk checkout bound, so it lives with the other
    ALP_SDK_*-gated suites.
  3. Retire the hand-ports. alp-sdk ADR-0028 already relocates
    scripts/alp_cli/model.py's engine into python/tan/model/, which removes
    that entry outright rather than auditing it. The same argument applies to the
    rest of scripts/alp_cli/ — this issue is evidence for that direction, since
    a duplicate that cannot be verified is worse than one that does not exist.

Whatever is chosen, the gate must stop being able to pass while a hand-port is
wrong.

Related

Metadata

Metadata

Labels

bugSomething isn't workingciCI workflows, gates and test wiringpython-portRust-to-Python port of the tan command surface

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions