diff --git a/docs/developer/diagnostics.md b/docs/developer/diagnostics.md index 5b723ae572..1a15884d4b 100644 --- a/docs/developer/diagnostics.md +++ b/docs/developer/diagnostics.md @@ -88,13 +88,13 @@ linux_tracing: ## Per-Run Enablement -By default, `post_run_diagnostics` resolves from `diagnostics.post_run_analysis` (shipped +By default, `pipeline_health` resolves from `diagnostics.pipeline_health` (shipped default: `false`). To enable diagnostics for a single run, the orchestrator can pass -`overrides={"post_run_diagnostics": "true"}` to `open_kitchen`. The override takes effect +`overrides={"pipeline_health": "true"}` to `open_kitchen`. The override takes effect for that kitchen session only and does not modify the persistent config. The orchestrator can also lock the value for the session via -`lock_ingredients(locked={"post_run_diagnostics": "true"})` to ensure it is not overridden +`lock_ingredients(locked={"pipeline_health": "true"})` to ensure it is not overridden by downstream steps. For post-hoc diagnostics on a completed run, use: diff --git a/src/autoskillit/config/_config_dataclasses.py b/src/autoskillit/config/_config_dataclasses.py index d2b96a0c00..38952558eb 100644 --- a/src/autoskillit/config/_config_dataclasses.py +++ b/src/autoskillit/config/_config_dataclasses.py @@ -305,7 +305,7 @@ class LoggingConfig: @dataclass class DiagnosticsConfig: - post_run_analysis: bool = False + pipeline_health: bool = False @dataclass diff --git a/src/autoskillit/config/defaults.yaml b/src/autoskillit/config/defaults.yaml index 11b18ea698..75786447b7 100644 --- a/src/autoskillit/config/defaults.yaml +++ b/src/autoskillit/config/defaults.yaml @@ -118,7 +118,7 @@ logging: json_output: null diagnostics: - post_run_analysis: false + pipeline_health: false linux_tracing: enabled: true diff --git a/src/autoskillit/config/ingredient_defaults.py b/src/autoskillit/config/ingredient_defaults.py index 1dce9b5b11..32b264af59 100644 --- a/src/autoskillit/config/ingredient_defaults.py +++ b/src/autoskillit/config/ingredient_defaults.py @@ -135,7 +135,7 @@ def iter_display_categories( SERVER_AUTHORITATIVE_KEY_HINTS: dict[str, str] = {} -CONFIG_DEFAULT_INGREDIENTS: frozenset[str] = frozenset({"post_run_diagnostics"}) +CONFIG_DEFAULT_INGREDIENTS: frozenset[str] = frozenset({"pipeline_health"}) def build_config_default_layer(defaults: dict[str, str]) -> dict[str, str]: @@ -169,13 +169,13 @@ def resolve_ingredient_defaults(project_dir: Path) -> dict[str, str]: resolved["base_branch"] = cfg.branching.default_base_branch resolved["local_review_rounds"] = str(cfg.review.local_review_rounds) resolved["adversarial_review_level"] = cfg.plan.adversarial_review_level - resolved["post_run_diagnostics"] = str(cfg.diagnostics.post_run_analysis).lower() + resolved["pipeline_health"] = str(cfg.diagnostics.pipeline_health).lower() except Exception: logger.warning("resolve_base_branch_failed", exc_info=True) resolved["base_branch"] = "main" resolved["local_review_rounds"] = "0" resolved["adversarial_review_level"] = "auto" - resolved["post_run_diagnostics"] = "false" + resolved["pipeline_health"] = "false" # Fleet dispatch detection — reads env vars, not config, so must run unconditionally. resolved["is_fleet_dispatch"] = "true" if os.environ.get(DISPATCH_ID_ENV_VAR) else "false" diff --git a/src/autoskillit/migrations/0.10.884-to-0.10.885.yaml b/src/autoskillit/migrations/0.10.884-to-0.10.885.yaml new file mode 100644 index 0000000000..30ba4e5318 --- /dev/null +++ b/src/autoskillit/migrations/0.10.884-to-0.10.885.yaml @@ -0,0 +1,27 @@ +from_version: "0.10.884" +to_version: "0.10.885" +description: > + Diagnostics configuration rename: diagnostics.post_run_analysis is now + diagnostics.pipeline_health. +changes: + - id: diagnostics-post-run-analysis-to-pipeline-health + description: > + The diagnostics.post_run_analysis config key has been renamed to + diagnostics.pipeline_health. The value and default behavior are unchanged. + instruction: | + In your user or project .autoskillit/config.yaml, replace: + diagnostics: + post_run_analysis: true + with: + diagnostics: + pipeline_health: true + Preserve the configured boolean value. The old 'post_run_analysis' key is + no longer recognized and will raise a ConfigSchemaError at startup. + detect: + key: diagnostics.post_run_analysis + example_before: | + diagnostics: + post_run_analysis: true + example_after: | + diagnostics: + pipeline_health: true diff --git a/src/autoskillit/recipes/campaigns/promote-to-main.json b/src/autoskillit/recipes/campaigns/promote-to-main.json index 0aff7b84cb..14771d9c15 100644 --- a/src/autoskillit/recipes/campaigns/promote-to-main.json +++ b/src/autoskillit/recipes/campaigns/promote-to-main.json @@ -39,7 +39,7 @@ "default": "200000", "hidden": true }, - "post_run_diagnostics": { + "pipeline_health": { "description": "Run diagnostic analysis after pipeline completion", "default": "false", "hidden": true @@ -132,7 +132,7 @@ "name": "consolidate-diagnostics", "recipe": "consolidate-health-reports", "task": "Consolidate pipeline health reports from all dispatches in this campaign.", - "skip_when": "${{ inputs.post_run_diagnostics }} == false", + "skip_when": "${{ inputs.pipeline_health }} == false", "ingredients": { "kitchen_id": "${{ inputs.kitchen_id }}", "diagnostics_log_dir": "${{ inputs.diagnostics_log_dir }}" diff --git a/src/autoskillit/recipes/campaigns/promote-to-main.yaml b/src/autoskillit/recipes/campaigns/promote-to-main.yaml index 1b098c3e40..296e671859 100644 --- a/src/autoskillit/recipes/campaigns/promote-to-main.yaml +++ b/src/autoskillit/recipes/campaigns/promote-to-main.yaml @@ -36,7 +36,7 @@ ingredients: description: "Model context window in tokens; set to 1000000 for Opus 1M" default: "200000" hidden: true - post_run_diagnostics: + pipeline_health: description: Run diagnostic analysis after pipeline completion default: "false" hidden: true @@ -110,7 +110,7 @@ dispatches: - name: consolidate-diagnostics recipe: consolidate-health-reports task: "Consolidate pipeline health reports from all dispatches in this campaign." - skip_when: "${{ inputs.post_run_diagnostics }} == false" + skip_when: "${{ inputs.pipeline_health }} == false" ingredients: kitchen_id: "${{ inputs.kitchen_id }}" diagnostics_log_dir: "${{ inputs.diagnostics_log_dir }}" diff --git a/src/autoskillit/recipes/diagrams/implementation-groups.md b/src/autoskillit/recipes/diagrams/implementation-groups.md index 8a66dd7ac4..03c23d2864 100644 --- a/src/autoskillit/recipes/diagrams/implementation-groups.md +++ b/src/autoskillit/recipes/diagrams/implementation-groups.md @@ -1,4 +1,4 @@ - + ## implementation-groups diff --git a/src/autoskillit/recipes/diagrams/implementation.md b/src/autoskillit/recipes/diagrams/implementation.md index 6002f8423c..afa48ae3e1 100644 --- a/src/autoskillit/recipes/diagrams/implementation.md +++ b/src/autoskillit/recipes/diagrams/implementation.md @@ -1,4 +1,4 @@ - + ## implementation diff --git a/src/autoskillit/recipes/diagrams/merge-prs.md b/src/autoskillit/recipes/diagrams/merge-prs.md index 28a3552002..8815d135d0 100644 --- a/src/autoskillit/recipes/diagrams/merge-prs.md +++ b/src/autoskillit/recipes/diagrams/merge-prs.md @@ -1,4 +1,4 @@ - + ## merge-prs Merge multiple PRs into an integration branch with conflict resolution and CI gates. diff --git a/src/autoskillit/recipes/diagrams/remediation.md b/src/autoskillit/recipes/diagrams/remediation.md index 56ef04f673..654c4b3cfc 100644 --- a/src/autoskillit/recipes/diagrams/remediation.md +++ b/src/autoskillit/recipes/diagrams/remediation.md @@ -1,4 +1,4 @@ - + ## remediation diff --git a/src/autoskillit/recipes/implementation-groups.json b/src/autoskillit/recipes/implementation-groups.json index e8f9d2c7d7..930036e77d 100644 --- a/src/autoskillit/recipes/implementation-groups.json +++ b/src/autoskillit/recipes/implementation-groups.json @@ -106,7 +106,7 @@ "default": "false", "hidden": true }, - "post_run_diagnostics": { + "pipeline_health": { "description": "Run diagnostic analysis after pipeline completion", "default": "false", "hidden": true @@ -1605,20 +1605,20 @@ "status": "error", "step_name": "register_clone_no_ci" }, - "on_success": "run_diagnostic_no_ci", - "on_failure": "run_diagnostic_no_ci" + "on_success": "analyze_pipeline_health_no_ci", + "on_failure": "analyze_pipeline_health_no_ci" }, - "run_diagnostic_no_ci": { + "analyze_pipeline_health_no_ci": { "description": "Run post-pipeline diagnostic analysis on session logs (no-CI path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop_no_ci", "on_failure": "escalate_stop_no_ci", @@ -2518,21 +2518,21 @@ "status": "unconfirmed", "step_name": "register_clone_unconfirmed" }, - "on_success": "run_diagnostic_unconfirmed", - "on_failure": "run_diagnostic_unconfirmed", + "on_success": "analyze_pipeline_health_unconfirmed", + "on_failure": "analyze_pipeline_health_unconfirmed", "note": "Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection.\n" }, - "run_diagnostic_unconfirmed": { + "analyze_pipeline_health_unconfirmed": { "description": "Run post-pipeline diagnostic analysis (unconfirmed path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_unconfirmed", "on_failure": "done_unconfirmed", @@ -2634,20 +2634,20 @@ "status": "success", "step_name": "register_clone_success" }, - "on_success": "run_diagnostic", - "on_failure": "run_diagnostic" + "on_success": "analyze_pipeline_health", + "on_failure": "analyze_pipeline_health" }, - "run_diagnostic": { + "analyze_pipeline_health": { "description": "Run post-pipeline diagnostic analysis on session logs", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done", "on_failure": "done", @@ -2663,20 +2663,20 @@ "status": "error", "step_name": "register_clone_failure" }, - "on_success": "run_diagnostic_error", - "on_failure": "run_diagnostic_error" + "on_success": "analyze_pipeline_health_error", + "on_failure": "analyze_pipeline_health_error" }, - "run_diagnostic_error": { + "analyze_pipeline_health_error": { "description": "Run post-pipeline diagnostic analysis on session logs (error path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop", "on_failure": "escalate_stop", diff --git a/src/autoskillit/recipes/implementation-groups.yaml b/src/autoskillit/recipes/implementation-groups.yaml index 81431b6355..9e34afbe48 100644 --- a/src/autoskillit/recipes/implementation-groups.yaml +++ b/src/autoskillit/recipes/implementation-groups.yaml @@ -91,7 +91,7 @@ ingredients: description: "Set to 'true' when process-issues has already claimed this issue upfront. Allows claim_issue defense step to pass through without aborting." default: "false" hidden: true - post_run_diagnostics: + pipeline_health: description: Run diagnostic analysis after pipeline completion default: 'false' hidden: true @@ -1440,21 +1440,21 @@ steps: clone_path: "${{ context.work_dir }}" status: "error" step_name: register_clone_no_ci - on_success: run_diagnostic_no_ci - on_failure: run_diagnostic_no_ci + on_success: analyze_pipeline_health_no_ci + on_failure: analyze_pipeline_health_no_ci - run_diagnostic_no_ci: + analyze_pipeline_health_no_ci: description: Run post-pipeline diagnostic analysis on session logs (no-CI path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop_no_ci on_failure: escalate_stop_no_ci on_context_limit: escalate_stop_no_ci @@ -2252,26 +2252,26 @@ steps: clone_path: "${{ context.work_dir }}" status: "unconfirmed" step_name: register_clone_unconfirmed - on_success: run_diagnostic_unconfirmed - on_failure: run_diagnostic_unconfirmed + on_success: analyze_pipeline_health_unconfirmed + on_failure: analyze_pipeline_health_unconfirmed note: > Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection. - run_diagnostic_unconfirmed: + analyze_pipeline_health_unconfirmed: description: Run post-pipeline diagnostic analysis (unconfirmed path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_unconfirmed on_failure: done_unconfirmed on_context_limit: done_unconfirmed @@ -2390,21 +2390,21 @@ steps: clone_path: "${{ context.work_dir }}" status: "success" step_name: register_clone_success - on_success: run_diagnostic - on_failure: run_diagnostic + on_success: analyze_pipeline_health + on_failure: analyze_pipeline_health - run_diagnostic: + analyze_pipeline_health: description: Run post-pipeline diagnostic analysis on session logs tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done on_failure: done on_context_limit: done @@ -2420,21 +2420,21 @@ steps: clone_path: "${{ context.work_dir }}" status: "error" step_name: register_clone_failure - on_success: run_diagnostic_error - on_failure: run_diagnostic_error + on_success: analyze_pipeline_health_error + on_failure: analyze_pipeline_health_error - run_diagnostic_error: + analyze_pipeline_health_error: description: Run post-pipeline diagnostic analysis on session logs (error path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop on_failure: escalate_stop on_context_limit: escalate_stop @@ -2455,4 +2455,3 @@ steps: Pipeline failed — human intervention needed. Check the worktree and plan for details. Emit the L3 result sentinel JSON block now with success=false. Example sentinel: {"success": false, "reason": "implementation-groups pipeline failed"} - diff --git a/src/autoskillit/recipes/implementation.json b/src/autoskillit/recipes/implementation.json index 1f7641bcca..ec63b86eef 100644 --- a/src/autoskillit/recipes/implementation.json +++ b/src/autoskillit/recipes/implementation.json @@ -116,7 +116,7 @@ "default": "6", "hidden": true }, - "post_run_diagnostics": { + "pipeline_health": { "description": "Run diagnostic analysis after pipeline completion", "default": "false", "hidden": true @@ -1677,20 +1677,20 @@ "status": "error", "step_name": "register_clone_no_ci" }, - "on_success": "run_diagnostic_no_ci", - "on_failure": "run_diagnostic_no_ci" + "on_success": "analyze_pipeline_health_no_ci", + "on_failure": "analyze_pipeline_health_no_ci" }, - "run_diagnostic_no_ci": { + "analyze_pipeline_health_no_ci": { "description": "Run post-pipeline diagnostic analysis on session logs (no-CI path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop_no_ci", "on_failure": "escalate_stop_no_ci", @@ -2657,21 +2657,21 @@ "status": "unconfirmed", "step_name": "register_clone_unconfirmed" }, - "on_success": "run_diagnostic_unconfirmed", - "on_failure": "run_diagnostic_unconfirmed", + "on_success": "analyze_pipeline_health_unconfirmed", + "on_failure": "analyze_pipeline_health_unconfirmed", "note": "Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection.\n" }, - "run_diagnostic_unconfirmed": { + "analyze_pipeline_health_unconfirmed": { "description": "Run post-pipeline diagnostic analysis on session logs (unconfirmed path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_unconfirmed", "on_failure": "done_unconfirmed", @@ -2703,8 +2703,8 @@ "status": "success", "step_name": "register_clone_success" }, - "on_success": "run_diagnostic", - "on_failure": "run_diagnostic" + "on_success": "analyze_pipeline_health", + "on_failure": "analyze_pipeline_health" }, "register_clone_failure": { "description": "Register clone as preserved (error pipeline)", @@ -2714,20 +2714,20 @@ "status": "error", "step_name": "register_clone_failure" }, - "on_success": "run_diagnostic_error", - "on_failure": "run_diagnostic_error" + "on_success": "analyze_pipeline_health_error", + "on_failure": "analyze_pipeline_health_error" }, - "run_diagnostic": { + "analyze_pipeline_health": { "description": "Run post-pipeline diagnostic analysis on session logs", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done", "on_failure": "done", @@ -2735,17 +2735,17 @@ "on_rate_limit": "done", "note": "Execute this diagnostic step. Failures are logged but do not alter pipeline routing. Both on_failure and on_context_limit route to the same terminal as on_success.\n" }, - "run_diagnostic_error": { + "analyze_pipeline_health_error": { "description": "Run post-pipeline diagnostic analysis on session logs (error path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop", "on_failure": "escalate_stop", @@ -2761,20 +2761,20 @@ "status": "success", "step_name": "register_clone_no_changes" }, - "on_success": "run_diagnostic_no_changes", - "on_failure": "run_diagnostic_no_changes" + "on_success": "analyze_pipeline_health_no_changes", + "on_failure": "analyze_pipeline_health_no_changes" }, - "run_diagnostic_no_changes": { + "analyze_pipeline_health_no_changes": { "description": "Run post-pipeline diagnostic analysis (zero-change path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_no_changes", "on_failure": "done_no_changes", @@ -2790,20 +2790,20 @@ "status": "success", "step_name": "register_clone_already_done" }, - "on_success": "run_diagnostic_already_done", - "on_failure": "run_diagnostic_already_done" + "on_success": "analyze_pipeline_health_already_done", + "on_failure": "analyze_pipeline_health_already_done" }, - "run_diagnostic_already_done": { + "analyze_pipeline_health_already_done": { "description": "Run post-pipeline diagnostic analysis (already-done path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_already_done", "on_failure": "done_already_done", diff --git a/src/autoskillit/recipes/implementation.yaml b/src/autoskillit/recipes/implementation.yaml index d458f886de..7ff9854ad8 100644 --- a/src/autoskillit/recipes/implementation.yaml +++ b/src/autoskillit/recipes/implementation.yaml @@ -107,7 +107,7 @@ ingredients: to build-execution-map. Must be a positive integer (expressed as a string). default: '6' hidden: true - post_run_diagnostics: + pipeline_health: description: Run diagnostic analysis after pipeline completion default: 'false' hidden: true @@ -1524,21 +1524,21 @@ steps: clone_path: ${{ context.work_dir }} status: error step_name: register_clone_no_ci - on_success: run_diagnostic_no_ci - on_failure: run_diagnostic_no_ci - run_diagnostic_no_ci: + on_success: analyze_pipeline_health_no_ci + on_failure: analyze_pipeline_health_no_ci + analyze_pipeline_health_no_ci: description: Run post-pipeline diagnostic analysis on session logs (no-CI path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop_no_ci on_failure: escalate_stop_no_ci on_context_limit: escalate_stop_no_ci @@ -2420,28 +2420,28 @@ steps: clone_path: ${{ context.work_dir }} status: unconfirmed step_name: register_clone_unconfirmed - on_success: run_diagnostic_unconfirmed - on_failure: run_diagnostic_unconfirmed + on_success: analyze_pipeline_health_unconfirmed + on_failure: analyze_pipeline_health_unconfirmed note: 'Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection. ' - run_diagnostic_unconfirmed: + analyze_pipeline_health_unconfirmed: description: Run post-pipeline diagnostic analysis on session logs (unconfirmed path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_unconfirmed on_failure: done_unconfirmed on_context_limit: done_unconfirmed @@ -2475,8 +2475,8 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_success - on_success: run_diagnostic - on_failure: run_diagnostic + on_success: analyze_pipeline_health + on_failure: analyze_pipeline_health register_clone_failure: description: Register clone as preserved (error pipeline) tool: register_clone_status @@ -2484,21 +2484,21 @@ steps: clone_path: ${{ context.work_dir }} status: error step_name: register_clone_failure - on_success: run_diagnostic_error - on_failure: run_diagnostic_error - run_diagnostic: + on_success: analyze_pipeline_health_error + on_failure: analyze_pipeline_health_error + analyze_pipeline_health: description: Run post-pipeline diagnostic analysis on session logs tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done on_failure: done on_context_limit: done @@ -2507,19 +2507,19 @@ steps: routing. Both on_failure and on_context_limit route to the same terminal as on_success. ' - run_diagnostic_error: + analyze_pipeline_health_error: description: Run post-pipeline diagnostic analysis on session logs (error path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop on_failure: escalate_stop on_context_limit: escalate_stop @@ -2535,21 +2535,21 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_no_changes - on_success: run_diagnostic_no_changes - on_failure: run_diagnostic_no_changes - run_diagnostic_no_changes: + on_success: analyze_pipeline_health_no_changes + on_failure: analyze_pipeline_health_no_changes + analyze_pipeline_health_no_changes: description: Run post-pipeline diagnostic analysis (zero-change path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_no_changes on_failure: done_no_changes on_context_limit: done_no_changes @@ -2565,21 +2565,21 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_already_done - on_success: run_diagnostic_already_done - on_failure: run_diagnostic_already_done - run_diagnostic_already_done: + on_success: analyze_pipeline_health_already_done + on_failure: analyze_pipeline_health_already_done + analyze_pipeline_health_already_done: description: Run post-pipeline diagnostic analysis (already-done path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_already_done on_failure: done_already_done on_context_limit: done_already_done diff --git a/src/autoskillit/recipes/merge-prs.json b/src/autoskillit/recipes/merge-prs.json index 4f211af5f3..8270aff65e 100644 --- a/src/autoskillit/recipes/merge-prs.json +++ b/src/autoskillit/recipes/merge-prs.json @@ -42,7 +42,7 @@ "description": "Plan files for audit", "default": "{{AUTOSKILLIT_TEMP}}/merge-prs" }, - "post_run_diagnostics": { + "pipeline_health": { "description": "Run diagnostic analysis after pipeline completion", "default": "false", "hidden": true @@ -1792,8 +1792,8 @@ "status": "success", "step_name": "register_clone_success" }, - "on_success": "run_diagnostic", - "on_failure": "run_diagnostic" + "on_success": "analyze_pipeline_health", + "on_failure": "analyze_pipeline_health" }, "register_clone_failure": { "description": "Register clone as preserved (error pipeline)", @@ -1803,20 +1803,20 @@ "status": "error", "step_name": "register_clone_failure" }, - "on_success": "run_diagnostic_error", - "on_failure": "run_diagnostic_error" + "on_success": "analyze_pipeline_health_error", + "on_failure": "analyze_pipeline_health_error" }, - "run_diagnostic": { + "analyze_pipeline_health": { "description": "Run post-pipeline diagnostic analysis on session logs", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done", "on_failure": "done", @@ -1824,17 +1824,17 @@ "on_rate_limit": "done", "note": "Execute this diagnostic step. Failures are logged but do not alter pipeline routing. Both on_failure and on_context_limit route to the same terminal as on_success.\n" }, - "run_diagnostic_error": { + "analyze_pipeline_health_error": { "description": "Run post-pipeline diagnostic analysis on session logs (error path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop", "on_failure": "escalate_stop", diff --git a/src/autoskillit/recipes/merge-prs.yaml b/src/autoskillit/recipes/merge-prs.yaml index 2926334cd8..5a26e35e84 100644 --- a/src/autoskillit/recipes/merge-prs.yaml +++ b/src/autoskillit/recipes/merge-prs.yaml @@ -39,7 +39,7 @@ ingredients: plans_dir: description: Plan files for audit default: '{{AUTOSKILLIT_TEMP}}/merge-prs' - post_run_diagnostics: + pipeline_health: description: Run diagnostic analysis after pipeline completion default: 'false' hidden: true @@ -1729,8 +1729,8 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_success - on_success: run_diagnostic - on_failure: run_diagnostic + on_success: analyze_pipeline_health + on_failure: analyze_pipeline_health register_clone_failure: description: Register clone as preserved (error pipeline) tool: register_clone_status @@ -1738,21 +1738,21 @@ steps: clone_path: ${{ context.work_dir }} status: error step_name: register_clone_failure - on_success: run_diagnostic_error - on_failure: run_diagnostic_error - run_diagnostic: + on_success: analyze_pipeline_health_error + on_failure: analyze_pipeline_health_error + analyze_pipeline_health: description: Run post-pipeline diagnostic analysis on session logs tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done on_failure: done on_context_limit: done @@ -1761,19 +1761,19 @@ steps: routing. Both on_failure and on_context_limit route to the same terminal as on_success. ' - run_diagnostic_error: + analyze_pipeline_health_error: description: Run post-pipeline diagnostic analysis on session logs (error path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop on_failure: escalate_stop on_context_limit: escalate_stop diff --git a/src/autoskillit/recipes/remediation.json b/src/autoskillit/recipes/remediation.json index f2bd212820..f8a693ccb4 100644 --- a/src/autoskillit/recipes/remediation.json +++ b/src/autoskillit/recipes/remediation.json @@ -128,7 +128,7 @@ "default": "6", "hidden": true }, - "post_run_diagnostics": { + "pipeline_health": { "description": "Run diagnostic analysis after pipeline completion", "default": "false", "hidden": true @@ -1891,20 +1891,20 @@ "status": "error", "step_name": "register_clone_no_ci" }, - "on_success": "run_diagnostic_no_ci", - "on_failure": "run_diagnostic_no_ci" + "on_success": "analyze_pipeline_health_no_ci", + "on_failure": "analyze_pipeline_health_no_ci" }, - "run_diagnostic_no_ci": { + "analyze_pipeline_health_no_ci": { "description": "Run post-pipeline diagnostic analysis on session logs (no-CI path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop_no_ci", "on_failure": "escalate_stop_no_ci", @@ -2843,21 +2843,21 @@ "status": "unconfirmed", "step_name": "register_clone_unconfirmed" }, - "on_success": "run_diagnostic_unconfirmed", - "on_failure": "run_diagnostic_unconfirmed", + "on_success": "analyze_pipeline_health_unconfirmed", + "on_failure": "analyze_pipeline_health_unconfirmed", "note": "Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection.\n" }, - "run_diagnostic_unconfirmed": { + "analyze_pipeline_health_unconfirmed": { "description": "Run post-pipeline diagnostic analysis on session logs (unconfirmed path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_unconfirmed", "on_failure": "done_unconfirmed", @@ -2917,8 +2917,8 @@ "status": "success", "step_name": "register_clone_success" }, - "on_success": "run_diagnostic", - "on_failure": "run_diagnostic" + "on_success": "analyze_pipeline_health", + "on_failure": "analyze_pipeline_health" }, "register_clone_failure": { "description": "Register clone as preserved (error pipeline)", @@ -2928,20 +2928,20 @@ "status": "error", "step_name": "register_clone_failure" }, - "on_success": "run_diagnostic_error", - "on_failure": "run_diagnostic_error" + "on_success": "analyze_pipeline_health_error", + "on_failure": "analyze_pipeline_health_error" }, - "run_diagnostic": { + "analyze_pipeline_health": { "description": "Run post-pipeline diagnostic analysis on session logs", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done", "on_failure": "done", @@ -2949,17 +2949,17 @@ "on_rate_limit": "done", "note": "Execute this diagnostic step. Failures are logged but do not alter pipeline routing. Both on_failure and on_context_limit route to the same terminal as on_success.\n" }, - "run_diagnostic_error": { + "analyze_pipeline_health_error": { "description": "Run post-pipeline diagnostic analysis on session logs (error path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "escalate_stop", "on_failure": "escalate_stop", @@ -2975,20 +2975,20 @@ "status": "success", "step_name": "register_clone_no_changes" }, - "on_success": "run_diagnostic_no_changes", - "on_failure": "run_diagnostic_no_changes" + "on_success": "analyze_pipeline_health_no_changes", + "on_failure": "analyze_pipeline_health_no_changes" }, - "run_diagnostic_no_changes": { + "analyze_pipeline_health_no_changes": { "description": "Run post-pipeline diagnostic analysis (zero-change path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_no_changes", "on_failure": "done_no_changes", @@ -3004,20 +3004,20 @@ "status": "success", "step_name": "register_clone_already_done" }, - "on_success": "run_diagnostic_already_done", - "on_failure": "run_diagnostic_already_done" + "on_success": "analyze_pipeline_health_already_done", + "on_failure": "analyze_pipeline_health_already_done" }, - "run_diagnostic_already_done": { + "analyze_pipeline_health_already_done": { "description": "Run post-pipeline diagnostic analysis (already-done path)", "tool": "run_skill", "model": "", "stale_threshold": 2400, "optional": true, - "skip_when_false": "inputs.post_run_diagnostics", + "skip_when_false": "inputs.pipeline_health", "with": { "skill_command": "/autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }}", "cwd": "${{ context.work_dir }}", - "step_name": "post_run_diagnostics" + "step_name": "analyze_pipeline_health" }, "on_success": "done_already_done", "on_failure": "done_already_done", diff --git a/src/autoskillit/recipes/remediation.yaml b/src/autoskillit/recipes/remediation.yaml index 8b7cf58218..3ebaba6dce 100644 --- a/src/autoskillit/recipes/remediation.yaml +++ b/src/autoskillit/recipes/remediation.yaml @@ -140,7 +140,7 @@ ingredients: to build-execution-map. Must be a positive integer (expressed as a string). default: '6' hidden: true - post_run_diagnostics: + pipeline_health: description: Run diagnostic analysis after pipeline completion default: 'false' hidden: true @@ -1719,21 +1719,21 @@ steps: clone_path: ${{ context.work_dir }} status: error step_name: register_clone_no_ci - on_success: run_diagnostic_no_ci - on_failure: run_diagnostic_no_ci - run_diagnostic_no_ci: + on_success: analyze_pipeline_health_no_ci + on_failure: analyze_pipeline_health_no_ci + analyze_pipeline_health_no_ci: description: Run post-pipeline diagnostic analysis on session logs (no-CI path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop_no_ci on_failure: escalate_stop_no_ci on_context_limit: escalate_stop_no_ci @@ -2581,28 +2581,28 @@ steps: clone_path: ${{ context.work_dir }} status: unconfirmed step_name: register_clone_unconfirmed - on_success: run_diagnostic_unconfirmed - on_failure: run_diagnostic_unconfirmed + on_success: analyze_pipeline_health_unconfirmed + on_failure: analyze_pipeline_health_unconfirmed note: 'Called when a merge-wait step times out before merge is confirmed. Does NOT call release_issue — the in-progress label stays on the issue so operators can see the PR is still actively queued. The clone is preserved (status: unconfirmed) for human inspection. ' - run_diagnostic_unconfirmed: + analyze_pipeline_health_unconfirmed: description: Run post-pipeline diagnostic analysis on session logs (unconfirmed path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_unconfirmed on_failure: done_unconfirmed on_context_limit: done_unconfirmed @@ -2668,8 +2668,8 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_success - on_success: run_diagnostic - on_failure: run_diagnostic + on_success: analyze_pipeline_health + on_failure: analyze_pipeline_health register_clone_failure: description: Register clone as preserved (error pipeline) tool: register_clone_status @@ -2677,21 +2677,21 @@ steps: clone_path: ${{ context.work_dir }} status: error step_name: register_clone_failure - on_success: run_diagnostic_error - on_failure: run_diagnostic_error - run_diagnostic: + on_success: analyze_pipeline_health_error + on_failure: analyze_pipeline_health_error + analyze_pipeline_health: description: Run post-pipeline diagnostic analysis on session logs tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done on_failure: done on_context_limit: done @@ -2700,19 +2700,19 @@ steps: routing. Both on_failure and on_context_limit route to the same terminal as on_success. ' - run_diagnostic_error: + analyze_pipeline_health_error: description: Run post-pipeline diagnostic analysis on session logs (error path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: escalate_stop on_failure: escalate_stop on_context_limit: escalate_stop @@ -2728,21 +2728,21 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_no_changes - on_success: run_diagnostic_no_changes - on_failure: run_diagnostic_no_changes - run_diagnostic_no_changes: + on_success: analyze_pipeline_health_no_changes + on_failure: analyze_pipeline_health_no_changes + analyze_pipeline_health_no_changes: description: Run post-pipeline diagnostic analysis (zero-change path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_no_changes on_failure: done_no_changes on_context_limit: done_no_changes @@ -2758,21 +2758,21 @@ steps: clone_path: ${{ context.work_dir }} status: success step_name: register_clone_already_done - on_success: run_diagnostic_already_done - on_failure: run_diagnostic_already_done - run_diagnostic_already_done: + on_success: analyze_pipeline_health_already_done + on_failure: analyze_pipeline_health_already_done + analyze_pipeline_health_already_done: description: Run post-pipeline diagnostic analysis (already-done path) tool: run_skill model: '' stale_threshold: 2400 optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:analyze-pipeline-health ${{ inputs.kitchen_id }} --dispatch-id=${{ inputs.dispatch_id }} --diagnostics-log-dir=${{ inputs.diagnostics_log_dir }} cwd: ${{ context.work_dir }} - step_name: post_run_diagnostics + step_name: analyze_pipeline_health on_success: done_already_done on_failure: done_already_done on_context_limit: done_already_done diff --git a/src/autoskillit/server/tools/tools_kitchen.py b/src/autoskillit/server/tools/tools_kitchen.py index 6fdf1365aa..c572b21802 100644 --- a/src/autoskillit/server/tools/tools_kitchen.py +++ b/src/autoskillit/server/tools/tools_kitchen.py @@ -787,7 +787,7 @@ async def open_kitchen( with ``authority: config`` (base_branch, local_review_rounds, adversarial_review_level) cannot be set via overrides — they resolve from server config and caller values are ignored with a warning. - Config-default ingredients (post_run_diagnostics) use config as the default + Config-default ingredients (pipeline_health) use config as the default but an explicit override wins. ingredients_only: When True and name is provided, return only the ingredient schema (ingredients_table, validity, suggestions) without the full recipe diff --git a/tests/arch/test_subpackage_isolation.py b/tests/arch/test_subpackage_isolation.py index d6bfaf483f..288abb4011 100644 --- a/tests/arch/test_subpackage_isolation.py +++ b/tests/arch/test_subpackage_isolation.py @@ -1013,7 +1013,7 @@ def test_data_directories_are_not_python_packages() -> None: "_dispatch_infeasible_response accepting capability_detail kwarg for none_pass " "diagnostic enrichment (+24 net lines)" "; config-default ingredient layer: build_config_default_layer call and " - "docstring update for post_run_diagnostics demotion (+10 net lines)" + "docstring update for pipeline_health demotion (+10 net lines)" "; get_recipe session_serve_overrides replay via serve_recipe; " "deferred-recall snapshot update guard (+3 net lines)" "; per-step backend override config_backend kwarg threading (+5 net lines)" diff --git a/tests/config/test_config.py b/tests/config/test_config.py index 4f92813cd7..023835ef65 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -48,9 +48,9 @@ def test_default_model_config(self): assert cfg.model.provider == "anthropic" def test_diagnostics_config_defaults(self): - """DIAG_C1: DiagnosticsConfig.post_run_analysis defaults to False.""" + """DIAG_C1: DiagnosticsConfig.pipeline_health defaults to False.""" cfg = AutomationConfig() - assert cfg.diagnostics.post_run_analysis is False + assert cfg.diagnostics.pipeline_health is False def test_model_provider_custom(self): """MOD_C4: CoreRunConfig accepts custom provider.""" @@ -173,14 +173,14 @@ def test_load_yaml_full_config(self, tmp_path): assert cfg.worktree_setup.command == ["task", "install-worktree"] def test_load_diagnostics_config(self, tmp_path): - """DIAG_C2: diagnostics.post_run_analysis can be set via YAML.""" + """DIAG_C2: diagnostics.pipeline_health can be set via YAML.""" config_dir = tmp_path / ".autoskillit" config_dir.mkdir() (config_dir / "config.yaml").write_text( - yaml.dump({"diagnostics": {"post_run_analysis": True}}) + yaml.dump({"diagnostics": {"pipeline_health": True}}) ) cfg = load_config(tmp_path) - assert cfg.diagnostics.post_run_analysis is True + assert cfg.diagnostics.pipeline_health is True def test_partial_yaml_preserves_defaults(self, tmp_path): """C4: YAML with only test_check.command -> other fields keep defaults.""" @@ -290,9 +290,9 @@ def test_yaml_loads_model_config(self, tmp_path): assert cfg.model.provider == "anthropic" def test_diagnostics_config_defaults(self): - """DIAG_C1: DiagnosticsConfig.post_run_analysis defaults to False.""" + """DIAG_C1: DiagnosticsConfig.pipeline_health defaults to False.""" cfg = AutomationConfig() - assert cfg.diagnostics.post_run_analysis is False + assert cfg.diagnostics.pipeline_health is False def test_yaml_loads_model_provider(self, tmp_path): """MOD_C5: YAML model.provider loads into CoreRunConfig.provider.""" diff --git a/tests/config/test_helpers.py b/tests/config/test_helpers.py index 765dbeb1bb..6c506fce37 100644 --- a/tests/config/test_helpers.py +++ b/tests/config/test_helpers.py @@ -77,8 +77,8 @@ def test_resolve_ingredient_defaults_includes_adversarial_review_level(tmp_path) assert defaults.get("adversarial_review_level") is not None -def test_resolve_ingredient_defaults_includes_post_run_diagnostics(tmp_path): - """DIAG_C3: resolve_ingredient_defaults includes post_run_diagnostics default false.""" +def test_resolve_ingredient_defaults_includes_pipeline_health(tmp_path): + """DIAG_C3: resolve_ingredient_defaults includes pipeline_health default false.""" from autoskillit.config import resolve_ingredient_defaults repo = tmp_path / "repo" @@ -90,7 +90,7 @@ def test_resolve_ingredient_defaults_includes_post_run_diagnostics(tmp_path): ) defaults = resolve_ingredient_defaults(repo) - assert defaults.get("post_run_diagnostics") == "false" + assert defaults.get("pipeline_health") == "false" def test_resolve_ingredient_defaults_includes_is_fleet_dispatch_false(tmp_path): @@ -183,7 +183,7 @@ def test_resolve_ingredient_defaults_base_branch_from_config(tmp_path): mock_cfg.branching.default_base_branch = "develop" mock_cfg.review.local_review_rounds = 3 mock_cfg.plan.adversarial_review_level = "aggressive" - mock_cfg.diagnostics.post_run_analysis = False + mock_cfg.diagnostics.pipeline_health = False with patch("autoskillit.config.settings.load_config", return_value=mock_cfg): defaults = resolve_ingredient_defaults(repo) @@ -280,16 +280,16 @@ def test_apply_config_authoritative_overrides_unknown_key_retains_caller_value(t # T4: REQ-ING-003 -def test_post_run_diagnostics_not_server_authoritative() -> None: - """post_run_diagnostics must be a config-default, not server-authoritative.""" +def test_pipeline_health_not_server_authoritative() -> None: + """pipeline_health must be a config-default, not server-authoritative.""" from autoskillit.config import SERVER_AUTHORITATIVE_INGREDIENTS - assert "post_run_diagnostics" not in SERVER_AUTHORITATIVE_INGREDIENTS + assert "pipeline_health" not in SERVER_AUTHORITATIVE_INGREDIENTS # T6: REQ-ING-005 -def test_post_run_diagnostics_in_config_default_ingredients() -> None: - """post_run_diagnostics must be in CONFIG_DEFAULT_INGREDIENTS.""" +def test_pipeline_health_in_config_default_ingredients() -> None: + """pipeline_health must be in CONFIG_DEFAULT_INGREDIENTS.""" from autoskillit.config import CONFIG_DEFAULT_INGREDIENTS - assert "post_run_diagnostics" in CONFIG_DEFAULT_INGREDIENTS + assert "pipeline_health" in CONFIG_DEFAULT_INGREDIENTS diff --git a/tests/execution/backends/test_cli_conformance_probes.py b/tests/execution/backends/test_cli_conformance_probes.py index bab432025e..2454015b4e 100644 --- a/tests/execution/backends/test_cli_conformance_probes.py +++ b/tests/execution/backends/test_cli_conformance_probes.py @@ -938,7 +938,7 @@ def _large_output_prompt(workspace: Path) -> str: '{"task":"test task","issue_url":"https://github.com/test/test/issues/1",' '"is_fleet_dispatch":"true","adversarial_review_level":"true",' '"local_review_rounds":"true","base_branch":"true",' - '"post_run_diagnostics":"true"}. Then make every autoskillit run_cmd call below, ' + '"pipeline_health":"true"}. Then make every autoskillit run_cmd call below, ' "in order. Do not substitute native shell tools and do not omit a call.\n" f"{calls}\nAfter all calls, respond with exactly: probe-complete" ) diff --git a/tests/execution/test_recording_sigterm.py b/tests/execution/test_recording_sigterm.py index 8d146d5c50..24460dd1f0 100644 --- a/tests/execution/test_recording_sigterm.py +++ b/tests/execution/test_recording_sigterm.py @@ -33,6 +33,8 @@ def test_sigterm_writes_scenario_json(tmp_path): output_dir.mkdir() state_dir = tmp_path / "state" state_dir.mkdir() + home_dir = tmp_path / "home" + home_dir.mkdir() env = { **os.environ, @@ -40,12 +42,15 @@ def test_sigterm_writes_scenario_json(tmp_path): "RECORD_SCENARIO_DIR": str(output_dir), "RECORD_SCENARIO_RECIPE": "test-recipe", "AUTOSKILLIT_STATE_DIR": str(state_dir), + "HOME": str(home_dir), } # Use sys.executable -m to ensure we run the worktree-installed version, # not a system-wide `autoskillit` binary that may lack the lifespan fix. - # cwd=tmp_path and AUTOSKILLIT_STATE_DIR isolate the subprocess's - # filesystem state from the project tree (e.g. any real execution - # markers under CWD) so the sentinel location is deterministic. + # cwd=tmp_path, AUTOSKILLIT_STATE_DIR, and HOME isolate the subprocess's + # filesystem state from the project tree and the developer's real + # ~/.autoskillit/config.yaml (e.g. any real execution markers under CWD, + # or stale config keys from a prior schema) so the sentinel location and + # config layers are deterministic. proc = subprocess.Popen( [sys.executable, "-m", "autoskillit"], stdin=subprocess.PIPE, diff --git a/tests/infra/test_pretty_output_recipe.py b/tests/infra/test_pretty_output_recipe.py index 1f9e73b82e..b544178ecc 100644 --- a/tests/infra/test_pretty_output_recipe.py +++ b/tests/infra/test_pretty_output_recipe.py @@ -916,7 +916,7 @@ def _strip_presentation_fields(parsed: dict) -> dict: "adversarial_review_level": "true", "local_review_rounds": "true", "base_branch": "true", - "post_run_diagnostics": "true", + "pipeline_health": "true", }, } @@ -1052,8 +1052,8 @@ def test_canonical_recipe_responses_fit_independent_registry_ceilings(tmp_path, for ingredients_only in (False, True) } assert maxima == { - "load_recipe": (182_759, "remediation", "all_truthy"), - "open_kitchen": (182_818, "remediation", "all_truthy"), + "load_recipe": (183_420, "remediation", "all_truthy"), + "open_kitchen": (183_479, "remediation", "all_truthy"), } diff --git a/tests/migration/AGENTS.md b/tests/migration/AGENTS.md index 7bea21fd20..08596c28b9 100644 --- a/tests/migration/AGENTS.md +++ b/tests/migration/AGENTS.md @@ -12,5 +12,6 @@ Migration engine, store, and loader tests. | `test_engine.py` | Tests for migration_engine.py — ME1 through ME21 | | `test_fleet_migration_note.py` | Fleet migration note tests | | `test_loader.py` | Tests for migration note discovery and version chaining | +| `test_pipeline_health_migration_note.py` | Diagnostics config-key rename migration note tests | | `test_store.py` | Tests for failure_store.py — FS1 through FS11 and FS-IM1 through FS-IM4 | | `test_vis_lens_rename_migration_note.py` | Vis-lens skill rename migration note tests | diff --git a/tests/migration/test_pipeline_health_migration_note.py b/tests/migration/test_pipeline_health_migration_note.py new file mode 100644 index 0000000000..684bf7dcf9 --- /dev/null +++ b/tests/migration/test_pipeline_health_migration_note.py @@ -0,0 +1,25 @@ +"""Tests for the diagnostics pipeline-health config migration note.""" + +import pytest + +from autoskillit.core import load_yaml, pkg_root + +pytestmark = [pytest.mark.layer("migration"), pytest.mark.small] + + +def test_pipeline_health_config_rename_has_migration_note() -> None: + """The persisted diagnostics key rename must have actionable migration guidance.""" + note_path = pkg_root() / "migrations" / "0.10.884-to-0.10.885.yaml" + note = load_yaml(note_path) + changes = note["changes"] + change = next( + item + for item in changes + if item.get("detect", {}).get("key") == "diagnostics.post_run_analysis" + ) + + assert note["from_version"] == "0.10.884" + assert note["to_version"] == "0.10.885" + assert change["instruction"].strip() + assert "post_run_analysis" in change["example_before"] + assert "pipeline_health" in change["example_after"] diff --git a/tests/recipe/test_bundled_recipes_all_truthy.py b/tests/recipe/test_bundled_recipes_all_truthy.py index dc9e029328..580f4e5341 100644 --- a/tests/recipe/test_bundled_recipes_all_truthy.py +++ b/tests/recipe/test_bundled_recipes_all_truthy.py @@ -26,7 +26,7 @@ "adversarial_review_level": "true", "local_review_rounds": "true", "base_branch": "true", - "post_run_diagnostics": "true", + "pipeline_health": "true", } diff --git a/tests/recipe/test_bundled_recipes_general.py b/tests/recipe/test_bundled_recipes_general.py index fcc25d693e..2ae4ab05c6 100644 --- a/tests/recipe/test_bundled_recipes_general.py +++ b/tests/recipe/test_bundled_recipes_general.py @@ -684,18 +684,18 @@ def test_recipe_has_unconditional_register_steps(recipe_name: str) -> None: assert "register_clone_failure" in recipe.steps s = recipe.steps["register_clone_success"] f = recipe.steps["register_clone_failure"] - # Accept direct routing to done/escalate_stop OR indirect via optional run_diagnostic steps - assert s.on_success in ("done", "run_diagnostic"), ( - "register_clone_success.on_success must route to done or run_diagnostic, " + # Accept direct routing or indirect routing through optional pipeline-health analysis + assert s.on_success in ("done", "analyze_pipeline_health"), ( + "register_clone_success.on_success must route to done or analyze_pipeline_health, " f"got {s.on_success!r}" ) - assert f.on_success in ("escalate_stop", "run_diagnostic_error"), ( + assert f.on_success in ("escalate_stop", "analyze_pipeline_health_error"), ( "register_clone_failure.on_success must route to escalate_stop or " - f"run_diagnostic_error, got {f.on_success!r}" + f"analyze_pipeline_health_error, got {f.on_success!r}" ) - assert f.on_failure in ("escalate_stop", "run_diagnostic_error"), ( + assert f.on_failure in ("escalate_stop", "analyze_pipeline_health_error"), ( "register_clone_failure.on_failure must route to escalate_stop or " - f"run_diagnostic_error, got {f.on_failure!r}" + f"analyze_pipeline_health_error, got {f.on_failure!r}" ) assert "check_defer_cleanup" not in recipe.steps assert "check_defer_on_failure" not in recipe.steps diff --git a/tests/recipe/test_check_ci_already_passed_routing.py b/tests/recipe/test_check_ci_already_passed_routing.py index 3e7ed8e151..5e145b129d 100644 --- a/tests/recipe/test_check_ci_already_passed_routing.py +++ b/tests/recipe/test_check_ci_already_passed_routing.py @@ -90,7 +90,7 @@ def test_no_direct_escalate_stop_no_ci_callers_except_safety_net(recipe): "escalate_stop_no_ci", "mark_issue_failed_no_ci", "register_clone_no_ci", - "run_diagnostic_no_ci", + "analyze_pipeline_health_no_ci", } for name, step in recipe.steps.items(): if name in EXCLUDED: @@ -116,14 +116,14 @@ def test_register_clone_no_ci_routes_to_escalate_stop_no_ci(recipe): """register_clone_no_ci registers clone as error and routes toward escalate_stop_no_ci.""" step = recipe.steps["register_clone_no_ci"] assert step.tool == "register_clone_status" - # May route via optional run_diagnostic_no_ci step first - assert step.on_success in ("escalate_stop_no_ci", "run_diagnostic_no_ci"), ( + # May route via optional analyze_pipeline_health_no_ci step first + assert step.on_success in ("escalate_stop_no_ci", "analyze_pipeline_health_no_ci"), ( "register_clone_no_ci.on_success must route to escalate_stop_no_ci " - f"or run_diagnostic_no_ci, got {step.on_success!r}" + f"or analyze_pipeline_health_no_ci, got {step.on_success!r}" ) - assert step.on_failure in ("escalate_stop_no_ci", "run_diagnostic_no_ci"), ( + assert step.on_failure in ("escalate_stop_no_ci", "analyze_pipeline_health_no_ci"), ( "register_clone_no_ci.on_failure must route to escalate_stop_no_ci " - f"or run_diagnostic_no_ci, got {step.on_failure!r}" + f"or analyze_pipeline_health_no_ci, got {step.on_failure!r}" ) assert step.with_args.get("status") == "error" @@ -139,8 +139,8 @@ def test_no_ci_failure_chain_complete(recipe): assert mark_step.on_success == "register_clone_no_ci" reg_step = recipe.steps["register_clone_no_ci"] - # May route via optional run_diagnostic_no_ci step that then routes to escalate_stop_no_ci - assert reg_step.on_success in ("escalate_stop_no_ci", "run_diagnostic_no_ci"), ( + # The optional analysis step may route onward to escalate_stop_no_ci. + assert reg_step.on_success in ("escalate_stop_no_ci", "analyze_pipeline_health_no_ci"), ( "register_clone_no_ci.on_success must route toward escalate_stop_no_ci, " f"got {reg_step.on_success!r}" ) diff --git a/tests/recipe/test_diagnostic_steps.py b/tests/recipe/test_diagnostic_steps.py index d285e0b2cc..dc39d6f48e 100644 --- a/tests/recipe/test_diagnostic_steps.py +++ b/tests/recipe/test_diagnostic_steps.py @@ -39,24 +39,29 @@ def test_analyze_pipeline_health_coordinator_validates_scanners(): ) -# DIAG_C9: run_diagnostic steps have required fields in implementation recipe +# DIAG_C9: analyze_pipeline_health steps have required fields in implementation recipe @pytest.mark.parametrize("recipe_name", ["implementation", "remediation", "merge-prs"]) -def test_run_diagnostic_steps_have_required_fields(recipe_name): - """run_diagnostic steps must have on_context_limit, optional=true, skip_when_false.""" +def test_analyze_pipeline_health_steps_have_required_fields(recipe_name): + """analyze_pipeline_health steps must have required optional-step fields.""" recipe = load_recipe(builtin_recipes_dir() / f"{recipe_name}.yaml") - for name, step in recipe.steps.items(): - if name.startswith("run_diagnostic"): - assert step.on_context_limit is not None, f"{name} missing on_context_limit" - assert step.optional is True, f"{name} optional must be True" - assert step.skip_when_false == "inputs.post_run_diagnostics", ( - f"{name} skip_when_false must be inputs.post_run_diagnostics" - ) + analysis_steps = [ + (name, step) + for name, step in recipe.steps.items() + if name.startswith("analyze_pipeline_health") + ] + assert analysis_steps, f"{recipe_name}: expected at least one analyze_pipeline_health step" + for name, step in analysis_steps: + assert step.on_context_limit is not None, f"{name} missing on_context_limit" + assert step.optional is True, f"{name} optional must be True" + assert step.skip_when_false == "inputs.pipeline_health", ( + f"{name} skip_when_false must be inputs.pipeline_health" + ) # T7: REQ-TEST-004 def test_implementation_family_recipes_route_terminals_through_diagnostics() -> None: """REQ-TEST-004: Every register_clone_* terminal in implementation-family recipes - routes through a run_diagnostic* step gated on post_run_diagnostics.""" + routes through an analyze_pipeline_health* step gated on pipeline_health.""" recipes_dir = builtin_recipes_dir() target_names = ["implementation.yaml", "implementation-groups.yaml"] missing: list[str] = [] @@ -66,8 +71,8 @@ def test_implementation_family_recipes_route_terminals_through_diagnostics() -> missing.append(name) assert not missing, f"Recipe files not found: {missing}" - diag_step_prefixes = ("run_diagnostic",) - required_post_run_refs = ("inputs.post_run_diagnostics",) + diag_step_prefixes = ("analyze_pipeline_health",) + required_post_run_refs = ("inputs.pipeline_health",) for name in target_names: recipe_path = recipes_dir / name @@ -76,14 +81,14 @@ def test_implementation_family_recipes_route_terminals_through_diagnostics() -> clone_steps = [(n, s) for n, s in steps.items() if n.startswith("register_clone_")] assert clone_steps, f"{name}: expected at least one register_clone_* step" for step_name, cs in clone_steps: - # The step must route on_success to a run_diagnostic* step + # The step must route on_success to an analyze_pipeline_health* step next_step = cs.on_success assert next_step is not None, f"{name}: {step_name} has no on_success" assert next_step.startswith(diag_step_prefixes), ( f"{name}: {step_name}.on_success={next_step!r} must start with " f"{diag_step_prefixes!r}" ) - # The run_diagnostic* step must gate on inputs.post_run_diagnostics + # The analyze_pipeline_health* step must gate on inputs.pipeline_health diag = steps.get(next_step) assert diag is not None, ( f"{name}: step {step_name} routes to {next_step!r} but no such step exists" diff --git a/tests/recipe/test_hidden_ingredients.py b/tests/recipe/test_hidden_ingredients.py index fc7aa2ca71..7123d89542 100644 --- a/tests/recipe/test_hidden_ingredients.py +++ b/tests/recipe/test_hidden_ingredients.py @@ -128,7 +128,7 @@ def test_prune_skipped_steps_truthy_clears_field() -> None: name="test", description="test", ingredients={ - "post_run_diagnostics": RecipeIngredient( + "pipeline_health": RecipeIngredient( description="Enable post-run diagnostics", default="false", hidden=True, @@ -141,7 +141,7 @@ def test_prune_skipped_steps_truthy_clears_field() -> None: "diag": RecipeStep( tool="run_skill", optional=True, - skip_when_false="inputs.post_run_diagnostics", + skip_when_false="inputs.pipeline_health", on_success="done", on_failure="done", with_args={"skill_command": "/autoskillit:diagnose /tmp/x.md", "cwd": "/tmp"}, @@ -152,14 +152,14 @@ def test_prune_skipped_steps_truthy_clears_field() -> None: ) pruned, resolutions = _prune_skipped_steps( - recipe, ingredient_overrides={"post_run_diagnostics": "true"} + recipe, ingredient_overrides={"pipeline_health": "true"} ) assert "diag" in pruned.steps assert pruned.steps["diag"].skip_when_false is None assert resolutions["diag"] is True pruned2, resolutions2 = _prune_skipped_steps( - recipe, ingredient_overrides={"post_run_diagnostics": "false"} + recipe, ingredient_overrides={"pipeline_health": "false"} ) assert "diag" not in pruned2.steps assert resolutions2["diag"] is False @@ -173,7 +173,7 @@ def test_prune_skipped_steps_removes_step_and_cleans_routes() -> None: name="test", description="test", ingredients={ - "post_run_diagnostics": RecipeIngredient( + "pipeline_health": RecipeIngredient( description="Enable diagnostics", default="false", hidden=True, @@ -186,7 +186,7 @@ def test_prune_skipped_steps_removes_step_and_cleans_routes() -> None: "diag": RecipeStep( tool="run_skill", optional=True, - skip_when_false="inputs.post_run_diagnostics", + skip_when_false="inputs.pipeline_health", on_success="done", on_failure="done", with_args={"skill_command": "/autoskillit:diagnose /tmp/x.md", "cwd": "/tmp"}, @@ -196,9 +196,7 @@ def test_prune_skipped_steps_removes_step_and_cleans_routes() -> None: kitchen_rules=["test"], ) - pruned, _ = _prune_skipped_steps( - recipe, ingredient_overrides={"post_run_diagnostics": "false"} - ) + pruned, _ = _prune_skipped_steps(recipe, ingredient_overrides={"pipeline_health": "false"}) assert "diag" not in pruned.steps # Route repaired: upstream.on_success now points to diag's on_success (done) assert pruned.steps["upstream"].on_success == "done" @@ -392,7 +390,7 @@ def test_load_and_validate_resolves_skip_guards_in_content(tmp_path: Path) -> No kitchen_rules: - no native tools ingredients: - post_run_diagnostics: + pipeline_health: description: Enable diagnostics default: "false" hidden: true @@ -405,7 +403,7 @@ def test_load_and_validate_resolves_skip_guards_in_content(tmp_path: Path) -> No diag: tool: run_skill optional: true - skip_when_false: inputs.post_run_diagnostics + skip_when_false: inputs.pipeline_health with: skill_command: /autoskillit:diagnose /tmp/x.md cwd: /tmp @@ -422,9 +420,9 @@ def test_load_and_validate_resolves_skip_guards_in_content(tmp_path: Path) -> No result = load_and_validate( "test-skip-guards", project_dir=tmp_path, - ingredient_overrides={"post_run_diagnostics": "true"}, + ingredient_overrides={"pipeline_health": "true"}, ) - assert "inputs.post_run_diagnostics" not in result["content"] + assert "inputs.pipeline_health" not in result["content"] content = result["content"] diag_block_start = content.index(" diag:\n") next_step_start = content.find("\n done:\n", diag_block_start) @@ -435,9 +433,9 @@ def test_load_and_validate_resolves_skip_guards_in_content(tmp_path: Path) -> No result2 = load_and_validate( "test-skip-guards", project_dir=tmp_path, - ingredient_overrides={"post_run_diagnostics": "false"}, + ingredient_overrides={"pipeline_health": "false"}, ) - assert "inputs.post_run_diagnostics" not in result2["content"] + assert "inputs.pipeline_health" not in result2["content"] assert 'skip_when_false: "false"' not in result2["content"] assert " diag:\n" not in result2["content"] diff --git a/tests/recipe/test_implementation.py b/tests/recipe/test_implementation.py index e6deea73bb..74f2f4c2b5 100644 --- a/tests/recipe/test_implementation.py +++ b/tests/recipe/test_implementation.py @@ -244,28 +244,28 @@ def test_done_already_done_stop_exists(recipe) -> None: def test_register_clone_no_changes_routes_to_diagnostic(recipe) -> None: - """register_clone_no_changes must route to run_diagnostic_no_changes.""" + """register_clone_no_changes must route to analyze_pipeline_health_no_changes.""" assert "register_clone_no_changes" in recipe.steps step = recipe.steps["register_clone_no_changes"] - assert step.on_success == "run_diagnostic_no_changes" + assert step.on_success == "analyze_pipeline_health_no_changes" def test_register_clone_already_done_routes_to_diagnostic(recipe) -> None: - """register_clone_already_done must route to run_diagnostic_already_done.""" + """register_clone_already_done must route to analyze_pipeline_health_already_done.""" assert "register_clone_already_done" in recipe.steps step = recipe.steps["register_clone_already_done"] - assert step.on_success == "run_diagnostic_already_done" + assert step.on_success == "analyze_pipeline_health_already_done" def test_register_clone_unconfirmed_routes_to_done_unconfirmed(recipe) -> None: """register_clone_unconfirmed must route toward done_unconfirmed.""" step = recipe.steps["register_clone_unconfirmed"] - # May route via optional run_diagnostic_unconfirmed step first - assert step.on_success in ("done_unconfirmed", "run_diagnostic_unconfirmed"), ( + # May route via optional analyze_pipeline_health_unconfirmed step first + assert step.on_success in ("done_unconfirmed", "analyze_pipeline_health_unconfirmed"), ( "register_clone_unconfirmed.on_success must route toward done_unconfirmed, " f"got {step.on_success!r}" ) - assert step.on_failure in ("done_unconfirmed", "run_diagnostic_unconfirmed"), ( + assert step.on_failure in ("done_unconfirmed", "analyze_pipeline_health_unconfirmed"), ( "register_clone_unconfirmed.on_failure must route toward done_unconfirmed, " f"got {step.on_failure!r}" ) diff --git a/tests/recipe/test_implementation_groups_pr_decomposition.py b/tests/recipe/test_implementation_groups_pr_decomposition.py index a2218caa4f..420cf596a8 100644 --- a/tests/recipe/test_implementation_groups_pr_decomposition.py +++ b/tests/recipe/test_implementation_groups_pr_decomposition.py @@ -68,7 +68,7 @@ def test_done_unconfirmed_stop_exists(recipe) -> None: def test_register_clone_unconfirmed_routes_to_done_unconfirmed(recipe) -> None: - """register_clone_unconfirmed must route to run_diagnostic_unconfirmed.""" + """register_clone_unconfirmed must route to analyze_pipeline_health_unconfirmed.""" step = recipe.steps["register_clone_unconfirmed"] - assert step.on_success == "run_diagnostic_unconfirmed" - assert step.on_failure == "run_diagnostic_unconfirmed" + assert step.on_success == "analyze_pipeline_health_unconfirmed" + assert step.on_failure == "analyze_pipeline_health_unconfirmed" diff --git a/tests/recipe/test_remediation_recipe.py b/tests/recipe/test_remediation_recipe.py index 717c81663c..e4bab32e52 100644 --- a/tests/recipe/test_remediation_recipe.py +++ b/tests/recipe/test_remediation_recipe.py @@ -251,28 +251,28 @@ def test_done_already_done_stop_exists(recipe) -> None: def test_register_clone_no_changes_routes_to_diagnostic(recipe) -> None: - """register_clone_no_changes must route to run_diagnostic_no_changes.""" + """register_clone_no_changes must route to analyze_pipeline_health_no_changes.""" assert "register_clone_no_changes" in recipe.steps step = recipe.steps["register_clone_no_changes"] - assert step.on_success == "run_diagnostic_no_changes" + assert step.on_success == "analyze_pipeline_health_no_changes" def test_register_clone_already_done_routes_to_diagnostic(recipe) -> None: - """register_clone_already_done must route to run_diagnostic_already_done.""" + """register_clone_already_done must route to analyze_pipeline_health_already_done.""" assert "register_clone_already_done" in recipe.steps step = recipe.steps["register_clone_already_done"] - assert step.on_success == "run_diagnostic_already_done" + assert step.on_success == "analyze_pipeline_health_already_done" def test_register_clone_unconfirmed_routes_to_done_unconfirmed(recipe) -> None: """register_clone_unconfirmed must route toward done_unconfirmed.""" step = recipe.steps["register_clone_unconfirmed"] - # May route via optional run_diagnostic_unconfirmed step first - assert step.on_success in ("done_unconfirmed", "run_diagnostic_unconfirmed"), ( + # May route via optional analyze_pipeline_health_unconfirmed step first + assert step.on_success in ("done_unconfirmed", "analyze_pipeline_health_unconfirmed"), ( "register_clone_unconfirmed.on_success must route toward done_unconfirmed, " f"got {step.on_success!r}" ) - assert step.on_failure in ("done_unconfirmed", "run_diagnostic_unconfirmed"), ( + assert step.on_failure in ("done_unconfirmed", "analyze_pipeline_health_unconfirmed"), ( "register_clone_unconfirmed.on_failure must route toward done_unconfirmed, " f"got {step.on_failure!r}" ) diff --git a/tests/server/_helpers.py b/tests/server/_helpers.py index 9cb49aeab6..e83a9886a3 100644 --- a/tests/server/_helpers.py +++ b/tests/server/_helpers.py @@ -106,7 +106,7 @@ def _skill_fail() -> SkillResult: "adversarial_review_level": "aggressive", "is_fleet_dispatch": "true", "dispatch_id": "test-dispatch-999", - "post_run_diagnostics": "true", + "pipeline_health": "true", } _SERVER_ONLY_KEYS = frozenset({"kitchen_id", "diagnostics_log_dir", "backend_supports_git_write"}) diff --git a/tests/server/test_lock_ingredients.py b/tests/server/test_lock_ingredients.py index 89ab72ea83..0462cc0627 100644 --- a/tests/server/test_lock_ingredients.py +++ b/tests/server/test_lock_ingredients.py @@ -490,8 +490,8 @@ async def call_lock(pipeline_id: str) -> None: # T3: REQ-ING-004 @pytest.mark.anyio -async def test_post_run_diagnostics_lockable(tmp_path): - """REQ-ING-004: lock_ingredients accepts post_run_diagnostics.""" +async def test_pipeline_health_lockable(tmp_path): + """REQ-ING-004: lock_ingredients accepts pipeline_health.""" temp_dir = tmp_path / ".autoskillit" / "temp" temp_dir.mkdir(parents=True) (temp_dir / ".hook_config.json").write_text("{}") @@ -503,11 +503,7 @@ async def test_post_run_diagnostics_lockable(tmp_path): with patch("autoskillit.server._get_ctx", return_value=ctx): from autoskillit.server.tools.tools_kitchen import lock_ingredients - result_str = await lock_ingredients( - locked={"post_run_diagnostics": "true"}, pipeline_id="a" - ) + result_str = await lock_ingredients(locked={"pipeline_health": "true"}, pipeline_id="a") result = json.loads(result_str) - assert result.get("success") is True, ( - f"post_run_diagnostics must be lockable; got result={result}" - ) + assert result.get("success") is True, f"pipeline_health must be lockable; got result={result}" diff --git a/tests/server/test_mcp_overrides.py b/tests/server/test_mcp_overrides.py index 75a0405a75..dd63a3f770 100644 --- a/tests/server/test_mcp_overrides.py +++ b/tests/server/test_mcp_overrides.py @@ -64,7 +64,7 @@ async def test_load_recipe_tool_accepts_overrides_param(tmp_path: Path) -> None: assert result.get("valid") is True # Verify user-supplied overrides were passed through to load_and_validate - # (merged with auto-injected kitchen_id and post_run_diagnostics) + # (merged with auto-injected kitchen_id and pipeline_health) mock_recipes.load_and_validate.assert_called_once() call_kwargs = mock_recipes.load_and_validate.call_args actual_overrides = call_kwargs.kwargs.get("ingredient_overrides") or {} @@ -121,7 +121,7 @@ async def test_open_kitchen_accepts_overrides_param(tmp_path: Path) -> None: assert result.get("valid") is True # Verify user-supplied overrides were passed through to load_and_validate - # (merged with auto-injected kitchen_id and post_run_diagnostics) + # (merged with auto-injected kitchen_id and pipeline_health) mock_recipes.load_and_validate.assert_called_once() call_kwargs = mock_recipes.load_and_validate.call_args actual_overrides = call_kwargs.kwargs.get("ingredient_overrides") or {} diff --git a/tests/server/test_tools_kitchen_envelope.py b/tests/server/test_tools_kitchen_envelope.py index e9d8b1ee6f..60e29d685d 100644 --- a/tests/server/test_tools_kitchen_envelope.py +++ b/tests/server/test_tools_kitchen_envelope.py @@ -444,7 +444,7 @@ async def test_open_kitchen_config_authority_overrides_caller(tmp_path, monkeypa "autoskillit.server.tools.tools_kitchen.resolve_ingredient_defaults", return_value={ "base_branch": "develop", - "post_run_diagnostics": "false", + "pipeline_health": "false", "is_fleet_dispatch": "false", "dispatch_id": "", }, @@ -538,7 +538,7 @@ async def test_open_kitchen_with_config_authority_ingredient(monkeypatch): "autoskillit.server.tools.tools_kitchen.resolve_ingredient_defaults", lambda _: { "base_branch": "develop", - "post_run_diagnostics": "false", + "pipeline_health": "false", "is_fleet_dispatch": "false", "dispatch_id": "", }, @@ -1095,21 +1095,21 @@ def test_recipe_validation_error_response_handles_malformed_suggestions(): # --------------------------------------------------------------------------- -# post_run_diagnostics demotion tests (T1, T2, T5) +# pipeline_health demotion tests (T1, T2, T5) # --------------------------------------------------------------------------- # T1: REQ-ING-001 @pytest.mark.anyio -async def test_post_run_diagnostics_override_wins_over_config(tmp_path, monkeypatch): - """REQ-ING-001: open_kitchen override for post_run_diagnostics wins over config.""" +async def test_pipeline_health_override_wins_over_config(tmp_path, monkeypatch): + """REQ-ING-001: open_kitchen override for pipeline_health wins over config.""" monkeypatch.chdir(tmp_path) mock_ctx = _make_mock_ctx() mock_ctx.enable_components = AsyncMock() mock_ctx.recipes = MagicMock() mock_recipe_obj = MagicMock() mock_recipe_obj.steps = {"do": MagicMock()} - mock_recipe_obj.ingredients = {"post_run_diagnostics": MagicMock()} + mock_recipe_obj.ingredients = {"pipeline_health": MagicMock()} mock_ctx.recipes.load.return_value = mock_recipe_obj mock_ctx.recipes.load_and_validate.return_value = { "content": "name: demo\nsteps:\n do:\n tool: run_cmd\n", @@ -1139,7 +1139,7 @@ async def test_post_run_diagnostics_override_wins_over_config(tmp_path, monkeypa "autoskillit.server.tools.tools_kitchen.resolve_ingredient_defaults", return_value={ "base_branch": "develop", - "post_run_diagnostics": "false", + "pipeline_health": "false", "is_fleet_dispatch": "false", "dispatch_id": "", }, @@ -1148,22 +1148,20 @@ async def test_post_run_diagnostics_override_wins_over_config(tmp_path, monkeypa await open_kitchen( name="demo", - overrides={"post_run_diagnostics": "true"}, + overrides={"pipeline_health": "true"}, ctx=mock_ctx, ) call_kwargs = mock_ctx.recipes.load_and_validate.call_args.kwargs overrides = call_kwargs["ingredient_overrides"] - assert overrides["post_run_diagnostics"] == "true", ( - f"Override must win; got overrides={overrides}" - ) + assert overrides["pipeline_health"] == "true", f"Override must win; got overrides={overrides}" call_args_list = mock_ctx.recipes.load_and_validate.call_args_list assert call_args_list, "open_kitchen should call load_and_validate" # T2: REQ-ING-002 @pytest.mark.anyio -async def test_post_run_diagnostics_config_default_applied(tmp_path, monkeypatch): +async def test_pipeline_health_config_default_applied(tmp_path, monkeypatch): """REQ-ING-002: Without override, config value is used as default.""" monkeypatch.chdir(tmp_path) mock_ctx = _make_mock_ctx() @@ -1171,7 +1169,7 @@ async def test_post_run_diagnostics_config_default_applied(tmp_path, monkeypatch mock_ctx.recipes = MagicMock() mock_recipe_obj = MagicMock() mock_recipe_obj.steps = {"do": MagicMock()} - mock_recipe_obj.ingredients = {"post_run_diagnostics": MagicMock()} + mock_recipe_obj.ingredients = {"pipeline_health": MagicMock()} mock_ctx.recipes.load.return_value = mock_recipe_obj mock_ctx.recipes.load_and_validate.return_value = { "content": "name: demo\nsteps:\n do:\n tool: run_cmd\n", @@ -1201,7 +1199,7 @@ async def test_post_run_diagnostics_config_default_applied(tmp_path, monkeypatch "autoskillit.server.tools.tools_kitchen.resolve_ingredient_defaults", return_value={ "base_branch": "develop", - "post_run_diagnostics": "true", + "pipeline_health": "true", "is_fleet_dispatch": "false", "dispatch_id": "", }, @@ -1212,7 +1210,7 @@ async def test_post_run_diagnostics_config_default_applied(tmp_path, monkeypatch call_kwargs = mock_ctx.recipes.load_and_validate.call_args.kwargs overrides = call_kwargs["ingredient_overrides"] - assert overrides["post_run_diagnostics"] == "true", ( + assert overrides["pipeline_health"] == "true", ( f"Config default must apply; got overrides={overrides}" )