engineering-platform 2.3.58__tar.gz → 2.3.66__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/PKG-INFO +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/pyproject.toml +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/agent_state.py +14 -3
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard.css +3 -3
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard.js +40 -21
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard_locales.mjs +16 -10
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/console_route_ownership.py +1 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_state.py +23 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_supervisor.swift +10 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/evidence_projection.py +35 -2
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_executor.py +51 -3
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_host.py +383 -83
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_reporting.py +6 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_admission.py +26 -2
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_executor.py +30 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_operation.py +6 -4
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/live_status.py +26 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/operational_installation_record.py +30 -0
- engineering_platform-2.3.66/src/engineering_platform/owner_credential_recovery.py +1150 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/platform_version.py +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/server.py +295 -22
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/server_console_services.py +1 -2
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/server_relay.py +32 -4
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/templates/workspace-config.json +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/PKG-INFO +1 -1
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/SOURCES.txt +1 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/README.md +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/setup.cfg +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/__init__.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/__main__.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/agent_trust.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/capability_preflight.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/capability_review.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/central_data_transfer.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/central_database.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/central_store_migration.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/codex_capacity.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/codex_chat.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/codex_observability.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/component_lock.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/component_logging.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/console_presentation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/contracts/__init__.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/contracts/ep_consumer.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/contracts/models.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/contracts/projection.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_browser_validation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/dashboard_translation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/dependabot_producer.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/development_profile.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/drift_diagnostics.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/emergency_recovery.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/engineering_memory.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/ep_consumer_credentials.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_activity.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_context.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_errors.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_evidence.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_finalization.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_host_evidence.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_lease.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_lifecycle.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_models.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_readiness.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_repository.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_timeout_policy.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_timing.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/execution_transaction.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/external_producer_binding.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/file_inbox.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/forensic_attribution.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/forensic_attribution_v2.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/forensic_delta.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/golden_scenario.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/host_admin.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/host_preflight.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_relocation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_activation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_backup.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_composition.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_migration.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_plan.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/installation_update_preparation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/investigation_ledger.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/legacy_inbox_migration.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/legacy_installation_adoption.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/lifecycle_worker.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/local_api.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/local_api_keychain.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/local_repository_binding.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/managed_autonomy.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/managed_codex_runtime.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/operational_installation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/operational_installation_lock.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/parity_context.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/platform_admin.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/platform_api.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/platform_bootstrap.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/platform_components.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/pr_check_repair.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/pr_evidence_backfill.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/producer.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/product_installation_readback.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/project_agent.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/project_agent_service.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/project_topology.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/prompt_history.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_context.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_context_benchmark.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_context_scope.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_interruption.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_process_identity.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_readiness.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_recovery.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/provider_usage.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/providers.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/qualification.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/qualification_runtime.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/recommendation_handoff.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/release_operation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/report_analysis.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/repository_attachment.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/repository_handoff.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/resources.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/reviewer_evidence.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/revision_binding.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/server_service.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/status_model.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/status_reconciliation.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/storage.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/submission_cli.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/submission_intake.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/submission_service.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/system_installation_topology.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/system_server_service.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/telemetry.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/validation_identity.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/validation_profile.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/version_preparation_delivery.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/workspace_preflight.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/worktree_provenance.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/worktree_tooling.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/entry_points.txt +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform.egg-info/top_level.txt +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/tests/test_adaptive_action_sizing_design.py +0 -0
- {engineering_platform-2.3.58 → engineering_platform-2.3.66}/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.66",
|
|
5
5
|
"handoff_protocol": 1,
|
|
6
6
|
"memory_format": 2,
|
|
7
7
|
"minimum_codex_cli": "0.146.0",
|
|
8
8
|
"inbox_protocol": 1,
|
|
9
|
-
"platform_version": "2.3.
|
|
9
|
+
"platform_version": "2.3.66",
|
|
10
10
|
"report_format": 2,
|
|
11
|
-
"runner_version": "2.3.
|
|
11
|
+
"runner_version": "2.3.66",
|
|
12
12
|
"status_model": 1,
|
|
13
13
|
"storage_schema": 44,
|
|
14
|
-
"watcher_version": "2.3.
|
|
14
|
+
"watcher_version": "2.3.66"
|
|
15
15
|
}
|
{engineering_platform-2.3.58 → engineering_platform-2.3.66}/src/engineering_platform/agent_state.py
RENAMED
|
@@ -301,27 +301,38 @@ class TransactionState:
|
|
|
301
301
|
not isinstance(item, dict) or set(item) != audit_fields
|
|
302
302
|
or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
|
|
303
303
|
or not item["iteration"].isdigit() or int(item["iteration"]) < 1
|
|
304
|
-
or item["outcome"] not in {"validated", "validation_failed", "agent_failed"}
|
|
304
|
+
or item["outcome"] not in {"validated", "validation_failed", "agent_failed", "assessment_rejected"}
|
|
305
305
|
or (item["commit_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["commit_sha"]))
|
|
306
306
|
for item in state.local_validation_audit
|
|
307
307
|
)
|
|
308
308
|
):
|
|
309
309
|
raise StateError("checkpoint local validation audit is invalid or unsafe")
|
|
310
310
|
repair_audit_fields = audit_fields | {"repair_id", "origin", "input_candidate_sha", "dispatch_id"}
|
|
311
|
+
repair_delivery_scope_fields = repair_audit_fields | {"pre_repair_pull_request"}
|
|
312
|
+
repair_delivery_authority_fields = repair_delivery_scope_fields | {"repair_branch", "repair_base", "first_pr_authorized"}
|
|
311
313
|
if (
|
|
312
314
|
not isinstance(state.repair_audit, tuple)
|
|
313
315
|
or len(state.repair_audit) > 3
|
|
314
316
|
or any(
|
|
315
|
-
not isinstance(item, dict) or set(item) not in (audit_fields, repair_audit_fields)
|
|
317
|
+
not isinstance(item, dict) or set(item) not in (audit_fields, repair_audit_fields, repair_delivery_scope_fields, repair_delivery_authority_fields)
|
|
316
318
|
or not all(isinstance(value, str) and value and len(value) <= MAX_DIAGNOSTIC_LENGTH and value == redact_diagnostic(value) for value in item.values())
|
|
317
319
|
or not item["iteration"].isdigit() or int(item["iteration"]) < 1
|
|
318
320
|
or item["outcome"] not in {"planned", "submitted_for_recheck", "agent_failed", "agent_timed_out"}
|
|
319
321
|
or (item["commit_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["commit_sha"]))
|
|
320
|
-
or (set(item)
|
|
322
|
+
or (set(item) in (repair_audit_fields, repair_delivery_scope_fields, repair_delivery_authority_fields) and (
|
|
321
323
|
not re.fullmatch(r"repair:[A-Za-z0-9_.:-]+:[1-3]", item["repair_id"])
|
|
322
324
|
or item["origin"] not in {"validation", "quality", "security", "hosted", "finalization"}
|
|
323
325
|
or (item["input_candidate_sha"] != "not_recorded" and not re.fullmatch(r"[0-9a-f]{40}", item["input_candidate_sha"]))
|
|
324
326
|
))
|
|
327
|
+
or (set(item) in (repair_delivery_scope_fields, repair_delivery_authority_fields) and (
|
|
328
|
+
item["pre_repair_pull_request"] != "none"
|
|
329
|
+
and not (item["pre_repair_pull_request"].isdigit() and int(item["pre_repair_pull_request"]) >= 1)
|
|
330
|
+
))
|
|
331
|
+
or (set(item) == repair_delivery_authority_fields and (
|
|
332
|
+
(item["pre_repair_pull_request"] != "none" and item["first_pr_authorized"] != "no")
|
|
333
|
+
or (item["pre_repair_pull_request"] == "none" and item["first_pr_authorized"] not in {"yes", "no"})
|
|
334
|
+
or item["repair_branch"] == "none" or item["repair_base"] != "main"
|
|
335
|
+
))
|
|
325
336
|
for item in state.repair_audit
|
|
326
337
|
)
|
|
327
338
|
or len({item.get("repair_id", f"legacy:{item['iteration']}") for item in state.repair_audit}) != len(state.repair_audit)
|
|
@@ -273,7 +273,7 @@ html[data-theme="light"] :is(#rateLimitReset,#codexCliUpdate){background:#e8fff5
|
|
|
273
273
|
.prompt-history-row{cursor:pointer}.prompt-history-lineage{color:#b9b6c0;display:block;font:11px/1.35 system-ui;margin-top:4px;white-space:normal}
|
|
274
274
|
/* The shared modal shell owns the prompt-detail frame and header. This
|
|
275
275
|
component owns only its evidence layout and its inner document cards. */
|
|
276
|
-
.prompt-detail-modal__panel{display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;overflow:hidden}.prompt-detail-modal__content{align-items:start;box-sizing:border-box;display:grid;gap:18px;grid-template-columns:minmax(0,1fr) minmax(280px,.82fr);min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 12px 10px;scrollbar-gutter:stable both-edges}.prompt-detail-leftbar,.prompt-detail-rightbar{align-content:start;align-items:start;display:grid;gap:18px;grid-row:1;min-width:0}.prompt-detail-leftbar{grid-column:1}.prompt-detail-rightbar{grid-column:2}.prompt-detail-leftbar :is(.prompt-detail-card--execution-summary,.prompt-detail-sidebar),.prompt-detail-rightbar :is(.prompt-detail-card--execution-context,.prompt-detail-card--pull-requests){grid-column:auto;grid-row:auto}.prompt-detail-sidebar{align-content:start;align-items:start;display:grid;gap:18px}.prompt-detail-card{border:1px solid var(--category-color);border-radius:14px;padding:18px}.prompt-detail-card--wide{grid-column:1/-1}.prompt-detail-card h3{color:var(--category-color);font-size:18px;margin:0 0 14px}.prompt-detail-card .field{margin:0 0 14px}.prompt-detail-card .field:last-child{margin-bottom:0}.prompt-detail-card pre{overflow-wrap:anywhere;white-space:pre-wrap}.prompt-detail-card--execution-context{min-width:0;overflow:hidden}.prompt-detail-card--execution-context :is(.field,.label,span,li){min-width:0;overflow-wrap:anywhere;word-break:break-word}.detail-list-field ul{margin:6px 0 0;padding-inline-start:22px}@media (max-width:620px){.prompt-detail-modal__content{grid-template-columns:1fr;padding-inline:8px}.prompt-detail-leftbar,.prompt-detail-rightbar{grid-column:1;grid-row:auto}}
|
|
276
|
+
.prompt-detail-modal__panel{display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;overflow:hidden}.prompt-detail-modal__content{align-items:start;box-sizing:border-box;display:grid;gap:18px;grid-template-columns:minmax(0,1fr) minmax(280px,.82fr);min-height:0;overflow:auto;overscroll-behavior:contain;padding:0 12px 10px;scrollbar-gutter:stable both-edges}.prompt-detail-leftbar,.prompt-detail-rightbar{align-content:start;align-items:start;display:grid;gap:18px;grid-row:1;min-width:0}.prompt-detail-leftbar{grid-column:1}.prompt-detail-rightbar{grid-column:2}.prompt-detail-leftbar :is(.prompt-detail-card--execution-summary,.prompt-detail-sidebar),.prompt-detail-rightbar :is(.prompt-detail-card--execution-context,.prompt-detail-card--pull-requests){grid-column:auto;grid-row:auto}.prompt-detail-sidebar{align-content:start;align-items:start;display:grid;gap:18px}.prompt-detail-card{border:1px solid var(--category-color);border-radius:14px;padding:18px}.prompt-detail-card--wide{grid-column:1/-1}.prompt-detail-card h3{color:var(--category-color);font-size:18px;margin:0 0 14px}.prompt-detail-card .field{margin:0 0 14px}.prompt-detail-card .field:last-child{margin-bottom:0}.prompt-detail-card pre{overflow-wrap:anywhere;white-space:pre-wrap}.prompt-detail-diagnostic>span:last-child{white-space:pre-wrap}.prompt-detail-card--execution-context{min-width:0;overflow:hidden}.prompt-detail-card--execution-context :is(.field,.label,span,li){min-width:0;overflow-wrap:anywhere;word-break:break-word}.detail-list-field ul{margin:6px 0 0;padding-inline-start:22px}@media (max-width:620px){.prompt-detail-modal__content{grid-template-columns:1fr;padding-inline:8px}.prompt-detail-leftbar,.prompt-detail-rightbar{grid-column:1;grid-row:auto}}
|
|
277
277
|
.prompt-detail-provider-review{display:grid;gap:18px;grid-column:1/-1;grid-template-columns:minmax(0,1fr) minmax(260px,.58fr)}@media (max-width:760px){.prompt-detail-provider-review{grid-template-columns:1fr}}
|
|
278
278
|
.prompt-detail-provider-review-stack{display:grid;gap:18px;grid-column:1/-1}.prompt-detail-provider-review>.prompt-detail-card{align-self:stretch;box-sizing:border-box}.prompt-detail-card--commit-timeline{display:flex;flex-direction:column;min-height:0}.prompt-detail-commit-timeline__list{align-content:start;display:grid;flex:1;gap:10px;list-style:none;margin:0;max-height:none;min-height:0;overflow:auto;padding:0 8px 0 0;scrollbar-gutter:stable}.prompt-detail-commit-timeline__item{border-top:1px solid color-mix(in srgb,var(--category-color) 38%,transparent);display:grid;gap:3px;padding-top:10px}.prompt-detail-commit-timeline__item:first-child{border-top:0;padding-top:0}.prompt-detail-commit-timeline__meta{color:var(--dashboard-modal-muted);font-size:12px;line-height:1.35}.prompt-detail-commit-timeline__item code{font-size:12px;overflow-wrap:anywhere}.prompt-detail-commit-timeline__item>span{font-size:13px;line-height:1.4;overflow-wrap:anywhere}
|
|
279
279
|
.prompt-detail-commit-timeline__phase{border-top:1px solid color-mix(in srgb,var(--category-color) 52%,transparent);list-style:none;padding:13px 0 0}.prompt-detail-commit-timeline__phase:first-child{border-top:0;padding-top:0}.prompt-detail-commit-timeline__phase h4{color:var(--category-color);font-size:12px;letter-spacing:.04em;margin:0 0 9px;text-transform:uppercase}.prompt-detail-commit-timeline__phase-entries{display:grid;gap:10px;list-style:none;margin:0;padding:0 0 2px}.prompt-detail-commit-timeline__phase-entries .prompt-detail-commit-timeline__item{border-top:0;padding-top:0}
|
|
@@ -639,7 +639,7 @@ html[data-theme="light"] :is(.log-table,.telemetry-table) tbody tr:hover>td:firs
|
|
|
639
639
|
#currentRun{--category-color:#65c5d9;--category-secondary:#a7e7f2;background:#1e2b33}
|
|
640
640
|
#currentRun{container-name:active-execution;container-type:inline-size}
|
|
641
641
|
#currentRun .current-run__grid,#currentRun .current-run__grid>*{min-width:0}
|
|
642
|
-
@container active-execution (min-width:760px){#currentRun .current-run__grid{grid-template-columns:repeat(2,minmax(0,1fr))}#currentRun #currentDiagnostic{grid-column:1 / -1}}
|
|
642
|
+
@container active-execution (min-width:760px){#currentRun .current-run__grid{grid-template-columns:repeat(2,minmax(0,1fr))}#currentRun #executionIdentity{grid-column:1}#currentRun .card:has(#executionEstimate){grid-column:2}#currentRun #executionContext,#currentRun #currentDiagnostic{grid-column:1 / -1}}
|
|
643
643
|
#currentRun .card,#currentRun .card:has(#currentTime),#currentRun .card:has(#executionEstimate),#currentRun .card:has(#runId),#currentRun .card:has(#executionMode){--category-color:#65c5d9;--category-secondary:#a7e7f2;background:#1b2931;border-color:#65c5d9}
|
|
644
644
|
#currentRun :is(.execution-lifecycle,.execution-context--primary){background:#1b2931!important}
|
|
645
645
|
#engineering-dashboard-content>#technicalDetails{--category-color:var(--house-style);--section-secondary:#a7e7f2;background:#302a24;border-color:var(--house-style)}
|
|
@@ -985,7 +985,7 @@ html[data-theme="light"] ::-webkit-scrollbar-thumb:hover{background:#0a6b9d}
|
|
|
985
985
|
/* Telemetry can contain multiple long tables. Keep its outer dialog within
|
|
986
986
|
the visual viewport and scroll only its evidence body on small screens. */
|
|
987
987
|
.telemetry-detail-modal{--modal-accent:#fb7185;--category-color:var(--modal-accent);--modal-outer-gutter:24px;--modal-panel-max-width:1120px;--modal-shell-inset:24px;--modal-shell-padding:0}.telemetry-detail-modal__panel{--modal-header-inset:var(--dashboard-modal-panel-padding);display:grid;grid-template-rows:auto auto minmax(0,1fr);height:100%;max-height:100%;overflow:hidden;width:min(1120px,100%)}.telemetry-detail-modal__content{max-height:none;min-height:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;padding:0 4px 4px}@media(max-width:620px){.telemetry-detail-modal__panel{--modal-header-inset:18px;padding:18px}.telemetry-detail-modal__content{padding-inline:2px}}
|
|
988
|
-
.lifecycle-detail-modal{--modal-default-accent:#65c5d9}.lifecycle-detail-modal__panel{background:var(--modal-surface);border:2px solid var(--modal-accent);border-radius:var(--dashboard-modal-radius);box-sizing:border-box;color:var(--dashboard-modal-ink);display:grid;grid-template-rows:auto minmax(0,1fr);max-width:min(680px,calc(100vw - 32px));overflow:hidden;padding:var(--dashboard-modal-panel-padding);width:100%}.lifecycle-detail-modal__content{color:var(--dashboard-modal-ink);display:grid;gap:18px;max-height:none;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px}.lifecycle-detail-modal__content .field>span:last-child{color:var(--dashboard-modal-ink)}.lifecycle-detail-modal__content h3{color:var(--modal-accent);font-size:16px;margin:0 0 8px}.lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:var(--modal-secondary-accent)}.lifecycle-detail-modal__phase-list{display:grid;gap:8px;list-style:none;margin:0;padding:0}.lifecycle-detail-modal__phase-list li{align-items:baseline;border-bottom:1px solid color-mix(in srgb,var(--modal-accent) 32%,transparent);display:flex;gap:12px;justify-content:space-between;padding:8px 0}.lifecycle-detail-modal__phase-list li:last-child{border-bottom:0}.lifecycle-detail-modal__phase-list span{color:var(--dashboard-modal-muted);text-align:
|
|
988
|
+
.lifecycle-detail-modal{--modal-default-accent:#65c5d9}.lifecycle-detail-modal__panel{background:var(--modal-surface);border:2px solid var(--modal-accent);border-radius:var(--dashboard-modal-radius);box-sizing:border-box;color:var(--dashboard-modal-ink);display:grid;grid-template-rows:auto minmax(0,1fr);max-width:min(680px,calc(100vw - 32px));overflow:hidden;padding:var(--dashboard-modal-panel-padding);width:100%}.lifecycle-detail-modal__content{color:var(--dashboard-modal-ink);display:grid;gap:18px;max-height:none;min-height:0;overflow:auto;overscroll-behavior:contain;padding:4px}.lifecycle-detail-modal__content .field>span:last-child{color:var(--dashboard-modal-ink)}.lifecycle-detail-modal__content h3{color:var(--modal-accent);font-size:16px;margin:0 0 8px}.lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:var(--modal-secondary-accent)}.lifecycle-detail-modal__phase-list{display:grid;gap:8px;list-style:none;margin:0;padding:0}.lifecycle-detail-modal__phase-list li{align-items:baseline;border-bottom:1px solid color-mix(in srgb,var(--modal-accent) 32%,transparent);display:flex;gap:12px;justify-content:space-between;padding:8px 0}.lifecycle-detail-modal__phase-list li:last-child{border-bottom:0}.lifecycle-detail-modal__phase-list span{color:var(--dashboard-modal-muted);text-align:start}html[data-theme="light"] .lifecycle-detail-modal :is(.label,.lifecycle-detail-modal__phase-list strong){color:color-mix(in srgb,var(--modal-secondary-accent) 76%,#182230)}@media(max-width:620px){.lifecycle-detail-modal__panel{max-width:calc(100vw - 32px);padding:18px}.lifecycle-detail-modal__phase-list li{align-items:flex-start;flex-direction:column;gap:4px}.lifecycle-detail-modal__phase-list span{text-align:start}}
|
|
989
989
|
/* A telemetry Run-ID is a redundant activator inside an interactive row.
|
|
990
990
|
The row owns its continuous rose selection surface, never the text itself. */
|
|
991
991
|
.telemetry-run-link{-webkit-appearance:none;appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;font:inherit;line-height:inherit;min-height:0;min-width:0;padding:0;text-align:left;text-decoration:none;white-space:nowrap}.telemetry-run-link:is(:hover,:active){background:transparent!important;color:inherit!important}.telemetry-run-link:is(:focus,:focus-visible){border-color:transparent!important;box-shadow:none!important;outline:0!important}
|
|
@@ -1863,6 +1863,8 @@ function renderExecutionContext(context, execution = {}) {
|
|
|
1863
1863
|
[t("detail.target_checkout"), execution.checkout_path],
|
|
1864
1864
|
[t("detail.target_branch"), execution.target_branch],
|
|
1865
1865
|
[t("ui.active_branch"), execution.active_branch],
|
|
1866
|
+
[t("detail.candidate_sha"), execution.candidate_sha],
|
|
1867
|
+
[t("detail.repair_iteration"), execution.repair_iteration],
|
|
1866
1868
|
].filter(([, value]) => executionContextValue(value));
|
|
1867
1869
|
if (!context || typeof context !== "object") {
|
|
1868
1870
|
card.replaceChildren(
|
|
@@ -2244,7 +2246,7 @@ function lifecycleRepairEvidence(step) {
|
|
|
2244
2246
|
dynamicField(t("detail.failed_checks"), item.failed_checks),
|
|
2245
2247
|
dynamicField(t("detail.proposed_action"), item.proposed_action),
|
|
2246
2248
|
dynamicField(t("detail.ai_repair_summary"), item.agent_summary),
|
|
2247
|
-
lifecycleDetailField(t("detail.commit"), String(item.commit_sha || t("detail.not_recorded"))),
|
|
2249
|
+
lifecycleDetailField(t("detail.commit"), item.commit_sha === "not_recorded" ? t("detail.not_recorded") : String(item.commit_sha || t("detail.not_recorded"))),
|
|
2248
2250
|
lifecycleDetailField(t("detail.outcome"), t("lifecycle.repair_outcome." + outcome, {}, outcome || t("detail.not_recorded"))),
|
|
2249
2251
|
);
|
|
2250
2252
|
section.append(heading, grid);
|
|
@@ -2386,18 +2388,24 @@ function lifecycleFlow(projection, { historical = false } = {}) {
|
|
|
2386
2388
|
return section;
|
|
2387
2389
|
}
|
|
2388
2390
|
function activeRunPullRequestEntries(execution) {
|
|
2389
|
-
const repository = String(execution?.target_repository || "").trim();
|
|
2390
|
-
|
|
2391
|
+
const repository = String(execution?.github_repository || execution?.target_repository || "").trim();
|
|
2392
|
+
const githubRepository = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(repository)
|
|
2393
|
+
? repository : null;
|
|
2394
|
+
const seen = new Set();
|
|
2391
2395
|
return [
|
|
2396
|
+
["bound", execution?.pull_request],
|
|
2392
2397
|
["implementation", execution?.implementation_pr],
|
|
2393
2398
|
["finalization", execution?.finalization_pr],
|
|
2394
2399
|
].flatMap(([role, value]) => {
|
|
2395
2400
|
const number = Number(value);
|
|
2396
|
-
if (!Number.isInteger(number) || number <= 0) return [];
|
|
2401
|
+
if (!Number.isInteger(number) || number <= 0 || seen.has(number)) return [];
|
|
2402
|
+
seen.add(number);
|
|
2397
2403
|
return [{
|
|
2398
2404
|
role,
|
|
2399
2405
|
number,
|
|
2400
|
-
url:
|
|
2406
|
+
url: githubRepository
|
|
2407
|
+
? `https://github.com/${githubRepository.split("/").map(encodeURIComponent).join("/")}/pull/${number}`
|
|
2408
|
+
: null,
|
|
2401
2409
|
}];
|
|
2402
2410
|
});
|
|
2403
2411
|
}
|
|
@@ -2408,19 +2416,22 @@ function renderActivePullRequests(execution, lifecycle) {
|
|
|
2408
2416
|
const entries = activeRunPullRequestEntries(execution);
|
|
2409
2417
|
if (!entries.length) return;
|
|
2410
2418
|
const labels = {
|
|
2419
|
+
bound: t("detail.bound_pull_request"),
|
|
2411
2420
|
implementation: t("detail.implementation_pull_request"),
|
|
2412
2421
|
finalization: t("detail.finalization_pull_request"),
|
|
2413
2422
|
};
|
|
2414
2423
|
const fields = entries.map((entry) => {
|
|
2415
2424
|
const field = detailField(labels[entry.role], "");
|
|
2416
|
-
const
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2425
|
+
const value = entry.url ? document.createElement("a") : document.createElement("span");
|
|
2426
|
+
value.className = "prompt-detail-pr-link";
|
|
2427
|
+
value.textContent = `#${entry.number}${entry.url ? " ↗" : ""}`;
|
|
2428
|
+
value.setAttribute("aria-label", `${labels[entry.role]} #${entry.number}`);
|
|
2429
|
+
if (entry.url) {
|
|
2430
|
+
value.href = entry.url;
|
|
2431
|
+
value.target = "_blank";
|
|
2432
|
+
value.rel = "noopener noreferrer";
|
|
2433
|
+
}
|
|
2434
|
+
field.lastElementChild.replaceChildren(value);
|
|
2424
2435
|
return field;
|
|
2425
2436
|
});
|
|
2426
2437
|
const card = promptDetailCard(
|
|
@@ -3759,6 +3770,7 @@ const COMPONENT_DETAIL_CODES = new Set([
|
|
|
3759
3770
|
"LIFECYCLE_WORKER_SERVER_HOSTED", "OPERATIONS_CONSOLE_SERVER_NATIVE",
|
|
3760
3771
|
"DASHBOARD_RELAY_TAILSCALE_AVAILABLE", "DASHBOARD_RELAY_LAUNCH_AGENT_UNLOADED",
|
|
3761
3772
|
"DASHBOARD_RELAY_PROCESS_INACTIVE", "DASHBOARD_RELAY_LIFECYCLE_UNAVAILABLE",
|
|
3773
|
+
"DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE", "DASHBOARD_RELAY_ENDPOINT_UNREACHABLE",
|
|
3762
3774
|
]);
|
|
3763
3775
|
function transportState(code) {
|
|
3764
3776
|
const raw = String(code || ""), normalized = LEGACY_TRANSPORT_STATUS_CODES[raw] || raw;
|
|
@@ -3895,6 +3907,19 @@ function showComponentModal(payload) {
|
|
|
3895
3907
|
payload.healthy ? t("component.health_healthy") : t("component.health_unhealthy"),
|
|
3896
3908
|
);
|
|
3897
3909
|
componentDetailField(fields, t("component.version"), payload.version);
|
|
3910
|
+
if (payload.component === "dashboard_relay") {
|
|
3911
|
+
componentDetailEndpoint(fields, t("component.relay_access"), payload.relay_endpoint);
|
|
3912
|
+
componentDetailField(fields, t("component.tailscale_ipv4"), payload.tailscale_ipv4);
|
|
3913
|
+
componentDetailField(
|
|
3914
|
+
fields,
|
|
3915
|
+
t("component.relay_probe"),
|
|
3916
|
+
payload.relay_reachable === true
|
|
3917
|
+
? t("component.relay_reachable")
|
|
3918
|
+
: payload.relay_reachable === false
|
|
3919
|
+
? t("component.relay_unreachable")
|
|
3920
|
+
: null,
|
|
3921
|
+
);
|
|
3922
|
+
}
|
|
3898
3923
|
if (payload.kind === "TRANSPORT") {
|
|
3899
3924
|
const transportTimestamp = (value) => value ? formatTimestamp(value) : null;
|
|
3900
3925
|
if (payload.component === "http_ingress")
|
|
@@ -7808,7 +7833,8 @@ function promptDetailExecutionSections(history) {
|
|
|
7808
7833
|
const dynamicRows = [];
|
|
7809
7834
|
const dynamicDiagnosticField = (label, source) => {
|
|
7810
7835
|
const original = executionContextValue(source), value = formatDiagnostic(original || t("detail.not_recorded"));
|
|
7811
|
-
const field = detailField(label, value
|
|
7836
|
+
const field = detailField(label, value);
|
|
7837
|
+
field.classList.add("prompt-detail-diagnostic");
|
|
7812
7838
|
if (dynamicDiagnosticSource(original)) dynamicRows.push({ source: original, element: field.lastElementChild, format: formatDiagnosticProjection });
|
|
7813
7839
|
return field;
|
|
7814
7840
|
};
|
|
@@ -7912,19 +7938,12 @@ function promptDetailUsageSection(usage) {
|
|
|
7912
7938
|
usage_snapshot_count: t("detail.usage_snapshot_count"),
|
|
7913
7939
|
intermediate_usage_delta_available: t("detail.intermediate_usage_delta_available"),
|
|
7914
7940
|
maximum_incremental_input_tokens: t("detail.maximum_incremental_input_tokens"),
|
|
7915
|
-
actual_single_request_context_size: t("detail.actual_single_request_context_size"),
|
|
7916
|
-
active_context_size: t("detail.active_context_size"),
|
|
7917
7941
|
estimated_credits: t("detail.estimated_credits"),
|
|
7918
7942
|
estimated_eur: t("detail.estimated_eur"),
|
|
7919
|
-
speed_state: t("detail.speed_state"),
|
|
7920
7943
|
usage_authority: t("detail.usage_authority"),
|
|
7921
7944
|
};
|
|
7922
7945
|
const visible = Object.entries(usage).filter(([key, value]) => labels[key] && value !== null && typeof value !== "object");
|
|
7923
7946
|
const displayValue = (key, value) => {
|
|
7924
|
-
if (["actual_single_request_context_size", "active_context_size"].includes(key) && value === "UNAVAILABLE") {
|
|
7925
|
-
return t("format.unavailable");
|
|
7926
|
-
}
|
|
7927
|
-
if (key === "speed_state") return t(`provider_usage.speed.${String(value).toLowerCase()}`, {}, String(value));
|
|
7928
7947
|
if (key === "usage_authority") return t(`provider_usage.authority.${String(value).toLowerCase()}`, {}, String(value));
|
|
7929
7948
|
return value;
|
|
7930
7949
|
};
|
|
@@ -3391,11 +3391,11 @@ Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.detail_assurance":"Kwaliteits-
|
|
|
3391
3391
|
Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.detail_assurance":"Qualitäts- und Sicherheitsprüfung","lifecycle.repair_rounds":"Reparaturrunden: {used}/{maximum}","lifecycle.assurance_no_findings":"Keine Befunde erfasst"});
|
|
3392
3392
|
Object.assign(DASHBOARD_MESSAGES.fr, {"lifecycle.detail_assurance":"Assurance qualité et sécurité","lifecycle.repair_rounds":"Cycles de correction : {used}/{maximum}","lifecycle.assurance_no_findings":"Aucune conclusion enregistrée"});
|
|
3393
3393
|
Object.assign(DASHBOARD_MESSAGES.es, {"lifecycle.detail_assurance":"Garantía de calidad y seguridad","lifecycle.repair_rounds":"Rondas de reparación: {used}/{maximum}","lifecycle.assurance_no_findings":"No se registraron hallazgos"});
|
|
3394
|
-
Object.assign(DASHBOARD_MESSAGES.en, {"lifecycle.detail_repair_evidence":"Executed pull request check repairs","lifecycle.detail_repair_iteration":"Repair iteration {iteration}","lifecycle.repair_outcome.submitted_for_recheck":"Submitted for recheck","lifecycle.repair_outcome.agent_failed":"Agent repair failed","lifecycle.repair_outcome.agent_timed_out":"Agent repair timed out"});
|
|
3395
|
-
Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.detail_repair_evidence":"Uitgevoerd PR-controleherstel","lifecycle.detail_repair_iteration":"Hersteliteratie {iteration}","lifecycle.repair_outcome.submitted_for_recheck":"Ingediend voor hercontrole","lifecycle.repair_outcome.agent_failed":"Agentherstel mislukt","lifecycle.repair_outcome.agent_timed_out":"Agentherstel heeft de tijdslimiet overschreden"});
|
|
3396
|
-
Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.detail_repair_evidence":"Durchgeführte PR-Prüfreparaturen","lifecycle.detail_repair_iteration":"Reparaturiteration {iteration}","lifecycle.repair_outcome.submitted_for_recheck":"Zur erneuten Prüfung eingereicht","lifecycle.repair_outcome.agent_failed":"Agentenreparatur fehlgeschlagen","lifecycle.repair_outcome.agent_timed_out":"Zeitlimit der Agentenreparatur überschritten"});
|
|
3397
|
-
Object.assign(DASHBOARD_MESSAGES.fr, {"lifecycle.detail_repair_evidence":"Réparations de contrôles de pull request effectuées","lifecycle.detail_repair_iteration":"Itération de réparation {iteration}","lifecycle.repair_outcome.submitted_for_recheck":"Soumis pour nouvelle vérification","lifecycle.repair_outcome.agent_failed":"Réparation par l’agent échouée","lifecycle.repair_outcome.agent_timed_out":"La réparation par l’agent a dépassé le délai"});
|
|
3398
|
-
Object.assign(DASHBOARD_MESSAGES.es, {"lifecycle.detail_repair_evidence":"Reparaciones de comprobaciones de solicitud realizadas","lifecycle.detail_repair_iteration":"Iteración de reparación {iteration}","lifecycle.repair_outcome.submitted_for_recheck":"Enviado para nueva comprobación","lifecycle.repair_outcome.agent_failed":"La reparación del agente falló","lifecycle.repair_outcome.agent_timed_out":"La reparación del agente superó el tiempo límite"});
|
|
3394
|
+
Object.assign(DASHBOARD_MESSAGES.en, {"lifecycle.detail_repair_evidence":"Executed pull request check repairs","lifecycle.detail_repair_iteration":"Repair iteration {iteration}","lifecycle.repair_outcome.planned":"Planned","lifecycle.repair_outcome.submitted_for_recheck":"Submitted for recheck","lifecycle.repair_outcome.agent_failed":"Agent repair failed","lifecycle.repair_outcome.agent_timed_out":"Agent repair timed out"});
|
|
3395
|
+
Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.detail_repair_evidence":"Uitgevoerd PR-controleherstel","lifecycle.detail_repair_iteration":"Hersteliteratie {iteration}","lifecycle.repair_outcome.planned":"Gepland","lifecycle.repair_outcome.submitted_for_recheck":"Ingediend voor hercontrole","lifecycle.repair_outcome.agent_failed":"Agentherstel mislukt","lifecycle.repair_outcome.agent_timed_out":"Agentherstel heeft de tijdslimiet overschreden"});
|
|
3396
|
+
Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.detail_repair_evidence":"Durchgeführte PR-Prüfreparaturen","lifecycle.detail_repair_iteration":"Reparaturiteration {iteration}","lifecycle.repair_outcome.planned":"Geplant","lifecycle.repair_outcome.submitted_for_recheck":"Zur erneuten Prüfung eingereicht","lifecycle.repair_outcome.agent_failed":"Agentenreparatur fehlgeschlagen","lifecycle.repair_outcome.agent_timed_out":"Zeitlimit der Agentenreparatur überschritten"});
|
|
3397
|
+
Object.assign(DASHBOARD_MESSAGES.fr, {"lifecycle.detail_repair_evidence":"Réparations de contrôles de pull request effectuées","lifecycle.detail_repair_iteration":"Itération de réparation {iteration}","lifecycle.repair_outcome.planned":"Planifiée","lifecycle.repair_outcome.submitted_for_recheck":"Soumis pour nouvelle vérification","lifecycle.repair_outcome.agent_failed":"Réparation par l’agent échouée","lifecycle.repair_outcome.agent_timed_out":"La réparation par l’agent a dépassé le délai"});
|
|
3398
|
+
Object.assign(DASHBOARD_MESSAGES.es, {"lifecycle.detail_repair_evidence":"Reparaciones de comprobaciones de solicitud realizadas","lifecycle.detail_repair_iteration":"Iteración de reparación {iteration}","lifecycle.repair_outcome.planned":"Planificada","lifecycle.repair_outcome.submitted_for_recheck":"Enviado para nueva comprobación","lifecycle.repair_outcome.agent_failed":"La reparación del agente falló","lifecycle.repair_outcome.agent_timed_out":"La reparación del agente superó el tiempo límite"});
|
|
3399
3399
|
Object.assign(DASHBOARD_MESSAGES.en, {"lifecycle.step.autonomous_quality_repair":"Autonomous quality repair","lifecycle.detail_autonomous_quality_repair_evidence":"Completed quality repair iterations"});
|
|
3400
3400
|
Object.assign(DASHBOARD_MESSAGES.nl, {"lifecycle.step.autonomous_quality_repair":"Autonoom kwaliteitsherstel","lifecycle.detail_autonomous_quality_repair_evidence":"Uitgevoerde kwaliteitshersteliteraties"});
|
|
3401
3401
|
Object.assign(DASHBOARD_MESSAGES.de, {"lifecycle.step.autonomous_quality_repair":"Autonome Qualitätsreparatur","lifecycle.detail_autonomous_quality_repair_evidence":"Durchgeführte Qualitätsreparaturiterationen"});
|
|
@@ -3722,11 +3722,11 @@ Object.assign(DASHBOARD_MESSAGES.de, {"configuration.provider_readiness_interval
|
|
|
3722
3722
|
Object.assign(DASHBOARD_MESSAGES.fr, {"configuration.provider_readiness_interval":"Intervalle de vérification de disponibilité des fournisseurs","configuration.provider_readiness_interval_help":"À quelle fréquence ce tableau de bord ouvert revérifie la disponibilité locale de Codex et GitHub sans démarrer d’exécution.","configuration.minute_1":"1 minute","configuration.minutes_5":"5 minutes","configuration.minutes_10":"10 minutes"});
|
|
3723
3723
|
Object.assign(DASHBOARD_MESSAGES.es, {"configuration.provider_readiness_interval":"Intervalo de comprobación de disponibilidad de proveedores","configuration.provider_readiness_interval_help":"Con qué frecuencia este panel abierto vuelve a comprobar la disponibilidad local de Codex y GitHub sin iniciar una ejecución.","configuration.minute_1":"1 minuto","configuration.minutes_5":"5 minutos","configuration.minutes_10":"10 minutos"});
|
|
3724
3724
|
|
|
3725
|
-
Object.assign(DASHBOARD_MESSAGES.en, {"detail.pull_requests":"Pull requests","detail.implementation_pull_request":"Implementation pull request","detail.finalization_pull_request":"Finalization pull request"});
|
|
3726
|
-
Object.assign(DASHBOARD_MESSAGES.nl, {"detail.pull_requests":"Pull requests","detail.implementation_pull_request":"Implementatie-pullrequest","detail.finalization_pull_request":"Finalisatie-pullrequest"});
|
|
3727
|
-
Object.assign(DASHBOARD_MESSAGES.de, {"detail.pull_requests":"Pull Requests","detail.implementation_pull_request":"Implementierungs-Pull-Request","detail.finalization_pull_request":"Finalisierungs-Pull-Request"});
|
|
3728
|
-
Object.assign(DASHBOARD_MESSAGES.fr, {"detail.pull_requests":"Pull requests","detail.implementation_pull_request":"Pull request d’implémentation","detail.finalization_pull_request":"Pull request de finalisation"});
|
|
3729
|
-
Object.assign(DASHBOARD_MESSAGES.es, {"detail.pull_requests":"Solicitudes de extracción","detail.implementation_pull_request":"Solicitud de extracción de implementación","detail.finalization_pull_request":"Solicitud de extracción de finalización"});
|
|
3725
|
+
Object.assign(DASHBOARD_MESSAGES.en, {"detail.pull_requests":"Pull requests","detail.bound_pull_request":"Bound pull request","detail.implementation_pull_request":"Implementation pull request","detail.finalization_pull_request":"Finalization pull request","detail.candidate_sha":"Candidate SHA"});
|
|
3726
|
+
Object.assign(DASHBOARD_MESSAGES.nl, {"detail.pull_requests":"Pull requests","detail.bound_pull_request":"Gebonden pull request","detail.implementation_pull_request":"Implementatie-pullrequest","detail.finalization_pull_request":"Finalisatie-pullrequest","detail.candidate_sha":"Kandidaat-SHA"});
|
|
3727
|
+
Object.assign(DASHBOARD_MESSAGES.de, {"detail.pull_requests":"Pull Requests","detail.bound_pull_request":"Gebundener Pull Request","detail.implementation_pull_request":"Implementierungs-Pull-Request","detail.finalization_pull_request":"Finalisierungs-Pull-Request","detail.candidate_sha":"Kandidaten-SHA"});
|
|
3728
|
+
Object.assign(DASHBOARD_MESSAGES.fr, {"detail.pull_requests":"Pull requests","detail.bound_pull_request":"Pull request lié","detail.implementation_pull_request":"Pull request d’implémentation","detail.finalization_pull_request":"Pull request de finalisation","detail.candidate_sha":"SHA candidat"});
|
|
3729
|
+
Object.assign(DASHBOARD_MESSAGES.es, {"detail.pull_requests":"Solicitudes de extracción","detail.bound_pull_request":"Solicitud de extracción vinculada","detail.implementation_pull_request":"Solicitud de extracción de implementación","detail.finalization_pull_request":"Solicitud de extracción de finalización","detail.candidate_sha":"SHA candidato"});
|
|
3730
3730
|
Object.assign(DASHBOARD_MESSAGES.en, {"detail.pull_request_commits":"Commits","detail.pull_request_checks":"GitHub checks","detail.pull_request_changed_files":"Files changed"});
|
|
3731
3731
|
Object.assign(DASHBOARD_MESSAGES.nl, {"detail.pull_request_commits":"Commits","detail.pull_request_checks":"GitHub-controles","detail.pull_request_changed_files":"Gewijzigde bestanden"});
|
|
3732
3732
|
Object.assign(DASHBOARD_MESSAGES.de, {"detail.pull_request_commits":"Commits","detail.pull_request_checks":"GitHub-Prüfungen","detail.pull_request_changed_files":"Geänderte Dateien"});
|
|
@@ -3904,6 +3904,12 @@ Object.assign(DASHBOARD_MESSAGES.es, {
|
|
|
3904
3904
|
"ui.execution_status": "Estado de ejecución", "configuration.dashboard_settings": "Configuración de la consola de operaciones", "configuration.dashboard_stream_interval": "Intervalo de actualización de la consola de operaciones", "configuration.inbox_scan_interval": "Intervalo de exploración de entrada File Inbox", "configuration.operator_merge_interval_help": "Con qué frecuencia el Lifecycle Worker comprueba si ha cambiado el estado de una pull request que espera una fusión del operador.", "configuration.timeout_policy_description": "Límites fijos administrados por el host para cada acción del proveedor. Estos límites no se pueden editar en la consola de operaciones.", "dashboard.status_invalid": "El estado de la consola de operaciones no es válido.", "dashboard.status_unavailable": "La consola de operaciones no está disponible.", "header.skip": "Ir al contenido de la consola de operaciones", "logs.dashboard_unavailable": "El registro de la plataforma no está disponible.", "queue.defer_description": "¿Mover {title} fuera de la cola activa? El envío se conserva como entrada File Inbox diferida y no se ejecuta hasta que se devuelva explícitamente.", "queue.defer_failed": "El envío de entrada File Inbox no se pudo diferir de forma segura.", "queue.managed_branch_blocked": "La entrada File Inbox está en pausa porque este espacio de trabajo está en una rama de trabajo. El Execution Host solo puede reclamar trabajo desde main.", "queue.managed_branch_recovery": "La restauración devuelve un espacio de trabajo limpio a main y reinicia el Lifecycle Worker. No cambia ningún elemento de la cola.", "queue.managed_branch_recovery_ready": "Espacio de trabajo restaurado a main; el Lifecycle Worker vuelve a estar activo.", "queue.managed_branch_recovery_title": "Restaurar el espacio de trabajo de entrada File Inbox", "queue.runtime_invocation_blocked": "La entrada File Inbox está esperando porque la CLI local de Codex no puede iniciarse. Repare la instalación administrada de la CLI de Codex antes de volver a intentarlo.", "recovery.details": "¿Reintentar esta ejecución terminal mediante la ruta normal de entrada File Inbox? Engineering Platform vuelve a realizar la comprobación previa actual antes de crear una ejecución de sustitución. La ejecución fallida y sus evidencias no cambian.", "recovery.ready": "La recuperación está en cola; el Lifecycle Worker reclamará la ejecución de sustitución.", "refresh.refreshing": "Actualizando la consola de operaciones…", "status_reconciliation.confirmation": "Se colocará una conciliación Finalization específica en la cola de envíos de Engineering Platform. No cambia ningún comportamiento de producto ni de ejecución.", "ui.codex_cli_update_confirmation": "¿Instalar la actualización disponible de la CLI de Codex en esta máquina? La consola de operaciones verificará después la versión instalada.", "workspace.worktree_switch_confirmation": "¿Cambiar Engineering Platform a {branch} en {path}?\n\nEngineering Platform vuelve a comprobar:\n• no hay ninguna ejecución activa;\n• la cola de entrada File Inbox está vacía;\n• este árbol de trabajo registrado está limpio y exactamente en {branch}.\n\nDespués reinicia la consola de operaciones, el Lifecycle Worker y el Server Relay desde este árbol de trabajo.", "component.dashboard_relay": "Server Relay", "dashboard.health.DASHBOARD_RELAY_ACTIVE": "Server Relay activo", "dashboard.health.DASHBOARD_RELAY_UNAVAILABLE": "Server Relay no disponible", "dashboard.health.watcher": "Entrada File Inbox", "dashboard.health.watcher_state": "Estado del Lifecycle Worker", "state.WATCHER_IDLE": "No hay ejecución activa",
|
|
3905
3905
|
});
|
|
3906
3906
|
|
|
3907
|
+
Object.assign(DASHBOARD_MESSAGES.en, {"component.relay_access":"Relay access","component.tailscale_ipv4":"Tailscale IPv4","component.relay_probe":"Functional relay check","component.relay_reachable":"Reachable","component.relay_unreachable":"Unreachable","component.detail.DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE":"Tailscale address unavailable","component.detail.DASHBOARD_RELAY_ENDPOINT_UNREACHABLE":"Relay endpoint unreachable"});
|
|
3908
|
+
Object.assign(DASHBOARD_MESSAGES.nl, {"component.relay_access":"Relay-toegang","component.tailscale_ipv4":"Tailscale-IPv4","component.relay_probe":"Functionele relaycontrole","component.relay_reachable":"Bereikbaar","component.relay_unreachable":"Niet bereikbaar","component.detail.DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE":"Tailscale-adres niet beschikbaar","component.detail.DASHBOARD_RELAY_ENDPOINT_UNREACHABLE":"Relay-endpoint niet bereikbaar"});
|
|
3909
|
+
Object.assign(DASHBOARD_MESSAGES.de, {"component.relay_access":"Relay-Zugriff","component.tailscale_ipv4":"Tailscale-IPv4","component.relay_probe":"Funktionale Relay-Prüfung","component.relay_reachable":"Erreichbar","component.relay_unreachable":"Nicht erreichbar","component.detail.DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE":"Tailscale-Adresse nicht verfügbar","component.detail.DASHBOARD_RELAY_ENDPOINT_UNREACHABLE":"Relay-Endpunkt nicht erreichbar"});
|
|
3910
|
+
Object.assign(DASHBOARD_MESSAGES.fr, {"component.relay_access":"Accès au relais","component.tailscale_ipv4":"IPv4 Tailscale","component.relay_probe":"Vérification fonctionnelle du relais","component.relay_reachable":"Accessible","component.relay_unreachable":"Inaccessible","component.detail.DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE":"Adresse Tailscale indisponible","component.detail.DASHBOARD_RELAY_ENDPOINT_UNREACHABLE":"Point d’accès du relais inaccessible"});
|
|
3911
|
+
Object.assign(DASHBOARD_MESSAGES.es, {"component.relay_access":"Acceso al relé","component.tailscale_ipv4":"IPv4 de Tailscale","component.relay_probe":"Comprobación funcional del relé","component.relay_reachable":"Accesible","component.relay_unreachable":"No accesible","component.detail.DASHBOARD_RELAY_TAILSCALE_UNAVAILABLE":"Dirección de Tailscale no disponible","component.detail.DASHBOARD_RELAY_ENDPOINT_UNREACHABLE":"Punto de acceso del relé no accesible"});
|
|
3912
|
+
|
|
3907
3913
|
export class LocalizationContractError extends Error {
|
|
3908
3914
|
constructor({ locale, key, surface = "Console" }) {
|
|
3909
3915
|
super(`LOCALIZATION_MISSING locale=${locale} key=${key} surface=${surface}`);
|
|
@@ -37,6 +37,7 @@ ROUTE_OWNERSHIP_MATRIX: tuple[ConsoleRoute, ...] = (
|
|
|
37
37
|
ConsoleRoute(("GET",), r"/(?:favicon\.ico|apple-touch-icon(?:-precomposed)?\.png)", PLATFORM, "console_shell", "Console icons"),
|
|
38
38
|
ConsoleRoute(("GET",), r"/assets/[A-Za-z0-9_./-]+", PLATFORM, "console_shell", "Installed Console assets"),
|
|
39
39
|
ConsoleRoute(("GET",), r"/health", PLATFORM, "platform_components", "Platform Components health", True),
|
|
40
|
+
ConsoleRoute(("GET",), r"/api/health", PLATFORM, "platform_components", "Platform Components health compatibility alias", True),
|
|
40
41
|
ConsoleRoute(("GET",), r"/api/platform-status", PLATFORM, "platform_components", "Platform Components projection", True),
|
|
41
42
|
ConsoleRoute(("GET",), r"/api/(?:dashboard-snapshot|status|events)", PLATFORM, "platform_components", "Platform status projection or stream", True),
|
|
42
43
|
ConsoleRoute(("GET",), rf"/api/components/{PLATFORM_COMPONENT_ROUTE_PATTERN}/details", PLATFORM, "platform_components", "Component detail popout", True),
|
|
@@ -39,6 +39,21 @@ def _successful_reviewer_agents(value: object) -> list[dict[str, object]]:
|
|
|
39
39
|
return reviewers if all(item.get("status") == "completed" for item in reviewers) else []
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
def _run_workspace_preflight(root: Path, run_id: object) -> dict[str, object]:
|
|
43
|
+
"""Return workspace-preflight evidence only when it belongs to this run.
|
|
44
|
+
|
|
45
|
+
The dashboard may retain the most recent workspace preflight for technical
|
|
46
|
+
diagnostics, but the active-run card must never borrow a branch result
|
|
47
|
+
from another run.
|
|
48
|
+
"""
|
|
49
|
+
if not isinstance(run_id, str) or not run_id:
|
|
50
|
+
return {}
|
|
51
|
+
preflight = latest_workspace_preflight(root)
|
|
52
|
+
if not isinstance(preflight, dict) or preflight.get("run_id") != run_id:
|
|
53
|
+
return {}
|
|
54
|
+
return preflight
|
|
55
|
+
|
|
56
|
+
|
|
42
57
|
def _active_runner_checkpoint(root: Path) -> tuple[dict[str, object], dict[str, object]] | None:
|
|
43
58
|
"""Return a current checkpoint only while its recorded runner group exists.
|
|
44
59
|
|
|
@@ -349,6 +364,7 @@ def status(root: Path) -> bytes:
|
|
|
349
364
|
try:
|
|
350
365
|
if live is None:
|
|
351
366
|
raise ValueError("No canonical live status")
|
|
367
|
+
run_workspace_preflight = _run_workspace_preflight(root, live.get("run_id"))
|
|
352
368
|
live_liveness = lease_liveness(root, live.get("run_id"))
|
|
353
369
|
if runner_liveness is not None and runner_liveness.get("state") == "LIVE":
|
|
354
370
|
live_liveness = {**live_liveness, **runner_liveness}
|
|
@@ -392,8 +408,15 @@ def status(root: Path) -> bytes:
|
|
|
392
408
|
"predecessor_recovery_action": watcher.get("predecessor_recovery_action"),
|
|
393
409
|
"execution_mode": live.get("execution_mode"),
|
|
394
410
|
"target_repository": live.get("target_repository"),
|
|
411
|
+
"github_repository": live.get("github_repository"),
|
|
395
412
|
"checkout_path": live.get("checkout_path"),
|
|
413
|
+
# This is the observed branch from the preflight owned by the
|
|
414
|
+
# displayed run; active_branch remains the current checkout.
|
|
415
|
+
"target_branch": run_workspace_preflight.get("branch"),
|
|
396
416
|
"active_branch": live.get("active_branch"),
|
|
417
|
+
"candidate_sha": live.get("candidate_sha"),
|
|
418
|
+
"repair_iteration": live.get("repair_iteration"),
|
|
419
|
+
"workspace_preflight": run_workspace_preflight,
|
|
397
420
|
# Only a wholly successful specialist review survives its
|
|
398
421
|
# live phase as historical evidence for this active run. A
|
|
399
422
|
# partial, failed or stale reviewer projection remains hidden.
|
|
@@ -8,17 +8,26 @@ let loopbackAddress = "127.0.0.1"
|
|
|
8
8
|
func tailscaleAddress() -> String? {
|
|
9
9
|
let process = Process()
|
|
10
10
|
let output = Pipe()
|
|
11
|
+
let reader = output.fileHandleForReading
|
|
12
|
+
let writer = output.fileHandleForWriting
|
|
13
|
+
defer {
|
|
14
|
+
reader.closeFile()
|
|
15
|
+
writer.closeFile()
|
|
16
|
+
}
|
|
11
17
|
process.executableURL = URL(fileURLWithPath: "/usr/local/bin/tailscale")
|
|
12
18
|
process.arguments = ["ip", "-4"]
|
|
13
19
|
process.standardOutput = output
|
|
14
20
|
do {
|
|
15
21
|
try process.run()
|
|
22
|
+
// The child owns its duplicated descriptor. Closing the parent's
|
|
23
|
+
// write end prevents retries from retaining one pipe per attempt.
|
|
24
|
+
writer.closeFile()
|
|
16
25
|
process.waitUntilExit()
|
|
17
26
|
} catch {
|
|
18
27
|
return nil
|
|
19
28
|
}
|
|
20
29
|
guard process.terminationStatus == 0,
|
|
21
|
-
let text = String(data:
|
|
30
|
+
let text = String(data: reader.readDataToEndOfFile(), encoding: .utf8),
|
|
22
31
|
let value = text.split(whereSeparator: \.isNewline).first
|
|
23
32
|
else { return nil }
|
|
24
33
|
return String(value)
|
|
@@ -113,8 +113,9 @@ def project_output(command: Iterable[str], output: str, exit_code: int) -> Evide
|
|
|
113
113
|
class ToolProxyEnvironment:
|
|
114
114
|
"""Temporary PATH proxy. It retains no output after the invocation ends."""
|
|
115
115
|
|
|
116
|
-
def __init__(self) -> None:
|
|
116
|
+
def __init__(self, *, deny_delivery_mutations: bool = False) -> None:
|
|
117
117
|
self._temporary: TemporaryDirectory[str] | None = None
|
|
118
|
+
self._deny_delivery_mutations = deny_delivery_mutations
|
|
118
119
|
|
|
119
120
|
def __enter__(self) -> Mapping[str, str]:
|
|
120
121
|
self._temporary = TemporaryDirectory(prefix="engineering-platform-evidence-")
|
|
@@ -149,6 +150,10 @@ class ToolProxyEnvironment:
|
|
|
149
150
|
environment["ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH"] = environment.get("PATH", os.defpath)
|
|
150
151
|
environment["PATH"] = f"{directory}{os.pathsep}{environment['ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH']}"
|
|
151
152
|
environment["ENGINEERING_PLATFORM_CONTEXT_ESCALATION_FILE"] = str(directory / "context-escalations.jsonl")
|
|
153
|
+
if self._deny_delivery_mutations:
|
|
154
|
+
# This is deliberately an invocation-scoped capability boundary,
|
|
155
|
+
# not a prompt convention. The validation adapter opts into it.
|
|
156
|
+
environment["ENGINEERING_PLATFORM_DENY_DELIVERY_MUTATIONS"] = "1"
|
|
152
157
|
return environment
|
|
153
158
|
|
|
154
159
|
def __exit__(self, *_: object) -> None:
|
|
@@ -172,13 +177,20 @@ class ToolProxyEnvironment:
|
|
|
172
177
|
def proxy_main(name: str | None = None) -> None:
|
|
173
178
|
"""Run the proxied command and emit only its bounded invocation-local view."""
|
|
174
179
|
name = name or Path(sys.argv[0]).name
|
|
180
|
+
if os.environ.get("ENGINEERING_PLATFORM_DENY_DELIVERY_MUTATIONS") == "1" and _is_delivery_mutation(name, sys.argv[1:]):
|
|
181
|
+
sys.stderr.write("Read-only assessment tool policy refused a delivery mutation.\n")
|
|
182
|
+
raise SystemExit(126)
|
|
175
183
|
original_path = os.environ.get("ENGINEERING_PLATFORM_EVIDENCE_ORIGINAL_PATH", os.defpath)
|
|
176
184
|
executable = shutil.which(name, path=original_path)
|
|
177
185
|
if executable is None:
|
|
178
186
|
raise SystemExit(f"Evidence proxy could not resolve {name}.")
|
|
179
187
|
completed = subprocess.run( # nosec B603
|
|
180
188
|
(executable, *sys.argv[1:]), text=True, capture_output=True,
|
|
181
|
-
|
|
189
|
+
# Retain the interposer for descendants. Restoring only the original
|
|
190
|
+
# PATH let a proxied interpreter launch an unmediated `gh` child.
|
|
191
|
+
# The original path remains separately available for this launcher's
|
|
192
|
+
# own executable resolution above, avoiding recursive proxy loops.
|
|
193
|
+
env=os.environ.copy(), check=False,
|
|
182
194
|
)
|
|
183
195
|
raw = f"{completed.stdout}{completed.stderr}"
|
|
184
196
|
if os.environ.get("ENGINEERING_PLATFORM_EVIDENCE_EXPAND") == "1":
|
|
@@ -188,6 +200,27 @@ def proxy_main(name: str | None = None) -> None:
|
|
|
188
200
|
raise SystemExit(completed.returncode)
|
|
189
201
|
|
|
190
202
|
|
|
203
|
+
def _is_delivery_mutation(name: str, arguments: Iterable[str]) -> bool:
|
|
204
|
+
"""Recognize the small Git/GitHub write surface relevant to assessment.
|
|
205
|
+
|
|
206
|
+
This runs inside the PATH interposer, so it remains effective even if a
|
|
207
|
+
caller accidentally grants an owner-authorized lifecycle flag elsewhere.
|
|
208
|
+
It intentionally permits read-only inspection and CI-status observation.
|
|
209
|
+
"""
|
|
210
|
+
args = tuple(arguments)
|
|
211
|
+
if name == "gh":
|
|
212
|
+
if len(args) >= 2 and args[0] == "pr" and args[1] in {"create", "edit", "ready", "merge"}:
|
|
213
|
+
return True
|
|
214
|
+
return bool(args and args[0] == "api" and any(value in {"PATCH", "POST", "PUT", "DELETE"} for value in args))
|
|
215
|
+
if name != "git" or not args:
|
|
216
|
+
return False
|
|
217
|
+
# Git accepts global options before the command (`git -C repo push`).
|
|
218
|
+
index = 0
|
|
219
|
+
while index < len(args) and args[index].startswith("-"):
|
|
220
|
+
index += 2 if args[index] in {"-C", "-c", "--git-dir", "--work-tree", "--namespace"} else 1
|
|
221
|
+
return index < len(args) and args[index] in {"commit", "push", "switch", "checkout", "branch", "merge", "reset", "rebase"}
|
|
222
|
+
|
|
223
|
+
|
|
191
224
|
def context_escalation_main(_: str | None = None) -> None:
|
|
192
225
|
"""Validate and record one bounded historical-context escalation."""
|
|
193
226
|
from .provider_context_scope import ContextEscalationReason, ContextEscalationRequest, HistoryBoundaryKind
|
|
@@ -50,6 +50,27 @@ _UNITTEST_FAILURE = re.compile(r"^(?:FAIL|ERROR): [^(]+ \(([^)]+)\)$", re.MULTIL
|
|
|
50
50
|
_UNITTEST_COUNTS = re.compile(r"FAILED \((?P<details>[^)]*)\)")
|
|
51
51
|
_UNITTEST_COUNT = re.compile(r"\b(?P<name>failures|errors)=(?P<count>\d+)\b")
|
|
52
52
|
_TURN_ABORTED = re.compile(r'"type"\s*:\s*"turn_aborted"[^\n]*"reason"\s*:\s*"interrupted"', re.IGNORECASE)
|
|
53
|
+
_ASSESSMENT_STATES = frozenset({"COMPLETE", "WAITING", "FAILED", "BLOCKED"})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _parse_validation_assessment(raw: object) -> AgentResult:
|
|
57
|
+
"""Validate the small read-only contract before projecting AgentResult.
|
|
58
|
+
|
|
59
|
+
JSON Schema constrains cooperative providers, but terminal lifecycle code
|
|
60
|
+
must fail closed for malformed, old, or adapter-produced output too.
|
|
61
|
+
"""
|
|
62
|
+
if not isinstance(raw, dict) or set(raw) != {"terminal_state", "diagnostic", "pull_request"}:
|
|
63
|
+
raise TypeError("validation assessment fields are invalid")
|
|
64
|
+
state, diagnostic, pull_request = raw["terminal_state"], raw["diagnostic"], raw["pull_request"]
|
|
65
|
+
if not isinstance(state, str) or state not in _ASSESSMENT_STATES:
|
|
66
|
+
raise TypeError("validation assessment terminal state is invalid")
|
|
67
|
+
if not isinstance(diagnostic, str) or len(diagnostic) > 500:
|
|
68
|
+
raise TypeError("validation assessment diagnostic is invalid")
|
|
69
|
+
if pull_request is not None and (
|
|
70
|
+
not isinstance(pull_request, int) or isinstance(pull_request, bool) or pull_request < 1
|
|
71
|
+
):
|
|
72
|
+
raise TypeError("validation assessment pull request is invalid")
|
|
73
|
+
return AgentResult(state, pull_request=pull_request, diagnostic=diagnostic)
|
|
53
74
|
|
|
54
75
|
|
|
55
76
|
def provider_turn_interruption(stdout: str, stderr: str) -> str | None:
|
|
@@ -520,6 +541,7 @@ class CodexCliClient:
|
|
|
520
541
|
self.last_context_escalations = ()
|
|
521
542
|
self.last_execution_seconds = None
|
|
522
543
|
self.last_runtime_metadata = self._runtime_metadata()
|
|
544
|
+
assessment_contract = getattr(self, "_validation_contract", False)
|
|
523
545
|
schema = {
|
|
524
546
|
"type": "object",
|
|
525
547
|
"additionalProperties": False,
|
|
@@ -572,6 +594,19 @@ class CodexCliClient:
|
|
|
572
594
|
},
|
|
573
595
|
},
|
|
574
596
|
}
|
|
597
|
+
if assessment_contract:
|
|
598
|
+
# A local-validation turn is an assessment of host receipts, not
|
|
599
|
+
# a delivery turn. Keep the legacy PR echo only as a bounded
|
|
600
|
+
# compatibility signal; lifecycle fields are projected by EP.
|
|
601
|
+
schema = {
|
|
602
|
+
"type": "object", "additionalProperties": False,
|
|
603
|
+
"required": ["terminal_state", "diagnostic", "pull_request"],
|
|
604
|
+
"properties": {
|
|
605
|
+
"terminal_state": {"type": "string", "enum": ["COMPLETE", "WAITING", "FAILED", "BLOCKED"]},
|
|
606
|
+
"diagnostic": {"type": "string", "maxLength": 500},
|
|
607
|
+
"pull_request": {"type": ["integer", "null"]},
|
|
608
|
+
},
|
|
609
|
+
}
|
|
575
610
|
with tempfile.NamedTemporaryFile(
|
|
576
611
|
"w", encoding="utf-8", suffix=".json", delete=False
|
|
577
612
|
) as handle:
|
|
@@ -588,11 +623,19 @@ class CodexCliClient:
|
|
|
588
623
|
str(root),
|
|
589
624
|
"--json",
|
|
590
625
|
]
|
|
626
|
+
if assessment_contract:
|
|
627
|
+
# These supported CLI switches keep account authentication
|
|
628
|
+
# while excluding user-configured MCP/app/tool surfaces and
|
|
629
|
+
# user- or project-scoped execpolicy rules from this
|
|
630
|
+
# receipt-only role. In particular, an inherited allow rule
|
|
631
|
+
# must not move an assessment command outside the read-only
|
|
632
|
+
# sandbox selected by the host.
|
|
633
|
+
command.extend(("--ignore-user-config", "--ignore-rules", "--ephemeral"))
|
|
591
634
|
for extra_root in extra_roots:
|
|
592
635
|
command.extend(("--add-dir", str(extra_root)))
|
|
593
636
|
command.extend(("--output-schema", str(schema_path), prompt))
|
|
594
637
|
started = time.monotonic()
|
|
595
|
-
proxy = ToolProxyEnvironment()
|
|
638
|
+
proxy = ToolProxyEnvironment(deny_delivery_mutations=assessment_contract)
|
|
596
639
|
with proxy as environment:
|
|
597
640
|
completed = self._run_invocation(tuple(command), root, environment)
|
|
598
641
|
self.last_context_escalations = proxy.context_escalations()
|
|
@@ -623,7 +666,10 @@ class CodexCliClient:
|
|
|
623
666
|
)
|
|
624
667
|
try:
|
|
625
668
|
raw = json.loads(_codex_final_message(completed.stdout))
|
|
626
|
-
|
|
669
|
+
if assessment_contract:
|
|
670
|
+
result = _parse_validation_assessment(raw)
|
|
671
|
+
else:
|
|
672
|
+
result = AgentResult(**raw)
|
|
627
673
|
if not isinstance(result.validation_evidence, (list, tuple)) or not isinstance(result.quality_evidence, (list, tuple)):
|
|
628
674
|
raise TypeError("execution evidence must be a list")
|
|
629
675
|
if result.validation_disposition not in {"product_failure", "environmental_instability"}:
|
|
@@ -649,7 +695,7 @@ class CodexCliClient:
|
|
|
649
695
|
if result.diagnostic is not None:
|
|
650
696
|
result = replace(result, diagnostic=redact_diagnostic(result.diagnostic))
|
|
651
697
|
return result
|
|
652
|
-
except (IndexError, json.JSONDecodeError, TypeError) as error:
|
|
698
|
+
except (IndexError, KeyError, json.JSONDecodeError, TypeError) as error:
|
|
653
699
|
interruption = provider_turn_interruption(completed.stdout, completed.stderr)
|
|
654
700
|
raise CodexInvocationError(
|
|
655
701
|
"Provider turn interrupted before returning the required structured terminal result."
|
|
@@ -671,10 +717,12 @@ class CodexCliClient:
|
|
|
671
717
|
if hasattr(self, "_sandbox_override"):
|
|
672
718
|
raise RunnerError("nested validation sandbox override is invalid")
|
|
673
719
|
self._sandbox_override = "read-only"
|
|
720
|
+
self._validation_contract = True
|
|
674
721
|
try:
|
|
675
722
|
return self.invoke(root, prompt)
|
|
676
723
|
finally:
|
|
677
724
|
del self._sandbox_override
|
|
725
|
+
del self._validation_contract
|
|
678
726
|
|
|
679
727
|
def _run_invocation(
|
|
680
728
|
self, command: tuple[str, ...], root: Path, environment: Mapping[str, str] | None = None
|