What is true
morph::model::payloadShapeString<A>() (include/morph/core/payload_schema.hpp,
added for #174) renders every type that carries its own glz::meta as the
single opaque tag x, because it deliberately refuses to use glz::name_v —
that name is derived from __PRETTY_FUNCTION__/__FUNCSIG__ and differs
between compilers, and a journal fingerprint that changes when the compiler
changes would make a journal unreadable by a peer build.
Measured on the #174 branch (clang++ -std=c++23, standalone probe):
struct WithSpecial {
morph::math::Rational amount;
morph::time::Timestamp at;
morph::util::Tagged<std::string, "acct"> id;
};
payloadShapeString<WithSpecial>() -> (amount:x,at:x,id:x)
So swapping Rational for Timestamp in a recorded action's field does not
change the fingerprint, and replay()'s mismatch gate does not fire. (Swapping
a custom-codec type for a plain one is caught — x versus s — and every
member rename, addition, and removal is caught regardless of the member types.)
This is documented as a known boundary in docs/spec/journal/journal.md, "What
the fingerprint does not catch". Filing it so the boundary is tracked rather
than only described.
What a fix would need
A per-type discriminator that is stable across compilers, standard libraries,
and platforms — not a compiler-spelled type name. Candidates:
- An opt-in trait a custom-codec type specialises to declare its own stable
shape tag (morph::model::PayloadShapeTag<T>), defaulted to x. Cheap;
requires each such type to opt in, and a new type silently gets x again.
- Hashing
glz::write_json_schema<T>(). Type-aware and derived, but its
$defs keys come from glz::name_v, which reintroduces exactly the
portability problem — would need the $defs normalised away first.
Verification status
Reproduced. The probe above was compiled and run on the #174 branch. Not
measured: whether any shipped action in examples/** actually has two
custom-codec fields whose types could plausibly be swapped for one another —
this is a gap in the mechanism, not an observed defect in a rung.
What would change the verdict
Close when the fingerprint distinguishes at least Rational, Quantity,
DateTime, and Tagged from one another without introducing a
compiler-dependent term, or when a decision is recorded that x is the
permanent answer and the spec's boundary paragraph is the whole story.
What is true
morph::model::payloadShapeString<A>()(include/morph/core/payload_schema.hpp,added for #174) renders every type that carries its own
glz::metaas thesingle opaque tag
x, because it deliberately refuses to useglz::name_v—that name is derived from
__PRETTY_FUNCTION__/__FUNCSIG__and differsbetween compilers, and a journal fingerprint that changes when the compiler
changes would make a journal unreadable by a peer build.
Measured on the #174 branch (
clang++ -std=c++23, standalone probe):So swapping
RationalforTimestampin a recorded action's field does notchange the fingerprint, and
replay()'s mismatch gate does not fire. (Swappinga custom-codec type for a plain one is caught —
xversuss— and everymember rename, addition, and removal is caught regardless of the member types.)
This is documented as a known boundary in
docs/spec/journal/journal.md, "Whatthe fingerprint does not catch". Filing it so the boundary is tracked rather
than only described.
What a fix would need
A per-type discriminator that is stable across compilers, standard libraries,
and platforms — not a compiler-spelled type name. Candidates:
shape tag (
morph::model::PayloadShapeTag<T>), defaulted tox. Cheap;requires each such type to opt in, and a new type silently gets
xagain.glz::write_json_schema<T>(). Type-aware and derived, but its$defskeys come fromglz::name_v, which reintroduces exactly theportability problem — would need the
$defsnormalised away first.Verification status
Reproduced. The probe above was compiled and run on the #174 branch. Not
measured: whether any shipped action in
examples/**actually has twocustom-codec fields whose types could plausibly be swapped for one another —
this is a gap in the mechanism, not an observed defect in a rung.
What would change the verdict
Close when the fingerprint distinguishes at least
Rational,Quantity,DateTime, andTaggedfrom one another without introducing acompiler-dependent term, or when a decision is recorded that
xis thepermanent answer and the spec's boundary paragraph is the whole story.