engineering-platform 2.3.1__tar.gz → 2.3.66__tar.gz

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 (163) hide show
  1. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/PKG-INFO +2 -2
  2. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/pyproject.toml +2 -2
  3. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
  4. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +5 -5
  5. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/agent_state.py +109 -11
  6. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard.css +7 -6
  7. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard.js +589 -233
  8. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard_locales.mjs +89 -24
  9. engineering_platform-2.3.66/src/engineering_platform/assets/dashboard_translation.mjs +192 -0
  10. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/central_data_transfer.py +2 -1
  11. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/central_database.py +19 -15
  12. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/central_store_migration.py +16 -9
  13. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/codex_chat.py +56 -38
  14. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/component_logging.py +263 -13
  15. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/console_route_ownership.py +12 -2
  16. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/contracts/projection.py +38 -51
  17. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_browser_validation.py +4 -1
  18. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_state.py +23 -0
  19. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_supervisor.swift +10 -1
  20. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_translation.py +36 -18
  21. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/dependabot_producer.py +11 -3
  22. engineering_platform-2.3.66/src/engineering_platform/development_profile.py +344 -0
  23. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/evidence_projection.py +55 -4
  24. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_executor.py +96 -5
  25. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_host.py +806 -87
  26. engineering_platform-2.3.66/src/engineering_platform/execution_host_evidence.py +167 -0
  27. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_lease.py +57 -11
  28. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_lifecycle.py +45 -5
  29. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_reporting.py +6 -0
  30. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_timing.py +3 -1
  31. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/host_admin.py +8 -3
  32. engineering_platform-2.3.66/src/engineering_platform/installation_update_activation.py +125 -0
  33. engineering_platform-2.3.66/src/engineering_platform/installation_update_admission.py +503 -0
  34. engineering_platform-2.3.66/src/engineering_platform/installation_update_backup.py +56 -0
  35. engineering_platform-2.3.66/src/engineering_platform/installation_update_composition.py +326 -0
  36. engineering_platform-2.3.66/src/engineering_platform/installation_update_executor.py +221 -0
  37. engineering_platform-2.3.66/src/engineering_platform/installation_update_migration.py +62 -0
  38. engineering_platform-2.3.66/src/engineering_platform/installation_update_operation.py +685 -0
  39. engineering_platform-2.3.66/src/engineering_platform/installation_update_plan.py +136 -0
  40. engineering_platform-2.3.66/src/engineering_platform/installation_update_preparation.py +532 -0
  41. engineering_platform-2.3.66/src/engineering_platform/legacy_installation_adoption.py +384 -0
  42. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/lifecycle_worker.py +53 -5
  43. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/live_status.py +26 -0
  44. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/managed_autonomy.py +17 -1
  45. engineering_platform-2.3.66/src/engineering_platform/operational_installation.py +409 -0
  46. engineering_platform-2.3.66/src/engineering_platform/operational_installation_lock.py +51 -0
  47. engineering_platform-2.3.66/src/engineering_platform/operational_installation_record.py +211 -0
  48. engineering_platform-2.3.66/src/engineering_platform/owner_credential_recovery.py +1150 -0
  49. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/parity_context.py +46 -1
  50. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/parity_lifecycle_dispatcher.py +395 -43
  51. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/platform_bootstrap.py +3 -2
  52. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/platform_version.py +1 -1
  53. engineering_platform-2.3.66/src/engineering_platform/product_installation_readback.py +567 -0
  54. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/prompt_history.py +2 -2
  55. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_interruption.py +15 -7
  56. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/providers.py +272 -3
  57. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/qualification_runtime.py +48 -13
  58. engineering_platform-2.3.66/src/engineering_platform/release_operation.py +313 -0
  59. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/report_analysis.py +43 -10
  60. engineering_platform-2.3.66/src/engineering_platform/revision_binding.py +39 -0
  61. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +13 -1
  62. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/server.py +3465 -305
  63. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/server_console_services.py +5 -6
  64. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/server_relay.py +32 -4
  65. engineering_platform-2.3.66/src/engineering_platform/server_service.py +398 -0
  66. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/storage.py +470 -72
  67. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/submission_service.py +487 -27
  68. engineering_platform-2.3.66/src/engineering_platform/system_installation_topology.py +596 -0
  69. engineering_platform-2.3.66/src/engineering_platform/system_server_service.py +607 -0
  70. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/templates/workspace-config.json +1 -1
  71. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/validation_profile.py +196 -7
  72. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/PKG-INFO +2 -2
  73. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/SOURCES.txt +25 -1
  74. engineering_platform-2.3.66/tests/test_adaptive_action_sizing_design.py +119 -0
  75. engineering_platform-2.3.66/tests/test_role_task_model_policy_design.py +141 -0
  76. engineering_platform-2.3.1/src/engineering_platform/server_service.py +0 -161
  77. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/README.md +0 -0
  78. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/setup.cfg +0 -0
  79. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/__init__.py +0 -0
  80. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/__main__.py +0 -0
  81. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/agent_trust.py +0 -0
  82. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
  83. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  84. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  85. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
  86. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
  87. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  88. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
  89. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/capability_preflight.py +0 -0
  90. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/capability_review.py +0 -0
  91. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/codex_capacity.py +0 -0
  92. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/codex_observability.py +0 -0
  93. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/component_lock.py +0 -0
  94. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/console_presentation.py +0 -0
  95. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/contracts/__init__.py +0 -0
  96. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/contracts/ep_consumer.py +0 -0
  97. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/contracts/models.py +0 -0
  98. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/drift_diagnostics.py +0 -0
  99. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/emergency_recovery.py +0 -0
  100. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/engineering_memory.py +0 -0
  101. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/ep_consumer_credentials.py +0 -0
  102. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_activity.py +0 -0
  103. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_context.py +0 -0
  104. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_errors.py +0 -0
  105. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_evidence.py +0 -0
  106. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_finalization.py +0 -0
  107. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_models.py +0 -0
  108. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_readiness.py +0 -0
  109. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_repository.py +0 -0
  110. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_timeout_policy.py +0 -0
  111. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/execution_transaction.py +0 -0
  112. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/external_producer_binding.py +0 -0
  113. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/file_inbox.py +0 -0
  114. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/forensic_attribution.py +0 -0
  115. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/forensic_attribution_v2.py +0 -0
  116. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/forensic_delta.py +0 -0
  117. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/golden_scenario.py +0 -0
  118. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
  119. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/host_preflight.py +0 -0
  120. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/installation_relocation.py +0 -0
  121. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/investigation_ledger.py +0 -0
  122. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/legacy_inbox_migration.py +0 -0
  123. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/local_api.py +0 -0
  124. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/local_api_keychain.py +0 -0
  125. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/local_repository_binding.py +0 -0
  126. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/managed_codex_runtime.py +0 -0
  127. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/platform_admin.py +0 -0
  128. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/platform_api.py +0 -0
  129. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/platform_components.py +0 -0
  130. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/pr_check_repair.py +0 -0
  131. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/pr_evidence_backfill.py +0 -0
  132. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/producer.py +0 -0
  133. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/project_agent.py +0 -0
  134. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/project_agent_service.py +0 -0
  135. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/project_topology.py +0 -0
  136. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_context.py +0 -0
  137. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_context_benchmark.py +0 -0
  138. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_context_scope.py +0 -0
  139. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_process_identity.py +0 -0
  140. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_readiness.py +0 -0
  141. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_recovery.py +0 -0
  142. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/provider_usage.py +0 -0
  143. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/qualification.py +0 -0
  144. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/recommendation_handoff.py +0 -0
  145. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/repository_attachment.py +0 -0
  146. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/repository_handoff.py +0 -0
  147. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/resources.py +0 -0
  148. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/reviewer_evidence.py +0 -0
  149. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
  150. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
  151. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/status_model.py +0 -0
  152. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/status_reconciliation.py +0 -0
  153. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/submission_cli.py +0 -0
  154. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/submission_intake.py +0 -0
  155. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/telemetry.py +0 -0
  156. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/validation_identity.py +0 -0
  157. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/version_preparation_delivery.py +0 -0
  158. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/workspace_preflight.py +0 -0
  159. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/worktree_provenance.py +0 -0
  160. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform/worktree_tooling.py +0 -0
  161. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
  162. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/entry_points.txt +0 -0
  163. {engineering_platform-2.3.1 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-platform
3
- Version: 2.3.1
3
+ Version: 2.3.66
4
4
  Summary: Local-first Engineering Platform execution operations runtime
5
5
  Author: Peter van Tol
6
6
  License: MIT
7
- Requires-Python: >=3.11
7
+ Requires-Python: <3.15,>=3.14
8
8
  Description-Content-Type: text/markdown
9
9
 
10
10
  # Engineering Platform
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "engineering-platform"
7
- version = "2.3.1"
7
+ version = "2.3.66"
8
8
  description = "Local-first Engineering Platform execution operations runtime"
9
9
  readme = "README.md"
10
- requires-python = ">=3.11"
10
+ requires-python = ">=3.14,<3.15"
11
11
  license = {text = "MIT"}
12
12
  authors = [{name = "Peter van Tol"}]
13
13
  dependencies = []
@@ -3,7 +3,7 @@
3
3
  "platform": {
4
4
  "id": "engineering-platform",
5
5
  "name": "Engineering Platform",
6
- "version": "2.3.1",
6
+ "version": "2.3.66",
7
7
  "generation": 2,
8
8
  "documentation_namespace": "engineering-platform",
9
9
  "capability_registry_version": 1
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "bootstrap_contract": "2026.12",
3
3
  "checkpoint_format": 1,
4
- "dashboard_version": "2.3.1",
4
+ "dashboard_version": "2.3.66",
5
5
  "handoff_protocol": 1,
6
6
  "memory_format": 2,
7
7
  "minimum_codex_cli": "0.146.0",
8
8
  "inbox_protocol": 1,
9
- "platform_version": "2.3.1",
9
+ "platform_version": "2.3.66",
10
10
  "report_format": 2,
11
- "runner_version": "2.3.1",
11
+ "runner_version": "2.3.66",
12
12
  "status_model": 1,
13
- "storage_schema": 41,
14
- "watcher_version": "2.3.1"
13
+ "storage_schema": 44,
14
+ "watcher_version": "2.3.66"
15
15
  }
@@ -4,11 +4,13 @@ from __future__ import annotations
4
4
 
5
5
  from dataclasses import asdict, dataclass
6
6
  import json
7
+ import logging
7
8
  import os
8
9
  from pathlib import Path
9
10
  import re
10
11
  import sqlite3
11
12
  import tempfile
13
+ from time import sleep
12
14
 
13
15
  from .storage import (
14
16
  CENTRAL_OPERATIONAL_DATABASE_ENVIRONMENT,
@@ -21,6 +23,7 @@ SCHEMA_VERSION = 1
21
23
  PHASES = frozenset({"INITIALIZE", "CAPABILITY_REVIEW", "EXECUTE_AGENT", "LOCAL_REPOSITORY_VALIDATION", "QUALITY_CONTROL_AGENT", "REPAIR_AGENT", "FINALIZE_AGENT", "RECONCILE_AGENT", "WAIT_FOR_TERMINAL_EVIDENCE", "WAIT_FOR_OPERATOR_MERGE", "REPOSITORY_CLEANUP", "COMPLETE", "BLOCKED", "FAILED"})
22
24
  RUN_ID_PATTERN = re.compile(r"^[a-z0-9][a-z0-9-]{0,63}$")
23
25
  MAX_DIAGNOSTIC_LENGTH = 500
26
+ _TRANSIENT_CHECKPOINT_DELAYS = (0.02,)
24
27
  MAX_COMMIT_EVIDENCE_RECORDS = 48
25
28
  COMMIT_EVIDENCE_FIELDS = frozenset({"phase", "observed_at", "commit_sha", "description"})
26
29
  COMMIT_EVIDENCE_TIMESTAMP_PATTERN = re.compile(
@@ -46,6 +49,7 @@ COMMIT_EVIDENCE_DESCRIPTIONS = frozenset({
46
49
  "implementation_merge_verified",
47
50
  "finalization_merge_verified",
48
51
  "reconciliation_merge_verified",
52
+ "managed_noop_repository_reconciled",
49
53
  })
50
54
  SENSITIVE_DIAGNOSTIC_PATTERN = re.compile(
51
55
  r"(?i)\b(api[_ -]?key|oauth|access[_ -]?token|refresh[_ -]?token|secret|cookie|authorization|password)\b\s*[:=]\s*\S+|\bbearer\s+\S+|\b[A-Z][A-Z0-9_]{2,}\s*=\s*\S+"
@@ -112,6 +116,12 @@ class TransactionState:
112
116
  branch: str | None = None
113
117
  pull_request: int | None = None
114
118
  last_verified_sha: str | None = None
119
+ # The original accepted request remains distinct from both the selected
120
+ # baseline and any implementation candidate. It is never inferred from a
121
+ # later checkout head.
122
+ requested_repository_revision: str | None = None
123
+ execution_baseline_sha: str | None = None
124
+ allowed_baseline_revision: str | None = None
115
125
  next_action: str = "invoke_agent"
116
126
  terminal_condition: str = "repository_reconciled"
117
127
  diagnostic: str | None = None
@@ -168,6 +178,8 @@ class TransactionState:
168
178
  defaults = {
169
179
  "diagnostic": None, "owner_authorized": False, "transaction_kind": "IMPLEMENTATION",
170
180
  "execution_mode": "MANAGED", "genesis_repository_path": None, "genesis_commit_sha": None,
181
+ "requested_repository_revision": None, "execution_baseline_sha": None,
182
+ "allowed_baseline_revision": None,
171
183
  "action_intent": "MUTATING_DELIVERY",
172
184
  "implementation_branch": None, "implementation_pull_request": None,
173
185
  "implementation_head_sha": None, "implementation_merge_commit": None,
@@ -233,6 +245,14 @@ class TransactionState:
233
245
  raise StateError("checkpoint pull_request is invalid")
234
246
  if state.last_verified_sha is not None and not re.fullmatch(r"[0-9a-f]{40}", state.last_verified_sha):
235
247
  raise StateError("checkpoint last_verified_sha is invalid")
248
+ revision_binding_fields = (
249
+ state.requested_repository_revision, state.execution_baseline_sha,
250
+ state.allowed_baseline_revision,
251
+ )
252
+ if any(value is not None and (not isinstance(value, str) or not re.fullmatch(r"[0-9a-f]{40}", value)) for value in revision_binding_fields):
253
+ raise StateError("checkpoint repository revision binding is invalid")
254
+ if state.allowed_baseline_revision is not None and state.requested_repository_revision is None:
255
+ raise StateError("checkpoint allowed baseline requires a requested revision")
236
256
  if state.diagnostic is not None and (not isinstance(state.diagnostic, str) or not state.diagnostic or state.diagnostic != redact_diagnostic(state.diagnostic)):
237
257
  raise StateError("checkpoint diagnostic is invalid or unsafe")
238
258
  if not isinstance(state.owner_authorized, bool) or state.transaction_kind not in {"IMPLEMENTATION", "FINALIZATION", "RECONCILIATION"} or state.execution_mode not in {"MANAGED", "GENESIS"} or state.action_intent not in {"MUTATING_DELIVERY", "VALIDATION_ONLY"}:
@@ -281,27 +301,38 @@ class TransactionState:
281
301
  not isinstance(item, dict) or set(item) != audit_fields
282
302
  or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
283
303
  or not item["iteration"].isdigit() or int(item["iteration"]) < 1
284
- or item["outcome"] not in {"validated", "validation_failed", "agent_failed"}
304
+ or item["outcome"] not in {"validated", "validation_failed", "agent_failed", "assessment_rejected"}
285
305
  or (item["commit_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["commit_sha"]))
286
306
  for item in state.local_validation_audit
287
307
  )
288
308
  ):
289
309
  raise StateError("checkpoint local validation audit is invalid or unsafe")
290
310
  repair_audit_fields = audit_fields | {"repair_id", "origin", "input_candidate_sha", "dispatch_id"}
311
+ repair_delivery_scope_fields = repair_audit_fields | {"pre_repair_pull_request"}
312
+ repair_delivery_authority_fields = repair_delivery_scope_fields | {"repair_branch", "repair_base", "first_pr_authorized"}
291
313
  if (
292
314
  not isinstance(state.repair_audit, tuple)
293
315
  or len(state.repair_audit) > 3
294
316
  or any(
295
- not isinstance(item, dict) or set(item) not in (audit_fields, repair_audit_fields)
317
+ not isinstance(item, dict) or set(item) not in (audit_fields, repair_audit_fields, repair_delivery_scope_fields, repair_delivery_authority_fields)
296
318
  or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
297
319
  or not item["iteration"].isdigit() or int(item["iteration"]) < 1
298
320
  or item["outcome"] not in {"planned", "submitted_for_recheck", "agent_failed", "agent_timed_out"}
299
321
  or (item["commit_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["commit_sha"]))
300
- or (set(item) == repair_audit_fields and (
322
+ or (set(item) in (repair_audit_fields, repair_delivery_scope_fields, repair_delivery_authority_fields) and (
301
323
  not re.fullmatch(r"repair:[A-Za-z0-9_.:-]+:[1-3]", item["repair_id"])
302
324
  or item["origin"] not in {"validation", "quality", "security", "hosted", "finalization"}
303
325
  or (item["input_candidate_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["input_candidate_sha"]))
304
326
  ))
327
+ or (set(item) in (repair_delivery_scope_fields, repair_delivery_authority_fields) and (
328
+ item["pre_repair_pull_request"] != "none"
329
+ and not (item["pre_repair_pull_request"].isdigit() and int(item["pre_repair_pull_request"]) >= 1)
330
+ ))
331
+ or (set(item) == repair_delivery_authority_fields and (
332
+ (item["pre_repair_pull_request"] != "none" and item["first_pr_authorized"] != "no")
333
+ or (item["pre_repair_pull_request"] == "none" and item["first_pr_authorized"] not in {"yes", "no"})
334
+ or item["repair_branch"] == "none" or item["repair_base"] != "main"
335
+ ))
305
336
  for item in state.repair_audit
306
337
  )
307
338
  or len({item.get("repair_id", f"legacy:{item['iteration']}") for item in state.repair_audit}) != len(state.repair_audit)
@@ -379,12 +410,21 @@ class TransactionState:
379
410
  raise StateError("checkpoint quality evidence is invalid or unsafe")
380
411
  profile_fields = {"version", "digest", "candidate_sha"}
381
412
  current_profile_fields = profile_fields | {"criteria_digest"}
413
+ validation_bound_profile_fields = current_profile_fields | {"validation_profile_digest"}
382
414
  if state.assurance_profile is not None and (
383
415
  not isinstance(state.assurance_profile, dict)
384
- or set(state.assurance_profile) not in (profile_fields, current_profile_fields)
416
+ or set(state.assurance_profile) not in (
417
+ profile_fields, current_profile_fields, validation_bound_profile_fields,
418
+ )
385
419
  or not all(isinstance(value, str) and value for value in state.assurance_profile.values())
386
420
  or not re.fullmatch(r"sha256:[0-9a-f]{64}", state.assurance_profile["digest"])
387
421
  or not re.fullmatch(r"[0-9a-f]{40}", state.assurance_profile["candidate_sha"])
422
+ or (
423
+ "validation_profile_digest" in state.assurance_profile
424
+ and not re.fullmatch(
425
+ r"sha256:[0-9a-f]{64}", state.assurance_profile["validation_profile_digest"],
426
+ )
427
+ )
388
428
  ):
389
429
  raise StateError("checkpoint assurance profile is invalid")
390
430
  review_fields = {"reviewer", "status", "candidate_sha", "profile_digest", "invocation_id", "findings"}
@@ -462,8 +502,25 @@ class StateStore:
462
502
  # composition root. It must never rediscover that authority from the
463
503
  # execution checkout. The directory remains only a compatibility
464
504
  # location for legacy JSON projections.
465
- self.central_database = central_database.resolve() if central_database else None
505
+ environment_database = os.environ.get(CENTRAL_OPERATIONAL_DATABASE_ENVIRONMENT)
506
+ self.central_database = (
507
+ central_database.resolve()
508
+ if central_database is not None
509
+ else Path(environment_database).expanduser().resolve()
510
+ if environment_database
511
+ else None
512
+ )
466
513
  self.emit_local_projection = emit_local_projection
514
+ self._lifecycle_logger = None
515
+ if self.central_database is not None:
516
+ # Delayed to keep the state validator independent of the logging
517
+ # formatter, which itself uses ``redact_diagnostic`` above.
518
+ from .component_logging import component_logger
519
+ self._lifecycle_logger = component_logger(
520
+ self.central_database.parent,
521
+ "lifecycle_worker",
522
+ central_database=self.central_database,
523
+ )
467
524
 
468
525
  def path_for(self, run_id: str) -> Path:
469
526
  if not RUN_ID_PATTERN.fullmatch(run_id):
@@ -526,10 +583,18 @@ class StateStore:
526
583
  def save(self, state: TransactionState) -> Path:
527
584
  path = self.path_for(state.run_id)
528
585
  canonical = json.dumps(state.to_dict(), separators=(",", ":"), sort_keys=True)
529
- try:
530
- connection = self._open(create=True)
586
+ previous_phase: str | None = None
587
+ for delay in (0.0, *_TRANSIENT_CHECKPOINT_DELAYS):
588
+ connection: sqlite3.Connection | None = None
531
589
  try:
590
+ if delay:
591
+ sleep(delay)
592
+ connection = self._open(create=True)
532
593
  connection.execute("BEGIN IMMEDIATE")
594
+ prior = connection.execute(
595
+ "SELECT phase FROM engineering_transactions WHERE run_id=?", (state.run_id,)
596
+ ).fetchone()
597
+ previous_phase = str(prior[0]) if prior is not None else None
533
598
  connection.execute(
534
599
  "INSERT INTO engineering_transactions(run_id,payload,phase,updated_at) VALUES(?,?,?,CURRENT_TIMESTAMP) "
535
600
  "ON CONFLICT(run_id) DO UPDATE SET payload=excluded.payload,phase=excluded.phase,updated_at=excluded.updated_at",
@@ -540,13 +605,46 @@ class StateStore:
540
605
  (state.run_id, state.phase, canonical),
541
606
  )
542
607
  connection.execute("COMMIT")
608
+ break
609
+ except sqlite3.OperationalError as error:
610
+ if connection is not None:
611
+ try:
612
+ connection.execute("ROLLBACK")
613
+ except sqlite3.DatabaseError:
614
+ pass
615
+ if delay == _TRANSIENT_CHECKPOINT_DELAYS[-1] or "disk i/o" not in str(error).casefold():
616
+ raise
617
+ continue
618
+ except (EngineeringStorageError, OSError) as error:
619
+ raise StateError("canonical engineering storage could not save checkpoint") from error
543
620
  except Exception:
544
- connection.execute("ROLLBACK")
621
+ if connection is not None:
622
+ try:
623
+ connection.execute("ROLLBACK")
624
+ except sqlite3.DatabaseError:
625
+ pass
545
626
  raise
546
627
  finally:
547
- connection.close()
548
- except (EngineeringStorageError, OSError) as error:
549
- raise StateError("canonical engineering storage could not save checkpoint") from error
628
+ if connection is not None:
629
+ connection.close()
630
+ else:
631
+ raise StateError("canonical engineering storage could not save checkpoint")
632
+ if self._lifecycle_logger is not None:
633
+ from .component_logging import log_event
634
+ log_event(
635
+ self._lifecycle_logger,
636
+ logging.INFO if not state.terminal or state.phase == "COMPLETE" else logging.WARNING,
637
+ "lifecycle_phase_checkpointed",
638
+ run_id=state.run_id,
639
+ diagnostic=state.diagnostic,
640
+ context={
641
+ "previous_phase": previous_phase or "INITIAL",
642
+ "phase": state.phase,
643
+ "next_action": state.next_action,
644
+ "terminal_state": state.phase if state.terminal else "RUNNING",
645
+ "execution_mode": state.execution_mode,
646
+ },
647
+ )
550
648
  # CENTRAL runs must not create a repository-local checkpoint shadow.
551
649
  # The database row above is the sole durable state and is sufficient
552
650
  # for restart, recovery and Console/history projections.
@@ -119,7 +119,7 @@ button:not(.theme-toggle):not(.section-state-toggle):hover:not(:disabled){backgr
119
119
  #copyToast{align-items:center;background:var(--house-style-surface);border:1px solid var(--house-style);border-radius:999px;box-shadow:0 8px 24px #0009;box-sizing:border-box;color:var(--house-style-contrast);display:flex;font:600 13px system-ui;gap:8px;inset:auto;inset-block-end:max(20px,env(safe-area-inset-bottom));inset-inline-start:50%;margin:0;max-width:calc(100vw - 32px);opacity:0;padding:10px 15px;pointer-events:none;position:fixed;transform:translate(-50%,16px);transition:opacity .16s ease,transform .16s ease;z-index:110}#copyToast::before{content:attr(data-toast-glyph);font:700 17px/1 system-ui}#copyToast.copy-toast--visible{opacity:1;transform:translate(-50%,0)}
120
120
  body{overflow-x:hidden}.dashboard-grid,.dashboard-grid>*{min-width:0}.telemetry,.platform-health{min-width:0}.telemetry-scroll{max-width:100%;-webkit-overflow-scrolling:touch}.platform-health__component{min-width:0}.platform-health__component-detail{overflow-wrap:anywhere}.dashboard-titlebar{align-items:center;background:#121217;box-shadow:0 10px 18px #121217;box-sizing:border-box;display:flex;gap:14px;justify-content:space-between;margin:0 0 18px;max-width:100%;padding:8px 16px 12px;position:sticky;top:0;width:100%;z-index:15}.dashboard-titlebar:has(+.dashboard-status-banner:not([hidden])){margin-bottom:0}.dashboard-status-banner{align-items:flex-start;box-sizing:border-box;display:flex;gap:8px;margin:0 0 18px;padding:10px 16px;position:sticky;top:0;width:100%;z-index:14}.dashboard-status-banner[hidden]{display:none}.dashboard-status-banner--usage-limit,.dashboard-status-banner--usage-warning,.dashboard-status-banner--usage-critical{box-shadow:0 10px 18px #121217;font:600 13px/1.45 system-ui}.dashboard-status-banner--usage-limit{background:color-mix(in srgb,var(--house-style) 24%,#241b16);border-bottom:1px solid var(--house-style);color:#fff0dc}.dashboard-status-banner--usage-limit strong{color:var(--house-style)}.dashboard-status-banner--usage-warning{background:#5b4316;border-bottom:1px solid #f4c34f;color:#fff4d6}.dashboard-status-banner--usage-warning strong{color:#ffd768}.dashboard-status-banner--usage-critical{background:#5b1d27;border-bottom:1px solid #ff6b7d;color:#ffe9ed}.dashboard-status-banner--usage-critical strong{color:#ff99a7}.dashboard-status-banner strong{flex:none}.dashboard-status-banner span{min-width:0}.dashboard-titlebar__brand{align-items:center;display:flex;flex:1 1 260px;gap:10px;min-width:0}.dashboard-titlebar h1{font-size:28px;line-height:1.1;margin:0;overflow-wrap:anywhere}.dashboard-titlebar__actions{align-items:center;display:flex;flex:none;gap:12px}.auto-refresh-toggle{align-items:center;color:#b9b6c0;cursor:pointer;display:flex;flex:none;font-size:12px;gap:7px;white-space:nowrap}.auto-refresh-toggle input{accent-color:#54d6a0;height:18px;margin:0;width:18px}.section-state-toggle{align-items:center;background:transparent;border:0;color:#b9b6c0;cursor:pointer;display:flex;font:12px system-ui;gap:7px;margin:0;min-height:44px;min-width:44px;padding:0;position:relative}.section-state-toggle::before{background:#4a4a55;border-radius:999px;content:"";height:24px;transition:background .18s ease;width:42px}.section-state-toggle::after{background:#f7f3ee;border-radius:50%;box-shadow:0 1px 3px #0008;content:"";height:18px;left:3px;position:absolute;top:13px;transform:translateX(0);transition:transform .18s ease;width:18px}.section-state-toggle[aria-checked="true"]::before{background:#8dc7ff}.section-state-toggle[aria-checked="true"]::after{transform:translateX(18px)}.section-state-toggle:focus-visible{box-shadow:none;outline:2px solid #8dc7ff;outline-offset:3px}@media (max-width:1400px){.dashboard-titlebar{align-items:flex-start;flex-wrap:wrap}.dashboard-titlebar__actions{flex:1 1 100%;flex-wrap:wrap;justify-content:flex-end}}@media (max-width:760px){.dashboard-titlebar__actions{justify-content:flex-start}}@media (max-width:620px){.dashboard-status-banner{align-items:stretch;flex-direction:column;margin-bottom:12px;padding:10px 14px}.dashboard-titlebar h1{font-size:25px}.auto-refresh-toggle span,.section-state-toggle__label{display:none}.dashboard-titlebar__actions{gap:8px}}html[data-theme="light"] .dashboard-status-banner--usage-limit{background:color-mix(in srgb,var(--house-style) 18%,#fff);color:#643a13}html[data-theme="light"] .dashboard-status-banner--usage-warning{background:#fff4d6;color:#654600}html[data-theme="light"] .dashboard-status-banner--usage-critical{background:#ffe8eb;color:#7d1726}
121
121
  .dashboard-titlebar__brand{align-items:center;display:flex;gap:10px;min-width:0}.dashboard-app-icon{border-radius:9px;display:block;flex:none;height:32px;width:32px}@media (max-width:620px){.dashboard-app-icon{height:28px;width:28px}}
122
- .inbox-queue{--category-color:#818cf8;background:#25243a;border:2px solid var(--category-color);border-radius:18px;box-shadow:0 5px 24px #0006;cursor:pointer;padding:14px}.inbox-queue>summary{border-bottom:1px solid var(--category-color);box-sizing:border-box;cursor:pointer;display:block;list-style:none;margin-bottom:8px;min-height:35px;padding:0 40px 10px 0;position:relative}.inbox-queue>summary::-webkit-details-marker{display:none}.inbox-queue>summary::before{color:var(--category-color);content:"▸ ";font-size:24px;line-height:1;margin:0;padding:0;position:absolute;right:0;top:0;vertical-align:-2px}.inbox-queue[open]>summary::before{content:"▾ "}.inbox-queue>summary>strong{color:var(--category-color);font-size:17px;font-weight:700;letter-spacing:.04em;line-height:1.25;text-transform:uppercase}.inbox-queue .category-description{color:#c9c7e2;font-size:14px;line-height:1.4;margin:12px 0}.inbox-queue .estimate-meta{color:#c9c7e2}.inbox-queue .queue-item{border-top-color:#48446f}
122
+ .inbox-queue{--category-color:#818cf8;background:#24242d;border:2px solid var(--category-color);border-radius:18px;box-shadow:0 5px 24px #0006;cursor:pointer;padding:14px}.inbox-queue>summary{border-bottom:1px solid var(--category-color);box-sizing:border-box;cursor:pointer;display:block;list-style:none;margin-bottom:8px;min-height:35px;padding:0 40px 10px 0;position:relative}.inbox-queue>summary::-webkit-details-marker{display:none}.inbox-queue>summary::before{color:var(--category-color);content:"▸ ";font-size:24px;line-height:1;margin:0;padding:0;position:absolute;right:0;top:0;vertical-align:-2px}.inbox-queue[open]>summary::before{content:"▾ "}.inbox-queue>summary>strong{color:var(--category-color);font-size:17px;font-weight:700;letter-spacing:.04em;line-height:1.25;text-transform:uppercase}.inbox-queue .category-description{color:#c9c7e2;font-size:14px;line-height:1.4;margin:12px 0}.inbox-queue .estimate-meta{color:#c9c7e2}.inbox-queue .queue-item{border-top-color:#48446f}
123
123
  .prompt-history{--category-color:#f29ab2;background:#36232d;border:2px solid var(--category-color);border-radius:18px;box-shadow:0 5px 24px #0006;cursor:pointer;padding:14px}.prompt-history>summary{border-bottom:1px solid var(--category-color);box-sizing:border-box;cursor:pointer;display:block;list-style:none;margin-bottom:8px;min-height:35px;padding:0 40px 10px 0;position:relative}.prompt-history>summary::-webkit-details-marker{display:none}.prompt-history>summary::before{color:var(--category-color);content:"▸ ";font-size:24px;line-height:1;margin:0;padding:0;position:absolute;right:0;top:0;vertical-align:-2px}.prompt-history[open]>summary::before{content:"▾ "}.prompt-history>summary>strong{color:var(--category-color);font-size:17px;font-weight:700;letter-spacing:.04em;line-height:1.25;text-transform:uppercase}.prompt-history .category-description{color:#dfc3ce;font-size:14px;line-height:1.4;margin:12px 0}.prompt-history .log-controls label,.prompt-history .log-table th{color:var(--category-color)}.prompt-history .log-table-wrap{border-color:color-mix(in srgb,var(--category-color) 55%,#3d3651)}.prompt-history .log-table th,.prompt-history .log-table td{border-bottom-color:color-mix(in srgb,var(--category-color) 30%,#3d3651)}.prompt-history .log-table th.log-sortable::after{color:var(--category-color)}.prompt-history .log-table th.log-sortable:focus-visible{outline:2px solid var(--category-color);outline-offset:-2px}.prompt-history .log-pagination button{background:#442b37;border-color:var(--category-color);color:#ffe9ef}.prompt-history-report,.prompt-history-analysis{align-items:center;background:transparent;border:1px solid var(--category-color);border-radius:50%;color:var(--category-color);display:inline-flex;font:16px/1 system-ui;justify-content:center;min-height:32px;min-width:32px;padding:0}.prompt-history-report:hover,.prompt-history-analysis:hover{background:var(--category-color);color:#271923}.prompt-history-analysis-actions{align-items:center;display:flex;gap:6px}.prompt-history-status{font-weight:700}.prompt-history-status--complete{color:#54d6a0}.prompt-history-status--blocked{color:#f0b66a}.prompt-history-status--failed{color:#ff718f}.report-view-modal{background:transparent;border:0;max-height:90vh;max-width:min(1000px,94vw);padding:0;width:min(1000px,94vw)}.report-view-modal::backdrop{background:#0d1018bb}.report-view-modal__panel{--category-color:#8dc7ff;background:#24242d;border:2px solid var(--category-color);border-radius:18px;box-shadow:0 16px 50px #000a;color:#f7f3ee;max-height:90vh;overflow:auto;padding:18px;position:relative}.report-view-modal__title{color:var(--category-color);font-size:20px;margin:0 80px 14px 0}.report-view-modal__actions{display:flex;gap:8px;position:absolute;right:16px;top:14px}.report-view-modal__actions .copy,.report-view-modal__actions .download{position:static}.report-view-modal__content{min-height:80px;padding:12px}.report-view-modal__close{background:#24242d;border:1px solid var(--category-color);border-radius:50%;color:var(--category-color);font:22px/1 system-ui;height:32px;min-height:32px;min-width:32px;padding:0}.report-view-modal__close:hover{background:var(--category-color);color:#17151a}
124
124
  .prompt-history-details{align-items:center;background:transparent;border:1px solid #8dc7ff;border-radius:50%;color:#8dc7ff;display:inline-flex;font:700 19px/1 system-ui;justify-content:center;min-height:32px;min-width:32px;padding:0}.prompt-history-details:hover{background:#8dc7ff!important;border-color:#8dc7ff!important;color:#172331!important}.prompt-history-run-id-field{align-items:center;display:flex;flex-wrap:wrap;gap:8px}.prompt-history-run-id-field .label{flex-basis:100%}.prompt-history-run-id-field pre{margin:0}.prompt-history-run-id-copy{align-items:center;background:transparent;border:1px solid #8dc7ff;border-radius:50%;color:#8dc7ff;display:inline-flex;font:700 16px/1 system-ui;justify-content:center;min-height:28px;min-width:28px;padding:0}.prompt-history-run-id-copy:hover{background:#8dc7ff!important;border-color:#8dc7ff!important;color:#172331!important}
125
125
  #promptHistory .log-table{width:100%}#promptHistory .log-table th:nth-child(2),#promptHistory .log-table td:nth-child(2){width:100%}
@@ -273,7 +273,7 @@ html[data-theme="light"] :is(#rateLimitReset,#codexCliUpdate){background:#e8fff5
273
273
  .prompt-history-row{cursor:pointer}.prompt-history-lineage{color:#b9b6c0;display:block;font:11px/1.35 system-ui;margin-top:4px;white-space:normal}
274
274
  /* The shared modal shell owns the prompt-detail frame and header. This
275
275
  component owns only its evidence layout and its inner document cards. */
276
- .prompt-detail-modal__panel{display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;overflow:hidden}.prompt-detail-modal__content{align-items:start;box-sizing:border-box;display:grid;gap:18px;grid-template-columns:minmax(0,1fr) minmax(280px,.82fr);min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 12px 10px;scrollbar-gutter:stable both-edges}.prompt-detail-leftbar,.prompt-detail-rightbar{align-content:start;align-items:start;display:grid;gap:18px;grid-row:1;min-width:0}.prompt-detail-leftbar{grid-column:1}.prompt-detail-rightbar{grid-column:2}.prompt-detail-leftbar :is(.prompt-detail-card--execution-summary,.prompt-detail-sidebar),.prompt-detail-rightbar :is(.prompt-detail-card--execution-context,.prompt-detail-card--pull-requests){grid-column:auto;grid-row:auto}.prompt-detail-sidebar{align-content:start;align-items:start;display:grid;gap:18px}.prompt-detail-card{border:1px solid var(--category-color);border-radius:14px;padding:18px}.prompt-detail-card--wide{grid-column:1/-1}.prompt-detail-card h3{color:var(--category-color);font-size:18px;margin:0 0 14px}.prompt-detail-card .field{margin:0 0 14px}.prompt-detail-card .field:last-child{margin-bottom:0}.prompt-detail-card pre{overflow-wrap:anywhere;white-space:pre-wrap}.prompt-detail-card--execution-context{min-width:0;overflow:hidden}.prompt-detail-card--execution-context :is(.field,.label,span,li){min-width:0;overflow-wrap:anywhere;word-break:break-word}.detail-list-field ul{margin:6px 0 0;padding-inline-start:22px}@media (max-width:620px){.prompt-detail-modal__content{grid-template-columns:1fr;padding-inline:8px}.prompt-detail-leftbar,.prompt-detail-rightbar{grid-column:1;grid-row:auto}}
276
+ .prompt-detail-modal__panel{display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;overflow:hidden}.prompt-detail-modal__content{align-items:start;box-sizing:border-box;display:grid;gap:18px;grid-template-columns:minmax(0,1fr) minmax(280px,.82fr);min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 12px 10px;scrollbar-gutter:stable both-edges}.prompt-detail-leftbar,.prompt-detail-rightbar{align-content:start;align-items:start;display:grid;gap:18px;grid-row:1;min-width:0}.prompt-detail-leftbar{grid-column:1}.prompt-detail-rightbar{grid-column:2}.prompt-detail-leftbar :is(.prompt-detail-card--execution-summary,.prompt-detail-sidebar),.prompt-detail-rightbar :is(.prompt-detail-card--execution-context,.prompt-detail-card--pull-requests){grid-column:auto;grid-row:auto}.prompt-detail-sidebar{align-content:start;align-items:start;display:grid;gap:18px}.prompt-detail-card{border:1px solid var(--category-color);border-radius:14px;padding:18px}.prompt-detail-card--wide{grid-column:1/-1}.prompt-detail-card h3{color:var(--category-color);font-size:18px;margin:0 0 14px}.prompt-detail-card .field{margin:0 0 14px}.prompt-detail-card .field:last-child{margin-bottom:0}.prompt-detail-card pre{overflow-wrap:anywhere;white-space:pre-wrap}.prompt-detail-diagnostic>span:last-child{white-space:pre-wrap}.prompt-detail-card--execution-context{min-width:0;overflow:hidden}.prompt-detail-card--execution-context :is(.field,.label,span,li){min-width:0;overflow-wrap:anywhere;word-break:break-word}.detail-list-field ul{margin:6px 0 0;padding-inline-start:22px}@media (max-width:620px){.prompt-detail-modal__content{grid-template-columns:1fr;padding-inline:8px}.prompt-detail-leftbar,.prompt-detail-rightbar{grid-column:1;grid-row:auto}}
277
277
  .prompt-detail-provider-review{display:grid;gap:18px;grid-column:1/-1;grid-template-columns:minmax(0,1fr) minmax(260px,.58fr)}@media (max-width:760px){.prompt-detail-provider-review{grid-template-columns:1fr}}
278
278
  .prompt-detail-provider-review-stack{display:grid;gap:18px;grid-column:1/-1}.prompt-detail-provider-review>.prompt-detail-card{align-self:stretch;box-sizing:border-box}.prompt-detail-card--commit-timeline{display:flex;flex-direction:column;min-height:0}.prompt-detail-commit-timeline__list{align-content:start;display:grid;flex:1;gap:10px;list-style:none;margin:0;max-height:none;min-height:0;overflow:auto;padding:0 8px 0 0;scrollbar-gutter:stable}.prompt-detail-commit-timeline__item{border-top:1px solid color-mix(in srgb,var(--category-color) 38%,transparent);display:grid;gap:3px;padding-top:10px}.prompt-detail-commit-timeline__item:first-child{border-top:0;padding-top:0}.prompt-detail-commit-timeline__meta{color:var(--dashboard-modal-muted);font-size:12px;line-height:1.35}.prompt-detail-commit-timeline__item code{font-size:12px;overflow-wrap:anywhere}.prompt-detail-commit-timeline__item>span{font-size:13px;line-height:1.4;overflow-wrap:anywhere}
279
279
  .prompt-detail-commit-timeline__phase{border-top:1px solid color-mix(in srgb,var(--category-color) 52%,transparent);list-style:none;padding:13px 0 0}.prompt-detail-commit-timeline__phase:first-child{border-top:0;padding-top:0}.prompt-detail-commit-timeline__phase h4{color:var(--category-color);font-size:12px;letter-spacing:.04em;margin:0 0 9px;text-transform:uppercase}.prompt-detail-commit-timeline__phase-entries{display:grid;gap:10px;list-style:none;margin:0;padding:0 0 2px}.prompt-detail-commit-timeline__phase-entries .prompt-detail-commit-timeline__item{border-top:0;padding-top:0}
@@ -406,7 +406,7 @@ html[data-theme="light"] :is(.dashboard-locale,.dashboard-project){color:#415168
406
406
 
407
407
  /* Main sections */
408
408
  .dashboard-grid{gap:var(--dashboard-section-gap)}
409
- .execution-context--primary{background:#1f3140!important;border-color:#65c5d9!important}.execution-context--primary strong{color:#8de1f2!important}.execution-context--primary .field{border-top:1px solid #65c5d955;padding-top:8px}.execution-context--primary .field:first-of-type{border-top:0;padding-top:0}.execution-context__phase{border:1px solid currentColor;border-radius:999px;display:inline-block;font-weight:700;padding:4px 8px}.execution-context__planning-empty{border-top:1px solid #65c5d955;color:var(--dashboard-modal-muted);font-size:14px;line-height:1.45;margin:0;padding-top:10px}
409
+ .execution-context--primary{background:#1f3140!important;border-color:#65c5d9!important}.execution-context--primary strong{color:#8de1f2!important}.execution-context--primary .field{border-top:1px solid #65c5d955;padding-top:8px}.execution-context--primary .field:first-of-type{border-top:0;padding-top:0}.execution-context__planning-empty{border-top:1px solid #65c5d955;color:var(--dashboard-modal-muted);font-size:14px;line-height:1.45;margin:0;padding-top:10px}
410
410
  .execution-mode-field__value{align-items:center;display:flex;gap:10px;justify-content:space-between;min-width:0}.execution-mode-field__value>span{min-width:0;overflow-wrap:anywhere}.execution-mode-info{color:#65c5d9;flex:none;grid-area:auto}.execution-mode-info:hover{background:#65c5d9!important;border-color:#65c5d9!important;color:#162832!important}
411
411
  .workspace-card{margin-bottom:0}
412
412
  .workspace-card,.inbox-queue,.prompt-history,#rateLimits,#componentLogs,#codexChat,#engineering-dashboard-content>.technical-details:not(#componentLogs),.telemetry,.platform-health,.current-run{box-shadow:none}
@@ -433,7 +433,7 @@ html[data-theme="light"] :is(.dashboard-locale,.dashboard-project){color:#415168
433
433
  @media (max-width:620px) and (orientation:portrait) and (hover:none) and (pointer:coarse){
434
434
  /* iOS handles a document scroll more reliably than a nested flex scroller.
435
435
  It also lets the title naturally leave the viewport with the content. */
436
- .dashboard-sticky-header{position:static}.dashboard-titlebar{position:static}
436
+ .dashboard-sticky-header{max-height:none;overflow:visible;overscroll-behavior:auto;position:static}.dashboard-titlebar{position:static}
437
437
  body{display:block;height:auto;min-height:100dvh;overflow-x:hidden;overflow-y:auto;padding-inline:max(12px,env(safe-area-inset-left)) max(12px,env(safe-area-inset-right))}
438
438
  .dashboard-scroll-region{min-height:auto;overflow:visible;padding-inline:6px;scrollbar-gutter:stable both-edges}
439
439
  .footer{box-sizing:border-box;display:flex;flex-wrap:wrap;gap:4px 10px;justify-content:center;overflow:visible;padding-inline:6px;text-align:center;white-space:normal}
@@ -639,7 +639,7 @@ html[data-theme="light"] :is(.log-table,.telemetry-table) tbody tr:hover>td:firs
639
639
  #currentRun{--category-color:#65c5d9;--category-secondary:#a7e7f2;background:#1e2b33}
640
640
  #currentRun{container-name:active-execution;container-type:inline-size}
641
641
  #currentRun .current-run__grid,#currentRun .current-run__grid>*{min-width:0}
642
- @container active-execution (min-width:760px){#currentRun .current-run__grid{grid-template-columns:repeat(2,minmax(0,1fr))}#currentRun #currentDiagnostic{grid-column:1 / -1}}
642
+ @container active-execution (min-width:760px){#currentRun .current-run__grid{grid-template-columns:repeat(2,minmax(0,1fr))}#currentRun #executionIdentity{grid-column:1}#currentRun .card:has(#executionEstimate){grid-column:2}#currentRun #executionContext,#currentRun #currentDiagnostic{grid-column:1 / -1}}
643
643
  #currentRun .card,#currentRun .card:has(#currentTime),#currentRun .card:has(#executionEstimate),#currentRun .card:has(#runId),#currentRun .card:has(#executionMode){--category-color:#65c5d9;--category-secondary:#a7e7f2;background:#1b2931;border-color:#65c5d9}
644
644
  #currentRun :is(.execution-lifecycle,.execution-context--primary){background:#1b2931!important}
645
645
  #engineering-dashboard-content>#technicalDetails{--category-color:var(--house-style);--section-secondary:#a7e7f2;background:#302a24;border-color:var(--house-style)}
@@ -985,7 +985,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
985
985
  /* Telemetry can contain multiple long tables. Keep its outer dialog within
986
986
  the visual viewport and scroll only its evidence body on small screens. */
987
987
  .telemetry-detail-modal{--modal-accent:#fb7185;--category-color:var(--modal-accent);--modal-outer-gutter:24px;--modal-panel-max-width:1120px;--modal-shell-inset:24px;--modal-shell-padding:0}.telemetry-detail-modal__panel{--modal-header-inset:var(--dashboard-modal-panel-padding);display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;max-height:100%;overflow:hidden;width:min(1120px,100%)}.telemetry-detail-modal__content{max-height:none;min-height:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding:0 4px 4px}@media(max-width:620px){.telemetry-detail-modal__panel{--modal-header-inset:18px;padding:18px}.telemetry-detail-modal__content{padding-inline:2px}}
988
- .lifecycle-detail-modal{--modal-default-accent:#65c5d9}.lifecycle-detail-modal__panel{background:var(--modal-surface);border:2px solid var(--modal-accent);border-radius:var(--dashboard-modal-radius);box-sizing:border-box;color:var(--dashboard-modal-ink);display:grid;grid-template-rows:auto minmax(0,1fr);max-width:min(680px,calc(100vw - 32px));overflow:hidden;padding:var(--dashboard-modal-panel-padding);width:100%}.lifecycle-detail-modal__content{color:var(--dashboard-modal-ink);display:grid;gap:18px;max-height:none;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px}.lifecycle-detail-modal__content .field>span:last-child{color:var(--dashboard-modal-ink)}.lifecycle-detail-modal__content h3{color:var(--modal-accent);font-size:16px;margin:0 0 8px}.lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:var(--modal-secondary-accent)}.lifecycle-detail-modal__phase-list{display:grid;gap:8px;list-style:none;margin:0;padding:0}.lifecycle-detail-modal__phase-list li{align-items:baseline;border-bottom:1px solid color-mix(in srgb,var(--modal-accent) 32%,transparent);display:flex;gap:12px;justify-content:space-between;padding:8px 0}.lifecycle-detail-modal__phase-list li:last-child{border-bottom:0}.lifecycle-detail-modal__phase-list span{color:var(--dashboard-modal-muted);text-align:end}html[data-theme="light"] .lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:color-mix(in srgb,var(--modal-secondary-accent) 76%,#182230)}@media(max-width:620px){.lifecycle-detail-modal__panel{max-width:calc(100vw - 32px);padding:18px}.lifecycle-detail-modal__phase-list li{align-items:flex-start;flex-direction:column;gap:4px}.lifecycle-detail-modal__phase-list span{text-align:start}}
988
+ .lifecycle-detail-modal{--modal-default-accent:#65c5d9}.lifecycle-detail-modal__panel{background:var(--modal-surface);border:2px solid var(--modal-accent);border-radius:var(--dashboard-modal-radius);box-sizing:border-box;color:var(--dashboard-modal-ink);display:grid;grid-template-rows:auto minmax(0,1fr);max-width:min(680px,calc(100vw - 32px));overflow:hidden;padding:var(--dashboard-modal-panel-padding);width:100%}.lifecycle-detail-modal__content{color:var(--dashboard-modal-ink);display:grid;gap:18px;max-height:none;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px}.lifecycle-detail-modal__content .field>span:last-child{color:var(--dashboard-modal-ink)}.lifecycle-detail-modal__content h3{color:var(--modal-accent);font-size:16px;margin:0 0 8px}.lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:var(--modal-secondary-accent)}.lifecycle-detail-modal__phase-list{display:grid;gap:8px;list-style:none;margin:0;padding:0}.lifecycle-detail-modal__phase-list li{align-items:baseline;border-bottom:1px solid color-mix(in srgb,var(--modal-accent) 32%,transparent);display:flex;gap:12px;justify-content:space-between;padding:8px 0}.lifecycle-detail-modal__phase-list li:last-child{border-bottom:0}.lifecycle-detail-modal__phase-list span{color:var(--dashboard-modal-muted);text-align:start}html[data-theme="light"] .lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:color-mix(in srgb,var(--modal-secondary-accent) 76%,#182230)}@media(max-width:620px){.lifecycle-detail-modal__panel{max-width:calc(100vw - 32px);padding:18px}.lifecycle-detail-modal__phase-list li{align-items:flex-start;flex-direction:column;gap:4px}.lifecycle-detail-modal__phase-list span{text-align:start}}
989
989
  /* A telemetry Run-ID is a redundant activator inside an interactive row.
990
990
  The row owns its continuous rose selection surface, never the text itself. */
991
991
  .telemetry-run-link{-webkit-appearance:none;appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;font:inherit;line-height:inherit;min-height:0;min-width:0;padding:0;text-align:left;text-decoration:none;white-space:nowrap}.telemetry-run-link:is(:hover,:active){background:transparent!important;color:inherit!important}.telemetry-run-link:is(:focus,:focus-visible){border-color:transparent!important;box-shadow:none!important;outline:0!important}
@@ -1228,6 +1228,7 @@ html[data-theme="light"] .dashboard-status-banner--provider-unavailable .provide
1228
1228
  outline-offset:0!important;
1229
1229
  }
1230
1230
 
1231
+
1231
1232
  /* Native date editors otherwise inherit the muted category colour from their
1232
1233
  label. They are values, so use the same high-contrast ink as every field. */
1233
1234
  #componentLogControls :is(input[type="date"],input[type="datetime-local"]){