engineering-platform 2.3.92__tar.gz → 2.3.93__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 (172) hide show
  1. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/PKG-INFO +1 -1
  2. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/pyproject.toml +1 -1
  3. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
  4. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
  5. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard.css +1 -1
  6. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard.js +139 -12
  7. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_locales.mjs +10 -0
  8. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_host.py +30 -0
  9. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/platform_version.py +1 -1
  10. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/server.py +24 -6
  11. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/server_console_services.py +24 -1
  12. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/templates/workspace-config.json +1 -1
  13. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/PKG-INFO +1 -1
  14. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/README.md +0 -0
  15. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/setup.cfg +0 -0
  16. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/__init__.py +0 -0
  17. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/__main__.py +0 -0
  18. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/agent_state.py +0 -0
  19. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/agent_trust.py +0 -0
  20. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
  21. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
  22. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  23. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  24. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
  25. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
  26. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  27. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
  28. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/assurance_scope.py +0 -0
  29. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/capability_preflight.py +0 -0
  30. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/capability_review.py +0 -0
  31. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/central_data_transfer.py +0 -0
  32. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/central_database.py +0 -0
  33. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/central_operational_reset.py +0 -0
  34. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/central_store_migration.py +0 -0
  35. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/codex_capacity.py +0 -0
  36. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/codex_chat.py +0 -0
  37. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/codex_observability.py +0 -0
  38. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/component_lock.py +0 -0
  39. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/component_logging.py +0 -0
  40. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/console_presentation.py +0 -0
  41. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/console_route_ownership.py +0 -0
  42. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/contracts/__init__.py +0 -0
  43. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/contracts/ep_consumer.py +0 -0
  44. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/contracts/models.py +0 -0
  45. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/contracts/projection.py +0 -0
  46. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_browser_validation.py +0 -0
  47. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_state.py +0 -0
  48. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_supervisor.swift +0 -0
  49. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_translation.py +0 -0
  50. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/dependabot_producer.py +0 -0
  51. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/development_profile.py +0 -0
  52. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/drift_diagnostics.py +0 -0
  53. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/emergency_recovery.py +0 -0
  54. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/engineering_memory.py +0 -0
  55. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/ep_consumer_credentials.py +0 -0
  56. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/evidence_projection.py +0 -0
  57. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_activity.py +0 -0
  58. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_context.py +0 -0
  59. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_errors.py +0 -0
  60. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_evidence.py +0 -0
  61. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_executor.py +0 -0
  62. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_finalization.py +0 -0
  63. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_host_evidence.py +0 -0
  64. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_lease.py +0 -0
  65. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_lifecycle.py +0 -0
  66. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_models.py +0 -0
  67. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_readiness.py +0 -0
  68. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_reporting.py +0 -0
  69. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_repository.py +0 -0
  70. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_timeout_policy.py +0 -0
  71. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_timing.py +0 -0
  72. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/execution_transaction.py +0 -0
  73. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/external_producer_binding.py +0 -0
  74. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/file_inbox.py +0 -0
  75. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/forensic_attribution.py +0 -0
  76. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/forensic_attribution_v2.py +0 -0
  77. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/forensic_delta.py +0 -0
  78. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/golden_scenario.py +0 -0
  79. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
  80. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/host_admin.py +0 -0
  81. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/host_preflight.py +0 -0
  82. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_relocation.py +0 -0
  83. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_activation.py +0 -0
  84. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_admission.py +0 -0
  85. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_backup.py +0 -0
  86. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_composition.py +0 -0
  87. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_executor.py +0 -0
  88. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_migration.py +0 -0
  89. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_operation.py +0 -0
  90. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_plan.py +0 -0
  91. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_preparation.py +0 -0
  92. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/investigation_ledger.py +0 -0
  93. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/legacy_inbox_migration.py +0 -0
  94. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/legacy_installation_adoption.py +0 -0
  95. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/lifecycle_worker.py +0 -0
  96. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/live_status.py +0 -0
  97. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/local_api.py +0 -0
  98. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/local_api_keychain.py +0 -0
  99. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/local_repository_binding.py +0 -0
  100. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/managed_autonomy.py +0 -0
  101. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/managed_codex_runtime.py +0 -0
  102. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/managed_workspace_readiness.py +0 -0
  103. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/merge_delegation.py +0 -0
  104. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation.py +0 -0
  105. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation_lock.py +0 -0
  106. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation_record.py +0 -0
  107. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/owner_credential_recovery.py +0 -0
  108. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/parity_context.py +0 -0
  109. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
  110. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/platform_admin.py +0 -0
  111. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/platform_api.py +0 -0
  112. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/platform_bootstrap.py +0 -0
  113. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/platform_components.py +0 -0
  114. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/pr_check_repair.py +0 -0
  115. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/pr_evidence_backfill.py +0 -0
  116. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/producer.py +0 -0
  117. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/product_installation_readback.py +0 -0
  118. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/project_agent.py +0 -0
  119. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/project_agent_service.py +0 -0
  120. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/project_topology.py +0 -0
  121. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/prompt_history.py +0 -0
  122. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_context.py +0 -0
  123. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_context_benchmark.py +0 -0
  124. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_context_scope.py +0 -0
  125. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_interruption.py +0 -0
  126. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_process_identity.py +0 -0
  127. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_readiness.py +0 -0
  128. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_recovery.py +0 -0
  129. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/provider_usage.py +0 -0
  130. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/providers.py +0 -0
  131. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/qualification.py +0 -0
  132. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/qualification_runtime.py +0 -0
  133. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/recommendation_handoff.py +0 -0
  134. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/reconciliation_adoption.py +0 -0
  135. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/release_operation.py +0 -0
  136. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/report_analysis.py +0 -0
  137. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/repository_attachment.py +0 -0
  138. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/repository_handoff.py +0 -0
  139. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/resources.py +0 -0
  140. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/reviewer_evidence.py +0 -0
  141. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/revision_binding.py +0 -0
  142. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
  143. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.3.schema.json +0 -0
  144. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
  145. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
  146. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/server_relay.py +0 -0
  147. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/server_service.py +0 -0
  148. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/status_model.py +0 -0
  149. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/status_reconciliation.py +0 -0
  150. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/storage.py +0 -0
  151. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/submission_cli.py +0 -0
  152. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/submission_intake.py +0 -0
  153. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/submission_service.py +0 -0
  154. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/system_installation_topology.py +0 -0
  155. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/system_server_service.py +0 -0
  156. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/telemetry.py +0 -0
  157. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_contract.py +0 -0
  158. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_export.py +0 -0
  159. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_metrics.py +0 -0
  160. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/terminal_evidence_reconciliation.py +0 -0
  161. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/validation_identity.py +0 -0
  162. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/validation_profile.py +0 -0
  163. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/version_preparation_delivery.py +0 -0
  164. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/workspace_preflight.py +0 -0
  165. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/worktree_provenance.py +0 -0
  166. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform/worktree_tooling.py +0 -0
  167. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/SOURCES.txt +0 -0
  168. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
  169. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/entry_points.txt +0 -0
  170. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/top_level.txt +0 -0
  171. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/tests/test_adaptive_action_sizing_design.py +0 -0
  172. {engineering_platform-2.3.92 → engineering_platform-2.3.93}/tests/test_role_task_model_policy_design.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-platform
