Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/generated/api-operation-parity.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/library-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ Route/tier class: `index-read`. CLI: `analyze`, `read`. MCP: `query`, `get`, `st
| `Polylogue.pathology_report` | `async (self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None) -> 'PathologyReport'` |
| `Polylogue.portfolio_bundle` | `async (self, spec: 'SessionQuerySpec | None' = None, *, limit: 'int | None' = None, top_n: 'int' = 10) -> 'PortfolioBundle'` |
| `Polylogue.export_insight_bundle` | `async (self, request: 'InsightExportBundleRequest') -> 'InsightExportBundleResult'` |
| `Polylogue.regenerate_private_fable_packet` | `async (self, *, seed: 'str', requested_size: 'int', schema_id: 'str' = 'delegation.discourse', schema_version: 'int' = 1, exact_template_cap: 'int' = 1) -> 'FableDelegationPacket'` |

### Context and evidence

Expand Down
5 changes: 5 additions & 0 deletions docs/plans/layering-surface-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"file": "polylogue/api/archive.py",
"import": "polylogue.sources.parsers.hermes_lifecycle"
},
{
"target": "polylogue/api",
"file": "polylogue/api/archive.py",
"import": "polylogue.storage.block_anchor"
},
{
"target": "polylogue/api",
"file": "polylogue/api/archive.py",
Expand Down
77 changes: 77 additions & 0 deletions polylogue/api/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
from polylogue.core.protocols import ProgressCallback
from polylogue.insights.audit import InsightRigorAuditQuery, InsightRigorAuditReport
from polylogue.insights.export_bundles import InsightExportBundleRequest, InsightExportBundleResult
from polylogue.insights.fable_packet import FableDelegationPacket
from polylogue.insights.hermes_integration_health import HermesIntegrationHealth
from polylogue.insights.judgment.types import ComparativeJudgment
from polylogue.insights.pathology import PathologyReport
Expand Down Expand Up @@ -3858,6 +3859,7 @@ async def export_otel(

async def resolve_ref(self, ref: str) -> PublicRefResolutionPayload:
"""Resolve one public object/evidence ref into a bounded read payload."""
from polylogue.storage.block_anchor import InvalidBlockAnchorError, parse_block_anchor, resolve_block_anchor
from polylogue.surfaces.payloads import PublicRefResolutionPayload

invalid_unicode_ref = _invalid_unicode_ref_payload(ref)
Expand All @@ -3875,6 +3877,47 @@ async def resolve_ref(self, ref: str) -> PublicRefResolutionPayload:
return cast(PublicRefResolutionPayload, bounded_batch_ref)
if batch_candidate.kind != "annotation-batch":
return cast(PublicRefResolutionPayload, bounded_batch_ref)
try:
block_anchor = parse_block_anchor(ref)
except InvalidBlockAnchorError:
block_anchor = None
if block_anchor is not None:
archive_root = _active_archive_root(self.config)

def read_anchor(archive: ArchiveStore) -> PublicRefResolutionPayload:
resolution = resolve_block_anchor(archive._conn, block_anchor)
resolved = resolution.state in {"ok", "drifted_position", "drifted_message"}
object_refs = (
(f"message:{resolution.resolved_message_id}",) if resolution.resolved_message_id is not None else ()
)
return PublicRefResolutionPayload(
ref=ref,
kind="block",
resolved=resolved,
payload_kind="block-anchor",
payload={
"state": resolution.state,
"anchor": resolution.anchor.to_text(),
"resolved_message_id": resolution.resolved_message_id,
"resolved_position": resolution.resolved_position,
"candidates": [
{"message_id": message_id, "position": position}
for message_id, position in resolution.candidates
],
"detail": resolution.detail,
},
object_refs=object_refs,
caveats=() if resolved else (resolution.detail or f"block anchor state: {resolution.state}",),
)

return await run_archive_read(
archive_root,
operation="archive.resolve_block_anchor",
arguments={"ref": ref},
work=read_anchor,
projection="block-anchor-resolution",
stable_order="canonical",
)
try:
parsed = parse_public_ref(ref)
except ValueError as exc:
Expand Down Expand Up @@ -5491,6 +5534,40 @@ async def insight_rigor_audit(
workload_class="scan",
)

async def regenerate_private_fable_packet(
self,
*,
seed: str,
requested_size: int,
schema_id: str = "delegation.discourse",
schema_version: int = 1,
exact_template_cap: int = 1,
) -> FableDelegationPacket:
"""Cold-regenerate the private descriptive Fable packet from the archive."""
from polylogue.insights.fable_packet import regenerate_private_fable_packet

return await run_archive_read(
_active_archive_root(self.config),
operation="insights.fable_packet.regenerate",
arguments={
"seed": seed,
"requested_size": requested_size,
"schema_id": schema_id,
"schema_version": schema_version,
"exact_template_cap": exact_template_cap,
},
work=lambda archive: regenerate_private_fable_packet(
archive,
seed=seed,
requested_size=requested_size,
schema_id=schema_id,
schema_version=schema_version,
exact_template_cap=exact_template_cap,
),
projection="fable-delegation-packet",
workload_class="scan",
)

async def get_messages_paginated(
self,
session_id: str,
Expand Down
1 change: 1 addition & 0 deletions polylogue/api/operation_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ def _surface(*names: str) -> SurfaceBinding:
"Polylogue.pathology_report",
"Polylogue.portfolio_bundle",
"Polylogue.export_insight_bundle",
"Polylogue.regenerate_private_fable_packet",
),
_surface("analyze", "read"),
_surface("query", "get", "status", "explain"),
Expand Down
14 changes: 14 additions & 0 deletions polylogue/archive/query/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
from polylogue.archive.query.expression import RefOperand, RelationGrain, ResolvedRefOperand
from polylogue.core.query_identity import require_supported_definition_protocol_version
from polylogue.core.refs import ObjectRef
from polylogue.storage.sqlite.holdout_cohorts import (
HoldoutAccessError,
require_non_holdout_access,
)
from polylogue.storage.sqlite.query_objects import (
EvaluationReceipt,
QueryObject,
Expand Down Expand Up @@ -72,11 +76,13 @@ def __init__(
*,
owner_query_hash: str | None = None,
created_at_ms: int = 0,
declared_confirmation: bool = False,
) -> None:
self._conn = conn
self._evaluator = evaluator
self._owner_query_hash = owner_query_hash
self._created_at_ms = created_at_ms
self._declared_confirmation = declared_confirmation

def resolve_ref_operand(self, operand: RefOperand) -> ResolvedRefOperand:
reference = operand.reference
Expand Down Expand Up @@ -121,6 +127,14 @@ def _retained_result(
manifest = get_result_set(self._conn, result_set_id)
if manifest is None:
raise RetainedRelationUnavailableError(f"retained result-set:{result_set_id} is unavailable")
try:
require_non_holdout_access(
self._conn,
result_set_id,
declared_confirmation=self._declared_confirmation,
)
except HoldoutAccessError as exc:
raise RetainedRelationUnavailableError(str(exc)) from exc
if extra_lineage:
run = get_retained_query_run(self._conn, extra_lineage[0].object_id)
if run is None or manifest.query_hash != run.query_hash:
Expand Down
Loading