engineering-platform 2.2.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 (130) hide show
  1. engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +32 -0
  2. engineering_platform/ENGINEERING_PLATFORM_VERSION.json +15 -0
  3. engineering_platform/__init__.py +1 -0
  4. engineering_platform/__main__.py +7 -0
  5. engineering_platform/agent_state.py +530 -0
  6. engineering_platform/agent_trust.py +174 -0
  7. engineering_platform/assets/dashboard.css +1317 -0
  8. engineering_platform/assets/dashboard.js +8534 -0
  9. engineering_platform/assets/dashboard_locales.mjs +4049 -0
  10. engineering_platform/assets/dashboard_status_store.mjs +41 -0
  11. engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  12. engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  13. engineering_platform/assets/operations-console/icon-dark.png +0 -0
  14. engineering_platform/assets/operations-console/icon-light.png +0 -0
  15. engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  16. engineering_platform/assets/operations-console/manifest.webmanifest +11 -0
  17. engineering_platform/capability_preflight.py +285 -0
  18. engineering_platform/capability_review.py +261 -0
  19. engineering_platform/central_data_transfer.py +195 -0
  20. engineering_platform/central_database.py +245 -0
  21. engineering_platform/central_store_migration.py +1672 -0
  22. engineering_platform/codex_capacity.py +81 -0
  23. engineering_platform/codex_chat.py +226 -0
  24. engineering_platform/codex_observability.py +153 -0
  25. engineering_platform/component_lock.py +40 -0
  26. engineering_platform/component_logging.py +420 -0
  27. engineering_platform/console_presentation.py +14 -0
  28. engineering_platform/console_route_ownership.py +83 -0
  29. engineering_platform/contracts/__init__.py +38 -0
  30. engineering_platform/contracts/ep_consumer.py +391 -0
  31. engineering_platform/contracts/models.py +105 -0
  32. engineering_platform/contracts/projection.py +401 -0
  33. engineering_platform/dashboard_browser_validation.py +206 -0
  34. engineering_platform/dashboard_state.py +630 -0
  35. engineering_platform/dashboard_supervisor.swift +105 -0
  36. engineering_platform/dashboard_translation.py +129 -0
  37. engineering_platform/dependabot_producer.py +349 -0
  38. engineering_platform/drift_diagnostics.py +144 -0
  39. engineering_platform/emergency_recovery.py +268 -0
  40. engineering_platform/engineering_memory.py +139 -0
  41. engineering_platform/ep_consumer_credentials.py +473 -0
  42. engineering_platform/evidence_projection.py +213 -0
  43. engineering_platform/execution_activity.py +218 -0
  44. engineering_platform/execution_context.py +132 -0
  45. engineering_platform/execution_errors.py +42 -0
  46. engineering_platform/execution_evidence.py +24 -0
  47. engineering_platform/execution_executor.py +730 -0
  48. engineering_platform/execution_finalization.py +44 -0
  49. engineering_platform/execution_host.py +3306 -0
  50. engineering_platform/execution_lease.py +365 -0
  51. engineering_platform/execution_lifecycle.py +447 -0
  52. engineering_platform/execution_models.py +43 -0
  53. engineering_platform/execution_readiness.py +166 -0
  54. engineering_platform/execution_reporting.py +1607 -0
  55. engineering_platform/execution_repository.py +253 -0
  56. engineering_platform/execution_timeout_policy.py +56 -0
  57. engineering_platform/execution_timing.py +440 -0
  58. engineering_platform/execution_transaction.py +28 -0
  59. engineering_platform/external_producer_binding.py +235 -0
  60. engineering_platform/file_inbox.py +249 -0
  61. engineering_platform/forensic_attribution.py +338 -0
  62. engineering_platform/forensic_attribution_v2.py +134 -0
  63. engineering_platform/forensic_delta.py +299 -0
  64. engineering_platform/golden_scenario.py +63 -0
  65. engineering_platform/historical_dashboard_configuration.py +171 -0
  66. engineering_platform/host_admin.py +199 -0
  67. engineering_platform/host_preflight.py +231 -0
  68. engineering_platform/installation_relocation.py +122 -0
  69. engineering_platform/investigation_ledger.py +89 -0
  70. engineering_platform/legacy_inbox_migration.py +79 -0
  71. engineering_platform/lifecycle_worker.py +223 -0
  72. engineering_platform/live_status.py +267 -0
  73. engineering_platform/local_api.py +209 -0
  74. engineering_platform/local_api_keychain.py +51 -0
  75. engineering_platform/local_repository_binding.py +138 -0
  76. engineering_platform/managed_autonomy.py +509 -0
  77. engineering_platform/managed_codex_runtime.py +105 -0
  78. engineering_platform/parity_context.py +203 -0
  79. engineering_platform/parity_lifecycle_dispatcher.py +488 -0
  80. engineering_platform/platform_admin.py +13 -0
  81. engineering_platform/platform_api.py +428 -0
  82. engineering_platform/platform_bootstrap.py +385 -0
  83. engineering_platform/platform_components.py +65 -0
  84. engineering_platform/platform_version.py +171 -0
  85. engineering_platform/pr_check_repair.py +276 -0
  86. engineering_platform/pr_evidence_backfill.py +278 -0
  87. engineering_platform/producer.py +209 -0
  88. engineering_platform/project_agent.py +366 -0
  89. engineering_platform/project_agent_service.py +244 -0
  90. engineering_platform/project_topology.py +126 -0
  91. engineering_platform/prompt_history.py +591 -0
  92. engineering_platform/provider_context.py +136 -0
  93. engineering_platform/provider_context_benchmark.py +41 -0
  94. engineering_platform/provider_context_scope.py +90 -0
  95. engineering_platform/provider_interruption.py +168 -0
  96. engineering_platform/provider_process_identity.py +80 -0
  97. engineering_platform/provider_readiness.py +138 -0
  98. engineering_platform/provider_recovery.py +647 -0
  99. engineering_platform/provider_usage.py +497 -0
  100. engineering_platform/providers.py +471 -0
  101. engineering_platform/qualification.py +220 -0
  102. engineering_platform/recommendation_handoff.py +238 -0
  103. engineering_platform/report_analysis.py +193 -0
  104. engineering_platform/repository_attachment.py +171 -0
  105. engineering_platform/repository_handoff.py +95 -0
  106. engineering_platform/resources.py +38 -0
  107. engineering_platform/reviewer_evidence.py +70 -0
  108. engineering_platform/schemas/repository-attachment.schema.json +61 -0
  109. engineering_platform/server.py +3679 -0
  110. engineering_platform/server_console_services.py +2024 -0
  111. engineering_platform/server_relay.py +172 -0
  112. engineering_platform/server_service.py +122 -0
  113. engineering_platform/status_model.py +135 -0
  114. engineering_platform/status_reconciliation.py +34 -0
  115. engineering_platform/storage.py +2440 -0
  116. engineering_platform/submission_cli.py +77 -0
  117. engineering_platform/submission_intake.py +45 -0
  118. engineering_platform/submission_service.py +317 -0
  119. engineering_platform/telemetry.py +951 -0
  120. engineering_platform/templates/workspace-config.json +25 -0
  121. engineering_platform/validation_identity.py +50 -0
  122. engineering_platform/validation_profile.py +211 -0
  123. engineering_platform/workspace_preflight.py +263 -0
  124. engineering_platform/worktree_provenance.py +147 -0
  125. engineering_platform/worktree_tooling.py +18 -0
  126. engineering_platform-2.2.0.dist-info/METADATA +18 -0
  127. engineering_platform-2.2.0.dist-info/RECORD +130 -0
  128. engineering_platform-2.2.0.dist-info/WHEEL +5 -0
  129. engineering_platform-2.2.0.dist-info/entry_points.txt +6 -0
  130. engineering_platform-2.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,630 @@
1
+ """Read-only state projections used by the Engineering Status dashboard.
2
+
3
+ This module deliberately has no HTTP concerns. The dashboard façade supplies
4
+ the small repository-specific readers, which keeps state composition testable
5
+ without giving it lifecycle or transaction authority.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ from collections.abc import Callable
13
+ from pathlib import Path
14
+ from typing import Any
15
+ from .host_preflight import latest as latest_host_preflight
16
+ from .workspace_preflight import latest as latest_workspace_preflight
17
+ from .capability_preflight import latest as latest_capability_preflight
18
+ from .drift_diagnostics import guidance as drift_guidance
19
+ from .platform_api import PlatformConfigurationError, execution_host_configuration
20
+ from .telemetry import comparable_duration_estimate
21
+ from .storage import EngineeringStorageError, import_legacy_projection_once, is_active_blocking_predecessor, load_execution_context_snapshot, load_forge_governance_handoff_snapshot, load_projection, load_readiness_evaluation, open_storage
22
+ from .execution_lease import liveness as lease_liveness
23
+ from .execution_lifecycle import projection as lifecycle_projection
24
+ from .agent_state import redact_diagnostic
25
+
26
+
27
+ JsonReader = Callable[[Path], bytes]
28
+ RunJsonReader = Callable[[Path, str | None], bytes]
29
+ TERMINAL_PHASES = frozenset({"COMPLETE", "BLOCKED", "FAILED"})
30
+
31
+
32
+ def _successful_reviewer_agents(value: object) -> list[dict[str, object]]:
33
+ """Expose only a wholly successful review beyond its live phase."""
34
+ if not isinstance(value, list):
35
+ return []
36
+ reviewers = [item for item in value if isinstance(item, dict)]
37
+ if not reviewers or len(reviewers) != len(value):
38
+ return []
39
+ return reviewers if all(item.get("status") == "completed" for item in reviewers) else []
40
+
41
+
42
+ def _active_runner_checkpoint(root: Path) -> tuple[dict[str, object], dict[str, object]] | None:
43
+ """Return a current checkpoint only while its recorded runner group exists.
44
+
45
+ The watcher intentionally detaches while a managed execution is running.
46
+ Its last status publication can therefore lag the runner. The runner's
47
+ atomic checkpoint is safe to present only when the exact recorded process
48
+ group is still alive; a status file by itself never establishes liveness.
49
+ """
50
+ try:
51
+ current = json.loads((root / ".engineering" / "status" / "current.json").read_text(encoding="utf-8"))
52
+ runner = json.loads((root / ".engineering" / "status" / "runner_process.json").read_text(encoding="utf-8"))
53
+ except (OSError, json.JSONDecodeError):
54
+ return None
55
+ run_id, phase = current.get("run_id"), current.get("phase")
56
+ pid, process_group = runner.get("pid"), runner.get("process_group")
57
+ if (
58
+ not isinstance(run_id, str)
59
+ or not run_id
60
+ or not isinstance(phase, str)
61
+ or phase in TERMINAL_PHASES
62
+ or runner.get("run_id") != run_id
63
+ or not isinstance(pid, int)
64
+ or pid <= 0
65
+ or not isinstance(process_group, int)
66
+ or process_group <= 0
67
+ ):
68
+ return None
69
+ try:
70
+ if os.getpgid(pid) != process_group:
71
+ return None
72
+ os.killpg(process_group, 0)
73
+ except OSError:
74
+ return None
75
+ return current, {
76
+ "state": "LIVE",
77
+ "source": "RUNNER_PROCESS",
78
+ "runner_pid": pid,
79
+ "process_group": process_group,
80
+ }
81
+
82
+
83
+ def _active_prompt_metadata(root: Path, run_id: object) -> tuple[str | None, str | None]:
84
+ """Return bounded title-only prompt context for the active run.
85
+
86
+ The watcher normally owns these fields. A restart can leave an older run
87
+ with only its durable transaction checkpoint, so recover just the first
88
+ Markdown H1 and filename for the operator hand-off. Never expose prompt
89
+ body text through the status projection.
90
+ """
91
+ if not isinstance(run_id, str) or not run_id:
92
+ return None, None
93
+ try:
94
+ connection = open_storage(root, create=False)
95
+ try:
96
+ row = connection.execute(
97
+ "SELECT payload FROM engineering_transactions WHERE run_id=?", (run_id,)
98
+ ).fetchone()
99
+ finally:
100
+ connection.close()
101
+ checkpoint = json.loads(row[0]) if row and isinstance(row[0], str) else {}
102
+ prompt_path = checkpoint.get("prompt_path") if isinstance(checkpoint, dict) else None
103
+ if not isinstance(prompt_path, str) or not prompt_path:
104
+ return None, None
105
+ path = Path(prompt_path)
106
+ filename = redact_diagnostic(path.name, limit=240) or None
107
+ with path.open(encoding="utf-8") as prompt:
108
+ for _ in range(512):
109
+ line = prompt.readline()
110
+ if not line:
111
+ break
112
+ if line.startswith("# ") and line[2:].strip():
113
+ return filename, redact_diagnostic(line[2:].strip(), limit=240) or filename
114
+ return filename, filename
115
+ except (EngineeringStorageError, OSError, UnicodeDecodeError, json.JSONDecodeError):
116
+ return None, None
117
+
118
+
119
+ def _transient_live_action(root: Path, run_id: object) -> str | None:
120
+ """Read the non-persistent current action title for its owning live run."""
121
+ if not isinstance(run_id, str):
122
+ return None
123
+ try:
124
+ current = json.loads((root / ".engineering" / "status" / "current.json").read_text(encoding="utf-8"))
125
+ except (OSError, json.JSONDecodeError):
126
+ return None
127
+ action = current.get("transient_action") if current.get("run_id") == run_id else None
128
+ return action if isinstance(action, str) and 4 <= len(action) <= 160 else None
129
+
130
+
131
+ def _terminal_checkpoint(root: Path, run_id: object) -> bool:
132
+ """Return whether a live-status run has already reached a terminal checkpoint.
133
+
134
+ ``current.json`` is written by the runner and can briefly outlive its terminal
135
+ checkpoint. It must therefore never keep a completed execution visible as
136
+ an active dashboard prompt.
137
+ """
138
+ if not isinstance(run_id, str):
139
+ return False
140
+ try:
141
+ connection = open_storage(root)
142
+ try:
143
+ row = connection.execute(
144
+ "SELECT phase FROM engineering_transactions WHERE run_id=?", (run_id,)
145
+ ).fetchone()
146
+ finally:
147
+ connection.close()
148
+ except EngineeringStorageError:
149
+ return False
150
+ if row:
151
+ return row[0] in TERMINAL_PHASES
152
+ # Narrow compatibility window for a terminal pre-v12 runner that did not
153
+ # contain enough fields to be promoted during the one-time migration.
154
+ try:
155
+ checkpoint = json.loads(
156
+ (root / ".engineering" / "engineering-runs" / f"{run_id}.json").read_text(encoding="utf-8")
157
+ )
158
+ except (OSError, json.JSONDecodeError):
159
+ return False
160
+ return isinstance(checkpoint, dict) and checkpoint.get("phase") in TERMINAL_PHASES
161
+
162
+
163
+ def _watcher_has_terminal_run(watcher: object, run_id: object) -> bool:
164
+ """Return whether the watcher has already closed the live run."""
165
+ return (
166
+ isinstance(watcher, dict)
167
+ and isinstance(run_id, str)
168
+ and watcher.get("last_executed_run") == run_id
169
+ and watcher.get("last_executed_phase") in TERMINAL_PHASES
170
+ )
171
+
172
+
173
+ def _watcher_lags_live_phase(
174
+ watcher: object, live: object, lifecycle: object,
175
+ ) -> bool:
176
+ """Return whether an old implementation-merge wait masks later progress.
177
+
178
+ The watcher can retain its last operator-merge publication while the
179
+ resumed Execution Host has already persisted a later phase for the same
180
+ run: finalization, bounded validation repair, or cleanup. That is not
181
+ another merge wait. Keep the later lifecycle visible even when the host
182
+ lease has subsequently gone stale, so the operator sees the durable state
183
+ and its ownership warning instead of an obsolete PR hand-off.
184
+ """
185
+ return (
186
+ isinstance(watcher, dict)
187
+ and isinstance(live, dict)
188
+ and watcher.get("run_id") == live.get("run_id")
189
+ and watcher.get("watcher_state") == "WAITING_FOR_OPERATOR_MERGE"
190
+ and watcher.get("current_phase") == "WAIT_FOR_OPERATOR_MERGE"
191
+ and isinstance(lifecycle, dict)
192
+ and lifecycle.get("current_step") in {
193
+ "INITIALIZE", "CAPABILITY_REVIEW", "EXECUTE_AGENT", "REPAIR_AGENT", "FINALIZATION_REPAIR_AGENT", "FINALIZE_AGENT", "RECONCILE_AGENT", "REPOSITORY_CLEANUP",
194
+ }
195
+ )
196
+
197
+
198
+ def _is_operator_merge_wait(live: object, lifecycle: object) -> bool:
199
+ """Keep the durable PR hand-off visible during internal check polling.
200
+
201
+ ``WAIT_FOR_TERMINAL_EVIDENCE`` is an implementation detail used while an
202
+ open implementation PR is polled. Its lifecycle projection deliberately
203
+ presents that interval as ``WAIT_FOR_OPERATOR_MERGE``. The dashboard
204
+ status must use the same presentation phase even when a short-lived live
205
+ lease wins over the watcher projection; otherwise the operator's PR
206
+ controls flicker away between polling updates.
207
+ """
208
+ if not isinstance(live, dict) or not isinstance(lifecycle, dict):
209
+ return False
210
+ phase = live.get("phase")
211
+ if phase == "WAIT_FOR_OPERATOR_MERGE":
212
+ return lifecycle.get("current_step") in {
213
+ "WAIT_FOR_OPERATOR_MERGE", "WAIT_FOR_FINALIZATION_MERGE", "WAIT_FOR_RECONCILIATION_MERGE",
214
+ }
215
+ return (
216
+ phase == "WAIT_FOR_TERMINAL_EVIDENCE"
217
+ and lifecycle.get("current_step") in {"WAIT_FOR_OPERATOR_MERGE", "WAIT_FOR_FINALIZATION_MERGE", "WAIT_FOR_RECONCILIATION_MERGE"}
218
+ and isinstance(live.get("pull_request"), int)
219
+ and not isinstance(live.get("pull_request"), bool)
220
+ and live["pull_request"] > 0
221
+ )
222
+
223
+
224
+ def _has_verified_merge_continuation(watcher: object, live: object, lifecycle: object) -> bool:
225
+ """Return whether a proven merge has already scheduled its visible next step."""
226
+ return (
227
+ isinstance(watcher, dict)
228
+ and isinstance(live, dict)
229
+ and isinstance(lifecycle, dict)
230
+ and watcher.get("watcher_state") == "ENGINEERING_RUN_ACTIVE"
231
+ and watcher.get("run_id") == live.get("run_id")
232
+ and watcher.get("current_phase") == lifecycle.get("current_step")
233
+ and watcher.get("current_phase") in {"FINALIZE_AGENT", "RECONCILE_AGENT"}
234
+ and watcher.get("current_action") in {
235
+ "create_finalization", "reconcile_rolling_records_on_main",
236
+ }
237
+ )
238
+
239
+
240
+ def unavailable_status() -> bytes:
241
+ """Return the complete, safe status shape when no projection exists yet."""
242
+ return json.dumps(
243
+ {
244
+ "watcher_state": "REMOTE_ENGINEERING_DEGRADED",
245
+ "current_phase": "status niet beschikbaar",
246
+ "current_action": "Voer het Engineering Platform uit om een statusupdate te publiceren.",
247
+ "run_id": None,
248
+ "queue_depth": 0,
249
+ "queue_items": [],
250
+ "implementation_pr": None,
251
+ "finalization_pr": None,
252
+ "reconciliation_pr": None,
253
+ "repository_state": "UNKNOWN",
254
+ "workspace_state": "UNKNOWN",
255
+ "diagnostic": "Er is nog geen lokale engineeringstatus gepubliceerd.",
256
+ "submitted_filename": None,
257
+ "prompt_title": None,
258
+ "last_executed_filename": None,
259
+ "last_executed_title": None,
260
+ "last_executed_run": None,
261
+ "last_executed_phase": None,
262
+ "blocking_predecessor_run": None,
263
+ "blocking_predecessor_phase": None,
264
+ "blocking_predecessor_filename": None,
265
+ "blocking_predecessor_title": None,
266
+ "predecessor_recovery_action": None,
267
+ },
268
+ separators=(",", ":"),
269
+ ).encode()
270
+
271
+
272
+ def status(root: Path) -> bytes:
273
+ """Project watcher and live-run state into the stable dashboard contract."""
274
+ try:
275
+ watcher = load_projection(root, "watcher_status")
276
+ live = load_projection(root, "live_status")
277
+ # One explicit compatibility migration supports upgraded hosts where
278
+ # status files predate the canonical store. It is not a normal read
279
+ # path once the row has been imported.
280
+ if watcher is None:
281
+ watcher = import_legacy_projection_once(
282
+ root, "watcher_status", root / ".engineering" / "status" / "status.json"
283
+ )
284
+ if live is None:
285
+ live = import_legacy_projection_once(
286
+ root, "live_status", root / ".engineering" / "status" / "current.json"
287
+ )
288
+ runner_checkpoint = _active_runner_checkpoint(root)
289
+ if runner_checkpoint is not None:
290
+ # A detached watcher can retain RUNNER_STARTING while the exact
291
+ # Execution Host process group continues the run. The fresh runner
292
+ # checkpoint is then the authoritative dashboard run projection.
293
+ live, runner_liveness = runner_checkpoint
294
+ else:
295
+ runner_liveness = None
296
+ watcher = watcher or {}
297
+ # The dashboard is a read model, but it must not repeat a stale
298
+ # compatibility projection after SQLite has recorded dismissal. The
299
+ # watcher persists the same reconciliation on its next publication.
300
+ predecessor_run = watcher.get("blocking_predecessor_run")
301
+ if (
302
+ watcher.get("watcher_state") == "WAITING_FOR_PREDECESSOR"
303
+ and isinstance(predecessor_run, str)
304
+ and predecessor_run
305
+ and not is_active_blocking_predecessor(
306
+ root, predecessor_run, watcher.get("blocking_predecessor_phase"),
307
+ )
308
+ ):
309
+ watcher = {
310
+ **watcher,
311
+ "watcher_state": "WATCHER_IDLE",
312
+ "current_phase": None,
313
+ "current_action": "Execution Host Idle",
314
+ "blocking_predecessor_run": None,
315
+ "blocking_predecessor_phase": None,
316
+ "blocking_predecessor_filename": None,
317
+ "blocking_predecessor_title": None,
318
+ "predecessor_recovery_action": None,
319
+ }
320
+ # A watcher publication from before predecessor projection was
321
+ # introduced can still say WATCHER_IDLE while its undismissed terminal
322
+ # execution would hold every later Inbox submission. The dashboard is
323
+ # read-only, so normalize that misleading legacy projection here until
324
+ # the watcher publishes the same state on its next cycle.
325
+ if (
326
+ watcher.get("watcher_state") == "WATCHER_IDLE"
327
+ and is_active_blocking_predecessor(
328
+ root, watcher.get("last_executed_run"), watcher.get("last_executed_phase"),
329
+ )
330
+ ):
331
+ predecessor_run = watcher["last_executed_run"]
332
+ watcher = {
333
+ **watcher,
334
+ "watcher_state": "WAITING_FOR_PREDECESSOR",
335
+ "current_phase": "WAITING_FOR_PREDECESSOR",
336
+ "current_action": "Wachtrij gepauzeerd tot de voorafgaande prompt is hersteld.",
337
+ "blocking_predecessor_run": predecessor_run,
338
+ "blocking_predecessor_phase": watcher.get("last_executed_phase"),
339
+ "blocking_predecessor_filename": watcher.get("last_executed_filename"),
340
+ "blocking_predecessor_title": watcher.get("last_executed_title"),
341
+ "predecessor_recovery_action": (
342
+ "Herstel de geblokkeerde prompt of dien die bewust opnieuw in met een eigen regel "
343
+ f"`Retry-Of: {predecessor_run}`. De wachtrij blijft gepauzeerd totdat deze herindiening voltooid is."
344
+ ),
345
+ }
346
+ except EngineeringStorageError:
347
+ watcher = {}
348
+ live = None
349
+ try:
350
+ if live is None:
351
+ raise ValueError("No canonical live status")
352
+ live_liveness = lease_liveness(root, live.get("run_id"))
353
+ if runner_liveness is not None and runner_liveness.get("state") == "LIVE":
354
+ live_liveness = {**live_liveness, **runner_liveness}
355
+ transient_action = _transient_live_action(root, live.get("run_id"))
356
+ lifecycle = lifecycle_projection(root, live.get("run_id"))
357
+ if isinstance(lifecycle, dict) and transient_action:
358
+ # Ephemeral, redacted CLI progress is presentation-only. It is
359
+ # deliberately not persisted in lifecycle, reports or telemetry.
360
+ lifecycle["live_activity"] = transient_action
361
+ fallback_filename, fallback_prompt_title = _active_prompt_metadata(root, live.get("run_id"))
362
+ projection = json.dumps(
363
+ {
364
+ "watcher_state": "ENGINEERING_RUN_ACTIVE",
365
+ "platform_version": watcher.get("platform_version"),
366
+ "current_phase": live.get("phase") or "INITIALIZE",
367
+ "current_action": transient_action or live.get("current_action") or "Engineeringuitvoering is actief.",
368
+ "run_id": live.get("run_id"),
369
+ # The watcher owns the queue. A live runner only adds current
370
+ # execution details, so it must not replace the queued count.
371
+ "queue_depth": watcher.get("queue_depth", len(watcher.get("queue_items", []))),
372
+ "queue_items": watcher.get("queue_items", []),
373
+ "implementation_pr": live.get("implementation_pr"),
374
+ "finalization_pr": live.get("finalization_pr"),
375
+ "reconciliation_pr": live.get("reconciliation_pr"),
376
+ "pull_request": live.get("pull_request"),
377
+ "waiting_for_merge_since": live.get("waiting_for_merge_since"),
378
+ "repository_state": live.get("repository_state") or "ACTIVE",
379
+ "workspace_state": live.get("workspace_state") or "ACTIVE",
380
+ "prompt_characters": live.get("prompt_characters"),
381
+ "diagnostic": live.get("diagnostic"),
382
+ "submitted_filename": watcher.get("submitted_filename") or fallback_filename,
383
+ "prompt_title": watcher.get("prompt_title") or fallback_prompt_title,
384
+ "last_executed_filename": watcher.get("last_executed_filename"),
385
+ "last_executed_title": watcher.get("last_executed_title"),
386
+ "last_executed_run": watcher.get("last_executed_run"),
387
+ "last_executed_phase": watcher.get("last_executed_phase"),
388
+ "blocking_predecessor_run": watcher.get("blocking_predecessor_run"),
389
+ "blocking_predecessor_phase": watcher.get("blocking_predecessor_phase"),
390
+ "blocking_predecessor_filename": watcher.get("blocking_predecessor_filename"),
391
+ "blocking_predecessor_title": watcher.get("blocking_predecessor_title"),
392
+ "predecessor_recovery_action": watcher.get("predecessor_recovery_action"),
393
+ "execution_mode": live.get("execution_mode"),
394
+ "target_repository": live.get("target_repository"),
395
+ "checkout_path": live.get("checkout_path"),
396
+ "active_branch": live.get("active_branch"),
397
+ # Only a wholly successful specialist review survives its
398
+ # live phase as historical evidence for this active run. A
399
+ # partial, failed or stale reviewer projection remains hidden.
400
+ "reviewer_agents": (
401
+ live.get("reviewer_agents", [])
402
+ if live.get("phase") == "CAPABILITY_REVIEW"
403
+ else _successful_reviewer_agents(live.get("reviewer_agents"))
404
+ ),
405
+ "runtime_metadata": live.get("runtime_metadata", {}),
406
+ "workspace_progress": live.get("workspace_progress"),
407
+ "execution_liveness": live_liveness,
408
+ "readiness": load_readiness_evaluation(root, live.get("run_id")),
409
+ # The dashboard consumes only the immutable context snapshot
410
+ # linked to this run; legacy/current prompt projections never
411
+ # become an Execution Context source.
412
+ "execution_context": load_execution_context_snapshot(root, str(live.get("run_id"))),
413
+ "forge_governance_handoff": load_forge_governance_handoff_snapshot(root, str(live.get("run_id"))),
414
+ "lifecycle": lifecycle,
415
+ },
416
+ separators=(",", ":"),
417
+ ).encode()
418
+ except (ValueError, TypeError):
419
+ live, projection, lifecycle = None, None, None
420
+ if live and _has_verified_merge_continuation(watcher, live, lifecycle):
421
+ continuation_projection = json.loads(projection or b"{}")
422
+ continuation_projection.update(
423
+ {
424
+ "watcher_state": watcher["watcher_state"],
425
+ "current_phase": watcher["current_phase"],
426
+ "current_action": watcher["current_action"],
427
+ }
428
+ )
429
+ return json.dumps(continuation_projection, separators=(",", ":")).encode()
430
+ if (
431
+ live
432
+ and _is_operator_merge_wait(live, lifecycle)
433
+ and not _terminal_checkpoint(root, live.get("run_id"))
434
+ ):
435
+ waiting_projection = json.loads(projection or b"{}")
436
+ waiting_projection.update(
437
+ {
438
+ "watcher_state": "WAITING_FOR_OPERATOR_MERGE",
439
+ "current_phase": "WAIT_FOR_OPERATOR_MERGE",
440
+ "current_action": "Waiting for the operator to merge the pull request.",
441
+ "pull_request": live.get("pull_request"),
442
+ "waiting_for_merge_since": live.get("waiting_for_merge_since"),
443
+ }
444
+ )
445
+ return json.dumps(waiting_projection, separators=(",", ":")).encode()
446
+ if (
447
+ live
448
+ and live.get("phase") not in TERMINAL_PHASES
449
+ and live_liveness.get("state") != "LIVE"
450
+ and not _terminal_checkpoint(root, live.get("run_id"))
451
+ and (
452
+ not watcher
453
+ or watcher.get("watcher_state") == "WATCHER_IDLE"
454
+ or watcher.get("run_id") == live.get("run_id")
455
+ or _watcher_lags_live_phase(watcher, live, lifecycle)
456
+ )
457
+ ):
458
+ # Lifecycle is intentionally retained for auditability, but a stale
459
+ # lease must never be presented as an actively running execution.
460
+ stale_projection = json.loads(projection or b"{}")
461
+ reconciliation = live_liveness.get("reconciliation_outcome")
462
+ recovery = (
463
+ "RESUME_AVAILABLE"
464
+ if reconciliation == "RECOVERABLE"
465
+ else "TERMINAL_EVIDENCE_RECONCILIATION"
466
+ if reconciliation == "TERMINAL_EVIDENCE_PRESENT"
467
+ else "OPERATOR_INTERVENTION_REQUIRED"
468
+ )
469
+ stale_projection.update(
470
+ {
471
+ "watcher_state": "ENGINEERING_RUN_STALE",
472
+ # The lifecycle is the canonical presentation mapping for
473
+ # internal polling. In particular, a finalization PR's check
474
+ # polling must never be labelled as the older implementation
475
+ # merge hand-off.
476
+ "current_phase": lifecycle.get("current_step") or live.get("phase"),
477
+ "current_action": "Execution Host ownership is stale; no execution is currently running.",
478
+ "recovery_action": recovery,
479
+ }
480
+ )
481
+ return json.dumps(stale_projection, separators=(",", ":")).encode()
482
+ if (
483
+ live
484
+ and live.get("phase") not in TERMINAL_PHASES
485
+ and live_liveness.get("state") == "LIVE"
486
+ and not _terminal_checkpoint(root, live.get("run_id"))
487
+ and not _watcher_has_terminal_run(watcher, live.get("run_id"))
488
+ ):
489
+ # A watcher can already be idle after it has detached a runner. A
490
+ # confirmed live lease is authoritative for the active execution and
491
+ # must not be hidden by that older watcher projection.
492
+ return projection
493
+ if watcher:
494
+ # A queued prompt can be held before it receives its own run ID when
495
+ # its predecessor is terminally blocked. Keep that predecessor's
496
+ # persisted lifecycle visible in the operational card so the operator
497
+ # can see the exact blocking flow, without misrepresenting it as a
498
+ # live execution of the queued prompt.
499
+ predecessor_run = watcher.get("blocking_predecessor_run")
500
+ if (
501
+ watcher.get("watcher_state") == "WAITING_FOR_PREDECESSOR"
502
+ and isinstance(predecessor_run, str)
503
+ and predecessor_run
504
+ ):
505
+ watcher = dict(watcher)
506
+ lifecycle = dict(lifecycle_projection(root, predecessor_run))
507
+ # Recovery belongs to the predecessor detail view. The queue wait
508
+ # card only presents its immutable lifecycle evidence.
509
+ lifecycle["recovery"] = None
510
+ watcher["lifecycle"] = lifecycle
511
+ return json.dumps(watcher, separators=(",", ":")).encode()
512
+ return projection or unavailable_status()
513
+
514
+
515
+ def sse_status(root: Path) -> bytes:
516
+ """Encode the status as a single SSE data line."""
517
+ try:
518
+ payload = json.loads(status(root))
519
+ except json.JSONDecodeError:
520
+ payload = json.loads(unavailable_status())
521
+ return json.dumps(payload, separators=(",", ":")).encode()
522
+
523
+
524
+ def snapshot(
525
+ root: Path,
526
+ *,
527
+ status_reader: JsonReader,
528
+ unavailable_reader: Callable[[], bytes],
529
+ prompt_started_reader: JsonReader,
530
+ usage_reader: JsonReader,
531
+ rate_limits_reader: Callable[[], bytes],
532
+ usage_for_run_reader: RunJsonReader,
533
+ completion_commits_reader: JsonReader,
534
+ last_executed_commits_reader: JsonReader,
535
+ reviewer_agents_reader: RunJsonReader,
536
+ execution_reader: RunJsonReader,
537
+ runtime_metadata_reader: RunJsonReader,
538
+ report_analysis_available_reader: Callable[[Path, str | None], bool],
539
+ telemetry_reader: Callable[[Path], list[dict[str, Any]]],
540
+ process_metrics_reader: Callable[[], bytes],
541
+ build_commit_reader: Callable[[Path], str],
542
+ component_log_versions_reader: Callable[[Path], dict[str, str]],
543
+ dashboard_version: str,
544
+ worker_version: str,
545
+ ) -> bytes:
546
+ """Compose one complete read-only dashboard snapshot from small readers."""
547
+ def read_json(reader: Callable[..., bytes], *args: object, fallback: Any) -> Any:
548
+ try:
549
+ return json.loads(reader(*args))
550
+ except json.JSONDecodeError:
551
+ return fallback
552
+
553
+ status_payload = read_json(status_reader, root, fallback=None)
554
+ if not isinstance(status_payload, dict):
555
+ status_payload = read_json(unavailable_reader, fallback={})
556
+ run_id = status_payload.get("last_executed_run")
557
+ active_run_id = status_payload.get("run_id")
558
+ active_liveness = lease_liveness(root, active_run_id)
559
+ active = (
560
+ status_payload.get("watcher_state") == "ENGINEERING_RUN_ACTIVE"
561
+ and isinstance(active_run_id, str)
562
+ and active_liveness.get("state") == "LIVE"
563
+ )
564
+ try:
565
+ telemetry = telemetry_reader(root)
566
+ except Exception:
567
+ telemetry = []
568
+ try:
569
+ duration_estimate = (
570
+ comparable_duration_estimate(
571
+ root,
572
+ prompt_characters=status_payload.get("prompt_characters"),
573
+ runtime_metadata=status_payload.get("runtime_metadata"),
574
+ run_id=active_run_id,
575
+ current_phase=status_payload.get("current_phase"),
576
+ execution_mode=status_payload.get("execution_mode"),
577
+ )
578
+ if active
579
+ else {}
580
+ )
581
+ except Exception:
582
+ duration_estimate = {}
583
+ try:
584
+ identity = execution_host_configuration(root).resolve_execution_host_identity()
585
+ execution_host = {
586
+ "name": identity.name,
587
+ "version": identity.version,
588
+ "runtime": identity.runtime,
589
+ "runtime_prompt_transport": identity.runtime_prompt_transport,
590
+ }
591
+ except PlatformConfigurationError:
592
+ execution_host = {}
593
+ host_preflight = latest_host_preflight(root)
594
+ workspace_preflight = latest_workspace_preflight(root)
595
+ capability_preflight = latest_capability_preflight(root)
596
+ # A successful preflight supersedes any evidence it may have replaced on
597
+ # disk. Only unresolved checks belong in the current-drift projection.
598
+ current_drift = next((
599
+ item for preflight in (host_preflight, workspace_preflight, capability_preflight)
600
+ if str(preflight.get("outcome", "")).upper() != "PASS"
601
+ for item in preflight.get("drift_evidence", []) if isinstance(item, dict)
602
+ ), None)
603
+ return json.dumps(
604
+ {
605
+ "status": status_payload,
606
+ "build_commit": build_commit_reader(root),
607
+ "prompt_started": read_json(prompt_started_reader, root, fallback={}),
608
+ "usage": read_json(usage_reader, root, fallback={}),
609
+ "rate_limits": read_json(rate_limits_reader, fallback={}),
610
+ "last_executed_usage": read_json(usage_for_run_reader, root, run_id, fallback={}),
611
+ "completion_commits": read_json(completion_commits_reader, root, fallback={}),
612
+ "last_executed_commits": read_json(last_executed_commits_reader, root, fallback={}),
613
+ "last_executed_reviewer_agents": read_json(reviewer_agents_reader, root, run_id, fallback=[]),
614
+ "last_executed_execution": read_json(execution_reader, root, run_id, fallback={}),
615
+ "last_executed_runtime_metadata": read_json(runtime_metadata_reader, root, run_id, fallback={}),
616
+ "last_executed_report_analysis_available": report_analysis_available_reader(root, run_id),
617
+ "telemetry": telemetry,
618
+ "duration_estimate": duration_estimate,
619
+ "process_metrics": read_json(process_metrics_reader, root, fallback={}) if active else {},
620
+ "component_log_versions": component_log_versions_reader(root),
621
+ "component_versions": {"dashboard": dashboard_version, "worker": worker_version},
622
+ "host_preflight": host_preflight,
623
+ "workspace_preflight": workspace_preflight,
624
+ "capability_preflight": capability_preflight,
625
+ "current_drift": current_drift or {},
626
+ "resume_guidance": drift_guidance([current_drift] if current_drift else []),
627
+ "execution_host": execution_host,
628
+ },
629
+ separators=(",", ":"),
630
+ ).encode()