Spaces:
Paused
Paused
fix: allow write_file during APP_STARTING so agents can fix stuck startups
Browse filesAPP_STARTING was incorrectly grouped with BUILDING/RESTARTING in
write-blocking guards. During BUILDING, writes reset the build. But
during APP_STARTING, writes trigger a NEW build β which is exactly
what agents need to fix a stuck startup (e.g. wrong entrypoint,
blocking restore script, missing deps).
This caused agents to diagnose the problem correctly but be unable
to apply fixes, wasting entire grace periods on read-only diagnostics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- scripts/conversation-loop.py +10 -8
scripts/conversation-loop.py
CHANGED
|
@@ -544,8 +544,9 @@ def parse_and_execute_actions(raw_text, depth=0):
|
|
| 544 |
"Writing the same file twice wastes a rebuild cycle.")
|
| 545 |
results.append({"action": key, "result": result})
|
| 546 |
print(f"[BLOCKED] {key} β duplicate write this cycle")
|
| 547 |
-
# Guard: block write_file during BUILDING/
|
| 548 |
-
|
|
|
|
| 549 |
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. "
|
| 550 |
"Writing to Space during build RESETS the entire build from scratch. "
|
| 551 |
"Wait for it to finish, then try again.")
|
|
@@ -598,10 +599,11 @@ def parse_and_execute_actions(raw_text, depth=0):
|
|
| 598 |
if len(results) >= MAX_ACTIONS_PER_TURN:
|
| 599 |
break
|
| 600 |
|
| 601 |
-
# Block restart/write when Cain is building/
|
| 602 |
-
|
|
|
|
| 603 |
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. "
|
| 604 |
-
"Do NOT restart or make changes β wait for it to finish
|
| 605 |
"Every write_file during build RESETS the entire build from scratch. "
|
| 606 |
"Use [ACTION: check_health] to monitor progress.")
|
| 607 |
results.append({"action": action_str, "result": result})
|
|
@@ -692,10 +694,10 @@ def parse_and_execute_actions(raw_text, depth=0):
|
|
| 692 |
break
|
| 693 |
|
| 694 |
# Apply same blocking rules
|
| 695 |
-
if child_state["stage"] in ("BUILDING", "RESTARTING"
|
| 696 |
-
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. Wait for it to finish
|
| 697 |
results.append({"action": action_str, "result": result})
|
| 698 |
-
print(f"[BLOCKED
|
| 699 |
break
|
| 700 |
|
| 701 |
# Rebuild cooldown (emoji parser)
|
|
|
|
| 544 |
"Writing the same file twice wastes a rebuild cycle.")
|
| 545 |
results.append({"action": key, "result": result})
|
| 546 |
print(f"[BLOCKED] {key} β duplicate write this cycle")
|
| 547 |
+
# Guard: block write_file during BUILDING/RESTARTING (would reset build)
|
| 548 |
+
# APP_STARTING is allowed β writing triggers a new build which may fix the stuck state
|
| 549 |
+
elif target == "space" and child_state["stage"] in ("BUILDING", "RESTARTING"):
|
| 550 |
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. "
|
| 551 |
"Writing to Space during build RESETS the entire build from scratch. "
|
| 552 |
"Wait for it to finish, then try again.")
|
|
|
|
| 599 |
if len(results) >= MAX_ACTIONS_PER_TURN:
|
| 600 |
break
|
| 601 |
|
| 602 |
+
# Block restart/write when Cain is building/restarting β would reset build
|
| 603 |
+
# APP_STARTING is allowed so agents can fix stuck startups
|
| 604 |
+
if child_state["stage"] in ("BUILDING", "RESTARTING") and name in ("restart", "write_file", "set_env", "set_secret"):
|
| 605 |
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. "
|
| 606 |
+
"Do NOT restart or make changes β wait for it to finish. "
|
| 607 |
"Every write_file during build RESETS the entire build from scratch. "
|
| 608 |
"Use [ACTION: check_health] to monitor progress.")
|
| 609 |
results.append({"action": action_str, "result": result})
|
|
|
|
| 694 |
break
|
| 695 |
|
| 696 |
# Apply same blocking rules
|
| 697 |
+
if child_state["stage"] in ("BUILDING", "RESTARTING") and name in ("restart", "write_file", "set_env", "set_secret"):
|
| 698 |
+
result = (f"β BLOCKED: Cain is currently {child_state['stage']}. Wait for it to finish. Writing during build RESETS it.")
|
| 699 |
results.append({"action": action_str, "result": result})
|
| 700 |
+
print(f"[BLOCKED] sub-agent {name} β Cain is {child_state['stage']}")
|
| 701 |
break
|
| 702 |
|
| 703 |
# Rebuild cooldown (emoji parser)
|