devflow-engine 1.2.1__py3-none-any.whl → 1.2.2__py3-none-any.whl

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.
@@ -151,6 +151,34 @@ def _proof_candidate(verification: dict[str, Any] | None) -> dict[str, Any]:
151
151
  return {}
152
152
 
153
153
 
154
+ def _observation_fix_proof(context: dict[str, Any]) -> dict[str, Any]:
155
+ build_observability = context.get("BuildObservability")
156
+ if not isinstance(build_observability, dict):
157
+ return {}
158
+ output = build_observability.get("output")
159
+ if not isinstance(output, dict):
160
+ return {}
161
+ observation = output.get("observation")
162
+ if not isinstance(observation, dict):
163
+ return {}
164
+ proof = observation.get("fix_proof")
165
+ return proof if isinstance(proof, dict) else {}
166
+
167
+
168
+ def _verification_with_observed_fix_proof(
169
+ verification: dict[str, Any] | None,
170
+ context: dict[str, Any],
171
+ ) -> dict[str, Any] | None:
172
+ if _proof_candidate(verification):
173
+ return verification
174
+ observed_proof = _observation_fix_proof(context)
175
+ if not observed_proof:
176
+ return verification
177
+ merged = dict(verification or {})
178
+ merged["fix_proof"] = observed_proof
179
+ return merged
180
+
181
+
154
182
  def _resolve_artifact_path(repo_root: Path, artifact_path: Any) -> Path | None:
155
183
  raw = str(artifact_path or "").strip()
156
184
  if not raw:
@@ -1138,6 +1166,10 @@ class ResolveNode(Node):
1138
1166
  error_task_id = task_context.event.error_task_id
1139
1167
 
1140
1168
  verification = task_context.metadata.get("verification")
1169
+ effective_verification = _verification_with_observed_fix_proof(
1170
+ verification if isinstance(verification, dict) else None,
1171
+ context,
1172
+ )
1141
1173
  # Red-before-fix invariant: ResolveNode refuses to mark resolved
1142
1174
  # unless BuildObservability persisted observable=True at intake.
1143
1175
  # Closes the "already-green-at-intake" leak — a green-gate True with
@@ -1147,14 +1179,14 @@ class ResolveNode(Node):
1147
1179
  if isinstance(bo, dict):
1148
1180
  bo_out = bo.get("output") if isinstance(bo.get("output"), dict) else {}
1149
1181
  observation_was_red = bool(bo_out.get("observable"))
1150
- green_gate = bool((verification or {}).get("green_gate"))
1182
+ green_gate = bool((effective_verification or {}).get("green_gate"))
1151
1183
  proof_verified = True
1152
1184
  fix_proof: dict[str, Any] | None = None
1153
1185
  proof_failure_reason: str | None = None
1154
1186
  if _ui_proof_required(context):
1155
1187
  proof_verified, fix_proof, proof_failure_reason = _validate_ui_fix_proof(
1156
1188
  repo_root=persistor.repo_root,
1157
- verification=verification if isinstance(verification, dict) else None,
1189
+ verification=effective_verification if isinstance(effective_verification, dict) else None,
1158
1190
  )
1159
1191
  verified = green_gate and observation_was_red and proof_verified
1160
1192
  runtime_context = context.get("runtimeContext") if isinstance(context.get("runtimeContext"), dict) else None
@@ -1165,13 +1197,13 @@ class ResolveNode(Node):
1165
1197
  fingerprint = runtime_context.get("fingerprint") or current_record.get("fingerprint")
1166
1198
  title = context.get("metadata", {}).get("title") if isinstance(context.get("metadata"), dict) else None
1167
1199
 
1168
- resolve_output: dict[str, Any] = {"verification": verification, "verified": verified}
1200
+ resolve_output: dict[str, Any] = {"verification": effective_verification, "verified": verified}
1169
1201
  if proof_failure_reason:
1170
1202
  resolve_output["proof_failure_reason"] = proof_failure_reason
1171
1203
  if fix_proof:
1172
1204
  resolve_output["fix_proof"] = fix_proof
1173
1205
  persistor.persist(context=context, node_name="Resolve", output=resolve_output)
1174
- self.save_output(ResolveNode.OutputType(verified=verified, verification=verification))
1206
+ self.save_output(ResolveNode.OutputType(verified=verified, verification=effective_verification))
1175
1207
 
1176
1208
  if verified:
1177
1209
  if fix_proof:
@@ -1185,7 +1217,7 @@ class ResolveNode(Node):
1185
1217
  persistor.repo_root,
1186
1218
  error_task_id=error_task_id,
1187
1219
  title=str(title) if title is not None else None,
1188
- verification=verification,
1220
+ verification=effective_verification if isinstance(effective_verification, dict) else None,
1189
1221
  )
1190
1222
  task_context.metadata["commit_result"] = commit_result
1191
1223
  # v1.1.19: persist resolution_commit_sha + portal_token so the
@@ -1228,7 +1260,7 @@ class ResolveNode(Node):
1228
1260
  outcome=str(task_context.metadata.get("outcome") or "in_progress"),
1229
1261
  title=str(title) if title is not None else None,
1230
1262
  fingerprint=str(fingerprint) if fingerprint is not None else None,
1231
- verification=verification,
1263
+ verification=effective_verification if isinstance(effective_verification, dict) else None,
1232
1264
  reason=str(task_context.metadata.get("reason")) if task_context.metadata.get("reason") else None,
1233
1265
  context_path=persistor.context_path,
1234
1266
  runtime_context=runtime_context,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devflow-engine
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: DevFlow v2 CLI-first engine (projects, stories, execution store, review packets)
5
5
  Author: DevFlow
6
6
  License: Proprietary
@@ -32,7 +32,7 @@ devflow_engine/devin2/agent_definition.py,sha256=pCp915tojwPlepRpvjlU1DoPuT_anxR
32
32
  devflow_engine/devin2/pi_runner.py,sha256=xRl-qA3RgMFgiR5fnG6fTwwL95PMk6zVdRdFa-fXy2E,7466
33
33
  devflow_engine/error/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  devflow_engine/error/remediation.py,sha256=Z4LJQzZPzb7_6tea_XtasDvFYQiEdpkFlyxoCEO1I2k,548
35
- devflow_engine/errors/error_solver_dag.py,sha256=9SQT74F485gJvN0h0fXojd6kGU4YJxt2g4tsio9LKCQ,58180
35
+ devflow_engine/errors/error_solver_dag.py,sha256=U7n6pgt95SIePgFDPNMp_OFOW8Eq0Nyw29Kjf7XBf9E,59446
36
36
  devflow_engine/errors/question_classifier.py,sha256=oBJ29hszG--TUna62BQHnNmi6hPwf-wEE8eGLmgS624,9729
37
37
  devflow_engine/errors/repo_quality_judge.py,sha256=LVBaXN6AsID-x8qb-IriQKYY1c9AMMRNo-tWMeiuMaA,9962
38
38
  devflow_engine/errors/runtime_observability.py,sha256=Do93Ah3vxLEocYtC0JpnRIRQN6uNAOkYjBz0pmOqg5g,29719
@@ -382,7 +382,7 @@ devflow_engine/prompts/source_doc_mutation/source_doc_enrichment_coherence/promp
382
382
  devflow_engine/prompts/source_doc_mutation/user_workflows/prompt.md,sha256=2Bv-EkZwzxtPSsDGdw9YuuuzT1c_2R9c6HPSMdP-MD0,406
383
383
  devflow_engine/prompts/source_scope/doctrine/prompt.md,sha256=AJk1gfePTdaBSw5DHvCr7Sigsk2orGaRVNZ3Dj3NdcQ,837
384
384
  devflow_engine/prompts/ui_grounding/doctrine/prompt.md,sha256=0L5y-QjjquPABqxAHZNPkcjyHMZQSDRVncNDQa2app0,409
385
- devflow_engine-1.2.1.dist-info/METADATA,sha256=y30DsM64igxG19kjixCV0h-RN0NbLptfTWThXz4AbXQ,7755
386
- devflow_engine-1.2.1.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
387
- devflow_engine-1.2.1.dist-info/entry_points.txt,sha256=U5Pw4y4v4u4xcRS5DbXfemBg0RKp74kMxcnEoL0MACY,99
388
- devflow_engine-1.2.1.dist-info/RECORD,,
385
+ devflow_engine-1.2.2.dist-info/METADATA,sha256=gs_L91c1G3EHidj1wi52bGWurkduxKak2V5DlW2yKdM,7755
386
+ devflow_engine-1.2.2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
387
+ devflow_engine-1.2.2.dist-info/entry_points.txt,sha256=U5Pw4y4v4u4xcRS5DbXfemBg0RKp74kMxcnEoL0MACY,99
388
+ devflow_engine-1.2.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.30.1
2
+ Generator: hatchling 1.31.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any