engineering-platform 2.3.92__tar.gz → 2.3.94__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.94}/PKG-INFO +1 -1
  2. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/pyproject.toml +1 -1
  3. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
  4. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
  5. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/agent_state.py +33 -1
  6. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/dashboard.css +5 -1
  7. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/dashboard.js +244 -37
  8. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/dashboard_locales.mjs +15 -0
  9. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/capability_review.py +104 -3
  10. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/dashboard_state.py +8 -7
  11. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_executor.py +64 -20
  12. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_host.py +112 -33
  13. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_reporting.py +18 -0
  14. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/live_status.py +11 -11
  15. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/platform_version.py +1 -1
  16. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/qualification_runtime.py +15 -2
  17. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/server.py +24 -6
  18. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/server_console_services.py +24 -1
  19. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/templates/workspace-config.json +1 -1
  20. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform.egg-info/PKG-INFO +1 -1
  21. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/README.md +0 -0
  22. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/setup.cfg +0 -0
  23. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/__init__.py +0 -0
  24. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/__main__.py +0 -0
  25. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/agent_trust.py +0 -0
  26. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
  27. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
  28. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  29. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  30. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
  31. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
  32. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  33. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
  34. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/assurance_scope.py +0 -0
  35. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/capability_preflight.py +0 -0
  36. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/central_data_transfer.py +0 -0
  37. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/central_database.py +0 -0
  38. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/central_operational_reset.py +0 -0
  39. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/central_store_migration.py +0 -0
  40. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/codex_capacity.py +0 -0
  41. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/codex_chat.py +0 -0
  42. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/codex_observability.py +0 -0
  43. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/component_lock.py +0 -0
  44. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/component_logging.py +0 -0
  45. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/console_presentation.py +0 -0
  46. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/console_route_ownership.py +0 -0
  47. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/contracts/__init__.py +0 -0
  48. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/contracts/ep_consumer.py +0 -0
  49. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/contracts/models.py +0 -0
  50. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/contracts/projection.py +0 -0
  51. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/dashboard_browser_validation.py +0 -0
  52. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/dashboard_supervisor.swift +0 -0
  53. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/dashboard_translation.py +0 -0
  54. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/dependabot_producer.py +0 -0
  55. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/development_profile.py +0 -0
  56. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/drift_diagnostics.py +0 -0
  57. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/emergency_recovery.py +0 -0
  58. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/engineering_memory.py +0 -0
  59. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/ep_consumer_credentials.py +0 -0
  60. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/evidence_projection.py +0 -0
  61. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_activity.py +0 -0
  62. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_context.py +0 -0
  63. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_errors.py +0 -0
  64. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_evidence.py +0 -0
  65. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_finalization.py +0 -0
  66. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_host_evidence.py +0 -0
  67. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_lease.py +0 -0
  68. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_lifecycle.py +0 -0
  69. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_models.py +0 -0
  70. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_readiness.py +0 -0
  71. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_repository.py +0 -0
  72. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_timeout_policy.py +0 -0
  73. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_timing.py +0 -0
  74. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/execution_transaction.py +0 -0
  75. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/external_producer_binding.py +0 -0
  76. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/file_inbox.py +0 -0
  77. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/forensic_attribution.py +0 -0
  78. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/forensic_attribution_v2.py +0 -0
  79. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/forensic_delta.py +0 -0
  80. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/golden_scenario.py +0 -0
  81. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
  82. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/host_admin.py +0 -0
  83. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/host_preflight.py +0 -0
  84. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_relocation.py +0 -0
  85. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_activation.py +0 -0
  86. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_admission.py +0 -0
  87. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_backup.py +0 -0
  88. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_composition.py +0 -0
  89. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_executor.py +0 -0
  90. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_migration.py +0 -0
  91. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_operation.py +0 -0
  92. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_plan.py +0 -0
  93. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/installation_update_preparation.py +0 -0
  94. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/investigation_ledger.py +0 -0
  95. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/legacy_inbox_migration.py +0 -0
  96. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/legacy_installation_adoption.py +0 -0
  97. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/lifecycle_worker.py +0 -0
  98. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/local_api.py +0 -0
  99. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/local_api_keychain.py +0 -0
  100. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/local_repository_binding.py +0 -0
  101. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/managed_autonomy.py +0 -0
  102. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/managed_codex_runtime.py +0 -0
  103. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/managed_workspace_readiness.py +0 -0
  104. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/merge_delegation.py +0 -0
  105. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/operational_installation.py +0 -0
  106. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/operational_installation_lock.py +0 -0
  107. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/operational_installation_record.py +0 -0
  108. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/owner_credential_recovery.py +0 -0
  109. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/parity_context.py +0 -0
  110. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
  111. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/platform_admin.py +0 -0
  112. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/platform_api.py +0 -0
  113. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/platform_bootstrap.py +0 -0
  114. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/platform_components.py +0 -0
  115. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/pr_check_repair.py +0 -0
  116. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/pr_evidence_backfill.py +0 -0
  117. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/producer.py +0 -0
  118. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/product_installation_readback.py +0 -0
  119. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/project_agent.py +0 -0
  120. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/project_agent_service.py +0 -0
  121. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/project_topology.py +0 -0
  122. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/prompt_history.py +0 -0
  123. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_context.py +0 -0
  124. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_context_benchmark.py +0 -0
  125. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_context_scope.py +0 -0
  126. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_interruption.py +0 -0
  127. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_process_identity.py +0 -0
  128. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_readiness.py +0 -0
  129. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_recovery.py +0 -0
  130. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/provider_usage.py +0 -0
  131. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/providers.py +0 -0
  132. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/qualification.py +0 -0
  133. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/recommendation_handoff.py +0 -0
  134. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/reconciliation_adoption.py +0 -0
  135. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/release_operation.py +0 -0
  136. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/report_analysis.py +0 -0
  137. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/repository_attachment.py +0 -0
  138. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/repository_handoff.py +0 -0
  139. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/resources.py +0 -0
  140. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/reviewer_evidence.py +0 -0
  141. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/revision_binding.py +0 -0
  142. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
  143. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/schemas/producer-readback-v1.3.schema.json +0 -0
  144. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
  145. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
  146. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/server_relay.py +0 -0
  147. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/server_service.py +0 -0
  148. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/status_model.py +0 -0
  149. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/status_reconciliation.py +0 -0
  150. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/storage.py +0 -0
  151. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/submission_cli.py +0 -0
  152. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/submission_intake.py +0 -0
  153. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/submission_service.py +0 -0
  154. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/system_installation_topology.py +0 -0
  155. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/system_server_service.py +0 -0
  156. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/telemetry.py +0 -0
  157. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/telemetry_contract.py +0 -0
  158. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/telemetry_export.py +0 -0
  159. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/telemetry_metrics.py +0 -0
  160. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/terminal_evidence_reconciliation.py +0 -0
  161. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/validation_identity.py +0 -0
  162. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/validation_profile.py +0 -0
  163. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/version_preparation_delivery.py +0 -0
  164. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/workspace_preflight.py +0 -0
  165. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/worktree_provenance.py +0 -0
  166. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform/worktree_tooling.py +0 -0
  167. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform.egg-info/SOURCES.txt +0 -0
  168. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
  169. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform.egg-info/entry_points.txt +0 -0
  170. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/src/engineering_platform.egg-info/top_level.txt +0 -0
  171. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/tests/test_adaptive_action_sizing_design.py +0 -0
  172. {engineering_platform-2.3.92 → engineering_platform-2.3.94}/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.94
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.94"
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.94",
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.94",
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.94",
10
10
  "report_format": 2,
