graphite-code 0.3.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.
- graphite/__init__.py +41 -0
- graphite/__main__.py +7 -0
- graphite/_cleanup_worker.py +525 -0
- graphite/activation.py +164 -0
- graphite/agent_hooks.py +577 -0
- graphite/agent_settings.py +226 -0
- graphite/analyze.py +146 -0
- graphite/answer_contract.py +420 -0
- graphite/bootstrap.py +210 -0
- graphite/buildlock.py +99 -0
- graphite/cache.py +131 -0
- graphite/channel.py +1325 -0
- graphite/cli.py +3053 -0
- graphite/cluster.py +111 -0
- graphite/config.py +209 -0
- graphite/context.py +355 -0
- graphite/daemon.py +745 -0
- graphite/daemon_health.py +733 -0
- graphite/debt.py +118 -0
- graphite/dependency_install.py +1597 -0
- graphite/detach.py +33 -0
- graphite/doctor.py +678 -0
- graphite/doctor_probes.py +2100 -0
- graphite/engine_identity.py +238 -0
- graphite/export/__init__.py +6 -0
- graphite/export/html.py +244 -0
- graphite/export/json.py +39 -0
- graphite/export/md.py +68 -0
- graphite/extract/__init__.py +4 -0
- graphite/extract/ast.py +1964 -0
- graphite/freshness.py +127 -0
- graphite/git.py +406 -0
- graphite/graph.py +117 -0
- graphite/graph_io.py +188 -0
- graphite/health.py +147 -0
- graphite/hook_entry.py +68 -0
- graphite/hookinstall.py +224 -0
- graphite/hookshim.py +86 -0
- graphite/incident_ledger.py +247 -0
- graphite/ingest.py +279 -0
- graphite/init.py +791 -0
- graphite/io.py +32 -0
- graphite/listing.py +51 -0
- graphite/llm.py +518 -0
- graphite/llm_probe.py +157 -0
- graphite/mcp.py +7 -0
- graphite/mcp_server.py +450 -0
- graphite/natural_query.py +252 -0
- graphite/overlays.py +713 -0
- graphite/probe_process.py +879 -0
- graphite/probe_workspace.py +728 -0
- graphite/process_contracts.py +22 -0
- graphite/provider_observer.py +397 -0
- graphite/query.py +646 -0
- graphite/query_plan.py +97 -0
- graphite/replacement_audit.py +291 -0
- graphite/resolve.py +660 -0
- graphite/review.py +782 -0
- graphite/routing/__init__.py +5 -0
- graphite/routing/approval.py +362 -0
- graphite/routing/classifier.py +169 -0
- graphite/routing/claude_executor.py +419 -0
- graphite/routing/claude_probe.py +102 -0
- graphite/routing/cli_identity.py +84 -0
- graphite/routing/codex_executor.py +383 -0
- graphite/routing/codex_probe.py +93 -0
- graphite/routing/context_builder.py +327 -0
- graphite/routing/contracts.py +802 -0
- graphite/routing/diff_policy.py +468 -0
- graphite/routing/edit_apply.py +166 -0
- graphite/routing/effort.py +43 -0
- graphite/routing/lifecycle.py +771 -0
- graphite/routing/lifecycle_operator.py +227 -0
- graphite/routing/lifecycle_service.py +555 -0
- graphite/routing/lifecycle_storage.py +977 -0
- graphite/routing/ollama_executor.py +341 -0
- graphite/routing/ollama_probe.py +72 -0
- graphite/routing/openrouter_executor.py +338 -0
- graphite/routing/openrouter_probe.py +188 -0
- graphite/routing/policy.py +815 -0
- graphite/routing/probe_runner.py +543 -0
- graphite/routing/process_runner.py +523 -0
- graphite/routing/profiles.py +554 -0
- graphite/routing/prompt.py +58 -0
- graphite/routing/registry.py +444 -0
- graphite/routing/route_pool.py +629 -0
- graphite/routing/route_pool_execution.py +275 -0
- graphite/routing/schema_validation.py +169 -0
- graphite/routing/service.py +1263 -0
- graphite/routing/settings.py +99 -0
- graphite/routing/shadow.py +201 -0
- graphite/routing/storage.py +4001 -0
- graphite/routing/telemetry.py +346 -0
- graphite/routing/worktree.py +259 -0
- graphite/routing/zai_edit.py +113 -0
- graphite/routing/zai_executor.py +191 -0
- graphite/routing/zai_probe.py +126 -0
- graphite/savings.py +84 -0
- graphite/ts_bridge.py +142 -0
- graphite/ts_resolver.mjs +314 -0
- graphite/typescript_activation.py +1586 -0
- graphite/usage_ledger.py +156 -0
- graphite/validation.py +148 -0
- graphite/watch.py +167 -0
- graphite/windows_job.py +368 -0
- graphite/windows_startup.py +144 -0
- graphite/windows_task.py +212 -0
- graphite_code-0.3.0.dist-info/METADATA +743 -0
- graphite_code-0.3.0.dist-info/RECORD +112 -0
- graphite_code-0.3.0.dist-info/WHEEL +4 -0
- graphite_code-0.3.0.dist-info/entry_points.txt +3 -0
- graphite_code-0.3.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""Read-only, bounded operator surface for provider lifecycle authority."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from .contracts import Effort
|
|
10
|
+
from .lifecycle import ProviderCompatibilityPolicy, ProviderLifecycleState
|
|
11
|
+
from .lifecycle_service import LifecycleServiceError, build_verification_manifest
|
|
12
|
+
from .lifecycle_storage import (
|
|
13
|
+
MAX_EVENT_PAGE_SIZE,
|
|
14
|
+
CurrentLifecycleObservation,
|
|
15
|
+
LifecycleStorageError,
|
|
16
|
+
LifecycleStore,
|
|
17
|
+
)
|
|
18
|
+
from .storage import StorageError
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LifecycleOperatorError(RuntimeError):
|
|
22
|
+
"""A stable, sanitized lifecycle operator failure."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, code: str) -> None:
|
|
25
|
+
self.code = code
|
|
26
|
+
super().__init__(code)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _page_limit(value: object) -> int:
|
|
30
|
+
if (
|
|
31
|
+
isinstance(value, bool)
|
|
32
|
+
or not isinstance(value, int)
|
|
33
|
+
or not 1 <= value <= MAX_EVENT_PAGE_SIZE
|
|
34
|
+
):
|
|
35
|
+
raise LifecycleOperatorError("lifecycle_limit_invalid")
|
|
36
|
+
return value
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _canonical_digest(value: dict[str, Any]) -> str:
|
|
40
|
+
payload = json.dumps(
|
|
41
|
+
value, sort_keys=True, separators=(",", ":"), ensure_ascii=True
|
|
42
|
+
).encode("utf-8")
|
|
43
|
+
return hashlib.sha256(payload).hexdigest()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class LifecycleOperator:
|
|
47
|
+
"""Inspect lifecycle authority and prepare non-activating candidates."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, repository_root: Path | str) -> None:
|
|
50
|
+
try:
|
|
51
|
+
self.store = LifecycleStore(Path(repository_root))
|
|
52
|
+
except (LifecycleStorageError, StorageError, ValueError, OSError) as exc:
|
|
53
|
+
code = getattr(exc, "code", "lifecycle_operator_invalid")
|
|
54
|
+
raise LifecycleOperatorError(code) from None
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def _public_observation(
|
|
58
|
+
observation: CurrentLifecycleObservation,
|
|
59
|
+
) -> dict[str, object]:
|
|
60
|
+
return {
|
|
61
|
+
"boundary_digest": observation.boundary_digest,
|
|
62
|
+
"provider": observation.provider.value,
|
|
63
|
+
"runtime_kind": observation.runtime_kind.value,
|
|
64
|
+
"state": observation.state.value,
|
|
65
|
+
"lifecycle_identity_digest": (
|
|
66
|
+
None if observation.identity is None else observation.identity.digest
|
|
67
|
+
),
|
|
68
|
+
"policy_version": observation.policy_version,
|
|
69
|
+
"observed_at": observation.observed_at,
|
|
70
|
+
"updated_at": observation.updated_at,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
def _current(self, boundary_digest: str) -> CurrentLifecycleObservation:
|
|
74
|
+
try:
|
|
75
|
+
current = self.store.read_current_observation(boundary_digest)
|
|
76
|
+
except (LifecycleStorageError, ValueError) as exc:
|
|
77
|
+
raise LifecycleOperatorError(
|
|
78
|
+
getattr(exc, "code", "lifecycle_operator_invalid")
|
|
79
|
+
) from None
|
|
80
|
+
if current is None:
|
|
81
|
+
raise LifecycleOperatorError("lifecycle_observation_missing")
|
|
82
|
+
return current
|
|
83
|
+
|
|
84
|
+
def status(self, boundary_digest: str) -> dict[str, object]:
|
|
85
|
+
return {
|
|
86
|
+
"schema_version": 1,
|
|
87
|
+
"storage_integrity": "ok",
|
|
88
|
+
"observation": self._public_observation(self._current(boundary_digest)),
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
def list_observations(self, *, limit: int) -> dict[str, object]:
|
|
92
|
+
bounded = _page_limit(limit)
|
|
93
|
+
try:
|
|
94
|
+
observations = self.store.read_observations(limit=bounded)
|
|
95
|
+
except (LifecycleStorageError, ValueError) as exc:
|
|
96
|
+
raise LifecycleOperatorError(
|
|
97
|
+
getattr(exc, "code", "lifecycle_operator_invalid")
|
|
98
|
+
) from None
|
|
99
|
+
public = [self._public_observation(observation) for observation in observations]
|
|
100
|
+
return {"schema_version": 1, "count": len(public), "observations": public}
|
|
101
|
+
|
|
102
|
+
def history(self, boundary_digest: str, *, limit: int) -> dict[str, object]:
|
|
103
|
+
bounded = _page_limit(limit)
|
|
104
|
+
try:
|
|
105
|
+
events = self.store.read_events(boundary_digest, limit=bounded)
|
|
106
|
+
except (LifecycleStorageError, ValueError) as exc:
|
|
107
|
+
raise LifecycleOperatorError(
|
|
108
|
+
getattr(exc, "code", "lifecycle_operator_invalid")
|
|
109
|
+
) from None
|
|
110
|
+
public = [event.to_dict() for event in events]
|
|
111
|
+
return {"schema_version": 1, "count": len(public), "events": public}
|
|
112
|
+
|
|
113
|
+
def inspect_policy(self, boundary_digest: str) -> dict[str, object]:
|
|
114
|
+
current = self._current(boundary_digest)
|
|
115
|
+
return {
|
|
116
|
+
"schema_version": 1,
|
|
117
|
+
"boundary_digest": current.boundary_digest,
|
|
118
|
+
"provider": current.provider.value,
|
|
119
|
+
"runtime_kind": current.runtime_kind.value,
|
|
120
|
+
"lifecycle_identity_digest": (
|
|
121
|
+
None if current.identity is None else current.identity.digest
|
|
122
|
+
),
|
|
123
|
+
"policy_version": current.policy_version,
|
|
124
|
+
"policy_parameters_persisted": False,
|
|
125
|
+
"change_rules": {
|
|
126
|
+
"hash_or_patch": "standard_probe_then_verification_required",
|
|
127
|
+
"minor": "expanded_probe_then_verification_required",
|
|
128
|
+
"major": "incompatible_pending_policy_promotion",
|
|
129
|
+
},
|
|
130
|
+
"automatic_activation": False,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
def prepare_policy_promotion(
|
|
134
|
+
self,
|
|
135
|
+
*,
|
|
136
|
+
boundary_digest: str,
|
|
137
|
+
lifecycle_identity_digest: str,
|
|
138
|
+
proposed_policy_version: str,
|
|
139
|
+
minimum_version: str,
|
|
140
|
+
maximum_version_exclusive: str,
|
|
141
|
+
required_capabilities: tuple[str, ...],
|
|
142
|
+
prepared_at: int,
|
|
143
|
+
) -> dict[str, object]:
|
|
144
|
+
current = self._current(boundary_digest)
|
|
145
|
+
if current.identity is None or current.identity.digest != lifecycle_identity_digest:
|
|
146
|
+
raise LifecycleOperatorError("lifecycle_identity_changed")
|
|
147
|
+
if current.state is not ProviderLifecycleState.INCOMPATIBLE:
|
|
148
|
+
raise LifecycleOperatorError("lifecycle_policy_promotion_not_required")
|
|
149
|
+
if (
|
|
150
|
+
isinstance(prepared_at, bool)
|
|
151
|
+
or not isinstance(prepared_at, int)
|
|
152
|
+
or not current.updated_at <= prepared_at <= 10**12
|
|
153
|
+
):
|
|
154
|
+
raise LifecycleOperatorError("lifecycle_policy_candidate_invalid")
|
|
155
|
+
try:
|
|
156
|
+
proposed = ProviderCompatibilityPolicy(
|
|
157
|
+
provider=current.provider,
|
|
158
|
+
runtime_kind=current.runtime_kind,
|
|
159
|
+
policy_version=proposed_policy_version,
|
|
160
|
+
minimum_version=minimum_version,
|
|
161
|
+
maximum_version_exclusive=maximum_version_exclusive,
|
|
162
|
+
required_capabilities=required_capabilities,
|
|
163
|
+
)
|
|
164
|
+
except (TypeError, ValueError):
|
|
165
|
+
raise LifecycleOperatorError("lifecycle_policy_candidate_invalid") from None
|
|
166
|
+
candidate = {
|
|
167
|
+
"boundary_digest": current.boundary_digest,
|
|
168
|
+
"lifecycle_identity_digest": lifecycle_identity_digest,
|
|
169
|
+
"current_state": current.state.value,
|
|
170
|
+
"current_policy_version": current.policy_version,
|
|
171
|
+
"proposed_policy": proposed.to_dict(),
|
|
172
|
+
"prepared_at": prepared_at,
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
"schema_version": 1,
|
|
176
|
+
**candidate,
|
|
177
|
+
"candidate_digest": _canonical_digest(candidate),
|
|
178
|
+
"promotion_requires_separate_human_authority": True,
|
|
179
|
+
"automatic_activation": False,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
def prepare_verification_manifest(
|
|
183
|
+
self,
|
|
184
|
+
*,
|
|
185
|
+
boundary_digest: str,
|
|
186
|
+
lifecycle_identity_digest: str,
|
|
187
|
+
requested_model: str,
|
|
188
|
+
expected_effective_model: str,
|
|
189
|
+
effort: Effort,
|
|
190
|
+
max_input_tokens: int,
|
|
191
|
+
max_output_tokens: int,
|
|
192
|
+
timeout_seconds: int,
|
|
193
|
+
expires_at: int,
|
|
194
|
+
fixture_repository_commit: str,
|
|
195
|
+
graph_fingerprint: str,
|
|
196
|
+
prompt_contract_hash: str,
|
|
197
|
+
response_contract_hash: str,
|
|
198
|
+
max_cost_microunits: int | None = None,
|
|
199
|
+
) -> dict[str, object]:
|
|
200
|
+
current = self._current(boundary_digest)
|
|
201
|
+
if current.identity is None or current.identity.digest != lifecycle_identity_digest:
|
|
202
|
+
raise LifecycleOperatorError("lifecycle_identity_changed")
|
|
203
|
+
try:
|
|
204
|
+
manifest = build_verification_manifest(
|
|
205
|
+
current,
|
|
206
|
+
requested_model=requested_model,
|
|
207
|
+
expected_effective_model=expected_effective_model,
|
|
208
|
+
effort=effort,
|
|
209
|
+
max_input_tokens=max_input_tokens,
|
|
210
|
+
max_output_tokens=max_output_tokens,
|
|
211
|
+
timeout_seconds=timeout_seconds,
|
|
212
|
+
expires_at=expires_at,
|
|
213
|
+
fixture_repository_commit=fixture_repository_commit,
|
|
214
|
+
graph_fingerprint=graph_fingerprint,
|
|
215
|
+
prompt_contract_hash=prompt_contract_hash,
|
|
216
|
+
response_contract_hash=response_contract_hash,
|
|
217
|
+
max_cost_microunits=max_cost_microunits,
|
|
218
|
+
)
|
|
219
|
+
except LifecycleServiceError as exc:
|
|
220
|
+
raise LifecycleOperatorError(exc.code) from None
|
|
221
|
+
return {
|
|
222
|
+
"schema_version": 1,
|
|
223
|
+
"manifest_digest": manifest.digest,
|
|
224
|
+
"manifest": manifest.to_dict(),
|
|
225
|
+
"execution_performed": False,
|
|
226
|
+
"activation_performed": False,
|
|
227
|
+
}
|