Implementation Plan: Hook-Based Recipe Reload Guard — Block Duplicate Recipe Loads#3939
Merged
Trecek merged 5 commits intoJun 8, 2026
Conversation
Add a new PostToolUse hook for run_skill that writes a
{session_id}_recipe_confirmed.json marker to kitchen_state/ after
the first successful run_skill completes. This marker is read by
open_kitchen_guard to block mid-run recipe reloads (the recipe is
instructions, not runtime state — re-loading cannot change pipeline
behavior).
The marker is scoped by session_id so stale markers from crashed
sessions do not affect new sessions. Idempotent: skips writing if
the marker already exists. Fails open on all error paths.
Files:
- New hook: src/autoskillit/hooks/recipe_confirmed_post_hook.py
- New test: tests/hooks/test_recipe_confirmed_post_hook.py (T1-1 to T1-6)
- Arch exemption: tests/arch/_rules.py _BROAD_EXCEPT_EXEMPT
- Docs: hooks/AGENTS.md, tests/hooks/AGENTS.md, docs/safety/hooks.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…e starts Extend open_kitchen_guard with _check_recipe_reload_block(): on the permit path, block open_kitchen(name=...) if a recipe-confirmed marker exists for the current session. Gate-only opens (no name) and ingredients_only=True calls remain allowed. This enforces that the recipe is instructions, not runtime state: mid-run reloads cannot change pipeline behavior. To re-open the kitchen gate without loading a recipe, callers can call open_kitchen() without a name parameter. Tests (T2-1 to T2-7): - test_reload_blocked_after_confirmed_marker - test_gate_only_open_allowed_after_confirmed - test_ingredients_only_allowed_after_confirmed - test_different_session_id_not_blocked - test_no_confirmed_marker_allows_load - test_corrupted_confirmed_marker_fails_open - test_reload_denied_in_headless_orchestrator_after_confirmed Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add recipe_confirmed_post_hook.py to the existing run_skill PostToolUse HookDef's scripts list. Update Codex compatibility table to mark recipe_confirmed_post_hook as works-as-is. Regenerate registry.sha256 with the new hash (e16b7355310b925a6937aee8e0d6028f4dbe6c475d14c8d8f487923601ab8702) so test_committed_registry_hash_matches_live_registry passes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ecipe_confirmed_post_hook Bump hooks/ file-count exemption from 13→14 and add recipe_confirmed_post_hook to the dispatcher logical-name allowlist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…post_hook Bare `except Exception` silently swallowed disk-full or permission errors, leaving the recipe-confirmed marker unwritten so the reload guard never fired. Capture the exception and write to stderr before cleanup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
c33b17c to
a1119e4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add a timing-based guard that structurally blocks duplicate
open_kitchen(name=...)calls after the recipe initialization phase completes. A new PostToolUse hook (recipe_confirmed_post_hook.py) writes a{session_id}_recipe_confirmed.jsonmarker tokitchen_state/after the first successfulrun_skillcompletes. The existingopen_kitchen_guard.pyPreToolUse hook is extended to read this marker and deny recipe-loadingopen_kitchencalls when it exists. Gate-only opens (noname),ingredients_only=Truecalls, and all calls during the initialization phase (before any pipeline step executes) remain allowed.Closes #3912
Implementation Plan
Plan file:
/home/talon/projects/autoskillit-runs/impl-20260608-102437-791030/.autoskillit/temp/make-plan/recipe_reload_guard_plan_2026-06-08_103500.md🤖 Generated with Claude Code via AutoSkillit