Item E (slice-1 fix round). SaveMeta/SaveNav emitted no header at all
and no per-STATE/per-NAV editor-fold comment pair, so proof (4)
(byte-identity against metaf's own canonical emission) could only ever
pass after stripping every "~~" line — which hid that metaf's own
ExportToMetAF DOES mechanically emit both:
- OutputText.metaHeader/navHeader (metaf_monolithic.py:365-434): a fixed
auto-completion-assistance banner, prepended to every meta/nav-only
file respectively.
- State.ExportToMetAF / Nav.ExportToMetAF (py:12050-12054,12463-12467):
every STATE:/NAV: block wrapped in "~~ {" ... "~~ }", unconditionally
(including the single-node Target/follow NAV case).
- Meta.ExportToMetAF (py:12775-12794): when any NAV exists, a blank
line, the exact separator
"~~========================= ONLY NAVS APPEAR BELOW THIS LINE =========================~~"
(no space beside either "~~"), and another blank line, before the
first NAV: block.
Changes:
- MetafSerializer: MetaHeaderLines/NavOutputHeaderLines — the header
text copied byte-for-byte from Fixtures/vtank/af/bella.af (meta) and
nav_ab.af (nav-only) rather than retyped from the Python source, per
the slice-1 contract. Joined with bare "\n" (matching metaf's own
multi-line string constant, written as ONE f.line entry) plus a
trailing "\n" — combined with this writer's own "\r\n" join separator,
reproduces the single blank line real output has between the header
and the first STATE:/NAV: line exactly.
- SaveMeta: prepends MetaHeader; wraps every STATE: block in "~~ {"/
"~~ }"; emits the "ONLY NAVS APPEAR BELOW..." separator only when at
least one embedded Nav tag exists.
- WriteNavBlock: wraps every NAV: block (both waypoint-list and
Target/follow modes) in "~~ {"/"~~ }".
- SaveNav: prepends NavOutputHeader; writes the sole nav under tag
"nav0" (matching metaf's Meta.GenerateUniqueNavTag counter starting at
0 — every committed nav_*.af fixture's tag is literally "nav0";
the prior tag "route" was a MossTank invention).
Proof (4) is now REAL byte identity (Assert.Equal(original, rewritten),
no comment stripping, no blank-line normalization) plus a new nav-only
case (WriterOutputMatchesMetafCanonicalEmissionNavOnly, against
nav_ab.af). Investigating the raw bytes of every candidate fixture
found real, PRE-EXISTING header divergence unrelated to this writer:
aphus.af/neftet.af/follower.af open "~~ {\r\n~~ " (CRLF) where a fresh
metaf conversion's header is bare-LF internally ("~~ {\n~~ ",
confirmed against augments.af/bella.af/gauntlet_leader.af/
empyrean_facility.af/example_sort_meta.af) — evidence of a re-save by
something other than metaf itself (e.g. a text editor normalizing every
line ending). hunting.af and lockandkey.af carry a wholly custom
hand-written banner instead of metaf's own. ByteIdenticalFixtureData is
narrowed to the five fixtures whose header IS metaf's fresh canonical
form (bella, gauntlet_leader, empyrean_facility, augments,
example_sort_meta — still five, per the slice-1 contract's floor);
aphus/neftet/hunting/follower/lockandkey keep exercising every other
proof (parse, parse-write-parse, and the ptl/tlk direct assertions from
the item-A fix) normally, with the header divergence documented at the
exclusion site rather than asserted away.
Three MossTankPanelTests assertions changed from StartsWith to Contains
("STATE: "/"NAV: ") since exported .af content is no longer the first
thing in the file.
Full MossTank suite: 570 -> 566 (5 fixtures dropped from the
byte-identity theory, replaced by 1 new nav-only fact: -4 net).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>