Session hooks and extraction¶
retold.ingest.session ¶
The session transcript: a process-local cache over persisted turns, and the adapter-facing hooks.
SessionBuffer ¶
Read session turns efficiently while keeping writes durable in the store.
Call append_turn on this buffer, rather than on its store, whenever the cache is in use.
turns ¶
turns(session_id: str | None) -> list[Turn]
Return a detached transcript in turn order, or no turns for a missing session ID.
append_turn ¶
append_turn(turn: Turn) -> None
Persist a turn and invalidate the matching cached transcript.
invalidate ¶
invalidate(session_id: str) -> None
Drop the cached transcript so the next read sees turns another process or thread appended.
SessionHooks ¶
LLD 12: the three calls an adapter makes, plus the idle-timeout split for hosts without a session end.
A split closes the idle session, hands it to on_end for extraction, and continues under a derived
session id. Evidence quoted from the earlier segment is then unfindable from the new one, so such a
write is downgraded by the ordinary evidence rule rather than lost; a cross-session lookback is an LLD 18
item and is not built here.
on_session_start ¶
on_session_start(
principal: Principal, *, at: datetime | None = None
) -> None
Create the session for the derived principal; a repeated start is a no-op.
on_turn ¶
on_turn(
principal: Principal,
role: TurnRole,
content: str,
*,
at: datetime | None = None,
) -> Principal
Append one numbered turn and return the principal to keep using, split if the session went idle.
on_session_end ¶
on_session_end(
principal: Principal, *, at: datetime | None = None
) -> Thread | None
Mark the session complete and return the extraction thread the callback started, if any.
retold.ingest.ingestor ¶
The explicit, evidence-backed memory write path.
WriteRequest
dataclass
¶
The validated values accepted by the framework-neutral memory write path.
SummaryRequest
dataclass
¶
One session summary: the extractor's text plus the session it describes.
WriteResult
dataclass
¶
The durable outcome, lifecycle status, audit note, and timings of one write.
EntityAmbiguityCandidate
dataclass
¶
One readable entity returned to let a caller resolve an ambiguous mention safely.
Ingestor ¶
Write explicit memories with evidence, lifecycle checks, durable indexes, and audit events.
write ¶
write(
principal: Principal, request: WriteRequest
) -> WriteResult
Validate and persist one explicit memory or return its safe non-write outcome.
revise ¶
revise(
principal: Principal,
record_id: str,
action: Literal["confirm", "supersede", "expire"],
reason: str,
*,
content: str | None = None,
source_kind: SourceKind = "agent_inference",
evidence: str | None = None,
evidence_turn: int | None = None,
) -> WriteResult
Apply a user-authorized lifecycle revision after checking scope, status, and supersession authority.
write_session_summary ¶
write_session_summary(
principal: Principal, request: SummaryRequest
) -> WriteResult
Write the one live summary for a session, replacing an earlier summary whose text changed.
The summary is keyed by source_ref = "session:<id>", not by neighbour similarity. A re-run with
identical text changes nothing; changed text supersedes the earlier summary so its history remains.
Mention-role entities are linked when they resolve unambiguously and dropped otherwise.
retold.ingest.extraction ¶
Session extraction: claim, extract, validate, review, revalidate, write, summarise, finish.
The order is the safety argument. A session is claimed atomically before any model call, so two workers
cannot both process it. The extractor and the reviewer run before anything is written, so a failure in
either writes nothing and leaves the claim to expire. Accepted candidates then go through the same
ingestor as an explicit memory_write; the extractor gets no shortcut past evidence, entity, duplicate,
or supersession rules. Activation is decided afterwards by the activation service, which is a separate
decision from whether the candidate was worth keeping.
CandidateOutcome
dataclass
¶
What happened to one proposed candidate, and at which stage.
ExtractionRunner ¶
Run the asynchronous write path for one finished session.
schedule ¶
schedule(
session_id: str,
principal: Principal,
*,
force: bool = False,
) -> Thread
Run extract_session on a daemon thread; the host continues without waiting.
extract_session ¶
extract_session(
session_id: str,
principal: Principal,
*,
force: bool = False,
) -> ExtractionResult
LLD 8.2 steps 1 to 8. Refuses without an event when another worker holds the session.
retold.ingest.extractor ¶
The extractor: a finished transcript in, candidate records and one session summary out.
The extractor proposes; it never writes. Its output is validated, reviewed, and revalidated by
extraction.py before anything reaches the ingestor. The prompt lives beside this module and its version
is recorded on every extraction.run event, so a prompt change is tracked like an embedding-model change.
ExtractionError ¶
Bases: RuntimeError
The extractor could not produce a usable ExtractionOutput; the run fails closed.
FakeExtractor ¶
Return a canned output, run a script, or raise; records every call for assertions.
StructuredLLMExtractor ¶
Call a hosted model with the versioned prompt and parse its JSON into ExtractionOutput.
render_request ¶
render_request(
turns: Sequence[Turn], context: ExtractionContext
) -> str
Number the transcript and attach the bounded context the prompt describes.
parse_extraction_output ¶
parse_extraction_output(
payload: dict[str, Any], *, max_candidates: int
) -> ExtractionOutput
Validate the model's JSON strictly; anything outside the contract is a malformed output.
dump_candidate ¶
dump_candidate(
candidate: CandidateRecord,
) -> dict[str, Any]
Serialise a candidate for prompts and audit payloads.
retold.ingest.reviewer ¶
Review before apply: an independent judgement on each extracted candidate.
The reviewer sees the candidate, its evidence turn with the turns around it, and the live records about the
same subject in the destination scope. It accepts, rejects, or narrows. check_revision enforces what a
revision may touch: content, the attribute hint, temporal metadata, and confidence, each only in the
narrowing direction. Source authority, the quote and its turn, the scope, the entity mentions, and the
event time are outside its reach; the extraction runner rejects any revision that changes them.
ReviewError ¶
Bases: RuntimeError
The reviewer failed or answered outside its contract; the whole extraction run fails closed.
TableReviewer ¶
Decide by candidate content from a table, or by a script; accept anything unlisted.
StructuredLLMReviewer ¶
Ask a hosted model for accept, reject, or a narrowing revision, using the versioned prompt.
check_revision ¶
check_revision(
original: CandidateRecord, revised: CandidateRecord
) -> str | None
Return why a revision is invalid, or None when it only narrows the candidate.
adjacent_turns ¶
adjacent_turns(
turns: Sequence[Turn], turn_number: int
) -> list[Turn]
The turns immediately before and after turn_number.