Skip to content

fix: correct stale skill exclusion text and mutation state display#40

Merged
karngyan merged 2 commits into
mainfrom
fix/skill-template-and-state-display
Jul 17, 2026
Merged

fix: correct stale skill exclusion text and mutation state display#40
karngyan merged 2 commits into
mainfrom
fix/skill-template-and-state-display

Conversation

@karngyan

@karngyan karngyan commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Claim

Two honesty bugs found in today's hands-on audit, plus a batch-abort regression the fix itself would have introduced:

  1. Installed SKILL.md contradicted itself. Every generated package exclusion said "Do not block execution; this candidate is advisory until replay and shadow evaluation pass." — but mutations install only runs after replay and shadow both passed, and the same file states so two lines later.
  2. mutations propose/synthesize printed a stale state column. Rows rendered the registration outcome's initial state, so a mutation that was already shadow_passed or retired displayed as candidate.
  3. Template evolution must not abort re-proposal. Deterministic generation re-derives the same mutation id from the same evidence, so the new template phrasing conflicts with immutable packages registered under the old phrasing; the registry's refusal previously became a hard error that killed the whole propose/synthesize batch on any pre-existing database (reproduced against a real 69k-event corpus).

Fix

  • autophagy-mutations: new candidates carry stage-neutral phrasing — "Do not block execution; this instruction is advisory." (ADVISORY_EXCLUSION); old text preserved as LEGACY_ADVISORY_UNTIL_REPLAY_EXCLUSION for structural matching.
  • autophagy-install: stored packages are immutable and never rewritten; at render time the installer exact-matches the one legacy template line and renders the corrected text, leaving every other exclusion verbatim.
  • autophagy-cli + autophagy-store: after registration, propose/synthesize fetch each generated mutation's current stored state and print that; a per-candidate MutationContentConflict becomes a warning ("earlier-template content; the stored immutable package is kept") instead of a batch abort. JSON note: reports gain an additive current_states map and (proposal, only when non-empty) a warnings array — no existing fields changed.

Evidence

  • generated_skill_has_no_self_contradicting_exclusion and installer_tolerates_legacy_advisory_exclusion_phrasing (autophagy-install)
  • generated_exclusions_stay_true_at_every_lifecycle_stage (autophagy-mutations)
  • propose_and_synthesize_display_current_mutation_state_not_stale_candidate and propose_and_synthesize_survive_immutable_template_conflicts (autophagy-cli integration)
  • Verified against a real-data copy: installing a legacy-phrased package renders the corrected SKILL.md section; re-running synthesize on a pre-existing registry warns twice and exits 0 with correct per-mutation states (active, candidate).
  • mise run check green (exit 0, unpiped).

Privacy

None — template text and display state only; no new persisted data beyond the derived state map in command output.

🤖 Generated with Claude Code

https://claude.ai/code/session_015LY7xtercMc3NtLeX2z4YV

karngyan and others added 2 commits July 17, 2026 20:23
The deterministic candidate template stamped "advisory until replay and
shadow evaluation pass" into every package exclusion, and the installer
rendered it verbatim into SKILL.md — a self-contradiction, since
installation only happens after both stages passed. New candidates now
carry stage-neutral phrasing; the installer recognizes the exact legacy
line in already-registered (immutable) packages and renders the corrected
text instead.

propose/synthesize rows also printed the registration outcome's initial
state, so an already shadow_passed or retired mutation displayed as
"candidate". Both commands now fetch and print each mutation's current
stored state; the JSON reports gain an additive current_states map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deterministic generation re-derives the same mutation id from the same
evidence, so a template-text change between releases makes regeneration
conflict with the immutable stored package. The registry correctly
refuses the overwrite, but propose/synthesize turned that refusal into a
hard error that aborted the whole batch on any database with candidates
registered by an earlier template. Catch the content conflict per
candidate, keep the stored package authoritative, surface a warning in
text and JSON output, and let the rest of the batch register.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@karngyan
karngyan merged commit 930d172 into main Jul 17, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant