engineering-platform 2.3.70__tar.gz → 2.3.71__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.70 → engineering_platform-2.3.71}/PKG-INFO +1 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/pyproject.toml +2 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +5 -5
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/contracts/projection.py +7 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_finalization.py +4 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_host.py +136 -46
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_lifecycle.py +3 -2
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_reporting.py +4 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_repository.py +13 -3
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/managed_autonomy.py +21 -4
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/platform_version.py +1 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/qualification_runtime.py +71 -17
- engineering_platform-2.3.71/src/engineering_platform/reconciliation_adoption.py +186 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/server.py +21 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/storage.py +54 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/templates/workspace-config.json +1 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform.egg-info/PKG-INFO +1 -1
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform.egg-info/SOURCES.txt +1 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform.egg-info/entry_points.txt +1 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/README.md +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/setup.cfg +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/__init__.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/__main__.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/agent_state.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/agent_trust.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/dashboard.css +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/dashboard.js +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/dashboard_locales.mjs +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/capability_preflight.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/capability_review.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/central_data_transfer.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/central_database.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/central_store_migration.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/codex_capacity.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/codex_chat.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/codex_observability.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/component_lock.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/component_logging.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/console_presentation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/console_route_ownership.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/contracts/__init__.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/contracts/ep_consumer.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/contracts/models.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/dashboard_browser_validation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/dashboard_state.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/dashboard_supervisor.swift +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/dashboard_translation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/dependabot_producer.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/development_profile.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/drift_diagnostics.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/emergency_recovery.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/engineering_memory.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/ep_consumer_credentials.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/evidence_projection.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_activity.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_context.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_errors.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_evidence.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_executor.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_host_evidence.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_lease.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_models.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_readiness.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_timeout_policy.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_timing.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/execution_transaction.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/external_producer_binding.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/file_inbox.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/forensic_attribution.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/forensic_attribution_v2.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/forensic_delta.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/golden_scenario.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/host_admin.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/host_preflight.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_relocation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_activation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_admission.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_backup.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_composition.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_executor.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_migration.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_operation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_plan.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/installation_update_preparation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/investigation_ledger.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/legacy_inbox_migration.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/legacy_installation_adoption.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/lifecycle_worker.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/live_status.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/local_api.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/local_api_keychain.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/local_repository_binding.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/managed_codex_runtime.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/operational_installation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/operational_installation_lock.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/operational_installation_record.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/owner_credential_recovery.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/parity_context.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/platform_admin.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/platform_api.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/platform_bootstrap.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/platform_components.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/pr_check_repair.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/pr_evidence_backfill.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/producer.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/product_installation_readback.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/project_agent.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/project_agent_service.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/project_topology.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/prompt_history.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_context.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_context_benchmark.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_context_scope.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_interruption.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_process_identity.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_readiness.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_recovery.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/provider_usage.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/providers.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/qualification.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/recommendation_handoff.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/release_operation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/report_analysis.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/repository_attachment.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/repository_handoff.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/resources.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/reviewer_evidence.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/revision_binding.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/server_console_services.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/server_relay.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/server_service.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/status_model.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/status_reconciliation.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/submission_cli.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/submission_intake.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/submission_service.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/system_installation_topology.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/system_server_service.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/telemetry.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/validation_identity.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/validation_profile.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/version_preparation_delivery.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/workspace_preflight.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/worktree_provenance.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform/worktree_tooling.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/src/engineering_platform.egg-info/top_level.txt +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/tests/test_adaptive_action_sizing_design.py +0 -0
- {engineering_platform-2.3.70 → engineering_platform-2.3.71}/tests/test_role_task_model_policy_design.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "engineering-platform"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.71"
|
|
8
8
|
description = "Local-first Engineering Platform execution operations runtime"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.14,<3.15"
|
|
@@ -18,6 +18,7 @@ engineering-platform-host = "engineering_platform.__main__:main"
|
|
|
18
18
|
engineering-platform-server = "engineering_platform.server:main"
|
|
19
19
|
engineering-platform = "engineering_platform.submission_cli:main"
|
|
20
20
|
engineering-project-agent = "engineering_platform.project_agent:main"
|
|
21
|
+
engineering-reconciliation-adopt = "engineering_platform.reconciliation_adoption:main"
|
|
21
22
|
|
|
22
23
|
[tool.setuptools]
|
|
23
24
|
package-dir = {"" = "src"}
|
|
@@ -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.71",
|
|
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.71",
|
|
10
10
|
"report_format": 2,
|
|
11
|
-
"runner_version": "2.3.
|
|
11
|
+
"runner_version": "2.3.71",
|
|
12
12
|
"status_model": 1,
|
|
13
|
-
"storage_schema":
|
|
14
|
-
"watcher_version": "2.3.
|
|
13
|
+
"storage_schema": 45,
|
|
14
|
+
"watcher_version": "2.3.71"
|
|
15
15
|
}
|
|
@@ -306,6 +306,7 @@ def get_run_context(root: Path, run_id: str) -> dict[str, object]:
|
|
|
306
306
|
snapshot_checks = qualification_source.get("pr_checks", {}) if qualification_source else {}
|
|
307
307
|
implementation = snapshot_checks.get("IMPLEMENTATION", {}) if qualification_source and isinstance(snapshot_checks, dict) else checks.get("IMPLEMENTATION", {})
|
|
308
308
|
finalization = snapshot_checks.get("FINALIZATION", {}) if qualification_source and isinstance(snapshot_checks, dict) else checks.get("FINALIZATION", {})
|
|
309
|
+
reconciliation = snapshot_checks.get("RECONCILIATION", {}) if qualification_source and isinstance(snapshot_checks, dict) else checks.get("RECONCILIATION", {})
|
|
309
310
|
objective = _safe_objective(submission[3] if submission else {})
|
|
310
311
|
validation_only = action_intent == "VALIDATION_ONLY"
|
|
311
312
|
persisted_required_validation = qualification_source.get("validation_profile", UNAVAILABLE) if qualification_source else qualification_validation or UNAVAILABLE
|
|
@@ -337,8 +338,14 @@ def get_run_context(root: Path, run_id: str) -> dict[str, object]:
|
|
|
337
338
|
"finalization_pr": "NOT_REQUIRED" if validation_only else _value(qualification_source.get("finalization_pr") if qualification_source else checkpoint.get("finalization_pull_request") or finalization.get("pr_number")), "finalization_pr_current_state": "NOT_REQUIRED" if validation_only else _value(finalization.get("pr_state")),
|
|
338
339
|
"finalization_merge_state": _value(finalization.get("merge_state")), "finalization_merge_commit": _value(finalization.get("merge_commit") if qualification_source else checkpoint.get("finalization_merge_commit") or finalization.get("merge_commit")),
|
|
339
340
|
"finalization_required_checks_state": _value(finalization.get("required_checks_state")), "finalization_merge_gate": "EXPECTED_OPERATOR_GATE" if phase == "WAIT_FOR_FINALIZATION_MERGE" else UNAVAILABLE,
|
|
341
|
+
"reconciliation_pr": "NOT_REQUIRED" if validation_only else _value(qualification_source.get("reconciliation_pr") if qualification_source else checkpoint.get("reconciliation_pull_request") or reconciliation.get("pr_number")),
|
|
342
|
+
"reconciliation_pr_current_state": "NOT_REQUIRED" if validation_only else _value(reconciliation.get("pr_state")),
|
|
343
|
+
"reconciliation_merge_state": _value(reconciliation.get("merge_state")),
|
|
344
|
+
"reconciliation_required_checks_state": _value(reconciliation.get("required_checks_state")),
|
|
345
|
+
"reconciliation_merge_gate": "EXPECTED_OPERATOR_GATE" if phase == "WAIT_FOR_RECONCILIATION_MERGE" else UNAVAILABLE,
|
|
340
346
|
"implementation_delivery": _value(qualification_source.get("implementation_delivery")),
|
|
341
347
|
"finalization_delivery": _value(qualification_source.get("finalization_delivery")),
|
|
348
|
+
"reconciliation_delivery": _value(qualification_source.get("reconciliation_delivery")),
|
|
342
349
|
"run_delivery_commit": _value(checkpoint.get("implementation_head_sha") or checkpoint.get("last_verified_sha")), "current_repository_head": _value(checkpoint.get("last_verified_sha")), "delivery_commit_head_relationship": UNAVAILABLE},
|
|
343
350
|
"validation": {"engineering_platform_qualification": UNAVAILABLE, "controls": validation_controls,
|
|
344
351
|
"required_validation": persisted_required_validation,
|
|
@@ -33,7 +33,10 @@ class FinalizationCoordinator:
|
|
|
33
33
|
if not callable(operation):
|
|
34
34
|
return save_terminal(cleanup, "BLOCKED", "cleanup_unavailable", "Cleanup client is unavailable; resume with repository cleanup evidence.")
|
|
35
35
|
try:
|
|
36
|
-
|
|
36
|
+
branches = (cleanup.implementation_branch, cleanup.finalization_branch)
|
|
37
|
+
if cleanup.transaction_kind == "RECONCILIATION":
|
|
38
|
+
branches += (cleanup.branch,)
|
|
39
|
+
result = operation(root, branches)
|
|
37
40
|
except RunnerError as error:
|
|
38
41
|
return save_terminal(cleanup, "BLOCKED", "repository_cleanup_required", str(error))
|
|
39
42
|
return save_terminal(
|
|
@@ -82,7 +82,7 @@ from .reviewer_evidence import ReviewerEvidence
|
|
|
82
82
|
from .investigation_ledger import InvocationInvestigationLedger
|
|
83
83
|
from .execution_errors import CodexHandoffTimeout, CodexInvocationError, RunnerError
|
|
84
84
|
from .execution_errors import ProviderReadinessBlocked
|
|
85
|
-
from .execution_timeout_policy import FINALIZATION, REPAIR, agent_timeout
|
|
85
|
+
from .execution_timeout_policy import END_RECONCILIATION, FINALIZATION, REPAIR, agent_timeout
|
|
86
86
|
from .provider_readiness import failures as provider_readiness_failures
|
|
87
87
|
from .execution_repository import GitHubClient as ProviderGitHubClient, RepositoryClient as ProviderRepositoryClient
|
|
88
88
|
from .execution_repository import GhCliClient as ProviderGhCliClient, SubprocessRepositoryClient as ProviderRepositoryClientImpl
|
|
@@ -125,6 +125,7 @@ from .component_logging import component_logger, record_technical_diagnostic, sh
|
|
|
125
125
|
|
|
126
126
|
# Compatibility exports for integrations that already import these names.
|
|
127
127
|
FINALIZATION_PR_HANDOFF_MAX_SECONDS = FINALIZATION.seconds
|
|
128
|
+
RECONCILIATION_PR_HANDOFF_MAX_SECONDS = END_RECONCILIATION.seconds
|
|
128
129
|
REPAIR_AGENT_MAX_SECONDS = REPAIR.seconds
|
|
129
130
|
|
|
130
131
|
# A repair remains scoped to its original PR, but it must also have a finite
|
|
@@ -305,11 +306,12 @@ def assemble_prompt(
|
|
|
305
306
|
)
|
|
306
307
|
authority = (
|
|
307
308
|
"""This is the sole automatic post-Finalization reconciliation. You may only update
|
|
308
|
-
the four canonical rolling records
|
|
309
|
-
|
|
310
|
-
authority, lifecycle, retry, validation, provider, Forge, queue, or delivery semantics.
|
|
311
|
-
|
|
312
|
-
|
|
309
|
+
the four canonical rolling records on the exact checkpointed reconciliation branch, commit and
|
|
310
|
+
push that branch, and create one draft pull request to `main`. Do not change runtime code,
|
|
311
|
+
authority, lifecycle, retry, validation, provider, Forge, queue, or delivery semantics. Do not
|
|
312
|
+
merge the pull request or push directly to `main`. Return `COMPLETE`, `repository_reconciled`,
|
|
313
|
+
the branch, pull-request number, and exact candidate commit SHA only after verifying a clean
|
|
314
|
+
workspace."""
|
|
313
315
|
if state and state.transaction_kind == "RECONCILIATION"
|
|
314
316
|
else
|
|
315
317
|
"""The runner holds explicit owner authorization for this exact bounded transaction. You may create, commit and push one bounded branch and draft pull request, or repair that same pull request. The runner may mark that pull request ready for review, but only the human operator may merge it. Do not merge, release, deploy, tag, publish, upload, change repository settings, bypass protection, or expand the objective."""
|
|
@@ -1090,7 +1092,7 @@ class EngineeringRunner:
|
|
|
1090
1092
|
def _managed_pr_check(self, state: TransactionState, pr: PullRequestEvidence) -> None:
|
|
1091
1093
|
"""Persist current GitHub required-check evidence separately from historical waits."""
|
|
1092
1094
|
role = state.transaction_kind
|
|
1093
|
-
if role not in {"IMPLEMENTATION", "FINALIZATION"}:
|
|
1095
|
+
if role not in {"IMPLEMENTATION", "FINALIZATION", "RECONCILIATION"}:
|
|
1094
1096
|
return
|
|
1095
1097
|
check_state = "PASS" if pr.checks_terminal and pr.checks_passed else "FAIL" if pr.checks_terminal else "WAITING"
|
|
1096
1098
|
try:
|
|
@@ -2731,6 +2733,8 @@ First implementation pull-request publication gate:
|
|
|
2731
2733
|
return self._advance_after_repair_agent_result(state, result)
|
|
2732
2734
|
if lifecycle_phase == "FINALIZE_AGENT":
|
|
2733
2735
|
return self._advance_after_finalization_agent_result(state, result)
|
|
2736
|
+
if lifecycle_phase == "RECONCILE_AGENT":
|
|
2737
|
+
return self._advance_after_reconciliation_agent_result(state, result)
|
|
2734
2738
|
return self._save_terminal(state, "BLOCKED", "recovered_provider_phase_invalid", "Recovered provider result has an unsupported lifecycle phase.")
|
|
2735
2739
|
|
|
2736
2740
|
def run(
|
|
@@ -2898,7 +2902,7 @@ First implementation pull-request publication gate:
|
|
|
2898
2902
|
recovered_resume = (
|
|
2899
2903
|
isinstance(recovery_snapshot, dict)
|
|
2900
2904
|
and recovery_snapshot.get("state") == "RECOVERED"
|
|
2901
|
-
and recovery_snapshot.get("lifecycle_phase") in {"EXECUTE_AGENT", "QUALITY_CONTROL_AGENT", "REPAIR_AGENT", "FINALIZE_AGENT"}
|
|
2905
|
+
and recovery_snapshot.get("lifecycle_phase") in {"EXECUTE_AGENT", "QUALITY_CONTROL_AGENT", "REPAIR_AGENT", "FINALIZE_AGENT", "RECONCILE_AGENT"}
|
|
2902
2906
|
)
|
|
2903
2907
|
try:
|
|
2904
2908
|
persisted_submission = load_submission_for_run(self.root, state.run_id, central_database=self.store.central_database)
|
|
@@ -3281,6 +3285,8 @@ First implementation pull-request publication gate:
|
|
|
3281
3285
|
state = self._record_agent_execution_time(state)
|
|
3282
3286
|
self.console_detail = error.console_detail
|
|
3283
3287
|
return self._terminalize_provider_invocation_error(state, error)
|
|
3288
|
+
if state.transaction_kind == "RECONCILIATION":
|
|
3289
|
+
return self._advance_after_reconciliation_agent_result(state, result)
|
|
3284
3290
|
return self._advance_after_primary_agent_result(state, result, evidence)
|
|
3285
3291
|
|
|
3286
3292
|
def _active_genesis_transaction(self, target: Path, run_id: str) -> str | None:
|
|
@@ -3397,10 +3403,7 @@ First implementation pull-request publication gate:
|
|
|
3397
3403
|
next_action="create_finalization",
|
|
3398
3404
|
)
|
|
3399
3405
|
if state.transaction_kind == "RECONCILIATION" and not state.reconciliation_pull_request:
|
|
3400
|
-
return
|
|
3401
|
-
state, phase="RECONCILE_AGENT", last_verified_sha=evidence.head_sha,
|
|
3402
|
-
next_action="create_reconciliation",
|
|
3403
|
-
)
|
|
3406
|
+
return self._recover_reconciliation_pull_request(state, evidence)
|
|
3404
3407
|
if (
|
|
3405
3408
|
state.transaction_kind == "FINALIZATION"
|
|
3406
3409
|
and state.finalization_merge_commit
|
|
@@ -3478,6 +3481,54 @@ First implementation pull-request publication gate:
|
|
|
3478
3481
|
write_live_status(self.root, recovered, recovered.next_action)
|
|
3479
3482
|
return self._poll(recovered)
|
|
3480
3483
|
|
|
3484
|
+
def _recover_reconciliation_pull_request(
|
|
3485
|
+
self, state: TransactionState, evidence: RepositoryEvidence,
|
|
3486
|
+
) -> TransactionState:
|
|
3487
|
+
"""Recover only the PR bound to the durable reconciliation branch."""
|
|
3488
|
+
if state.reconciliation_pull_request:
|
|
3489
|
+
return replace(
|
|
3490
|
+
state, pull_request=state.reconciliation_pull_request,
|
|
3491
|
+
phase="WAIT_FOR_TERMINAL_EVIDENCE", next_action="poll_required_checks",
|
|
3492
|
+
)
|
|
3493
|
+
if (
|
|
3494
|
+
not state.branch
|
|
3495
|
+
or state.branch == "main"
|
|
3496
|
+
or not state.finalization_merge_commit
|
|
3497
|
+
or evidence.branch not in {"main", state.branch}
|
|
3498
|
+
or not evidence.clean
|
|
3499
|
+
or not self.repository.main_contains(self.root, state.finalization_merge_commit)
|
|
3500
|
+
):
|
|
3501
|
+
return self._save_terminal(
|
|
3502
|
+
state, "BLOCKED", "reconciliation_recovery_evidence_required",
|
|
3503
|
+
"Reconciliation recovery requires its checkpointed branch and a verified Finalization merge.",
|
|
3504
|
+
)
|
|
3505
|
+
candidate = self.github.pull_request_for_head_branch(state.branch)
|
|
3506
|
+
if candidate is None:
|
|
3507
|
+
return self._save_terminal(
|
|
3508
|
+
state, "BLOCKED", "reconciliation_recovery_evidence_required",
|
|
3509
|
+
"No reconciliation pull request matches the checkpointed branch; no replacement was created.",
|
|
3510
|
+
)
|
|
3511
|
+
if (
|
|
3512
|
+
candidate.head_branch != state.branch
|
|
3513
|
+
or candidate.base_branch != "main"
|
|
3514
|
+
or candidate.state not in {"OPEN", "MERGED"}
|
|
3515
|
+
):
|
|
3516
|
+
return self._save_terminal(
|
|
3517
|
+
state, "BLOCKED", "reconciliation_recovery_evidence_invalid",
|
|
3518
|
+
"Reconciliation pull request evidence does not match the checkpointed branch and main base.",
|
|
3519
|
+
)
|
|
3520
|
+
recovered = replace(
|
|
3521
|
+
state, pull_request=candidate.number,
|
|
3522
|
+
reconciliation_pull_request=candidate.number,
|
|
3523
|
+
phase="WAIT_FOR_TERMINAL_EVIDENCE", next_action="poll_required_checks",
|
|
3524
|
+
last_verified_sha=evidence.head_sha,
|
|
3525
|
+
latest_repository_evidence=_repository_summary(evidence),
|
|
3526
|
+
latest_github_evidence=_pull_request_summary(candidate),
|
|
3527
|
+
)
|
|
3528
|
+
self.store.save(recovered)
|
|
3529
|
+
write_live_status(self.root, recovered, recovered.next_action)
|
|
3530
|
+
return self._poll(recovered)
|
|
3531
|
+
|
|
3481
3532
|
def _poll(self, state: TransactionState, result: AgentResult | None = None) -> TransactionState:
|
|
3482
3533
|
if state.pull_request:
|
|
3483
3534
|
state = self._provider_readiness_gate(
|
|
@@ -3497,32 +3548,10 @@ First implementation pull-request publication gate:
|
|
|
3497
3548
|
"Agent result referenced a pull request without a transaction branch; the current main branch cannot be reused as execution evidence.",
|
|
3498
3549
|
)
|
|
3499
3550
|
if not state.pull_request:
|
|
3500
|
-
if state.transaction_kind == "RECONCILIATION" and result
|
|
3551
|
+
if state.transaction_kind == "RECONCILIATION" and result:
|
|
3501
3552
|
return self._save_terminal(
|
|
3502
|
-
state, "BLOCKED", "
|
|
3503
|
-
"Automatic reconciliation
|
|
3504
|
-
)
|
|
3505
|
-
if state.transaction_kind == "RECONCILIATION" and result and result.terminal_state == "COMPLETE":
|
|
3506
|
-
evidence = self.repository.inspect(self.root)
|
|
3507
|
-
if (
|
|
3508
|
-
result.terminal_condition == "repository_reconciled"
|
|
3509
|
-
and result.commit_sha
|
|
3510
|
-
and evidence.clean
|
|
3511
|
-
and evidence.branch == "main"
|
|
3512
|
-
and evidence.head_sha == result.commit_sha
|
|
3513
|
-
and evidence.main_contains_head
|
|
3514
|
-
):
|
|
3515
|
-
reconciled = replace(state, last_verified_sha=result.commit_sha)
|
|
3516
|
-
reconciled = self._append_verified_commit_evidence(
|
|
3517
|
-
reconciled,
|
|
3518
|
-
phase="RECONCILE_AGENT",
|
|
3519
|
-
commit_sha=result.commit_sha,
|
|
3520
|
-
description="end_reconciliation_commit_verified",
|
|
3521
|
-
)
|
|
3522
|
-
return self._cleanup(reconciled)
|
|
3523
|
-
return self._save_terminal(
|
|
3524
|
-
state, "BLOCKED", "automatic_reconciliation_evidence_required",
|
|
3525
|
-
"Automatic reconciliation requires a clean main checkout containing its reported commit.",
|
|
3553
|
+
state, "BLOCKED", "reconciliation_pr_required",
|
|
3554
|
+
"Automatic reconciliation requires its checkpointed pull request before cleanup.",
|
|
3526
3555
|
)
|
|
3527
3556
|
if result and result.terminal_state == "COMPLETE":
|
|
3528
3557
|
evidence = self.repository.inspect(self.root)
|
|
@@ -3885,12 +3914,7 @@ First implementation pull-request publication gate:
|
|
|
3885
3914
|
return self._poll(finalization, result)
|
|
3886
3915
|
|
|
3887
3916
|
def _start_automatic_reconciliation(self, state: TransactionState) -> TransactionState:
|
|
3888
|
-
"""Apply the bounded rolling-record update
|
|
3889
|
-
|
|
3890
|
-
This is deliberately a direct, post-merge `main` commit: it has no PR,
|
|
3891
|
-
review, approval, or operator merge boundary. Its scope is enforced by
|
|
3892
|
-
the supplied reconciliation prompt and the exact commit evidence below.
|
|
3893
|
-
"""
|
|
3917
|
+
"""Apply the bounded rolling-record update through a protected PR."""
|
|
3894
3918
|
synchronize = getattr(self.repository, "synchronize_main", None)
|
|
3895
3919
|
if callable(synchronize):
|
|
3896
3920
|
synchronize(self.root)
|
|
@@ -3900,22 +3924,37 @@ First implementation pull-request publication gate:
|
|
|
3900
3924
|
state,
|
|
3901
3925
|
"End reconciliation is waiting for a clean, synchronized main checkout.",
|
|
3902
3926
|
)
|
|
3927
|
+
expected_branch = (
|
|
3928
|
+
state.branch
|
|
3929
|
+
if state.transaction_kind == "RECONCILIATION" and state.branch != "main"
|
|
3930
|
+
else None
|
|
3931
|
+
) or f"codex/reconcile-{state.run_id}"
|
|
3903
3932
|
reconciliation = replace(
|
|
3904
3933
|
state, phase="RECONCILE_AGENT", transaction_kind="RECONCILIATION",
|
|
3905
|
-
branch=
|
|
3906
|
-
next_action="
|
|
3934
|
+
branch=expected_branch, pull_request=None, reconciliation_pull_request=None,
|
|
3935
|
+
next_action="create_reconciliation_pull_request", waiting_for_merge_since=None,
|
|
3907
3936
|
latest_repository_evidence=_repository_summary(evidence),
|
|
3908
3937
|
)
|
|
3909
3938
|
self._managed_action(reconciliation, "AUTOMATIC_RECONCILIATION")
|
|
3910
3939
|
self.store.save(reconciliation)
|
|
3911
3940
|
write_live_status(self.root, reconciliation, reconciliation.next_action)
|
|
3941
|
+
reconciliation_span = self._start_phase(state.run_id, "RECONCILIATION")
|
|
3942
|
+
handoff_started = time.monotonic()
|
|
3943
|
+
set_handoff_deadline = getattr(self.agent, "set_handoff_deadline_callback", None)
|
|
3944
|
+
if callable(set_handoff_deadline):
|
|
3945
|
+
set_handoff_deadline(
|
|
3946
|
+
lambda: time.monotonic() - handoff_started
|
|
3947
|
+
>= RECONCILIATION_PR_HANDOFF_MAX_SECONDS
|
|
3948
|
+
)
|
|
3912
3949
|
try:
|
|
3913
3950
|
result = self._invoke_agent_with_timing(
|
|
3914
3951
|
reconciliation,
|
|
3915
3952
|
assemble_prompt(
|
|
3916
3953
|
Path(reconciliation.prompt_path), reconciliation,
|
|
3917
3954
|
managed_target=self.root if reconciliation.execution_mode == "MANAGED" else None,
|
|
3918
|
-
)
|
|
3955
|
+
)
|
|
3956
|
+
+ "\n\nReconcile only the four canonical rolling current-state records after the verified Finalization merge. "
|
|
3957
|
+
f"Preserve immutable Prompt History and create one draft pull request on exactly `{expected_branch}`.",
|
|
3919
3958
|
)
|
|
3920
3959
|
reconciliation = self._record_agent_execution_time(reconciliation)
|
|
3921
3960
|
reconciliation = self._record_validation_evidence(reconciliation, result)
|
|
@@ -3926,12 +3965,63 @@ First implementation pull-request publication gate:
|
|
|
3926
3965
|
description="end_reconciliation_commit_verified",
|
|
3927
3966
|
)
|
|
3928
3967
|
self._persist_agent_usage(reconciliation.run_id)
|
|
3968
|
+
except CodexHandoffTimeout:
|
|
3969
|
+
complete_phase(self.root, reconciliation_span, outcome="FAILED")
|
|
3970
|
+
reconciliation = self._record_agent_execution_time(reconciliation)
|
|
3971
|
+
return self._recover_reconciliation_pull_request(
|
|
3972
|
+
reconciliation, self.repository.inspect(self.root)
|
|
3973
|
+
)
|
|
3929
3974
|
except ProviderReadinessBlocked as blocked:
|
|
3975
|
+
complete_phase(self.root, reconciliation_span, outcome="BLOCKED")
|
|
3930
3976
|
return blocked.state
|
|
3931
3977
|
except CodexInvocationError as error:
|
|
3978
|
+
complete_phase(
|
|
3979
|
+
self.root, reconciliation_span,
|
|
3980
|
+
outcome="INTERRUPTED" if error.provider_turn_interrupted else "FAILED",
|
|
3981
|
+
)
|
|
3932
3982
|
reconciliation = self._record_agent_execution_time(reconciliation)
|
|
3933
3983
|
self.console_detail = error.console_detail
|
|
3934
3984
|
return self._terminalize_provider_invocation_error(reconciliation, error)
|
|
3985
|
+
finally:
|
|
3986
|
+
if callable(set_handoff_deadline):
|
|
3987
|
+
set_handoff_deadline(None)
|
|
3988
|
+
complete_phase(self.root, reconciliation_span)
|
|
3989
|
+
return self._advance_after_reconciliation_agent_result(reconciliation, result)
|
|
3990
|
+
|
|
3991
|
+
def _advance_after_reconciliation_agent_result(
|
|
3992
|
+
self, reconciliation: TransactionState, result: AgentResult,
|
|
3993
|
+
) -> TransactionState:
|
|
3994
|
+
"""Bind a live or recovered reconciliation result to its one PR."""
|
|
3995
|
+
if result.terminal_state in {"BLOCKED", "FAILED"} or not result.pull_request:
|
|
3996
|
+
return self._save_terminal(
|
|
3997
|
+
reconciliation,
|
|
3998
|
+
result.terminal_state
|
|
3999
|
+
if result.terminal_state in {"BLOCKED", "FAILED"}
|
|
4000
|
+
else "BLOCKED",
|
|
4001
|
+
"reconciliation_pr_required",
|
|
4002
|
+
result.diagnostic or "Reconciliation pull request was not created.",
|
|
4003
|
+
)
|
|
4004
|
+
expected_branch = reconciliation.branch
|
|
4005
|
+
if not expected_branch or expected_branch == "main" or result.branch != expected_branch:
|
|
4006
|
+
return self._save_terminal(
|
|
4007
|
+
reconciliation, "BLOCKED", "reconciliation_branch_mismatch",
|
|
4008
|
+
"Reconciliation returned a pull request outside the durable reconciliation branch.",
|
|
4009
|
+
)
|
|
4010
|
+
reconciliation = replace(
|
|
4011
|
+
reconciliation,
|
|
4012
|
+
phase="WAIT_FOR_TERMINAL_EVIDENCE",
|
|
4013
|
+
pull_request=result.pull_request,
|
|
4014
|
+
reconciliation_pull_request=result.pull_request,
|
|
4015
|
+
terminal_condition="repository_reconciled",
|
|
4016
|
+
next_action="poll_required_checks",
|
|
4017
|
+
)
|
|
4018
|
+
self.store.save(reconciliation)
|
|
4019
|
+
write_live_status(self.root, reconciliation, reconciliation.next_action)
|
|
4020
|
+
evidence = self.github.pull_request(result.pull_request)
|
|
4021
|
+
if evidence.state == "MERGED":
|
|
4022
|
+
return self._poll(reconciliation, result)
|
|
4023
|
+
self.github.normalize_markdown_body(result.pull_request)
|
|
4024
|
+
self.github.ready(result.pull_request)
|
|
3935
4025
|
return self._poll(reconciliation, result)
|
|
3936
4026
|
|
|
3937
4027
|
def _save_terminal(
|
|
@@ -19,12 +19,12 @@ TERMINAL = frozenset({"COMPLETE", "BLOCKED", "FAILED"})
|
|
|
19
19
|
_MANAGED_PATH = (
|
|
20
20
|
"START", "INITIALIZE", "CAPABILITY_REVIEW", "EXECUTE_AGENT", "LOCAL_REPOSITORY_VALIDATION", "QUALITY_CONTROL_AGENT", "REPAIR_AGENT",
|
|
21
21
|
"WAIT_FOR_OPERATOR_MERGE", "FINALIZE_AGENT", "WAIT_FOR_FINALIZATION_MERGE",
|
|
22
|
-
"RECONCILE_AGENT", "REPOSITORY_CLEANUP", "TERMINAL",
|
|
22
|
+
"RECONCILE_AGENT", "WAIT_FOR_RECONCILIATION_MERGE", "REPOSITORY_CLEANUP", "TERMINAL",
|
|
23
23
|
)
|
|
24
24
|
_FINALIZATION_REPAIR_PATH = (
|
|
25
25
|
"START", "INITIALIZE", "CAPABILITY_REVIEW", "EXECUTE_AGENT", "QUALITY_CONTROL_AGENT", "REPAIR_AGENT",
|
|
26
26
|
"WAIT_FOR_OPERATOR_MERGE", "FINALIZE_AGENT", "FINALIZATION_REPAIR_AGENT", "WAIT_FOR_FINALIZATION_MERGE",
|
|
27
|
-
"RECONCILE_AGENT", "REPOSITORY_CLEANUP", "TERMINAL",
|
|
27
|
+
"RECONCILE_AGENT", "WAIT_FOR_RECONCILIATION_MERGE", "REPOSITORY_CLEANUP", "TERMINAL",
|
|
28
28
|
)
|
|
29
29
|
# Genesis has no pull-request merge boundary. This is presentation of the
|
|
30
30
|
# existing mode contract, not a new execution sequence.
|
|
@@ -52,6 +52,7 @@ _STEP_PHASES = {
|
|
|
52
52
|
"WAIT_FOR_OPERATOR_MERGE": frozenset({"PR_OR_MERGE", "EXTERNAL_CI_WAIT"}),
|
|
53
53
|
"FINALIZE_AGENT": frozenset({"REPOSITORY_FINALIZATION", "FINALIZATION"}),
|
|
54
54
|
"RECONCILE_AGENT": frozenset({"RECONCILIATION", "REPORT_GENERATION", "EVIDENCE_PERSISTENCE"}),
|
|
55
|
+
"WAIT_FOR_RECONCILIATION_MERGE": frozenset({"PR_OR_MERGE", "EXTERNAL_CI_WAIT"}),
|
|
55
56
|
"REPOSITORY_CLEANUP": frozenset({"REPOSITORY_CLEANUP"}),
|
|
56
57
|
"TERMINAL": frozenset({"TOTAL_EXECUTION"}),
|
|
57
58
|
}
|
|
@@ -397,6 +397,7 @@ def _commit_strategy(state: TransactionState, bundle: TerminalEvidenceBundle) ->
|
|
|
397
397
|
f"- Implementation merge: `{state.implementation_merge_commit or 'not recorded'}`",
|
|
398
398
|
f"- Finalization PR: `{state.finalization_pull_request or 'not recorded'}`",
|
|
399
399
|
f"- Finalization merge: `{state.finalization_merge_commit or 'not recorded'}`",
|
|
400
|
+
f"- Reconciliation PR: `{state.reconciliation_pull_request or 'not recorded'}`",
|
|
400
401
|
)
|
|
401
402
|
|
|
402
403
|
|
|
@@ -1080,6 +1081,7 @@ def _managed_autonomy_projection(root: Path, state: TransactionState, bundle: Te
|
|
|
1080
1081
|
snapshot = managed_autonomy_snapshot(
|
|
1081
1082
|
root, run_id=state.run_id, execution_outcome=state.phase,
|
|
1082
1083
|
implementation_pr=state.implementation_pull_request, finalization_pr=state.finalization_pull_request,
|
|
1084
|
+
reconciliation_pr=state.reconciliation_pull_request,
|
|
1083
1085
|
repository_state="MERGED_RECONCILED" if state.phase == "COMPLETE" and (state.finalization_merge_commit or state.action_intent == "VALIDATION_ONLY") else "UNAVAILABLE",
|
|
1084
1086
|
workspace_state="WORKSPACE_READY" if state.phase == "COMPLETE" and bundle.worktree_state == "clean" else "UNAVAILABLE",
|
|
1085
1087
|
main_origin_sync="YES" if bundle.target_branch == "main" else "UNAVAILABLE",
|
|
@@ -1503,6 +1505,7 @@ def generate_terminal_report(
|
|
|
1503
1505
|
"## Pull Requests",
|
|
1504
1506
|
f"- Implementation: branch `{state.implementation_branch}`, PR `{state.implementation_pull_request}`, merge `{state.implementation_merge_commit}`",
|
|
1505
1507
|
f"- Finalization: branch `{state.finalization_branch}`, PR `{state.finalization_pull_request}`, merge `{state.finalization_merge_commit}`",
|
|
1508
|
+
f"- Reconciliation: branch `{state.branch if state.transaction_kind == 'RECONCILIATION' else None}`, PR `{state.reconciliation_pull_request}`",
|
|
1506
1509
|
"",
|
|
1507
1510
|
*_retry_relationship(state),
|
|
1508
1511
|
"## Initial Repository Assessment",
|
|
@@ -1600,7 +1603,7 @@ def generate_terminal_report(
|
|
|
1600
1603
|
"## Metrics",
|
|
1601
1604
|
f"- Codex CLI execution time: {state.agent_execution_seconds if state.agent_execution_seconds is not None else 'not measured'} seconds",
|
|
1602
1605
|
f"- Repair iterations: {state.repair_iterations}",
|
|
1603
|
-
f"- PRs created: {sum(value is not None for value in (state.implementation_pull_request, state.finalization_pull_request))}",
|
|
1606
|
+
f"- PRs created: {sum(value is not None for value in (state.implementation_pull_request, state.finalization_pull_request, state.reconciliation_pull_request))}",
|
|
1604
1607
|
f"- Merges performed: {sum(value is not None for value in (state.implementation_merge_commit, state.finalization_merge_commit))}",
|
|
1605
1608
|
"",
|
|
1606
1609
|
)
|
|
@@ -44,7 +44,9 @@ class GitHubClient(Protocol):
|
|
|
44
44
|
def ready(self, number: int) -> None: ...
|
|
45
45
|
def normalize_markdown_body(self, number: int) -> bool: ...
|
|
46
46
|
def merge(self, number: int) -> None: ...
|
|
47
|
-
def create_or_recover_pull_request(
|
|
47
|
+
def create_or_recover_pull_request(
|
|
48
|
+
self, branch: str, base: str, title: str, body: str, *, draft: bool = False,
|
|
49
|
+
) -> PullRequestEvidence: ...
|
|
48
50
|
def qualification_for_exact_head(self, number: int, head_sha: str) -> dict[str, object]: ...
|
|
49
51
|
def version_preparation_writer(self) -> dict[str, object]: ...
|
|
50
52
|
|
|
@@ -250,7 +252,9 @@ class GhCliClient:
|
|
|
250
252
|
raise RunnerError("Finalization recovery found more than one pull request for its checkpointed branch.")
|
|
251
253
|
return self.pull_request(numbers[0])
|
|
252
254
|
|
|
253
|
-
def create_or_recover_pull_request(
|
|
255
|
+
def create_or_recover_pull_request(
|
|
256
|
+
self, branch: str, base: str, title: str, body: str, *, draft: bool = False,
|
|
257
|
+
) -> PullRequestEvidence:
|
|
254
258
|
"""Create one bounded PR or recover the sole existing branch identity."""
|
|
255
259
|
existing = self.pull_request_for_head_branch(branch)
|
|
256
260
|
if existing is not None:
|
|
@@ -258,7 +262,13 @@ class GhCliClient:
|
|
|
258
262
|
raise RunnerError("Version preparation branch already has a pull request for another base.")
|
|
259
263
|
return existing
|
|
260
264
|
try:
|
|
261
|
-
|
|
265
|
+
arguments = [
|
|
266
|
+
"pr", "create", "--head", branch, "--base", base,
|
|
267
|
+
"--title", title, "--body", body,
|
|
268
|
+
]
|
|
269
|
+
if draft:
|
|
270
|
+
arguments.append("--draft")
|
|
271
|
+
raw = self._github(*arguments)
|
|
262
272
|
except RuntimeError as error:
|
|
263
273
|
# A successful create may lose its acknowledgement. Only recover
|
|
264
274
|
# the deterministic branch identity; never create a second PR.
|
|
@@ -30,13 +30,17 @@ AUTHORITIES = frozenset(
|
|
|
30
30
|
"UNKNOWN_AUTHORITY",
|
|
31
31
|
}
|
|
32
32
|
)
|
|
33
|
-
GATE_TYPES = frozenset({
|
|
33
|
+
GATE_TYPES = frozenset({
|
|
34
|
+
"IMPLEMENTATION_MERGE_APPROVAL",
|
|
35
|
+
"FINALIZATION_MERGE_APPROVAL",
|
|
36
|
+
"RECONCILIATION_MERGE_APPROVAL",
|
|
37
|
+
})
|
|
34
38
|
GATE_STATUSES = frozenset({"NOT_REQUIRED", "WAITING", "SATISFIED", "UNAVAILABLE"})
|
|
35
39
|
VALIDATION_STATES = frozenset(
|
|
36
40
|
{"PASS", "FAIL", "NOT_EXECUTED", "NOT_APPLICABLE", "UNAVAILABLE", "WAITING"}
|
|
37
41
|
)
|
|
38
42
|
PR_CHECK_STATES = frozenset({"PASS", "FAIL", "WAITING", "UNAVAILABLE"})
|
|
39
|
-
PR_ROLES = frozenset({"IMPLEMENTATION", "FINALIZATION"})
|
|
43
|
+
PR_ROLES = frozenset({"IMPLEMENTATION", "FINALIZATION", "RECONCILIATION"})
|
|
40
44
|
|
|
41
45
|
|
|
42
46
|
def _connection(root: Path, central_database: Path | None) -> sqlite3.Connection:
|
|
@@ -256,6 +260,7 @@ def terminal_snapshot(
|
|
|
256
260
|
worktree_state: str,
|
|
257
261
|
active_blocker: str,
|
|
258
262
|
recovery_required: str,
|
|
263
|
+
reconciliation_pr: int | None = None,
|
|
259
264
|
retry_parent: str | None = None,
|
|
260
265
|
resume_parent: str | None = None,
|
|
261
266
|
submission_id: str | None = None,
|
|
@@ -358,6 +363,7 @@ def terminal_snapshot(
|
|
|
358
363
|
"submission_id": submission_id or "UNAVAILABLE",
|
|
359
364
|
"implementation_pr": implementation_pr,
|
|
360
365
|
"finalization_pr": finalization_pr,
|
|
366
|
+
"reconciliation_pr": reconciliation_pr,
|
|
361
367
|
"gates": [{"gate_type": row[0], "status": row[1], "related_pr": row[2]} for row in gates],
|
|
362
368
|
"actions": [{"action": row[0], "authority": row[1]} for row in actions],
|
|
363
369
|
"validation_current": validation,
|
|
@@ -385,7 +391,10 @@ def terminal_snapshot(
|
|
|
385
391
|
),
|
|
386
392
|
"observed_at": _now(),
|
|
387
393
|
}
|
|
388
|
-
|
|
394
|
+
deliveries = [("IMPLEMENTATION", implementation_pr), ("FINALIZATION", finalization_pr)]
|
|
395
|
+
if reconciliation_pr is not None:
|
|
396
|
+
deliveries.append(("RECONCILIATION", reconciliation_pr))
|
|
397
|
+
for role, pr_number in deliveries:
|
|
389
398
|
check = pr_checks.get(role, {})
|
|
390
399
|
snapshot[f"{role.lower()}_delivery"] = (
|
|
391
400
|
"COMPLETE"
|
|
@@ -474,6 +483,11 @@ def evaluate(snapshot: dict[str, object]) -> tuple[str, list[str]]:
|
|
|
474
483
|
reasons.append("IMPLEMENTATION_MERGE_GATE_UNPROVEN")
|
|
475
484
|
if gate.get("FINALIZATION_MERGE_APPROVAL") != "SATISFIED":
|
|
476
485
|
reasons.append("FINALIZATION_MERGE_GATE_UNPROVEN")
|
|
486
|
+
if snapshot.get("reconciliation_pr") is not None:
|
|
487
|
+
if snapshot.get("reconciliation_delivery") != "COMPLETE":
|
|
488
|
+
reasons.append("RECONCILIATION_DELIVERY_UNPROVEN")
|
|
489
|
+
if gate.get("RECONCILIATION_MERGE_APPROVAL") != "SATISFIED":
|
|
490
|
+
reasons.append("RECONCILIATION_MERGE_GATE_UNPROVEN")
|
|
477
491
|
autonomous = {
|
|
478
492
|
row.get("action")
|
|
479
493
|
for row in snapshot.get("actions", [])
|
|
@@ -498,7 +512,10 @@ def evaluate(snapshot: dict[str, object]) -> tuple[str, list[str]]:
|
|
|
498
512
|
reasons.append("EVIDENCE_CONFLICT")
|
|
499
513
|
if snapshot.get("pr_check_projection_conflict"):
|
|
500
514
|
reasons.append("EVIDENCE_CONFLICT")
|
|
501
|
-
|
|
515
|
+
roles = ["IMPLEMENTATION", "FINALIZATION"]
|
|
516
|
+
if snapshot.get("reconciliation_pr") is not None:
|
|
517
|
+
roles.append("RECONCILIATION")
|
|
518
|
+
for role in (() if validation_only else roles):
|
|
502
519
|
if snapshot.get(f"{role.lower()}_pr") is not None:
|
|
503
520
|
check = snapshot.get("pr_checks", {}).get(role, {})
|
|
504
521
|
if check.get("required_checks_state") != "PASS":
|
|
@@ -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.71"
|
|
16
16
|
MANIFEST_FIELDS = frozenset(
|
|
17
17
|
{
|
|
18
18
|
"platform_version",
|