11
- "runner_version": "2.3.92",
11
+ "runner_version": "2.3.94",
12
12
  "status_model": 1,
13
13
  "storage_schema": 45,
14
- "watcher_version": "2.3.92"
14
+ "watcher_version": "2.3.94"
15
15
  }
@@ -458,13 +458,16 @@ class TransactionState:
458
458
  raise StateError("checkpoint assurance profile is invalid")
459
459
  review_fields = {"reviewer", "status", "candidate_sha", "profile_digest", "invocation_id", "findings"}
460
460
  current_review_fields = review_fields | {"contract_version", "started_at", "completed_at"}
461
+ integral_review_fields = current_review_fields | {"coverage", "finding_dispositions"}
461
462
  finding_fields = {"id", "fingerprint", "category", "criterion", "observation", "severity", "confidence", "blocking", "disposition"}
462
463
  current_finding_fields = finding_fields | {"evidence_ref"}
464
+ coverage_fields = {"surface", "status", "evidence_ref"}
465
+ finding_disposition_fields = {"finding_id", "disposition", "evidence_ref"}
463
466
  if (
464
467
  not isinstance(state.assurance_reviews, tuple)
465
468
  or len(state.assurance_reviews) > 16
466
469
  or any(
467
- not isinstance(review, dict) or set(review) not in (review_fields, current_review_fields)
470
+ not isinstance(review, dict) or set(review) not in (review_fields, current_review_fields, integral_review_fields)
468
471
  or review.get("reviewer") not in {"quality", "security"}
469
472
  or review.get("status") not in {"PASS", "FAIL", "UNRESOLVED"}
470
473
  or not isinstance(review.get("candidate_sha"), str) or not re.fullmatch(r"[0-9a-f]{40}", review["candidate_sha"])
@@ -486,6 +489,35 @@ class TransactionState:
486
489
  or not isinstance(review.get("started_at"), str)
487
490
  or not isinstance(review.get("completed_at"), str)
488
491
  ))
492
+ or (set(review) == integral_review_fields and (
493
+ review.get("contract_version") != "2.0"
494
+ or not isinstance(review.get("started_at"), str)
495
+ or not isinstance(review.get("completed_at"), str)
496
+ or not isinstance(review.get("coverage"), list)
497
+ or not 1 <= len(review["coverage"]) <= 16
498
+ or any(
499
+ not isinstance(item, dict) or set(item) != coverage_fields
500
+ or item.get("status") not in {"REVIEWED", "NOT_APPLICABLE"}
501
+ or any(
502
+ not isinstance(value, str) or not value or len(value) > 240
503
+ or value != redact_diagnostic(value, limit=240)
504
+ for value in item.values()
505
+ )
506
+ for item in review["coverage"]
507
+ )
508
+ or not isinstance(review.get("finding_dispositions"), list)
509
+ or len(review["finding_dispositions"]) > 64
510
+ or any(
511
+ not isinstance(item, dict) or set(item) != finding_disposition_fields
512
+ or item.get("disposition") not in {"RESOLVED", "OPEN"}
513
+ or any(
514
+ not isinstance(value, str) or not value or len(value) > 240
515
+ or value != redact_diagnostic(value, limit=240)
516
+ for value in item.values()
517
+ )
518
+ for item in review["finding_dispositions"]
519
+ )
520
+ ))
489
521
  for review in state.assurance_reviews
490
522
  )
491
523
  ):
@@ -280,6 +280,8 @@ html[data-theme="light"] :is(#rateLimitReset,#codexCliUpdate){background:#e8fff5
280
280
  .prompt-detail-provider-review{display:grid;gap:18px;grid-column:1/-1;grid-template-columns:minmax(0,1fr) minmax(320px,.78fr)}@media (max-width:760px){.prompt-detail-provider-review{grid-template-columns:1fr}}
281
281
  .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:normal;white-space:nowrap}.prompt-detail-commit-timeline__item>span{font-size:13px;line-height:1.4;overflow-wrap:anywhere}
282
282
  .prompt-detail-card--evidence pre,.prompt-detail-card--reviewers pre,.prompt-detail-card--assurance-reviews pre{font-family:inherit}
