feat(prepass): the excerpt's new fields reach the prompt, po stops dropping them twice
P2 measured that the producer's payload now carries title/req_number/sources/source_* on every excerpt (14 members, was 9), but PrepassExcerpt ignored them (extra="ignore") and _data_blocks rendered only concept_id/adjudication/trust_tier -- so (b') was a po verdict, never a model verdict. title/req_number/sources are now named fields; source_* locators are read via model_extra and a prefix scan (measured: the producer treats source_* as an open-ended family, not a fixed allowlist), so a future producer's new source_foo key reaches the prompt without a code change here. A P1-form payload renders byte-identical to before. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
c6e6066b1b
commit
2453246d4b
5 changed files with 406 additions and 3 deletions
|
|
@ -110,6 +110,16 @@ class PrepassDenominators(_Permissive):
|
|||
delivered: int
|
||||
|
||||
|
||||
class PrepassSource(_Permissive):
|
||||
"""SS 8's declared address for an excerpt: where the underlying source document lives.
|
||||
|
||||
A fixed, singular member (never a growing family like ``source_*``) — named on purpose.
|
||||
"""
|
||||
|
||||
resource: str
|
||||
title: str | None = None
|
||||
|
||||
|
||||
class PrepassExcerpt(_Permissive):
|
||||
"""One delivered unit of bundle content.
|
||||
|
||||
|
|
@ -117,8 +127,21 @@ class PrepassExcerpt(_Permissive):
|
|||
names no content member at all — a payload can be fully conformant and carry nothing to read,
|
||||
and this seam's entire value is the content. Requiring them refuses that case by name instead
|
||||
of discovering it as an empty prompt.
|
||||
|
||||
``title``, ``req_number`` and ``sources`` are named fields because they are SS-8-declared,
|
||||
singular members — every payload has at most one of each. ``source_*`` locators
|
||||
(``source_element_id``, ``source_sha256``, and whatever a future producer adds) are NOT named
|
||||
here: measured (P3, order 20260908T141941Z), the producer's own message calls that a PREFIX
|
||||
RULE rather than a fixed allowlist — a real corpus already carries five such members where
|
||||
another carries two. Naming two of them would need a new field and a new render line for a
|
||||
third; ``extra="allow"`` plus :meth:`source_locators`' prefix scan needs neither. Every field
|
||||
here defaults to ``None`` (or, for ``sources``, absent) because most payloads in this
|
||||
repository predate P2's producer change and carry none of them — a required field would
|
||||
refuse every payload written before today.
|
||||
"""
|
||||
|
||||
model_config = ConfigDict(extra="allow")
|
||||
|
||||
bundle_id: str
|
||||
concept_id: str
|
||||
sha256: str
|
||||
|
|
@ -126,6 +149,26 @@ class PrepassExcerpt(_Permissive):
|
|||
trust_tier: str
|
||||
text: str
|
||||
text_sha256: str
|
||||
title: str | None = None
|
||||
req_number: str | None = None
|
||||
sources: tuple[PrepassSource, ...] | None = None
|
||||
|
||||
def source_locators(self) -> tuple[tuple[str, str], ...]:
|
||||
"""Every ``source_*`` scalar the producer attached, sorted by key.
|
||||
|
||||
Reads ``model_extra`` rather than a named field for each one — the prefix-rule reason
|
||||
this class's docstring gives. ``sources`` itself is excluded: it is a named field (a list,
|
||||
never a scalar) and does not land in ``model_extra`` in the first place, but the guard
|
||||
is explicit rather than relying on that.
|
||||
"""
|
||||
extra = self.model_extra or {}
|
||||
return tuple(
|
||||
sorted(
|
||||
(key, str(value))
|
||||
for key, value in extra.items()
|
||||
if key.startswith("source_") and key != "sources"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class PrepassWithheld(_Permissive):
|
||||
|
|
@ -505,14 +548,39 @@ def _declaration_lines(payload: PrepassPayload, *, rest_reachable: bool = False)
|
|||
]
|
||||
|
||||
|
||||
def _excerpt_header(excerpt: PrepassExcerpt) -> str:
|
||||
"""The BEGIN line for one excerpt: ``concept_id`` plus whatever the producer named it with.
|
||||
|
||||
**Known-negative, load-bearing:** a P1-form excerpt (none of the five new fields) renders
|
||||
BYTE-IDENTICAL to before P3 — the loop below appends nothing, and the line is exactly the
|
||||
old ``(adjudication: ..., trust_tier: ...)`` form
|
||||
(``test_a_p1_form_payload_renders_the_header_exactly_as_before``). Carrying a field through
|
||||
must never change what an older payload renders as.
|
||||
|
||||
``req_number`` and ``title`` are what a person would cite; the address (``sources[0].resource``)
|
||||
and every ``source_*`` locator are what lets a claim be traced back to the document that
|
||||
produced it — measured (P2 SS 4) to be the exact thing modelled proposals cited a UUID instead
|
||||
of, because the UUID was the only identifier that reached the prompt.
|
||||
"""
|
||||
fields = [f"adjudication: {excerpt.adjudication}", f"trust_tier: {excerpt.trust_tier}"]
|
||||
if excerpt.req_number is not None:
|
||||
fields.append(f"req_number: {excerpt.req_number}")
|
||||
if excerpt.title is not None:
|
||||
fields.append(f"title: {excerpt.title}")
|
||||
if excerpt.sources:
|
||||
fields.append(f"source: {excerpt.sources[0].resource}")
|
||||
for key, value in excerpt.source_locators():
|
||||
fields.append(f"{key}: {value}")
|
||||
return f"--- BEGIN DATA {excerpt.concept_id} ({', '.join(fields)}) ---"
|
||||
|
||||
|
||||
def _data_blocks(payload: PrepassPayload) -> list[str]:
|
||||
"""The delimited DATA blocks, one per delivered excerpt (SS 9.3), shared by both arms."""
|
||||
lines: list[str] = []
|
||||
for excerpt in payload.excerpts:
|
||||
lines += [
|
||||
"",
|
||||
f"--- BEGIN DATA {excerpt.concept_id} "
|
||||
f"(adjudication: {excerpt.adjudication}, trust_tier: {excerpt.trust_tier}) ---",
|
||||
_excerpt_header(excerpt),
|
||||
excerpt.text,
|
||||
f"--- END DATA {excerpt.concept_id} ---",
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue