engineering-platform 2.3.78__tar.gz → 2.3.79__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/PKG-INFO +1 -1
  2. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/pyproject.toml +1 -1
  3. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +1 -1
  4. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +4 -4
  5. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_finalization.py +9 -1
  6. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_host.py +9 -9
  7. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_reporting.py +142 -6
  8. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/managed_autonomy.py +5 -3
  9. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/platform_version.py +1 -1
  10. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/recommendation_handoff.py +5 -2
  11. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/storage.py +65 -0
  12. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/templates/workspace-config.json +1 -1
  13. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform.egg-info/PKG-INFO +1 -1
  14. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/README.md +0 -0
  15. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/setup.cfg +0 -0
  16. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/__init__.py +0 -0
  17. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/__main__.py +0 -0
  18. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/agent_state.py +0 -0
  19. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/agent_trust.py +0 -0
  20. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/dashboard.css +0 -0
  21. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/dashboard.js +0 -0
  22. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/dashboard_locales.mjs +0 -0
  23. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/dashboard_status_store.mjs +0 -0
  24. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/dashboard_translation.mjs +0 -0
  25. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/apple-touch-icon-dark.png +0 -0
  26. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/apple-touch-icon-light.png +0 -0
  27. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/icon-dark.png +0 -0
  28. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/icon-light.png +0 -0
  29. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/icon-transparent.png +0 -0
  30. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/assets/operations-console/manifest.webmanifest +0 -0
  31. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/capability_preflight.py +0 -0
  32. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/capability_review.py +0 -0
  33. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/central_data_transfer.py +0 -0
  34. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/central_database.py +0 -0
  35. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/central_store_migration.py +0 -0
  36. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/codex_capacity.py +0 -0
  37. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/codex_chat.py +0 -0
  38. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/codex_observability.py +0 -0
  39. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/component_lock.py +0 -0
  40. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/component_logging.py +0 -0
  41. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/console_presentation.py +0 -0
  42. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/console_route_ownership.py +0 -0
  43. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/contracts/__init__.py +0 -0
  44. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/contracts/ep_consumer.py +0 -0
  45. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/contracts/models.py +0 -0
  46. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/contracts/projection.py +0 -0
  47. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/dashboard_browser_validation.py +0 -0
  48. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/dashboard_state.py +0 -0
  49. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/dashboard_supervisor.swift +0 -0
  50. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/dashboard_translation.py +0 -0
  51. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/dependabot_producer.py +0 -0
  52. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/development_profile.py +0 -0
  53. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/drift_diagnostics.py +0 -0
  54. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/emergency_recovery.py +0 -0
  55. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/engineering_memory.py +0 -0
  56. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/ep_consumer_credentials.py +0 -0
  57. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/evidence_projection.py +0 -0
  58. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_activity.py +0 -0
  59. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_context.py +0 -0
  60. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_errors.py +0 -0
  61. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_evidence.py +0 -0
  62. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_executor.py +0 -0
  63. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_host_evidence.py +0 -0
  64. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_lease.py +0 -0
  65. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_lifecycle.py +0 -0
  66. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_models.py +0 -0
  67. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_readiness.py +0 -0
  68. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_repository.py +0 -0
  69. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_timeout_policy.py +0 -0
  70. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_timing.py +0 -0
  71. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/execution_transaction.py +0 -0
  72. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/external_producer_binding.py +0 -0
  73. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/file_inbox.py +0 -0
  74. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/forensic_attribution.py +0 -0
  75. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/forensic_attribution_v2.py +0 -0
  76. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/forensic_delta.py +0 -0
  77. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/golden_scenario.py +0 -0
  78. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/historical_dashboard_configuration.py +0 -0
  79. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/host_admin.py +0 -0
  80. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/host_preflight.py +0 -0
  81. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_relocation.py +0 -0
  82. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_activation.py +0 -0
  83. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_admission.py +0 -0
  84. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_backup.py +0 -0
  85. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_composition.py +0 -0
  86. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_executor.py +0 -0
  87. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_migration.py +0 -0
  88. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_operation.py +0 -0
  89. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_plan.py +0 -0
  90. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/installation_update_preparation.py +0 -0
  91. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/investigation_ledger.py +0 -0
  92. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/legacy_inbox_migration.py +0 -0
  93. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/legacy_installation_adoption.py +0 -0
  94. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/lifecycle_worker.py +0 -0
  95. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/live_status.py +0 -0
  96. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/local_api.py +0 -0
  97. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/local_api_keychain.py +0 -0
  98. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/local_repository_binding.py +0 -0
  99. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/managed_codex_runtime.py +0 -0
  100. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/operational_installation.py +0 -0
  101. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/operational_installation_lock.py +0 -0
  102. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/operational_installation_record.py +0 -0
  103. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/owner_credential_recovery.py +0 -0
  104. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/parity_context.py +0 -0
  105. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/parity_lifecycle_dispatcher.py +0 -0
  106. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/platform_admin.py +0 -0
  107. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/platform_api.py +0 -0
  108. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/platform_bootstrap.py +0 -0
  109. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/platform_components.py +0 -0
  110. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/pr_check_repair.py +0 -0
  111. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/pr_evidence_backfill.py +0 -0
  112. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/producer.py +0 -0
  113. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/product_installation_readback.py +0 -0
  114. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/project_agent.py +0 -0
  115. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/project_agent_service.py +0 -0
  116. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/project_topology.py +0 -0
  117. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/prompt_history.py +0 -0
  118. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_context.py +0 -0
  119. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_context_benchmark.py +0 -0
  120. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_context_scope.py +0 -0
  121. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_interruption.py +0 -0
  122. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_process_identity.py +0 -0
  123. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_readiness.py +0 -0
  124. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_recovery.py +0 -0
  125. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/provider_usage.py +0 -0
  126. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/providers.py +0 -0
  127. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/qualification.py +0 -0
  128. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/qualification_runtime.py +0 -0
  129. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/reconciliation_adoption.py +0 -0
  130. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/release_operation.py +0 -0
  131. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/report_analysis.py +0 -0
  132. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/repository_attachment.py +0 -0
  133. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/repository_handoff.py +0 -0
  134. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/resources.py +0 -0
  135. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/reviewer_evidence.py +0 -0
  136. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/revision_binding.py +0 -0
  137. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/schemas/producer-readback-v1.2.schema.json +0 -0
  138. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/schemas/producer-readback-v1.schema.json +0 -0
  139. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/schemas/repository-attachment.schema.json +0 -0
  140. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/server.py +0 -0
  141. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/server_console_services.py +0 -0
  142. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/server_relay.py +0 -0
  143. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/server_service.py +0 -0
  144. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/status_model.py +0 -0
  145. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/status_reconciliation.py +0 -0
  146. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/submission_cli.py +0 -0
  147. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/submission_intake.py +0 -0
  148. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/submission_service.py +0 -0
  149. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/system_installation_topology.py +0 -0
  150. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/system_server_service.py +0 -0
  151. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/telemetry.py +0 -0
  152. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/telemetry_contract.py +0 -0
  153. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/terminal_evidence_reconciliation.py +0 -0
  154. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/validation_identity.py +0 -0
  155. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/validation_profile.py +0 -0
  156. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/version_preparation_delivery.py +0 -0
  157. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/workspace_preflight.py +0 -0
  158. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/worktree_provenance.py +0 -0
  159. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform/worktree_tooling.py +0 -0
  160. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform.egg-info/SOURCES.txt +0 -0
  161. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform.egg-info/dependency_links.txt +0 -0
  162. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform.egg-info/entry_points.txt +0 -0
  163. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/src/engineering_platform.egg-info/top_level.txt +0 -0
  164. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/tests/test_adaptive_action_sizing_design.py +0 -0
  165. {engineering_platform-2.3.78 → engineering_platform-2.3.79}/tests/test_role_task_model_policy_design.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-platform
