feat(inbox): surface adjudication state and its dwell time

This commit is contained in:
Kjell Tore Guttormsen 2026-09-02 14:49:45 +02:00
commit a60312a5f3
9 changed files with 219 additions and 9 deletions

View file

@ -194,6 +194,19 @@ def render_inbox_concept(
frontmatter[policy.offset_key] = _render_flow_list([str(offset) for offset in segment.span])
if segment.parent_id is not None:
frontmatter["parent"] = segment.parent_id
if policy.adjudication_key is not None:
# The per-entry verdict IS the discriminator. A plan-level
# `adjudicated: true` with no record for THIS entry leaves it
# `proposed`: B2 forbids the ratified state without the three keys
# beside it, so a flag alone cannot promote a segment.
verdict = segment.adjudication
if verdict is None:
frontmatter[policy.adjudication_key] = ADJUDICATION_PROPOSED
else:
frontmatter[policy.adjudication_key] = ADJUDICATION_ADJUDICATED
frontmatter["adjudicated_by"] = verdict.adjudicated_by
frontmatter["adjudicated_at"] = verdict.adjudicated_at
frontmatter["adjudication_dwell_s"] = str(verdict.adjudication_dwell_s)
return f"---\n{profile.frontmatter.emit(frontmatter)}\n---\n\n{_normalize_body(text)}"
@ -847,6 +860,23 @@ def process_inbox(
)
#: The adjudication states a segment concept may carry, and the whole set.
#: CLOSED on purpose (PM decision B2, `docs/plan/office-intake.md` § 5): a
#: value outside it is an error, not an extension point. The consumer's half of
#: the same contract is that ABSENCE of the key means `unknown` -- an older
#: bundle -- never a collapse to `absent`, so a producer emitting the key
#: inconsistently would make that distinction unmeasurable on their side.
ADJUDICATION_PROPOSED = "proposed"
ADJUDICATION_ADJUDICATED = "adjudicated"
ADJUDICATION_STATES = (ADJUDICATION_PROPOSED, ADJUDICATION_ADJUDICATED)
#: Written beside the state when, and only when, it is `adjudicated`. The dwell
#: time travels WITH the verdict: a ratified flag carrying no per-item time is
#: unfalsifiable, and it is the same number that makes adjudication throughput
#: measurable at all.
ADJUDICATION_COMPANION_KEYS = ("adjudicated_by", "adjudicated_at", "adjudication_dwell_s")
def _validate_facets(structure: DocumentStructure, profile: BundleProfile) -> None:
"""Refuse a document whose values cannot be rendered as index facets.
@ -859,8 +889,22 @@ def _validate_facets(structure: DocumentStructure, profile: BundleProfile) -> No
markers are this library's own tokens.
"""
assert profile.index.facets is not None
values = structure_frontmatter(structure, profile.index.facets.keys)
policy = profile.segmentation
key = None if policy is None else policy.adjudication_key
# Refused HERE rather than at reprojection, for the reason above: the only
# adjudication value that can be wrong is one the producer declared in the
# dropped document itself, and refusing it per file keeps a single bad
# document from failing the index for every other one.
if key is not None and key in values and values[key] not in ADJUDICATION_STATES:
raise MaterializationError(
f"frontmatter key {key!r} carries {values[key]!r}, which is outside the closed "
f"set {ADJUDICATION_STATES} — the adjudication state is a contract, not an "
"extension point",
code="index_facet_invalid",
)
try:
profile.index.facets.render(structure_frontmatter(structure, profile.index.facets.keys))
profile.index.facets.render(values)
except ValueError as exc:
raise MaterializationError(str(exc), code="index_facet_invalid") from exc