283
+ .reviewer-agent__status--failed{background:#ff6b6b;box-shadow:0 0 8px #ff6b6b66;color:#351313;font:800 14px/1 system-ui;height:16px;width:16px}
284
+ .prompt-detail-reviewer{border-top:1px solid color-mix(in srgb,var(--category-color) 45%,transparent);display:grid;gap:7px;padding-top:14px}.prompt-detail-reviewer:first-of-type{border-top:0;padding-top:0}.prompt-detail-reviewer h4{color:var(--category-color);font-size:16px;margin:0 0 4px}.prompt-detail-reviewer>.field{margin:2px 0 0}.prompt-detail-reviewer__status{align-items:center;display:inline-flex;gap:8px}.prompt-detail-reviewer__status-icon{align-items:center;border-radius:50%;display:inline-flex;flex:0 0 18px;font:800 12px/1 system-ui;height:18px;justify-content:center}.prompt-detail-reviewer__status-icon--completed{background:#51d88a;box-shadow:0 0 8px #51d88a66;color:#11261d}.prompt-detail-reviewer__status-icon--failed{background:#ff6b6b;box-shadow:0 0 8px #ff6b6b66;color:#351313}.prompt-detail-reviewer__status-icon--neutral{background:#9a9aa3;color:#202027}
283
285
  .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}
284
286
  .prompt-detail-commit-timeline__phase{--commit-kind-color:#8dc7ff;border-left:3px solid var(--commit-kind-color);padding-left:10px}.prompt-detail-commit-timeline__phase--implementation{--commit-kind-color:#65c5d9}.prompt-detail-commit-timeline__phase--validation{--commit-kind-color:#65d9a3}.prompt-detail-commit-timeline__phase--quality{--commit-kind-color:#c29aff}.prompt-detail-commit-timeline__phase--repair{--commit-kind-color:#f4c34f}.prompt-detail-commit-timeline__phase--finalization{--commit-kind-color:#ff99a7}.prompt-detail-commit-timeline__phase--implementation_merge,.prompt-detail-commit-timeline__phase--finalization_merge,.prompt-detail-commit-timeline__phase--reconciliation_merge{--commit-kind-color:#f3d36a}.prompt-detail-commit-timeline__phase--reconciliation{--commit-kind-color:#73d6b0}.prompt-detail-commit-timeline__phase h4{align-items:center;color:var(--commit-kind-color);display:flex;gap:7px}.prompt-detail-commit-timeline__kind{border:1px solid currentColor;border-radius:999px;font-size:10px;line-height:1;padding:4px 6px}.prompt-detail-commit-timeline__phase-name{color:var(--dashboard-modal-muted);font-size:11px;font-weight:500;letter-spacing:0;text-transform:none;white-space:nowrap}
285
287
 
@@ -990,7 +992,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
990
992
  /* Telemetry can contain multiple long tables. Keep its outer dialog within
991
993
  the visual viewport and scroll only its evidence body on small screens. */
992
994
  .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}}
995
+ .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
996
  /* A telemetry Run-ID is a redundant activator inside an interactive row.
995
997
  The row owns its continuous rose selection surface, never the text itself. */
996
998
  .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}
@@ -1335,3 +1337,5 @@ html[data-theme="light"] :is(.dashboard-status-banner--provider-auth_required .p
1335
1337
  }
