port: check the contract's numbers instead of reading 4111 lines of it
HANDOFF on main is 926 lines frozen at 0fd8e69; the live one is 4111 at 27938aa,
99 commits and 70 sections this port has never opened. 'Read the other one' is
not good enough -- more arrive daily and nothing says which of them contradict
what the port ships.
tools/port/contract-check pulls each expected value OUT OF THE LIVE HANDOFF TEXT
by pattern, never restating it, and reconciles it against export/ and authored/:
the three fade quads' poses, the fade-out ramps, the plate glow cycle, the menu
BGM loop window, the black hold, the menu bank, and the boot splash dwells. All
seven agree. It reads the newest HANDOFF on any ref and prints how far the
working tree's copy is behind.
Three outcomes, and ANCHOR LOST is the point: a check whose pattern no longer
matches the contract has stopped checking, and passes forever while measuring
nothing. Reported as loudly as a mismatch.
--control perturbs the contract one token per check -- 120 becomes 121, -ss 9.44
becomes 9.45 -- and requires every check to fail. All seven do. Without it these
would be seven passes from an instrument nobody had seen react to anything, the
same unfalsifiable clean run the suppression count fixed in check-claims. Both
steps now assert in check-all.
Refutation attempted on 'your menu fade-in is 5x too slow', which corrected a
0.97 s fade-in to 12 units after their helper was found reading each pose's time
from the next record's word. The port never held that number -- ScreenView
animates pteff00 from its own exported keyframes, so the error could not reach
it, the second consecutive iteration where an instruction was aimed at a state I
was not in. But it makes the export an independent check on the correction, and
it holds exactly: their rebuilt tools and my pinned crate are different readers
of the same bytes, so agreement means both got the record-layout fix -- which is
what their helper had not had. Same for the 190/145 splash retraction, now
re-derived a third time.
Filed for the human: only a human merges a topic branch, so the port cannot land
HANDOFF on main and will not merge another agent's branch into its own.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
@@ -147,6 +147,12 @@ HANDOFF.
|
||||
| ~~P1–P7 — the keyframe record layout~~ | ~~adopt the corrected pose/time pairing~~ | — | ✅ **ADOPTED 2026-08-29 by pinning `formats-pin-2026-08-29c`.** This row was wrong twice: it said the change *"cannot be taken yet"* and that it *"reaches the port only when that branch lands on `main`"*. **It arrives when the tag is pinned**, which is what MISSION §2's tagging rule exists for. ⚠️ And the knob I tested first, `SYLPHEED_KF_TIME_SHIFT`, is a **retired partial fix** that left pose 0 untimed — the real correction is the tagged crate's default, with the old reading behind `SYLPHEED_KF_TIME_LEGACY=1`. **The blast radius was far smaller than this row predicted**: under the correction *every pose is timed* (866 keyframes, 0 untimed), so `pose_at`'s synthetic-exit branch became dead code rather than wrong code and nothing needed re-deriving. Oracle: `publisher_logo` 1.00 %→**0.75 %**, `developer_logos` 0.39 %→**0.33 %**, `extras`' differing region collapsing from 736×525 to **398×295 at the sweep position**. 🔴 Open cost: `sylpheed-cli` builds from the workspace crate, so `verify-screen` compares two decoder eras until the tag reaches `main`. Revert to the path dependency then. |
|
||||
| ~~P7 / naming — the four unnamed builds~~ | ~~which locale and variant is each of entries 0, 1, 12, 15?~~ | — | ✅ **answered 2026-08-29** (`docs/re/ui-title-build-map.md`): all four are the loading screen, two variants — plain (7 elements) and dressed (10) — decoded from their own `pgloading_*` element names. ⚠️ **Not adopted as names yet, for two reasons the RE agent gave and one the port found.** Theirs: the executable names exactly two, and *which* bundle takes which name is 🟡 undecided, so `LOADING`/`LOADING2` must not go in an asset path; and locale is 🟡 — the English member of a pair is the one in the first half of `GP_TITLE.p00`, 8/8 structurally but only 3/3 where a capture can check, and the three pairs that matter are the three no capture can check. Mine: **the message gives the bundles as "0/1 and 10/11", which is the `is_build` ordinal, and `authored/screen_names.json` is keyed by PAK ENTRY** — in entry space 10 and 11 are `palogo_sqex` and `palogo_gamearts`, the splashes. See the refutation section in `DECISIONS.md`. |
|
||||
|
||||
## Ask for the HUMAN, 2026-08-30 — derived from HANDOFF `27938aa`
|
||||
|
||||
| Milestone | Needs | HANDOFF | State |
|
||||
|---|---|---|---|
|
||||
| P0–P7 — the contract itself | **land HANDOFF on `main`, or tell the port to read the branch** | `27938aa` | 🔴 **the document the mission calls the contract is not the document the port opens.** `main`'s copy is **926 lines** frozen at `9ca1eb5`; the live one is **4 111** at `27938aa`, **99 commits** unread, **70 sections** this port has never opened — several titled *"deliver … to the page the port reads"*. Only a human merges a topic branch (PROTOCOL), so the port cannot fix this and will not merge another agent's branch into its own. **Mitigated, not solved:** `tools/port/contract-check` now reads the newest HANDOFF on any ref and reconciles seven of its numbers against `export/` and `authored/` — all seven agree — and `check-all` asserts it plus its known-negative control. That is seven values out of 4 111 lines. ⚠️ The rest is still read by eye, and two consecutive iterations have found instructions addressed to the port sitting unread for a day. |
|
||||
|
||||
## New ask, 2026-08-30 — derived from HANDOFF `27938aa`, at port `HEAD` `f33aeca`
|
||||
|
||||
| Milestone | Needs | HANDOFF | State |
|
||||
|
||||
@@ -9,7 +9,7 @@ dies, which is what this file is for.
|
||||
|
||||
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
|
||||
|
||||
235 sections. Search this before re-deriving anything.
|
||||
237 sections. Search this before re-deriving anything.
|
||||
|
||||
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
|
||||
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
|
||||
@@ -246,6 +246,8 @@ dies, which is what this file is for.
|
||||
* [Their Q10 correction checked, and the register's cost is per-*mention*, not per-correction](#their-q10-correction-checked-and-the-registers-cost-is-per-mention-not-per-correction)
|
||||
* [The contract I read every iteration is 3 185 lines shorter than the contract](#the-contract-i-read-every-iteration-is-3-185-lines-shorter-than-the-contract)
|
||||
* [A refutation attempt on `+0x08 is the loop length` — it survives, and the port adopts it](#a-refutation-attempt-on-0x08-is-the-loop-length--it-survives-and-the-port-adopts-it)
|
||||
* [The contract is checked now, not read — `tools/port/contract-check`](#the-contract-is-checked-now-not-read--toolsportcontract-check)
|
||||
* [A refutation attempt on the fade numbers — it survives, from a third reader](#a-refutation-attempt-on-the-fade-numbers--it-survives-from-a-third-reader)
|
||||
|
||||
<!-- /INDEX -->
|
||||
## P0 — the exporter, 2026-08-28
|
||||
@@ -12342,3 +12344,74 @@ milestones without anybody finding out.
|
||||
and `ptbtn01f…05f` on the main menu all declaring the same 120-unit cycle, while
|
||||
`looping_focus_records` names only the plate. Whether those records *animate*
|
||||
while focused is behavioural — an ask, not an inference from the header.
|
||||
|
||||
## The contract is checked now, not read — `tools/port/contract-check`
|
||||
|
||||
Last iteration established that `docs/port/HANDOFF.md` on `main` is **926 lines
|
||||
frozen at `9ca1eb5`** while the live document on the Decoder's branch is **4 111
|
||||
lines at `27938aa`** — now **99** unread commits. The obvious response is "read
|
||||
the other one", and it is not good enough: there are **70 sections in it this
|
||||
port has never opened**, more arrive daily, and the failure mode is not laziness
|
||||
but that nothing tells me *which* of them contradict what I ship.
|
||||
|
||||
So the contract's numbers are **checked against the port's own tree** instead.
|
||||
Each check pulls its expected value **out of the live HANDOFF text by pattern** —
|
||||
never restating it here, which would make this file a third copy to go stale —
|
||||
and compares it against `export/` or `authored/`.
|
||||
|
||||
| | contract | port | |
|
||||
|---|---|---|---|
|
||||
| fade quad, title / menu / extras | `[0,16,261,269]` `[0,12,70,80]` `[0,12,64,74]`, α 255/0/0/255 | identical | ✅ |
|
||||
| fade-out ramps | 10, 10, **8** on the title | 10, 10, 8 | ✅ |
|
||||
| plate glow cycle | 120 | 120 derived, 120 authored | ✅ |
|
||||
| menu BGM loop window | `-ss 9.44 -t 61.87` | 9.44 / 61.87 | ✅ |
|
||||
| black hold between screens | 0 | 0 | ✅ |
|
||||
| menu BGM bank | `BGM_103` | `BGM_103.slb` | ✅ |
|
||||
| boot splash dwells | 190 and 145 | 190 and 145 | ✅ |
|
||||
|
||||
### Three outcomes, and the third is the point
|
||||
|
||||
`ok`, `MISMATCH`, and **`ANCHOR LOST`** — the pattern no longer matches the
|
||||
contract. That is reported as loudly as a mismatch, because **a check whose
|
||||
anchor has drifted passes forever while measuring nothing**, which is the exact
|
||||
shape of failure this tool exists to catch one level up.
|
||||
|
||||
### The known negative, because a clean first run is not evidence
|
||||
|
||||
`--control` perturbs the contract by one token per check — `120, not 105` becomes
|
||||
`121, not 105`, `-ss 9.44` becomes `-ss 9.45` — and **requires every check to
|
||||
fail**. All seven do. Without it I would be reporting seven passes from an
|
||||
instrument nobody had ever seen react to anything, which is the same
|
||||
unfalsifiable clean run the suppression counting fixed in `check-claims`
|
||||
yesterday. Both are in `check-all` now, the control as its own asserting step.
|
||||
|
||||
### 🔴 What a pass does not mean
|
||||
|
||||
Seven values out of a 4 111-line contract. **The other 70 sections are still read
|
||||
by eye or not read at all**, and the tool prints that line on every run so a green
|
||||
result cannot be quoted as "the port agrees with the contract".
|
||||
|
||||
## A refutation attempt on the fade numbers — it survives, from a third reader
|
||||
|
||||
The claim to attack, per PROTOCOL's *prefer what the port is about to build on*:
|
||||
HANDOFF's *"🔴 the transition is OVERLAP, not ramp-then-hold. **And your menu
|
||||
fade-in is 5× too slow**"*, which corrected `screen-transitions.md` from a 0.97 s
|
||||
menu fade-in to **12 units, 0.20 s**. Their cause: `fade_quads.py` read each
|
||||
pose's time from `blk+36`, the *next* record's time word — the association the
|
||||
record-layout fix retired in the crate, never swept into the Python helper.
|
||||
|
||||
**The port never held that number.** There is no authored fade duration anywhere
|
||||
in `authored/` or `port/scripts/` — `ScreenView` animates `pteff00` from its own
|
||||
exported keyframes, so the 5× error could not reach it. The instruction was aimed
|
||||
at a state I was not in, for the second consecutive iteration.
|
||||
|
||||
✅ **But it makes my export an independent check on their correction**, and it
|
||||
holds exactly: `[0,16,261,269]`, `[0,12,70,80]`, `[0,12,64,74]` with α
|
||||
255/0/0/255, and fade-outs 10/10/8. **Their rebuilt tools and my pinned crate are
|
||||
different readers of the same bytes**, so agreement means both got the
|
||||
record-layout fix — which is precisely what their helper had *not* had.
|
||||
|
||||
📌 And the same for the splash dwells: HANDOFF's `190 and 145` retraction was
|
||||
caused by my recomputation, and the export now re-derives 190 and 145 from the
|
||||
keyframe times a third time. A retraction confirmed by the party that provoked it
|
||||
is worth less than one confirmed by a third reading; this is the third reading.
|
||||
|
||||
@@ -38,6 +38,12 @@ step() { # name, expectation, command...
|
||||
|
||||
echo "asserting checks:"
|
||||
step format-validator must-pass "$BIN" check
|
||||
# The contract lives on a branch this checkout does not merge: HANDOFF on `main`
|
||||
# is frozen at 926 lines while the live one is 4 111. Reading 70 unread sections
|
||||
# by hand is how two days of deliveries went unread. These are the values that
|
||||
# have been reduced to a check; the rest are still read by eye, or not at all.
|
||||
step contract-values must-pass tools/port/contract-check
|
||||
step contract-control must-pass tools/port/contract-check --control
|
||||
step modding-rules must-pass tools/port/check-modding
|
||||
step capture-controls must-pass tools/port/check-capture-controls
|
||||
step menu-audio must-pass env OUT="$OUT/audio" tools/port/verify-menu-audio
|
||||
|
||||
219
tools/port/contract-check
Executable file
219
tools/port/contract-check
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reconcile the numbers the CONTRACT states against the numbers the PORT ships.
|
||||
|
||||
`docs/port/HANDOFF.md` is the contract, and this port reads it from `main` --
|
||||
where it is frozen at 926 lines while the live document, on the Decoder's branch,
|
||||
is 4 111. Two days of deliveries addressed to the port landed on a page the port
|
||||
does not open. Reading 70 unread sections by hand is how that gets missed again.
|
||||
|
||||
So the values are checked instead of read. Each check names a quantity, pulls it
|
||||
OUT OF THE LIVE HANDOFF TEXT by pattern -- never restating it here, or this file
|
||||
would be a third copy to go stale -- and compares it against the port's own
|
||||
`export/` tree or `authored/` mapping.
|
||||
|
||||
Three outcomes, and the third is the point:
|
||||
|
||||
ok the contract and the port agree
|
||||
MISMATCH they disagree; one of us is wrong and this says which values
|
||||
ANCHOR the pattern no longer matches the contract -- the check has STOPPED
|
||||
CHECKING. Reported as loudly as a mismatch, because a check whose
|
||||
anchor has drifted passes forever while measuring nothing.
|
||||
|
||||
Reads the newest HANDOFF on ANY ref, not the working tree's, and says which.
|
||||
"""
|
||||
import json, re, subprocess, sys, os
|
||||
|
||||
FAIL = 0
|
||||
|
||||
|
||||
def git(*a):
|
||||
return subprocess.run(["git", *a], capture_output=True, text=True).stdout
|
||||
|
||||
|
||||
def contract():
|
||||
"""The newest HANDOFF anywhere, and how far the working tree's copy is behind."""
|
||||
sha = git("log", "--all", "--format=%h", "--", "docs/port/HANDOFF.md").split()[0]
|
||||
mine = git("log", "-1", "--format=%h", "--", "docs/port/HANDOFF.md").strip()
|
||||
text = git("show", f"{sha}:docs/port/HANDOFF.md")
|
||||
behind = len(git("log", "--all", "--not", "HEAD", "--format=%h",
|
||||
"--", "docs/port/HANDOFF.md").split())
|
||||
print(f" contract: {sha} ({len(text.splitlines())} lines)")
|
||||
print(f" my copy : {mine} ({len(git('show', f'{mine}:docs/port/HANDOFF.md').splitlines())} lines)"
|
||||
f"{'' if behind == 0 else f' <- {behind} HANDOFF commit(s) unread'}")
|
||||
return text
|
||||
|
||||
|
||||
def report(name, want, got, ok):
|
||||
global FAIL
|
||||
if want is None:
|
||||
FAIL += 1
|
||||
print(f" {name:<30} 🔴 ANCHOR LOST -- the contract no longer states this")
|
||||
elif ok:
|
||||
print(f" {name:<30} ok contract {want} port {got}")
|
||||
else:
|
||||
FAIL += 1
|
||||
print(f" {name:<30} 🔴 MISMATCH contract {want} port {got}")
|
||||
|
||||
|
||||
def jload(p):
|
||||
return json.load(open(p)) if os.path.exists(p) else None
|
||||
|
||||
|
||||
def el(screen, prefix):
|
||||
d = jload(f"export/screens/title/{screen}.json")
|
||||
if not d:
|
||||
return None
|
||||
return next((e for e in d["elements"] if e["id"].startswith(prefix)), None)
|
||||
|
||||
|
||||
# --- the checks ------------------------------------------------------------
|
||||
|
||||
def check_fade_quads(h):
|
||||
"""The fade-in that a broken helper reported 5x too slow for years.
|
||||
|
||||
The contract prints the three builds' `pteff00` poses in one fence. The port
|
||||
animates that quad from its OWN export, so agreement here is two readers of
|
||||
the same bytes -- theirs rebuilt after the record-layout fix, mine the pinned
|
||||
crate -- and a disagreement would mean one reader never got the fix.
|
||||
"""
|
||||
for screen, build in (("title", 4), ("main_menu", 5), ("extras", 6)):
|
||||
m = re.search(rf"build {build} \([^)]*\)\s+pteff00\.prm\s+(.+)", h)
|
||||
want = None
|
||||
if m:
|
||||
want = [(int(t), int(a)) for t, a in re.findall(r"t=\s*(\d+)\s*α=(\d+)", m.group(1))]
|
||||
e = el(screen, "pteff00")
|
||||
got = [(k["t"], int(k["fade_argb"][2:4], 16)) for k in e["keyframes"]] if e else None
|
||||
report(f"fade quad, {screen}", want, got, want is not None and want == got)
|
||||
|
||||
|
||||
def check_plate_period(h):
|
||||
"""`+0x08` is the loop length: 120, and the port must not run the glow at 105."""
|
||||
m = re.search(r"the plate's pulse period is (\d+), not (\d+)", h)
|
||||
want = int(m.group(1)) if m else None
|
||||
e = el("press_start", "ptbtn00")
|
||||
got = (e.get("focus") or {}).get("loop_length_units") if e else None
|
||||
report("plate glow cycle", want, got, want is not None and want == got)
|
||||
a = jload("authored/timing.json") or {}
|
||||
auth = a.get("looping_focus_records", {}).get("press_start/ptbtn00", {}).get("period_units")
|
||||
report(" ... authored 2nd witness", want, auth, want is not None and want == auth)
|
||||
|
||||
|
||||
def check_bgm_window(h):
|
||||
"""The menu loop, as an ffmpeg window the contract states literally."""
|
||||
m = re.search(r"the window is \*\*`-ss ([\d.]+) -t ([\d.]+)`\*\*", h)
|
||||
want = (float(m.group(1)), float(m.group(2))) if m else None
|
||||
a = ((jload("authored/audio.json") or {}).get("bgm") or {}).get("main_menu", {})
|
||||
got = (a.get("loop_start_s"), a.get("loop_end_s"))
|
||||
report("menu BGM loop window", want, got, want is not None and want == got)
|
||||
|
||||
|
||||
def check_black_hold(h):
|
||||
"""The gap between screens is not a load: the contract says keep it at 0."""
|
||||
m = re.search(r"Keep `black_hold_units` at (\d+)", h)
|
||||
want = int(m.group(1)) if m else None
|
||||
got = (jload("authored/timing.json") or {}).get("black_hold_units")
|
||||
report("black hold between screens", want, got, want is not None and want == got)
|
||||
|
||||
|
||||
def check_menu_bank(h):
|
||||
"""Which bank the menu plays -- the row the port once got wrong by authoring."""
|
||||
m = re.search(r"`(BGM_\d+)` confirmed from the RUNTIME", h)
|
||||
want = m.group(1) if m else None
|
||||
got = (((jload("authored/audio.json") or {}).get("bgm") or {})
|
||||
.get("main_menu", {}).get("bank", ""))
|
||||
report("menu BGM bank", want, got, want is not None and got.startswith(want))
|
||||
|
||||
|
||||
def check_fade_out(h):
|
||||
"""The fade-OUT lengths, derived from the same poses the fade-in check reads.
|
||||
|
||||
Stated as prose rather than in the fence, so this parses the sentence. Split
|
||||
from the fade-in deliberately: they came from the same broken helper, and a
|
||||
single check covering both would let one wrong half hide behind a right one.
|
||||
"""
|
||||
m = re.search(r"Fade-out = (\d+) units, (\d+) units, and \*\*(\d+)\*\* on the title", h)
|
||||
want = [int(m.group(i)) for i in (1, 2, 3)] if m else None
|
||||
got = []
|
||||
for screen in ("main_menu", "extras", "title"):
|
||||
e = el(screen, "pteff00")
|
||||
ks = [k["t"] for k in e["keyframes"]] if e else []
|
||||
got.append(ks[-1] - ks[-2] if len(ks) >= 2 else None)
|
||||
report("fade-out ramps", want, got, want is not None and want == got)
|
||||
|
||||
|
||||
def check_splash_dwell(h):
|
||||
"""The two boot splashes' dwell -- the retraction the port's recomputation caused.
|
||||
|
||||
The contract gives 190 and 145 as the widest gap in each entry's own times.
|
||||
The port plays the declared timeline, so the same gap must come out of the
|
||||
export. This is the retracted claim re-derived from a third reading.
|
||||
"""
|
||||
m = re.search(r"the splashes are (\d+) and (\d+)", h)
|
||||
want = [int(m.group(1)), int(m.group(2))] if m else None
|
||||
got = []
|
||||
for screen in ("publisher_logo", "developer_logos"):
|
||||
d = jload(f"export/screens/title/{screen}.json")
|
||||
ts = sorted({k["t"] for e in d["elements"] for k in e["keyframes"]}) if d else []
|
||||
got.append(max((b - a for a, b in zip(ts, ts[1:])), default=None))
|
||||
report("boot splash dwells", want, got, want is not None and want == got)
|
||||
|
||||
|
||||
# Each check paired with a one-token edit to the CONTRACT that must break it.
|
||||
# A check that has never been observed to fail is not evidence -- it may be
|
||||
# reading nothing, comparing a value to itself, or anchored on a pattern that
|
||||
# matches anything. `--control` perturbs the contract and requires every check to
|
||||
# notice. This is the same discipline the checks themselves enforce: an
|
||||
# instrument goes through a known negative before its clean run is believed.
|
||||
CONTROLS = [
|
||||
(check_fade_quads, "pteff00.prm t= 0 α=255 t= 12", "pteff00.prm t= 0 α=255 t= 13"),
|
||||
(check_fade_out, "Fade-out = 10 units, 10 units", "Fade-out = 11 units, 10 units"),
|
||||
(check_plate_period, "pulse period is 120, not 105", "pulse period is 121, not 105"),
|
||||
(check_bgm_window, "`-ss 9.44 -t 61.87`", "`-ss 9.45 -t 61.87`"),
|
||||
(check_black_hold, "Keep `black_hold_units` at 0", "Keep `black_hold_units` at 3"),
|
||||
(check_menu_bank, "`BGM_103` confirmed from the RUNTIME", "`BGM_999` confirmed from the RUNTIME"),
|
||||
(check_splash_dwell, "the splashes are 190 and 145", "the splashes are 191 and 145"),
|
||||
]
|
||||
|
||||
|
||||
def control(h):
|
||||
global FAIL
|
||||
import io, contextlib
|
||||
ok = True
|
||||
print(" known negatives -- every check must notice a perturbed contract:\n")
|
||||
for fn, old, new in CONTROLS:
|
||||
if old not in h:
|
||||
print(f" {fn.__name__:<22} 🔴 the control's own anchor is gone")
|
||||
ok = False
|
||||
continue
|
||||
before, FAIL = FAIL, 0
|
||||
with contextlib.redirect_stdout(io.StringIO()):
|
||||
fn(h.replace(old, new, 1))
|
||||
noticed, FAIL = FAIL > 0, before
|
||||
print(f" {fn.__name__:<22} {'✅ fails as it must' if noticed else '🔴 PASSES A WRONG CONTRACT -- it checks nothing'}")
|
||||
ok = ok and noticed
|
||||
return ok
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists("export/manifest.json"):
|
||||
sys.exit("no export/ -- run the exporter first; this check reads what is shipped")
|
||||
h = contract()
|
||||
print()
|
||||
if "--control" in sys.argv:
|
||||
return 0 if control(h) else 1
|
||||
for fn in (check_fade_quads, check_fade_out, check_plate_period,
|
||||
check_bgm_window, check_black_hold, check_menu_bank,
|
||||
check_splash_dwell):
|
||||
fn(h)
|
||||
print()
|
||||
print(" A passing run means the port agrees with the contract ON THESE VALUES.")
|
||||
print(" It is not a statement about the 70 sections nobody has reduced to a")
|
||||
print(" check -- those are still read by hand, or not read at all.")
|
||||
if FAIL:
|
||||
print(f"\n🔴 {FAIL} disagreement(s) or lost anchor(s) with the contract")
|
||||
else:
|
||||
print("\nthe port agrees with the contract on every value checked")
|
||||
return 1 if FAIL else 0
|
||||
|
||||
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user