rememberstack 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rememberstack/__init__.py +9 -0
- rememberstack/adapters/__init__.py +42 -0
- rememberstack/adapters/codex_writer.py +221 -0
- rememberstack/adapters/markitdown_converter.py +42 -0
- rememberstack/adapters/openrouter.py +136 -0
- rememberstack/adapters/selfhost/__init__.py +54 -0
- rememberstack/adapters/selfhost/forget.py +66 -0
- rememberstack/adapters/selfhost/git.py +374 -0
- rememberstack/adapters/selfhost/lance.py +328 -0
- rememberstack/adapters/selfhost/minio.py +279 -0
- rememberstack/adapters/selfhost/mounts.py +249 -0
- rememberstack/adapters/selfhost/object_store.py +130 -0
- rememberstack/adapters/selfhost/projection.py +80 -0
- rememberstack/adapters/selfhost/queue.py +137 -0
- rememberstack/adapters/selfhost/telemetry.py +45 -0
- rememberstack/adapters/selfhost/watcher.py +70 -0
- rememberstack/adapters/testing/__init__.py +15 -0
- rememberstack/adapters/testing/cost_meter.py +13 -0
- rememberstack/adapters/testing/model_provider.py +83 -0
- rememberstack/adapters/testing/queue.py +43 -0
- rememberstack/adapters/testing/telemetry.py +22 -0
- rememberstack/client.py +19 -0
- rememberstack/core/__init__.py +127 -0
- rememberstack/core/blockizer.py +189 -0
- rememberstack/core/chunker.py +216 -0
- rememberstack/core/consumption_skill.py +275 -0
- rememberstack/core/conversion.py +76 -0
- rememberstack/core/core_manifest.py +598 -0
- rememberstack/core/extension_packs.py +124 -0
- rememberstack/core/forget.py +17 -0
- rememberstack/core/knowledge_authored.py +276 -0
- rememberstack/core/knowledge_compile.py +215 -0
- rememberstack/core/knowledge_fact_sheet.py +210 -0
- rememberstack/core/knowledge_hashing.py +68 -0
- rememberstack/core/knowledge_planner.py +64 -0
- rememberstack/core/knowledge_writer.py +175 -0
- rememberstack/core/ranking.py +200 -0
- rememberstack/core/recipe_linter.py +149 -0
- rememberstack/core/section_snap.py +209 -0
- rememberstack/core/storage_routing.py +27 -0
- rememberstack/eval/__init__.py +53 -0
- rememberstack/eval/consumption.py +141 -0
- rememberstack/eval/contradiction.py +184 -0
- rememberstack/eval/harness.py +136 -0
- rememberstack/eval/lifecycle.py +400 -0
- rememberstack/eval/operational_scale.py +49 -0
- rememberstack/eval/resolution.py +255 -0
- rememberstack/eval/retrieval_spikes.py +50 -0
- rememberstack/eval/skeleton.py +231 -0
- rememberstack/llm/__init__.py +1 -0
- rememberstack/model/__init__.py +589 -0
- rememberstack/model/adjudication.py +100 -0
- rememberstack/model/auth.py +27 -0
- rememberstack/model/blocks.py +30 -0
- rememberstack/model/chunks.py +190 -0
- rememberstack/model/claims.py +162 -0
- rememberstack/model/client.py +98 -0
- rememberstack/model/clustering.py +54 -0
- rememberstack/model/component_version.py +124 -0
- rememberstack/model/consumption.py +88 -0
- rememberstack/model/conversion.py +31 -0
- rememberstack/model/deployment.py +53 -0
- rememberstack/model/documents.py +168 -0
- rememberstack/model/envelope.py +513 -0
- rememberstack/model/evaluation.py +72 -0
- rememberstack/model/forget.py +143 -0
- rememberstack/model/git.py +13 -0
- rememberstack/model/knowledge.py +840 -0
- rememberstack/model/knowledge_authored.py +325 -0
- rememberstack/model/knowledge_planner.py +431 -0
- rememberstack/model/lifecycle.py +42 -0
- rememberstack/model/model_provider.py +78 -0
- rememberstack/model/mounts.py +24 -0
- rememberstack/model/object_store.py +21 -0
- rememberstack/model/operational_scale.py +59 -0
- rememberstack/model/operations.py +153 -0
- rememberstack/model/processing.py +228 -0
- rememberstack/model/queue.py +73 -0
- rememberstack/model/recipes.py +83 -0
- rememberstack/model/relations.py +79 -0
- rememberstack/model/resolution.py +83 -0
- rememberstack/model/retrieval_spikes.py +62 -0
- rememberstack/model/sections.py +120 -0
- rememberstack/model/telemetry.py +30 -0
- rememberstack/ports/__init__.py +29 -0
- rememberstack/ports/auth.py +16 -0
- rememberstack/ports/connector.py +23 -0
- rememberstack/ports/cost_meter.py +17 -0
- rememberstack/ports/forget.py +20 -0
- rememberstack/ports/git.py +20 -0
- rememberstack/ports/model_provider.py +28 -0
- rememberstack/ports/mounts.py +16 -0
- rememberstack/ports/object_store.py +27 -0
- rememberstack/ports/p1_index.py +92 -0
- rememberstack/ports/purge.py +93 -0
- rememberstack/ports/queue.py +23 -0
- rememberstack/ports/telemetry.py +21 -0
- rememberstack/profiles/__init__.py +22 -0
- rememberstack/profiles/selfhost.py +324 -0
- rememberstack/profiles/selfhost_forget.py +158 -0
- rememberstack/profiles/selfhost_operations.py +95 -0
- rememberstack/py.typed +1 -0
- rememberstack/spine/__init__.py +93 -0
- rememberstack/spine/admission.py +26 -0
- rememberstack/spine/backfill.py +168 -0
- rememberstack/spine/catalog_contract.py +742 -0
- rememberstack/spine/chunk_catalog.py +237 -0
- rememberstack/spine/claim_catalog.py +298 -0
- rememberstack/spine/clustering.py +740 -0
- rememberstack/spine/component_versions.py +208 -0
- rememberstack/spine/consumption.py +81 -0
- rememberstack/spine/deployment_bootstrap.py +445 -0
- rememberstack/spine/document_catalog.py +621 -0
- rememberstack/spine/entity_registry.py +205 -0
- rememberstack/spine/extension_packs.py +220 -0
- rememberstack/spine/fact_catalog.py +571 -0
- rememberstack/spine/forget.py +1753 -0
- rememberstack/spine/knowledge.py +5467 -0
- rememberstack/spine/lifecycle.py +1071 -0
- rememberstack/spine/migrations/__init__.py +1 -0
- rememberstack/spine/migrations/_helpers.py +153 -0
- rememberstack/spine/migrations/env.py +58 -0
- rememberstack/spine/migrations/script.py.mako +27 -0
- rememberstack/spine/migrations/versions/__init__.py +1 -0
- rememberstack/spine/migrations/versions/p0_02_0001_extensions_enums.py +189 -0
- rememberstack/spine/migrations/versions/p0_02_0002_infrastructure_registries.py +321 -0
- rememberstack/spine/migrations/versions/p0_02_0003_entities_evaluation_e0_e1.py +631 -0
- rememberstack/spine/migrations/versions/p0_02_0004_claims_facts_evidence.py +411 -0
- rememberstack/spine/migrations/versions/p0_02_0005_projection_knowledge_retrieval.py +391 -0
- rememberstack/spine/migrations/versions/p0_02_0006_partitions_views.py +158 -0
- rememberstack/spine/migrations/versions/p2_06_0007_invalidated_outcome.py +26 -0
- rememberstack/spine/migrations/versions/p3_01_0008_document_version_target.py +58 -0
- rememberstack/spine/migrations/versions/p3_05_0009_reconcile_stage.py +27 -0
- rememberstack/spine/migrations/versions/p3_07_0010_lifecycle_eval_suite.py +25 -0
- rememberstack/spine/migrations/versions/p4_01_0011_survivor_view_rewrite.py +57 -0
- rememberstack/spine/migrations/versions/p6_02_0012_knowledge_compile_recovery.py +58 -0
- rememberstack/spine/migrations/versions/p6_04_0013_knowledge_writer_ledger.py +46 -0
- rememberstack/spine/migrations/versions/p6_05_0014_knowledge_planner_runtime.py +217 -0
- rememberstack/spine/migrations/versions/p6_06_0015_authored_dispatch_runtime.py +38 -0
- rememberstack/spine/migrations/versions/p7_02_0016_operational_eval_suite.py +19 -0
- rememberstack/spine/migrations/versions/p7_05_0017_hard_forget.py +55 -0
- rememberstack/spine/observation_adjudication.py +778 -0
- rememberstack/spine/operations.py +298 -0
- rememberstack/spine/projection.py +662 -0
- rememberstack/spine/recipes.py +276 -0
- rememberstack/spine/resolver.py +763 -0
- rememberstack/spine/review.py +650 -0
- rememberstack/spine/settings.py +22 -0
- rememberstack/spine/supersession.py +510 -0
- rememberstack/spine/sync.py +128 -0
- rememberstack/spine/work_ledger.py +816 -0
- rememberstack/surfaces/__init__.py +110 -0
- rememberstack/surfaces/cli.py +447 -0
- rememberstack/surfaces/consumption_skill.py +87 -0
- rememberstack/surfaces/graph_queries.py +698 -0
- rememberstack/surfaces/http_api.py +377 -0
- rememberstack/surfaces/mcp.py +67 -0
- rememberstack/surfaces/query_engine.py +1591 -0
- rememberstack/surfaces/recipe_executor.py +185 -0
- rememberstack/surfaces/recipe_surface.py +219 -0
- rememberstack/surfaces/remote_mcp.py +133 -0
- rememberstack/surfaces/sdk.py +324 -0
- rememberstack/workers/__init__.py +155 -0
- rememberstack/workers/base.py +312 -0
- rememberstack/workers/e0.py +577 -0
- rememberstack/workers/e1.py +425 -0
- rememberstack/workers/e2.py +525 -0
- rememberstack/workers/e3.py +434 -0
- rememberstack/workers/forget.py +299 -0
- rememberstack/workers/knowledge_authored.py +146 -0
- rememberstack/workers/knowledge_driver.py +735 -0
- rememberstack/workers/knowledge_fact_sheet.py +123 -0
- rememberstack/workers/knowledge_planner.py +325 -0
- rememberstack/workers/knowledge_writer.py +393 -0
- rememberstack/workers/operations.py +42 -0
- rememberstack/workers/p1.py +234 -0
- rememberstack/workers/p2.py +513 -0
- rememberstack/workers/p2_analytics.py +276 -0
- rememberstack/workers/p3.py +673 -0
- rememberstack/workers/reconcile.py +485 -0
- rememberstack/workers/sync.py +168 -0
- rememberstack-0.1.0.dist-info/METADATA +213 -0
- rememberstack-0.1.0.dist-info/RECORD +186 -0
- rememberstack-0.1.0.dist-info/WHEEL +4 -0
- rememberstack-0.1.0.dist-info/entry_points.txt +2 -0
- rememberstack-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Provider-neutral values for the D50/D60 single-deployment auth perimeter."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from pydantic import ConfigDict
|
|
8
|
+
from pydantic import Field
|
|
9
|
+
from pydantic import SecretBytes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PerimeterCredential(BaseModel):
|
|
13
|
+
"""Opaque perimeter credential passed to the configured auth adapter."""
|
|
14
|
+
|
|
15
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
16
|
+
|
|
17
|
+
scheme: Annotated[str, Field(min_length=1)]
|
|
18
|
+
value: SecretBytes
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AuthenticatedContext(BaseModel):
|
|
22
|
+
"""Authenticated principal inside one deployment-wide trust domain."""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
25
|
+
|
|
26
|
+
deployment_id: UUID
|
|
27
|
+
principal: Annotated[str, Field(min_length=1)]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Typed block records — the deterministic identity atoms of a document (D57)."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
from pydantic import ConfigDict
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BlockType(StrEnum):
|
|
11
|
+
"""The structural kinds a blockizer emits (e1 §2)."""
|
|
12
|
+
|
|
13
|
+
PARAGRAPH = "paragraph"
|
|
14
|
+
HEADING = "heading"
|
|
15
|
+
TABLE = "table"
|
|
16
|
+
LIST_ITEM = "list_item"
|
|
17
|
+
CODE = "code"
|
|
18
|
+
QUOTE = "quote"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Block(BaseModel):
|
|
22
|
+
"""One block: a slice of document.md with its deterministic identity hash."""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
25
|
+
|
|
26
|
+
ordinal: int = Field(ge=0)
|
|
27
|
+
type: BlockType
|
|
28
|
+
char_start: int = Field(ge=0)
|
|
29
|
+
char_end: int = Field(ge=0)
|
|
30
|
+
block_hash: str
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""E1 chunk-layer values: packing inputs/outputs, catalog records, P1 rows (D58).
|
|
2
|
+
|
|
3
|
+
Chunks are non-overlapping runs of whole blocks within one section; their
|
|
4
|
+
identity is the ordered block-hash sequence, which is what makes reuse (D56)
|
|
5
|
+
a sequence comparison instead of a semantic judgment.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Annotated
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from pydantic import ConfigDict
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
|
|
15
|
+
from rememberstack.model.queue import UTCDateTime
|
|
16
|
+
|
|
17
|
+
_NonEmpty = Annotated[str, Field(min_length=1)]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SectionSpan(BaseModel):
|
|
21
|
+
"""One section's block range and signals, as the chunker consumes it."""
|
|
22
|
+
|
|
23
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
24
|
+
|
|
25
|
+
section_id: UUID
|
|
26
|
+
node_path: str
|
|
27
|
+
role: str
|
|
28
|
+
block_start: int = Field(ge=0)
|
|
29
|
+
block_end: int = Field(ge=-1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ChunkSource(BaseModel):
|
|
33
|
+
"""Everything the chunk stage loads about its claimed representation."""
|
|
34
|
+
|
|
35
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
36
|
+
|
|
37
|
+
deployment_id: UUID
|
|
38
|
+
doc_id: UUID
|
|
39
|
+
version_id: UUID
|
|
40
|
+
representation_id: UUID
|
|
41
|
+
markdown_uri: str
|
|
42
|
+
blocks_uri: str
|
|
43
|
+
title: str | None
|
|
44
|
+
source_kind: str
|
|
45
|
+
source_modified_at: UTCDateTime | None
|
|
46
|
+
published_at: UTCDateTime | None
|
|
47
|
+
language: str | None
|
|
48
|
+
structurer_version: str
|
|
49
|
+
sections: tuple[SectionSpan, ...]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class PackedChunk(BaseModel):
|
|
53
|
+
"""One packed run of whole blocks: the chunker's pure output."""
|
|
54
|
+
|
|
55
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
56
|
+
|
|
57
|
+
ordinal: int = Field(ge=0)
|
|
58
|
+
section_id: UUID
|
|
59
|
+
block_start: int = Field(ge=0)
|
|
60
|
+
block_end: int = Field(ge=0)
|
|
61
|
+
char_start: int = Field(ge=0)
|
|
62
|
+
char_end: int = Field(ge=0)
|
|
63
|
+
chunk_content_hash: _NonEmpty
|
|
64
|
+
token_count: int = Field(ge=0)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ChunkRecord(BaseModel):
|
|
68
|
+
"""One chunk row for the spine ledger (text and vectors live elsewhere, D37/D8)."""
|
|
69
|
+
|
|
70
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
71
|
+
|
|
72
|
+
chunk_id: UUID
|
|
73
|
+
deployment_id: UUID
|
|
74
|
+
doc_id: UUID
|
|
75
|
+
version_id: UUID
|
|
76
|
+
representation_id: UUID
|
|
77
|
+
section_id: UUID
|
|
78
|
+
ordinal: int = Field(ge=0)
|
|
79
|
+
block_start: int = Field(ge=0)
|
|
80
|
+
block_end: int = Field(ge=0)
|
|
81
|
+
chunk_content_hash: _NonEmpty
|
|
82
|
+
extraction_input_hash: _NonEmpty
|
|
83
|
+
char_start: int = Field(ge=0)
|
|
84
|
+
char_end: int = Field(ge=0)
|
|
85
|
+
token_count: int = Field(ge=0)
|
|
86
|
+
chunker_version: _NonEmpty
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ChunkForEmbedding(BaseModel):
|
|
90
|
+
"""One chunk row as the embed stage loads it (spans + signals, no body)."""
|
|
91
|
+
|
|
92
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
93
|
+
|
|
94
|
+
chunk_id: UUID
|
|
95
|
+
doc_id: UUID
|
|
96
|
+
version_id: UUID
|
|
97
|
+
ordinal: int = Field(ge=0)
|
|
98
|
+
char_start: int = Field(ge=0)
|
|
99
|
+
char_end: int = Field(ge=0)
|
|
100
|
+
chunk_content_hash: str
|
|
101
|
+
extraction_input_hash: str
|
|
102
|
+
section_role: str
|
|
103
|
+
section_path: str
|
|
104
|
+
context_prefix: str | None
|
|
105
|
+
prefixer_version: str | None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class CarryForwardSource(BaseModel):
|
|
109
|
+
"""A prior version's chunk whose LLM-derived context is carried forward.
|
|
110
|
+
|
|
111
|
+
D56/A3: for an unchanged chunk (same content hash within the lineage) the
|
|
112
|
+
stored prefix and embedding are REUSED, never regenerated — LLM output is
|
|
113
|
+
non-deterministic, so regenerating would both pay again and produce
|
|
114
|
+
different bytes.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
118
|
+
|
|
119
|
+
chunk_id: UUID
|
|
120
|
+
context_prefix: str
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class EmbeddingUpdate(BaseModel):
|
|
124
|
+
"""The embed stage's write-back onto one chunk row."""
|
|
125
|
+
|
|
126
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
127
|
+
|
|
128
|
+
chunk_id: UUID
|
|
129
|
+
embedding_ref: _NonEmpty
|
|
130
|
+
embedding_version: _NonEmpty
|
|
131
|
+
context_prefix: _NonEmpty
|
|
132
|
+
prefixer_version: _NonEmpty
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class ContextPrefix(BaseModel):
|
|
136
|
+
"""The structured response of the E1 context-prefix call (D58/D63)."""
|
|
137
|
+
|
|
138
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
139
|
+
|
|
140
|
+
prefix: _NonEmpty
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class P1ChunkRow(BaseModel):
|
|
144
|
+
"""One row of the P1 chunk table: text + vector + filter scalars (D8)."""
|
|
145
|
+
|
|
146
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
147
|
+
|
|
148
|
+
chunk_id: UUID
|
|
149
|
+
deployment_id: UUID
|
|
150
|
+
doc_id: UUID
|
|
151
|
+
version_id: UUID
|
|
152
|
+
section_role: str
|
|
153
|
+
text: _NonEmpty
|
|
154
|
+
vector: Annotated[tuple[float, ...], Field(min_length=1)]
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ChunkSourceNotFoundError(Exception):
|
|
158
|
+
"""The chunk stage referenced a representation the spine does not know."""
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class P1ClaimRow(BaseModel):
|
|
162
|
+
"""One row of the P1 claims channel: the needle index (D8/D58).
|
|
163
|
+
|
|
164
|
+
`is_current_testimony` is the scalar the DEFAULT claims channel filters
|
|
165
|
+
on (retrieval §5): current-testimony-only unless a recipe asks otherwise.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
169
|
+
|
|
170
|
+
claim_id: UUID
|
|
171
|
+
deployment_id: UUID
|
|
172
|
+
doc_id: UUID
|
|
173
|
+
chunk_id: UUID
|
|
174
|
+
text: Annotated[str, Field(min_length=1)]
|
|
175
|
+
is_current_testimony: bool
|
|
176
|
+
is_attributed: bool
|
|
177
|
+
vector: Annotated[tuple[float, ...], Field(min_length=1)]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class P1FactRow(BaseModel):
|
|
181
|
+
"""One row of the P1 facts channel: fact/observation labels (D8)."""
|
|
182
|
+
|
|
183
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
184
|
+
|
|
185
|
+
fact_id: UUID
|
|
186
|
+
deployment_id: UUID
|
|
187
|
+
kind: Annotated[str, Field(min_length=1)] # relation | observation
|
|
188
|
+
label: Annotated[str, Field(min_length=1)]
|
|
189
|
+
status: Annotated[str, Field(min_length=1)] # active | invalidated
|
|
190
|
+
vector: Annotated[tuple[float, ...], Field(min_length=1)]
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""E2 claim-extraction values: call responses, grounding, and ledger records (D31-D35)."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from pydantic import ConfigDict
|
|
9
|
+
from pydantic import Field
|
|
10
|
+
|
|
11
|
+
_NonEmpty = Annotated[str, Field(min_length=1)]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SelectionVerdict(StrEnum):
|
|
15
|
+
"""Selection's per-candidate outcome (D31/D35)."""
|
|
16
|
+
|
|
17
|
+
KEEP = "keep"
|
|
18
|
+
KEEP_FLAGGED = "keep_flagged"
|
|
19
|
+
DROP = "drop"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SelectionCandidate(BaseModel):
|
|
23
|
+
"""One proposition Selection judged inside the target chunk."""
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
26
|
+
|
|
27
|
+
source_span: _NonEmpty
|
|
28
|
+
verdict: SelectionVerdict
|
|
29
|
+
drop_reason: str | None = None
|
|
30
|
+
protected_class: str | None = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SelectionResponse(BaseModel):
|
|
34
|
+
"""The Selection call's structured output: every judged candidate."""
|
|
35
|
+
|
|
36
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
37
|
+
|
|
38
|
+
candidates: tuple[SelectionCandidate, ...]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class AddedContext(BaseModel):
|
|
42
|
+
"""One substring decontextualization added, tagged with its bundle source (D32)."""
|
|
43
|
+
|
|
44
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
45
|
+
|
|
46
|
+
text: _NonEmpty
|
|
47
|
+
source_kind: _NonEmpty # header | neighbour | prefix | hint
|
|
48
|
+
source_ref: str | None = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CandidateClaim(BaseModel):
|
|
52
|
+
"""One decontextualized, decomposed claim before the deterministic gate."""
|
|
53
|
+
|
|
54
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
55
|
+
|
|
56
|
+
claim_text: _NonEmpty
|
|
57
|
+
source_span: _NonEmpty
|
|
58
|
+
added_context: tuple[AddedContext, ...] = ()
|
|
59
|
+
entailment_self_verdict: bool
|
|
60
|
+
is_attributed: bool = False
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ClaimifyResponse(BaseModel):
|
|
64
|
+
"""The fused call's structured output: decontextualize + decompose + ground."""
|
|
65
|
+
|
|
66
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
67
|
+
|
|
68
|
+
claims: tuple[CandidateClaim, ...]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ClaimRecord(BaseModel):
|
|
72
|
+
"""One accepted claim row: past the deterministic grounding gate (D32)."""
|
|
73
|
+
|
|
74
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
75
|
+
|
|
76
|
+
claim_id: UUID
|
|
77
|
+
deployment_id: UUID
|
|
78
|
+
doc_id: UUID
|
|
79
|
+
chunk_id: UUID
|
|
80
|
+
section_id: UUID | None
|
|
81
|
+
claim_text: _NonEmpty
|
|
82
|
+
source_span: _NonEmpty
|
|
83
|
+
char_start: int = Field(ge=0)
|
|
84
|
+
char_end: int = Field(ge=0)
|
|
85
|
+
added_context: tuple[AddedContext, ...]
|
|
86
|
+
is_attributed: bool
|
|
87
|
+
entailment_self_verdict: bool
|
|
88
|
+
kept_flagged: bool
|
|
89
|
+
extractor_version: _NonEmpty
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class DecisionType(StrEnum):
|
|
93
|
+
"""The D33 ledger's decision kinds."""
|
|
94
|
+
|
|
95
|
+
SELECTION_DROP = "selection_drop"
|
|
96
|
+
SELECTION_KEEP_FLAGGED = "selection_keep_flagged"
|
|
97
|
+
DECONTEXT_EDIT = "decontext_edit"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class DecisionRecord(BaseModel):
|
|
101
|
+
"""One append-only extraction-transcript row (D33)."""
|
|
102
|
+
|
|
103
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
104
|
+
|
|
105
|
+
decision_id: UUID
|
|
106
|
+
deployment_id: UUID
|
|
107
|
+
doc_id: UUID
|
|
108
|
+
chunk_id: UUID
|
|
109
|
+
claim_id: UUID | None
|
|
110
|
+
decision_type: DecisionType
|
|
111
|
+
source_span: str | None
|
|
112
|
+
reason: str | None
|
|
113
|
+
edit_detail: dict[str, object] | None
|
|
114
|
+
protected_class: str | None
|
|
115
|
+
extractor_version: _NonEmpty
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class ClaimForEmbedding(BaseModel):
|
|
119
|
+
"""One claim row as the claim-embed stage loads it."""
|
|
120
|
+
|
|
121
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
122
|
+
|
|
123
|
+
claim_id: UUID
|
|
124
|
+
doc_id: UUID
|
|
125
|
+
chunk_id: UUID
|
|
126
|
+
claim_text: _NonEmpty
|
|
127
|
+
is_current_testimony: bool
|
|
128
|
+
is_attributed: bool
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class FactForLabeling(BaseModel):
|
|
132
|
+
"""One relation as the label stage loads it (names resolved for the label)."""
|
|
133
|
+
|
|
134
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
135
|
+
|
|
136
|
+
relation_id: UUID
|
|
137
|
+
subject_name: _NonEmpty
|
|
138
|
+
predicate: _NonEmpty
|
|
139
|
+
object_name: _NonEmpty
|
|
140
|
+
status: _NonEmpty
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class ObservationForEmbedding(BaseModel):
|
|
144
|
+
"""One observation as the label stage loads it (obs_label is the text)."""
|
|
145
|
+
|
|
146
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
147
|
+
|
|
148
|
+
observation_id: UUID
|
|
149
|
+
obs_label: _NonEmpty
|
|
150
|
+
status: _NonEmpty
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class FactLabelResponse(BaseModel):
|
|
154
|
+
"""The fact-labeler call's structured output: one readable sentence."""
|
|
155
|
+
|
|
156
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
157
|
+
|
|
158
|
+
label: _NonEmpty
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class OtherPredicateGrammarError(Exception):
|
|
162
|
+
"""An other:<freetext> escape value violating the D5 grammar."""
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Client-surface values that are safe in the dependency-light base install."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
from typing import Self
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from pydantic import ConfigDict
|
|
9
|
+
from pydantic import Field
|
|
10
|
+
from pydantic import JsonValue
|
|
11
|
+
from pydantic import model_validator
|
|
12
|
+
|
|
13
|
+
_SECRET_CONFIGURATION_KEYS = frozenset(
|
|
14
|
+
{
|
|
15
|
+
"accesstoken",
|
|
16
|
+
"apikey",
|
|
17
|
+
"credential",
|
|
18
|
+
"credentials",
|
|
19
|
+
"password",
|
|
20
|
+
"refreshtoken",
|
|
21
|
+
"secret",
|
|
22
|
+
"token",
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ConnectorNotFoundError(Exception):
|
|
28
|
+
"""A connector id is not present in this deployment."""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ToolDescriptor(BaseModel):
|
|
32
|
+
"""One deployment recipe rendered as a typed SDK/MCP tool."""
|
|
33
|
+
|
|
34
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
35
|
+
|
|
36
|
+
name: str
|
|
37
|
+
description: str
|
|
38
|
+
input_schema: dict[str, object]
|
|
39
|
+
output_grain: str
|
|
40
|
+
answer_intent: str
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ConnectorCreate(BaseModel):
|
|
44
|
+
"""Deployment-side connector configuration sent by a client.
|
|
45
|
+
|
|
46
|
+
``credential_ref`` names a secret already held by the deployment. Raw
|
|
47
|
+
credentials never become client-surface configuration.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
51
|
+
|
|
52
|
+
kind: str = Field(min_length=1)
|
|
53
|
+
name: str = Field(min_length=1)
|
|
54
|
+
configuration: dict[str, JsonValue] = Field(default_factory=dict)
|
|
55
|
+
credential_ref: str | None = None
|
|
56
|
+
|
|
57
|
+
@model_validator(mode="after")
|
|
58
|
+
def _credentials_are_references(self) -> Self:
|
|
59
|
+
"""Reject conventional secret fields at any configuration depth."""
|
|
60
|
+
secret_key = _find_secret_key(self.configuration)
|
|
61
|
+
if secret_key is not None:
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"configuration field {secret_key!r} looks like a credential;"
|
|
64
|
+
" store it deployment-side and use credential_ref"
|
|
65
|
+
)
|
|
66
|
+
return self
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ConnectorDescriptor(BaseModel):
|
|
70
|
+
"""One managed connector, never an instruction to execute it client-side."""
|
|
71
|
+
|
|
72
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
73
|
+
|
|
74
|
+
connector_id: UUID
|
|
75
|
+
kind: str
|
|
76
|
+
name: str
|
|
77
|
+
status: Literal["active", "paused", "error"]
|
|
78
|
+
configuration: dict[str, JsonValue] = Field(default_factory=dict)
|
|
79
|
+
credential_ref: str | None = None
|
|
80
|
+
message: str | None = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _find_secret_key(value: object) -> str | None:
|
|
84
|
+
"""Return the first conventional credential key in nested JSON-like data."""
|
|
85
|
+
if isinstance(value, dict):
|
|
86
|
+
for key, nested in value.items():
|
|
87
|
+
normalized = key.casefold().replace("-", "").replace("_", "")
|
|
88
|
+
if normalized in _SECRET_CONFIGURATION_KEYS:
|
|
89
|
+
return key
|
|
90
|
+
found = _find_secret_key(nested)
|
|
91
|
+
if found is not None:
|
|
92
|
+
return found
|
|
93
|
+
elif isinstance(value, (list, tuple)):
|
|
94
|
+
for nested in value:
|
|
95
|
+
found = _find_secret_key(nested)
|
|
96
|
+
if found is not None:
|
|
97
|
+
return found
|
|
98
|
+
return None
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Clustering values (D21): config, merge outcomes, and neighborhood reports.
|
|
2
|
+
|
|
3
|
+
The asymmetry every number serves: over-merging is catastrophic and silent;
|
|
4
|
+
under-merging is gradual and recoverable — so the machinery is paranoid in
|
|
5
|
+
one direction, and every merge is reversible.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Annotated
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from pydantic import ConfigDict
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ClusterConfig(BaseModel):
|
|
17
|
+
"""The decide-stage parameters (starting points to measure, D22).
|
|
18
|
+
|
|
19
|
+
`distance_cut` is the HAC cut on cosine DISTANCE (1 - similarity):
|
|
20
|
+
pieces below the cut are one entity. `blob_cap` is the black-hole
|
|
21
|
+
guard; `blast_radius_cap` routes big merges to human review (D24).
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
25
|
+
|
|
26
|
+
distance_cut: Annotated[float, Field(ge=0.0, le=2.0)] = 0.15
|
|
27
|
+
blob_cap: Annotated[int, Field(ge=2)] = 50
|
|
28
|
+
blast_radius_cap: Annotated[int, Field(ge=1)] = 100
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class MergeProposal(BaseModel):
|
|
32
|
+
"""One decide-stage grouping: entities the cut placed in one piece."""
|
|
33
|
+
|
|
34
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
35
|
+
|
|
36
|
+
survivor_id: UUID
|
|
37
|
+
absorbed_ids: tuple[UUID, ...]
|
|
38
|
+
blast_radius: int = Field(ge=0)
|
|
39
|
+
mean_distance: float
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class NeighborhoodReport(BaseModel):
|
|
43
|
+
"""What one neighborhood re-decision did (nDR, registries §6)."""
|
|
44
|
+
|
|
45
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
46
|
+
|
|
47
|
+
members: int
|
|
48
|
+
merged: tuple[UUID, ...] = () # merge_event ids written
|
|
49
|
+
queued_for_review: int = 0
|
|
50
|
+
black_hole_tightened: bool = False
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class UnmergeError(Exception):
|
|
54
|
+
"""The merge event cannot be reversed (already reversed, or unknown)."""
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Typed values and errors for immutable pipeline component versions."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
import re
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
from typing import Any
|
|
9
|
+
from typing import Self
|
|
10
|
+
from typing import TypeAlias
|
|
11
|
+
from uuid import UUID
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel
|
|
14
|
+
from pydantic import ConfigDict
|
|
15
|
+
from pydantic import Field
|
|
16
|
+
from pydantic import field_validator
|
|
17
|
+
from pydantic import model_validator
|
|
18
|
+
from pydantic import StringConstraints
|
|
19
|
+
|
|
20
|
+
NonEmptyStrictString: TypeAlias = Annotated[
|
|
21
|
+
str, StringConstraints(strict=True, min_length=1)
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PipelineComponent(StrEnum):
|
|
26
|
+
"""Exact values of the binding Postgres ``pipeline_component`` enum."""
|
|
27
|
+
|
|
28
|
+
INGESTER = "ingester"
|
|
29
|
+
CONVERTER = "converter"
|
|
30
|
+
BLOCKIZER = "blockizer"
|
|
31
|
+
STRUCTURER = "structurer"
|
|
32
|
+
CROSSREFERENCER = "crossreferencer"
|
|
33
|
+
CHUNKER = "chunker"
|
|
34
|
+
CONTEXT_PREFIXER = "context_prefixer"
|
|
35
|
+
EXTRACTOR = "extractor"
|
|
36
|
+
GROUNDER = "grounder"
|
|
37
|
+
RESOLVER = "resolver"
|
|
38
|
+
NORMALIZER = "normalizer"
|
|
39
|
+
ADJUDICATOR = "adjudicator"
|
|
40
|
+
EMBEDDER = "embedder"
|
|
41
|
+
FACT_LABELER = "fact_labeler"
|
|
42
|
+
PROFILE_SUMMARIZER = "profile_summarizer"
|
|
43
|
+
COMMUNITY_DETECTOR = "community_detector"
|
|
44
|
+
SNAPSHOT_BUILDER = "snapshot_builder"
|
|
45
|
+
KNOWLEDGE_PLANNER = "knowledge_planner"
|
|
46
|
+
KNOWLEDGE_WRITER = "knowledge_writer"
|
|
47
|
+
KNOWLEDGE_REFLECTOR = "knowledge_reflector"
|
|
48
|
+
KNOWLEDGE_LINTER = "knowledge_linter"
|
|
49
|
+
JUDGE = "judge"
|
|
50
|
+
FORGETTER = "forgetter"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class RegisterComponentVersionInput(BaseModel):
|
|
54
|
+
"""One explicit immutable pipeline component definition to register."""
|
|
55
|
+
|
|
56
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
57
|
+
|
|
58
|
+
deployment_id: UUID
|
|
59
|
+
component: PipelineComponent
|
|
60
|
+
version: NonEmptyStrictString
|
|
61
|
+
model_name: str | None = None
|
|
62
|
+
prompt_hash: str | None = None
|
|
63
|
+
embedding_dim: int | None = None
|
|
64
|
+
params: Mapping[str, Any] = Field(default_factory=dict)
|
|
65
|
+
notes: str | None = None
|
|
66
|
+
|
|
67
|
+
@field_validator("prompt_hash")
|
|
68
|
+
@classmethod
|
|
69
|
+
def require_lowercase_sha256(cls, value: str | None) -> str | None:
|
|
70
|
+
"""Require an exact lowercase hexadecimal SHA-256 when one is supplied."""
|
|
71
|
+
if value is not None and re.fullmatch(r"[0-9a-f]{64}", value) is None:
|
|
72
|
+
raise ValueError(
|
|
73
|
+
"prompt_hash must be exactly 64 lowercase hexadecimal characters"
|
|
74
|
+
)
|
|
75
|
+
return value
|
|
76
|
+
|
|
77
|
+
@model_validator(mode="after")
|
|
78
|
+
def require_embedder_for_embedding_dimension(self) -> Self:
|
|
79
|
+
"""Allow an embedding dimension only on the embedder component."""
|
|
80
|
+
if (
|
|
81
|
+
self.embedding_dim is not None
|
|
82
|
+
and self.component is not PipelineComponent.EMBEDDER
|
|
83
|
+
):
|
|
84
|
+
raise ValueError("embedding_dim is allowed only for the embedder component")
|
|
85
|
+
return self
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class RegisterComponentVersionResult(BaseModel):
|
|
89
|
+
"""Identity and creation disposition for one registration attempt."""
|
|
90
|
+
|
|
91
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
92
|
+
|
|
93
|
+
deployment_id: UUID
|
|
94
|
+
component: PipelineComponent
|
|
95
|
+
version: str
|
|
96
|
+
created: bool
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class ComponentVersionRecord(BaseModel):
|
|
100
|
+
"""A resolved immutable component definition including its database timestamp."""
|
|
101
|
+
|
|
102
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
103
|
+
|
|
104
|
+
deployment_id: UUID
|
|
105
|
+
component: PipelineComponent
|
|
106
|
+
version: str
|
|
107
|
+
model_name: str | None
|
|
108
|
+
prompt_hash: str | None
|
|
109
|
+
embedding_dim: int | None
|
|
110
|
+
params: Mapping[str, Any]
|
|
111
|
+
notes: str | None
|
|
112
|
+
configured_at: datetime
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class ComponentVersionError(RuntimeError):
|
|
116
|
+
"""Base class for a known component-version catalog failure."""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class ComponentVersionConflictError(ComponentVersionError):
|
|
120
|
+
"""An existing key has a different immutable component definition."""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ComponentVersionNotFoundError(ComponentVersionError):
|
|
124
|
+
"""No component version exists for the requested primary-key triple."""
|