Commit ·
08381bd
1
Parent(s): 920fc45
Schema + executor: accept string shorthand for on_failure, edit_file returns content
Browse fileswork_block_schema.py: _FAILURE_HANDLER now uses oneOf — accepts both string
shorthands ("abort", "skip", "continue", etc.) and the full object form
{"action": "abort_block"}. Easier spec authoring without breaking existing specs.
spec_executor.py: _handle_failure normalizes string shorthands to dict at
entry so execution works regardless of which form the spec uses.
spec_executor.py: edit_file in _direct_filesystem_op now returns new file
content instead of a confirmation string, enabling contains/not_contains
validation checks on the result of an edit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- spec_executor.py +14 -2
- work_block_schema.py +21 -9
spec_executor.py
CHANGED
|
@@ -409,7 +409,7 @@ class SpecExecutor:
|
|
| 409 |
return {"status": "error", "error": f"old_text found {count} times in {path} — must be unique"}
|
| 410 |
new_content = content.replace(old_text, new_text, 1)
|
| 411 |
target.write_text(new_content, encoding="utf-8")
|
| 412 |
-
return
|
| 413 |
|
| 414 |
elif tool_name == "shell_execute":
|
| 415 |
import subprocess as _sp
|
|
@@ -504,7 +504,19 @@ class SpecExecutor:
|
|
| 504 |
# Failure handling
|
| 505 |
# ------------------------------------------------------------------
|
| 506 |
|
| 507 |
-
def _handle_failure(self, handler
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
action = handler["action"]
|
| 509 |
msg = handler.get("message", f"Step {step_id} failed")
|
| 510 |
|
|
|
|
| 409 |
return {"status": "error", "error": f"old_text found {count} times in {path} — must be unique"}
|
| 410 |
new_content = content.replace(old_text, new_text, 1)
|
| 411 |
target.write_text(new_content, encoding="utf-8")
|
| 412 |
+
return new_content
|
| 413 |
|
| 414 |
elif tool_name == "shell_execute":
|
| 415 |
import subprocess as _sp
|
|
|
|
| 504 |
# Failure handling
|
| 505 |
# ------------------------------------------------------------------
|
| 506 |
|
| 507 |
+
def _handle_failure(self, handler, step_id: str, ctx: ExecutionContext):
|
| 508 |
+
# Normalize string shorthand (e.g. "abort", "skip") to full dict form.
|
| 509 |
+
if isinstance(handler, str):
|
| 510 |
+
_shorthand_map = {
|
| 511 |
+
"abort": "abort_block",
|
| 512 |
+
"abort_block": "abort_block",
|
| 513 |
+
"continue": "skip",
|
| 514 |
+
"skip": "skip",
|
| 515 |
+
"retry": "retry",
|
| 516 |
+
"goto": "goto",
|
| 517 |
+
"escalate_to_qb": "escalate_to_qb",
|
| 518 |
+
}
|
| 519 |
+
handler = {"action": _shorthand_map.get(handler, "abort_block")}
|
| 520 |
action = handler["action"]
|
| 521 |
msg = handler.get("message", f"Step {step_id} failed")
|
| 522 |
|
work_block_schema.py
CHANGED
|
@@ -64,16 +64,28 @@ _CONDITION_CHECK = {
|
|
| 64 |
},
|
| 65 |
}
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
_FAILURE_HANDLER = {
|
| 68 |
-
"
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
}
|
| 78 |
|
| 79 |
_VALIDATION_BLOCK = {
|
|
|
|
| 64 |
},
|
| 65 |
}
|
| 66 |
|
| 67 |
+
# String shorthands accepted in on_failure for easier spec authoring.
|
| 68 |
+
# Executor normalizes these to the full object form before acting on them.
|
| 69 |
+
_FAILURE_SHORTHANDS = ["abort", "abort_block", "continue", "skip", "retry", "goto", "escalate_to_qb"]
|
| 70 |
+
|
| 71 |
_FAILURE_HANDLER = {
|
| 72 |
+
"oneOf": [
|
| 73 |
+
{
|
| 74 |
+
"type": "string",
|
| 75 |
+
"enum": _FAILURE_SHORTHANDS,
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"type": "object",
|
| 79 |
+
"required": ["action"],
|
| 80 |
+
"additionalProperties": False,
|
| 81 |
+
"properties": {
|
| 82 |
+
"action": {"enum": _FAILURE_ACTIONS},
|
| 83 |
+
"max_retries": {"type": "integer", "minimum": 0, "default": 0},
|
| 84 |
+
"goto_step": {"type": "string"},
|
| 85 |
+
"message": {"type": "string"},
|
| 86 |
+
},
|
| 87 |
+
},
|
| 88 |
+
]
|
| 89 |
}
|
| 90 |
|
| 91 |
_VALIDATION_BLOCK = {
|