Fix Orchestrator Anti-Patterns Identified by run_cmd Pattern Mining#285
Closed
Fix Orchestrator Anti-Patterns Identified by run_cmd Pattern Mining#285
Conversation
- tests/recipe/test_anti_pattern_guards.py: new file with AP1-AP5 guards - tests/workspace/test_skills.py: add diagnose-ci to BUNDLED_SKILLS and test_diagnose_ci_skill_is_resolvable - tests/server/test_tools_git.py: add test for base_branch_name parameter on create_unique_branch
New bundled skill that fetches CI logs via gh CLI, classifies the failure type (test/lint/build/type_check/env/unknown), and writes a structured diagnosis report to temp/diagnose-ci/. Orchestrators route to this skill on ci_watch failure before resolve-failures.
When base_branch_name is provided, it is used directly as the base name instead of composing from slug+issue_number. The ls-remote collision check and -2/-3 suffix logic apply regardless of which path is taken. Also makes slug and remote optional (default "" and "origin") so the new base_branch_name path can be the sole entry point without requiring callers to pass empty slug and issue_number.
AP5: Add step_name to capture_base_sha and set_merge_target run_cmd steps
AP3: Replace create_branch bash script with compute_branch (run_cmd, name only)
+ create_branch (create_unique_branch MCP tool); update claim_issue routing
AP1: Add diagnose_ci step between ci_watch failure and resolve_ci; update
ci_watch.on_failure and resolve_ci.skill_command to include diagnosis_path
Same changes as implementation.yaml: step_name on capture_base_sha and set_merge_target, compute_branch + create_unique_branch for AP3, diagnose_ci step for AP1.
…P1/AP2/AP5
AP5: Add step_name to all unnamed run_cmd steps in both recipes
AP2: Switch push_integration_branch from run_cmd to push_to_remote MCP tool;
add kitchen rule forbidding intermediate pushes inside the merge loop
AP1: Add diagnose_ci_pr step; change ci_watch_pr.on_failure to diagnose_ci_pr
…AP3/AP5
AP5: Add step_name to set_merge_target run_cmd steps
AP3: Replace create_branch bash script with compute_branch + create_unique_branch
MCP tool; update claim_issue routing to compute_branch
AP1: Add diagnose_ci step; change ci_watch.on_failure to diagnose_ci;
update resolve_ci.skill_command to include diagnosis_path
Add diagnose-ci to the Bundled AutoSkillit Skills section of write-recipe/SKILL.md and to the skills directory listing in CLAUDE.md.
New recipe that shares clone/base_sha/set_merge_target setup once across all issues, then loops per-issue for get_issue_title → claim_issue → compute_branch → create_branch → implement → push → open_pr_step. Full loop state accumulation deferred to after write_telemetry_files (#237) lands. This delivers the shared-setup structure and reduces setup overhead from O(n) to O(1).
Auto-fix ruff format issues in test files; shorten test docstring in test_tools_git.py to satisfy E501 line length limit.
- Fix create_unique_branch parameter order (restore slug/issue_number/remote/cwd to match legacy call signature; add base_branch_name as addl optional param) - Fix batch-implementation.yaml YAML syntax error (quote summary with colons) - Add current_issue_url/current_issue_task as ingredients; replace context. references with inputs. to satisfy skip-when-false-undeclared rule - Remove dead base_sha capture; fix issue_title dead-output in batch recipe - Add capture_list/glob note to implement step for multipart-plan compliance - Fix unbounded-cycle errors via cleanup_failure exits in get_issue_title/ claim_issue/release_issue_failure - Add diagnose-ci to skill_contracts.yaml with outputs contract - Fix diagnose_ci_pr: add capture + on_result to satisfy implicit-handoff and dead-output rules simultaneously - Update test_bundled_recipes.py: check compute_branch.cmd instead of create_branch.cmd; update ci_watch on_failure assertions to diagnose_ci - Update test_issue_url_pipeline.py: check compute_branch.cmd for slug fallback; update claim_issue routing assertion to compute_branch - Update test_pr_merge_pipeline.py: update ci_watch_pr routing to diagnose_ci_pr Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Trecek
commented
Mar 10, 2026
Collaborator
Author
Trecek
left a comment
There was a problem hiding this comment.
AutoSkillit Review Findings
Verdict: changes_requested
9 actionable findings (clear fixes available) + 1 decision finding (requires human judgment).
src/autoskillit/recipes/batch-implementation.yaml
| Line | Severity | Dimension | Message |
|---|---|---|---|
| 383 | warning | bugs | create_branch runs inside the batch loop against the same shared clone. After the first issue's feature branch is created, subsequent iterations branch from the current HEAD (the prior feature branch) rather than base_branch. There is no git checkout base_branch between iterations, so branches stack on each other. |
| 402 | warning | bugs | The 'implement' step invokes /autoskillit:make-plan (planning only), but on_success routes to open_pr_step which opens a PR — implying working code is present. A TODO comment acknowledges this, but opening a PR after make-plan with no actual implementation step will produce empty PRs. Should this step use implement-worktree-no-merge instead? |
| 454 | warning | bugs | next_or_done_issue uses ${{ result.next }} == more_issues but action: route calls no tool and no prior step produces a next field. The routing condition is permanently unsatisfiable — the pipeline always routes to confirm_cleanup and never loops back to get_issue_title. |
src/autoskillit/recipes/pr-merge-pipeline.yaml
| Line | Severity | Dimension | Message |
|---|---|---|---|
| 880 | warning | cohesion | Step is named 'diagnose_ci_pr' here but 'diagnose_ci' in all other recipes (implementation.yaml, implementation-groups.yaml, audit-and-fix.yaml, remediation.yaml). The '_pr' suffix breaks cross-recipe naming symmetry without adding structural distinction. |
| 888 | warning | cohesion | diagnose_ci_pr uses 'on_result' with a single unconditional route to 'cleanup_failure', while all sibling diagnose_ci steps use 'on_success'/'on_failure' routing. The asymmetric routing pattern diverges from the established convention for this step type across every other recipe. |
src/autoskillit/server/tools_git.py
| Line | Severity | Dimension | Message |
|---|---|---|---|
| 1099 | warning | defense | create_unique_branch has no validation guard: if base_branch_name is None and slug is also empty (both are defaults), base_name becomes '' or '-{issue_number}' — both invalid git branch names. Add a defensive check that raises an error when neither base_branch_name nor slug is provided. |
| 1103 | warning | defense | base_branch_name is typed str |
tests/recipe/test_anti_pattern_guards.py
| Line | Severity | Dimension | Message |
|---|---|---|---|
| 1381 | warning | tests | test_implementation_groups_ci_failure_routes_to_diagnose_ci asserts only ci_watch.on_failure == 'diagnose_ci' and step existence, but its sister test for implementation.yaml also asserts diag.tool == 'run_skill' and 'diagnosis_path' in diag.capture. The weaker assertions here mean a misconfigured diagnose_ci step (wrong tool or missing capture) would pass undetected for implementation-groups. |
| 1409 | warning | tests | test_pr_merge_pipeline_has_no_loop_push_kitchen_rule uses fragile prose substring matching ('NEVER push inside the' or 'no intermediate push') on a joined rule string. Any rewording (e.g. 'NEVER push within the') silently breaks the guard. Prefer asserting a stable structural property instead. |
tests/server/test_tools_git.py
| Line | Severity | Dimension | Message |
|---|---|---|---|
| 1649 | warning | tests | The generator expression passed to next() has no default, so if no subprocess call contains 'ls-remote' in its args, next() raises a bare StopIteration with no diagnostic message. Add next(..., None) and assert the result for a readable failure. |
… quality - batch-implementation: add checkout_base step before create_branch to prevent feature branches stacking on prior iteration's HEAD - batch-implementation: fix unsatisfiable routing in next_or_done_issue (result.next never set); use inputs.current_issue_url instead - pr-merge-pipeline: rename diagnose_ci_pr → diagnose_ci for cross-recipe naming symmetry; replace unconditional on_result with on_success/on_failure - pr-merge-pipeline: add dead-output exemption in _analysis.py for diagnosis_path observability captures (parallel to cleanup_succeeded) - tools_git.create_unique_branch: guard against empty base_branch_name (truthy check instead of is not None); error when neither base_branch_name nor slug is provided - test_anti_pattern_guards: strengthen implementation-groups diagnose_ci assertions (add tool and capture checks); replace fragile prose matching in loop-push test with structural push_to_remote step set assertion - test_tools_git: add default to next() call to produce readable failure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Trecek
added a commit
that referenced
this pull request
Mar 10, 2026
Collaborator
Author
Trecek
added a commit
that referenced
this pull request
Mar 10, 2026
## Integration Summary Collapsed 4 PRs into `pr-batch/pr-merge-20260309-184208` targeting `main`. ## Merged PRs | # | Title | Complexity | Additions | Deletions | Overlaps | |---|-------|-----------|-----------|-----------|---------| | #281 | Track MCP Tool Response Token Counts in Diagnostic Logging | simple | +616 | -12 | — | | #280 | Rectify: Recipe Diagram Renderer — Graph Model Unification — PART A ONLY | needs_check | +727 | -152 | #281 | | #285 | Fix Orchestrator Anti-Patterns Identified by run_cmd Pattern Mining | needs_check | +909 | -181 | #281, #280 | | #284 | Phase 3 — Registration Consolidation and chefs-hat CLI | needs_check | +608 | -333 | #281, #285 | ## Architecture Impact ### Development Diagram ```mermaid %%{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 output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff; classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff; subgraph Structure ["PROJECT STRUCTURE"] direction LR SRC["src/autoskillit/<br/>━━━━━━━━━━<br/>101 source files<br/>9 sub-packages"] TESTS["tests/<br/>━━━━━━━━━━<br/>160 test files<br/>arch/cli/recipe/server..."] end subgraph Build ["● BUILD TOOLING"] direction LR PYPROJECT["● pyproject.toml<br/>━━━━━━━━━━<br/>hatchling backend<br/>uv package manager<br/>Python >=3.11"] TASKFILE["Taskfile.yml<br/>━━━━━━━━━━<br/>test-all / test-check<br/>install-worktree"] UVLOCK["● uv.lock<br/>━━━━━━━━━━<br/>Pinned dependencies<br/>10 runtime + 7 dev"] end subgraph Quality ["CODE QUALITY GATES (pre-commit)"] direction LR FORMAT["ruff-format<br/>━━━━━━━━━━<br/>Auto-format<br/>line-length=99"] LINT["ruff check<br/>━━━━━━━━━━<br/>E/F/I/UP/TID251<br/>banned: logging.getLogger"] TYPES["mypy<br/>━━━━━━━━━━<br/>src/ --ignore-missing-imports<br/>layer contracts enforced"] SECRETS["gitleaks<br/>━━━━━━━━━━<br/>Secret scanning<br/>v8.30.0"] NOCONFIGS["no-generated-configs<br/>━━━━━━━━━━<br/>Blocks hooks.json<br/>settings.json diagrams/"] end subgraph Testing ["TEST FRAMEWORK"] direction LR PYTEST["pytest + asyncio<br/>━━━━━━━━━━<br/>asyncio_mode=auto<br/>timeout=60s"] XDIST["pytest-xdist<br/>━━━━━━━━━━<br/>-n 4 parallel workers<br/>safe parallel execution"] IMPORTLINTER["import-linter<br/>━━━━━━━━━━<br/>6 layer contracts<br/>L0→L1→L2→L3"] end subgraph NewPipeline ["★ NEW PIPELINE COMPONENT"] MCPRESP["★ mcp_response.py<br/>━━━━━━━━━━<br/>DefaultMcpResponseLog<br/>per-tool response tracking"] end subgraph EntryPoints ["ENTRY POINTS"] direction LR CLI["● autoskillit<br/>━━━━━━━━━━<br/>● app.py (serve/init/config)<br/>● _doctor.py / _marketplace.py"] CHEFHAT["★ chefs-hat<br/>━━━━━━━━━━<br/>★ _chefs_hat.py<br/>Ephemeral skill session launcher"] end %% FLOW %% SRC --> PYPROJECT TESTS --> PYPROJECT PYPROJECT --> UVLOCK PYPROJECT --> TASKFILE PYPROJECT --> FORMAT FORMAT --> LINT LINT --> TYPES TYPES --> SECRETS SECRETS --> NOCONFIGS NOCONFIGS --> PYTEST PYTEST --> XDIST PYTEST --> IMPORTLINTER SRC --> NewPipeline NewPipeline --> MCPRESP PYPROJECT --> CLI PYPROJECT --> CHEFHAT %% CLASS ASSIGNMENTS %% class SRC,TESTS cli; class PYPROJECT,TASKFILE,UVLOCK phase; class FORMAT,LINT,TYPES,SECRETS,NOCONFIGS detector; class PYTEST,XDIST,IMPORTLINTER handler; class MCPRESP newComponent; class CLI output; class CHEFHAT newComponent; ``` ### Data Lineage Diagram ```mermaid %%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 60, 'curve': 'basis'}}}%% flowchart LR %% 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 output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff; classDef integration fill:#c62828,stroke:#ef9a9a,stroke-width:2px,color:#fff; classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff; subgraph MCPFlow ["★ MCP RESPONSE TRACKING FLOW (PR #281)"] direction LR TOOL["● MCP Tool Handlers<br/>━━━━━━━━━━<br/>tools_*.py<br/>returns: str | dict"] DECORATOR["★ track_response_size<br/>━━━━━━━━━━<br/>● server/helpers.py<br/>json.dumps → UTF-8 encode<br/>bytes // 4 = tokens"] RESPLOG["★ DefaultMcpResponseLog<br/>━━━━━━━━━━<br/>★ pipeline/mcp_response.py<br/>McpResponseEntry per tool<br/>invocation_count, bytes, tokens"] THRESHOLD["● config/settings.py<br/>━━━━━━━━━━<br/>alert_threshold_tokens<br/>● defaults.yaml"] end subgraph TokenSummary ["● TOKEN SUMMARY AGGREGATION"] direction TB TOKLOG["TokenLog<br/>━━━━━━━━━━<br/>pipeline/tokens.py<br/>per-step token counts"] GETSUMMARY["● get_token_summary<br/>━━━━━━━━━━<br/>● tools_status.py<br/>merges token + ★ mcp_responses"] end subgraph TelemetryOut ["TELEMETRY ARTIFACTS (write-only)"] direction TB TOKMD["token_summary.md<br/>━━━━━━━━━━<br/>Markdown table<br/>per-step tokens"] TIMEMD["timing_summary.md<br/>━━━━━━━━━━<br/>Markdown table<br/>per-step timing"] MCPJSON["★ mcp_response_metrics.json<br/>━━━━━━━━━━<br/>JSON per-tool response stats<br/>bytes + estimated tokens"] end subgraph RecipeFlow ["● RECIPE DIAGRAM FLOW (PR #280)"] direction LR YAML["Recipe YAML<br/>━━━━━━━━━━<br/>recipes/*.yaml<br/>step definitions"] LOADER["load_recipe()<br/>━━━━━━━━━━<br/>recipe/io.py<br/>→ Recipe dataclass"] GRAPH["● build_recipe_graph()<br/>━━━━━━━━━━<br/>● recipe/_analysis.py<br/>→ igraph.Graph<br/>vertex/edge attrs"] LAYOUT["● _compute_layout()<br/>━━━━━━━━━━<br/>● recipe/diagrams.py<br/>FOR EACH cycle detect<br/>back-edge flags"] DIAGRAMMD["● recipes/diagrams/{stem}.md<br/>━━━━━━━━━━<br/>● v6 format diagram<br/>SHA-256 hash embedded"] end subgraph ValidationFlow ["● ANTI-PATTERN VALIDATION FLOW (PR #285)"] direction LR YAML2["Recipe YAML<br/>━━━━━━━━━━<br/>recipes/*.yaml"] CONTRACTS["● skill_contracts.yaml<br/>━━━━━━━━━━<br/>Skill tool contracts<br/>● recipe/"] ANALYSIS["● analyze_dataflow()<br/>━━━━━━━━━━<br/>● recipe/_analysis.py<br/>BFS passes: dead outputs<br/>implicit handoffs, ref invalidations"] REPORT["DataFlowReport<br/>━━━━━━━━━━<br/>recipe/schema.py<br/>warnings: list[DataFlowWarning]<br/>DEAD_OUTPUT / IMPLICIT_HANDOFF<br/>REF_INVALIDATED"] SEMRULES["Semantic Rules<br/>━━━━━━━━━━<br/>recipe/rules_*.py<br/>ValidationContext<br/>→ RuleFindings"] end %% MCP TRACKING FLOW %% TOOL -->|"return value"| DECORATOR THRESHOLD -->|"alert_threshold_tokens"| DECORATOR DECORATOR -->|"record(tool_name, bytes, tokens)"| RESPLOG RESPLOG -->|"get_report()"| GETSUMMARY TOKLOG -->|"get_report()"| GETSUMMARY GETSUMMARY -.->|"write-only"| TOKMD GETSUMMARY -.->|"write-only"| TIMEMD GETSUMMARY -.->|"★ write-only"| MCPJSON %% RECIPE DIAGRAM FLOW %% YAML -->|"parse YAML"| LOADER LOADER -->|"Recipe dataclass"| GRAPH GRAPH -->|"igraph.Graph"| LAYOUT LAYOUT -.->|"atomic write"| DIAGRAMMD %% VALIDATION FLOW %% YAML2 -->|"parse"| LOADER CONTRACTS -->|"read"| ANALYSIS LOADER -->|"Recipe dataclass"| ANALYSIS ANALYSIS -->|"DataFlowReport"| REPORT REPORT -->|"ValidationContext"| SEMRULES %% CLASS ASSIGNMENTS %% class TOOL,YAML,YAML2 cli; class DECORATOR newComponent; class RESPLOG newComponent; class THRESHOLD phase; class TOKLOG stateNode; class GETSUMMARY handler; class TOKMD,TIMEMD output; class MCPJSON newComponent; class LOADER phase; class GRAPH handler; class LAYOUT handler; class DIAGRAMMD output; class CONTRACTS stateNode; class ANALYSIS handler; class REPORT stateNode; class SEMRULES detector; ``` ### Module Dependency Diagram ```mermaid %%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 70, 'curve': 'basis'}}}%% graph TB %% CLASS DEFINITIONS %% classDef cli fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff; classDef phase fill:#6a1b9a,stroke:#ba68c8,stroke-width:2px,color:#fff; classDef handler fill:#e65100,stroke:#ffb74d,stroke-width:2px,color:#fff; classDef stateNode fill:#004d40,stroke:#4db6ac,stroke-width:2px,color:#fff; classDef newComponent fill:#2e7d32,stroke:#81c784,stroke-width:2px,color:#fff; classDef integration fill:#c62828,stroke:#ef9a9a,stroke-width:2px,color:#fff; classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff; subgraph L3 ["L3 — APPLICATION (cli/ + server/)"] direction LR CLIAPP["● cli/app.py<br/>━━━━━━━━━━<br/>serve/init/config/doctor<br/>skills/recipes/workspace"] CHEFHAT["★ cli/_chefs_hat.py<br/>━━━━━━━━━━<br/>chefs-hat command<br/>ephemeral skill session"] CLIDOC["● cli/_doctor.py<br/>● cli/_init_helpers.py<br/>● cli/_marketplace.py<br/>━━━━━━━━━━<br/>CLI sub-commands"] SRVHELPER["● server/helpers.py<br/>━━━━━━━━━━<br/>★ track_response_size<br/>wraps all tool handlers"] SRVTOOLS["● server/tools_*.py<br/>━━━━━━━━━━<br/>36 MCP tool handlers<br/>all decorated by helpers"] end subgraph L2 ["L2 — DOMAIN (recipe/ + migration/)"] direction LR ANALYSIS["● recipe/_analysis.py<br/>━━━━━━━━━━<br/>build_recipe_graph()<br/>analyze_dataflow()<br/>igraph.Graph model"] DIAGRAMS["● recipe/diagrams.py<br/>━━━━━━━━━━<br/>_compute_layout()<br/>v6 format + SHA-256"] RULES["● recipe/rules_*.py<br/>━━━━━━━━━━<br/>semantic rules<br/>anti-pattern guards"] CONTRACTS["● recipe/skill_contracts.yaml<br/>━━━━━━━━━━<br/>tool contract data<br/>read by _analysis.py"] end subgraph L1 ["L1 — SERVICES (pipeline/ + config/ + execution/ + workspace/)"] direction LR MCPRESP["★ pipeline/mcp_response.py<br/>━━━━━━━━━━<br/>McpResponseEntry<br/>DefaultMcpResponseLog<br/>per-tool byte/token tracking"] CTX["● pipeline/context.py<br/>━━━━━━━━━━<br/>ToolContext DI container<br/>● +response_log field"] CFGSETTINGS["● config/settings.py<br/>━━━━━━━━━━<br/>AutomationConfig<br/>● +mcp_response section"] CFGYAML["● config/defaults.yaml<br/>━━━━━━━━━━<br/>● alert_threshold_tokens<br/>● alert_on_threshold"] end subgraph L0 ["L0 — FOUNDATION (core/)"] direction LR CORETYPES["● core/types.py<br/>━━━━━━━━━━<br/>StrEnums, protocols<br/>constants"] COREINIT["● core/__init__.py<br/>━━━━━━━━━━<br/>Re-exports public surface"] end subgraph External ["EXTERNAL PACKAGES"] direction LR IGRAPH["igraph<br/>━━━━━━━━━━<br/>Graph model<br/>subcomponent() for cycles"] FASTMCP["fastmcp<br/>━━━━━━━━━━<br/>MCP server framework<br/>tool registration"] CYCLOPTS["cyclopts<br/>━━━━━━━━━━<br/>CLI framework<br/>★ chefs-hat entry"] STRUCTLOG["structlog<br/>━━━━━━━━━━<br/>Structured logging"] end %% L3 → L2 dependencies %% SRVTOOLS -->|"imports schema, validator"| ANALYSIS SRVTOOLS -->|"imports diagrams"| DIAGRAMS CLIAPP -->|"imports recipe io"| ANALYSIS %% L3 → L1 dependencies %% SRVHELPER -->|"★ imports DefaultMcpResponseLog"| MCPRESP SRVHELPER -->|"imports ToolContext"| CTX SRVTOOLS -->|"imports ToolContext"| CTX CLIAPP -->|"imports config"| CFGSETTINGS CHEFHAT -->|"imports core paths"| COREINIT %% L2 → L1 dependencies %% ANALYSIS -->|"imports DataFlowWarning"| CORETYPES DIAGRAMS -->|"imports load_recipe"| ANALYSIS %% L2 → External %% ANALYSIS -->|"igraph.Graph"| IGRAPH %% L1 → L1 dependencies %% CTX -->|"★ holds response_log"| MCPRESP CTX -->|"reads threshold from"| CFGSETTINGS CFGSETTINGS -->|"reads defaults"| CFGYAML %% L1 → L0 dependencies %% MCPRESP -->|"imports StrEnum"| CORETYPES CTX -->|"imports protocols"| CORETYPES COREINIT -->|"re-exports"| CORETYPES %% L3 → External %% SRVTOOLS -->|"FastMCP tools"| FASTMCP CLIAPP -->|"CLI commands"| CYCLOPTS CHEFHAT -->|"★ CLI command"| CYCLOPTS %% CLASS ASSIGNMENTS %% class CLIAPP,CLIDOC cli; class CHEFHAT newComponent; class SRVHELPER handler; class SRVTOOLS handler; class ANALYSIS phase; class DIAGRAMS phase; class RULES detector; class CONTRACTS stateNode; class MCPRESP newComponent; class CTX stateNode; class CFGSETTINGS phase; class CFGYAML stateNode; class CORETYPES stateNode; class COREINIT stateNode; class IGRAPH,FASTMCP,CYCLOPTS,STRUCTLOG integration; ``` Closes #223 Closes #229 Closes #238 Closes #270 🤖 Generated with [Claude Code](https://claude.com/claude-code) via AutoSkillit --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pattern mining of 736
run_cmdinvocations across 47 orchestrator sessions identified fivebehavioral anti-patterns where the orchestrator bypasses the recipe routing discipline. This
plan fixes all five:
AP1 — CI Investigation Spiral (22 occurrences): Create a
diagnose-ciskill so theorchestrator has a proper
run_skillchannel for CI log investigation. Update recipes toinsert a
diagnose_cistep beforeresolve_cion CI failure paths.AP2 — Push-Per-Merge (8 wasted pushes): Switch
push_integration_branchinpr-merge-pipeline.yamlfromrun_cmdto thepush_to_remoteMCP tool (the same toolall other push steps use), and add an explicit kitchen rule forbidding intermediate pushes
inside the merge loop.
AP3 — Branch Checkout Retries (12 redundant attempts): Add
base_branch_nameparameter to the
create_unique_branchMCP tool. Replace thecreate_branchrun_cmdbash script in all recipes with two cleaner steps:
compute_branch(name-onlyrun_cmd)create_branch(create_unique_branchMCP tool). The atomic MCP call eliminates thegap where the orchestrator inserts extra
git fetch + checkout -bcommands.AP4 — Multi-Issue Boilerplate (80-command sessions): Add a
batch-implementation.yamlrecipe skeleton that runs shared setup (clone, base_sha) once and loops per-issue for the
branch+implement+push steps. Full loop implementation is deferred pending
write_telemetry_filesfrom issue feat: new MCP tools for high-frequency run_cmd patterns (pattern mining 2026-03-08) #237; this plan delivers the recipe structure and the shared-setup savings.
AP5 — Unnamed Step Commands (88.3%): Add
step_nameto everyrun_cmdstep in allbundled recipes that currently lacks one. Target: ≤20% unnamed commands.
Architecture Impact
Process Flow Diagram
%%{init: {'flowchart': {'nodeSpacing': 45, 'rankSpacing': 55, '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 output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff; classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff; classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff; %% TERMINALS %% START([START]) DONE([DONE]) ESCALATE([ESCALATE]) subgraph AP3 ["AP3 Fix: Branch Creation (implementation, audit-and-fix, remediation)"] direction TB COMPUTE["● compute_branch<br/>━━━━━━━━━━<br/>run_cmd: name only<br/>slug/issue → proposed_branch<br/>no git operations"] CUB["★ create_branch<br/>━━━━━━━━━━<br/>create_unique_branch tool<br/>base_branch_name=proposed_branch<br/>atomic: ls-remote + checkout -b"] PUSH_MT["push_merge_target<br/>━━━━━━━━━━<br/>push_to_remote MCP"] end subgraph IMPL ["Core Loop (implement → test → merge)"] direction LR PLAN["plan / implement<br/>━━━━━━━━━━<br/>run_skill sessions"] TEST{"test passes?"} FIX["fix<br/>━━━━━━━━━━<br/>resolve-failures"] MERGE["merge<br/>━━━━━━━━━━<br/>merge_worktree MCP"] end subgraph AP1 ["AP1 Fix: CI Failure Path (implementation, audit-and-fix, remediation)"] direction TB PUSH_PR["push / open_pr / review_pr<br/>━━━━━━━━━━<br/>upstream push + GitHub PR"] CI_WATCH{"● ci_watch<br/>━━━━━━━━━━<br/>wait_for_ci"} DIAG_CI["★ diagnose_ci<br/>━━━━━━━━━━<br/>run_skill: /autoskillit:diagnose-ci<br/>gh logs → failure_type, is_fixable<br/>writes temp/diagnose-ci/diagnosis_*.md"] RES_CI["● resolve_ci<br/>━━━━━━━━━━<br/>resolve-failures + diagnosis_path<br/>retries: 2"] RE_PUSH["re_push<br/>━━━━━━━━━━<br/>push_to_remote MCP"] end subgraph AP2 ["AP2 Fix: PR Merge Pipeline Push (pr-merge-pipeline)"] direction TB MERGE_LOOP["merge_pr loop<br/>━━━━━━━━━━<br/>sequential PR merges<br/>no intermediate pushes"] PUSH_INT["● push_integration_branch<br/>━━━━━━━━━━<br/>push_to_remote MCP tool<br/>(was: run_cmd git push)"] CI_WATCH_PR{"● ci_watch_pr<br/>━━━━━━━━━━<br/>wait_for_ci: integration branch"} DIAG_CI_PR["★ diagnose_ci_pr<br/>━━━━━━━━━━<br/>run_skill: /autoskillit:diagnose-ci<br/>observability only — no auto-retry"] end %% FLOW: Branch Creation %% START --> COMPUTE COMPUTE -->|"proposed_branch captured"| CUB CUB -->|"merge_target captured"| PUSH_MT PUSH_MT --> PLAN %% FLOW: Core Loop %% PLAN --> TEST TEST -->|"pass"| MERGE TEST -->|"fail"| FIX FIX --> TEST MERGE -->|"success"| PUSH_PR %% FLOW: CI failure path %% PUSH_PR --> CI_WATCH CI_WATCH -->|"success"| DONE CI_WATCH -->|"failure"| DIAG_CI DIAG_CI -->|"diagnosis_path → resolve_ci<br/>(success OR failure)"| RES_CI RES_CI -->|"success"| RE_PUSH RES_CI -->|"exhausted / failure"| ESCALATE RE_PUSH -->|"loop back"| CI_WATCH %% FLOW: PR merge pipeline (parallel flow) %% MERGE_LOOP -->|"all PRs merged"| PUSH_INT PUSH_INT --> CI_WATCH_PR CI_WATCH_PR -->|"success"| DONE CI_WATCH_PR -->|"failure"| DIAG_CI_PR DIAG_CI_PR -->|"always → cleanup_failure"| ESCALATE %% CLASS ASSIGNMENTS %% class START,DONE,ESCALATE terminal; class COMPUTE,MERGE,PUSH_MT,RE_PUSH,PUSH_PR,PLAN,MERGE_LOOP handler; class CUB,DIAG_CI,DIAG_CI_PR,PUSH_INT newComponent; class RES_CI phase; class CI_WATCH,CI_WATCH_PR stateNode; class TEST detector;Error/Resilience Diagram
%%{init: {'flowchart': {'nodeSpacing': 45, 'rankSpacing': 55, '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 output fill:#00695c,stroke:#4db6ac,stroke-width:2px,color:#fff; classDef detector fill:#b71c1c,stroke:#ef5350,stroke-width:2px,color:#fff; classDef gap fill:#ff6f00,stroke:#ffa726,stroke-width:2px,color:#000; T_SUCCESS([CI PASSED]) T_ESCALATE([ESCALATED]) T_CLEANUP([CLEANUP FAILURE]) subgraph AP3_RES ["AP3: Branch Collision Guard (create_unique_branch)"] direction LR LS_REMOTE["● ls-remote check<br/>━━━━━━━━━━<br/>refs/heads/{proposed_branch}"] SUFFIX{"collision?"} CHECKOUT["git checkout -b<br/>━━━━━━━━━━<br/>atomic branch creation"] SUFFIX_N["append suffix<br/>━━━━━━━━━━<br/>-2, -3, ... -100"] end subgraph AP1_IMPL ["AP1: CI Failure Recovery (implementation / audit-and-fix / remediation)"] direction TB CI_WATCH{"● ci_watch<br/>━━━━━━━━━━<br/>wait_for_ci<br/>success | failure"} DIAG_CI["★ diagnose_ci<br/>━━━━━━━━━━<br/>/autoskillit:diagnose-ci<br/>classifies: test|lint|build<br/>writes diagnosis_*.md<br/>captures: diagnosis_path"] RES_CI["● resolve_ci<br/>━━━━━━━━━━<br/>resolve-failures + diagnosis_path<br/>retries: 2"] RE_PUSH["re_push<br/>━━━━━━━━━━<br/>push_to_remote MCP<br/>re-triggers CI watch loop"] end subgraph AP1_PR ["AP1: Integration CI Observability (pr-merge-pipeline)"] direction TB CI_WATCH_PR{"● ci_watch_pr<br/>━━━━━━━━━━<br/>wait_for_ci: integration branch"} DIAG_CI_PR["★ diagnose_ci_pr<br/>━━━━━━━━━━<br/>/autoskillit:diagnose-ci<br/>observability only<br/>NO automated remediation"] end subgraph TEST_LOOP ["Test-Fix Loop (all recipes)"] direction LR TEST_GATE{"test passes?<br/>━━━━━━━━━━<br/>task test-check"} FIX["fix<br/>━━━━━━━━━━<br/>resolve-failures<br/>no hard retry limit"] end LS_REMOTE --> SUFFIX SUFFIX -->|"no collision"| CHECKOUT SUFFIX -->|"collision"| SUFFIX_N SUFFIX_N -->|"retry ls-remote"| SUFFIX CHECKOUT --> TEST_GATE TEST_GATE -->|"pass"| CI_WATCH TEST_GATE -->|"fail"| FIX FIX -->|"retry"| TEST_GATE CI_WATCH -->|"success"| T_SUCCESS CI_WATCH -->|"failure"| DIAG_CI DIAG_CI -->|"success OR failure"| RES_CI RES_CI -->|"resolved"| RE_PUSH RES_CI -->|"exhausted (retry 2)"| T_ESCALATE RE_PUSH -->|"re-triggers CI loop"| CI_WATCH CI_WATCH_PR -->|"success"| T_SUCCESS CI_WATCH_PR -->|"failure"| DIAG_CI_PR DIAG_CI_PR -->|"always (no auto-retry)"| T_CLEANUP class T_SUCCESS,T_ESCALATE,T_CLEANUP terminal; class LS_REMOTE,RE_PUSH,FIX handler; class CHECKOUT output; class SUFFIX_N phase; class DIAG_CI,DIAG_CI_PR newComponent; class RES_CI phase; class SUFFIX,CI_WATCH,CI_WATCH_PR,TEST_GATE detector;Closes #238
Implementation Plan
Plan file:
/home/talon/projects/autoskillit-runs/impl-20260309-163144-711104/temp/make-plan/orchestrator_anti_patterns_fix_plan_2026-03-09_120000.mdToken Usage Summary
Token Usage Summary
Step Timing Summary
Step Timing Summary
🤖 Generated with Claude Code via AutoSkillit