engineering-platform 2.3.91__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.
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/PKG-INFO +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/pyproject.toml +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard.css +4 -4
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard.js +139 -12
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_locales.mjs +10 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_host.py +71 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_timing.py +23 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/platform_version.py +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/server.py +51 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/server_console_services.py +24 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/templates/workspace-config.json +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/PKG-INFO +1 -1
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/README.md +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/setup.cfg +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/__init__.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/__main__.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/agent_state.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/agent_trust.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/assurance_scope.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/capability_preflight.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/capability_review.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/central_data_transfer.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/central_database.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/central_operational_reset.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/central_store_migration.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/codex_capacity.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/codex_chat.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/codex_observability.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/component_lock.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/component_logging.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/console_presentation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/console_route_ownership.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/contracts/__init__.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/contracts/ep_consumer.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/contracts/models.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/contracts/projection.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_browser_validation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_state.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_supervisor.swift +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/dashboard_translation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/dependabot_producer.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/development_profile.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/drift_diagnostics.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/emergency_recovery.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/engineering_memory.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/ep_consumer_credentials.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/evidence_projection.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_activity.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_context.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_errors.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_evidence.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_executor.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_finalization.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_host_evidence.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_lease.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_lifecycle.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_models.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_readiness.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_reporting.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_repository.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_timeout_policy.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/execution_transaction.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/external_producer_binding.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/file_inbox.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/forensic_attribution.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/forensic_attribution_v2.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/forensic_delta.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/golden_scenario.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/host_admin.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/host_preflight.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_relocation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_activation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_admission.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_backup.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_composition.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_executor.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_migration.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_operation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_plan.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/installation_update_preparation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/investigation_ledger.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/legacy_inbox_migration.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/legacy_installation_adoption.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/lifecycle_worker.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/live_status.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/local_api.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/local_api_keychain.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/local_repository_binding.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/managed_autonomy.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/managed_codex_runtime.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/managed_workspace_readiness.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/merge_delegation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation_lock.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/operational_installation_record.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/owner_credential_recovery.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/parity_context.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/platform_admin.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/platform_api.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/platform_bootstrap.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/platform_components.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/pr_check_repair.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/pr_evidence_backfill.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/producer.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/product_installation_readback.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/project_agent.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/project_agent_service.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/project_topology.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/prompt_history.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_context.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_context_benchmark.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_context_scope.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_interruption.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_process_identity.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_readiness.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_recovery.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/provider_usage.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/providers.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/qualification.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/qualification_runtime.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/recommendation_handoff.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/reconciliation_adoption.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/release_operation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/report_analysis.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/repository_attachment.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/repository_handoff.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/resources.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/reviewer_evidence.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/revision_binding.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.3.schema.json +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/server_relay.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/server_service.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/status_model.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/status_reconciliation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/storage.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/submission_cli.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/submission_intake.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/submission_service.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/system_installation_topology.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/system_server_service.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/telemetry.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_contract.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_export.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/telemetry_metrics.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/terminal_evidence_reconciliation.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/validation_identity.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/validation_profile.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/version_preparation_delivery.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/workspace_preflight.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/worktree_provenance.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/worktree_tooling.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/SOURCES.txt +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/entry_points.txt +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform.egg-info/top_level.txt +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/tests/test_adaptive_action_sizing_design.py +0 -0
- {engineering_platform-2.3.91 → engineering_platform-2.3.93}/tests/test_role_task_model_policy_design.py +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bootstrap_contract": "2026.12",
|
|
3
3
|
"checkpoint_format": 1,
|
|
4
|
-
"dashboard_version": "2.3.
|
|
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.
|
|
9
|
+
"platform_version": "2.3.93",
|
|
10
10
|
"report_format": 2,
|
|
11
|
-
"runner_version": "2.3.
|
|
11
|
+
"runner_version": "2.3.93",
|
|
12
12
|
"status_model": 1,
|
|
13
13
|
"storage_schema": 45,
|
|
14
|
-
"watcher_version": "2.3.
|
|
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
|
|
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}
|
|
@@ -1144,9 +1144,9 @@ html[data-theme="light"] .dashboard-status-banner--provider-auth_required .provi
|
|
|
1144
1144
|
the other operational banners rather than as a scrolling dashboard card. */
|
|
1145
1145
|
.dashboard-sticky-header:has(#noProjectSelected:not([hidden])){padding-bottom:7px}.dashboard-status-banner--no-project{align-items:center;background:#163b59;border-bottom:1px solid #62bdf0;color:#e7f5ff;font:600 13px/1.45 system-ui}.dashboard-status-banner--no-project strong{color:#9bd7ff}.no-project-selected__dismiss{align-items:center;background:transparent!important;border:1px solid currentColor!important;border-radius:50%;color:inherit!important;cursor:pointer;display:inline-flex;flex:none;font:22px/1 system-ui;height:30px;justify-content:center;margin-left:auto;min-height:30px;min-width:30px;padding:0;width:30px}.no-project-selected__dismiss:hover,.no-project-selected__dismiss:focus-visible{background:#9bd7ff!important;border-color:#9bd7ff!important;color:#123a58!important}.no-project-selected__dismiss:focus-visible{box-shadow:0 0 0 4px #9bd7ff55!important;outline:2px solid #9bd7ff!important;outline-offset:2px!important}html[data-theme="light"] .dashboard-status-banner--no-project{background:#e2f3ff;color:#12466b}html[data-theme="light"] .dashboard-status-banner--no-project strong{color:#075985}html[data-theme="light"] .no-project-selected__dismiss:hover,html[data-theme="light"] .no-project-selected__dismiss:focus-visible{background:#075985!important;border-color:#075985!important;color:#fff!important}
|
|
1146
1146
|
|
|
1147
|
-
/*
|
|
1148
|
-
|
|
1149
|
-
.prompt-detail-card--pull-requests
|
|
1147
|
+
/* Active PR evidence starts in the left column directly below the lifecycle.
|
|
1148
|
+
Historical Mission details keep PR evidence in their right context column. */
|
|
1149
|
+
.prompt-detail-card--pull-requests{grid-column:2}.active-run-pull-requests{grid-column:1}.prompt-detail-pr-link{border-bottom:1px solid currentColor;color:var(--category-color);font-weight:400;text-decoration:none}.prompt-detail-pr-link:hover{background:transparent;color:var(--category-color);outline:0}.prompt-detail-pr-link:focus-visible{background:transparent;color:var(--category-color);outline:2px solid var(--category-color);outline-offset:2px}.prompt-detail-pr-metrics{color:var(--dashboard-modal-muted);display:flex;flex-wrap:wrap;font-size:12px;gap:5px 12px;margin-top:7px}.prompt-detail-pr-metric{white-space:nowrap}@media (max-width:620px){.prompt-detail-card--pull-requests,.active-run-pull-requests{grid-column:1;grid-row:auto}}
|
|
1150
1150
|
|
|
1151
1151
|
/* Authentication is a recoverable warning, not a destructive provider failure. */
|
|
1152
1152
|
.dashboard-status-banner--provider-auth_required .provider-readiness-banner__action{background:transparent!important;border-color:#ffd768!important;color:#fff4d6!important}.dashboard-status-banner--provider-auth_required .provider-readiness-banner__action:hover:not(:disabled),.dashboard-status-banner--provider-auth_required .provider-readiness-banner__action:focus-visible{background:#f4c34f!important;border-color:#ffd768!important;color:#2a2415!important}.dashboard-status-banner--provider-auth_required .provider-readiness-banner__action:focus-visible{box-shadow:0 0 0 4px #f4c34f88;outline-color:#ffd768}
|
|
@@ -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(
|
|
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
|
-
|
|
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(
|
|
2225
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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)
|
|
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 =
|
|
2319
|
-
||
|
|
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, {
|
|
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"});
|
|
@@ -119,6 +119,7 @@ from .execution_timing import complete_active_phase as _complete_active_phase
|
|
|
119
119
|
from .execution_timing import complete_phase as _complete_phase
|
|
120
120
|
from .execution_timing import start_or_resume_phase as _start_or_resume_phase
|
|
121
121
|
from .execution_timing import start_phase as _start_phase
|
|
122
|
+
from .execution_timing import update_active_phase_metadata as _update_active_phase_metadata
|
|
122
123
|
from .managed_autonomy import (
|
|
123
124
|
append_action as record_managed_action,
|
|
124
125
|
append_pr_check_observation as record_managed_pr_check,
|
|
@@ -194,6 +195,20 @@ def complete_phase(root: Path, active: ActivePhase | None, **kwargs: object) ->
|
|
|
194
195
|
)
|
|
195
196
|
|
|
196
197
|
|
|
198
|
+
def update_phase_metadata(
|
|
199
|
+
root: Path, active: ActivePhase | None, metadata: dict[str, object],
|
|
200
|
+
) -> None:
|
|
201
|
+
"""Publish optional bounded live phase data without affecting the run."""
|
|
202
|
+
if active is None:
|
|
203
|
+
return
|
|
204
|
+
try:
|
|
205
|
+
_update_active_phase_metadata(root, active, metadata)
|
|
206
|
+
except EngineeringStorageError as error:
|
|
207
|
+
_timing_unavailable(
|
|
208
|
+
root, active.run_id, error, central_database=active.central_database,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
197
212
|
def complete_active_phase(root: Path, run_id: str, phase_name: str, **kwargs: object) -> bool:
|
|
198
213
|
try:
|
|
199
214
|
return _complete_active_phase(root, run_id, phase_name, **kwargs)
|
|
@@ -700,6 +715,7 @@ class EngineeringRunner:
|
|
|
700
715
|
selection: ReviewerSelection,
|
|
701
716
|
event: str,
|
|
702
717
|
result: ReviewerResult | None = None,
|
|
718
|
+
phase: ActivePhase | None = None,
|
|
703
719
|
) -> None:
|
|
704
720
|
"""Publish bounded reviewer lifecycle status without granting reviewer authority."""
|
|
705
721
|
self._heartbeat()
|
|
@@ -725,6 +741,18 @@ class EngineeringRunner:
|
|
|
725
741
|
else 0
|
|
726
742
|
)
|
|
727
743
|
break
|
|
744
|
+
update_phase_metadata(
|
|
745
|
+
self.root,
|
|
746
|
+
phase,
|
|
747
|
+
{"reviewer_agents": [
|
|
748
|
+
{
|
|
749
|
+
"reviewer": str(item.get("reviewer", ""))[:80],
|
|
750
|
+
"capability": str(item.get("capability", "engineering"))[:80],
|
|
751
|
+
"status": str(item.get("status", "selected"))[:16],
|
|
752
|
+
}
|
|
753
|
+
for item in self.reviewer_runtime[:12]
|
|
754
|
+
]},
|
|
755
|
+
)
|
|
728
756
|
write_live_status(self.root, state, "Capability review: " + selection.reviewer, self.reviewer_runtime)
|
|
729
757
|
|
|
730
758
|
def _persist_agent_usage(self, run_id: str) -> None:
|
|
@@ -3366,6 +3394,18 @@ First implementation pull-request publication gate:
|
|
|
3366
3394
|
}
|
|
3367
3395
|
for item in selections
|
|
3368
3396
|
]
|
|
3397
|
+
update_phase_metadata(
|
|
3398
|
+
self.root,
|
|
3399
|
+
capability_review,
|
|
3400
|
+
{"reviewer_agents": [
|
|
3401
|
+
{
|
|
3402
|
+
"reviewer": str(item["reviewer"])[:80],
|
|
3403
|
+
"capability": str(item["capability"])[:80],
|
|
3404
|
+
"status": "selected",
|
|
3405
|
+
}
|
|
3406
|
+
for item in self.reviewer_runtime[:12]
|
|
3407
|
+
]},
|
|
3408
|
+
)
|
|
3369
3409
|
write_live_status(
|
|
3370
3410
|
self.root,
|
|
3371
3411
|
state
|
|
@@ -3399,7 +3439,7 @@ First implementation pull-request publication gate:
|
|
|
3399
3439
|
objective,
|
|
3400
3440
|
self.agent if hasattr(self.agent, "review") else None,
|
|
3401
3441
|
progress=lambda selection, event, result: self._publish_reviewer_progress(
|
|
3402
|
-
state, selection, event, result
|
|
3442
|
+
state, selection, event, result, capability_review
|
|
3403
3443
|
),
|
|
3404
3444
|
evidence=reviewer_evidence,
|
|
3405
3445
|
)
|
|
@@ -3413,6 +3453,36 @@ First implementation pull-request publication gate:
|
|
|
3413
3453
|
observed_snapshots=reviewer.usage_snapshots,
|
|
3414
3454
|
)
|
|
3415
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
|
+
)
|
|
3416
3486
|
# Reviewer reasoning is intentionally not merged into the primary
|
|
3417
3487
|
# provider context. Reviewers share the bounded factual snapshot, but
|
|
3418
3488
|
# retain independent reasoning responsibility and advisory records.
|
|
@@ -132,6 +132,29 @@ def complete_phase(root: Path, active: ActivePhase, *, outcome: str = "COMPLETE"
|
|
|
132
132
|
connection.close()
|
|
133
133
|
|
|
134
134
|
|
|
135
|
+
def update_active_phase_metadata(
|
|
136
|
+
root: Path, active: ActivePhase, metadata: Mapping[str, object],
|
|
137
|
+
) -> None:
|
|
138
|
+
"""Replace bounded metadata for one exact active phase.
|
|
139
|
+
|
|
140
|
+
Live projections can change while the measured phase is active. The phase
|
|
141
|
+
identity and timing remain immutable; only its bounded presentation data is
|
|
142
|
+
replaced, and a terminal phase cannot be rewritten.
|
|
143
|
+
"""
|
|
144
|
+
encoded = _metadata(metadata)
|
|
145
|
+
connection = _connection(root, active.central_database)
|
|
146
|
+
try:
|
|
147
|
+
changed = connection.execute(
|
|
148
|
+
"""UPDATE execution_phase_spans SET metadata=?
|
|
149
|
+
WHERE phase_id=? AND run_id=? AND outcome='ACTIVE'""",
|
|
150
|
+
(encoded, active.phase_id, active.run_id),
|
|
151
|
+
).rowcount
|
|
152
|
+
if changed != 1:
|
|
153
|
+
raise EngineeringStorageError("Execution phase is not active.")
|
|
154
|
+
finally:
|
|
155
|
+
connection.close()
|
|
156
|
+
|
|
157
|
+
|
|
135
158
|
def start_or_resume_phase(root: Path, run_id: str, phase_name: str, **kwargs: object) -> ActivePhase:
|
|
136
159
|
"""Start one envelope or resume its observed active database boundary.
|
|
137
160
|
|
|
@@ -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.
|
|
15
|
+
CURRENT_PLATFORM_VERSION = "2.3.93"
|
|
16
16
|
MANIFEST_FIELDS = frozenset(
|
|
17
17
|
{
|
|
18
18
|
"platform_version",
|
{engineering_platform-2.3.91 → engineering_platform-2.3.93}/src/engineering_platform/server.py
RENAMED
|
@@ -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,6 +3790,12 @@ 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:
|
|
3793
|
+
capability_phase = connection.execute(
|
|
3794
|
+
"""SELECT metadata,outcome FROM execution_phase_spans
|
|
3795
|
+
WHERE run_id=? AND phase_name='CAPABILITY_REVIEW'
|
|
3796
|
+
ORDER BY ordinal DESC LIMIT 1""",
|
|
3797
|
+
(run_id,),
|
|
3798
|
+
).fetchone()
|
|
3791
3799
|
rows = connection.execute(
|
|
3792
3800
|
"""SELECT role,completed_at FROM provider_invocations
|
|
3793
3801
|
WHERE run_id=? AND phase='CAPABILITY_REVIEW'
|
|
@@ -3797,6 +3805,49 @@ def _central_console_invocation_reviewers(data_root: Path, run_id: str) -> list[
|
|
|
3797
3805
|
).fetchall()
|
|
3798
3806
|
except (sqlite3.DatabaseError, storage.EngineeringStorageError):
|
|
3799
3807
|
return []
|
|
3808
|
+
if capability_phase is not None:
|
|
3809
|
+
try:
|
|
3810
|
+
metadata = json.loads(str(capability_phase[0]))
|
|
3811
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
3812
|
+
metadata = {}
|
|
3813
|
+
live = metadata.get("reviewer_agents") if isinstance(metadata, dict) else None
|
|
3814
|
+
if isinstance(live, list) and 0 < len(live) <= 12:
|
|
3815
|
+
projected: list[dict[str, object]] = []
|
|
3816
|
+
for item in live:
|
|
3817
|
+
if not isinstance(item, Mapping):
|
|
3818
|
+
projected = []
|
|
3819
|
+
break
|
|
3820
|
+
reviewer = str(item.get("reviewer") or "").strip()
|
|
3821
|
+
capability = str(item.get("capability") or "engineering").strip()
|
|
3822
|
+
status = str(item.get("status") or "").strip().lower()
|
|
3823
|
+
if (
|
|
3824
|
+
re.fullmatch(r"[a-z0-9][a-z0-9_-]{0,79}", reviewer) is None
|
|
3825
|
+
or re.fullmatch(r"[a-z0-9][a-z0-9_-]{0,79}", capability) is None
|
|
3826
|
+
or status not in {"selected", "running", "completed", "failed"}
|
|
3827
|
+
):
|
|
3828
|
+
projected = []
|
|
3829
|
+
break
|
|
3830
|
+
projected.append({
|
|
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 {}),
|
|
3842
|
+
})
|
|
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
|
+
):
|
|
3850
|
+
return projected
|
|
3800
3851
|
reviewers: list[dict[str, object]] = []
|
|
3801
3852
|
for role, completed_at in rows:
|
|
3802
3853
|
name = str(role).removeprefix("reviewer:").strip()
|