Skip to content

Per-task failure tolerance: on_failure: continue (#23 C2) - #40

Open
minerva-sky wants to merge 4 commits into
codenamev:mainfrom
minerva-sky:feature/on-failure-continue
Open

minerva-sky wants to merge 4 commits into
codenamev:mainfrom
minerva-sky:feature/on-failure-continue

Conversation

@minerva-sky

Copy link
Copy Markdown
Collaborator

Implements C2 from #23 (design in the research comment there). Stacked on #38, so the diff shows the #20 series until that merges; the new commit is e2ff6f2.

What

  • TaskDefinition#on_failure: "skip_dependents" (default) or "continue". Serialized only when non-default, so flat plans keep their shape; unknown values raise.
  • PlanOrchestrator#add_task(..., on_failure:): same policy per task. When a continue task fails terminally, its dependents are scheduled instead of skipped. A dependency counts as met when it completed or its failure was tolerated.
  • Task#succeeded?(dep) / Task#failure_of(dep) and NamedOutputs#succeeded? / #failure_of: dependents can branch on the failure. output_of stays nil, so tasks that ignore the flag see no change.
  • Planner schema gains an on_failure enum plus one prompt instruction; unknown values from the LLM fall back to the default with a warning.
  • Both CLI execution paths pass the flag through (build_task_graph now yields a 4-tuple).

Guard rails

  • Retries run first; continue only applies once the task is still :failed.
  • Intervention-required failures never continue: a human is already in the loop.
  • A skip_dependents task between a tolerated failure and its own dependents still skips downstream.
  • overall_status stays :partial_failure. Hiding a tolerated failure from the result would be lying to the journal.

Tests

19 new examples (5 TaskDefinition, 2 NamedOutputs, 7 orchestrator, 1 planner, CLI expectations updated). 87/0 across the touched files; standardrb clean. CHANGELOG under Unreleased/Added. VERSION bump left to the maintainer.

Not in v1: tolerated-error predicates and a plan-level default, per the #23 note.

🤖 Generated with Claude Code

minerva-sky and others added 4 commits September 14, 2026 15:07
TaskDefinition gains optional id, depends_on and needs; ExecutionPlan
gains from_hash and validate! (duplicate ids, dangling references,
self-dependency, cycles). All additive: flat plans serialize and load
unchanged. First of three staged PRs for codenamev#20.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
TaskPlanner's structured-output schema now asks for a plan-local id,
a depends_on list and needs wiring on every task, and the prompt tells
the model what each is for. needs travels as {name, task} pairs since
strict schemas cannot describe a free-form object; the parser folds
them into the hash TaskDefinition stores. Malformed edges are dropped
with a warning. After parsing, the plan is run through
ExecutionPlan#validate! and any dangling reference or cycle is logged,
with the edges kept so the plan stays inspectable and editable.

Part 2 of 3 for codenamev#20 (stacked on codenamev#35).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…v#20, part 3 of 3)

Both execution paths (`agentic plan --execute` and `agentic execute --plan`)
now build tasks through one helper that resolves the plan-local ids in
`depends_on` and `needs` to the Task objects it just built, then hands
each task to `PlanOrchestrator#add_task` with its edges. Dependents wait
for their upstream and receive its output under the declared name; flat
plans still run as an unordered swarm, exactly as before.

A plan whose graph cannot be scheduled (dangling id, cycle) fails fast
with the validator's message rather than executing anyway. The
non-quiet summary reports the edge count alongside the task count.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
TaskDefinition and PlanOrchestrator#add_task accept on_failure:
(skip_dependents, the default, or continue). A continue task that fails
for good no longer skips its dependents; they run and can branch on
Task#succeeded? / Task#failure_of (and needs.succeeded? / failure_of for
named inputs) while output_of stays nil. Retries still run first,
intervention-required failures never continue, and the plan status
stays :partial_failure. The planner schema asks the LLM for the flag
and both CLI execution paths pass it through.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@minerva-sky

Copy link
Copy Markdown
Collaborator Author

Diagnosis of the red Ruby 3.2.4 job: it isn't a nil / version split. Both failing logs show a dependency UUID coming back as [REDACTED_PHONE], which is the Sanitizer phone-regex over-match that #54 fixes (#54). 3.4 passing is coincidence of which UUID got generated. Plan: once #54 lands, merge main into this branch and CI should go green with no changes here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

loop:self Forward-thinking improvement loop (WORLD.md-aligned)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant