Implementation Plan: Move smoke-test recipe from bundled to project-local#612
Conversation
Move smoke-test.yaml, its contract card, and flow diagram from src/autoskillit/recipes/ to .autoskillit/recipes/ so the recipe is only visible when running from the AutoSkillit repo root. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Point SMOKE_SCRIPT to .autoskillit/recipes/ instead of bundled dir - Update smoke_recipe fixture to use SMOKE_SCRIPT constant - Update smoke_project fixture to copy recipe into temp dir - Add T1-T4 behavioral tests validating project-local discovery Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_bundled_recipes: point smoke_yaml fixture and standalone tests to .autoskillit/recipes/ path - test_bundled_recipe_hidden_policy: remove smoke-test from bundled list - test_tools_recipe: invert SS8 assertion (smoke-test not in empty project) - test_engine: update ME13 source path to project-local location Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Auto-fix ruff format changes in test files - Remove smoke-test entry from docs/recipes.md bundled section - Update bundled recipe count from 6 to 5 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Trecek
left a comment
There was a problem hiding this comment.
AutoSkillit PR Review — Verdict: changes_requested
| """smoke-test.yaml must exist in the project-local recipes directory.""" | ||
| assert SMOKE_SCRIPT.exists() | ||
|
|
||
| async def test_smoke_test_source_is_project(self, smoke_project: Path) -> None: |
There was a problem hiding this comment.
[warning] arch: test_smoke_test_source_is_project calls list_recipes() after smoke_project fixture chdirs. If list_recipes() caches the CWD at import time or uses a different resolution mechanism, this test may produce a false positive. The test has no assertion that list_recipes actually reads from tmp_path, not the real CWD or a module-level cache.
There was a problem hiding this comment.
Investigated — this is intentional. list_recipes() calls Path.cwd() at runtime (tools_recipe.py:50: tool_ctx.recipes.list_all(Path.cwd())), so no module-level caching occurs. The smoke_project fixture's monkeypatch.chdir(tmp_path) correctly sets the CWD used when list_recipes() is called. This pattern is already validated bidirectionally by test_smoke_test_invisible_from_external_project (lines 426-435) which confirms CWD-awareness in both directions.
Trecek
left a comment
There was a problem hiding this comment.
AutoSkillit review found 8 blocking issues. See inline comments.
Summary: The core refactor (moving smoke-test from bundled to project-local) is correct and complete. The test updates properly reflect the new structure. However, the path resolution pattern used to locate the project-local recipe is inconsistent and fragile across 6+ test sites — the PROJECT_ROOT constant already defined in test_smoke_pipeline.py should be the single source of truth, not repeated Path(__file__).resolve().parent.parent.parent traversals. Additionally, two defensive gaps were found in the new tests.
…gine.py - Add module-level PROJECT_ROOT constant (consistent with test_smoke_pipeline.py pattern) replacing fragile Path(__file__) traversal in test_contract_adapter_migrate_regenerates_card_on_disk - Add assert src_recipe.exists() guard before shutil.copy2 for actionable failure messages Addresses reviewer comments 3036345574 and 3036345580 on PR #612. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…CIPE constant Add module-level PROJECT_ROOT and SMOKE_RECIPE constants to test_bundled_recipes.py, replacing four inline Path(__file__).resolve().parent.parent.parent traversals that duplicated the same fragile path assumption. Addresses reviewer comments 3036345576, 3036345578, and 3036345585 on PR #612. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oke_pipeline.py - Add diagnostic message to assert SMOKE_SCRIPT.exists() check for actionable failures - Replace next(generator) with next(generator, None) + explicit assert to produce AssertionError instead of StopIteration when smoke-test is missing from list_recipes Addresses reviewer comments 3036345581 and 3036345583 on PR #612. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Move
smoke-test.yamland its companion artifacts (contract card, flow diagram) from the bundledsrc/autoskillit/recipes/directory to the project-local.autoskillit/recipes/directory. This makes smoke-test invisible to end-user projects while remaining fully functional when running from the AutoSkillit repository root. The existing project-local recipe discovery mechanism already supports this — no production code changes are needed. All changes are file relocations and test updates.Requirements
MOVE — Recipe File Relocation
src/autoskillit/recipes/smoke-test.yamlmust be relocated to.autoskillit/recipes/smoke-test.yamlat the project root.src/autoskillit/recipes/contracts/matchingsmoke-test*must be relocated to.autoskillit/recipes/contracts/.src/autoskillit/recipes/diagrams/matchingsmoke-test*must be relocated to.autoskillit/recipes/diagrams/.LIST — Listing Behavior
list_recipesoutput when the current working directory is outside the AutoSkillit repository.list_recipesoutput with sourcePROJECTwhen the current working directory is the AutoSkillit repository root.LOAD — Pipeline Compatibility
load_recipe("smoke-test")must succeed when invoked from the AutoSkillit repository root.TEST — Test Updates
RecipeSource.BUILTINmust be updated to assertRecipeSource.PROJECT.Architecture Impact
Operational Diagram
%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 60, 'curve': 'basis'}}}%% flowchart TB 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; START(["list_recipes / find_recipe_by_name called"]) subgraph ProjectLocal ["★ PROJECT-LOCAL SCAN (priority 1)"] direction TB PROJ_DIR["★ .autoskillit/recipes/<br/>━━━━━━━━━━<br/>source = PROJECT<br/>★ smoke-test.yaml (moved here)"] PROJ_CONTRACT["★ .autoskillit/recipes/contracts/<br/>━━━━━━━━━━<br/>★ smoke-test.yaml"] PROJ_DIAGRAM["★ .autoskillit/recipes/diagrams/<br/>━━━━━━━━━━<br/>★ smoke-test.md"] end subgraph Bundled ["BUNDLED SCAN (priority 2)"] direction TB BUILTIN_DIR["src/autoskillit/recipes/<br/>━━━━━━━━━━<br/>source = BUILTIN<br/>implementation, remediation,<br/>merge-prs, impl-groups<br/>(smoke-test removed)"] end DEDUP["Dedup via seen set<br/>━━━━━━━━━━<br/>Project names shadow bundled"] subgraph AutoskillitRepo ["AUTOSKILLIT REPO CONTEXT"] direction TB CLI_LIST["● autoskillit recipes list<br/>━━━━━━━━━━<br/>Shows smoke-test (source: project)"] CLI_ORDER["autoskillit order<br/>━━━━━━━━━━<br/>Pipeline execution menu"] CLI_RENDER["autoskillit recipes render<br/>━━━━━━━━━━<br/>_recipes_dir_for(PROJECT)<br/>→ .autoskillit/recipes/diagrams/"] end subgraph ExternalProject ["EXTERNAL PROJECT CONTEXT"] direction TB EXT_LIST["autoskillit recipes list<br/>━━━━━━━━━━<br/>smoke-test NOT visible<br/>(no project-local copy)"] end START --> PROJ_DIR PROJ_DIR --> DEDUP DEDUP --> BUILTIN_DIR PROJ_DIR --> PROJ_CONTRACT PROJ_DIR --> PROJ_DIAGRAM DEDUP --> CLI_LIST DEDUP --> CLI_ORDER CLI_RENDER --> PROJ_DIAGRAM DEDUP --> EXT_LIST class START terminal; class PROJ_DIR,PROJ_CONTRACT,PROJ_DIAGRAM newComponent; class BUILTIN_DIR stateNode; class DEDUP handler; class CLI_LIST,CLI_ORDER,CLI_RENDER cli; class EXT_LIST detector;Module Dependency Diagram
%%{init: {'flowchart': {'nodeSpacing': 50, 'rankSpacing': 70, 'curve': 'basis'}}}%% graph TB 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 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; classDef terminal fill:#1a237e,stroke:#7986cb,stroke-width:2px,color:#fff; subgraph Tests ["TESTS (modified ●)"] direction TB T_SMOKE["● test_smoke_pipeline.py<br/>━━━━━━━━━━<br/>uses SMOKE_SCRIPT<br/>→ project-local path"] T_BUNDLED["● test_bundled_recipes.py<br/>━━━━━━━━━━<br/>smoke_yaml fixture<br/>→ project-local path"] T_POLICY["● test_bundled_recipe_hidden_policy.py<br/>━━━━━━━━━━<br/>BUNDLED_RECIPE_NAMES<br/>smoke-test removed"] T_TOOLS["● test_tools_recipe.py<br/>━━━━━━━━━━<br/>list_recipes assertion<br/>smoke-test NOT in bundled"] T_ENGINE["● test_engine.py<br/>━━━━━━━━━━<br/>contract adapter test<br/>→ project-local path"] end subgraph L3 ["L3 — SERVER"] direction TB TOOLS_RECIPE["server.tools_recipe<br/>━━━━━━━━━━<br/>list_recipes, load_recipe<br/>validate_recipe"] end subgraph L2R ["L2 — RECIPE"] direction TB RECIPE_IO["recipe.io<br/>━━━━━━━━━━<br/>builtin_recipes_dir()<br/>list_recipes()"] RECIPE_VALIDATOR["recipe.validator<br/>━━━━━━━━━━<br/>run_semantic_rules<br/>analyze_dataflow"] RECIPE_CONTRACTS["recipe.contracts<br/>━━━━━━━━━━<br/>load_bundled_manifest"] end subgraph L2M ["L2 — MIGRATION"] direction TB MIG_ENGINE["migration.engine<br/>━━━━━━━━━━<br/>default_migration_engine<br/>contract adapters"] end subgraph L0 ["L0 — CORE"] direction TB CORE_PATHS["core.paths<br/>━━━━━━━━━━<br/>pkg_root() → bundled dir<br/>fan-in: all layers"] end subgraph Artifacts ["★ PROJECT-LOCAL ARTIFACTS (new)"] direction TB PROJ_RECIPE["★ .autoskillit/recipes/<br/>━━━━━━━━━━<br/>smoke-test.yaml"] PROJ_CONTRACT["★ .autoskillit/recipes/contracts/<br/>━━━━━━━━━━<br/>smoke-test.yaml"] PROJ_DIAGRAM["★ .autoskillit/recipes/diagrams/<br/>━━━━━━━━━━<br/>smoke-test.md"] end T_SMOKE -->|"imports"| TOOLS_RECIPE T_SMOKE -->|"imports"| RECIPE_IO T_BUNDLED -->|"imports"| RECIPE_IO T_BUNDLED -->|"imports"| RECIPE_CONTRACTS T_POLICY -->|"imports"| CORE_PATHS T_TOOLS -->|"imports"| TOOLS_RECIPE T_ENGINE -->|"imports"| CORE_PATHS T_ENGINE -->|"imports"| MIG_ENGINE TOOLS_RECIPE -->|"imports"| RECIPE_IO RECIPE_IO -->|"builtin_recipes_dir()"| CORE_PATHS RECIPE_VALIDATOR -->|"imports"| RECIPE_IO RECIPE_CONTRACTS -->|"imports"| RECIPE_IO MIG_ENGINE -->|"imports"| CORE_PATHS T_SMOKE -.->|"now reads"| PROJ_RECIPE T_BUNDLED -.->|"now reads"| PROJ_RECIPE T_ENGINE -.->|"now reads"| PROJ_CONTRACT class T_SMOKE,T_BUNDLED,T_POLICY,T_TOOLS,T_ENGINE phase; class TOOLS_RECIPE cli; class RECIPE_IO,RECIPE_VALIDATOR,RECIPE_CONTRACTS handler; class MIG_ENGINE handler; class CORE_PATHS stateNode; class PROJ_RECIPE,PROJ_CONTRACT,PROJ_DIAGRAM newComponent;Closes #600
Implementation Plan
Plan file:
/home/talon/projects/autoskillit-runs/impl-20260404-190817-394673/.autoskillit/temp/make-plan/move_smoke_test_recipe_plan_2026-04-04_190817.md🤖 Generated with Claude Code via AutoSkillit
Token Usage Summary