devagent-ai 0.8.4__tar.gz → 0.8.6__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 (226) hide show
  1. {devagent_ai-0.8.4/devagent_ai.egg-info → devagent_ai-0.8.6}/PKG-INFO +23 -1
  2. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/README.md +20 -0
  3. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/__init__.py +1 -1
  4. devagent_ai-0.8.6/devagent/__main__.py +4 -0
  5. devagent_ai-0.8.6/devagent/entrypoint.py +22 -0
  6. devagent_ai-0.8.6/devagent/plc/__init__.py +185 -0
  7. devagent_ai-0.8.6/devagent/plc/agent_harness_install_v15.py +27 -0
  8. devagent_ai-0.8.6/devagent/plc/agent_harness_v15.py +208 -0
  9. devagent_ai-0.8.6/devagent/plc/analysis.py +650 -0
  10. devagent_ai-0.8.6/devagent/plc/cli.py +320 -0
  11. devagent_ai-0.8.6/devagent/plc/execution_trust.py +176 -0
  12. devagent_ai-0.8.6/devagent/plc/fat_procedure_v12.py +165 -0
  13. devagent_ai-0.8.6/devagent/plc/four_contract_v13.py +196 -0
  14. devagent_ai-0.8.6/devagent/plc/inspect_cli.py +164 -0
  15. devagent_ai-0.8.6/devagent/plc/models.py +332 -0
  16. devagent_ai-0.8.6/devagent/plc/plc_dispatch.py +41 -0
  17. devagent_ai-0.8.6/devagent/plc/production.py +480 -0
  18. devagent_ai-0.8.6/devagent/plc/production_ai.py +440 -0
  19. devagent_ai-0.8.6/devagent/plc/production_evidence.py +159 -0
  20. devagent_ai-0.8.6/devagent/plc/production_models.py +220 -0
  21. devagent_ai-0.8.6/devagent/plc/production_readiness.py +223 -0
  22. devagent_ai-0.8.6/devagent/plc/production_readiness_v5.py +279 -0
  23. devagent_ai-0.8.6/devagent/plc/production_regression.py +306 -0
  24. devagent_ai-0.8.6/devagent/plc/production_report.py +325 -0
  25. devagent_ai-0.8.6/devagent/plc/production_review.py +253 -0
  26. devagent_ai-0.8.6/devagent/plc/production_utils.py +57 -0
  27. devagent_ai-0.8.6/devagent/plc/production_v5.py +412 -0
  28. devagent_ai-0.8.6/devagent/plc/production_verification.py +397 -0
  29. devagent_ai-0.8.6/devagent/plc/professional_report_install_v14.py +37 -0
  30. devagent_ai-0.8.6/devagent/plc/professional_report_v14.py +252 -0
  31. devagent_ai-0.8.6/devagent/plc/release_policy.py +230 -0
  32. devagent_ai-0.8.6/devagent/plc/report.py +114 -0
  33. devagent_ai-0.8.6/devagent/plc/report_clarity_install_v16.py +65 -0
  34. devagent_ai-0.8.6/devagent/plc/requirements.py +260 -0
  35. devagent_ai-0.8.6/devagent/plc/rockwell_action_requirements.py +146 -0
  36. devagent_ai-0.8.6/devagent/plc/rockwell_alias_hardening.py +273 -0
  37. devagent_ai-0.8.6/devagent/plc/rockwell_branch_coverage_v16.py +90 -0
  38. devagent_ai-0.8.6/devagent/plc/rockwell_closeout.py +307 -0
  39. devagent_ai-0.8.6/devagent/plc/rockwell_closeout_gate_hardening.py +224 -0
  40. devagent_ai-0.8.6/devagent/plc/rockwell_compare.py +489 -0
  41. devagent_ai-0.8.6/devagent/plc/rockwell_compare_hardening.py +466 -0
  42. devagent_ai-0.8.6/devagent/plc/rockwell_compare_reachability_hardening.py +127 -0
  43. devagent_ai-0.8.6/devagent/plc/rockwell_core_review_v12.py +226 -0
  44. devagent_ai-0.8.6/devagent/plc/rockwell_echo.py +483 -0
  45. devagent_ai-0.8.6/devagent/plc/rockwell_echo_gate.py +42 -0
  46. devagent_ai-0.8.6/devagent/plc/rockwell_entrypoint_hardening.py +227 -0
  47. devagent_ai-0.8.6/devagent/plc/rockwell_general_actions.py +387 -0
  48. devagent_ai-0.8.6/devagent/plc/rockwell_l5x.py +509 -0
  49. devagent_ai-0.8.6/devagent/plc/rockwell_motion_runtime_v11.py +149 -0
  50. devagent_ai-0.8.6/devagent/plc/rockwell_regression_case_compat_v12.py +86 -0
  51. devagent_ai-0.8.6/devagent/plc/rockwell_regression_evidence_hardening.py +583 -0
  52. devagent_ai-0.8.6/devagent/plc/rockwell_requirement_hardening.py +127 -0
  53. devagent_ai-0.8.6/devagent/plc/rockwell_risk_hardening.py +155 -0
  54. devagent_ai-0.8.6/devagent/plc/rockwell_semantic_capabilities.py +92 -0
  55. devagent_ai-0.8.6/devagent/plc/rockwell_st_case_v11.py +215 -0
  56. devagent_ai-0.8.6/devagent/plc/rockwell_st_v10.py +52 -0
  57. devagent_ai-0.8.6/devagent/plc/rockwell_standard_catalog.py +146 -0
  58. devagent_ai-0.8.6/devagent/plc/rockwell_state_machine_v11.py +219 -0
  59. devagent_ai-0.8.6/devagent/plc/rockwell_stateful_runtime.py +288 -0
  60. devagent_ai-0.8.6/devagent/plc/rockwell_structure.py +260 -0
  61. devagent_ai-0.8.6/devagent/plc/rockwell_system_service_install_v17.py +147 -0
  62. devagent_ai-0.8.6/devagent/plc/rockwell_system_service_report_install_v17.py +51 -0
  63. devagent_ai-0.8.6/devagent/plc/rockwell_system_service_v17.py +363 -0
  64. devagent_ai-0.8.6/devagent/plc/rockwell_v10_semantics.py +352 -0
  65. devagent_ai-0.8.6/devagent/plc/safe_analysis.py +247 -0
  66. devagent_ai-0.8.6/devagent/plc/semantic_coverage.py +238 -0
  67. devagent_ai-0.8.6/devagent/plc/semantic_coverage_report.py +197 -0
  68. devagent_ai-0.8.6/devagent/plc/siemens_call_graph_v3.py +1719 -0
  69. devagent_ai-0.8.6/devagent/plc/siemens_cli_install_v1.py +38 -0
  70. devagent_ai-0.8.6/devagent/plc/siemens_flgnet_extended_hardening_v4.py +257 -0
  71. devagent_ai-0.8.6/devagent/plc/siemens_flgnet_extended_v4.py +916 -0
  72. devagent_ai-0.8.6/devagent/plc/siemens_flgnet_hardening_v4.py +128 -0
  73. devagent_ai-0.8.6/devagent/plc/siemens_flgnet_v4.py +1284 -0
  74. devagent_ai-0.8.6/devagent/plc/siemens_integration_v1.py +526 -0
  75. devagent_ai-0.8.6/devagent/plc/siemens_interlock_permissive_v6.py +694 -0
  76. devagent_ai-0.8.6/devagent/plc/siemens_recovery_v7.py +567 -0
  77. devagent_ai-0.8.6/devagent/plc/siemens_scl_control_flow_hardening_v2.py +97 -0
  78. devagent_ai-0.8.6/devagent/plc/siemens_scl_control_flow_v2.py +588 -0
  79. devagent_ai-0.8.6/devagent/plc/siemens_state_machine_hardening_v5.py +206 -0
  80. devagent_ai-0.8.6/devagent/plc/siemens_state_machine_v5.py +1067 -0
  81. devagent_ai-0.8.6/devagent/plc/siemens_tia_v1.py +1050 -0
  82. devagent_ai-0.8.6/devagent/plc/siemens_v5_bindings_v1.py +32 -0
  83. devagent_ai-0.8.6/devagent/plc/siemens_v6_v7_token_hardening.py +155 -0
  84. devagent_ai-0.8.6/devagent/plc/signature_trust.py +212 -0
  85. devagent_ai-0.8.6/devagent/plc/trusted_snapshot.py +333 -0
  86. devagent_ai-0.8.6/devagent/plc/v2_guardrails.py +234 -0
  87. devagent_ai-0.8.6/devagent/plc/v2_semantics.py +780 -0
  88. {devagent_ai-0.8.4 → devagent_ai-0.8.6/devagent_ai.egg-info}/PKG-INFO +23 -1
  89. devagent_ai-0.8.6/devagent_ai.egg-info/SOURCES.txt +222 -0
  90. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent_ai.egg-info/entry_points.txt +1 -1
  91. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent_ai.egg-info/requires.txt +1 -0
  92. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/pyproject.toml +4 -2
  93. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_packaging_metadata.py +1 -1
  94. devagent_ai-0.8.6/tests/test_plc_agent_harness_trace_v15.py +91 -0
  95. devagent_ai-0.8.6/tests/test_plc_agent_harness_v15.py +259 -0
  96. devagent_ai-0.8.6/tests/test_plc_execution_trust.py +63 -0
  97. devagent_ai-0.8.6/tests/test_plc_four_contract_v13.py +179 -0
  98. devagent_ai-0.8.6/tests/test_plc_product_contract_v12.py +190 -0
  99. devagent_ai-0.8.6/tests/test_plc_production.py +453 -0
  100. devagent_ai-0.8.6/tests/test_plc_production_v5.py +358 -0
  101. devagent_ai-0.8.6/tests/test_plc_release_policy.py +78 -0
  102. devagent_ai-0.8.6/tests/test_plc_rockwell_boolean_alias_proof.py +92 -0
  103. devagent_ai-0.8.6/tests/test_plc_rockwell_canonical_risks.py +82 -0
  104. devagent_ai-0.8.6/tests/test_plc_rockwell_closeout_v9.py +180 -0
  105. devagent_ai-0.8.6/tests/test_plc_rockwell_closeout_v9_guardrails.py +85 -0
  106. devagent_ai-0.8.6/tests/test_plc_rockwell_closeout_v9_review_regressions.py +78 -0
  107. devagent_ai-0.8.6/tests/test_plc_rockwell_compare_v8.py +227 -0
  108. devagent_ai-0.8.6/tests/test_plc_rockwell_compare_v8_aliases.py +147 -0
  109. devagent_ai-0.8.6/tests/test_plc_rockwell_compare_v8_hardening.py +122 -0
  110. devagent_ai-0.8.6/tests/test_plc_rockwell_compare_v8_identity_assertions.py +185 -0
  111. devagent_ai-0.8.6/tests/test_plc_rockwell_compare_v8_review_regressions.py +145 -0
  112. devagent_ai-0.8.6/tests/test_plc_rockwell_echo_cli_v6.py +47 -0
  113. devagent_ai-0.8.6/tests/test_plc_rockwell_echo_v6.py +337 -0
  114. devagent_ai-0.8.6/tests/test_plc_rockwell_hardening.py +207 -0
  115. devagent_ai-0.8.6/tests/test_plc_rockwell_semantics_v7.py +140 -0
  116. devagent_ai-0.8.6/tests/test_plc_rockwell_v1.py +218 -0
  117. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_action_requirements.py +78 -0
  118. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_arbitrary_project_qualification.py +142 -0
  119. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_echo_compatibility.py +119 -0
  120. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_general_actions.py +110 -0
  121. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_general_semantics.py +264 -0
  122. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_inspect_cli.py +92 -0
  123. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_semantic_coverage.py +144 -0
  124. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_st_safe_functions.py +46 -0
  125. devagent_ai-0.8.6/tests/test_plc_rockwell_v10_stateful_runtime.py +67 -0
  126. devagent_ai-0.8.6/tests/test_plc_rockwell_v11_reporting.py +53 -0
  127. devagent_ai-0.8.6/tests/test_plc_rockwell_v11_st_motion.py +106 -0
  128. devagent_ai-0.8.6/tests/test_plc_rockwell_v11_state_machine.py +68 -0
  129. devagent_ai-0.8.6/tests/test_plc_rockwell_v16_semantic_hardening.py +99 -0
  130. devagent_ai-0.8.6/tests/test_plc_rockwell_v17_system_service_fat.py +150 -0
  131. devagent_ai-0.8.6/tests/test_plc_rockwell_v17_system_service_generic.py +61 -0
  132. devagent_ai-0.8.6/tests/test_plc_rockwell_v2.py +242 -0
  133. devagent_ai-0.8.6/tests/test_plc_rockwell_v9_entry_edgecases.py +105 -0
  134. devagent_ai-0.8.6/tests/test_plc_rockwell_v9_final_codex.py +319 -0
  135. devagent_ai-0.8.6/tests/test_plc_rockwell_v9_merge_gates.py +125 -0
  136. devagent_ai-0.8.6/tests/test_plc_rockwell_v9_reachable_writers.py +186 -0
  137. devagent_ai-0.8.6/tests/test_plc_siemens_v1.py +240 -0
  138. devagent_ai-0.8.6/tests/test_plc_siemens_v2.py +251 -0
  139. devagent_ai-0.8.6/tests/test_plc_siemens_v3_call_graph.py +636 -0
  140. devagent_ai-0.8.6/tests/test_plc_siemens_v4_extended.py +335 -0
  141. devagent_ai-0.8.6/tests/test_plc_siemens_v4_flgnet.py +412 -0
  142. devagent_ai-0.8.6/tests/test_plc_siemens_v5_state_machine.py +307 -0
  143. devagent_ai-0.8.6/tests/test_plc_siemens_v6_v7.py +415 -0
  144. devagent_ai-0.8.6/tests/test_plc_signature_trust.py +167 -0
  145. devagent_ai-0.8.6/tests/test_plc_v5_security_floor.py +101 -0
  146. devagent_ai-0.8.6/tests/test_plc_v5_toctou.py +116 -0
  147. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_production_v040.py +1 -1
  148. devagent_ai-0.8.4/devagent/__main__.py +0 -4
  149. devagent_ai-0.8.4/devagent_ai.egg-info/SOURCES.txt +0 -86
  150. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/LICENSE +0 -0
  151. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/NOTICE +0 -0
  152. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/__init__.py +0 -0
  153. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/llm.py +0 -0
  154. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/loop.py +0 -0
  155. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/memory.py +0 -0
  156. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/prompts.py +0 -0
  157. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/agent/tools.py +0 -0
  158. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/artifacts.py +0 -0
  159. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/automations.py +0 -0
  160. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/autonomy.py +0 -0
  161. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/browser.py +0 -0
  162. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/cli.py +0 -0
  163. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/config.py +0 -0
  164. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/discovery.py +0 -0
  165. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/evaluation.py +0 -0
  166. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/memory.py +0 -0
  167. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/models.py +0 -0
  168. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/orchestrator.py +0 -0
  169. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/provider_benchmark.py +0 -0
  170. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/providers.py +0 -0
  171. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/qualification.py +0 -0
  172. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/realworld.py +0 -0
  173. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/report.py +0 -0
  174. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/retrieval.py +0 -0
  175. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/routing.py +0 -0
  176. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/runtime.py +0 -0
  177. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/safety.py +0 -0
  178. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/skills.py +0 -0
  179. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/source_control.py +0 -0
  180. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/state_machine.py +0 -0
  181. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/tasking.py +0 -0
  182. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/technical_review.py +0 -0
  183. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/workspace.py +0 -0
  184. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent/worktree.py +0 -0
  185. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent_ai.egg-info/dependency_links.txt +0 -0
  186. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/devagent_ai.egg-info/top_level.txt +0 -0
  187. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/setup.cfg +0 -0
  188. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_acceptance_contract.py +0 -0
  189. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_benchmark_catalog.py +0 -0
  190. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_browser_verification.py +0 -0
  191. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_capability_discovery.py +0 -0
  192. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_cli.py +0 -0
  193. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_cli_progress.py +0 -0
  194. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_developer_review_report.py +0 -0
  195. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_discovery_memory.py +0 -0
  196. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_e2e_fake_provider.py +0 -0
  197. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_evaluation_harness.py +0 -0
  198. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_evaluation_matrix.py +0 -0
  199. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_evaluation_regression_evidence.py +0 -0
  200. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_functional_qualification.py +0 -0
  201. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_huge_monorepo_v070.py +0 -0
  202. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_migration_e2e_v070.py +0 -0
  203. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_model_routing.py +0 -0
  204. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_multilang_technical_review.py +0 -0
  205. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_multistack_devagent_e2e.py +0 -0
  206. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_multistack_qualification.py +0 -0
  207. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_plan_verification_normalization.py +0 -0
  208. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_preservation_contradiction.py +0 -0
  209. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_production_hardening.py +0 -0
  210. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_realworld_benchmark.py +0 -0
  211. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_requirement_compiler_v082.py +0 -0
  212. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_requirement_intelligence_v083.py +0 -0
  213. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_retrieval.py +0 -0
  214. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_runtime_sandbox.py +0 -0
  215. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_safety_workspace.py +0 -0
  216. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_source_control_publish.py +0 -0
  217. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_structural_devagent_e2e_v070.py +0 -0
  218. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_structural_operations.py +0 -0
  219. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_structured_provider_contract.py +0 -0
  220. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_tasking_state.py +0 -0
  221. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_v070_engineering_breadth.py +0 -0
  222. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_v080_autonomy.py +0 -0
  223. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_v080_provider_benchmark.py +0 -0
  224. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_v080_skills_automations.py +0 -0
  225. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_workspace_environment.py +0 -0
  226. {devagent_ai-0.8.4 → devagent_ai-0.8.6}/tests/test_worktree.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devagent-ai
3
- Version: 0.8.4
3
+ Version: 0.8.6
4
4
  Summary: Evidence-driven local autonomous software engineering agent
5
5
  Author: Tom Ha
6
6
  Maintainer: Tom Ha
@@ -9,6 +9,7 @@ Project-URL: Homepage, https://github.com/tomha85/devagent
9
9
  Project-URL: Repository, https://github.com/tomha85/devagent
10
10
  Project-URL: Issues, https://github.com/tomha85/devagent/issues
11
11
  Project-URL: Changelog, https://github.com/tomha85/devagent/blob/main/CHANGELOG.md
12
+ Project-URL: Sponsor, https://github.com/sponsors/tomha85
12
13
  Keywords: ai,agent,developer-tools,software-engineering,verification,local-first
13
14
  Classifier: Development Status :: 4 - Beta
14
15
  Classifier: Intended Audience :: Developers
@@ -23,6 +24,7 @@ License-File: LICENSE
23
24
  License-File: NOTICE
24
25
  Requires-Dist: openai>=1.40.0
25
26
  Requires-Dist: anthropic>=0.34.0
27
+ Requires-Dist: cryptography>=42.0.0
26
28
  Requires-Dist: tomli>=2.0.0; python_version < "3.11"
27
29
  Provides-Extra: dev
28
30
  Requires-Dist: pytest>=8.0; extra == "dev"
@@ -35,11 +37,14 @@ Dynamic: license-file
35
37
  [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/)
36
38
  [![Status: Beta](https://img.shields.io/badge/status-beta-blue.svg)](#project-status)
37
39
  [![Production CI](https://github.com/tomha85/devagent/actions/workflows/ci.yml/badge.svg)](https://github.com/tomha85/devagent/actions/workflows/ci.yml)
40
+ [![Sponsor DevAgent](https://img.shields.io/badge/Sponsor-DevAgent-EA4AAA?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/tomha85)
38
41
 
39
42
  **A local, evidence-driven software engineering agent that turns a requirement into a tested, independently reviewed patch, prints a developer-grade engineering report, and only publishes a branch when the result is `VERIFIED`.**
40
43
 
41
44
  > **From requirement to evidence-backed verified branch.**
42
45
 
46
+ > ❤️ **DevAgent is free during public beta.** If DevAgent saves you engineering time, consider [sponsoring continued development](https://github.com/sponsors/tomha85).
47
+
43
48
  DevAgent runs against a developer's local repository. It discovers the application, gathers source evidence, compiles explicit acceptance criteria, plans a bounded change, creates backups, implements the minimum necessary patch, runs repository-supported verification, independently reviews the final diff, and decides `VERIFIED`, `PARTIALLY_VERIFIED`, or `BLOCKED` from evidence rather than model confidence.
44
49
 
45
50
  For a normal verified run the deterministic harness prints the complete engineering report first, then commits reviewed paths and fast-forward pushes the developer's current non-protected branch. If the developer starts on `main`, `master`, or `trunk`, DevAgent creates a new safe branch instead. Runtime DevAgent never creates a pull request, merges, rebases, force-pushes, or deploys.
@@ -545,6 +550,23 @@ Remaining work is primarily **breadth and external validation**, not missing cor
545
550
 
546
551
  The project intentionally prioritizes trustworthy outcomes, reproducible evidence, and safe engineering behavior over feature count or unsupported "best agent" claims.
547
552
 
553
+ ## ❤️ Support DevAgent
554
+
555
+ DevAgent is currently free to use during public beta.
556
+
557
+ If DevAgent saves you engineering time or helps you deliver safer, better-verified software or PLC engineering work, you can support continued development through [GitHub Sponsors](https://github.com/sponsors/tomha85).
558
+
559
+ Your sponsorship helps fund:
560
+
561
+ - new engineering and PLC capabilities;
562
+ - Siemens and Rockwell verification;
563
+ - additional AI provider support;
564
+ - regression and production qualification;
565
+ - documentation and examples;
566
+ - continued free public releases.
567
+
568
+ [![Sponsor DevAgent](https://img.shields.io/badge/Sponsor-DevAgent-EA4AAA?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/tomha85)
569
+
548
570
  ## Contributing
549
571
 
550
572
  Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Changes to safety, verification, reporting, acceptance semantics, providers, or bounded publication behavior should include regression evidence and must not give model-generated actions unrestricted Git publishing authority.
@@ -4,11 +4,14 @@
4
4
  [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg)](https://www.python.org/)
5
5
  [![Status: Beta](https://img.shields.io/badge/status-beta-blue.svg)](#project-status)
6
6
  [![Production CI](https://github.com/tomha85/devagent/actions/workflows/ci.yml/badge.svg)](https://github.com/tomha85/devagent/actions/workflows/ci.yml)
7
+ [![Sponsor DevAgent](https://img.shields.io/badge/Sponsor-DevAgent-EA4AAA?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/tomha85)
7
8
 
8
9
  **A local, evidence-driven software engineering agent that turns a requirement into a tested, independently reviewed patch, prints a developer-grade engineering report, and only publishes a branch when the result is `VERIFIED`.**
9
10
 
10
11
  > **From requirement to evidence-backed verified branch.**
11
12
 
13
+ > ❤️ **DevAgent is free during public beta.** If DevAgent saves you engineering time, consider [sponsoring continued development](https://github.com/sponsors/tomha85).
14
+
12
15
  DevAgent runs against a developer's local repository. It discovers the application, gathers source evidence, compiles explicit acceptance criteria, plans a bounded change, creates backups, implements the minimum necessary patch, runs repository-supported verification, independently reviews the final diff, and decides `VERIFIED`, `PARTIALLY_VERIFIED`, or `BLOCKED` from evidence rather than model confidence.
13
16
 
14
17
  For a normal verified run the deterministic harness prints the complete engineering report first, then commits reviewed paths and fast-forward pushes the developer's current non-protected branch. If the developer starts on `main`, `master`, or `trunk`, DevAgent creates a new safe branch instead. Runtime DevAgent never creates a pull request, merges, rebases, force-pushes, or deploys.
@@ -514,6 +517,23 @@ Remaining work is primarily **breadth and external validation**, not missing cor
514
517
 
515
518
  The project intentionally prioritizes trustworthy outcomes, reproducible evidence, and safe engineering behavior over feature count or unsupported "best agent" claims.
516
519
 
520
+ ## ❤️ Support DevAgent
521
+
522
+ DevAgent is currently free to use during public beta.
523
+
524
+ If DevAgent saves you engineering time or helps you deliver safer, better-verified software or PLC engineering work, you can support continued development through [GitHub Sponsors](https://github.com/sponsors/tomha85).
525
+
526
+ Your sponsorship helps fund:
527
+
528
+ - new engineering and PLC capabilities;
529
+ - Siemens and Rockwell verification;
530
+ - additional AI provider support;
531
+ - regression and production qualification;
532
+ - documentation and examples;
533
+ - continued free public releases.
534
+
535
+ [![Sponsor DevAgent](https://img.shields.io/badge/Sponsor-DevAgent-EA4AAA?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/tomha85)
536
+
517
537
  ## Contributing
518
538
 
519
539
  Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Changes to safety, verification, reporting, acceptance semantics, providers, or bounded publication behavior should include regression evidence and must not give model-generated actions unrestricted Git publishing authority.
@@ -1,3 +1,3 @@
1
1
  """DevAgent: evidence-driven local software engineering automation."""
2
2
 
3
- __version__ = "0.8.4"
3
+ __version__ = "0.8.6"
@@ -0,0 +1,4 @@
1
+ from devagent.entrypoint import main
2
+
3
+ raise SystemExit(main())
4
+
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import Sequence
5
+
6
+
7
+ def main(argv: Sequence[str] | None = None) -> int:
8
+ """Route domain subcommands without changing the existing software CLI."""
9
+
10
+ arguments = list(sys.argv[1:] if argv is None else argv)
11
+ if len(arguments) >= 2 and arguments[0] == "plc" and arguments[1] == "inspect":
12
+ from devagent.plc.inspect_cli import main as plc_inspect_main
13
+
14
+ return plc_inspect_main(arguments[2:])
15
+ if arguments and arguments[0] == "plc":
16
+ from devagent.plc.cli import main as plc_main
17
+
18
+ return plc_main(arguments[1:])
19
+
20
+ from devagent.cli import main as software_main
21
+
22
+ return software_main(arguments)
@@ -0,0 +1,185 @@
1
+ """Vendor-neutral PLC engineering and production verification foundations for DevAgent."""
2
+
3
+ from devagent.plc import analysis as _analysis
4
+ from devagent.plc.rockwell_compare_hardening import install as _install_rockwell_compare_hardening
5
+ from devagent.plc.rockwell_alias_hardening import install as _install_rockwell_alias_hardening
6
+ from devagent.plc.rockwell_entrypoint_hardening import install as _install_rockwell_entrypoint_hardening
7
+ from devagent.plc.rockwell_st_v10 import install as _install_rockwell_st_v10
8
+
9
+ # Install fail-closed compare, alias, controller-entrypoint, and ST guards before
10
+ # production verification is imported. Every downstream Rockwell proof must
11
+ # share the same canonical writer identity and executable-entrypoint model.
12
+ _install_rockwell_compare_hardening()
13
+ _install_rockwell_alias_hardening()
14
+ _install_rockwell_entrypoint_hardening()
15
+ _install_rockwell_st_v10()
16
+
17
+ from devagent.plc.rockwell_compare_reachability_hardening import (
18
+ install as _install_rockwell_compare_reachability_hardening,
19
+ )
20
+
21
+ # The typed-compare theorem/FAT path is independent from boolean output-logic
22
+ # normalization, so explicitly bind it to the same executable routine closure.
23
+ _install_rockwell_compare_reachability_hardening()
24
+
25
+ from devagent.plc.rockwell_requirement_hardening import install as _install_rockwell_requirement_hardening
26
+ from devagent.plc.rockwell_v10_semantics import install as _install_rockwell_v10_semantics
27
+ from devagent.plc.rockwell_action_requirements import install as _install_rockwell_action_requirements
28
+ from devagent.plc.rockwell_risk_hardening import install as _install_rockwell_risk_hardening
29
+ from devagent.plc.rockwell_closeout_gate_hardening import install as _install_rockwell_closeout_gate_hardening
30
+
31
+ _install_rockwell_requirement_hardening()
32
+ # V10 extends the already-hardened V9 theorem. It proves bounded OTL/OTU action
33
+ # effects and may prove final retained scan state only inside the deliberately
34
+ # narrow same-active-Main-RLL-routine ordering theorem. Wider scheduling remains
35
+ # fail-closed until explicitly modeled.
36
+ _install_rockwell_v10_semantics()
37
+ # Explicit natural-language requirements may bind to deterministic MOV/COPY/
38
+ # CLR/RES local action effects, but never to final scan/process behavior.
39
+ _install_rockwell_action_requirements()
40
+ _install_rockwell_risk_hardening()
41
+ # Install the V9 support-contract guard before importing regression/production
42
+ # modules. Those modules import safe_analysis by value, so the patched support
43
+ # check must already be visible when safe_analysis is first loaded.
44
+ _install_rockwell_closeout_gate_hardening()
45
+
46
+ from devagent.plc.rockwell_core_review_v12 import install as _install_rockwell_core_review_v12
47
+
48
+ # V12 makes the commercial engineering-review contract explicit: cause/effect,
49
+ # unreachable logic, contradictory linear paths, and sequence-branch risks are
50
+ # deterministic review outputs. They remain evidence-backed findings, not AI
51
+ # guesses and not runtime PASS claims.
52
+ _install_rockwell_core_review_v12()
53
+
54
+ from devagent.plc.fat_procedure_v12 import install as _install_fat_procedure_v12
55
+
56
+ # Every FAT candidate, including tests created later by requirement mapping,
57
+ # must be an engineer-ready manual procedure. DevAgent plans the FAT; it does not
58
+ # connect to or execute the engineer's external simulator/HIL/controller.
59
+ _install_fat_procedure_v12()
60
+
61
+ from devagent.plc.rockwell_regression_evidence_hardening import (
62
+ install as _install_rockwell_regression_evidence_hardening,
63
+ install_domain_evidence as _install_rockwell_regression_domain_evidence,
64
+ )
65
+
66
+ _install_rockwell_regression_evidence_hardening()
67
+
68
+ from devagent.plc.rockwell_regression_case_compat_v12 import (
69
+ install as _install_rockwell_regression_case_compat_v12,
70
+ )
71
+
72
+ # FAT-plan regression is semantic and case-insensitive. Studio 5000 identifier
73
+ # spelling changes alone must not force a retest or create a false regression.
74
+ _install_rockwell_regression_case_compat_v12()
75
+
76
+ from devagent.plc.rockwell_branch_coverage_v16 import install as _install_rockwell_branch_coverage_v16
77
+
78
+ # V16 reconciles branch coverage with the full deterministic theorem set. A
79
+ # neutral-text branch proven by the bounded data/compute action theorem counts
80
+ # as modeled even when it is not an OTE/OTL/OTU boolean-output branch. Mixed or
81
+ # partially understood branch grammars remain fail-closed and withheld.
82
+ _install_rockwell_branch_coverage_v16()
83
+
84
+ from devagent.plc.rockwell_system_service_install_v17 import (
85
+ install as _install_rockwell_system_service_v17,
86
+ )
87
+
88
+ # V17 does not widen static proof. Reachable GSV/SSV system-service logic stays
89
+ # PARTIAL, but every such runtime-dependent gap receives an evidence-linked,
90
+ # engineer-executed FAT procedure and a specific commissioning risk. The install
91
+ # happens before production imports capture analysis/risk functions by value.
92
+ _install_rockwell_system_service_v17()
93
+
94
+ from devagent.plc.semantic_coverage_report import install as _install_semantic_coverage_report
95
+
96
+ # Ensure any later CLI import of render_production_report receives the
97
+ # reachability-aware semantic coverage augmentation.
98
+ _install_semantic_coverage_report()
99
+
100
+ from devagent.plc.rockwell_system_service_report_install_v17 import (
101
+ install as _install_rockwell_system_service_report_v17,
102
+ )
103
+
104
+ # Keep the public report renderer identity stable while adding an explicit V17
105
+ # system-service runtime boundary inside the semantic coverage section.
106
+ _install_rockwell_system_service_report_v17()
107
+
108
+ from devagent.plc.four_contract_v13 import install as _install_four_contract_v13
109
+
110
+ # V13 makes the commercial four-core contract explicit and testable:
111
+ # engineering analysis, logic/risk review, five-area optimization recommendations,
112
+ # and engineer-ready FAT planning. All optimization output is advisory only.
113
+ _install_four_contract_v13()
114
+
115
+ from devagent.plc.professional_report_install_v14 import install as _install_professional_report_v14
116
+
117
+ # V14 adds a customer-facing executive layer while preserving every detailed
118
+ # engineering/evidence section and the established public renderer identity.
119
+ # This is presentation-only: it cannot change deterministic verdicts/readiness.
120
+ _install_professional_report_v14()
121
+
122
+ from devagent.plc.report_clarity_install_v16 import install as _install_report_clarity_v16
123
+
124
+ # V16 clarifies project-only review and coverage terminology without changing
125
+ # deterministic engineering, risk, FAT, or release-readiness decisions.
126
+ _install_report_clarity_v16()
127
+
128
+ from devagent.plc.agent_harness_install_v15 import install as _install_agent_harness_v15
129
+
130
+ # V15 applies modern agent orchestration only to the probabilistic assistance
131
+ # layer: bounded propose/critic/revise graphs, deterministic evidence guards, and
132
+ # per-run trace capture. The PLC proof/risk/readiness core stays authoritative.
133
+ _install_agent_harness_v15()
134
+
135
+ from devagent.plc.siemens_integration_v1 import install as _install_siemens_integration_v1
136
+
137
+ # Siemens V1 is a vendor branch over the already-qualified production contract.
138
+ # It accepts offline TIA Portal Openness/XML and generated-source exports, proves
139
+ # only bounded top-level SCL semantics, and leaves control-flow/LAD/FBD/GRAPH/STL
140
+ # or protected behavior PARTIAL/OPAQUE. Qualified Rockwell dispatch still enters
141
+ # the exact guarded Rockwell analyzer above.
142
+ _install_siemens_integration_v1()
143
+
144
+ from devagent.plc.siemens_scl_control_flow_v2 import install as _install_siemens_scl_control_flow_v2
145
+
146
+ # Siemens V2 adds a deliberately bounded deterministic theorem for complete,
147
+ # single-level IF/ELSIF/ELSE Boolean assignment chains. Missing/incomplete branch
148
+ # assignments, nesting, CASE/loops, calls, cyclic/self-references, and unsupported
149
+ # expressions stay fail-closed and require engineer-executed FAT evidence.
150
+ _install_siemens_scl_control_flow_v2()
151
+
152
+ from devagent.plc.siemens_scl_control_flow_hardening_v2 import (
153
+ install as _install_siemens_scl_control_flow_hardening_v2,
154
+ )
155
+
156
+ # A syntactically complete inner IF is still nested control flow. Do not allow an
157
+ # inner chain to become independently FULL when its enclosing region is outside
158
+ # the V2 single-level theorem.
159
+ _install_siemens_scl_control_flow_hardening_v2()
160
+
161
+ from devagent.plc.production_v5 import run_production_verification_v5
162
+ from devagent.plc.siemens_v5_bindings_v1 import install as _install_siemens_v5_bindings_v1
163
+
164
+ # Agent Harness V15 loads Production V5 before Siemens integration. Refresh only
165
+ # V5's by-value shared production/evidence/review bindings after Siemens installs.
166
+ # Siemens then reaches the vendor dispatcher while Rockwell remains behind the
167
+ # exact qualified Rockwell functions selected by those vendor-aware wrappers.
168
+ _install_siemens_v5_bindings_v1()
169
+
170
+ # Production is now loaded; bind the stage-14 baseline evidence augmentation.
171
+ _install_rockwell_regression_domain_evidence()
172
+ from devagent.plc.safe_analysis import analyze_rockwell_l5x
173
+ from devagent.plc.plc_dispatch import analyze_plc_project
174
+ from devagent.plc.siemens_cli_install_v1 import install as _install_siemens_cli_v1
175
+
176
+ # CLI parsing is loaded only after production_v5 exists, avoiding circular
177
+ # imports while exposing both vendor input contracts through `devagent plc`.
178
+ _install_siemens_cli_v1()
179
+
180
+ # Keep existing imports from ``devagent.plc.analysis`` on the guarded Rockwell
181
+ # public path. The base module remains reusable by ``safe_analysis`` without
182
+ # recursive calls; vendor-neutral callers should use analyze_plc_project.
183
+ _analysis.analyze_rockwell_l5x = analyze_rockwell_l5x
184
+
185
+ __all__ = ["analyze_plc_project", "analyze_rockwell_l5x", "run_production_verification_v5"]
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Callable
4
+
5
+ from devagent.plc.agent_harness_v15 import begin_run_trace, end_run_trace
6
+ from devagent.plc import production_v5
7
+
8
+ _ORIGINAL: Callable[..., Any] = production_v5.run_production_verification_v5
9
+ _INSTALLED = False
10
+
11
+
12
+ def _run_with_harness_trace(*args: Any, **kwargs: Any):
13
+ trace, token = begin_run_trace()
14
+ try:
15
+ result = _ORIGINAL(*args, **kwargs)
16
+ result.ai_harness_trace = list(trace)
17
+ return result
18
+ finally:
19
+ end_run_trace(token)
20
+
21
+
22
+ def install() -> None:
23
+ global _INSTALLED
24
+ if _INSTALLED:
25
+ return
26
+ production_v5.run_production_verification_v5 = _run_with_harness_trace
27
+ _INSTALLED = True
@@ -0,0 +1,208 @@
1
+ from __future__ import annotations
2
+
3
+ from contextvars import ContextVar, Token
4
+ from typing import Any
5
+
6
+ from devagent.providers import ModelProvider
7
+
8
+ # The PLC agent harness is deliberately small and explicit. It is not part of the
9
+ # deterministic PLC proof engine. It only governs AI review candidates before
10
+ # they are admitted as AI_CANDIDATE observations.
11
+ MAX_REVIEW_ITERATIONS = 2
12
+ _ACTIVE_TRACE: ContextVar[list[dict[str, Any]] | None] = ContextVar(
13
+ "devagent_plc_agent_harness_trace",
14
+ default=None,
15
+ )
16
+
17
+ REVIEW_CRITIC_SCHEMA: dict[str, Any] = {
18
+ "type": "object",
19
+ "additionalProperties": False,
20
+ "required": ["decisions"],
21
+ "properties": {
22
+ "decisions": {
23
+ "type": "array",
24
+ "maxItems": 24,
25
+ "items": {
26
+ "type": "object",
27
+ "additionalProperties": False,
28
+ "required": ["finding_id", "decision", "reason", "supported_evidence_ids"],
29
+ "properties": {
30
+ "finding_id": {"type": "string", "minLength": 1},
31
+ "decision": {"type": "string", "enum": ["ACCEPT", "REVISE", "REJECT"]},
32
+ "reason": {"type": "string", "minLength": 1},
33
+ "supported_evidence_ids": {
34
+ "type": "array",
35
+ "maxItems": 8,
36
+ "items": {"type": "string", "minLength": 1},
37
+ },
38
+ },
39
+ },
40
+ }
41
+ },
42
+ }
43
+
44
+ REQUIREMENT_CRITIC_SCHEMA: dict[str, Any] = {
45
+ "type": "object",
46
+ "additionalProperties": False,
47
+ "required": ["decisions"],
48
+ "properties": {
49
+ "decisions": {
50
+ "type": "array",
51
+ "maxItems": 50,
52
+ "items": {
53
+ "type": "object",
54
+ "additionalProperties": False,
55
+ "required": ["requirement_id", "decision", "reason", "supported_evidence_ids"],
56
+ "properties": {
57
+ "requirement_id": {"type": "string", "minLength": 1},
58
+ "decision": {"type": "string", "enum": ["ACCEPT", "REJECT"]},
59
+ "reason": {"type": "string", "minLength": 1},
60
+ "supported_evidence_ids": {
61
+ "type": "array",
62
+ "maxItems": 8,
63
+ "items": {"type": "string", "minLength": 1},
64
+ },
65
+ },
66
+ },
67
+ }
68
+ },
69
+ }
70
+
71
+
72
+ def begin_run_trace() -> tuple[list[dict[str, Any]], Token[list[dict[str, Any]] | None]]:
73
+ sink: list[dict[str, Any]] = []
74
+ return sink, _ACTIVE_TRACE.set(sink)
75
+
76
+
77
+ def end_run_trace(token: Token[list[dict[str, Any]] | None]) -> None:
78
+ _ACTIVE_TRACE.reset(token)
79
+
80
+
81
+ def trace(
82
+ sink: list[dict[str, Any]] | None,
83
+ *,
84
+ graph: str,
85
+ node: str,
86
+ iteration: int,
87
+ outcome: str,
88
+ detail: str,
89
+ counts: dict[str, int] | None = None,
90
+ ) -> None:
91
+ target = sink if sink is not None else _ACTIVE_TRACE.get()
92
+ if target is None:
93
+ return
94
+ event: dict[str, Any] = {
95
+ "graph": graph,
96
+ "node": node,
97
+ "iteration": iteration,
98
+ "outcome": outcome,
99
+ "detail": detail,
100
+ }
101
+ if counts:
102
+ event["counts"] = dict(sorted(counts.items()))
103
+ target.append(event)
104
+
105
+
106
+ def critique_review_candidates(
107
+ provider: ModelProvider,
108
+ *,
109
+ candidates: list[dict[str, Any]],
110
+ evidence: list[dict[str, Any]],
111
+ iteration: int,
112
+ trace_sink: list[dict[str, Any]] | None,
113
+ ) -> dict[str, dict[str, Any]]:
114
+ if not candidates:
115
+ return {}
116
+ trace(
117
+ trace_sink,
118
+ graph="PLC_ENGINEERING_REVIEW",
119
+ node="CRITIC",
120
+ iteration=iteration,
121
+ outcome="START",
122
+ detail="Evaluate AI review candidates for evidence support, boundedness, and unsupported runtime/safety claims.",
123
+ counts={"candidates": len(candidates)},
124
+ )
125
+ response = provider.request(
126
+ role="plc_engineering_critic",
127
+ payload={
128
+ "instruction": (
129
+ "Act as an independent PLC review critic. Evaluate only the supplied candidate findings and evidence. "
130
+ "ACCEPT only when the finding is directly supported by its cited evidence and does not claim runtime behavior, safety certification, PASS, or release readiness. "
131
+ "Use REVISE when the core concern is supported but wording/claims overreach. REJECT unsupported findings. "
132
+ "supported_evidence_ids must be a subset of evidence actually supporting the candidate."
133
+ ),
134
+ "candidates": candidates,
135
+ "evidence": evidence,
136
+ },
137
+ schema=REVIEW_CRITIC_SCHEMA,
138
+ )
139
+ decisions = {
140
+ str(item["finding_id"]): item
141
+ for item in response.get("decisions", [])
142
+ if isinstance(item, dict) and item.get("finding_id")
143
+ }
144
+ trace(
145
+ trace_sink,
146
+ graph="PLC_ENGINEERING_REVIEW",
147
+ node="CRITIC",
148
+ iteration=iteration,
149
+ outcome="COMPLETE",
150
+ detail="Independent critic completed candidate evaluation.",
151
+ counts={
152
+ "accepted": sum(1 for item in decisions.values() if item.get("decision") == "ACCEPT"),
153
+ "revise": sum(1 for item in decisions.values() if item.get("decision") == "REVISE"),
154
+ "rejected": sum(1 for item in decisions.values() if item.get("decision") == "REJECT"),
155
+ },
156
+ )
157
+ return decisions
158
+
159
+
160
+ def critique_requirement_mappings(
161
+ provider: ModelProvider,
162
+ *,
163
+ mappings: list[dict[str, Any]],
164
+ evidence: list[dict[str, Any]],
165
+ iteration: int,
166
+ trace_sink: list[dict[str, Any]] | None,
167
+ ) -> dict[str, dict[str, Any]]:
168
+ if not mappings:
169
+ return {}
170
+ trace(
171
+ trace_sink,
172
+ graph="PLC_REQUIREMENT_MAPPING",
173
+ node="CRITIC",
174
+ iteration=iteration,
175
+ outcome="START",
176
+ detail="Evaluate AI requirement trace candidates without permitting verification promotion.",
177
+ counts={"mappings": len(mappings)},
178
+ )
179
+ response = provider.request(
180
+ role="plc_requirement_critic",
181
+ payload={
182
+ "instruction": (
183
+ "Evaluate only whether each proposed requirement-to-evidence trace candidate is plausibly supported by the supplied evidence. "
184
+ "Never declare VERIFIED, PASS, SAFE, compliant, or release-ready. ACCEPT only grounded traceability candidates; otherwise REJECT."
185
+ ),
186
+ "mappings": mappings,
187
+ "evidence": evidence,
188
+ },
189
+ schema=REQUIREMENT_CRITIC_SCHEMA,
190
+ )
191
+ decisions = {
192
+ str(item["requirement_id"]): item
193
+ for item in response.get("decisions", [])
194
+ if isinstance(item, dict) and item.get("requirement_id")
195
+ }
196
+ trace(
197
+ trace_sink,
198
+ graph="PLC_REQUIREMENT_MAPPING",
199
+ node="CRITIC",
200
+ iteration=iteration,
201
+ outcome="COMPLETE",
202
+ detail="Independent requirement critic completed mapping evaluation.",
203
+ counts={
204
+ "accepted": sum(1 for item in decisions.values() if item.get("decision") == "ACCEPT"),
205
+ "rejected": sum(1 for item in decisions.values() if item.get("decision") == "REJECT"),
206
+ },
207
+ )
208
+ return decisions