1336
1338
  .telemetry-note{color:var(--dashboard-muted,#b9b6c0);font-size:12px;line-height:1.45;margin:0 0 10px}.telemetry-run-detail{border-top:1px solid color-mix(in srgb,var(--category-color,#fb7185) 45%,transparent);display:grid;gap:16px;margin-top:16px;padding-top:16px}.telemetry-run-detail h4{color:var(--category-color,#fb7185);font-size:14px;margin:14px 0 8px}.telemetry-scope-switcher{display:flex;flex-wrap:wrap;gap:8px}.telemetry-scope-switcher button{background:var(--dashboard-expanded-content-surface,#24242d);border:1px solid color-mix(in srgb,var(--category-color,#fb7185) 72%,transparent);border-radius:7px;color:inherit;cursor:pointer;font:400 12px/1.2 system-ui;min-height:32px;padding:5px 9px}.telemetry-scope-switcher button:hover{background:color-mix(in srgb,var(--category-color,#fb7185) 14%,var(--dashboard-expanded-content-surface,#24242d));border-color:var(--category-color,#fb7185)}.telemetry-scope-switcher button[aria-selected="true"]{background:color-mix(in srgb,var(--category-color,#fb7185) 24%,var(--dashboard-expanded-content-surface,#24242d));border-color:var(--category-color,#fb7185);box-shadow:inset 3px 0 0 var(--category-color,#fb7185)}.telemetry-scope-switcher button:focus:not(:focus-visible){box-shadow:none!important;outline:0!important}.telemetry-scope-switcher button[aria-selected="true"]:focus:not(:focus-visible){box-shadow:inset 3px 0 0 var(--category-color,#fb7185)!important}.telemetry-timeline{display:grid;gap:5px;list-style:none;margin:0;padding:0}.telemetry-timeline li{border-left:2px solid color-mix(in srgb,var(--category-color,#fb7185) 60%,transparent);margin-left:calc(var(--timeline-depth,0) * 14px);padding:6px 8px;word-break:break-word}@media(max-width:620px){.telemetry-detail-modal__content .technical-grid{grid-template-columns:minmax(0,1fr)}.telemetry-scope-switcher{position:sticky;top:0;background:var(--dashboard-expanded-content-surface,#24242d);padding-block:6px;z-index:2}.telemetry-timeline li{margin-left:min(calc(var(--timeline-depth,0) * 9px),45px)}}
1337
1339
  .telemetry-timeline-axis{color:var(--dashboard-muted,#b9b6c0);display:flex;font:11px ui-monospace,monospace;justify-content:space-between;margin:4px 8px}.telemetry-timeline__label{font-size:12px;line-height:1.35}.telemetry-timeline__track{background:color-mix(in srgb,var(--category-color,#fb7185) 10%,transparent);border:1px solid color-mix(in srgb,var(--category-color,#fb7185) 24%,transparent);border-radius:4px;height:14px;margin:5px 0;overflow:hidden;position:relative}.telemetry-timeline__bar{background:var(--category-color,#fb7185);border-radius:3px;display:block;height:100%;min-width:2px;position:absolute}.telemetry-timeline__bar:focus-visible{outline:3px solid var(--house-style);outline-offset:2px}.telemetry-timeline__bar--unpositioned{background:repeating-linear-gradient(135deg,var(--category-color,#fb7185) 0 4px,transparent 4px 8px);inset:0;width:100%}.telemetry-timeline__identity{color:var(--dashboard-muted,#b9b6c0);display:block;font-size:10px;overflow-wrap:anywhere}.telemetry-export{min-width:38px}@media(max-width:620px){.telemetry-timeline-axis{margin-inline:0}.telemetry-timeline__identity{font-size:9px}.telemetry-actions{flex-wrap:wrap}}
1340
+ /* Status markers inside lifecycle assurance evidence mirror the main status language. */
1341
+ .lifecycle-detail-modal__assurance-heading{align-items:center;display:inline-flex;gap:8px}.lifecycle-detail-modal__assurance-status{align-items:center;border-radius:50%;display:inline-flex;flex:0 0 18px;font:800 12px/1 system-ui;height:18px;justify-content:center;width:18px!important}.lifecycle-detail-modal__assurance-status--passed{background:#51d88a;box-shadow:0 0 8px #51d88a66;color:#11261d!important}.lifecycle-detail-modal__assurance-status--failed{background:#ff6b6b;box-shadow:0 0 8px #ff6b6b66;color:#351313!important}.lifecycle-detail-modal__assurance-status--neutral{background:#9a9aa3;color:#202027!important}
@@ -831,12 +831,12 @@ function reviewerPresentationState(status = {}) {
831
831
  }
832
832
  function activeReviewerAgents(items, executionStatus = {}) {
833
833
  const reviewActive = String(executionStatus?.current_phase || "").toUpperCase() === "CAPABILITY_REVIEW";
834
- // A later phase may retain only a fully successful review as compact
835
- // historical evidence. Running, failed or incomplete projections stay
836
- // phase-scoped so they can never look like live reviewer work.
837
- const completedReview = Array.isArray(items) && items.length > 0
838
- && items.every((agent) => String(agent?.status || "").toLowerCase() === "completed");
839
- const agents = (reviewActive || completedReview) && Array.isArray(items) ? items : [];
834
+ // A later phase may retain a wholly terminal review as compact historical
835
+ // evidence. Running or incomplete projections stay phase-scoped so they can
836
+ // never look like live reviewer work.
837
+ const terminalReview = Array.isArray(items) && items.length > 0
838
+ && items.every((agent) => ["completed", "failed"].includes(String(agent?.status || "").toLowerCase()));
839
+ const agents = (reviewActive || terminalReview) && Array.isArray(items) ? items : [];
840
840
  let card = $("activeReviewerAgents");
841
841
  if (!card) {
842
842
  card = document.createElement("section");
@@ -871,19 +871,23 @@ function activeReviewerAgents(items, executionStatus = {}) {
871
871
  indicator = document.createElement("span"), rawStatus = String(agent?.status || "").toLowerCase(),
872
872
  status = rawStatus === "running" && presentation !== "active" ? presentation : rawStatus;
873
873
  const isRunning = status === "running";
874
- const isCompleted = ["completed", "uitgevoerd"].includes(status);
874
+ const isCompleted = ["completed", "uitgevoerd"].includes(status), isFailed = status === "failed";
875
875
  row.className = "reviewer-agent";
876
876
  header.className = "reviewer-agent__header";
877
877
  name.className = "reviewer-agent__name";
878
878
  meta.className = "reviewer-agent__meta";
879
879
  name.textContent = reviewerLabel(agent.reviewer);
880
880
  meta.textContent = `${reviewerCapabilityLabel(agent.capability || "ENGINEERING")} · ${reviewerStatusLabel(status || "selected")}`;
881
- if (isRunning || isCompleted) {
882
- indicator.className = `reviewer-agent__status reviewer-agent__status--${isRunning ? "running" : "completed"}`;
881
+ if (isRunning || isCompleted || isFailed) {
882
+ const tone = isRunning ? "running" : isFailed ? "failed" : "completed";
883
+ indicator.className = `reviewer-agent__status reviewer-agent__status--${tone}`;
883
884
  indicator.setAttribute("role", "status");
884
- indicator.setAttribute("aria-label", isRunning ? t("ui.reviewer_status_running") : t("ui.reviewer_status_completed"));
885
+ indicator.setAttribute("aria-label", isRunning
886
+ ? t("ui.reviewer_status_running")
887
+ : isFailed ? reviewerStatusLabel("failed") : t("ui.reviewer_status_completed"));
885
888
  indicator.setAttribute("title", indicator.getAttribute("aria-label"));
886
889
  if (isCompleted) indicator.textContent = "✓";
890
+ if (isFailed) indicator.textContent = "×";
887
891
  }
888
892
  header.append(name, indicator);
889
893
  row.append(header, meta);
@@ -2143,12 +2147,31 @@ function lifecycleAssuranceEvidence(step) {
2143
2147
  for (const review of reviews) {
2144
2148
  if (!review || typeof review !== "object") continue;
2145
2149
  const findings = Array.isArray(review.findings) ? review.findings : [];
2146
- const item = document.createElement("li");
2147
- const role = String(review.reviewer || ""); const status = String(review.status || "UNRESOLVED");
2148
- item.append(Object.assign(document.createElement("strong"), { textContent: `${reviewerLabel(role, role)} · ${assuranceStatusLabel(status, status)}` }));
2150
+ const item = document.createElement("li"), heading = document.createElement("strong"),
2151
+ statusIcon = document.createElement("span"), status = String(review.status || "UNRESOLVED"),
2152
+ normalizedStatus = status.toUpperCase();
2153
+ const role = String(review.reviewer || "");
2154
+ const passed = normalizedStatus === "PASS", failed = ["FAIL", "FAILED", "UNRESOLVED"].includes(normalizedStatus);
2155
+ heading.className = "lifecycle-detail-modal__assurance-heading";
2156
+ statusIcon.className = "lifecycle-detail-modal__assurance-status lifecycle-detail-modal__assurance-status--"
2157
+ + (passed ? "passed" : failed ? "failed" : "neutral");
2158
+ statusIcon.setAttribute("aria-hidden", "true");
2159
+ statusIcon.textContent = passed ? "✓" : failed ? "×" : "•";
2160
+ heading.append(statusIcon, Object.assign(document.createElement("span"), {
2161
+ textContent: `${reviewerLabel(role, role)} · ${assuranceStatusLabel(status, status)}`,
2162
+ }));
2163
+ item.append(heading);
2149
2164
  const summary = findings.map((finding) => String(finding?.observation || "").trim()).filter(Boolean).join("; ");
2150
2165
  const summaryElement = Object.assign(document.createElement("span"), { textContent: summary || t("lifecycle.assurance_no_findings") });
2151
2166
  item.append(summaryElement);
2167
+ const coverage = Array.isArray(review.coverage) ? review.coverage : [];
2168
+ const dispositions = Array.isArray(review.finding_dispositions) ? review.finding_dispositions : [];
2169
+ if (coverage.length || dispositions.length) item.append(Object.assign(document.createElement("span"), {
2170
+ className: "estimate-meta",
2171
+ textContent: t("lifecycle.assurance_integral_evidence", {
2172
+ coverage: coverage.length, dispositions: dispositions.length,
2173
+ }),
2174
+ }));
2152
2175
  if (summary) dynamicRows.push({ source: summary, element: summaryElement });
2153
2176
  list.append(item);
2154
2177
  }
@@ -2157,6 +2180,94 @@ function lifecycleAssuranceEvidence(step) {
2157
2180
  void localizeDynamicEvidence(dynamicRows);
2158
2181
  return section;
2159
2182
  }
2183
+ function lifecycleCapabilityEvidence(step) {
2184
+ const reviewers = Array.isArray(step?.reviewer_evidence) ? step.reviewer_evidence : [];
2185
+ if (!reviewers.length) return null;
2186
+ const section = document.createElement("section");
2187
+ section.className = "lifecycle-detail-modal__quality-evidence lifecycle-detail-modal__reviewer-evidence";
2188
+ section.append(Object.assign(document.createElement("h3"), {
2189
+ textContent: t("detail.specialist_reviews"),
2190
+ }));
2191
+ const list = document.createElement("ol");
2192
+ list.className = "lifecycle-detail-modal__phase-list";
2193
+ for (const reviewer of reviewers) {
2194
+ if (!reviewer || typeof reviewer !== "object") continue;
2195
+ const item = document.createElement("li");
2196
+ const details = [
2197
+ reviewerCapabilityLabel(reviewer.capability || "ENGINEERING"),
2198
+ reviewerStatusLabel(reviewer.status || "completed"),
2199
+ reviewer.selected_because
2200
+ ? t("detail.selected_because") + ": " + String(reviewer.selected_because)
2201
+ : null,
2202
+ reviewer.contribution
2203
+ ? t("detail.initial_observation") + ": " + String(reviewer.contribution)
2204
+ : null,
2205
+ Number.isInteger(reviewer.accepted_recommendations)
2206
+ ? t("detail.accepted_recommendations") + ": " + reviewer.accepted_recommendations
2207
+ : null,
2208
+ Number.isInteger(reviewer.rejected_recommendations)
2209
+ ? t("detail.rejected_recommendations") + ": " + reviewer.rejected_recommendations
2210
+ : null,
2211
+ ].filter(Boolean);
2212
+ item.append(
2213
+ Object.assign(document.createElement("strong"), {
2214
+ textContent: reviewerLabel(reviewer.reviewer, t("detail.specialist_review")),
2215
+ }),
2216
+ Object.assign(document.createElement("span"), {
2217
+ textContent: details.join("\n"),
2218
+ }),
2219
+ );
2220
+ list.append(item);
2221
+ }
2222
+ if (!list.childElementCount) return null;
2223
+ section.append(list);
2224
+ return section;
2225
+ }
2226
+ function lifecyclePullRequestField(label, pullRequest, repository) {
2227
+ const field = lifecycleDetailField(label, `#${pullRequest}`);
2228
+ const repositoryIdentity = String(repository || "").trim();
2229
+ if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repositoryIdentity)) return field;
2230
+ const link = document.createElement("a");
2231
+ link.className = "prompt-detail-pr-link";
2232
+ link.href = `https://github.com/${repositoryIdentity.split("/").map(encodeURIComponent).join("/")}/pull/${pullRequest}`;
2233
+ link.target = "_blank";
2234
+ link.rel = "noopener noreferrer";
2235
+ link.textContent = `#${pullRequest} ↗`;
2236
+ link.setAttribute("aria-label", `${label} #${pullRequest}`);
2237
+ field.lastElementChild.replaceWith(link);
2238
+ return field;
2239
+ }
2240
+ function lifecycleDeliveryEvidence(step) {
2241
+ const evidence = step?.delivery_evidence || step?.implementation_evidence;
2242
+ if (!evidence || typeof evidence !== "object") return null;
2243
+ const role = String(evidence.role || "implementation").toLowerCase();
2244
+ const titles = {
2245
+ implementation: "lifecycle.detail_implementation_evidence",
2246
+ finalization: "lifecycle.detail_finalization_evidence",
2247
+ reconciliation: "lifecycle.detail_reconciliation_evidence",
2248
+ };
2249
+ const pullRequestLabels = {
2250
+ implementation: "detail.implementation_pull_request",
2251
+ finalization: "detail.finalization_pull_request",
2252
+ reconciliation: "detail.reconciliation_pull_request",
2253
+ };
2254
+ const fields = [];
2255
+ if (evidence.branch) fields.push(lifecycleDetailField(t("workspace.current_branch"), String(evidence.branch)));
2256
+ if (evidence.candidate_sha) fields.push(lifecycleDetailField(t("detail.candidate_sha"), String(evidence.candidate_sha)));
2257
+ if (Number.isInteger(evidence.pull_request) && evidence.pull_request > 0) {
2258
+ const label = t(pullRequestLabels[role] || pullRequestLabels.implementation);
2259
+ fields.push(lifecyclePullRequestField(label, evidence.pull_request, evidence.repository));
2260
+ }
2261
+ if (!fields.length) return null;
2262
+ const section = document.createElement("section");
2263
+ section.className = "lifecycle-detail-modal__implementation-evidence";
2264
+ section.append(
2265
+ Object.assign(document.createElement("h3"), { textContent: t(titles[role] || titles.implementation) }),
2266
+ Object.assign(document.createElement("div"), { className: "technical-grid" }),
2267
+ );
2268
+ section.lastElementChild.append(...fields);
2269
+ return section;
2270
+ }
2160
2271
  function lifecycleRepairEvidence(step) {
2161
2272
  const audit = Array.isArray(step?.repair_audit) ? step.repair_audit : [];
2162
2273
  if (!audit.length) return null;
@@ -2171,9 +2282,16 @@ function lifecycleRepairEvidence(step) {
2171
2282
  const iteration = String(item.iteration || "").trim();
2172
2283
  if (!iteration) continue;
2173
2284
  const heading = document.createElement("h4");
2174
- heading.textContent = t("lifecycle.detail_repair_iteration", { iteration });
2285
+ heading.textContent = t(
2286
+ step?.id === "LOCAL_REPOSITORY_VALIDATION"
2287
+ ? "lifecycle.detail_validation_pass"
2288
+ : "lifecycle.detail_repair_iteration",
2289
+ { iteration },
2290
+ );
2175
2291
  const grid = document.createElement("div");
2176
2292
  grid.className = "technical-grid";
2293
+ const iterationSection = document.createElement("section");
2294
+ iterationSection.className = "lifecycle-detail-modal__repair-iteration";
2177
2295
  const outcome = String(item.outcome || "").trim();
2178
2296
  const dynamicField = (label, source) => {
2179
2297
  const value = String(source || t("detail.not_recorded"));
@@ -2188,7 +2306,8 @@ function lifecycleRepairEvidence(step) {
2188
2306
  lifecycleDetailField(t("detail.commit"), item.commit_sha === "not_recorded" ? t("detail.not_recorded") : String(item.commit_sha || t("detail.not_recorded"))),
2189
2307
  lifecycleDetailField(t("detail.outcome"), t("lifecycle.repair_outcome." + outcome, {}, outcome || t("detail.not_recorded"))),
2190
2308
  );
2191
- section.append(heading, grid);
2309
+ iterationSection.append(heading, grid);
2310
+ section.append(iterationSection);
2192
2311
  }
2193
2312
  if (section.childElementCount <= 1) return null;
2194
2313
  void localizeDynamicEvidence(dynamicRows);
@@ -2219,16 +2338,29 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2219
2338
  content.replaceChildren();
2220
2339
  const overview = document.createElement("section"), grid = document.createElement("div");
2221
2340
  grid.className = "technical-grid";
2341
+ const rawSpans = Array.isArray(timing.spans) ? timing.spans : [];
2342
+ const activeSpan = [...rawSpans].reverse().find((span) => String(span?.outcome || "").toUpperCase() === "ACTIVE");
2222
2343
  grid.append(
2223
2344
  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"))),
2345
+ lifecycleDetailField(
2346
+ t("lifecycle.detail_started_at"),
2347
+ formatTimestamp(activeSpan?.started_at || timing.started_at || step?.started_at),
2348
+ ),
2226
2349
  );
2350
+ if (String(step?.state || "").toUpperCase() !== "ACTIVE") {
2351
+ grid.append(lifecycleDetailField(
2352
+ t("lifecycle.detail_finished_at"),
2353
+ formatTimestamp(timing.finished_at, t("format.unavailable")),
2354
+ ));
2355
+ }
2227
2356
  if (Number.isInteger(step?.iteration_count) && step.iteration_count > 0) {
2228
2357
  grid.append(lifecycleDetailField(t("lifecycle.detail_iterations"), String(step.iteration_count)));
2229
2358
  }
2230
2359
  overview.append(grid); content.append(overview);
2231
- const spans = lifecyclePhaseTiming(Array.isArray(timing.spans) ? timing.spans : []);
2360
+ const localValidation = String(step?.id || "").toUpperCase() === "LOCAL_REPOSITORY_VALIDATION";
2361
+ const spans = localValidation && rawSpans.length > 1
2362
+ ? rawSpans.filter((span) => span && typeof span === "object").map((span, index) => ({ ...span, occurrence: index + 1 }))
2363
+ : lifecyclePhaseTiming(rawSpans);
2232
2364
  const phaseTiming = document.createElement("section");
2233
2365
  phaseTiming.append(Object.assign(document.createElement("h3"), { textContent: t("lifecycle.detail_phase_timing") }));
2234
2366
  if (!spans.length) {
@@ -2237,7 +2369,9 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2237
2369
  const list = document.createElement("ol"); list.className = "lifecycle-detail-modal__phase-list";
2238
2370
  for (const span of spans) {
2239
2371
  const item = document.createElement("li"), heading = document.createElement("strong"), meta = document.createElement("span");
2240
- heading.textContent = telemetryLabel(span.phase);
2372
+ heading.textContent = localValidation
2373
+ ? t("lifecycle.detail_validation_pass", { iteration: span.occurrence })
2374
+ : telemetryLabel(span.phase);
2241
2375
  meta.textContent = t("lifecycle.detail_phase_meta", {
2242
2376
  duration: telemetryMs(span.duration_ms), outcome: lifecycleStateLabel(span.outcome),
2243
2377
  });
@@ -2257,8 +2391,12 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2257
2391
  content.append(phaseTiming);
2258
2392
  const qualityEvidence = lifecycleQualityEvidence(step);
2259
2393
  if (qualityEvidence) content.append(qualityEvidence);
2394
+ const capabilityEvidence = lifecycleCapabilityEvidence(step);
2395
+ if (capabilityEvidence) content.append(capabilityEvidence);
2260
2396
  const assuranceEvidence = lifecycleAssuranceEvidence(step);
2261
2397
  if (assuranceEvidence) content.append(assuranceEvidence);
2398
+ const deliveryEvidence = lifecycleDeliveryEvidence(step);
2399
+ if (deliveryEvidence) content.append(deliveryEvidence);
2262
2400
  const repairEvidence = lifecycleRepairEvidence(step);
2263
2401
  if (repairEvidence) content.append(repairEvidence);
2264
2402
  if (!modal.open) modal.showModal();
@@ -2266,7 +2404,37 @@ function openLifecycleDetail(step, trigger, { presentationOnly = false } = {}) {
2266
2404
  }
2267
2405
  $("lifecycleDetailClose")?.addEventListener("click", closeLifecycleDetail);
2268
2406
  $("lifecycleDetailModal")?.addEventListener("close", () => { lifecycleDetailTrigger?.focus?.(); lifecycleDetailTrigger = null; lifecycleDetailStep = null; });
2269
- function lifecycleFlow(projection, { historical = false } = {}) {
2407
+ function lifecycleStepWithEvidence(step, context = {}) {
2408
+ const enriched = { ...step };
2409
+ const id = String(step?.id || "").toUpperCase();
2410
+ if (id === "CAPABILITY_REVIEW") {
2411
+ const reviewers = Array.isArray(context.reviewer_agents)
2412
+ ? context.reviewer_agents
2413
+ : Array.isArray(context.reviewers) ? context.reviewers : [];
2414
+ if (reviewers.length) enriched.reviewer_evidence = reviewers;
2415
+ }
2416
+ const deliverySteps = {
2417
+ EXECUTE_AGENT: { role: "implementation", candidate: "implementation_candidate_sha", branch: "implementation_branch", pullRequest: "implementation_pr" },
2418
+ FINALIZE_AGENT: { role: "finalization", candidate: "finalization_candidate_sha", branch: "finalization_branch", pullRequest: "finalization_pr" },
2419
+ RECONCILE_AGENT: { role: "reconciliation", candidate: "reconciliation_candidate_sha", branch: "reconciliation_branch", pullRequest: "reconciliation_pr" },
2420
+ };
2421
+ const delivery = deliverySteps[id];
2422
+ if (delivery) {
2423
+ const candidate = String(context[delivery.candidate] || "").trim();
2424
+ const branch = String(context[delivery.branch] || "").trim();
2425
+ const pullRequest = Number(context[delivery.pullRequest]);
2426
+ const repository = String(context.github_repository || context.target_repository || "").trim();
2427
+ const evidence = {};
2428
+ evidence.role = delivery.role;
2429
+ if (/^[0-9a-f]{40}$/.test(candidate)) evidence.candidate_sha = candidate;
2430
+ if (branch) evidence.branch = branch;
2431
+ if (Number.isInteger(pullRequest) && pullRequest > 0) evidence.pull_request = pullRequest;
2432
+ if (/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository)) evidence.repository = repository;
2433
+ if (Object.keys(evidence).length > 1) enriched.delivery_evidence = evidence;
2434
+ }
2435
+ return enriched;
2436
+ }
2437
+ function lifecycleFlow(projection, { historical = false, context = {} } = {}) {
2270
2438
  const section = document.createElement("section");
2271
2439
  section.className = "execution-lifecycle" + (historical ? " execution-lifecycle--historical" : "");
2272
2440
  if (projection?.run_id) section.dataset.runId = projection.run_id;
@@ -2278,7 +2446,9 @@ function lifecycleFlow(projection, { historical = false } = {}) {
2278
2446
  }
2279
2447
  const scroll = document.createElement("div"), list = document.createElement("ol");
2280
2448
  scroll.className = "execution-lifecycle__scroll"; list.className = "execution-lifecycle__path";
2281
- const steps = Array.isArray(projection.steps) ? projection.steps : [];
2449
+ const steps = Array.isArray(projection.steps)
2450
+ ? projection.steps.map((step) => lifecycleStepWithEvidence(step, context))
2451
+ : [];
2282
2452
  for (const [index, step] of steps.entries()) {
2283
2453
  const state = String(step?.state || "UNKNOWN").toLowerCase();
2284
2454
  const operatorWait = state === "active" && !historical && isOperatorMergeStep(step);
@@ -2315,8 +2485,8 @@ function lifecycleFlow(projection, { historical = false } = {}) {
2315
2485
  }
2316
2486
  scroll.append(list); section.append(scroll);
2317
2487
  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) || {};
2488
+ const currentStep = steps.find((step) => step?.state === "ACTIVE")
2489
+ || steps.find((step) => step?.state === projection?.terminal_state) || {};
2320
2490
  summary.textContent = t("lifecycle.summary", {
2321
2491
  step: lifecycleLabel(currentStep),
2322
2492
  status: isOperatorMergeStep(currentStep)
@@ -2395,7 +2565,7 @@ function renderActiveLifecycle(projection, execution = {}) {
2395
2565
  : 0;
2396
2566
  previous?.remove();
2397
2567
  if (projection?.run_id) {
2398
- const lifecycle = lifecycleFlow(projection);
2568
+ const lifecycle = lifecycleFlow(projection, { context: execution });
2399
2569
  const identity = $("executionIdentity"), estimate = $("executionEstimate")?.closest(".card");
2400
2570
  placeExecutionEstimate();
2401
2571
  // Keep run identity and its phase-aware estimate ahead of the read-only
@@ -2419,6 +2589,18 @@ function renderActiveLifecycle(projection, execution = {}) {
2419
2589
  revealActiveLifecycleStep(lifecycle.querySelector(".execution-lifecycle__scroll"));
2420
2590
  }
2421
2591
  renderActivePullRequests(execution, lifecycle);
2592
+ if ($("lifecycleDetailModal")?.open && lifecycleDetailStep) {
2593
+ const refreshed = (projection.steps || []).find((step) => step?.id === lifecycleDetailStep.id);
2594
+ if (refreshed) {
2595
+ const scrollTop = $("lifecycleDetailContent")?.scrollTop || 0;
2596
+ openLifecycleDetail(
2597
+ lifecycleStepWithEvidence(refreshed, execution),
2598
+ lifecycleDetailTrigger,
2599
+ { presentationOnly: true },
2600
+ );
2601
+ if ($("lifecycleDetailContent")) $("lifecycleDetailContent").scrollTop = scrollTop;
2602
+ }
2603
+ }
2422
2604
  } else {
2423
2605
  renderActivePullRequests(execution, null);
2424
2606
  }
@@ -8419,19 +8601,41 @@ function promptDetailRecommendationHandoff(handoff) {
8419
8601
  }
8420
8602
  function promptDetailReviewersSection(reviewers, { wide = true } = {}) {
8421
8603
  if (!reviewers.length) return null;
8422
- const fields = reviewers.map((reviewer) =>
8423
- detailField(
8424
- reviewerLabel(reviewer.reviewer, t("detail.specialist_review")),
8425
- t("detail.capability") + ": " +
8426
- reviewerCapabilityLabel(reviewer.capability || "ENGINEERING") + " · " +
8427
- reviewerStatusLabel(reviewer.status || "completed") + " · " +
8428
- t("detail.accepted_recommendations") + ": " +
8429
- (Number(reviewer.accepted_recommendations) || 0) + "\n" +
8430
- t("detail.selected_because") + ": " +
8604
+ const fields = reviewers.map((reviewer) => {
8605
+ const rawStatus = String(reviewer.status || "completed").toLowerCase();
8606
+ const failed = rawStatus === "failed", completed = ["completed", "uitgevoerd"].includes(rawStatus);
8607
+ const field = document.createElement("article"), heading = document.createElement("h4"),
8608
+ statusLabel = document.createElement("span"), statusRow = document.createElement("span"),
8609
+ indicator = document.createElement("span"), statusText = document.createElement("span");
8610
+ field.className = "field prompt-detail-reviewer";
8611
+ heading.textContent = reviewerLabel(reviewer.reviewer, t("detail.specialist_review"));
8612
+ statusLabel.className = "label";
8613
+ statusLabel.textContent = t("detail.prompt_status");
8614
+ statusRow.className = "prompt-detail-reviewer__status";
8615
+ indicator.className = "prompt-detail-reviewer__status-icon prompt-detail-reviewer__status-icon--"
8616
+ + (failed ? "failed" : completed ? "completed" : "neutral");
8617
+ indicator.setAttribute("aria-hidden", "true");
8618
+ indicator.textContent = failed ? "×" : completed ? "✓" : "•";
8619
+ statusText.className = "prompt-detail-reviewer__status-text";
8620
+ statusText.textContent = reviewerCapabilityLabel(reviewer.capability || "ENGINEERING")
8621
+ + " · " + reviewerStatusLabel(rawStatus);
8622
+ statusRow.append(indicator, statusText);
8623
+ field.append(
8624
+ heading,
8625
+ statusLabel,
8626
+ statusRow,
8627
+ detailField(
8628
+ t("detail.selected_because"),
8431
8629
  String(reviewer.selected_because || t("detail.not_recorded")),
8432
- true,
8433
- ),
8434
- );
8630
+ true,
8631
+ ),
8632
+ detailField(
8633
+ t("detail.accepted_recommendations"),
8634
+ String(Number(reviewer.accepted_recommendations) || 0),
8635
+ ),
8636
+ );
8637
+ return field;
8638
+ });
8435
8639
  return promptDetailCard(t("detail.specialist_reviews"), fields, wide, "prompt-detail-card--reviewers");
8436
8640
  }
8437
8641
  function promptDetailAssuranceReviewsSection(reviews) {
@@ -8516,7 +8720,10 @@ function renderPromptHistoryDetail(payload) {
8516
8720
  ]),
8517
8721
  ]),
8518
8722
  promptDetailRightbar([executionContext, promptDetailPullRequestsSection(pullRequests)]),
8519
- lifecycleFlow(payload?.lifecycle, { historical: true }),
8723
+ lifecycleFlow(payload?.lifecycle, {
8724
+ historical: true,
8725
+ context: { ...history, reviewers, commit_timeline: commitTimeline, pull_requests: pullRequests },
8726
+ }),
8520
8727
  statusReconciliationCard(payload?.lifecycle?.recovery),
8521
8728
  promptDetailProviderReviewSections(usage, reviewers, commitTimeline),
8522
8729
  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,17 @@ 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_finalization_evidence":"Finalization result","lifecycle.detail_reconciliation_evidence":"Reconciliation 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_finalization_evidence":"Finalisatieresultaat","lifecycle.detail_reconciliation_evidence":"Reconciliatieresultaat","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_finalization_evidence":"Finalisierungsergebnis","lifecycle.detail_reconciliation_evidence":"Abstimmungsergebnis","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_finalization_evidence":"Résultat de la finalisation","lifecycle.detail_reconciliation_evidence":"Résultat de la réconciliation","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_finalization_evidence":"Resultado de la finalización","lifecycle.detail_reconciliation_evidence":"Resultado de la conciliación","lifecycle.detail_validation_pass":"Pasada de validación {iteration}","detail.initial_observation":"Observación inicial","detail.rejected_recommendations":"Recomendaciones rechazadas"});
4281
+ Object.assign(DASHBOARD_MESSAGES.en, {"lifecycle.assurance_integral_evidence":"Impact surfaces reviewed: {coverage} · Prior findings reassessed: {dispositions}"});
4282
+ Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.assurance_integral_evidence":"Impactvlakken beoordeeld: {coverage} · Eerdere bevindingen herbeoordeeld: {dispositions}"});
4283
+ Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.assurance_integral_evidence":"Geprüfte Auswirkungsbereiche: {coverage} · Frühere Befunde erneut bewertet: {dispositions}"});
4284
+ Object.assign(DASHBOARD_MESSAGES.fr, {"lifecycle.assurance_integral_evidence":"Surfaces d’impact examinées : {coverage} · Constats antérieurs réévalués : {dispositions}"});
4285
+ Object.assign(DASHBOARD_MESSAGES.es, {"lifecycle.assurance_integral_evidence":"Superficies de impacto revisadas: {coverage} · Hallazgos anteriores reevaluados: {dispositions}"});