3
- Version: 2.3.92
3
+ Version: 2.3.93
4
4
  Summary: Local-first Engineering Platform execution operations runtime
5
5
  Author: Peter van Tol
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "engineering-platform"
7
- version = "2.3.92"
7
+ version = "2.3.93"
8
8
  description = "Local-first Engineering Platform execution operations runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14,<3.15"
@@ -3,7 +3,7 @@
3
3
  "platform": {
4
4
  "id": "engineering-platform",
5
5
  "name": "Engineering Platform",
6
- "version": "2.3.92",
6
+ "version": "2.3.93",
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.92",
4
+ "dashboard_version": "2.3.93",
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.92",
9
+ "platform_version": "2.3.93",
10
10
  "report_format": 2,
11
- "runner_version": "2.3.92",
11
+ "runner_version": "2.3.93",
12
12
  "status_model": 1,
13
13
  "storage_schema": 45,
14
- "watcher_version": "2.3.92"
14
+ "watcher_version": "2.3.93"
15
15
  }
@@ -990,7 +990,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
990
990
  /* Telemetry can contain multiple long tables. Keep its outer dialog within
991
991
  the visual viewport and scroll only its evidence body on small screens. */
992
992
  .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}}
993
- .lifecycle-detail-modal{--modal-default-accent:#65c5d9;--modal-panel-max-width:920px}.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(920px,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__assurance-evidence .lifecycle-detail-modal__phase-list strong{flex:0 0 auto;white-space:nowrap}.lifecycle-detail-modal__assurance-evidence .lifecycle-detail-modal__phase-list span{flex:1 1 0;min-width:0;overflow-wrap:anywhere}.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}.lifecycle-detail-modal__assurance-evidence .lifecycle-detail-modal__phase-list strong{white-space:normal}}
993
+ .lifecycle-detail-modal{--modal-default-accent:#65c5d9;--modal-panel-max-width:920px}.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(920px,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__content h4{color:var(--dashboard-modal-ink);font-size:15px;margin:0 0 14px}.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 :is(.lifecycle-detail-modal__assurance-evidence,.lifecycle-detail-modal__reviewer-evidence) .lifecycle-detail-modal__phase-list li{align-items:flex-start;flex-direction:column;gap:7px}.lifecycle-detail-modal :is(.lifecycle-detail-modal__assurance-evidence,.lifecycle-detail-modal__reviewer-evidence) .lifecycle-detail-modal__phase-list strong{white-space:normal}.lifecycle-detail-modal :is(.lifecycle-detail-modal__assurance-evidence,.lifecycle-detail-modal__reviewer-evidence) .lifecycle-detail-modal__phase-list span{min-width:0;overflow-wrap:anywhere;width:100%}.lifecycle-detail-modal__repair-iteration{padding:4px 0 10px}.lifecycle-detail-modal__repair-iteration+.lifecycle-detail-modal__repair-iteration{border-top:1px solid color-mix(in srgb,var(--modal-accent) 48%,transparent);margin-top:18px;padding-top:22px}.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}}
994
994
  /* A telemetry Run-ID is a redundant activator inside an interactive row.
995
995
  The row owns its continuous rose selection surface, never the text itself. */
996
996
  .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}
@@ -2157,6 +2157,68 @@ function lifecycleAssuranceEvidence(step) {
2157
2157
  void localizeDynamicEvidence(dynamicRows);
2158
2158
  return section;
2159
2159
  }
2160
+ function lifecycleCapabilityEvidence(step) {
2161
+ const reviewers = Array.isArray(step?.reviewer_evidence) ? step.reviewer_evidence : [];
2162
+ if (!reviewers.length) return null;
2163
+ const section = document.createElement("section");
2164
+ section.className = "lifecycle-detail-modal__quality-evidence lifecycle-detail-modal__reviewer-evidence";
2165
+ section.append(Object.assign(document.createElement("h3"), {
2166
+ textContent: t("detail.specialist_reviews"),
2167
+ }));
2168
+ const list = document.createElement("ol");
2169
+ list.className = "lifecycle-detail-modal__phase-list";
2170
+ for (const reviewer of reviewers) {
2171
+ if (!reviewer || typeof reviewer !== "object") continue;
2172
+ const item = document.createElement("li");
2173
+ const details = [
2174
+ reviewerCapabilityLabel(reviewer.capability || "ENGINEERING"),
2175
+ reviewerStatusLabel(reviewer.status || "completed"),
2176
+ reviewer.selected_because
2177
+ ? t("detail.selected_because") + ": " + String(reviewer.selected_because)
2178
+ : null,
2179
+ reviewer.contribution
2180
+ ? t("detail.initial_observation") + ": " + String(reviewer.contribution)
2181
+ : null,
2182
+ Number.isInteger(reviewer.accepted_recommendations)
2183
+ ? t("detail.accepted_recommendations") + ": " + reviewer.accepted_recommendations
2184
+ : null,
2185
+ Number.isInteger(reviewer.rejected_recommendations)
2186
+ ? t("detail.rejected_recommendations") + ": " + reviewer.rejected_recommendations
2187
+ : null,
2188
+ ].filter(Boolean);
2189
+ item.append(
2190
+ Object.assign(document.createElement("strong"), {
2191
+ textContent: reviewerLabel(reviewer.reviewer, t("detail.specialist_review")),
2192
+ }),
2193
+ Object.assign(document.createElement("span"), {
2194
+ textContent: details.join("\n"),
2195
+ }),
2196
+ );
2197
+ list.append(item);
2198
+ }
2199
+ if (!list.childElementCount) return null;
2200
+ section.append(list);
2201
+ return section;
2202
+ }
2203
+ function lifecycleImplementationEvidence(step) {
2204
+ const evidence = step?.implementation_evidence;
2205
+ if (!evidence || typeof evidence !== "object") return null;
2206
+ const fields = [];
2207
+ if (evidence.branch) fields.push(lifecycleDetailField(t("workspace.current_branch"), String(evidence.branch)));
2208
+ if (evidence.candidate_sha) fields.push(lifecycleDetailField(t("detail.candidate_sha"), String(evidence.candidate_sha)));
2209
+ if (Number.isInteger(evidence.pull_request) && evidence.pull_request > 0) {
2210
+ fields.push(lifecycleDetailField(t("detail.implementation_pull_request"), `#${evidence.pull_request}`));
2211
+ }
2212
+ if (!fields.length) return null;
2213
+ const section = document.createElement("section");
2214
+ section.className = "lifecycle-detail-modal__implementation-evidence";
2215
+ section.append(
2216
+ Object.assign(document.createElement("h3"), { textContent: t("lifecycle.detail_implementation_evidence") }),
2217
+ Object.assign(document.createElement("div"), { className: "technical-grid" }),
2218
+ );
2219
+ section.lastElementChild.append(...fields);
2220
+ return section;
2221
+ }
2160
2222
  function lifecycleRepairEvidence(step) {
2161
2223
  const audit = Array.isArray(step?.repair_audit) ? step.repair_audit : [];
2162
2224
  if (!audit.length) return null;
@@ -2171,9 +2233,16 @@ function lifecycleRepairEvidence(step) {
2171
2233
  const iteration = String(item.iteration || "").trim();
2172
2234
  if (!iteration) continue;
2173
2235
  const heading = document.createElement("h4");
2174
- heading.textContent = t("lifecycle.detail_repair_iteration", { iteration });
2236
+ heading.textContent = t(
2237
+ step?.id === "LOCAL_REPOSITORY_VALIDATION"
2238
+ ? "lifecycle.detail_validation_pass"
2239
+ : "lifecycle.detail_repair_iteration",
2240
+ { iteration },
2241
+ );
2175
2242
  const grid = document.createElement("div");
2176
2243
  grid.className = "technical-grid";
2244
+ const iterationSection = document.createElement("section");
2245
+ iterationSection.className = "lifecycle-detail-modal__repair-iteration";
2177
2246
  const outcome = String(item.outcome || "").trim();
2178
2247
  const dynamicField = (label, source) => {
2179
2248
  const value = String(source || t("detail.not_recorded"));
@@ -2188,7 +2257,8 @@ function lifecycleRepairEvidence(step) {
2188
2257
  lifecycleDetailField(t("detail.commit"), item.commit_sha === "not_recorded" ? t("detail.not_recorded") : String(item.commit_sha || t("detail.not_recorded"))),
2189
2258
  lifecycleDetailField(t("detail.outcome"), t("lifecycle.repair_outcome." + outcome, {}, outcome || t("detail.not_recorded"))),
2190
2259
  );
2191
- section.append(heading, grid);
2260
+ iterationSection.append(heading, grid);
2261
+ section.append(iterationSection);
2192
2262
  }
2193
2263
  if (section.childElementCount <= 1) return null;
2194
2264
  void localizeDynamicEvidence(dynamicRows);
@@ -2219,16 +2289,29 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2219
2289
  content.replaceChildren();
2220
2290
  const overview = document.createElement("section"), grid = document.createElement("div");
2221
2291
  grid.className = "technical-grid";
2292
+ const rawSpans = Array.isArray(timing.spans) ? timing.spans : [];
2293
+ const activeSpan = [...rawSpans].reverse().find((span) => String(span?.outcome || "").toUpperCase() === "ACTIVE");
2222
2294
  grid.append(
2223
2295
  lifecycleDetailStatusField(step?.state),
2224
- lifecycleDetailField(t("lifecycle.detail_started_at"), formatTimestamp(timing.started_at || step?.started_at)),
2225
- lifecycleDetailField(t("lifecycle.detail_finished_at"), formatTimestamp(timing.finished_at, t("format.unavailable"))),
2296
+ lifecycleDetailField(
2297
+ t("lifecycle.detail_started_at"),
2298
+ formatTimestamp(activeSpan?.started_at || timing.started_at || step?.started_at),
2299
+ ),
2226
2300
  );
2301
+ if (String(step?.state || "").toUpperCase() !== "ACTIVE") {
2302
+ grid.append(lifecycleDetailField(
2303
+ t("lifecycle.detail_finished_at"),
2304
+ formatTimestamp(timing.finished_at, t("format.unavailable")),
2305
+ ));
2306
+ }
2227
2307
  if (Number.isInteger(step?.iteration_count) && step.iteration_count > 0) {
2228
2308
  grid.append(lifecycleDetailField(t("lifecycle.detail_iterations"), String(step.iteration_count)));
2229
2309
  }
2230
2310
  overview.append(grid); content.append(overview);
2231
- const spans = lifecyclePhaseTiming(Array.isArray(timing.spans) ? timing.spans : []);
2311
+ const localValidation = String(step?.id || "").toUpperCase() === "LOCAL_REPOSITORY_VALIDATION";
2312
+ const spans = localValidation && rawSpans.length > 1
2313
+ ? rawSpans.filter((span) => span && typeof span === "object").map((span, index) => ({ ...span, occurrence: index + 1 }))
2314
+ : lifecyclePhaseTiming(rawSpans);
2232
2315
  const phaseTiming = document.createElement("section");
2233
2316
  phaseTiming.append(Object.assign(document.createElement("h3"), { textContent: t("lifecycle.detail_phase_timing") }));
2234
2317
  if (!spans.length) {
@@ -2237,7 +2320,9 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2237
2320
  const list = document.createElement("ol"); list.className = "lifecycle-detail-modal__phase-list";
2238
2321
  for (const span of spans) {
2239
2322
  const item = document.createElement("li"), heading = document.createElement("strong"), meta = document.createElement("span");
2240
- heading.textContent = telemetryLabel(span.phase);
2323
+ heading.textContent = localValidation
2324
+ ? t("lifecycle.detail_validation_pass", { iteration: span.occurrence })
2325
+ : telemetryLabel(span.phase);
2241
2326
  meta.textContent = t("lifecycle.detail_phase_meta", {
2242
2327
  duration: telemetryMs(span.duration_ms), outcome: lifecycleStateLabel(span.outcome),
2243
2328
  });
@@ -2257,8 +2342,12 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2257
2342
  content.append(phaseTiming);
2258
2343
  const qualityEvidence = lifecycleQualityEvidence(step);
2259
2344
  if (qualityEvidence) content.append(qualityEvidence);
2345
+ const capabilityEvidence = lifecycleCapabilityEvidence(step);
2346
+ if (capabilityEvidence) content.append(capabilityEvidence);
2260
2347
  const assuranceEvidence = lifecycleAssuranceEvidence(step);
2261
2348
  if (assuranceEvidence) content.append(assuranceEvidence);
2349
+ const implementationEvidence = lifecycleImplementationEvidence(step);
2350
+ if (implementationEvidence) content.append(implementationEvidence);
2262
2351
  const repairEvidence = lifecycleRepairEvidence(step);
2263
2352
  if (repairEvidence) content.append(repairEvidence);
2264
2353
  if (!modal.open) modal.showModal();
@@ -2266,7 +2355,28 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2266
2355
  }
2267
2356
  $("lifecycleDetailClose")?.addEventListener("click", closeLifecycleDetail);
2268
2357
  $("lifecycleDetailModal")?.addEventListener("close", () => { lifecycleDetailTrigger?.focus?.(); lifecycleDetailTrigger = null; lifecycleDetailStep = null; });
2269
- function lifecycleFlow(projection, { historical = false } = {}) {
2358
+ function lifecycleStepWithEvidence(step, context = {}) {
2359
+ const enriched = { ...step };
2360
+ const id = String(step?.id || "").toUpperCase();
2361
+ if (id === "CAPABILITY_REVIEW") {
2362
+ const reviewers = Array.isArray(context.reviewer_agents)
2363
+ ? context.reviewer_agents
2364
+ : Array.isArray(context.reviewers) ? context.reviewers : [];
2365
+ if (reviewers.length) enriched.reviewer_evidence = reviewers;
2366
+ }
2367
+ if (id === "EXECUTE_AGENT") {
2368
+ const candidate = String(context.implementation_candidate_sha || "").trim();
2369
+ const branch = String(context.implementation_branch || "").trim();
2370
+ const pullRequest = Number(context.implementation_pr);
2371
+ const evidence = {};
2372
+ if (/^[0-9a-f]{40}$/.test(candidate)) evidence.candidate_sha = candidate;
2373
+ if (branch) evidence.branch = branch;
2374
+ if (Number.isInteger(pullRequest) && pullRequest > 0) evidence.pull_request = pullRequest;
2375
+ if (Object.keys(evidence).length) enriched.implementation_evidence = evidence;
2376
+ }
2377
+ return enriched;
2378
+ }
2379
+ function lifecycleFlow(projection, { historical = false, context = {} } = {}) {
2270
2380
  const section = document.createElement("section");
2271
2381
  section.className = "execution-lifecycle" + (historical ? " execution-lifecycle--historical" : "");
2272
2382
  if (projection?.run_id) section.dataset.runId = projection.run_id;
@@ -2278,7 +2388,9 @@ function lifecycleFlow(projection, { historical = false } = {}) {
2278
2388
  }
2279
2389
  const scroll = document.createElement("div"), list = document.createElement("ol");
2280
2390
  scroll.className = "execution-lifecycle__scroll"; list.className = "execution-lifecycle__path";
2281
- const steps = Array.isArray(projection.steps) ? projection.steps : [];
2391
+ const steps = Array.isArray(projection.steps)
2392
+ ? projection.steps.map((step) => lifecycleStepWithEvidence(step, context))
2393
+ : [];
2282
2394
  for (const [index, step] of steps.entries()) {
2283
2395
  const state = String(step?.state || "UNKNOWN").toLowerCase();
2284
2396
  const operatorWait = state === "active" && !historical && isOperatorMergeStep(step);
@@ -2315,8 +2427,8 @@ function lifecycleFlow(projection, { historical = false } = {}) {
2315
2427
  }
2316
2428
  scroll.append(list); section.append(scroll);
2317
2429
  const summary = document.createElement("p"); summary.className = "execution-lifecycle__summary";
2318
- const currentStep = (projection.steps || []).find((step) => step?.state === "ACTIVE")
2319
- || (projection.steps || []).find((step) => step?.state === projection?.terminal_state) || {};
2430
+ const currentStep = steps.find((step) => step?.state === "ACTIVE")
2431
+ || steps.find((step) => step?.state === projection?.terminal_state) || {};
2320
2432
  summary.textContent = t("lifecycle.summary", {
2321
2433
  step: lifecycleLabel(currentStep),
2322
2434
  status: isOperatorMergeStep(currentStep)
@@ -2395,7 +2507,7 @@ function renderActiveLifecycle(projection, execution = {}) {
2395
2507
  : 0;
2396
2508
  previous?.remove();
2397
2509
  if (projection?.run_id) {
2398
- const lifecycle = lifecycleFlow(projection);
2510
+ const lifecycle = lifecycleFlow(projection, { context: execution });
2399
2511
  const identity = $("executionIdentity"), estimate = $("executionEstimate")?.closest(".card");
2400
2512
  placeExecutionEstimate();
2401
2513
  // Keep run identity and its phase-aware estimate ahead of the read-only
@@ -2419,6 +2531,18 @@ function renderActiveLifecycle(projection, execution = {}) {
2419
2531
  revealActiveLifecycleStep(lifecycle.querySelector(".execution-lifecycle__scroll"));
2420
2532
  }
2421
2533
  renderActivePullRequests(execution, lifecycle);
2534
+ if ($("lifecycleDetailModal")?.open && lifecycleDetailStep) {
2535
+ const refreshed = (projection.steps || []).find((step) => step?.id === lifecycleDetailStep.id);
2536
+ if (refreshed) {
2537
+ const scrollTop = $("lifecycleDetailContent")?.scrollTop || 0;
2538
+ openLifecycleDetail(
2539
+ lifecycleStepWithEvidence(refreshed, execution),
2540
+ lifecycleDetailTrigger,
2541
+ { presentationOnly: true },
2542
+ );
2543
+ if ($("lifecycleDetailContent")) $("lifecycleDetailContent").scrollTop = scrollTop;
2544
+ }
2545
+ }
2422
2546
  } else {
2423
2547
  renderActivePullRequests(execution, null);
2424
2548
  }
@@ -8516,7 +8640,10 @@ function renderPromptHistoryDetail(payload) {
8516
8640
  ]),
8517
8641
  ]),
8518
8642
  promptDetailRightbar([executionContext, promptDetailPullRequestsSection(pullRequests)]),
8519
- lifecycleFlow(payload?.lifecycle, { historical: true }),
8643
+ lifecycleFlow(payload?.lifecycle, {
8644
+ historical: true,
8645
+ context: { ...history, reviewers, commit_timeline: commitTimeline, pull_requests: pullRequests },
8646
+ }),
8520
8647
  statusReconciliationCard(payload?.lifecycle?.recovery),
8521
8648
  promptDetailProviderReviewSections(usage, reviewers, commitTimeline),
8522
8649
  promptDetailAssuranceReviewsSection(assuranceReviews),
@@ -3185,6 +3185,7 @@ Object.assign(DASHBOARD_MESSAGES.es, {
3185
3185
  "log_event.terminal_report_corrected":"Informe final corregido", "log_event.active_run_lease_reconciled":"Arrendamiento de ejecución activa conciliado", "log_event.detached_runner_job_missing":"Falta la tarea de ejecución desconectada", "log_event.inbox_scan":"Bandeja de entrada analizada", "log_event.active_transaction_queue_refreshed":"Cola de ejecución activa actualizada",
3186
3186
  "log_event.inbox_log_unavailable":"Registro del monitor de bandeja de entrada no disponible", "log_event.dashboard_log_unavailable":"Registro del panel de estado no disponible"
3187
3187
  });
3188
+
3188
3189
  Object.assign(DASHBOARD_MESSAGES.en, {"telemetry.download_overview_markdown":"Download complete overview as Markdown","telemetry.download_overview_json":"Download complete overview as JSON","telemetry.export_failed":"The telemetry export could not be created. Try again.","telemetry.export_download_target":"Telemetry export download response","telemetry.timeline_truncated_full_export":"Showing {shown} of {total} spans. The complete detail export contains all spans.","telemetry.invocations_truncated_full_export":"Showing {shown} of {total} invocations. The complete detail export contains all invocations.","telemetry.timing_correlation":"Timing correlation"});
3189
3190
  Object.assign(DASHBOARD_MESSAGES.nl, {"telemetry.download_overview_markdown":"Volledig overzicht als Markdown downloaden","telemetry.download_overview_json":"Volledig overzicht als JSON downloaden","telemetry.export_failed":"De telemetrie-export kon niet worden gemaakt. Probeer opnieuw.","telemetry.export_download_target":"Downloadrespons voor telemetrie-export","telemetry.timeline_truncated_full_export":"{shown} van {total} spans worden getoond. De volledige detailexport bevat alle spans.","telemetry.invocations_truncated_full_export":"{shown} van {total} invocations worden getoond. De volledige detailexport bevat alle invocations.","telemetry.timing_correlation":"Timingkoppeling"});
3190
3191
  Object.assign(DASHBOARD_MESSAGES.de, {"telemetry.download_overview_markdown":"Vollständige Übersicht als Markdown herunterladen","telemetry.download_overview_json":"Vollständige Übersicht als JSON herunterladen","telemetry.export_failed":"Der Telemetrieexport konnte nicht erstellt werden. Versuchen Sie es erneut.","telemetry.export_download_target":"Downloadantwort des Telemetrieexports","telemetry.timeline_truncated_full_export":"{shown} von {total} Zeitspannen werden angezeigt. Der vollständige Detailexport enthält alle Zeitspannen.","telemetry.invocations_truncated_full_export":"{shown} von {total} Aufrufen werden angezeigt. Der vollständige Detailexport enthält alle Aufrufe.","telemetry.timing_correlation":"Zeitkorrelation"});
@@ -4268,3 +4269,12 @@ Object.assign(DASHBOARD_MESSAGES.fr, {
4268
4269
  Object.assign(DASHBOARD_MESSAGES.es, {
4269
4270
  "telemetry.less_than_one_second":"<1 s","telemetry.population":"Población medida","telemetry.elapsed":"Tiempo transcurrido","telemetry.provider_unique_coverage":"Cobertura del proveedor en el tiempo transcurrido","telemetry.provider_cumulative_process":"Duración acumulada del proceso proveedor","telemetry.unassigned":"Tiempo no asignado","telemetry.observed_input":"Entrada observada","telemetry.observed_output":"Salida observada","telemetry.cache_ratio":"Proporción de caché","telemetry.measurement_coverage":"Cobertura de medición","telemetry.contract_version":"Contrato de cálculo","telemetry.inclusive_title":"Carga de fase inclusiva","telemetry.inclusive_help":"Los tiempos inclusivos pueden solaparse; sus porcentajes no son aditivos.","telemetry.exclusive_title":"Distribución exclusiva del tiempo transcurrido","telemetry.exclusive_help":"Distribución sin solapamiento del tiempo medido; el trabajo independiente simultáneo aparece como paralelo/solapamiento.","telemetry.category":"Categoría","telemetry.duration":"Duración","telemetry.longest_individual_span":"Tramo individual más largo","telemetry.scope_attempt":"Este intento","telemetry.scope_chain":"Cadena de ejecución completa","telemetry.chain_coverage":"Cobertura de la cadena","telemetry.chain_attempts":"Intentos en la cadena","telemetry.original_attempts":"Intentos originales","telemetry.retries":"Reintentos","telemetry.resumes":"Reanudaciones","telemetry.chain_elapsed":"Tiempo transcurrido de la cadena","telemetry.chain_processing":"Tiempo de procesamiento medido","telemetry.inter_attempt_gaps":"Intervalos entre intentos","telemetry.outside_window":"Intentos relacionados fuera de la fecha","telemetry.mission_scope":"Ámbito de Mission","telemetry.timeline":"Cronología","telemetry.timeline_truncated":"Cronología limitada a {count} observaciones.","telemetry.invocations":"Invocaciones del proveedor","telemetry.role":"Rol","telemetry.cached_input":"Entrada en caché","telemetry.uncached_input":"Entrada sin caché","telemetry.usage_coverage":"Cobertura de uso","telemetry.invocation_id":"ID de invocación","telemetry.retry_identity":"Número de reintento","telemetry.relation":"Relación","telemetry.technical_completion":"Finalización técnica","telemetry.qualification_status":"Calificación","telemetry.autonomy_acceptance":"Aceptación de autonomía","telemetry.coverage.complete":"Completa","telemetry.coverage.partial":"Parcial","telemetry.coverage.unavailable":"No disponible","telemetry.coverage.conflict":"En conflicto","telemetry.phase.parallel_overlap":"Paralelo / solapamiento","telemetry.phase.unassigned":"No asignado"
4270
4271
  });
4272
+
4273
+ // A repair step can be entered before a pull request exists and shares its
4274
+ // bounded budget across local validation, assurance, hosted checks and
4275
+ // finalization. Keep the flow label generic; detail evidence names the cause.
4276
+ Object.assign(DASHBOARD_MESSAGES.en, {"lifecycle.step.repair_agent":"Repair round","lifecycle.detail_repair_evidence":"Completed repair rounds","lifecycle.detail_implementation_evidence":"Implementation result","lifecycle.detail_validation_pass":"Validation pass {iteration}","detail.initial_observation":"Initial observation","detail.rejected_recommendations":"Rejected recommendations"});
4277
+ Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.step.repair_agent":"Herstelronde","lifecycle.detail_repair_evidence":"Uitgevoerde herstelrondes","lifecycle.detail_implementation_evidence":"Implementatieresultaat","lifecycle.detail_validation_pass":"Validatiepass {iteration}","detail.initial_observation":"Initiële bevinding","detail.rejected_recommendations":"Afgewezen aanbevelingen"});
4278
+ Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.step.repair_agent":"Reparaturrunde","lifecycle.detail_repair_evidence":"Abgeschlossene Reparaturrunden","lifecycle.detail_implementation_evidence":"Implementierungsergebnis","lifecycle.detail_validation_pass":"Validierungsdurchlauf {iteration}","detail.initial_observation":"Erste Beobachtung","detail.rejected_recommendations":"Abgelehnte Empfehlungen"});
4279
+ Object.assign(DASHBOARD_MESSAGES.fr, {"lifecycle.step.repair_agent":"Cycle de réparation","lifecycle.detail_repair_evidence":"Cycles de réparation terminés","lifecycle.detail_implementation_evidence":"Résultat de l’implémentation","lifecycle.detail_validation_pass":"Passe de validation {iteration}","detail.initial_observation":"Observation initiale","detail.rejected_recommendations":"Recommandations rejetées"});
4280
+ Object.assign(DASHBOARD_MESSAGES.es, {"lifecycle.step.repair_agent":"Ronda de reparación","lifecycle.detail_repair_evidence":"Rondas de reparación completadas","lifecycle.detail_implementation_evidence":"Resultado de la implementación","lifecycle.detail_validation_pass":"Pasada de validación {iteration}","detail.initial_observation":"Observación inicial","detail.rejected_recommendations":"Recomendaciones rechazadas"});
@@ -3453,6 +3453,36 @@ First implementation pull-request publication gate:
3453
3453
  observed_snapshots=reviewer.usage_snapshots,
3454
3454
  )
3455
3455
  self.reviewer_records = records_for_storage(selections, results)
3456
+ # Publish the bounded advisory result before leaving CAPABILITY_REVIEW.
3457
+ # The Console can then explain what each specialist contributed while
3458
+ # the Mission continues; it must not wait for the terminal report.
3459
+ self.reviewer_runtime = [
3460
+ {
3461
+ "reviewer": str(record.get("reviewer", ""))[:80],
3462
+ "capability": str(record.get("capability", "engineering"))[:80],
3463
+ "selected_because": redact_diagnostic(
3464
+ str(record.get("selected_because", "")), limit=180,
3465
+ ),
3466
+ "contribution": redact_diagnostic(
3467
+ str(record.get("contribution", "")), limit=240,
3468
+ ),
3469
+ "accepted_recommendations": max(
3470
+ 0, int(record.get("accepted_recommendations", 0) or 0),
3471
+ ),
3472
+ "rejected_recommendations": max(
3473
+ 0, int(record.get("rejected_recommendations", 0) or 0),
3474
+ ),
3475
+ "status": "failed" if record.get("failed") else "completed",
3476
+ }
3477
+ for record in self.reviewer_records[:12]
3478
+ ]
3479
+ update_phase_metadata(
3480
+ self.root, capability_review,
3481
+ {"reviewer_agents": self.reviewer_runtime},
3482
+ )
3483
+ write_live_status(
3484
+ self.root, state, "Capability review completed", self.reviewer_runtime,
3485
+ )
3456
3486
  # Reviewer reasoning is intentionally not merged into the primary
3457
3487
  # provider context. Reviewers share the bounded factual snapshot, but
3458
3488
  # retain independent reasoning responsibility and advisory records.
@@ -12,7 +12,7 @@ from .storage import ENGINEERING_STORAGE_SCHEMA_VERSION
12
12
 
13
13
  SEMVER = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$")
14
14
  CONTRACT = re.compile(r"^(\d{4})\.(0[1-9]|1[0-2])$")
15
- CURRENT_PLATFORM_VERSION = "2.3.92"
15
+ CURRENT_PLATFORM_VERSION = "2.3.93"
16
16
  MANIFEST_FIELDS = frozenset(
17
17
  {
18
18
  "platform_version",
@@ -3770,7 +3770,9 @@ def _central_console_report_reviewers(report: bytes | None) -> list[dict[str, ob
3770
3770
  # the viewer's locale-specific fallback instead of leaking a Dutch
3771
3771
  # server string into another locale.
3772
3772
  "selected_because": field("Selected because"),
3773
+ "contribution": field("Initial observation"),
3773
3774
  "accepted_recommendations": int(accepted) if accepted and accepted.isdigit() else 0,
3775
+ "rejected_recommendations": int(rejected) if (rejected := field("Rejected recommendations")) and rejected.isdigit() else 0,
3774
3776
  "status": "completed",
3775
3777
  })
3776
3778
  if len(records) == 12:
@@ -3788,9 +3790,9 @@ def _central_console_invocation_reviewers(data_root: Path, run_id: str) -> list[
3788
3790
  """
3789
3791
  try:
3790
3792
  with storage.sqlite_connection(data_root / SERVER_DATABASE_FILENAME) as connection:
3791
- active_phase = connection.execute(
3792
- """SELECT metadata FROM execution_phase_spans
3793
- WHERE run_id=? AND phase_name='CAPABILITY_REVIEW' AND outcome='ACTIVE'
3793
+ capability_phase = connection.execute(
3794
+ """SELECT metadata,outcome FROM execution_phase_spans
3795
+ WHERE run_id=? AND phase_name='CAPABILITY_REVIEW'
3794
3796
  ORDER BY ordinal DESC LIMIT 1""",
3795
3797
  (run_id,),
3796
3798
  ).fetchone()
@@ -3803,9 +3805,9 @@ def _central_console_invocation_reviewers(data_root: Path, run_id: str) -> list[
3803
3805
  ).fetchall()
3804
3806
  except (sqlite3.DatabaseError, storage.EngineeringStorageError):
3805
3807
  return []
3806
- if active_phase is not None:
3808
+ if capability_phase is not None:
3807
3809
  try:
3808
- metadata = json.loads(str(active_phase[0]))
3810
+ metadata = json.loads(str(capability_phase[0]))
3809
3811
  except (TypeError, ValueError, json.JSONDecodeError):
3810
3812
  metadata = {}
3811
3813
  live = metadata.get("reviewer_agents") if isinstance(metadata, dict) else None
@@ -3827,8 +3829,24 @@ def _central_console_invocation_reviewers(data_root: Path, run_id: str) -> list[
3827
3829
  break
3828
3830
  projected.append({
3829
3831
  "reviewer": reviewer, "capability": capability, "status": status,
3832
+ **({"selected_because": str(item["selected_because"])[:180]}
3833
+ if isinstance(item.get("selected_because"), str) else {}),
3834
+ **({"contribution": str(item["contribution"])[:240]}
3835
+ if isinstance(item.get("contribution"), str) else {}),
3836
+ **({"accepted_recommendations": max(0, int(item["accepted_recommendations"]))}
3837
+ if isinstance(item.get("accepted_recommendations"), int)
3838
+ and not isinstance(item.get("accepted_recommendations"), bool) else {}),
3839
+ **({"rejected_recommendations": max(0, int(item["rejected_recommendations"]))}
3840
+ if isinstance(item.get("rejected_recommendations"), int)
3841
+ and not isinstance(item.get("rejected_recommendations"), bool) else {}),
3830
3842
  })
3831
- if len(projected) == len(live):
3843
+ phase_outcome = str(capability_phase[1] or "").upper()
3844
+ terminal_detail = all(
3845
+ item.get("status") in {"completed", "failed"} for item in projected
3846
+ )
3847
+ if len(projected) == len(live) and (
3848
+ phase_outcome == "ACTIVE" or terminal_detail
3849
+ ):
3832
3850
  return projected
3833
3851
  reviewers: list[dict[str, object]] = []
3834
3852
  for role, completed_at in rows:
@@ -352,13 +352,33 @@ def _project_prompt_history_detail(
352
352
 
353
353
 
354
354
  def _checkpoint_pull_request_context(checkpoint: Mapping[str, object]) -> dict[str, object]:
355
- """Project recorded PR roles, including a newly bound PR in its active phase."""
355
+ """Project recorded delivery evidence, including a newly bound active PR.
356
+
357
+ The lifecycle detail renderer needs the persisted implementation candidate
358
+ even before a pull request exists. Keep that evidence beside the PR
359
+ projection so active and historical Console views use the same checkpoint
360
+ authority instead of inferring a candidate from the current checkout.
361
+ """
356
362
  repository = checkpoint.get("repository")
357
363
  if not isinstance(repository, str) or not re.fullmatch(
358
364
  r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", repository,
359
365
  ):
360
366
  repository = None
361
367
  context: dict[str, object] = {"github_repository": repository, "pull_requests": []}
368
+ implementation_branch = checkpoint.get("implementation_branch") or checkpoint.get("branch")
369
+ if (
370
+ isinstance(implementation_branch, str)
371
+ and 0 < len(implementation_branch) <= 255
372
+ and "\x00" not in implementation_branch
373
+ ):
374
+ context["implementation_branch"] = implementation_branch
375
+ candidate_sha = (
376
+ checkpoint.get("implementation_head_sha")
377
+ or checkpoint.get("genesis_commit_sha")
378
+ or checkpoint.get("last_verified_sha")
379
+ )
380
+ if isinstance(candidate_sha, str) and re.fullmatch(r"[0-9a-f]{40}", candidate_sha):
381
+ context["implementation_candidate_sha"] = candidate_sha
362
382
  if checkpoint.get("execution_mode") not in (None, "MANAGED"):
363
383
  return context
364
384
  roles = (
@@ -1422,12 +1442,15 @@ def _reviewer_agents_for_run(root: Path, run_id: str | None) -> bytes:
1422
1442
  return " ".join(match.group(1).split())[:180]
1423
1443
 
1424
1444
  accepted = field("Accepted recommendations")
1445
+ rejected = field("Rejected recommendations")
1425
1446
  records.append(
1426
1447
  {
1427
1448
  "reviewer": " ".join(reviewer.group(1).split())[:80],
1428
1449
  "capability": field("Capability") or "engineering",
1429
1450
  "selected_because": field("Selected because") or "Niet vastgelegd.",
1451
+ "contribution": field("Initial observation") or "Niet vastgelegd.",
1430
1452
  "accepted_recommendations": int(accepted) if accepted and accepted.isdigit() else 0,
1453
+ "rejected_recommendations": int(rejected) if rejected and rejected.isdigit() else 0,
1431
1454
  "status": "Uitgevoerd",
1432
1455
  }
1433
1456
  )
@@ -3,7 +3,7 @@
3
3
  "platform": {
4
4
  "id": "engineering-platform",
5
5
  "name": "Engineering Platform",
6
- "version": "2.3.92",
6
+ "version": "2.3.93",
7
7
  "generation": 2,
8
8
  "documentation_namespace": "engineering-platform",
9
9
  "capability_registry_version": 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-platform
3
- Version: 2.3.92
3
+ Version: 2.3.93
4
4
  Summary: Local-first Engineering Platform execution operations runtime
5
5
  Author: Peter van Tol
6
6
  License: MIT