Skip to content

Add Parallel Step Scheduling Rule to Sous-Chef Prompt#463

Merged
Trecek merged 1 commit intointegrationfrom
add-parallel-step-scheduling-rule-to-sous-chef-prompt/461
Mar 21, 2026
Merged

Add Parallel Step Scheduling Rule to Sous-Chef Prompt#463
Trecek merged 1 commit intointegrationfrom
add-parallel-step-scheduling-rule-to-sous-chef-prompt/461

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented Mar 21, 2026

Summary

Adds a PARALLEL STEP SCHEDULING — MANDATORY section to src/autoskillit/skills/sous-chef/SKILL.md that codifies the wavefront scheduling rule: when running multiple pipelines in parallel, all fast steps (MCP tool calls completing in seconds) across ALL pipelines must be completed before any slow step (run_skill, which launches headless sessions taking minutes) is launched. Slow steps are then batched and launched together so they overlap in wall-clock time. Additionally, adds a run_mode ingredient (default: sequential, option: parallel) to the implementation and remediation bundled recipes.

Requirements

PROMPT

  • REQ-PROMPT-001: The sous-chef SKILL.md must contain a PARALLEL STEP SCHEDULING section that is marked MANDATORY.
  • REQ-PROMPT-002: The section must define fast steps as MCP tool calls that complete in seconds: run_cmd, clone_repo, create_unique_branch, fetch_github_issue, claim_issue, merge_worktree, test_check, reset_test_dir, classify_fix.
  • REQ-PROMPT-003: The section must define slow steps as any run_skill invocation.
  • REQ-PROMPT-004: The section must instruct the orchestrator to complete all fast steps for ALL pipelines before launching any slow step.
  • REQ-PROMPT-005: The section must instruct the orchestrator to launch all slow steps together in one parallel batch once all pipelines are aligned at a slow step boundary.
  • REQ-PROMPT-006: The section must explicitly prohibit launching a slow step for one pipeline while another pipeline still has fast steps pending.
  • REQ-PROMPT-007: The section must explain the wall-clock rationale: batched rounds wait for the slowest step, so fast steps that finish instantly idle until the slow step completes.
  • REQ-PROMPT-008: The section must be placed after the existing MULTIPLE ISSUES section in the SKILL.md file.

INGREDIENT

  • REQ-INGREDIENT-001: Recipes that support multi-issue execution (e.g., implementation, remediation) must declare a run_mode ingredient with options sequential (default) and parallel.
  • REQ-INGREDIENT-002: The default value for run_mode must be sequential — parallel execution requires explicit opt-in.
  • REQ-INGREDIENT-003: When run_mode: parallel is set, the orchestrator must apply the wavefront scheduling rule from REQ-PROMPT-004 through REQ-PROMPT-006.
  • REQ-INGREDIENT-004: When run_mode: sequential is set (or defaulted), the orchestrator must process issues one at a time in the order provided.
  • REQ-INGREDIENT-005: The run_mode ingredient must be respected regardless of what the user says at runtime — if the user overrides verbally (e.g., says "run in parallel"), the verbal instruction takes precedence per the existing MULTIPLE ISSUES sous-chef rule.

Architecture Impact

Process Flow Diagram

%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 60, 'curve': 'basis'}}}%%
flowchart TB
    %% CLASS DEFINITIONS %%
    classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;
    classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff;
    classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff;
    classDef newComponent fill:#2e7d32,stroke:#81c784,stroke-width:2px,color:#fff;
    classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff;

    START([START: N issues submitted])

    subgraph ModeSelect ["● Mode Selection (MULTIPLE ISSUES + run_mode)"]
        direction TB
        MODE{"run_mode or<br/>user intent?"}
        SEQ["Sequential Mode<br/>━━━━━━━━━━<br/>Process one issue at a time<br/>in provided order"]
        PAR["Parallel Mode Selected<br/>━━━━━━━━━━<br/>Launch N independent pipelines<br/>apply wavefront scheduling"]
    end

    subgraph FastDrain ["★ Fast-Step Drain (PARALLEL STEP SCHEDULING)"]
        direction TB
        INSPECT["● Inspect next pending step<br/>━━━━━━━━━━<br/>for each of N pipelines"]
        HAS_FAST{"Any pipeline has<br/>a fast step pending?"}
        RUN_FAST["★ Execute all fast steps<br/>━━━━━━━━━━<br/>run_cmd · clone_repo<br/>create_unique_branch<br/>fetch_github_issue<br/>claim_issue · merge_worktree<br/>test_check · reset_test_dir<br/>classify_fix"]
    end

    subgraph SlowBatch ["★ Slow-Step Batch (PARALLEL STEP SCHEDULING)"]
        direction TB
        ALL_SLOW["★ All pipelines at slow boundary<br/>━━━━━━━━━━<br/>every next step is run_skill"]
        LAUNCH["★ Launch all slow steps together<br/>━━━━━━━━━━<br/>run_skill × N in parallel<br/>wall-clock time overlaps"]
        WAIT["Wait for batch completion<br/>━━━━━━━━━━<br/>bounded by slowest session"]
    end

    DONE_CHECK{"All pipelines<br/>complete?"}
    DONE([DONE: all N pipelines finished])

    START --> MODE
    MODE -->|"sequential / run_mode=sequential"| SEQ
    MODE -->|"parallel / run_mode=parallel"| PAR
    PAR --> INSPECT
    INSPECT --> HAS_FAST
    HAS_FAST -->|"YES — drain fast steps"| RUN_FAST
    RUN_FAST -->|"re-inspect after batch"| INSPECT
    HAS_FAST -->|"NO — all aligned at slow step"| ALL_SLOW
    ALL_SLOW --> LAUNCH
    LAUNCH --> WAIT
    WAIT --> DONE_CHECK
    DONE_CHECK -->|"more steps remain"| INSPECT
    DONE_CHECK -->|"all finished"| DONE
    SEQ --> DONE

    class START,DONE terminal;
    class MODE detector;
    class SEQ,PAR stateNode;
    class INSPECT phase;
    class HAS_FAST detector;
    class RUN_FAST newComponent;
    class ALL_SLOW,LAUNCH newComponent;
    class WAIT handler;
    class DONE_CHECK detector;
Loading

Color Legend:

Color Category Description
Dark Blue Terminal Start and end states
Red Detector Decision points and routing guards
Teal State Mode selection outcomes
Purple Phase Step inspection / control flow
Green (★) New Component New scheduling logic added by this PR
Orange Handler Wait / synchronization (bounded by slowest)

State Lifecycle Diagram

%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 60, 'curve': 'basis'}}}%%
flowchart TB
    %% CLASS DEFINITIONS %%
    classDef cli fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;
    classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff;
    classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff;
    classDef newComponent fill:#2e7d32,stroke:#81c784,stroke-width:2px,color:#fff;
    classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff;
    classDef output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff;
    classDef gap fill:#ff6f00,stroke:#ffa726,stroke-width:2px,color:#000;
    classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff;

    START([START: load_recipe called])

    subgraph IngredientDecl ["● Ingredient Declaration (INIT_ONLY)"]
        direction TB
        IMPL_YAML["● implementation.yaml<br/>━━━━━━━━━━<br/>run_mode:<br/>  default: sequential"]
        REMED_YAML["● remediation.yaml<br/>━━━━━━━━━━<br/>run_mode:<br/>  default: sequential"]
        OVERRIDE["override dict<br/>━━━━━━━━━━<br/>caller may pass<br/>run_mode=parallel"]
    end

    subgraph StructValidation ["Structural Validation Gates"]
        direction TB
        PRESENCE["ingredient presence check<br/>━━━━━━━━━━<br/>referenced names must<br/>be declared in recipe"]
        NO_ENUM["gap: no value validation<br/>━━━━━━━━━━<br/>sequential/parallel NOT<br/>enforced by schema"]
    end

    subgraph ActiveRecipe ["Resolved Ingredient State (INIT_ONLY after this point)"]
        direction TB
        RESOLVED["run_mode resolved<br/>━━━━━━━━━━<br/>sequential (default)<br/>OR parallel (override)"]
    end

    subgraph PromptContract ["● sous-chef SKILL.md Contract (reads run_mode)"]
        direction TB
        SKILL_READ["● PARALLEL STEP SCHEDULING<br/>━━━━━━━━━━<br/>reads run_mode at runtime<br/>applies wavefront rule if parallel"]
    end

    subgraph ContractTests ["★ Contract Enforcement (new test suite)"]
        direction TB
        SCHED_TESTS["★ test_sous_chef_scheduling.py<br/>━━━━━━━━━━<br/>REQ-PROMPT-001..008<br/>asserts section present + correct"]
        INGRED_TESTS["● TestRunModeIngredient<br/>━━━━━━━━━━<br/>REQ-INGREDIENT-001..005<br/>asserts run_mode declared + default"]
    end

    DONE([Orchestrator applies scheduling rule])

    START --> IMPL_YAML
    START --> REMED_YAML
    OVERRIDE --> RESOLVED
    IMPL_YAML --> PRESENCE
    REMED_YAML --> PRESENCE
    PRESENCE --> NO_ENUM
    NO_ENUM --> RESOLVED
    RESOLVED --> SKILL_READ
    SKILL_READ --> DONE

    SCHED_TESTS -.->|"enforces contract on"| SKILL_READ
    INGRED_TESTS -.->|"enforces contract on"| IMPL_YAML
    INGRED_TESTS -.->|"enforces contract on"| REMED_YAML

    class START,DONE terminal;
    class IMPL_YAML,REMED_YAML handler;
    class OVERRIDE phase;
    class PRESENCE stateNode;
    class NO_ENUM gap;
    class RESOLVED detector;
    class SKILL_READ handler;
    class SCHED_TESTS newComponent;
    class INGRED_TESTS newComponent;
Loading

Color Legend:

Color Category Description
Dark Blue Terminal Start and end states
Orange Handler Recipe YAML definitions and prompt reads
Purple Phase Caller-supplied override
Teal Gate Structural validation (presence check)
Yellow Gap Missing value constraint (no enum enforcement)
Red Resolved INIT_ONLY state after resolution — never mutated
Green (★) New Component New contract tests added by this PR

Closes #461

Implementation Plan

Plan file: temp/make-plan/add_parallel_step_scheduling_rule_plan_2026-03-21_085800.md

Token Usage Summary

No token data available for this pipeline run.

🤖 Generated with Claude Code via AutoSkillit

…ode ingredient to recipes

- Adds PARALLEL STEP SCHEDULING — MANDATORY section to sous-chef/SKILL.md with
  wavefront scheduling rule: drain all fast MCP steps across every pipeline before
  launching any slow run_skill batch; launch all slow steps together in one parallel
  batch so they overlap in wall-clock time
- Adds run_mode ingredient (default: sequential, option: parallel) to
  implementation.yaml and remediation.yaml bundled recipes
- Adds tests/contracts/test_sous_chef_scheduling.py with 13 contract tests
  verifying section presence, placement, fast/slow step enumeration, prohibition
  language, batch-launch instruction, and wall-clock rationale
- Adds TestRunModeIngredient class to tests/recipe/test_bundled_recipes.py with
  6 tests covering run_mode in both implementation and remediation recipes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit PR Review — Verdict: changes_requested

assert multiple_issues_pos != -1, "MULTIPLE ISSUES section must exist in sous-chef SKILL.md"
assert scheduling_pos != -1, "PARALLEL STEP SCHEDULING section must exist"
assert scheduling_pos > multiple_issues_pos, (
"PARALLEL STEP SCHEDULING section must appear after MULTIPLE ISSUES section"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[critical] bugs: NameError: variable scheduling_pos is referenced on lines 120-121 but never defined. The function assigns section_start = text.find("PARALLEL STEP SCHEDULING") at L116 but then uses scheduling_pos which does not exist — this will raise NameError at runtime.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. scheduling_pos is defined on line 116 (scheduling_pos = text.find("PARALLEL STEP SCHEDULING")) — 4 lines before its first use at line 118. The reviewer confused this function's variable naming (scheduling_pos/multiple_issues_pos) with the section_start pattern used in sibling tests. The code is correct and no NameError occurs.

assert "PARALLEL STEP SCHEDULING" in text, (
"sous-chef SKILL.md must contain a PARALLEL STEP SCHEDULING section"
)
assert "MANDATORY" in text[text.index("PARALLEL STEP SCHEDULING"):text.index("PARALLEL STEP SCHEDULING") + 60], (
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] tests: Brittle magic-offset check: text[...+60] assumes MANDATORY appears within 60 chars of the section heading. If whitespace changes the test silently false-negatives. Prefer extracting the full section slice (as sibling tests do) and searching within it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid observation — flagged for design decision. The heading in SKILL.md is '## PARALLEL STEP SCHEDULING — MANDATORY', placing MANDATORY at offset ~30, well within the 60-char window. The test currently passes correctly. However, the reviewer's structural concern is valid: if the heading were reformatted, the offset could silently false-negative. Sibling tests use a full section-slice approach for consistency. Flagged for human review to decide whether to refactor for uniformity.

)


