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,401 @@
1
+ """Deterministic, read-only projections from canonical EP evidence.
2
+
3
+ The module intentionally opens SQLite in read-only mode. It does not invoke
4
+ Git, GitHub, providers, lifecycle transitions, migrations, or action execution.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from datetime import datetime, timezone
10
+ import hashlib
11
+ import json
12
+ from pathlib import Path
13
+ import re
14
+ import sqlite3
15
+
16
+ from .models import (
17
+ ActionPolicyDecision,
18
+ AllowedAction,
19
+ CONTRACT_VERSION,
20
+ ContractVersionError,
21
+ EvidenceReference,
22
+ require_compatible_version,
23
+ )
24
+ from ..storage import EngineeringStorageError, database_path
25
+
26
+
27
+ UNAVAILABLE = "UNAVAILABLE"
28
+ PROJECTION_AUTHORITY = "DERIVED_FROM_CANONICAL_EVIDENCE"
29
+ POLICY_VERSION = "1.0"
30
+ _SAFE_OBJECTIVE_KEYS = frozenset({"objective_summary", "scope_summary", "constraints", "acceptance_summary", "prohibited_changes_summary"})
31
+ _UNSAFE_OBJECTIVE_TEXT = re.compile(
32
+ r"(?i)(?:\b(?:api[_ -]?key|access[_ -]?token|refresh[_ -]?token|secret|cookie|authorization|password)\b|\bbearer\b|(?:^|\s)/(?:\S+)|\b[a-z]:[\\/])"
33
+ )
34
+ _READ_ACTIONS = (
35
+ ("run.inspect.context", "run.inspect.*", "READ_CANONICAL_EVIDENCE"),
36
+ ("delivery.inspect.status", "delivery.inspect.*", "READ_DELIVERY_EVIDENCE"),
37
+ ("repository.inspect.state", "repository.inspect.*", "READ_REPOSITORY_EVIDENCE"),
38
+ ("workspace.inspect.state", "workspace.inspect.*", "READ_WORKSPACE_EVIDENCE"),
39
+ )
40
+
41
+
42
+ def _now() -> str:
43
+ return datetime.now(timezone.utc).isoformat()
44
+
45
+
46
+ def _readonly_connection(root: Path) -> sqlite3.Connection:
47
+ path = database_path(root)
48
+ if not path.is_file():
49
+ raise EngineeringStorageError("Engineering storage is unavailable.")
50
+ connection = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
51
+ connection.row_factory = sqlite3.Row
52
+ return connection
53
+
54
+
55
+ def _json_object(value: object) -> dict[str, object]:
56
+ try:
57
+ parsed = json.loads(value) if isinstance(value, str) else {}
58
+ except json.JSONDecodeError:
59
+ return {}
60
+ return parsed if isinstance(parsed, dict) else {}
61
+
62
+
63
+ def _value(value: object) -> object:
64
+ return value if value is not None else UNAVAILABLE
65
+
66
+
67
+ def _safe_objective(metadata: object) -> dict[str, object]:
68
+ raw = _json_object(metadata)
69
+ result: dict[str, object] = {}
70
+ for key in _SAFE_OBJECTIVE_KEYS:
71
+ value = raw.get(key)
72
+ if isinstance(value, str) and value and len(value) <= 500 and "\n" not in value and not _UNSAFE_OBJECTIVE_TEXT.search(value):
73
+ result[key] = value
74
+ elif isinstance(value, list) and len(value) <= 12 and all(isinstance(item, str) and len(item) <= 160 and "\n" not in item and not _UNSAFE_OBJECTIVE_TEXT.search(item) for item in value):
75
+ result[key] = value
76
+ else:
77
+ result[key] = UNAVAILABLE
78
+ return result
79
+
80
+
81
+ def _snapshot_id(payload: dict[str, object]) -> str:
82
+ encoded = json.dumps(payload, sort_keys=True, separators=(",", ":"), default=str).encode()
83
+ return f"snapshot:sha256:{hashlib.sha256(encoded).hexdigest()}"
84
+
85
+
86
+ def _reference(source_type: str, subject: str, observed_at: object, snapshot: str, code: str, freshness: str = "CURRENT") -> dict[str, object]:
87
+ identity = hashlib.sha256(f"{source_type}:{subject}:{snapshot}".encode()).hexdigest()[:24]
88
+ return EvidenceReference(
89
+ id=f"evidence:{identity}", source_type=source_type,
90
+ authority="CANONICAL_EP_EVIDENCE", observed_at=str(_value(observed_at)),
91
+ freshness=freshness, subject=subject, snapshot_identity=snapshot,
92
+ safe_summary_code=code,
93
+ ).to_dict()
94
+
95
+
96
+ def _current_checks(connection: sqlite3.Connection, run_id: str) -> dict[str, dict[str, object]]:
97
+ try:
98
+ rows = connection.execute(
99
+ "SELECT id,pr_number,pr_role,pr_state,merge_state,merge_commit,required_checks_state,evidence_ref,observed_at,currentness "
100
+ "FROM managed_pr_check_observations WHERE run_id=? ORDER BY id", (run_id,)
101
+ ).fetchall()
102
+ except sqlite3.OperationalError:
103
+ return {}
104
+ result: dict[str, dict[str, object]] = {}
105
+ for row in rows:
106
+ role = str(row[2])
107
+ candidate = {"pr_number": row[1], "pr_state": row[3], "merge_state": row[4], "merge_commit": row[5], "required_checks_state": row[6], "observed_at": row[8], "currentness": row[9]}
108
+ if role not in result or (int(row[9]), int(row[0])) >= (int(result[role]["currentness"]), -1):
109
+ result[role] = candidate
110
+ return result
111
+
112
+
113
+ def _validation_controls(connection: sqlite3.Connection, run_id: str, snapshot: str) -> list[dict[str, object]]:
114
+ """Select only the newest canonical observation per validation control."""
115
+ try:
116
+ rows = connection.execute(
117
+ "SELECT id,control,state,required,currentness,observed_at FROM managed_validation_observations WHERE run_id=? ORDER BY id",
118
+ (run_id,),
119
+ ).fetchall()
120
+ except sqlite3.OperationalError:
121
+ return []
122
+ current: dict[str, sqlite3.Row] = {}
123
+ for row in rows:
124
+ control = str(row[1])
125
+ if control not in current or (int(row[4]), int(row[0])) >= (int(current[control][4]), int(current[control][0])):
126
+ current[control] = row
127
+ return [{"control_id": control, "display_category_code": control, "state": row[2],
128
+ "execution_source": "MANAGED_VALIDATION_OBSERVATION", "required": bool(row[3]),
129
+ "observed_at": row[5], "evidence_reference": _reference("VALIDATION", f"run:{run_id}:{control}", row[5], snapshot, "VALIDATION_CONTROL", "BOUNDARY_SENSITIVE")}
130
+ for control, row in sorted(current.items())]
131
+
132
+
133
+ def _qualification_evidence(connection: sqlite3.Connection, run_id: str) -> tuple[dict[str, object] | None, dict[str, object] | None]:
134
+ """Read only explicit v33 qualification evidence; never infer legacy facts."""
135
+ try:
136
+ lineage = connection.execute(
137
+ "SELECT submission_id,fresh_submission,retry_parent_run_id,resume_parent_run_id,recorded_at "
138
+ "FROM execution_run_qualification_context WHERE run_id=?", (run_id,)
139
+ ).fetchone()
140
+ profile = connection.execute(
141
+ "SELECT selected_validation_tier,validation_profile_version,required_validation_controls,recorded_at "
142
+ "FROM execution_validation_profiles WHERE run_id=?", (run_id,)
143
+ ).fetchone()
144
+ controls = connection.execute(
145
+ "SELECT validation_id,category,required_for_profile,execution_status,result,observed_at,currentness "
146
+ "FROM execution_validation_control_results WHERE run_id=? ORDER BY id", (run_id,)
147
+ ).fetchall()
148
+ commands = connection.execute(
149
+ "SELECT inv.validation_id,inv.category,inv.required_for_profile,'EXECUTED',"
150
+ "COALESCE(term.result,'UNAVAILABLE'),COALESCE(term.completed_at,inv.started_at),inv.currentness "
151
+ "FROM execution_validation_command_invocations inv LEFT JOIN execution_validation_command_terminals term "
152
+ "ON term.run_id=inv.run_id AND term.command_id=inv.command_id WHERE inv.run_id=? ORDER BY inv.started_at",
153
+ (run_id,),
154
+ ).fetchall()
155
+ except sqlite3.OperationalError:
156
+ return None, None
157
+ lineage_projection = None if lineage is None else {
158
+ "submission_id": lineage[0], "fresh_submission": bool(lineage[1]),
159
+ "retry_parent": lineage[2], "resume_parent": lineage[3], "recorded_at": lineage[4],
160
+ }
161
+ if profile is None:
162
+ return lineage_projection, None
163
+ try:
164
+ payload = json.loads(profile[2])
165
+ required = payload.get("validation_ids", [])
166
+ except (AttributeError, TypeError, json.JSONDecodeError):
167
+ return lineage_projection, None
168
+ if not isinstance(required, list) or not all(isinstance(item, str) for item in required):
169
+ return lineage_projection, None
170
+ current: dict[str, sqlite3.Row] = {}
171
+ conflicts: set[str] = set()
172
+ for row in (*controls, *commands):
173
+ validation_id = str(row[0])
174
+ existing = current.get(validation_id)
175
+ if existing is None or int(row[6]) > int(existing[6]):
176
+ current[validation_id] = row
177
+ elif int(row[6]) == int(existing[6]) and row[4] != existing[4]:
178
+ conflicts.add(validation_id)
179
+ def result_for(validation_id: str) -> object:
180
+ if validation_id in conflicts:
181
+ return "UNRESOLVED"
182
+ row = current.get(validation_id)
183
+ return row[4] if row is not None else None
184
+ results = [result_for(validation_id) for validation_id in required]
185
+ required_state = "FAIL" if any(result == "FAIL" for result in results) else (
186
+ "PASS" if results and all(result == "PASS" for result in results) else "UNRESOLVED"
187
+ )
188
+ return lineage_projection, {
189
+ "selected_validation_tier": profile[0], "validation_profile_version": profile[1],
190
+ "profile_reference": payload.get("profile_reference", UNAVAILABLE),
191
+ "profile_selection_source": payload.get("profile_selection_source", UNAVAILABLE),
192
+ "required_validation_controls": required, "required_validation_state": required_state,
193
+ "control_bindings": payload.get("control_bindings", UNAVAILABLE),
194
+ "recorded_at": profile[3],
195
+ "controls": [
196
+ {"validation_id": validation_id, "category": row[1], "required_for_profile": bool(row[2]),
197
+ "execution_status": row[3], "result": result_for(validation_id), "observed_at": row[5]}
198
+ for validation_id, row in sorted(current.items())
199
+ ],
200
+ }
201
+
202
+
203
+ def _lease_projection(connection: sqlite3.Connection, run_id: str) -> dict[str, object]:
204
+ try:
205
+ rows = connection.execute(
206
+ "SELECT run_id,host_identity,lease_state,last_heartbeat_at FROM execution_run_leases WHERE lease_state='ACTIVE' ORDER BY updated_at DESC"
207
+ ).fetchall()
208
+ except sqlite3.OperationalError:
209
+ return {"workspace_state": UNAVAILABLE, "workspace_occupied": UNAVAILABLE, "active_owner_run_id": UNAVAILABLE,
210
+ "lease_state": UNAVAILABLE, "lease_owner_identity": UNAVAILABLE, "conflict_present": UNAVAILABLE,
211
+ "recovery_required": UNAVAILABLE, "last_verified_at": UNAVAILABLE}
212
+ foreign = next((row for row in rows if row[0] != run_id), None)
213
+ own = next((row for row in rows if row[0] == run_id), None)
214
+ active = foreign or own
215
+ return {"workspace_state": "OCCUPIED" if foreign else ("OWNED" if own else "AVAILABLE"),
216
+ "workspace_occupied": bool(foreign), "active_owner_run_id": foreign[0] if foreign else UNAVAILABLE,
217
+ "lease_state": own[2] if own else (foreign[2] if foreign else UNAVAILABLE),
218
+ "lease_owner_identity": active[1] if active else UNAVAILABLE, "conflict_present": bool(foreign),
219
+ "recovery_required": False, "last_verified_at": active[3] if active else UNAVAILABLE}
220
+
221
+
222
+ def _usage_projection_unavailable() -> tuple[dict[str, object], dict[str, object]]:
223
+ unavailable = {"provider": UNAVAILABLE, "model": UNAVAILABLE, "model_authority": UNAVAILABLE, "provider_invocation_count": UNAVAILABLE,
224
+ "reviewer_invocation_count": UNAVAILABLE, "run_cumulative_input": UNAVAILABLE, "cached_input": UNAVAILABLE,
225
+ "uncached_input": UNAVAILABLE, "output": UNAVAILABLE, "provider_execution_time": UNAVAILABLE,
226
+ "tool_output": UNAVAILABLE, "git_output": UNAVAILABLE, "github_output": UNAVAILABLE, "estimated_credits": UNAVAILABLE,
227
+ "estimated_eur": UNAVAILABLE, "speed_state": UNAVAILABLE, "authority": "UNAVAILABLE", "availability": "UNAVAILABLE"}
228
+ return unavailable, {"selection_policy_result": UNAVAILABLE, "selected_reviewer_count": UNAVAILABLE, "roles": [], "reviewers": [], "independence_state": UNAVAILABLE}
229
+
230
+
231
+ def _usage_projection(connection: sqlite3.Connection, run_id: str) -> tuple[dict[str, object], dict[str, object]]:
232
+ try:
233
+ rows = connection.execute(
234
+ "SELECT provider,model,role,duration_ms,input_tokens,cached_input_tokens,uncached_input_tokens,output_tokens,usage_authority,speed_state,estimated_credits,estimated_eur,churn FROM provider_invocations WHERE run_id=? ORDER BY ordinal",
235
+ (run_id,),
236
+ ).fetchall()
237
+ except sqlite3.OperationalError:
238
+ rows = []
239
+ if not rows:
240
+ return _usage_projection_unavailable()
241
+ def total(index: int) -> int:
242
+ return sum(value for row in rows if isinstance((value := row[index]), int))
243
+ primary = rows[-1]
244
+ reviewers = [row for row in rows if str(row[2]).casefold() == "reviewer"]
245
+ churn = _json_object(primary[12])
246
+ usage = {"provider": primary[0] or UNAVAILABLE, "model": primary[1] or UNAVAILABLE, "model_authority": primary[8], "provider_invocation_count": len(rows),
247
+ "reviewer_invocation_count": len(reviewers), "run_cumulative_input": total(5) + total(6), "cached_input": total(5), "uncached_input": total(6),
248
+ "output": total(7), "provider_execution_time": total(3), "tool_output": churn.get("tool_output_bytes", UNAVAILABLE),
249
+ "git_output": churn.get("git_output_bytes", UNAVAILABLE), "github_output": churn.get("github_output_bytes", UNAVAILABLE),
250
+ "estimated_credits": primary[10] if primary[10] is not None else UNAVAILABLE, "estimated_eur": primary[11] if primary[11] is not None else UNAVAILABLE,
251
+ "speed_state": primary[9], "authority": primary[8], "availability": "AVAILABLE"}
252
+ reviewer_projection = {"selection_policy_result": "AVAILABLE", "selected_reviewer_count": len(reviewers), "roles": sorted({str(row[2]) for row in rows}),
253
+ "reviewers": [{"role": row[2], "state": "COMPLETE" if row[3] is not None else "ACTIVE", "duration": row[3] if row[3] is not None else UNAVAILABLE, "conclusion": UNAVAILABLE} for row in reviewers],
254
+ "independence_state": "UNAVAILABLE"}
255
+ return usage, reviewer_projection
256
+
257
+
258
+ def _phase_workflow(phase: object, terminal: object) -> dict[str, object]:
259
+ current = str(_value(phase))
260
+ state = current if terminal is True else "RUNNING"
261
+ expected = {
262
+ "EXECUTE_AGENT": "LOCAL_REPOSITORY_VALIDATION", "LOCAL_REPOSITORY_VALIDATION": "QUALITY_CONTROL_AGENT", "QUALITY_CONTROL_AGENT": "WAIT_FOR_OPERATOR_MERGE",
263
+ "REPAIR_AGENT": "QUALITY_CONTROL_AGENT", "WAIT_FOR_OPERATOR_MERGE": "FINALIZE_AGENT",
264
+ "FINALIZE_AGENT": "WAIT_FOR_FINALIZATION_MERGE", "WAIT_FOR_FINALIZATION_MERGE": "RECONCILE_AGENT",
265
+ "RECONCILE_AGENT": "REPOSITORY_CLEANUP", "REPOSITORY_CLEANUP": "COMPLETE",
266
+ }.get(current, UNAVAILABLE)
267
+ waiting = "EXPECTED_OPERATOR_MERGE_GATE" if current in {"WAIT_FOR_OPERATOR_MERGE", "WAIT_FOR_FINALIZATION_MERGE"} else UNAVAILABLE
268
+ return {"current_phase": current, "current_state": state, "previous_completed_phase": UNAVAILABLE,
269
+ "next_expected_lifecycle_boundary": expected, "waiting_reason": waiting,
270
+ "blocking_reason": UNAVAILABLE, "last_activity_at": UNAVAILABLE,
271
+ "last_verified_at": UNAVAILABLE, "expected_current_authority": "EP_LIFECYCLE"}
272
+
273
+
274
+ def get_run_context(root: Path, run_id: str) -> dict[str, object]:
275
+ """Return one serializable run projection or an unavailable safe projection."""
276
+ generated_at = _now()
277
+ try:
278
+ connection = _readonly_connection(root)
279
+ try:
280
+ transaction = connection.execute("SELECT payload,phase,updated_at FROM engineering_transactions WHERE run_id=?", (run_id,)).fetchone()
281
+ run = connection.execute("SELECT execution_mode,producer_id,producer_type,execution_started_at,execution_finished_at,execution_seconds FROM execution_runs WHERE run_id=?", (run_id,)).fetchone()
282
+ submission = connection.execute("SELECT s.submission_id,s.producer_id,s.producer_type,s.prompt_metadata,s.received_at FROM execution_submissions AS s JOIN execution_submission_links AS l ON l.submission_id=s.submission_id WHERE l.run_id=?", (run_id,)).fetchone()
283
+ qualification_lineage, qualification_validation = _qualification_evidence(connection, run_id)
284
+ try:
285
+ row = connection.execute(
286
+ "SELECT payload FROM execution_run_qualification_snapshots WHERE run_id=?", (run_id,)
287
+ ).fetchone()
288
+ qualification_snapshot = _json_object(row[0]) if row else None
289
+ except sqlite3.OperationalError:
290
+ qualification_snapshot = None
291
+ checks = _current_checks(connection, run_id)
292
+ validation_controls = _validation_controls(connection, run_id, "pending")
293
+ workspace = _lease_projection(connection, run_id)
294
+ usage, reviewers = _usage_projection(connection, run_id)
295
+ finally:
296
+ connection.close()
297
+ except (EngineeringStorageError, sqlite3.Error):
298
+ transaction = run = submission = qualification_lineage = qualification_validation = qualification_snapshot = None
299
+ checks = {}
300
+ validation_controls = []
301
+ workspace = {"workspace_state": UNAVAILABLE, "workspace_occupied": UNAVAILABLE, "active_owner_run_id": UNAVAILABLE,
302
+ "lease_state": UNAVAILABLE, "lease_owner_identity": UNAVAILABLE, "conflict_present": UNAVAILABLE,
303
+ "recovery_required": UNAVAILABLE, "last_verified_at": UNAVAILABLE}
304
+ usage, reviewers = _usage_projection_unavailable()
305
+ checkpoint = _json_object(transaction[0]) if transaction else {}
306
+ phase = transaction[1] if transaction else UNAVAILABLE
307
+ observed_at = transaction[2] if transaction else UNAVAILABLE
308
+ snapshot = _snapshot_id({"run_id": run_id, "checkpoint": checkpoint, "phase": phase, "checks": checks,
309
+ "validation": validation_controls, "workspace": workspace, "usage": usage, "reviewers": reviewers})
310
+ # References embed the finalized snapshot identity, never an intermediate value.
311
+ validation_controls = [dict(item, evidence_reference=_reference("VALIDATION", f"run:{run_id}:{item['control_id']}", item["observed_at"], snapshot, "VALIDATION_CONTROL", "BOUNDARY_SENSITIVE")) for item in validation_controls]
312
+ evidence = [_reference("CHECKPOINT", f"run:{run_id}", observed_at, snapshot, "RUN_CHECKPOINT", "BOUNDARY_SENSITIVE")]
313
+ if checks:
314
+ evidence.append(_reference("GITHUB", f"run:{run_id}:checks", max(str(item.get("observed_at", "")) for item in checks.values()), snapshot, "PR_CHECKS", "BOUNDARY_SENSITIVE"))
315
+ terminal = checkpoint.get("terminal")
316
+ qualification_source = qualification_snapshot if isinstance(qualification_snapshot, dict) else {}
317
+ action_intent = qualification_source.get("action_intent", checkpoint.get("action_intent"))
318
+ execution_mode = qualification_source.get("execution_mode", run[0] if run else checkpoint.get("execution_mode"))
319
+ snapshot_checks = qualification_source.get("pr_checks", {}) if qualification_source else {}
320
+ implementation = snapshot_checks.get("IMPLEMENTATION", {}) if qualification_source and isinstance(snapshot_checks, dict) else checks.get("IMPLEMENTATION", {})
321
+ finalization = snapshot_checks.get("FINALIZATION", {}) if qualification_source and isinstance(snapshot_checks, dict) else checks.get("FINALIZATION", {})
322
+ objective = _safe_objective(submission[3] if submission else {})
323
+ validation_only = action_intent == "VALIDATION_ONLY"
324
+ persisted_required_validation = qualification_source.get("validation_profile", UNAVAILABLE) if qualification_source else qualification_validation or UNAVAILABLE
325
+ lineage_source = qualification_source if qualification_source else qualification_lineage
326
+ context: dict[str, object] = {
327
+ "contract_name": "run_context", "contract_version": CONTRACT_VERSION, "generated_at": generated_at,
328
+ "run_id": run_id, "evidence_version": snapshot, "projection_authority": PROJECTION_AUTHORITY,
329
+ "run": {"execution_mode": _value(execution_mode), "terminal": _value(terminal),
330
+ "current_execution_state": _value(phase), "current_phase": _value(phase),
331
+ "fresh_submission_state": "AVAILABLE" if lineage_source else UNAVAILABLE,
332
+ "fresh_submission": lineage_source["fresh_submission"] if lineage_source else UNAVAILABLE,
333
+ "retry_parent": lineage_source["retry_parent"] if lineage_source else UNAVAILABLE,
334
+ "resume_parent": lineage_source["resume_parent"] if lineage_source else UNAVAILABLE,
335
+ "producer": {"id": _value(submission[1] if submission else (run[1] if run else None)), "type": _value(submission[2] if submission else (run[2] if run else None))},
336
+ "execution_host": UNAVAILABLE, "lease_state": UNAVAILABLE, "recovery_required": False,
337
+ "active_blocking_predecessor": UNAVAILABLE},
338
+ "objective": objective,
339
+ "workflow": _phase_workflow(phase, terminal),
340
+ "blocker": {"blocker_present": phase in {"BLOCKED", "FAILED"} or workspace["workspace_occupied"] is True,
341
+ "blocker_type": "WORKSPACE_OCCUPIED" if workspace["workspace_occupied"] is True else ("TERMINAL_RUN" if phase in {"BLOCKED", "FAILED"} else UNAVAILABLE),
342
+ "summary_code": "WORKSPACE_OCCUPIED" if workspace["workspace_occupied"] is True else ("RUN_TERMINAL" if phase in {"BLOCKED", "FAILED"} else UNAVAILABLE),
343
+ "evidence_references": evidence, "blocking_run_id": workspace["active_owner_run_id"] if workspace["workspace_occupied"] is True else UNAVAILABLE, "blocking_pr": UNAVAILABLE,
344
+ "detected_at": _value(observed_at), "verified_at": _value(observed_at), "recoverability": UNAVAILABLE},
345
+ "delivery": {"action_intent": _value(action_intent),
346
+ "implementation_pr": "NOT_REQUIRED" if validation_only else _value(qualification_source.get("implementation_pr") if qualification_source else checkpoint.get("implementation_pull_request") or checkpoint.get("pull_request") or implementation.get("pr_number")),
347
+ "implementation_pr_current_state": "NOT_REQUIRED" if validation_only else _value(implementation.get("pr_state")), "implementation_merge_state": _value(implementation.get("merge_state")),
348
+ "implementation_merge_commit": _value(implementation.get("merge_commit") if qualification_source else checkpoint.get("implementation_merge_commit") or implementation.get("merge_commit")),
349
+ "implementation_required_checks_state": _value(implementation.get("required_checks_state")), "implementation_merge_gate": "EXPECTED_OPERATOR_GATE" if phase == "WAIT_FOR_OPERATOR_MERGE" else UNAVAILABLE,
350
+ "finalization_pr": "NOT_REQUIRED" if validation_only else _value(qualification_source.get("finalization_pr") if qualification_source else checkpoint.get("finalization_pull_request") or finalization.get("pr_number")), "finalization_pr_current_state": "NOT_REQUIRED" if validation_only else _value(finalization.get("pr_state")),
351
+ "finalization_merge_state": _value(finalization.get("merge_state")), "finalization_merge_commit": _value(finalization.get("merge_commit") if qualification_source else checkpoint.get("finalization_merge_commit") or finalization.get("merge_commit")),
352
+ "finalization_required_checks_state": _value(finalization.get("required_checks_state")), "finalization_merge_gate": "EXPECTED_OPERATOR_GATE" if phase == "WAIT_FOR_FINALIZATION_MERGE" else UNAVAILABLE,
353
+ "implementation_delivery": _value(qualification_source.get("implementation_delivery")),
354
+ "finalization_delivery": _value(qualification_source.get("finalization_delivery")),
355
+ "run_delivery_commit": _value(checkpoint.get("implementation_head_sha") or checkpoint.get("last_verified_sha")), "current_repository_head": _value(checkpoint.get("last_verified_sha")), "delivery_commit_head_relationship": UNAVAILABLE},
356
+ "validation": {"engineering_platform_qualification": UNAVAILABLE, "controls": validation_controls,
357
+ "required_validation": persisted_required_validation,
358
+ "run_qualification": qualification_snapshot.get("run_qualification", UNAVAILABLE) if qualification_snapshot else UNAVAILABLE,
359
+ "qualification_snapshot": qualification_snapshot or UNAVAILABLE},
360
+ "repository": {"repository_identity": _value(checkpoint.get("repository")), "expected_branch": "main", "current_branch": _value(checkpoint.get("branch")), "worktree_state": qualification_snapshot.get("reconciliation_evidence", {}).get("worktree_state", UNAVAILABLE) if qualification_snapshot else UNAVAILABLE, "main_origin_relationship": qualification_snapshot.get("reconciliation_evidence", {}).get("main_origin_sync", UNAVAILABLE) if qualification_snapshot else UNAVAILABLE, "repository_state": qualification_snapshot.get("reconciliation_evidence", {}).get("repository_state", UNAVAILABLE) if qualification_snapshot else UNAVAILABLE, "delivery_commit_relationship": UNAVAILABLE, "last_verified_at": _value(observed_at)},
361
+ "workspace": workspace,
362
+ "timing": {"run_wall_time": _value(run[5] if run else None), "provider_execution_time": _value(checkpoint.get("agent_execution_seconds")), "reviewer_time": UNAVAILABLE, "validation_time": UNAVAILABLE, "external_wait_time": UNAVAILABLE, "ci_wait_time": UNAVAILABLE, "merge_gate_wait_time": _value(checkpoint.get("waiting_for_merge_since")), "finalization_time": UNAVAILABLE, "reconciliation_time": UNAVAILABLE, "last_activity_at": _value(observed_at)},
363
+ "usage": usage,
364
+ "reviewers": reviewers,
365
+ "historical_report": {"availability": UNAVAILABLE}, "current_projection": {"availability": "AVAILABLE", "projection_generated_at": generated_at, "projection_authority": PROJECTION_AUTHORITY},
366
+ "authority": {"merge_authority": "OPERATOR", "projection_authority": PROJECTION_AUTHORITY}, "evidence": evidence,
367
+ }
368
+ context["allowed_actions"] = get_allowed_actions(root, run_id, context=context)
369
+ return context
370
+
371
+
372
+ def get_allowed_actions(root: Path, run_id: str, *, context: dict[str, object] | None = None) -> list[dict[str, object]]:
373
+ """Return only current EP policy descriptors; no mutating action is invented."""
374
+ context = context or get_run_context(root, run_id)
375
+ evidence_version = str(context.get("evidence_version", UNAVAILABLE))
376
+ known = context.get("run", {}).get("current_execution_state") != UNAVAILABLE if isinstance(context.get("run"), dict) else False
377
+ return [AllowedAction(action_id=action_id, action_namespace=namespace, run_id=run_id, allowed=known,
378
+ reason_code="READ_ONLY_INSPECTION_AVAILABLE" if known else "RUN_EVIDENCE_UNAVAILABLE",
379
+ evidence_version=evidence_version, expected_effect_code=effect,
380
+ blocked_reason_code=None if known else "RUN_EVIDENCE_UNAVAILABLE").to_dict()
381
+ for action_id, namespace, effect in _READ_ACTIONS]
382
+
383
+
384
+ def evaluate_action(root: Path, run_id: str, action: AllowedAction | dict[str, object]) -> dict[str, object]:
385
+ """Re-evaluate one descriptor against fresh evidence before any future action gateway use."""
386
+ descriptor = action.to_dict() if isinstance(action, AllowedAction) else dict(action) if isinstance(action, dict) else {}
387
+ context = get_run_context(root, run_id)
388
+ fresh = str(context["evidence_version"])
389
+ known_action_ids = {action_id for action_id, _, _ in _READ_ACTIONS}
390
+ action_id = str(descriptor.get("action_id")) if descriptor.get("action_id") in known_action_ids else UNAVAILABLE
391
+ try:
392
+ require_compatible_version(descriptor.get("contract_version"))
393
+ except ContractVersionError:
394
+ return ActionPolicyDecision(action_id=action_id, run_id=run_id, decision="UNAVAILABLE", reason_code="INCOMPATIBLE_CONTRACT_VERSION", policy_version=POLICY_VERSION, evaluated_at=_now(), evidence_version=fresh).to_dict()
395
+ if descriptor.get("run_id") != run_id or descriptor.get("evidence_version") != fresh:
396
+ return ActionPolicyDecision(action_id=action_id, run_id=run_id, decision="STALE_REVALIDATION_REQUIRED", reason_code="EVIDENCE_VERSION_CHANGED", policy_version=POLICY_VERSION, evaluated_at=_now(), evidence_version=fresh).to_dict()
397
+ permitted = {item["action_id"] for item in get_allowed_actions(root, run_id, context=context) if item["allowed"] is True}
398
+ decision = "ALLOWED" if action_id in permitted and descriptor.get("classification") == "READ_ONLY" else "DENIED"
399
+ return ActionPolicyDecision(action_id=action_id, run_id=run_id, decision=decision,
400
+ reason_code="READ_ONLY_INSPECTION_AVAILABLE" if decision == "ALLOWED" else "ACTION_NOT_CURRENTLY_ALLOWED",
401
+ policy_version=POLICY_VERSION, evaluated_at=_now(), evidence_version=fresh).to_dict()
@@ -0,0 +1,206 @@
1
+ """Run dashboard browser validation with local CI-parity and host safety."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+ import signal
8
+ import subprocess
9
+ import sys
10
+ import tempfile
11
+ import time
12
+ import json
13
+
14
+ from .component_lock import single_instance
15
+
16
+
17
+ SHARDS = ("1/4", "2/4", "3/4", "4/4")
18
+ PLAYWRIGHT_COMMAND = ("npx", "playwright", "test", "tests/engineering/dashboard.spec.mjs")
19
+ LOCK_COMPONENT = "dashboard-browser-validation"
20
+ LOCAL_BATCH_TIMEOUT_SECONDS = 300
21
+ PROCESS_TERMINATION_TIMEOUT_SECONDS = 5
22
+ EVIDENCE_RUN_ID_ENV = "ENGINEERING_PLATFORM_VALIDATION_RUN_ID"
23
+
24
+
25
+ def _common_git_directory(root: Path) -> Path:
26
+ """Return the Git directory shared by every worktree of this repository."""
27
+ observed = subprocess.run(
28
+ ("git", "rev-parse", "--path-format=absolute", "--git-common-dir"),
29
+ cwd=root,
30
+ capture_output=True,
31
+ check=False,
32
+ text=True,
33
+ )
34
+ directory = observed.stdout.strip()
35
+ if observed.returncode or not directory:
36
+ raise RuntimeError("Dashboard browser validation requires a Git worktree.")
37
+ return Path(directory)
38
+
39
+
40
+ def _command(*arguments: str) -> tuple[str, ...]:
41
+ return (*PLAYWRIGHT_COMMAND, "--workers=1", *arguments)
42
+
43
+
44
+ def dashboard_evidence_path(root: Path, run_id: str) -> Path:
45
+ """Return the ignored, run-scoped shard evidence payload location."""
46
+ return root / ".engineering" / "validation" / "dashboard-browser" / f"{run_id}.json"
47
+
48
+
49
+ def _write_evidence(root: Path, results: list[tuple[str, str, int | None]], *, cleanup: str) -> None:
50
+ """Write bounded structured shard facts only when the host supplied a run id."""
51
+ run_id = os.environ.get(EVIDENCE_RUN_ID_ENV)
52
+ if not run_id:
53
+ return
54
+ if not run_id.replace("-", "").isalnum():
55
+ return
56
+ path = dashboard_evidence_path(root, run_id)
57
+ path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
58
+ payload = {
59
+ "version": 1,
60
+ "expected_shard_count": len(SHARDS),
61
+ "actual_shard_count": len(results),
62
+ "workers_per_shard": 1,
63
+ "shards": [
64
+ {"shard": shard, "exit_code": result, "result": "PASS" if result == 0 else "FAIL" if result is not None else "UNAVAILABLE"}
65
+ for shard, _, result in results
66
+ ],
67
+ "cleanup": cleanup,
68
+ }
69
+ temporary = path.with_suffix(".tmp")
70
+ temporary.write_text(json.dumps(payload, sort_keys=True) + "\n", encoding="utf-8")
71
+ temporary.replace(path)
72
+
73
+
74
+ def load_dashboard_evidence(root: Path, run_id: str) -> dict[str, object] | None:
75
+ """Load only a complete, fixed-topology dashboard shard payload."""
76
+ try:
77
+ payload = json.loads(dashboard_evidence_path(root, run_id).read_text(encoding="utf-8"))
78
+ except (OSError, json.JSONDecodeError):
79
+ return None
80
+ if not isinstance(payload, dict) or payload.get("version") != 1:
81
+ return None
82
+ shards = payload.get("shards")
83
+ if (
84
+ payload.get("expected_shard_count") != len(SHARDS)
85
+ or payload.get("actual_shard_count") != len(SHARDS)
86
+ or payload.get("workers_per_shard") != 1
87
+ or not isinstance(shards, list)
88
+ or len(shards) != len(SHARDS)
89
+ or tuple(item.get("shard") for item in shards if isinstance(item, dict)) != SHARDS
90
+ ):
91
+ return None
92
+ return payload
93
+
94
+
95
+ def _run_ci(root: Path, arguments: tuple[str, ...]) -> int:
96
+ """Delegate one CI shard unchanged to Playwright."""
97
+ return subprocess.run(_command(*arguments), cwd=root, check=False).returncode
98
+
99
+
100
+ def _terminate_process_groups(processes: list[tuple[str, Path, subprocess.Popen[bytes]]]) -> None:
101
+ """Stop every owned shard group, including descendants of a failed parent."""
102
+ # A Playwright shard can exit before the dashboard server it started in the
103
+ # same session. Signal every owned process group so that failure cleanup
104
+ # does not leave that server behind merely because its parent has exited.
105
+ for _, _, process in processes:
106
+ try:
107
+ os.killpg(process.pid, signal.SIGTERM)
108
+ except (PermissionError, ProcessLookupError):
109
+ # A shard can already have exited and its process-group identity
110
+ # may no longer be signalable on macOS. Cleanup is best-effort;
111
+ # it must not replace the authoritative shard exit result.
112
+ pass
113
+ active = [process for _, _, process in processes if process.poll() is None]
114
+ for process in active:
115
+ try:
116
+ process.wait(timeout=PROCESS_TERMINATION_TIMEOUT_SECONDS)
117
+ except subprocess.TimeoutExpired:
118
+ try:
119
+ os.killpg(process.pid, signal.SIGKILL)
120
+ except (PermissionError, ProcessLookupError):
121
+ pass
122
+ try:
123
+ process.wait(timeout=PROCESS_TERMINATION_TIMEOUT_SECONDS)
124
+ except subprocess.TimeoutExpired:
125
+ pass
126
+
127
+
128
+ def _read_results(
129
+ processes: list[tuple[str, Path, subprocess.Popen[bytes]]],
130
+ ) -> list[tuple[str, str, int | None]]:
131
+ """Return captured output after every owned shard has reached a terminal state."""
132
+ return [
133
+ (shard, output.read_text(encoding="utf-8", errors="replace"), process.poll())
134
+ for shard, output, process in processes
135
+ ]
136
+
137
+
138
+ def _run_local_shards(root: Path) -> int:
139
+ """Run four isolated one-worker shards, refusing overlapping local batches."""
140
+ environment = {**os.environ, "CI": "1"}
141
+ common_git = _common_git_directory(root)
142
+ with single_instance(common_git, LOCK_COMPONENT):
143
+ with tempfile.TemporaryDirectory(prefix="engineering-platform-dashboard-shards-") as temporary:
144
+ directory = Path(temporary)
145
+ processes: list[tuple[str, Path, subprocess.Popen[bytes]]] = []
146
+ failed = False
147
+ timed_out = False
148
+ cleaned_up = False
149
+ cleanup_attempted = False
150
+ deadline = time.monotonic() + LOCAL_BATCH_TIMEOUT_SECONDS
151
+ try:
152
+ for index, shard in enumerate(SHARDS, start=1):
153
+ output = directory / f"shard-{index}.log"
154
+ with output.open("wb") as stream:
155
+ process = subprocess.Popen(
156
+ _command("--reporter=line", f"--shard={shard}", f"--output=test-results/dashboard-shard-{index}"),
157
+ cwd=root,
158
+ env=environment,
159
+ stderr=subprocess.STDOUT,
160
+ stdout=stream,
161
+ start_new_session=True,
162
+ )
163
+ processes.append((shard, output, process))
164
+ for _, _, process in processes:
165
+ remaining = deadline - time.monotonic()
166
+ if remaining <= 0:
167
+ timed_out = True
168
+ break
169
+ try:
170
+ if process.wait(timeout=remaining) != 0:
171
+ failed = True
172
+ except subprocess.TimeoutExpired:
173
+ timed_out = True
174
+ break
175
+ except BaseException:
176
+ _terminate_process_groups(processes)
177
+ cleaned_up = True
178
+ raise
179
+ finally:
180
+ if not cleaned_up and (timed_out or any(process.poll() is None for _, _, process in processes)):
181
+ _terminate_process_groups(processes)
182
+ cleanup_attempted = True
183
+ results = _read_results(processes)
184
+ _write_evidence(root, results, cleanup="ATTEMPTED" if cleanup_attempted else "NOT_REQUIRED")
185
+ for shard, output, _ in results:
186
+ print(f"\n=== Dashboard browser shard {shard} ===")
187
+ print(output, end="" if output.endswith("\n") else "\n")
188
+ if timed_out:
189
+ print(f"Dashboard browser validation exceeded its {LOCAL_BATCH_TIMEOUT_SECONDS}-second local deadline.")
190
+ return 1
191
+ return 0 if not failed and all(result == 0 for _, _, result in results) else 1
192
+
193
+
194
+ def main(arguments: tuple[str, ...] | None = None) -> int:
195
+ """Keep GitHub's one-worker shard contract and coordinate local parity runs."""
196
+ root = Path.cwd()
197
+ arguments = arguments if arguments is not None else tuple(sys.argv[1:])
198
+ if os.environ.get("CI"):
199
+ return _run_ci(root, arguments)
200
+ if arguments:
201
+ raise SystemExit("Local dashboard validation does not accept Playwright arguments; run the coordinated four-shard batch.")
202
+ return _run_local_shards(root)
203
+
204
+
205
+ if __name__ == "__main__":
206
+ raise SystemExit(main())