arcgraph 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.
- arcgraph/__init__.py +41 -0
- arcgraph/_build_provenance.json +10 -0
- arcgraph/adapters/__init__.py +6 -0
- arcgraph/adapters/arq_adapter.py +369 -0
- arcgraph/adapters/celery_adapter.py +440 -0
- arcgraph/adapters/common.py +436 -0
- arcgraph/adapters/django_adapter.py +765 -0
- arcgraph/adapters/fastapi_adapter.py +415 -0
- arcgraph/adapters/logging_adapter.py +335 -0
- arcgraph/adapters/mcp_adapter.py +100 -0
- arcgraph/adapters/pydantic_adapter.py +290 -0
- arcgraph/adapters/pytest_adapter.py +221 -0
- arcgraph/adapters/pytest_collection.py +96 -0
- arcgraph/adapters/pytest_fixtures.py +371 -0
- arcgraph/adapters/pytest_types.py +251 -0
- arcgraph/adapters/registry.py +34 -0
- arcgraph/adapters/service_container_adapter.py +548 -0
- arcgraph/adapters/sqlalchemy_adapter.py +446 -0
- arcgraph/adapters/typer_click_adapter.py +292 -0
- arcgraph/analyzers/__init__.py +1 -0
- arcgraph/analyzers/bindings.py +782 -0
- arcgraph/analyzers/calls/__init__.py +6 -0
- arcgraph/analyzers/calls/analyzer.py +2921 -0
- arcgraph/analyzers/calls/constants.py +702 -0
- arcgraph/analyzers/calls/context.py +298 -0
- arcgraph/analyzers/calls/lexical.py +237 -0
- arcgraph/analyzers/coverage.py +826 -0
- arcgraph/analyzers/exports.py +46 -0
- arcgraph/analyzers/har_trace.py +323 -0
- arcgraph/analyzers/imports.py +190 -0
- arcgraph/analyzers/otel_trace.py +352 -0
- arcgraph/analyzers/precise_references.py +1199 -0
- arcgraph/analyzers/python_scopes.py +56 -0
- arcgraph/analyzers/runtime_trace.py +516 -0
- arcgraph/analyzers/similarity.py +430 -0
- arcgraph/analyzers/symbols.py +363 -0
- arcgraph/analyzers/type_unions.py +89 -0
- arcgraph/analyzers/types.py +2293 -0
- arcgraph/assets/__init__.py +1 -0
- arcgraph/assets/workbench/__init__.py +1 -0
- arcgraph/assets/workbench/index.html +2398 -0
- arcgraph/assets/workbench/vendor/LICENSE.d3.txt +15 -0
- arcgraph/assets/workbench/vendor/d3.v7.min.js +2 -0
- arcgraph/change/__init__.py +10 -0
- arcgraph/change/baseline.py +145 -0
- arcgraph/change/changed_regions.py +728 -0
- arcgraph/change/contracts.py +927 -0
- arcgraph/change/errors.py +88 -0
- arcgraph/change/evidence.py +289 -0
- arcgraph/change/graph_delta.py +1422 -0
- arcgraph/change/identities.py +1277 -0
- arcgraph/change/paths.py +234 -0
- arcgraph/change/pins.py +426 -0
- arcgraph/change/planner.py +504 -0
- arcgraph/change/protected_surfaces.py +328 -0
- arcgraph/change/provider.py +46 -0
- arcgraph/change/service.py +1030 -0
- arcgraph/change/source_provider.py +311 -0
- arcgraph/change/store.py +1138 -0
- arcgraph/change/trusted_runners.py +154 -0
- arcgraph/change/verdicts.py +141 -0
- arcgraph/change/verification_plan.py +113 -0
- arcgraph/change/verifier.py +579 -0
- arcgraph/core/__init__.py +1 -0
- arcgraph/core/assurance.py +343 -0
- arcgraph/core/binding_metrics.py +75 -0
- arcgraph/core/cleanup.py +701 -0
- arcgraph/core/confidence_profiles.py +108 -0
- arcgraph/core/evidence_manifest.py +862 -0
- arcgraph/core/expression_kinds.py +11 -0
- arcgraph/core/force_graph_export.py +1125 -0
- arcgraph/core/freshness.py +94 -0
- arcgraph/core/graph_store.py +1099 -0
- arcgraph/core/ids.py +206 -0
- arcgraph/core/language_tiers.py +150 -0
- arcgraph/core/merge.py +649 -0
- arcgraph/core/metadata.py +30 -0
- arcgraph/core/operation_lock.py +218 -0
- arcgraph/core/passes.py +142 -0
- arcgraph/core/payload_policy.py +708 -0
- arcgraph/core/precise_references.py +124 -0
- arcgraph/core/query_engine.py +3078 -0
- arcgraph/core/recovery.py +18 -0
- arcgraph/core/scanner.py +1454 -0
- arcgraph/core/schemas.py +700 -0
- arcgraph/core/semantic.py +263 -0
- arcgraph/core/semantic_metrics.py +619 -0
- arcgraph/core/sharing_retry.py +84 -0
- arcgraph/core/structural.py +260 -0
- arcgraph/core/target_resolver.py +486 -0
- arcgraph/core/type_metrics.py +67 -0
- arcgraph/core/unresolved_classification.py +471 -0
- arcgraph/core/utils.py +100 -0
- arcgraph/core/visual_contract.py +240 -0
- arcgraph/core/visual_slice_engine.py +933 -0
- arcgraph/interfaces/__init__.py +1 -0
- arcgraph/interfaces/agent_capabilities.py +493 -0
- arcgraph/interfaces/agent_help.py +313 -0
- arcgraph/interfaces/benchmark.py +548 -0
- arcgraph/interfaces/ci.py +1992 -0
- arcgraph/interfaces/cli.py +2799 -0
- arcgraph/interfaces/cli_change.py +690 -0
- arcgraph/interfaces/cli_feedback.py +176 -0
- arcgraph/interfaces/cli_ops.py +69 -0
- arcgraph/interfaces/cli_support.py +113 -0
- arcgraph/interfaces/cli_trial.py +42 -0
- arcgraph/interfaces/cli_visual.py +601 -0
- arcgraph/interfaces/cli_workspace.py +300 -0
- arcgraph/interfaces/client_setup.py +481 -0
- arcgraph/interfaces/docs.py +1255 -0
- arcgraph/interfaces/human_output.py +409 -0
- arcgraph/interfaces/local_state.py +577 -0
- arcgraph/interfaces/mcp_server.py +457 -0
- arcgraph/interfaces/mcp_tools.py +1209 -0
- arcgraph/interfaces/metrics.py +571 -0
- arcgraph/interfaces/ops.py +330 -0
- arcgraph/interfaces/precision.py +1670 -0
- arcgraph/interfaces/project_probe.py +75 -0
- arcgraph/interfaces/reports.py +1121 -0
- arcgraph/interfaces/stdio_encoding.py +29 -0
- arcgraph/interfaces/trace.py +592 -0
- arcgraph/interfaces/trial_feedback.py +519 -0
- arcgraph/interfaces/trial_setup.py +535 -0
- arcgraph/interfaces/visual_server.py +354 -0
- arcgraph/interfaces/visual_slice.py +168 -0
- arcgraph/interfaces/visual_smoke.py +666 -0
- arcgraph/interfaces/workbench.py +576 -0
- arcgraph/interfaces/workspace.py +1513 -0
- arcgraph/pipeline/__init__.py +1 -0
- arcgraph/pipeline/contracts.py +122 -0
- arcgraph/pipeline/external_frontend.py +451 -0
- arcgraph/pipeline/external_l3_frontends.py +368 -0
- arcgraph/pipeline/external_protocol.py +358 -0
- arcgraph/pipeline/frontends.py +437 -0
- arcgraph/pipeline/indexer.py +661 -0
- arcgraph/pipeline/openapi_frontend.py +708 -0
- arcgraph/pipeline/python_frontend.py +298 -0
- arcgraph/pipeline/reindexer.py +1333 -0
- arcgraph/pipeline/scip_frontend.py +726 -0
- arcgraph/pipeline/typescript_extractor/declarations.mjs +183 -0
- arcgraph/pipeline/typescript_extractor/edges.mjs +2794 -0
- arcgraph/pipeline/typescript_extractor/graph_primitives.mjs +189 -0
- arcgraph/pipeline/typescript_extractor/module_resolution.mjs +877 -0
- arcgraph/pipeline/typescript_extractor/runtime.mjs +56 -0
- arcgraph/pipeline/typescript_extractor/similarity.mjs +619 -0
- arcgraph/pipeline/typescript_extractor/similarity_runner.mjs +19 -0
- arcgraph/pipeline/typescript_extractor/sources.mjs +23 -0
- arcgraph/pipeline/typescript_extractor.mjs +177 -0
- arcgraph/pipeline/typescript_frameworks.py +947 -0
- arcgraph/pipeline/typescript_frontend.py +656 -0
- arcgraph/pipeline/typescript_references.mjs +167 -0
- arcgraph/providers/__init__.py +27 -0
- arcgraph/providers/context_provider.py +1258 -0
- arcgraph/providers/flow_payload.py +117 -0
- arcgraph/providers/memory_connector.py +216 -0
- arcgraph/providers/orchestrator.py +475 -0
- arcgraph/providers/relationship_payload.py +102 -0
- arcgraph/providers/risk_provider.py +843 -0
- arcgraph/providers/why_provider.py +349 -0
- arcgraph/version_info.py +246 -0
- arcgraph-0.1.0.dist-info/METADATA +676 -0
- arcgraph-0.1.0.dist-info/RECORD +165 -0
- arcgraph-0.1.0.dist-info/WHEEL +4 -0
- arcgraph-0.1.0.dist-info/entry_points.txt +2 -0
- arcgraph-0.1.0.dist-info/licenses/LICENSE +203 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"""Operational helpers for ArcGraph rebuild and stale-index automation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import time
|
|
7
|
+
from typing import Any, Callable
|
|
8
|
+
|
|
9
|
+
from arcgraph.pipeline.indexer import ArcGraphIndexer
|
|
10
|
+
from arcgraph.core.cleanup import (
|
|
11
|
+
DEFAULT_BUILD_RETENTION,
|
|
12
|
+
prune_arcgraph_output,
|
|
13
|
+
)
|
|
14
|
+
from arcgraph.core.query_engine import QueryEngine, SchemaVersionError
|
|
15
|
+
from arcgraph.core.scanner import SourceRoot, SourceRootDetection
|
|
16
|
+
from arcgraph.core.schemas import SCHEMA_VERSION
|
|
17
|
+
from arcgraph.pipeline.reindexer import ArcGraphReindexer, FullBuildRequired
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def rebuild_index(
|
|
21
|
+
*,
|
|
22
|
+
repo_root: Path,
|
|
23
|
+
output_dir: Path,
|
|
24
|
+
source_roots: list[SourceRoot],
|
|
25
|
+
if_stale: bool = False,
|
|
26
|
+
scip_index_path: str | Path | None = None,
|
|
27
|
+
pyright_export_path: str | Path | None = None,
|
|
28
|
+
runtime_trace_path: str | Path | None = None,
|
|
29
|
+
coverage_path: str | Path | None = None,
|
|
30
|
+
enable_v2_call_resolution: bool = True,
|
|
31
|
+
source_root_detection: SourceRootDetection | None = None,
|
|
32
|
+
) -> dict[str, Any]:
|
|
33
|
+
before, reason = _current_status(output_dir)
|
|
34
|
+
freshness = before.get("freshness", {}) if before else {}
|
|
35
|
+
should_rebuild = (
|
|
36
|
+
not if_stale
|
|
37
|
+
or before is None
|
|
38
|
+
or freshness.get("stale")
|
|
39
|
+
or before.get("schema_version") != SCHEMA_VERSION
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
if not should_rebuild:
|
|
43
|
+
return {
|
|
44
|
+
"schema_version": SCHEMA_VERSION,
|
|
45
|
+
"status": "skipped",
|
|
46
|
+
"action": "none",
|
|
47
|
+
"reason": "Current index is fresh.",
|
|
48
|
+
"freshness": freshness,
|
|
49
|
+
"before": before,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
metadata, build_dir = ArcGraphIndexer(
|
|
53
|
+
repo_root,
|
|
54
|
+
output_dir,
|
|
55
|
+
source_roots,
|
|
56
|
+
scip_index_path=scip_index_path,
|
|
57
|
+
pyright_export_path=pyright_export_path,
|
|
58
|
+
runtime_trace_path=runtime_trace_path,
|
|
59
|
+
coverage_path=coverage_path,
|
|
60
|
+
enable_v2_call_resolution=enable_v2_call_resolution,
|
|
61
|
+
source_root_detection=source_root_detection,
|
|
62
|
+
).build()
|
|
63
|
+
payload = metadata.model_dump(mode="json")
|
|
64
|
+
return {
|
|
65
|
+
"schema_version": SCHEMA_VERSION,
|
|
66
|
+
"status": "available",
|
|
67
|
+
"action": "rebuilt",
|
|
68
|
+
"reason": reason or "Forced rebuild requested.",
|
|
69
|
+
"freshness": {"status": "fresh", "stale": False},
|
|
70
|
+
"before": before,
|
|
71
|
+
"metadata": payload,
|
|
72
|
+
"build_dir": str(build_dir),
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def stale_alert(
|
|
77
|
+
query_engine: QueryEngine, *, fail_on_stale: bool = False
|
|
78
|
+
) -> dict[str, Any]:
|
|
79
|
+
current = query_engine.current()
|
|
80
|
+
freshness = current.get("freshness", {})
|
|
81
|
+
stale = bool(freshness.get("stale"))
|
|
82
|
+
payload = {
|
|
83
|
+
"schema_version": SCHEMA_VERSION,
|
|
84
|
+
"index_version": current.get("index_version"),
|
|
85
|
+
"status": "warn" if stale else "pass",
|
|
86
|
+
"freshness": freshness,
|
|
87
|
+
"capabilities": current.get("capabilities", {}),
|
|
88
|
+
"warnings": ["ArcGraph index is stale."] if stale else [],
|
|
89
|
+
}
|
|
90
|
+
if stale and fail_on_stale:
|
|
91
|
+
payload["_exit_code"] = 1
|
|
92
|
+
return payload
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def sync_index(
|
|
96
|
+
*,
|
|
97
|
+
repo_root: Path,
|
|
98
|
+
output_dir: Path,
|
|
99
|
+
if_stale: bool = False,
|
|
100
|
+
) -> dict[str, Any]:
|
|
101
|
+
"""Explicitly publish an incremental index and preserve the old pointer on failure."""
|
|
102
|
+
|
|
103
|
+
started = time.monotonic()
|
|
104
|
+
before, reason = _current_status(output_dir)
|
|
105
|
+
if before is None:
|
|
106
|
+
return _sync_failure(
|
|
107
|
+
before=None,
|
|
108
|
+
reason=reason or "No current index exists.",
|
|
109
|
+
elapsed_ms=_elapsed_ms(started),
|
|
110
|
+
command="arcgraph build",
|
|
111
|
+
)
|
|
112
|
+
freshness = before.get("freshness", {})
|
|
113
|
+
if if_stale and not freshness.get("stale"):
|
|
114
|
+
return {
|
|
115
|
+
"schema_version": SCHEMA_VERSION,
|
|
116
|
+
"status": "skipped",
|
|
117
|
+
"action": "none",
|
|
118
|
+
"published": False,
|
|
119
|
+
"reason": "Current index is fresh.",
|
|
120
|
+
"before_index_version": before.get("index_version"),
|
|
121
|
+
"index_version": before.get("index_version"),
|
|
122
|
+
"freshness": freshness,
|
|
123
|
+
"elapsed_ms": _elapsed_ms(started),
|
|
124
|
+
}
|
|
125
|
+
try:
|
|
126
|
+
result = ArcGraphReindexer(repo_root, output_dir).reindex_changed(
|
|
127
|
+
cleanup_after_publish=False
|
|
128
|
+
)
|
|
129
|
+
except FullBuildRequired as exc:
|
|
130
|
+
return _sync_failure(
|
|
131
|
+
before=before,
|
|
132
|
+
reason=f"{type(exc).__name__}: {exc}",
|
|
133
|
+
elapsed_ms=_elapsed_ms(started),
|
|
134
|
+
command="arcgraph build",
|
|
135
|
+
)
|
|
136
|
+
except (OSError, RuntimeError, ValueError) as exc:
|
|
137
|
+
return _sync_failure(
|
|
138
|
+
before=before,
|
|
139
|
+
reason=f"{type(exc).__name__}: {exc}",
|
|
140
|
+
elapsed_ms=_elapsed_ms(started),
|
|
141
|
+
command="arcgraph sync --if-stale",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
after, after_reason = _current_status(output_dir)
|
|
145
|
+
if after is None:
|
|
146
|
+
return _sync_failure(
|
|
147
|
+
before=before,
|
|
148
|
+
reason=after_reason or "Published index could not be reopened.",
|
|
149
|
+
elapsed_ms=_elapsed_ms(started),
|
|
150
|
+
command="arcgraph build",
|
|
151
|
+
)
|
|
152
|
+
return {
|
|
153
|
+
"schema_version": SCHEMA_VERSION,
|
|
154
|
+
"status": "available",
|
|
155
|
+
"action": result.get("status", "reindexed"),
|
|
156
|
+
"published": after.get("index_version") != before.get("index_version"),
|
|
157
|
+
"before_index_version": before.get("index_version"),
|
|
158
|
+
"index_version": after.get("index_version"),
|
|
159
|
+
"freshness": after.get("freshness", {}),
|
|
160
|
+
"changed": result.get("changed", {}),
|
|
161
|
+
"cleanup": prune_arcgraph_output(
|
|
162
|
+
output_dir,
|
|
163
|
+
keep_builds=DEFAULT_BUILD_RETENTION,
|
|
164
|
+
dry_run=True,
|
|
165
|
+
),
|
|
166
|
+
"elapsed_ms": _elapsed_ms(started),
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def watch_index(
|
|
171
|
+
*,
|
|
172
|
+
repo_root: Path,
|
|
173
|
+
output_dir: Path,
|
|
174
|
+
poll_interval_seconds: float = 0.25,
|
|
175
|
+
debounce_seconds: float = 0.5,
|
|
176
|
+
max_cycles: int | None = None,
|
|
177
|
+
stop_requested: Callable[[], bool] | None = None,
|
|
178
|
+
stop_reason: Callable[[], str] | None = None,
|
|
179
|
+
on_event: Callable[[dict[str, Any]], None] | None = None,
|
|
180
|
+
) -> dict[str, Any]:
|
|
181
|
+
"""Poll freshness and debounce explicit incremental publications."""
|
|
182
|
+
|
|
183
|
+
poll_interval_seconds = max(0.05, min(poll_interval_seconds, 5.0))
|
|
184
|
+
debounce_seconds = max(0.0, min(debounce_seconds, 10.0))
|
|
185
|
+
cycles = 0
|
|
186
|
+
stale_since: float | None = None
|
|
187
|
+
events: list[dict[str, Any]] = []
|
|
188
|
+
event_count = 0
|
|
189
|
+
stopped = "max_cycles"
|
|
190
|
+
stop_requested_fn = stop_requested
|
|
191
|
+
stop_reason_fn = stop_reason
|
|
192
|
+
|
|
193
|
+
def record_event(event: dict[str, Any]) -> None:
|
|
194
|
+
nonlocal event_count
|
|
195
|
+
public_event = dict(event)
|
|
196
|
+
public_event.pop("_exit_code", None)
|
|
197
|
+
event_count += 1
|
|
198
|
+
events.append(public_event)
|
|
199
|
+
if len(events) > 20:
|
|
200
|
+
del events[0]
|
|
201
|
+
if on_event is not None:
|
|
202
|
+
on_event(
|
|
203
|
+
{
|
|
204
|
+
"schema_version": SCHEMA_VERSION,
|
|
205
|
+
"type": "watch_event",
|
|
206
|
+
"event_index": event_count,
|
|
207
|
+
"event": public_event,
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
while max_cycles is None or cycles < max_cycles:
|
|
213
|
+
if stop_requested_fn is not None and stop_requested_fn():
|
|
214
|
+
stopped = (
|
|
215
|
+
stop_reason_fn() if stop_reason_fn is not None else "requested"
|
|
216
|
+
)
|
|
217
|
+
break
|
|
218
|
+
cycles += 1
|
|
219
|
+
current, reason = _current_status(output_dir)
|
|
220
|
+
if current is None:
|
|
221
|
+
record_event(
|
|
222
|
+
_sync_failure(
|
|
223
|
+
before=None,
|
|
224
|
+
reason=reason or "No current index exists.",
|
|
225
|
+
elapsed_ms=0,
|
|
226
|
+
command="arcgraph build",
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
stopped = "index_unavailable"
|
|
230
|
+
break
|
|
231
|
+
now = time.monotonic()
|
|
232
|
+
if current.get("freshness", {}).get("stale"):
|
|
233
|
+
stale_since = stale_since or now
|
|
234
|
+
if now - stale_since >= debounce_seconds:
|
|
235
|
+
event = sync_index(
|
|
236
|
+
repo_root=repo_root,
|
|
237
|
+
output_dir=output_dir,
|
|
238
|
+
if_stale=True,
|
|
239
|
+
)
|
|
240
|
+
record_event(event)
|
|
241
|
+
if event.get("status") == "partial":
|
|
242
|
+
stopped = "sync_failed"
|
|
243
|
+
break
|
|
244
|
+
stale_since = None
|
|
245
|
+
else:
|
|
246
|
+
stale_since = None
|
|
247
|
+
if max_cycles is None or cycles < max_cycles:
|
|
248
|
+
time.sleep(poll_interval_seconds)
|
|
249
|
+
except KeyboardInterrupt:
|
|
250
|
+
stopped = "keyboard_interrupt"
|
|
251
|
+
abnormal_stop = stopped in {"index_unavailable", "sync_failed"}
|
|
252
|
+
payload = {
|
|
253
|
+
"schema_version": SCHEMA_VERSION,
|
|
254
|
+
"status": "partial" if abnormal_stop else "stopped",
|
|
255
|
+
"action": "watched",
|
|
256
|
+
"cycles": cycles,
|
|
257
|
+
"poll_interval_seconds": poll_interval_seconds,
|
|
258
|
+
"debounce_seconds": debounce_seconds,
|
|
259
|
+
"events": events,
|
|
260
|
+
"event_summary": {
|
|
261
|
+
"total": event_count,
|
|
262
|
+
"returned": len(events),
|
|
263
|
+
"limit": 20,
|
|
264
|
+
"truncated": event_count > len(events),
|
|
265
|
+
"omitted": max(0, event_count - len(events)),
|
|
266
|
+
},
|
|
267
|
+
"cleanup_policy": {
|
|
268
|
+
"automatic_deletion": False,
|
|
269
|
+
"detail": "Watch publishes indexes but only reports dry-run cleanup candidates.",
|
|
270
|
+
},
|
|
271
|
+
"stopped": stopped,
|
|
272
|
+
}
|
|
273
|
+
if abnormal_stop:
|
|
274
|
+
payload["_exit_code"] = 1
|
|
275
|
+
return payload
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _sync_failure(
|
|
279
|
+
*,
|
|
280
|
+
before: dict[str, Any] | None,
|
|
281
|
+
reason: str,
|
|
282
|
+
elapsed_ms: int,
|
|
283
|
+
command: str,
|
|
284
|
+
) -> dict[str, Any]:
|
|
285
|
+
return {
|
|
286
|
+
"schema_version": SCHEMA_VERSION,
|
|
287
|
+
"status": "partial",
|
|
288
|
+
"action": "kept_previous_index",
|
|
289
|
+
"published": False,
|
|
290
|
+
"reason": reason,
|
|
291
|
+
"before_index_version": (before or {}).get("index_version"),
|
|
292
|
+
"index_version": (before or {}).get("index_version"),
|
|
293
|
+
"freshness": (before or {}).get("freshness", {}),
|
|
294
|
+
"recovery_action": {
|
|
295
|
+
"kind": "refresh_index",
|
|
296
|
+
"command": command,
|
|
297
|
+
"automatic": False,
|
|
298
|
+
},
|
|
299
|
+
"elapsed_ms": elapsed_ms,
|
|
300
|
+
"_exit_code": 1,
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _elapsed_ms(started: float) -> int:
|
|
305
|
+
return max(0, round((time.monotonic() - started) * 1000))
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def prune_output(
|
|
309
|
+
*,
|
|
310
|
+
output_dir: Path,
|
|
311
|
+
keep_builds: int = DEFAULT_BUILD_RETENTION,
|
|
312
|
+
include_input_artifacts: bool = False,
|
|
313
|
+
apply: bool = False,
|
|
314
|
+
) -> dict[str, Any]:
|
|
315
|
+
return prune_arcgraph_output(
|
|
316
|
+
output_dir,
|
|
317
|
+
keep_builds=keep_builds,
|
|
318
|
+
include_input_artifacts=include_input_artifacts,
|
|
319
|
+
dry_run=not apply,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _current_status(output_dir: Path) -> tuple[dict[str, Any] | None, str | None]:
|
|
324
|
+
try:
|
|
325
|
+
current = QueryEngine(output_dir).current()
|
|
326
|
+
except FileNotFoundError:
|
|
327
|
+
return None, "No current index exists."
|
|
328
|
+
except SchemaVersionError as exc:
|
|
329
|
+
return None, str(exc)
|
|
330
|
+
return current, None
|