def test_sous_chef_parallel_scheduling_prohibits_slow_before_all_fast_done() -> None:
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] tests: Weak assertion: prohibition check accepts any of four generic words (never, must not, do not, prohibited) anywhere in the section text. The assertion is too broad to reliably guard the specific rule.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. The assertion checks within a scoped section slice (lines 71-74 extract text between the section heading and next '##'). The SKILL.md section contains 'Never launch a slow step for one pipeline while another pipeline still has fast steps pending.' — 'never' is present in unambiguous context. Broad keyword checks for prose contract tests are the established pattern across all sibling assertion tests in this file. The test correctly guards that prohibition vocabulary exists in the section.

next_section = text.find("\n## ", section_start + 1)
section_text = text[section_start:next_section] if next_section != -1 else text[section_start:]
lower = section_text.lower()
assert "together" in lower or "parallel batch" in lower or "all slow" in lower or "batch" in lower, (
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] tests: Weak assertion: batching check accepts the single word batch which could appear in unrelated context and produce a false pass. Prefer a phrase more precisely capturing the intent.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. The assertion uses four disjuncts: 'together', 'parallel batch', 'all slow', and 'batch'. The SKILL.md section contains 'Launch all slow steps together in one parallel batch' — matching both 'together' AND 'parallel batch' simultaneously. The stronger phrases are what trigger the pass; the single-word 'batch' fallback is a deliberate defensive addition. The reviewer's concern about 'batch' appearing out of context is moot because the OR chain includes specific multi-word phrases that unambiguously match the intended rule.

class TestRunModeIngredient:
"""REQ-INGREDIENT-001 through REQ-INGREDIENT-005: run_mode ingredient in multi-issue recipes.""" # noqa: E501

@pytest.fixture(scope="class")
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] tests: class-scoped fixture calls load_recipe (I/O). Under pytest-xdist if load_recipe raises, all tests in the class fail with a fixture error rather than a clear test failure.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. Class-scoped fixtures calling load_recipe() are the established pattern throughout this file: TestImplementationPipelineStructure, TestImplementationGroupsStructure, TestInvestigateFirstStructure, TestReviewPrRecipeIntegration, and TestImplementationRecipeMergeQueueRule all use scope='class' with load_recipe(). The new TestRunModeIngredient class follows the identical convention. load_recipe() reads a static bundled YAML file with no mutable side effects; a fixture error on one worker does not cascade to others under xdist.

)


# ---------------------------------------------------------------------------
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] slop: Redundant separator block duplicates the class name on L1602. The class definition is the canonical label; these comment dividers add no information.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated — this is intentional. The '# ---' separator block pattern is used consistently before every class definition and major section throughout test_bundled_recipes.py (before TestImplementationPipelineStructure, TestImplementationGroupsStructure, TestInvestigateFirstStructure, TestSmokeTestStructure, TestReviewPrRecipeIntegration, TestBaseBranchDefaults, TestImplementationRecipeMergeQueueRule, and multiple standalone function groups). The new TestRunModeIngredient separator follows this file-wide convention. Removing it would make the new code inconsistent with every other class in the file.

def test_implementation_has_run_mode_ingredient(self, impl_recipe) -> None:
"""REQ-INGREDIENT-001: implementation.yaml declares run_mode ingredient."""
assert "run_mode" in impl_recipe.ingredients, (
"implementation.yaml must declare run_mode ingredient"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[info] tests: Assertion message strings are not indented to match the opening parenthesis, diverging from style used elsewhere in the same file.

Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit review found 6 blocking issues (1 critical, 5 warnings). See inline comments.

Verdict: changes_requested

Key findings:

  • CRITICAL [bugs] test_sous_chef_scheduling.py:120 — NameError: scheduling_pos is never defined (should be section_start), will crash at runtime
  • WARNING [tests] test_sous_chef_scheduling.py:37 — Brittle 60-char magic offset for MANDATORY check
  • WARNING [tests] test_sous_chef_scheduling.py:68,94 — Weak assertions accept overly-broad keyword matches
  • WARNING [tests] test_bundled_recipes.py:1605 — class-scoped I/O fixture may obscure errors under xdist
  • WARNING [slop] test_bundled_recipes.py:1597 — Redundant separator comment duplicating class name

@Trecek Trecek added this pull request to the merge queue Mar 21, 2026
Merged via the queue into integration with commit d2f37cc Mar 21, 2026
2 checks passed
@Trecek Trecek deleted the add-parallel-step-scheduling-rule-to-sous-chef-prompt/461 branch March 21, 2026 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant