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.
Files changed (112) hide show
  1. graphite/__init__.py +41 -0
  2. graphite/__main__.py +7 -0
  3. graphite/_cleanup_worker.py +525 -0
  4. graphite/activation.py +164 -0
  5. graphite/agent_hooks.py +577 -0
  6. graphite/agent_settings.py +226 -0
  7. graphite/analyze.py +146 -0
  8. graphite/answer_contract.py +420 -0
  9. graphite/bootstrap.py +210 -0
  10. graphite/buildlock.py +99 -0
  11. graphite/cache.py +131 -0
  12. graphite/channel.py +1325 -0
  13. graphite/cli.py +3053 -0
  14. graphite/cluster.py +111 -0
  15. graphite/config.py +209 -0
  16. graphite/context.py +355 -0
  17. graphite/daemon.py +745 -0
  18. graphite/daemon_health.py +733 -0
  19. graphite/debt.py +118 -0
  20. graphite/dependency_install.py +1597 -0
  21. graphite/detach.py +33 -0
  22. graphite/doctor.py +678 -0
  23. graphite/doctor_probes.py +2100 -0
  24. graphite/engine_identity.py +238 -0
  25. graphite/export/__init__.py +6 -0
  26. graphite/export/html.py +244 -0
  27. graphite/export/json.py +39 -0
  28. graphite/export/md.py +68 -0
  29. graphite/extract/__init__.py +4 -0
  30. graphite/extract/ast.py +1964 -0
  31. graphite/freshness.py +127 -0
  32. graphite/git.py +406 -0
  33. graphite/graph.py +117 -0
  34. graphite/graph_io.py +188 -0
  35. graphite/health.py +147 -0
  36. graphite/hook_entry.py +68 -0
  37. graphite/hookinstall.py +224 -0
  38. graphite/hookshim.py +86 -0
  39. graphite/incident_ledger.py +247 -0
  40. graphite/ingest.py +279 -0
  41. graphite/init.py +791 -0
  42. graphite/io.py +32 -0
  43. graphite/listing.py +51 -0
  44. graphite/llm.py +518 -0
  45. graphite/llm_probe.py +157 -0
  46. graphite/mcp.py +7 -0
  47. graphite/mcp_server.py +450 -0
  48. graphite/natural_query.py +252 -0
  49. graphite/overlays.py +713 -0
  50. graphite/probe_process.py +879 -0
  51. graphite/probe_workspace.py +728 -0
  52. graphite/process_contracts.py +22 -0
  53. graphite/provider_observer.py +397 -0
  54. graphite/query.py +646 -0
  55. graphite/query_plan.py +97 -0
  56. graphite/replacement_audit.py +291 -0
  57. graphite/resolve.py +660 -0
  58. graphite/review.py +782 -0
  59. graphite/routing/__init__.py +5 -0
  60. graphite/routing/approval.py +362 -0
  61. graphite/routing/classifier.py +169 -0
  62. graphite/routing/claude_executor.py +419 -0
  63. graphite/routing/claude_probe.py +102 -0
  64. graphite/routing/cli_identity.py +84 -0
  65. graphite/routing/codex_executor.py +383 -0
  66. graphite/routing/codex_probe.py +93 -0
  67. graphite/routing/context_builder.py +327 -0
  68. graphite/routing/contracts.py +802 -0
  69. graphite/routing/diff_policy.py +468 -0
  70. graphite/routing/edit_apply.py +166 -0
  71. graphite/routing/effort.py +43 -0
  72. graphite/routing/lifecycle.py +771 -0
  73. graphite/routing/lifecycle_operator.py +227 -0
  74. graphite/routing/lifecycle_service.py +555 -0
  75. graphite/routing/lifecycle_storage.py +977 -0
  76. graphite/routing/ollama_executor.py +341 -0
  77. graphite/routing/ollama_probe.py +72 -0
  78. graphite/routing/openrouter_executor.py +338 -0
  79. graphite/routing/openrouter_probe.py +188 -0
  80. graphite/routing/policy.py +815 -0
  81. graphite/routing/probe_runner.py +543 -0
  82. graphite/routing/process_runner.py +523 -0
  83. graphite/routing/profiles.py +554 -0
  84. graphite/routing/prompt.py +58 -0
  85. graphite/routing/registry.py +444 -0
  86. graphite/routing/route_pool.py +629 -0
  87. graphite/routing/route_pool_execution.py +275 -0
  88. graphite/routing/schema_validation.py +169 -0
  89. graphite/routing/service.py +1263 -0
  90. graphite/routing/settings.py +99 -0
  91. graphite/routing/shadow.py +201 -0
  92. graphite/routing/storage.py +4001 -0
  93. graphite/routing/telemetry.py +346 -0
  94. graphite/routing/worktree.py +259 -0
  95. graphite/routing/zai_edit.py +113 -0
  96. graphite/routing/zai_executor.py +191 -0
  97. graphite/routing/zai_probe.py +126 -0
  98. graphite/savings.py +84 -0
  99. graphite/ts_bridge.py +142 -0
  100. graphite/ts_resolver.mjs +314 -0
  101. graphite/typescript_activation.py +1586 -0
  102. graphite/usage_ledger.py +156 -0
  103. graphite/validation.py +148 -0
  104. graphite/watch.py +167 -0
  105. graphite/windows_job.py +368 -0
  106. graphite/windows_startup.py +144 -0
  107. graphite/windows_task.py +212 -0
  108. graphite_code-0.3.0.dist-info/METADATA +743 -0
  109. graphite_code-0.3.0.dist-info/RECORD +112 -0
  110. graphite_code-0.3.0.dist-info/WHEEL +4 -0
  111. graphite_code-0.3.0.dist-info/entry_points.txt +3 -0
  112. 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
+ }