3
- Version: 2.3.78
3
+ Version: 2.3.79
4
4
  Summary: Local-first Engineering Platform execution operations runtime
5
5
  Author: Peter van Tol
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "engineering-platform"
7
- version = "2.3.78"
7
+ version = "2.3.79"
8
8
  description = "Local-first Engineering Platform execution operations runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14,<3.15"
@@ -3,7 +3,7 @@
3
3
  "platform": {
4
4
  "id": "engineering-platform",
5
5
  "name": "Engineering Platform",
6
- "version": "2.3.78",
6
+ "version": "2.3.79",
7
7
  "generation": 2,
8
8
  "documentation_namespace": "engineering-platform",
9
9
  "capability_registry_version": 1
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "bootstrap_contract": "2026.12",
3
3
  "checkpoint_format": 1,
4
- "dashboard_version": "2.3.78",
4
+ "dashboard_version": "2.3.79",
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.78",
9
+ "platform_version": "2.3.79",
10
10
  "report_format": 2,
11
- "runner_version": "2.3.78",
11
+ "runner_version": "2.3.79",
12
12
  "status_model": 1,
13
13
  "storage_schema": 45,
14
- "watcher_version": "2.3.78"
14
+ "watcher_version": "2.3.79"
15
15
  }
@@ -40,7 +40,15 @@ class FinalizationCoordinator:
40
40
  except RunnerError as error:
41
41
  return save_terminal(cleanup, "BLOCKED", "repository_cleanup_required", str(error))
42
42
  return save_terminal(
43
- replace(cleanup, latest_repository_evidence=redact_diagnostic(result)),
43
+ replace(
44
+ cleanup,
45
+ latest_repository_evidence=redact_diagnostic(result),
46
+ terminal_condition=(
47
+ "local_commit_reconciled"
48
+ if cleanup.execution_mode == "GENESIS"
49
+ else "repository_reconciled"
50
+ ),
51
+ ),
44
52
  "COMPLETE",
45
53
  "repository_cleanup_reconciled",
46
54
  None,
@@ -829,20 +829,20 @@ class EngineeringRunner:
829
829
  if kind is None:
830
830
  continue
831
831
  status = self._validation_summary_status(summary)
832
+ if profile_context and profile_context.get("profile_digest"):
833
+ binding = matching_control_binding(command, profile_context["control_bindings"])
834
+ validation_id = (
835
+ str(binding["validation_id"])
836
+ if isinstance(binding, dict) else self._validation_id(command, kind)
837
+ )
838
+ else:
839
+ validation_id = self._validation_id_for_profile(command, kind, tier)
832
840
  try:
833
841
  record_managed_validation(
834
842
  self.root, run_id=state.run_id, control=f"validation_{kind}", state=status,
835
- required=True, currentness=state.repair_iterations,
843
+ required=validation_id in required_controls, currentness=state.repair_iterations,
836
844
  central_database=self.store.central_database,
837
845
  )
838
- if profile_context and profile_context.get("profile_digest"):
839
- binding = matching_control_binding(command, profile_context["control_bindings"])
840
- validation_id = (
841
- str(binding["validation_id"])
842
- if isinstance(binding, dict) else self._validation_id(command, kind)
843
- )
844
- else:
845
- validation_id = self._validation_id_for_profile(command, kind, tier)
846
846
  record_validation_control_result(
847
847
  self.root, run_id=state.run_id, validation_id=validation_id, category="agent",
848
848
  control_identity=command[:160], required_for_profile=validation_id in required_controls, execution_status="EXECUTED",
@@ -25,7 +25,7 @@ from .producer import ProducerMetadata, parse_producer_metadata
25
25
  from .providers import GitProvider
26
26
  from .qualification import latest_qualification
27
27
  from .recommendation_handoff import ForgeGovernanceHandoff, report_lines as recommendation_handoff_report_lines
28
- from .storage import EngineeringStorageError, load_readiness_evaluation, load_run_qualification_snapshot, load_submission_for_run, load_run_lineage, load_validation_context
28
+ from .storage import EngineeringStorageError, load_readiness_evaluation, load_run_qualification_snapshot, load_submission_attempt_for_run, load_submission_for_run, load_run_lineage, load_validation_context
29
29
  from .telemetry_contract import run_telemetry_snapshot
30
30
  from .provider_recovery import load_recovery_state
31
31
  from .execution_activity import build_terminal_activity_summary, persist_terminal_activity_summary, terminal_activity_summary
@@ -164,7 +164,9 @@ def _persisted_producer_submission(
164
164
  ) -> tuple[ProducerMetadata, dict[str, object] | None]:
165
165
  """Use immutable Producer submission evidence before legacy prompt compatibility."""
166
166
  try:
167
- submission = load_submission_for_run(root, state.run_id, central_database=central_database)
167
+ submission = load_submission_attempt_for_run(
168
+ root, state.run_id, central_database=central_database,
169
+ )
168
170
  except EngineeringStorageError:
169
171
  submission = None
170
172
  if submission is None:
@@ -194,9 +196,16 @@ def _producer_submission_contract_lines(
194
196
  if isinstance(validation_context, dict) and isinstance(profile, dict)
195
197
  else "not supplied by Producer"
196
198
  )
199
+ canonical = submission.get("canonical_submission_id") if isinstance(submission, dict) else None
200
+ attempt = submission.get("submission_id") if isinstance(submission, dict) else None
201
+ lineage = (
202
+ (f"- Canonical Root Submission ID: `{canonical}`",)
203
+ if isinstance(canonical, str) and canonical != attempt else ()
204
+ )
197
205
  return (
198
206
  "## Producer Submission Contract",
199
207
  f"- Submission ID: `{submission.get('submission_id') if submission else 'legacy'}`",
208
+ *lineage,
200
209
  f"- Contract Version: `{submission.get('contract_version') if submission else 'legacy prompt'}`",
201
210
  "- Submission Status: `PERSISTED_IMMUTABLY`",
202
211
  "",
@@ -213,6 +222,66 @@ def _producer_submission_contract_lines(
213
222
  )
214
223
 
215
224
 
225
+ def _forge_execution_provenance_lines(
226
+ submission: dict[str, object] | None,
227
+ ) -> tuple[str, ...]:
228
+ """Render only the identifier-only subset of admitted Forge provenance."""
229
+ constraints = submission.get("constraints") if isinstance(submission, dict) else None
230
+ raw = constraints.get("forge_execution") if isinstance(constraints, dict) else None
231
+ if not isinstance(raw, dict):
232
+ return ()
233
+ runtime_prompt = raw.get("runtime_prompt")
234
+ runtime_prompt = runtime_prompt if isinstance(runtime_prompt, dict) else {}
235
+
236
+ def token(name: str, *, maximum: int = 512) -> str:
237
+ value = raw.get(name)
238
+ if not isinstance(value, str) or not value.strip() or len(value) > maximum or "\n" in value:
239
+ return "UNAVAILABLE"
240
+ return value.strip()
241
+
242
+ prompt_id = runtime_prompt.get("id")
243
+ prompt_digest = runtime_prompt.get("content_digest")
244
+ prompt_id = (
245
+ prompt_id.strip()
246
+ if isinstance(prompt_id, str) and prompt_id.strip()
247
+ and len(prompt_id) <= 512 and "\n" not in prompt_id
248
+ else "UNAVAILABLE"
249
+ )
250
+ prompt_digest = (
251
+ prompt_digest
252
+ if isinstance(prompt_digest, str)
253
+ and re.fullmatch(r"sha256:[0-9a-f]{64}", prompt_digest)
254
+ else "UNAVAILABLE"
255
+ )
256
+ submission_id = submission.get("submission_id") if isinstance(submission, dict) else None
257
+ correlation = token("correlation_id")
258
+ mission = token("mission_id")
259
+ action = token("action_id")
260
+ identity_matches = (
261
+ correlation == submission.get("correlation_id")
262
+ and mission == submission.get("mission_id")
263
+ and action == submission.get("engineering_action_id")
264
+ )
265
+ return (
266
+ "## Forge Execution Provenance",
267
+ "This is the immutable, attempt-scoped Forge provenance admitted by CENTRAL; it is distinct from the optional generic Execution Context snapshot.",
268
+ f"- Submission Attempt ID: `{submission_id or 'UNAVAILABLE'}`",
269
+ f"- Forge Provenance Contract: `{token('contract_version')}`",
270
+ f"- Identity Binding: `{'VERIFIED' if identity_matches else 'UNAVAILABLE'}`",
271
+ f"- Mission ID: `{mission}`",
272
+ f"- Mission Revision: `{token('mission_revision')}`",
273
+ f"- Intent ID: `{token('intent_id')}`",
274
+ f"- Intent Revision: `{token('intent_revision')}`",
275
+ f"- Engineering Action ID: `{action}`",
276
+ f"- Runtime Prompt ID: `{prompt_id}`",
277
+ f"- Runtime Prompt Digest: `{prompt_digest}`",
278
+ f"- Retry Correlation ID: `{token('retry_of_correlation_id') if raw.get('retry_of_correlation_id') is not None else 'NONE'}`",
279
+ f"- Action Context Envelope: `{'SUPPLIED' if isinstance(raw.get('action_context_envelope'), dict) else 'NOT SUPPLIED'}`",
280
+ f"- Planning Context Envelope: `{'SUPPLIED' if isinstance(raw.get('planning_context_envelope'), dict) else 'NOT SUPPLIED'}`",
281
+ "",
282
+ )
283
+
284
+
216
285
  def _repository_summary(evidence: RepositoryEvidence) -> str:
217
286
  return redact_diagnostic(
218
287
  f"branch={evidence.branch}; head={evidence.head_sha}; clean={evidence.clean}; main_contains_head={evidence.main_contains_head}"
@@ -343,8 +412,11 @@ def _evidence_lines(label: str, values: tuple[str, ...]) -> tuple[str, ...]:
343
412
  def _implementation_evidence(bundle: TerminalEvidenceBundle) -> str:
344
413
  """Classify file-level evidence without inferring unrecorded implementation intent."""
345
414
  changed = bundle.changed_files
415
+ implementation_files = tuple(
416
+ path for _component, paths in _component_inventory(bundle) for path in paths
417
+ )
346
418
  groups = {
347
- "Implemented components": tuple(path for path in changed if path.startswith("src/engineering_platform/")),
419
+ "Implemented components": implementation_files,
348
420
  "Updated models": tuple(path for path in changed if "model" in path.casefold() or "state" in path.casefold()),
349
421
  "Updated documentation": tuple(path for path in changed if path.endswith(".md")),
350
422
  "Updated tests": tuple(path for path in changed if path.startswith("tests/") or "/test_" in path),
@@ -693,7 +765,12 @@ def _runtime_projection(
693
765
  )
694
766
 
695
767
 
696
- def _execution_receipt_projection(root: Path, state: TransactionState, producer: ProducerMetadata) -> tuple[str, ...]:
768
+ def _execution_receipt_projection(
769
+ root: Path,
770
+ state: TransactionState,
771
+ producer: ProducerMetadata,
772
+ submission: dict[str, object] | None = None,
773
+ ) -> tuple[str, ...]:
697
774
  """Render receipt qualification fields only from the persisted terminal snapshot."""
698
775
  try:
699
776
  snapshot = load_run_qualification_snapshot(root, state.run_id) or {}
@@ -705,7 +782,7 @@ def _execution_receipt_projection(root: Path, state: TransactionState, producer:
705
782
  delivery_paths = activity.get("terminal_delivery_diff", {}).get("total_unique_changed_paths", "UNAVAILABLE") if isinstance(activity, dict) else "UNAVAILABLE"
706
783
  conflicts_text = ", ".join(conflicts) if isinstance(conflicts, list) and conflicts else "NONE"
707
784
  recovery = load_recovery_state(root, state.run_id) or {}
708
- submission = load_submission_for_run(root, state.run_id) or {}
785
+ submission = submission or load_submission_for_run(root, state.run_id) or {}
709
786
  return (
710
787
  f"- Receipt ID: `{state.run_id}`",
711
788
  "- Execution Host: `Engineering Platform`",
@@ -791,6 +868,16 @@ def report_consistency_errors(body: str, state: TransactionState, bundle: Termin
791
868
  errors.append("repository commit is missing")
792
869
  if state.phase == "COMPLETE" and "## Evidence Bundle" not in body:
793
870
  errors.append("complete report is missing Evidence Bundle")
871
+ receipt_resolution = re.search(r"^- Receipt Resolution: `([^`]+)`$", body, re.MULTILINE)
872
+ if (
873
+ state.phase == "COMPLETE"
874
+ and receipt_resolution is not None
875
+ and receipt_resolution.group(1) in {
876
+ "operator_merge_required", "open_pr_checks_terminal",
877
+ "post_merge_workspace_sync_required",
878
+ }
879
+ ):
880
+ errors.append("complete report has a nonterminal receipt resolution")
794
881
  fresh = re.search(r"^- Fresh Submission: `([^`]+)`$", body, re.MULTILINE)
795
882
  retry = re.search(r"^- Retry Parent: `([^`]+)`$", body, re.MULTILINE)
796
883
  resume = re.search(r"^- Resume Parent: `([^`]+)`$", body, re.MULTILINE)
@@ -1041,6 +1128,53 @@ def _format_reviewer_records(records: tuple[dict[str, object], ...], phase: str)
1041
1128
  return "\n".join(lines)
1042
1129
 
1043
1130
 
1131
+ def _format_assurance_reviews(state: TransactionState) -> tuple[str, ...]:
1132
+ """Project mandatory candidate-bound assurance separately from capability advice."""
1133
+ lines = [
1134
+ "## Candidate-bound Quality and Security Assurance",
1135
+ "These records are mandatory post-implementation assurance, not capability-review recommendations.",
1136
+ ]
1137
+ if not state.assurance_reviews:
1138
+ lines.extend(("- Assurance Reviews: `NOT RECORDED`", ""))
1139
+ return tuple(lines)
1140
+ for review in state.assurance_reviews:
1141
+ if not isinstance(review, dict):
1142
+ continue
1143
+ reviewer = review.get("reviewer")
1144
+ status = review.get("status")
1145
+ candidate = review.get("candidate_sha")
1146
+ findings = review.get("findings")
1147
+ if (
1148
+ reviewer not in {"quality", "security"}
1149
+ or status not in {"PASS", "FAIL", "UNRESOLVED"}
1150
+ or not isinstance(candidate, str)
1151
+ or re.fullmatch(r"[0-9a-f]{40}", candidate) is None
1152
+ or not isinstance(findings, list)
1153
+ ):
1154
+ continue
1155
+ lines.extend((
1156
+ f"- Reviewer: `{reviewer}`",
1157
+ f" - Status: `{status}`",
1158
+ f" - Candidate SHA: `{candidate}`",
1159
+ f" - Invocation ID: `{review.get('invocation_id', 'UNAVAILABLE')}`",
1160
+ f" - Finding Count: `{len(findings)}`",
1161
+ ))
1162
+ for finding in findings:
1163
+ if not isinstance(finding, dict):
1164
+ continue
1165
+ lines.append(
1166
+ " - Finding: "
1167
+ f"severity `{finding.get('severity', 'UNAVAILABLE')}`; "
1168
+ f"disposition `{finding.get('disposition', 'UNAVAILABLE')}`; "
1169
+ f"blocking `{'YES' if finding.get('blocking') is True else 'NO'}`; "
1170
+ f"evidence `{finding.get('evidence_ref', 'UNAVAILABLE')}`."
1171
+ )
1172
+ if len(lines) == 2:
1173
+ lines.append("- Assurance Reviews: `INVALID OR UNAVAILABLE`")
1174
+ lines.append("")
1175
+ return tuple(lines)
1176
+
1177
+
1044
1178
  def _format_engineering_outcome(state: TransactionState) -> str:
1045
1179
  """Describe final delivery from checkpoint and repository evidence, never advice."""
1046
1180
  if state.phase != "COMPLETE":
@@ -1459,6 +1593,7 @@ def generate_terminal_report(
1459
1593
  f"- Execution Constraint Version: `{producer.execution_constraint_version or 'not supplied'}`",
1460
1594
  "",
1461
1595
  *_producer_submission_contract_lines(submission, state, root),
1596
+ *_forge_execution_provenance_lines(submission),
1462
1597
  "## Execution Target Identity",
1463
1598
  "- Execution Host: `Engineering Platform`",
1464
1599
  f"- Execution Host Repository: `{state.repository}`",
@@ -1585,6 +1720,7 @@ def generate_terminal_report(
1585
1720
  _format_engineering_outcome(state),
1586
1721
  "",
1587
1722
  *_managed_autonomy_projection(root, state, bundle, reviewer_records),
1723
+ *_format_assurance_reviews(state),
1588
1724
  "## Reviewer Findings",
1589
1725
  "Initial observations only. They are not final repository claims.",
1590
1726
  _format_reviewer_records(reviewer_records, state.phase),
@@ -1609,7 +1745,7 @@ def generate_terminal_report(
1609
1745
  *_runtime_projection(state, producer, runtime_provider, reported_model),
1610
1746
  "",
1611
1747
  "## Execution Receipt Projection",
1612
- *_execution_receipt_projection(root, state, producer),
1748
+ *_execution_receipt_projection(root, state, producer, submission),
1613
1749
  "",
1614
1750
  "## Decision Evidence Projection",
1615
1751
  *_decision_evidence_projection(producer),
@@ -210,14 +210,16 @@ def append_pr_check_observation(
210
210
 
211
211
 
212
212
  def _current(rows: Iterable[tuple[object, ...]]) -> tuple[dict[str, str], bool]:
213
- grouped: dict[str, list[tuple[str, int]]] = {}
213
+ grouped: dict[str, list[tuple[str, int, bool]]] = {}
214
214
  for control, state, _required, currentness, _at in rows:
215
- grouped.setdefault(str(control), []).append((str(state), int(currentness)))
215
+ grouped.setdefault(str(control), []).append((str(state), int(currentness), bool(_required)))
216
216
  result, conflict = {}, False
217
217
  for control, values in grouped.items():
218
218
  latest = max(item[1] for item in values)
219
219
  states = {item[0] for item in values if item[1] == latest}
220
- conflict |= len(states) != 1
220
+ # Optional/provider-advisory observations remain visible, but only a
221
+ # conflicting required control can make run qualification ambiguous.
222
+ conflict |= len(states) != 1 and any(item[2] for item in values if item[1] == latest)
221
223
  result[control] = next(iter(states)) if len(states) == 1 else "UNAVAILABLE"
222
224
  return result, conflict
223
225
 
@@ -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.78"
15
+ CURRENT_PLATFORM_VERSION = "2.3.79"
16
16
  MANIFEST_FIELDS = frozenset(
17
17
  {
18
18
  "platform_version",
@@ -173,8 +173,11 @@ def report_lines(handoff: ForgeGovernanceHandoff | None, execution_status: str)
173
173
  if handoff is None:
174
174
  return (
175
175
  "## Forge Governance Handoff", "- Forge Governance Handoff: `NOT SUPPLIED BY PRODUCER`",
176
- "- Governance Status: `FORGE GOVERNANCE HANDOFF NOT SUPPLIED`", "- Decision Evidence: `NOT SUPPLIED BY PRODUCER`",
177
- "- Governance Handoff Completeness: `INCOMPLETE`", "- Business Review Readiness: `NOT SUPPLIED BY PRODUCER`", "",
176
+ "- Handoff Requirement: `NOT DECLARED BY PRODUCER`",
177
+ "- Governance Status: `NOT ASSESSED`", "- Decision Evidence: `NOT SUPPLIED BY PRODUCER`",
178
+ "- Governance Handoff Completeness: `NOT ASSESSED`",
179
+ "- Business Review Readiness: `NOT ASSESSED`",
180
+ "- Interpretation: absence is not a failed or incomplete governance review unless the Producer contract declared this handoff required.", "",
178
181
  )
179
182
  selected = handoff.selected
180
183
  evidence = handoff.decision_evidence or {}
@@ -2038,6 +2038,71 @@ def load_submission_for_run(root: Path, run_id: str, *, central_database: Path |
2038
2038
  }
2039
2039
 
2040
2040
 
2041
+ def load_submission_attempt_for_run(
2042
+ root: Path, run_id: str, *, central_database: Path | None = None,
2043
+ ) -> dict[str, object] | None:
2044
+ """Load the concrete admitted submission attempt bound to one run.
2045
+
2046
+ ``load_submission_for_run`` deliberately returns the immutable root
2047
+ submission for a correlated retry. A terminal report also needs the
2048
+ attempt identity and its admitted constraints; otherwise it can combine
2049
+ the root submission ID with retry-scoped qualification evidence. Keep the
2050
+ root metadata as provenance authority while overlaying only fields that
2051
+ CENTRAL persisted immutably for the exact run-bound attempt.
2052
+ """
2053
+ root_submission = load_submission_for_run(
2054
+ root, run_id, central_database=central_database,
2055
+ )
2056
+ if root_submission is None or central_database is None:
2057
+ return root_submission
2058
+ connection = _evidence_connection(root, central_database)
2059
+ try:
2060
+ row = connection.execute(
2061
+ "SELECT accepted.submission_id,accepted.producer_id,accepted.producer_type,"
2062
+ "accepted.producer_version,accepted.correlation_id,accepted.mission_id,"
2063
+ "accepted.engineering_action_id,accepted.constraints,attempt.canonical_submission_id "
2064
+ "FROM execution_submission_attempt_links AS link "
2065
+ "JOIN execution_submission_attempts AS attempt "
2066
+ "ON attempt.submission_id=link.submission_id "
2067
+ "JOIN ep_submissions AS accepted "
2068
+ "ON accepted.submission_id=link.submission_id "
2069
+ "WHERE link.run_id=?",
2070
+ (run_id,),
2071
+ ).fetchone()
2072
+ finally:
2073
+ connection.close()
2074
+ if row is None:
2075
+ return root_submission
2076
+ if (
2077
+ row[8] != root_submission["submission_id"]
2078
+ or row[1] != root_submission["producer_id"]
2079
+ or row[2] != root_submission["producer_type"]
2080
+ ):
2081
+ raise EngineeringStorageError(
2082
+ "Persisted submission attempt conflicts with canonical Producer provenance."
2083
+ )
2084
+ try:
2085
+ constraints = json.loads(row[7])
2086
+ except (TypeError, json.JSONDecodeError) as error:
2087
+ raise EngineeringStorageError(
2088
+ "Persisted submission attempt constraints are corrupt."
2089
+ ) from error
2090
+ if not isinstance(constraints, dict):
2091
+ raise EngineeringStorageError(
2092
+ "Persisted submission attempt constraints are invalid."
2093
+ )
2094
+ return {
2095
+ **root_submission,
2096
+ "canonical_submission_id": root_submission["submission_id"],
2097
+ "submission_id": row[0],
2098
+ "producer_version": row[3],
2099
+ "correlation_id": row[4],
2100
+ "mission_id": row[5],
2101
+ "engineering_action_id": row[6],
2102
+ "constraints": constraints,
2103
+ }
2104
+
2105
+
2041
2106
  def load_run_lineage(root: Path, run_id: str) -> dict[str, object] | None:
2042
2107
  """Load explicit qualification lineage; legacy rows deliberately remain unavailable."""
2043
2108
  connection = open_storage(root)
@@ -3,7 +3,7 @@
3
3
  "platform": {
4
4
  "id": "engineering-platform",
5
5
  "name": "Engineering Platform",
6
- "version": "2.3.78",
6
+ "version": "2.3.79",
7
7
  "generation": 2,
8
8
  "documentation_namespace": "engineering-platform",
9
9
  "capability_registry_version": 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-platform
3
- Version: 2.3.78
3
+ Version: 2.3.79
4
4
  Summary: Local-first Engineering Platform execution operations runtime
5
5
  Author: Peter van Tol
6
6
  License: MIT