feat: opt-in auto-verify hook and release CI safety net - #1
Merged
Conversation
Add opt-in PostToolUse hook (VIBESUBIN_AUTO_VERIFY=1) that runs refactor-verify's symbol-diff after MultiEdit >=5 or signature-changing edits. Defaults OFF — no behavior change for existing installs. Extends refactor-verify per invariant #2 (no new skill, no cap impact). Add release.yml workflow on tag push (v*.*.*) — validates skills, runs pytest, enforces manifest version sync (tag = marketplace = plugin), and checks for forbidden file types before creating the GitHub release. The manual gh release create policy stays; this is the safety net. Add marketplace.json metadata (category, tags, repository) for plugin discoverability. install.sh: ERROR: text replaces ❌ emoji prefix. Validator: OK (12 skills, manifests synced). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Functional-only style per CLAUDE.md invariant #4. Documents the auto-verify hook (opt-in), release.yml safety net, marketplace.json metadata, and install.sh emoji removal added in the prior commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
auto-verify.sh: remove symbol-diff inline invocation. The PostToolUse
hook fired symbol-diff.sh with HEAD HEAD (comparing HEAD to itself,
always 0 dropped) because at edit time there is no meaningful "before"
snapshot. Advisory message alone is the correct behavior; the actual
verification belongs to /vibesubin:refactor-verify which captures its
own snapshot.
release.yml: switch to draft: true. Auto-publishing conflicts with
CLAUDE.md step 8 ("write release notes to a temp file, functional-only
style"). CI now validates and creates a draft release the human edits
before publishing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marketplace.json: drop `repository` (not in plugin schema — 0 of 160
plugins in claude-plugins-official use it; `homepage` covers the role).
Replace `tags` with `keywords` to match the standard discovery field
(vercel, openai-codex, and most plugins use `keywords`).
release.yml: drop the instructional `body:` (conflicts with
`generate_release_notes`). Add a version-extract step so the release
title renders as "vibesubin 0.8.0" (matching CLAUDE.md step 9 example)
instead of "vibesubin v0.8.0". Human still curates the notes from
CHANGELOG.md before publishing.
auto-verify.sh: defensive `EDITS="${EDITS:-0}"` guard before the
numeric `-lt` comparison.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The advisory fired for two paths (MultiEdit >=5 OR signature line in diff) but always claimed "signature-changing", which is wrong for the MultiEdit volume path. Drop the qualifier; the directive to run /vibesubin:refactor-verify is sufficient context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
subinium
added a commit
that referenced
this pull request
Apr 27, 2026
…ygiene workers Two AI-native failure modes the pack now actively guards against per-worker: 1. Chesterton's Fence — workers refuse to recommend removal or replacement of unfamiliar code, files, env vars, assets, or conventions without identifying the *why* first. Internalized in fight-repo-rot, manage-assets, manage-secrets-env, refactor-verify, audit-security, project-conventions. Confidence tier verified requires both zero refs AND known origin; unclear origin downgrades to candidate-for-removal (or candidate-with-context-needed for convention changes). 2. Goodhart protection — workers refuse to recommend gate-gaming patterns (as any, eslint-disable, .skip, weakened assertions, suppression comments without CVE, continue-on-error: true on quality gates) as fixes when verification fails. Internalized in refactor-verify, audit-security, setup-ci, codex-fix. The wrapper (codex-fix) enforces the canonical pattern list at the wrapper boundary, no duplication. Framing: operationalizing existing invariants #2 (well-meaning junior developer — stop-and-ask before destructive action) and #1 (Done is proven, not claimed — proof for tier upgrades and gate passes), not new ideology. Per-skill bullets carry the rule, not the principle name — Karpathy precedent (no external shoutout in SKILL.md). No new skills (10+1 cap unchanged). No interface change. No README touch. Net diff +16 -2 across 11 files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
plugins/vibesubin/hooks/auto-verify.sh, gated byVIBESUBIN_AUTO_VERIFY=1) that emits a stderr advisory after MultiEdit ≥5 or signature-changing edits (export/def/class/pub fn/func/fn/async function/interface/type), nudging the user to run/vibesubin:refactor-verify. Defaults OFF — no behavior change for existing installs. PostToolUse cannot block (exit 0 always); the hook is purely advisory..github/workflows/release.ymlonv*.*.*tag push: runsvalidate_skills.py+pytest, HARD-checks manifest version sync (tag == marketplace.json == plugin.json) and forbidden file types (\.env$|\.pem$|id_rsa|\.key$), then creates a draft release for human-curated notes per CLAUDE.md step 8.marketplace.json: addcategory: "developer-tools"andkeywordsfor marketplace discoverability. Schema verified againstclaude-plugins-official(160 plugins union) —keywordsis the standard discovery field;repository/tagsare not in the spec.install.sh: replace❌emoji prefix withERROR:text in the 3 error paths. Avoids broken rendering on non-UTF-8 terminals; aligns with the pack's no-emoji ethos.CHANGELOG.md:[Unreleased]entries in functional-only style.What this is NOT
refactor-verify; 10+1 cap unchanged).[Unreleased]for the next release decision).vibesubin-mcpserver bundle (deferred — Cursor/Cline don't auto-discover Claude Code plugin MCPs, runtime friction outweighs benefit at this stage).Test plan
python3 scripts/validate_skills.pypasses (12 skills, manifests synced)marketplace.jsonandhooks.jsonvalid JSONgit ls-files | grep -iE '\.env\$|\.pem\$|id_rsa|\.key\$'returns nothing)VIBESUBIN_AUTO_VERIFY=1 claude), make a signature-changing edit, confirm advisory appears in panelv0.7.1or similar) on a fork, confirm draft release is created with all gates greenSelf-review rounds
5 commits, 3 review rounds caught:
auto-verify.shwas callingsymbol-diff.sh HEAD HEAD— useless self-comparison. Switched to advisory-only (the actual symbol-diff belongs to/vibesubin:refactor-verifywhich captures a proper snapshot).release.ymlwas auto-publishing — switched todraft: trueto honor CLAUDE.md step 8.repository(not in spec), replacedtagswithkeywords(standard field).release.ymlbody:conflicted withgenerate_release_notes— droppedbody:, added version-extract step so release title renders asvibesubin 0.8.0instead ofvibesubin v0.8.0.🤖 Generated with Claude Code