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,840 @@
|
|
|
1
|
+
"""Typed Plane-K control-plane values (D45)."""
|
|
2
|
+
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
from pathlib import PurePosixPath
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
from typing import Literal
|
|
7
|
+
from typing import TypeAlias
|
|
8
|
+
from uuid import UUID
|
|
9
|
+
|
|
10
|
+
from pydantic import AfterValidator
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
from pydantic import ConfigDict
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
from pydantic import field_validator
|
|
15
|
+
from pydantic import JsonValue
|
|
16
|
+
from pydantic import model_validator
|
|
17
|
+
|
|
18
|
+
from rememberstack.model.mounts import PublishedMounts
|
|
19
|
+
from rememberstack.model.queue import UTCDateTime
|
|
20
|
+
|
|
21
|
+
SHA256: TypeAlias = Annotated[str, Field(pattern=r"^[0-9a-f]{64}$")]
|
|
22
|
+
KNOWLEDGE_WRITER_OUTPUT_PATHS = (
|
|
23
|
+
"output/prose.md",
|
|
24
|
+
"output/citations.json",
|
|
25
|
+
"output/summary.md",
|
|
26
|
+
"output/suggestions.json",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _sorted_unique_strings(values: tuple[str, ...]) -> tuple[str, ...]:
|
|
31
|
+
"""Canonicalize a set-valued string parameter."""
|
|
32
|
+
return tuple(sorted(set(values)))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _sorted_unique_uuids(values: tuple[UUID, ...]) -> tuple[UUID, ...]:
|
|
36
|
+
"""Canonicalize a set-valued UUID parameter."""
|
|
37
|
+
return tuple(sorted(set(values), key=str))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _sorted_unique_candidate_layers(
|
|
41
|
+
values: tuple["KnowledgeCandidateLayer", ...],
|
|
42
|
+
) -> tuple["KnowledgeCandidateLayer", ...]:
|
|
43
|
+
"""Canonicalize a set-valued candidate-layer parameter."""
|
|
44
|
+
return tuple(sorted(set(values), key=lambda value: value.value))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
CanonicalStrings: TypeAlias = Annotated[
|
|
48
|
+
tuple[str, ...], AfterValidator(_sorted_unique_strings)
|
|
49
|
+
]
|
|
50
|
+
CanonicalUUIDs: TypeAlias = Annotated[
|
|
51
|
+
tuple[UUID, ...], AfterValidator(_sorted_unique_uuids)
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class KnowledgeRuleKind(StrEnum):
|
|
56
|
+
"""The closed, mechanically evaluated D45 routing-rule vocabulary."""
|
|
57
|
+
|
|
58
|
+
ENTITY = "entity"
|
|
59
|
+
ENTITY_SUBTREE = "entity_subtree"
|
|
60
|
+
PREDICATE_BEAT = "predicate_beat"
|
|
61
|
+
COMMUNITY = "community"
|
|
62
|
+
DOC_SET = "doc_set"
|
|
63
|
+
SCOPE_INTERESTS = "scope_interests"
|
|
64
|
+
MANUAL = "manual"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class KnowledgeRuleKeyKind(StrEnum):
|
|
68
|
+
"""The four coarse keys supported by the routing inverted index."""
|
|
69
|
+
|
|
70
|
+
ENTITY = "entity"
|
|
71
|
+
PREDICATE = "predicate"
|
|
72
|
+
COMMUNITY = "community"
|
|
73
|
+
DOC_SOURCE = "doc_source"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class KnowledgeCandidateLayer(StrEnum):
|
|
77
|
+
"""Candidate grains a rule may select for a compiled page."""
|
|
78
|
+
|
|
79
|
+
RELATIONS = "relations"
|
|
80
|
+
OBSERVATIONS = "observations"
|
|
81
|
+
CLAIMS = "claims"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
CanonicalCandidateLayers: TypeAlias = Annotated[
|
|
85
|
+
tuple[KnowledgeCandidateLayer, ...], AfterValidator(_sorted_unique_candidate_layers)
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class KnowledgeLayer(StrEnum):
|
|
90
|
+
"""The three content tiers sharing one compile mechanism (D47)."""
|
|
91
|
+
|
|
92
|
+
K1 = "K1"
|
|
93
|
+
K2 = "K2"
|
|
94
|
+
K3 = "K3"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class KnowledgePageKind(StrEnum):
|
|
98
|
+
"""The D46 page ownership contract."""
|
|
99
|
+
|
|
100
|
+
COMPILED = "compiled"
|
|
101
|
+
AUTHORED = "authored"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class KnowledgeArtifactStatus(StrEnum):
|
|
105
|
+
"""Lifecycle states of one Plane-K artifact handle."""
|
|
106
|
+
|
|
107
|
+
ACTIVE = "active"
|
|
108
|
+
STALE = "stale"
|
|
109
|
+
QUARANTINED = "quarantined"
|
|
110
|
+
TOMBSTONED = "tombstoned"
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class KnowledgePlanAction(StrEnum):
|
|
114
|
+
"""Append-only planner structure actions supported by the schema."""
|
|
115
|
+
|
|
116
|
+
CREATE_PAGE = "create_page"
|
|
117
|
+
SPLIT_PAGE = "split_page"
|
|
118
|
+
MERGE_PAGES = "merge_pages"
|
|
119
|
+
MOVE_PAGE = "move_page"
|
|
120
|
+
RETIRE_PAGE = "retire_page"
|
|
121
|
+
ADJUST_RULE = "adjust_rule"
|
|
122
|
+
CONVERT_KIND = "convert_kind"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class KnowledgePlanTrigger(StrEnum):
|
|
126
|
+
"""Reasons a planner may make a durable structure decision."""
|
|
127
|
+
|
|
128
|
+
ORPHAN_EVIDENCE = "orphan_evidence"
|
|
129
|
+
SIZE_OVERFLOW = "size_overflow"
|
|
130
|
+
COMMUNITY_CHANGE = "community_change"
|
|
131
|
+
REFLECTION = "reflection"
|
|
132
|
+
WRITER_SUGGESTION = "writer_suggestion"
|
|
133
|
+
HUMAN = "human"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class KnowledgePlanStatus(StrEnum):
|
|
137
|
+
"""Review state for a structure decision."""
|
|
138
|
+
|
|
139
|
+
PROPOSED = "proposed"
|
|
140
|
+
APPLIED = "applied"
|
|
141
|
+
REJECTED = "rejected"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class KnowledgeEvidenceRole(StrEnum):
|
|
145
|
+
"""How a K citation uses one evidence target."""
|
|
146
|
+
|
|
147
|
+
SUPPORTS = "supports"
|
|
148
|
+
CONTRADICTS = "contradicts"
|
|
149
|
+
CITES = "cites"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class EntityRuleParams(BaseModel):
|
|
153
|
+
"""Everything about one entity, optionally narrowed by fact layer/predicate."""
|
|
154
|
+
|
|
155
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
156
|
+
|
|
157
|
+
kind: Literal[KnowledgeRuleKind.ENTITY] = KnowledgeRuleKind.ENTITY
|
|
158
|
+
entity_id: UUID
|
|
159
|
+
predicates: CanonicalStrings = ()
|
|
160
|
+
layers: CanonicalCandidateLayers = (
|
|
161
|
+
KnowledgeCandidateLayer.RELATIONS,
|
|
162
|
+
KnowledgeCandidateLayer.OBSERVATIONS,
|
|
163
|
+
KnowledgeCandidateLayer.CLAIMS,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class EntitySubtreeRuleParams(BaseModel):
|
|
168
|
+
"""One entity plus the transitive subjects that are ``part_of`` it."""
|
|
169
|
+
|
|
170
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
171
|
+
|
|
172
|
+
kind: Literal[KnowledgeRuleKind.ENTITY_SUBTREE] = KnowledgeRuleKind.ENTITY_SUBTREE
|
|
173
|
+
root_entity_id: UUID
|
|
174
|
+
predicates: CanonicalStrings = ()
|
|
175
|
+
layers: CanonicalCandidateLayers = (
|
|
176
|
+
KnowledgeCandidateLayer.RELATIONS,
|
|
177
|
+
KnowledgeCandidateLayer.OBSERVATIONS,
|
|
178
|
+
KnowledgeCandidateLayer.CLAIMS,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class PredicateBeatRuleParams(BaseModel):
|
|
183
|
+
"""Relations of one governed predicate, optionally pinned to either endpoint."""
|
|
184
|
+
|
|
185
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
186
|
+
|
|
187
|
+
kind: Literal[KnowledgeRuleKind.PREDICATE_BEAT] = KnowledgeRuleKind.PREDICATE_BEAT
|
|
188
|
+
predicate: str
|
|
189
|
+
subject_entity_id: UUID | None = None
|
|
190
|
+
object_entity_id: UUID | None = None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class CommunityRuleParams(BaseModel):
|
|
194
|
+
"""Evidence about members of one detected entity community."""
|
|
195
|
+
|
|
196
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
197
|
+
|
|
198
|
+
kind: Literal[KnowledgeRuleKind.COMMUNITY] = KnowledgeRuleKind.COMMUNITY
|
|
199
|
+
community_id: UUID
|
|
200
|
+
layers: CanonicalCandidateLayers = (
|
|
201
|
+
KnowledgeCandidateLayer.RELATIONS,
|
|
202
|
+
KnowledgeCandidateLayer.OBSERVATIONS,
|
|
203
|
+
KnowledgeCandidateLayer.CLAIMS,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class DocSetRuleParams(BaseModel):
|
|
208
|
+
"""Evidence from one source family, with optional snapshot metadata filters.
|
|
209
|
+
|
|
210
|
+
``source_kind`` is required because it is the only document key represented
|
|
211
|
+
by ``knowledge_rule_keys``. MIME, origin, and time are exact secondary SQL
|
|
212
|
+
filters after that coarse key hit.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
216
|
+
|
|
217
|
+
kind: Literal[KnowledgeRuleKind.DOC_SET] = KnowledgeRuleKind.DOC_SET
|
|
218
|
+
source_kind: str
|
|
219
|
+
mime: str | None = None
|
|
220
|
+
origin: Literal["external", "system_generated"] | None = None
|
|
221
|
+
source_modified_from: UTCDateTime | None = None
|
|
222
|
+
source_modified_until: UTCDateTime | None = None
|
|
223
|
+
|
|
224
|
+
@model_validator(mode="after")
|
|
225
|
+
def require_ordered_time_range(self) -> "DocSetRuleParams":
|
|
226
|
+
"""Reject a document window whose upper bound precedes its lower bound."""
|
|
227
|
+
if (
|
|
228
|
+
self.source_modified_from is not None
|
|
229
|
+
and self.source_modified_until is not None
|
|
230
|
+
and self.source_modified_until < self.source_modified_from
|
|
231
|
+
):
|
|
232
|
+
raise ValueError(
|
|
233
|
+
"source_modified_until must not precede source_modified_from"
|
|
234
|
+
)
|
|
235
|
+
return self
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class ScopeInterestsRuleParams(BaseModel):
|
|
239
|
+
"""Delegate selection to the existing registry interests of one scope."""
|
|
240
|
+
|
|
241
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
242
|
+
|
|
243
|
+
kind: Literal[KnowledgeRuleKind.SCOPE_INTERESTS] = KnowledgeRuleKind.SCOPE_INTERESTS
|
|
244
|
+
scope_id: UUID
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ManualRuleParams(BaseModel):
|
|
248
|
+
"""An explicit editorial assignment of entities or evidence IDs."""
|
|
249
|
+
|
|
250
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
251
|
+
|
|
252
|
+
kind: Literal[KnowledgeRuleKind.MANUAL] = KnowledgeRuleKind.MANUAL
|
|
253
|
+
entity_ids: CanonicalUUIDs = ()
|
|
254
|
+
relation_ids: CanonicalUUIDs = ()
|
|
255
|
+
observation_ids: CanonicalUUIDs = ()
|
|
256
|
+
claim_ids: CanonicalUUIDs = ()
|
|
257
|
+
doc_ids: CanonicalUUIDs = ()
|
|
258
|
+
|
|
259
|
+
@model_validator(mode="after")
|
|
260
|
+
def require_a_target(self) -> "ManualRuleParams":
|
|
261
|
+
"""Reject a manual rule that can never select anything."""
|
|
262
|
+
if not any(
|
|
263
|
+
(
|
|
264
|
+
self.entity_ids,
|
|
265
|
+
self.relation_ids,
|
|
266
|
+
self.observation_ids,
|
|
267
|
+
self.claim_ids,
|
|
268
|
+
self.doc_ids,
|
|
269
|
+
)
|
|
270
|
+
):
|
|
271
|
+
raise ValueError("manual rule requires at least one target")
|
|
272
|
+
return self
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
KnowledgeRuleParams = Annotated[
|
|
276
|
+
EntityRuleParams
|
|
277
|
+
| EntitySubtreeRuleParams
|
|
278
|
+
| PredicateBeatRuleParams
|
|
279
|
+
| CommunityRuleParams
|
|
280
|
+
| DocSetRuleParams
|
|
281
|
+
| ScopeInterestsRuleParams
|
|
282
|
+
| ManualRuleParams,
|
|
283
|
+
Field(discriminator="kind"),
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class KnowledgePlanDecisionCreate(BaseModel):
|
|
288
|
+
"""One planner structure decision to append to the durable transcript."""
|
|
289
|
+
|
|
290
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
291
|
+
|
|
292
|
+
decision_id: UUID
|
|
293
|
+
deployment_id: UUID
|
|
294
|
+
scope_id: UUID | None = None
|
|
295
|
+
action: KnowledgePlanAction
|
|
296
|
+
payload: dict[str, JsonValue]
|
|
297
|
+
trigger: KnowledgePlanTrigger
|
|
298
|
+
planner_version: str
|
|
299
|
+
status: KnowledgePlanStatus = KnowledgePlanStatus.PROPOSED
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
class KnowledgeArtifactCreate(BaseModel):
|
|
303
|
+
"""The Postgres handle for one Plane-K git path."""
|
|
304
|
+
|
|
305
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
306
|
+
|
|
307
|
+
artifact_id: UUID
|
|
308
|
+
deployment_id: UUID
|
|
309
|
+
layer: KnowledgeLayer
|
|
310
|
+
page_kind: KnowledgePageKind
|
|
311
|
+
git_path: str
|
|
312
|
+
scope_id: UUID | None = None
|
|
313
|
+
parent_artifact_id: UUID | None = None
|
|
314
|
+
curation_path: str | None = None
|
|
315
|
+
artifact_kind: str | None = None
|
|
316
|
+
writer_version: str | None = None
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
class KnowledgePageRuleCreate(BaseModel):
|
|
320
|
+
"""One page-owned routing rule and the plan decision that authorized it."""
|
|
321
|
+
|
|
322
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
323
|
+
|
|
324
|
+
rule_id: UUID
|
|
325
|
+
deployment_id: UUID
|
|
326
|
+
artifact_id: UUID
|
|
327
|
+
plan_decision_id: UUID
|
|
328
|
+
params: KnowledgeRuleParams
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
class KnowledgeRuleKey(BaseModel):
|
|
332
|
+
"""One materialized coarse key for routing changed evidence."""
|
|
333
|
+
|
|
334
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
335
|
+
|
|
336
|
+
kind: KnowledgeRuleKeyKind
|
|
337
|
+
value: str
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class KnowledgeCitation(BaseModel):
|
|
341
|
+
"""One citation with exactly one schema-supported evidence target."""
|
|
342
|
+
|
|
343
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
344
|
+
|
|
345
|
+
role: KnowledgeEvidenceRole
|
|
346
|
+
claim_lineage_id: UUID | None = None
|
|
347
|
+
claim_chunk_content_hash: str | None = None
|
|
348
|
+
relation_id: UUID | None = None
|
|
349
|
+
doc_id: UUID | None = None
|
|
350
|
+
|
|
351
|
+
@model_validator(mode="after")
|
|
352
|
+
def require_exactly_one_target(self) -> "KnowledgeCitation":
|
|
353
|
+
"""Mirror the ``knowledge_artifact_evidence`` exactly-one CHECK."""
|
|
354
|
+
claim_coordinate_present = self.claim_lineage_id is not None
|
|
355
|
+
if claim_coordinate_present != (self.claim_chunk_content_hash is not None):
|
|
356
|
+
raise ValueError("claim citation requires its complete stable coordinate")
|
|
357
|
+
if (
|
|
358
|
+
sum(
|
|
359
|
+
target
|
|
360
|
+
for target in (
|
|
361
|
+
claim_coordinate_present,
|
|
362
|
+
self.relation_id is not None,
|
|
363
|
+
self.doc_id is not None,
|
|
364
|
+
)
|
|
365
|
+
)
|
|
366
|
+
!= 1
|
|
367
|
+
):
|
|
368
|
+
raise ValueError("citation requires exactly one evidence target")
|
|
369
|
+
return self
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
class KnowledgeEvidenceTarget(BaseModel):
|
|
373
|
+
"""One role-independent claim, relation, or document exclusion target."""
|
|
374
|
+
|
|
375
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
376
|
+
|
|
377
|
+
claim_lineage_id: UUID | None = None
|
|
378
|
+
claim_chunk_content_hash: str | None = None
|
|
379
|
+
relation_id: UUID | None = None
|
|
380
|
+
doc_id: UUID | None = None
|
|
381
|
+
|
|
382
|
+
@model_validator(mode="after")
|
|
383
|
+
def require_exactly_one_target(self) -> "KnowledgeEvidenceTarget":
|
|
384
|
+
"""Keep exclusions at the same exactly-one evidence grain as citations."""
|
|
385
|
+
claim_coordinate_present = self.claim_lineage_id is not None
|
|
386
|
+
if claim_coordinate_present != (self.claim_chunk_content_hash is not None):
|
|
387
|
+
raise ValueError("claim exclusion requires its complete stable coordinate")
|
|
388
|
+
if (
|
|
389
|
+
sum(
|
|
390
|
+
target
|
|
391
|
+
for target in (
|
|
392
|
+
claim_coordinate_present,
|
|
393
|
+
self.relation_id is not None,
|
|
394
|
+
self.doc_id is not None,
|
|
395
|
+
)
|
|
396
|
+
)
|
|
397
|
+
!= 1
|
|
398
|
+
):
|
|
399
|
+
raise ValueError("evidence target requires exactly one target")
|
|
400
|
+
return self
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
class KnowledgeCompilationWrite(BaseModel):
|
|
404
|
+
"""Validated compile metadata to commit atomically to the control plane."""
|
|
405
|
+
|
|
406
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
407
|
+
|
|
408
|
+
compilation_id: UUID
|
|
409
|
+
deployment_id: UUID
|
|
410
|
+
artifact_id: UUID
|
|
411
|
+
inputs_hash: SHA256
|
|
412
|
+
candidate_count: int = Field(ge=0)
|
|
413
|
+
uncited_count: int = Field(ge=0)
|
|
414
|
+
claims_cut_count: int = Field(default=0, ge=0)
|
|
415
|
+
citations: tuple[KnowledgeCitation, ...]
|
|
416
|
+
suggestions: tuple["KnowledgeWriterSuggestion", ...] = ()
|
|
417
|
+
evidence_invalidated: int = Field(default=0, ge=0)
|
|
418
|
+
writer_version: str
|
|
419
|
+
page_summary: str
|
|
420
|
+
content_hash: SHA256
|
|
421
|
+
tokens: int | None = Field(default=None, ge=0)
|
|
422
|
+
cost_usd: float | None = Field(default=None, ge=0)
|
|
423
|
+
session_transcript_uri: str | None = None
|
|
424
|
+
|
|
425
|
+
@model_validator(mode="after")
|
|
426
|
+
def require_bounded_uncited_count(self) -> "KnowledgeCompilationWrite":
|
|
427
|
+
"""Keep the offered-but-unused count within the candidate manifest."""
|
|
428
|
+
if self.uncited_count > self.candidate_count:
|
|
429
|
+
raise ValueError("uncited_count cannot exceed candidate_count")
|
|
430
|
+
return self
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class KnowledgeCompilationFailure(BaseModel):
|
|
434
|
+
"""One visible terminal writer attempt that never became publishable output."""
|
|
435
|
+
|
|
436
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
437
|
+
|
|
438
|
+
compilation_id: UUID
|
|
439
|
+
deployment_id: UUID
|
|
440
|
+
artifact_id: UUID
|
|
441
|
+
inputs_hash: SHA256
|
|
442
|
+
candidate_count: int = Field(ge=0)
|
|
443
|
+
claims_cut_count: int = Field(default=0, ge=0)
|
|
444
|
+
writer_version: str = Field(min_length=1)
|
|
445
|
+
failure: str = Field(min_length=1)
|
|
446
|
+
session_transcript_uri: str | None = None
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
class KnowledgeFactFingerprint(BaseModel):
|
|
450
|
+
"""The D45 state of one relation or observation candidate."""
|
|
451
|
+
|
|
452
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
453
|
+
|
|
454
|
+
kind: Literal["relation", "observation"]
|
|
455
|
+
fact_id: UUID
|
|
456
|
+
valid_from: UTCDateTime | None = None
|
|
457
|
+
valid_until: UTCDateTime | None = None
|
|
458
|
+
invalidated_at: UTCDateTime | None = None
|
|
459
|
+
evidence_count: int = Field(ge=0)
|
|
460
|
+
contradict_count: int = Field(ge=0)
|
|
461
|
+
contradiction_group: UUID | None = None
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
class KnowledgeClaimFingerprint(BaseModel):
|
|
465
|
+
"""Stable D54 claim grain: document lineage plus chunk content, never claim ID."""
|
|
466
|
+
|
|
467
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
468
|
+
|
|
469
|
+
lineage_id: UUID
|
|
470
|
+
chunk_content_hash: str
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
class KnowledgeRuleConfiguration(BaseModel):
|
|
474
|
+
"""The hash-visible configuration of one active page rule."""
|
|
475
|
+
|
|
476
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
477
|
+
|
|
478
|
+
rule_id: UUID
|
|
479
|
+
kind: KnowledgeRuleKind
|
|
480
|
+
params: dict[str, JsonValue]
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
class KnowledgeInputSnapshot(BaseModel):
|
|
484
|
+
"""Every deterministic input that decides whether a compiled page is stale."""
|
|
485
|
+
|
|
486
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
487
|
+
|
|
488
|
+
facts: tuple[KnowledgeFactFingerprint, ...] = ()
|
|
489
|
+
claims: tuple[KnowledgeClaimFingerprint, ...] = ()
|
|
490
|
+
rules: tuple[KnowledgeRuleConfiguration, ...] = ()
|
|
491
|
+
curation_hash: str | None = None
|
|
492
|
+
child_summary_hashes: tuple[str, ...] = ()
|
|
493
|
+
shared_model_summary_hash: str | None = None
|
|
494
|
+
writer_version: str
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class KnowledgeFactSheetFact(BaseModel):
|
|
498
|
+
"""One display-grade relation or observation selected by a page rule."""
|
|
499
|
+
|
|
500
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
501
|
+
|
|
502
|
+
kind: Literal["relation", "observation"]
|
|
503
|
+
fact_id: UUID
|
|
504
|
+
label: str = Field(min_length=1)
|
|
505
|
+
valid_from: UTCDateTime | None = None
|
|
506
|
+
valid_until: UTCDateTime | None = None
|
|
507
|
+
ingested_at: UTCDateTime
|
|
508
|
+
invalidated_at: UTCDateTime | None = None
|
|
509
|
+
evidence_count: int = Field(ge=0)
|
|
510
|
+
contradict_count: int = Field(ge=0)
|
|
511
|
+
contradiction_group: UUID | None = None
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class KnowledgeFactSheetSnapshot(BaseModel):
|
|
515
|
+
"""One repeatable-read rule result ready for deterministic rendering."""
|
|
516
|
+
|
|
517
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
518
|
+
|
|
519
|
+
artifact_id: UUID
|
|
520
|
+
deployment_id: UUID
|
|
521
|
+
evidence_as_of: UTCDateTime
|
|
522
|
+
input_snapshot: KnowledgeInputSnapshot
|
|
523
|
+
facts: tuple[KnowledgeFactSheetFact, ...]
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class KnowledgeRenderedFactSheet(BaseModel):
|
|
527
|
+
"""Rendered band plus the exact counts used by deterministic summaries."""
|
|
528
|
+
|
|
529
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
530
|
+
|
|
531
|
+
markdown: str
|
|
532
|
+
current_relation_count: int = Field(ge=0)
|
|
533
|
+
observation_count: int = Field(ge=0)
|
|
534
|
+
contradiction_group_count: int = Field(ge=0)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
class KnowledgeWriterFactReference(BaseModel):
|
|
538
|
+
"""One claim-to-fact evidence edge exposed inside a writer bundle."""
|
|
539
|
+
|
|
540
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
541
|
+
|
|
542
|
+
kind: Literal["relation", "observation"]
|
|
543
|
+
fact_id: UUID
|
|
544
|
+
stance: Literal["supports", "contradicts"]
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
class KnowledgeWriterClaim(BaseModel):
|
|
548
|
+
"""One current claim body carrying its stable D54 candidate coordinate."""
|
|
549
|
+
|
|
550
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
551
|
+
|
|
552
|
+
claim_id: UUID
|
|
553
|
+
lineage_id: UUID
|
|
554
|
+
chunk_content_hash: str = Field(min_length=1)
|
|
555
|
+
claim_text: str = Field(min_length=1)
|
|
556
|
+
source_span: str = Field(min_length=1)
|
|
557
|
+
document_title: str = Field(min_length=1)
|
|
558
|
+
source_kind: str = Field(min_length=1)
|
|
559
|
+
fact_references: tuple[KnowledgeWriterFactReference, ...] = ()
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class KnowledgeWriterClaimGroup(BaseModel):
|
|
563
|
+
"""All current claims at one stable lineage-plus-chunk candidate coordinate."""
|
|
564
|
+
|
|
565
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
566
|
+
|
|
567
|
+
lineage_id: UUID
|
|
568
|
+
chunk_content_hash: str = Field(min_length=1)
|
|
569
|
+
claims: tuple[KnowledgeWriterClaim, ...] = Field(min_length=1)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
class KnowledgeWriterBundle(BaseModel):
|
|
573
|
+
"""Exact fact candidates plus the deterministic capped claim offering."""
|
|
574
|
+
|
|
575
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
576
|
+
|
|
577
|
+
fact_sheet: KnowledgeFactSheetSnapshot
|
|
578
|
+
claim_groups: tuple[KnowledgeWriterClaimGroup, ...] = ()
|
|
579
|
+
claim_candidate_count: int = Field(ge=0)
|
|
580
|
+
claims_cut_count: int = Field(ge=0)
|
|
581
|
+
|
|
582
|
+
@model_validator(mode="after")
|
|
583
|
+
def require_honest_claim_cut(self) -> "KnowledgeWriterBundle":
|
|
584
|
+
"""Make the capped bundle account for every rule-matched claim coordinate."""
|
|
585
|
+
if len(self.claim_groups) + self.claims_cut_count != self.claim_candidate_count:
|
|
586
|
+
raise ValueError("offered and cut claim counts must equal claim candidates")
|
|
587
|
+
return self
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
class KnowledgeWriterCoverage(BaseModel):
|
|
591
|
+
"""Mechanical offered/cited/uncited candidate accounting for one writer."""
|
|
592
|
+
|
|
593
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
594
|
+
|
|
595
|
+
candidate_count: int = Field(ge=0)
|
|
596
|
+
cited_candidate_count: int = Field(ge=0)
|
|
597
|
+
uncited_count: int = Field(ge=0)
|
|
598
|
+
|
|
599
|
+
@model_validator(mode="after")
|
|
600
|
+
def require_complete_partition(self) -> "KnowledgeWriterCoverage":
|
|
601
|
+
"""Partition every offered candidate into cited or uncited exactly once."""
|
|
602
|
+
if self.cited_candidate_count + self.uncited_count != self.candidate_count:
|
|
603
|
+
raise ValueError("cited and uncited counts must partition candidates")
|
|
604
|
+
return self
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
class KnowledgeWriterSuggestion(BaseModel):
|
|
608
|
+
"""A writer-proposed planner input that WP-6.4 records but never applies."""
|
|
609
|
+
|
|
610
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
611
|
+
|
|
612
|
+
action: KnowledgePlanAction
|
|
613
|
+
rationale: str = Field(min_length=1)
|
|
614
|
+
payload: dict[str, JsonValue] = Field(default_factory=dict)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
class KnowledgeAgentSandboxPolicy(BaseModel):
|
|
618
|
+
"""The binding D52 limits applied to one stock-harness Plane-K session."""
|
|
619
|
+
|
|
620
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
621
|
+
|
|
622
|
+
network_access: Literal["none"] = "none"
|
|
623
|
+
memory_access: Literal["read_only"] = "read_only"
|
|
624
|
+
repository_write_access: Literal[False] = False
|
|
625
|
+
accepted_output_paths: tuple[str, ...]
|
|
626
|
+
|
|
627
|
+
@field_validator("accepted_output_paths")
|
|
628
|
+
@classmethod
|
|
629
|
+
def require_safe_declared_outputs(cls, value: tuple[str, ...]) -> tuple[str, ...]:
|
|
630
|
+
"""Keep each worker's declared output surface normalized and inside output/."""
|
|
631
|
+
if not value or len(set(value)) != len(value):
|
|
632
|
+
raise ValueError("agent output paths must be non-empty and unique")
|
|
633
|
+
for raw_path in value:
|
|
634
|
+
path = PurePosixPath(raw_path)
|
|
635
|
+
if (
|
|
636
|
+
path.is_absolute()
|
|
637
|
+
or ".." in path.parts
|
|
638
|
+
or str(path) != raw_path
|
|
639
|
+
or not raw_path.startswith("output/")
|
|
640
|
+
):
|
|
641
|
+
raise ValueError("agent output path must be normalized under output/")
|
|
642
|
+
return value
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
class KnowledgeWriterSandboxPolicy(KnowledgeAgentSandboxPolicy):
|
|
646
|
+
"""The fixed declared output surface of one prose-writer session."""
|
|
647
|
+
|
|
648
|
+
accepted_output_paths: tuple[str, ...] = KNOWLEDGE_WRITER_OUTPUT_PATHS
|
|
649
|
+
|
|
650
|
+
@field_validator("accepted_output_paths")
|
|
651
|
+
@classmethod
|
|
652
|
+
def require_declared_writer_outputs(cls, value: tuple[str, ...]) -> tuple[str, ...]:
|
|
653
|
+
"""Prevent runtime configuration from widening the writer's output surface."""
|
|
654
|
+
if value != KNOWLEDGE_WRITER_OUTPUT_PATHS:
|
|
655
|
+
raise ValueError("accepted writer output paths are fixed by contract")
|
|
656
|
+
return value
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
class KnowledgeAgentSessionRequest(BaseModel):
|
|
660
|
+
"""One isolated stock-harness invocation prepared by a Plane-K worker."""
|
|
661
|
+
|
|
662
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
663
|
+
|
|
664
|
+
session_id: UUID
|
|
665
|
+
model: str = Field(min_length=1)
|
|
666
|
+
prompt: str = Field(min_length=1)
|
|
667
|
+
timeout_seconds: int = Field(gt=0)
|
|
668
|
+
input_files: dict[str, str]
|
|
669
|
+
mounts: PublishedMounts
|
|
670
|
+
sandbox: KnowledgeAgentSandboxPolicy
|
|
671
|
+
|
|
672
|
+
@field_validator("input_files")
|
|
673
|
+
@classmethod
|
|
674
|
+
def require_safe_input_paths(cls, value: dict[str, str]) -> dict[str, str]:
|
|
675
|
+
"""Keep compiler-prepared inputs normalized and outside the output surface."""
|
|
676
|
+
for raw_path in value:
|
|
677
|
+
path = PurePosixPath(raw_path)
|
|
678
|
+
if (
|
|
679
|
+
not raw_path
|
|
680
|
+
or path.is_absolute()
|
|
681
|
+
or ".." in path.parts
|
|
682
|
+
or str(path) != raw_path
|
|
683
|
+
or raw_path.startswith("output/")
|
|
684
|
+
):
|
|
685
|
+
raise ValueError("agent input path must be normalized and read-only")
|
|
686
|
+
return value
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
class KnowledgeWriterSessionRequest(KnowledgeAgentSessionRequest):
|
|
690
|
+
"""One prose-writer invocation with the fixed writer output contract."""
|
|
691
|
+
|
|
692
|
+
sandbox: KnowledgeAgentSandboxPolicy = Field(
|
|
693
|
+
default_factory=KnowledgeWriterSandboxPolicy
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
@model_validator(mode="after")
|
|
697
|
+
def require_writer_output_contract(self) -> "KnowledgeWriterSessionRequest":
|
|
698
|
+
"""Reject callers that replace the fixed prose-writer output surface."""
|
|
699
|
+
if self.sandbox.accepted_output_paths != KNOWLEDGE_WRITER_OUTPUT_PATHS:
|
|
700
|
+
raise ValueError("accepted writer output paths are fixed by contract")
|
|
701
|
+
return self
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
class KnowledgeAgentSessionResult(BaseModel):
|
|
705
|
+
"""Raw declared files and complete process transcript from one harness session."""
|
|
706
|
+
|
|
707
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
708
|
+
|
|
709
|
+
session_id: UUID
|
|
710
|
+
exit_code: int | None
|
|
711
|
+
timed_out: bool = False
|
|
712
|
+
output_files: dict[str, str] = Field(default_factory=dict)
|
|
713
|
+
transcript: str = Field(min_length=1)
|
|
714
|
+
tokens: int | None = Field(default=None, ge=0)
|
|
715
|
+
cost_usd: float | None = Field(default=None, ge=0)
|
|
716
|
+
|
|
717
|
+
@model_validator(mode="after")
|
|
718
|
+
def require_consistent_terminal_state(self) -> "KnowledgeWriterSessionResult":
|
|
719
|
+
"""Distinguish a timeout from an ordinary process exit unambiguously."""
|
|
720
|
+
if self.timed_out == (self.exit_code is not None):
|
|
721
|
+
raise ValueError("timed-out sessions have no exit code; exited sessions do")
|
|
722
|
+
return self
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
KnowledgeWriterSessionResult = KnowledgeAgentSessionResult
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
class KnowledgeCompileContext(BaseModel):
|
|
729
|
+
"""Git/model inputs supplied to the Postgres-owned manifest computation."""
|
|
730
|
+
|
|
731
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
732
|
+
|
|
733
|
+
curation_hash: str | None = None
|
|
734
|
+
shared_model_summary_hash: str | None = None
|
|
735
|
+
writer_version: str
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
class KnowledgeCompileArtifact(BaseModel):
|
|
739
|
+
"""One compiled artifact as seen by the dependency scheduler."""
|
|
740
|
+
|
|
741
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
742
|
+
|
|
743
|
+
artifact_id: UUID
|
|
744
|
+
deployment_id: UUID
|
|
745
|
+
scope_id: UUID | None = None
|
|
746
|
+
parent_artifact_id: UUID | None = None
|
|
747
|
+
git_path: str
|
|
748
|
+
curation_path: str | None = None
|
|
749
|
+
artifact_kind: str | None = None
|
|
750
|
+
page_summary: str | None = None
|
|
751
|
+
content_hash: SHA256 | None = None
|
|
752
|
+
stale: bool
|
|
753
|
+
|
|
754
|
+
@field_validator("git_path", "curation_path")
|
|
755
|
+
@classmethod
|
|
756
|
+
def require_safe_markdown_path(cls, value: str | None) -> str | None:
|
|
757
|
+
"""Keep driver-owned writes relative, normalized, and Markdown-only."""
|
|
758
|
+
if value is None:
|
|
759
|
+
return None
|
|
760
|
+
path = PurePosixPath(value)
|
|
761
|
+
if (
|
|
762
|
+
not value
|
|
763
|
+
or path.is_absolute()
|
|
764
|
+
or ".." in path.parts
|
|
765
|
+
or str(path) != value
|
|
766
|
+
or path.suffix != ".md"
|
|
767
|
+
):
|
|
768
|
+
raise ValueError("git_path must be a normalized relative Markdown path")
|
|
769
|
+
return value
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
class KnowledgePageCompileRequest(BaseModel):
|
|
773
|
+
"""Deterministic context passed to the future per-page compiler seam."""
|
|
774
|
+
|
|
775
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
776
|
+
|
|
777
|
+
artifact: KnowledgeCompileArtifact
|
|
778
|
+
child_summaries: dict[UUID, str] = Field(default_factory=dict)
|
|
779
|
+
shared_model_summary: str | None = None
|
|
780
|
+
curation_hash: str | None = None
|
|
781
|
+
curation_markdown: str | None = None
|
|
782
|
+
previous_markdown: str | None = None
|
|
783
|
+
exclusions: tuple[KnowledgeEvidenceTarget, ...] = ()
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
class KnowledgePageCompileOutput(BaseModel):
|
|
787
|
+
"""Structured page output consumed and validated by the commit driver."""
|
|
788
|
+
|
|
789
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
790
|
+
|
|
791
|
+
compilation: KnowledgeCompilationWrite
|
|
792
|
+
markdown: str
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
class KnowledgePendingCycle(BaseModel):
|
|
796
|
+
"""One recoverable publish batch whose Postgres finalize step is pending."""
|
|
797
|
+
|
|
798
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
799
|
+
|
|
800
|
+
cycle_id: UUID
|
|
801
|
+
deployment_id: UUID
|
|
802
|
+
compilations: tuple[KnowledgeCompilationWrite, ...] = Field(min_length=1)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
class KnowledgeCommitCycleResult(BaseModel):
|
|
806
|
+
"""Observable outcome of one locked checkout/compile/publish cycle."""
|
|
807
|
+
|
|
808
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
809
|
+
|
|
810
|
+
checkout_revision: str
|
|
811
|
+
published_revision: str | None = None
|
|
812
|
+
compiled_artifact_ids: tuple[UUID, ...] = ()
|
|
813
|
+
recovered_cycle_ids: tuple[UUID, ...] = ()
|
|
814
|
+
quarantined_artifact_ids: tuple[UUID, ...] = ()
|
|
815
|
+
stamped_plan_decision_ids: tuple[UUID, ...] = ()
|
|
816
|
+
registered_authored_artifact_ids: tuple[UUID, ...] = ()
|
|
817
|
+
synced_authored_artifact_ids: tuple[UUID, ...] = ()
|
|
818
|
+
authored_lint_flag_artifact_ids: tuple[UUID, ...] = ()
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
class KnowledgeEvidenceDelta(BaseModel):
|
|
822
|
+
"""Fact/document/community identifiers changed since the previous K cycle."""
|
|
823
|
+
|
|
824
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
825
|
+
|
|
826
|
+
relation_ids: tuple[UUID, ...] = ()
|
|
827
|
+
observation_ids: tuple[UUID, ...] = ()
|
|
828
|
+
claim_ids: tuple[UUID, ...] = ()
|
|
829
|
+
doc_ids: tuple[UUID, ...] = ()
|
|
830
|
+
community_ids: tuple[UUID, ...] = ()
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class KnowledgeArtifactHash(BaseModel):
|
|
834
|
+
"""One artifact's recorded and freshly computed staleness keys."""
|
|
835
|
+
|
|
836
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
837
|
+
|
|
838
|
+
artifact_id: UUID
|
|
839
|
+
recorded_hash: str | None
|
|
840
|
+
computed_hash: str
|