fix(packs/register): remove bare '.' closings + ratify gate refuses them
The widened 100-pack tour surfaced four packs whose closings bucket
included a bare '.' entry: assertive_v1, blunt_v1, dry_v1, and
mathematical_v1. Seeded variation selects from buckets uniformly, so
roughly 1/N of turns would emit a '..'-style surface artefact
(e.g. 'Truth is what is true..') when '.' was selected and appended
to a surface CORE's deterministic realizer already terminated with
'.'.
This commit:
* Strips the bare '.' entry from the four affected packs' closings.
The remaining entries (e.g. ' — qed.', ' — that's it.', '') all
carry their own leading separator, so concatenation produces a
clean surface.
* Re-runs scripts/ratify_register_packs.py to re-seal each pack's
mastery_report.json with a fresh pack_source_sha256 and
self_seal_sha256 — these companion files are part of the diff
because pack content changed.
* Adds _validate_discourse_markers_shape() to
scripts/ratify_register_packs.py as defense in depth. The new
R4-tier gate refuses any closing entry whose first character is
bare sentence-final punctuation ('.', '!', '?', ';', ':') or an
alphanumeric — both classes would produce concatenation artefacts.
Ellipsis ('...', '…') is explicitly exempt as a legitimate
stylistic ending.
Verified:
* core eval cognition byte-identical (the eval runs unregistered)
* tests/test_cognition_eval_register_matrix.py: 801 passed in 5:23
(100 registers × 8 projection invariants + meta-test), confirming
the closing fix did not perturb ADR-0072 trace_hash invariance
or any per-case projection.
* Hand-verification across {assertive,blunt,dry,mathematical}_v1
× 4 prompts = 16 surfaces: 0 remaining double-period artefacts.
* Re-running ratify against a re-introduced bad closing produces
SystemExit with the new gate's diagnostic message.
mathematical_v1 now reads beautifully under "What is light?":
"Lemma: Light is visible medium that reveals truth. — qed."
This commit is contained in:
parent
483c66dc5f
commit
ae38412e93
9 changed files with 77 additions and 22 deletions
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Assertive register — declarative markers, no hedging.",
|
||||
"schema_version": "1.0.0",
|
||||
"mastery_report_sha256": "44750505a1fce4eaadf47a4fe5a22c8d3d53d41957f5d161797a539dc9258844",
|
||||
"mastery_report_sha256": "785f079aad5e2492ed7d054716ed2ecf897622230bd2cc96d419cf0ebe9cc9f5",
|
||||
"display_name": "Assertive",
|
||||
"depth_preference": "standard",
|
||||
"realizer_overrides": {
|
||||
|
|
@ -19,8 +19,7 @@
|
|||
],
|
||||
"transitions": [],
|
||||
"closings": [
|
||||
"",
|
||||
"."
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"depth_preference": "standard",
|
||||
"discourse_markers_empty": false,
|
||||
"marker_bucket_sizes": {
|
||||
"closings": 2,
|
||||
"closings": 1,
|
||||
"openings": 4,
|
||||
"transitions": 0
|
||||
},
|
||||
|
|
@ -16,10 +16,10 @@
|
|||
},
|
||||
"failure_reasons": [],
|
||||
"issued_at": "2026-05-20T00:00:00Z",
|
||||
"pack_source_sha256": "a6d1c49aee2ef5222c7e4481ddb968b40be4eb13cae6eaa14ad140a1a60ec128",
|
||||
"pack_source_sha256": "f542dae9062ee981018846517da65c6480200138e029df7254669b5b0a9dfc44",
|
||||
"ratification_method": "seeded_variation_replay_equivalence",
|
||||
"ratified": true,
|
||||
"register_id": "assertive_v1",
|
||||
"report_sha256": "44750505a1fce4eaadf47a4fe5a22c8d3d53d41957f5d161797a539dc9258844",
|
||||
"report_sha256": "785f079aad5e2492ed7d054716ed2ecf897622230bd2cc96d419cf0ebe9cc9f5",
|
||||
"schema_version": "1.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Blunt register — short, sharp, no qualification.",
|
||||
"schema_version": "1.0.0",
|
||||
"mastery_report_sha256": "2925ce07bd132a235296098d135ad46f171efc46f2cead69b06f52d309661d33",
|
||||
"mastery_report_sha256": "0c435910a295c7cade443cccfd175c90f0302cc90f0c5a6c613ef62c190462ed",
|
||||
"display_name": "Blunt",
|
||||
"depth_preference": "terse",
|
||||
"realizer_overrides": {
|
||||
|
|
@ -21,8 +21,7 @@
|
|||
],
|
||||
"transitions": [],
|
||||
"closings": [
|
||||
"",
|
||||
"."
|
||||
""
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"depth_preference": "terse",
|
||||
"discourse_markers_empty": false,
|
||||
"marker_bucket_sizes": {
|
||||
"closings": 2,
|
||||
"closings": 1,
|
||||
"openings": 4,
|
||||
"transitions": 0
|
||||
},
|
||||
|
|
@ -18,10 +18,10 @@
|
|||
},
|
||||
"failure_reasons": [],
|
||||
"issued_at": "2026-05-20T00:00:00Z",
|
||||
"pack_source_sha256": "71a9bc92336de59c4014777e5d3e36bdece30c6519e21f7fd8df984f7847309f",
|
||||
"pack_source_sha256": "6f148b6f90971ff4be82d8fa22001d890e2f8c98ac8f6caa4f453328ba1eabcd",
|
||||
"ratification_method": "seeded_variation_replay_equivalence",
|
||||
"ratified": true,
|
||||
"register_id": "blunt_v1",
|
||||
"report_sha256": "2925ce07bd132a235296098d135ad46f171efc46f2cead69b06f52d309661d33",
|
||||
"report_sha256": "0c435910a295c7cade443cccfd175c90f0302cc90f0c5a6c613ef62c190462ed",
|
||||
"schema_version": "1.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Dry register — understated, factual.",
|
||||
"schema_version": "1.0.0",
|
||||
"mastery_report_sha256": "1f3232b4eb99d6df156de3f34c5e8fe24f8453ac04a59bb3bd41553ffc5b169a",
|
||||
"mastery_report_sha256": "6f413313c0cc42bae47dfb3f1273d429006c0b4405a48764ad6aac8d69da3ebc",
|
||||
"display_name": "Dry",
|
||||
"depth_preference": "standard",
|
||||
"realizer_overrides": {
|
||||
|
|
@ -19,7 +19,6 @@
|
|||
"transitions": [],
|
||||
"closings": [
|
||||
"",
|
||||
".",
|
||||
" — that's it."
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"depth_preference": "standard",
|
||||
"discourse_markers_empty": false,
|
||||
"marker_bucket_sizes": {
|
||||
"closings": 3,
|
||||
"closings": 2,
|
||||
"openings": 3,
|
||||
"transitions": 0
|
||||
},
|
||||
|
|
@ -16,10 +16,10 @@
|
|||
},
|
||||
"failure_reasons": [],
|
||||
"issued_at": "2026-05-20T00:00:00Z",
|
||||
"pack_source_sha256": "eccd21f4b00102526fc22d28bac38e091dbda30a408848ac6f42bbfc16716bfb",
|
||||
"pack_source_sha256": "0db49fb251edc60106c04ca75b3422b4661a26e8e1ac17cd9ef2c7973f6617c8",
|
||||
"ratification_method": "seeded_variation_replay_equivalence",
|
||||
"ratified": true,
|
||||
"register_id": "dry_v1",
|
||||
"report_sha256": "1f3232b4eb99d6df156de3f34c5e8fe24f8453ac04a59bb3bd41553ffc5b169a",
|
||||
"report_sha256": "6f413313c0cc42bae47dfb3f1273d429006c0b4405a48764ad6aac8d69da3ebc",
|
||||
"schema_version": "1.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Mathematical register — proof-cadence.",
|
||||
"schema_version": "1.0.0",
|
||||
"mastery_report_sha256": "04e9a09cce4e599781b2d4994383cebf4f6529391f58005a84e69363494508c2",
|
||||
"mastery_report_sha256": "b85e2505fe647aa474b599cfa447c3677ad92c7c305d34ae63c97c8b5ba82fb6",
|
||||
"display_name": "Mathematical",
|
||||
"depth_preference": "standard",
|
||||
"realizer_overrides": {
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
"transitions": [],
|
||||
"closings": [
|
||||
"",
|
||||
".",
|
||||
" — qed."
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"depth_preference": "standard",
|
||||
"discourse_markers_empty": false,
|
||||
"marker_bucket_sizes": {
|
||||
"closings": 3,
|
||||
"closings": 2,
|
||||
"openings": 4,
|
||||
"transitions": 0
|
||||
},
|
||||
|
|
@ -17,10 +17,10 @@
|
|||
},
|
||||
"failure_reasons": [],
|
||||
"issued_at": "2026-05-20T00:00:00Z",
|
||||
"pack_source_sha256": "f7885f683ad806730ede0ce1a0a4f3d2503ead583719f055949e2a1ccdad281e",
|
||||
"pack_source_sha256": "59be9a46ca10a612aa201fcb3736d1791505b9fea5add9b40ac5e57e21f84028",
|
||||
"ratification_method": "seeded_variation_replay_equivalence",
|
||||
"ratified": true,
|
||||
"register_id": "mathematical_v1",
|
||||
"report_sha256": "04e9a09cce4e599781b2d4994383cebf4f6529391f58005a84e69363494508c2",
|
||||
"report_sha256": "b85e2505fe647aa474b599cfa447c3677ad92c7c305d34ae63c97c8b5ba82fb6",
|
||||
"schema_version": "1.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -266,6 +266,64 @@ def _validate_per_intent_block(
|
|||
)
|
||||
|
||||
|
||||
_BARE_SENTENCE_FINAL_PUNCT: frozenset[str] = frozenset(".!?;:")
|
||||
"""Closing entries beginning with one of these characters concatenate
|
||||
directly onto a surface that already ends in ``.`` (CORE's deterministic
|
||||
realizer always emits a trailing period) and produce double-punctuation
|
||||
artefacts like ``true..``. Ellipsis (``...`` / ``…``) is exempt — that
|
||||
is a legitimate stylistic ending in its own right.
|
||||
"""
|
||||
|
||||
|
||||
def _validate_discourse_markers_shape(pack: dict, register_id: str) -> None:
|
||||
"""Reject discourse-marker shapes that would produce surface
|
||||
artefacts when concatenated to a sentence-final surface.
|
||||
|
||||
Catches the class of authoring bug discovered during the 100-pack
|
||||
widened tour: a bare ``"."`` closing yields ``..`` when seeded
|
||||
variation picks it. Defense in depth — pack authors should not
|
||||
have to remember the realizer's trailing-period convention.
|
||||
|
||||
Rules (closings only — openings always lead the surface with a
|
||||
space separator inserted by the composer):
|
||||
* ``""`` is always legal (no-op closing)
|
||||
* Entries starting with bare ``.``, ``!``, ``?``, ``;``, ``:``
|
||||
are refused — they double-punctuate. Ellipsis (``"..."`` /
|
||||
``"…"``) is exempt and remains legal.
|
||||
* Entries starting with an alphanumeric character are refused —
|
||||
they would join with no separator, e.g. ``"true.holds."``.
|
||||
"""
|
||||
markers = pack.get("discourse_markers", {})
|
||||
if not isinstance(markers, dict):
|
||||
return # shape-only — schema validator owns dict-vs-not
|
||||
closings = markers.get("closings", [])
|
||||
if not isinstance(closings, list):
|
||||
return
|
||||
for entry in closings:
|
||||
if not isinstance(entry, str) or entry == "":
|
||||
continue
|
||||
first = entry[0]
|
||||
if entry.startswith(("...", "…")):
|
||||
continue
|
||||
if first in _BARE_SENTENCE_FINAL_PUNCT:
|
||||
raise SystemExit(
|
||||
f"R4 gate refuses {register_id!r}: discourse_markers."
|
||||
f"closings[{entry!r}] starts with bare sentence-final "
|
||||
f"punctuation. CORE's realizer always emits a trailing "
|
||||
f"'.', so {entry!r} concatenates to '..'-style "
|
||||
f"artefacts. Either drop the entry or prefix it with a "
|
||||
f"separator (e.g. ' — note.')."
|
||||
)
|
||||
if first.isalnum():
|
||||
raise SystemExit(
|
||||
f"R4 gate refuses {register_id!r}: discourse_markers."
|
||||
f"closings[{entry!r}] starts with an alphanumeric "
|
||||
f"character. Closings concatenate directly to the "
|
||||
f"surface — prefix with a space or punctuation "
|
||||
f"separator (e.g. ' note.' or ' — note.')."
|
||||
)
|
||||
|
||||
|
||||
def _markers_have_content(pack: dict) -> bool:
|
||||
"""True iff openings or closings has at least one entry (R4 needs
|
||||
one of these populated for a marker-using ratification).
|
||||
|
|
@ -301,6 +359,7 @@ def _ratify_one(pack_path: Path, register_id: str) -> tuple[dict, dict[str, Any]
|
|||
# must have at least one of openings/closings populated. Null
|
||||
# registers pass trivially.
|
||||
_validate_overrides_known_keys(pack, register_id)
|
||||
_validate_discourse_markers_shape(pack, register_id)
|
||||
|
||||
null_register = _is_null_register(pack)
|
||||
overrides = pack.get("realizer_overrides", {}) or {}
|
||||
|
|
|
|||
Loading…
Reference in a new issue