feat(install): add graphify vibe install for Mistral Vibe CLI - #2537
feat(install): add graphify vibe install for Mistral Vibe CLI#2537xavierpestel-ai wants to merge 1 commit into
Conversation
e138e96 to
a02e474
Compare
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
This pull request appears to reintroduce version 0.9.33 as "unreleased" in the CHANGELOG, removing the previously listed 0.9.34 and 0.9.35 entries, and adds a new feature line describing Mistral Vibe support. It updates the README with graphify vibe install documentation across the install tables and command reference, and wires up new Vibe-related imports (install/uninstall hooks, hook path helpers) in __main__.py. The build.py change removes the _coerce_hyperedge_member_refs helper. The changed-symbols list spans a much broader surface than the shown diff—covering skillgen expected fixtures/fragments, extractor engine/resolution logic, CLI and install modules, and multiple test files (serve, watch, cli_export)—suggesting the full changeset also touches skill generation output, extraction/resolution code, and their associated tests.
No blocking issues surfaced.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 5383 functions depend on the 3268 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_project_uninstall()— 5 callers, 14 callees - worse:
dispatch_install_cli()— 2 callers, 33 callees - worse:
install()— 5 callers, 12 callees - worse:
_build_server()— 2 callers, 21 callees - new:
_vibe_install()— 4 callers, 9 callees - worse:
_copy_skill_file()— 9 callers, 4 callees - worse:
_project_install()— 2 callers, 14 callees - worse:
uninstall_all()— 2 callers, 14 callees - …and 1 more
Verification — 5383 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 5383 function(s) in the blast radius were not formally verified this run
· 2 grounded finding(s) anchored inline below; 7 more finding(s) on lines outside this diff (see the check run).
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
This PR adds Mistral Vibe (mistralai/mistral-vibe) as a supported platform for graphify vibe install. It introduces a new vibe platform config, a skill file with user-invocable frontmatter, AGENTS.md integration, and two pre_tool hooks (for grep and read_file) merged into vibe's .vibe/hooks.toml via tomlkit, with corresponding install/uninstall helper functions exported from __main__.py. The surface area includes new install helpers in graphify/install.py (_vibe_install, _vibe_uninstall, _install_vibe_hook, _uninstall_vibe_hook, _vibe_hooks_path, _vibe_hook_entries, plus supporting path/normalization utilities), updates to README and CHANGELOG documentation, and changes to skill-generation tooling/fragments and vibe-related tests. Hook ownership is tracked by name, and both global (VIBE_HOME) and project scopes are handled.
No blocking issues surfaced. 6 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 880 functions depend on the 605 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_project_uninstall()— 5 callers, 14 callees - worse:
dispatch_install_cli()— 2 callers, 33 callees - worse:
install()— 5 callers, 12 callees - new:
_vibe_install()— 4 callers, 9 callees - worse:
_copy_skill_file()— 9 callers, 4 callees - worse:
_project_install()— 2 callers, 14 callees - worse:
uninstall_all()— 2 callers, 14 callees - new:
_vibe_uninstall()— 4 callers, 5 callees
Verification — 880 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 880 function(s) in the blast radius were not formally verified this run
· 2 grounded finding(s) anchored inline below; 6 more finding(s) on lines outside this diff (see the check run).
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Graphify review — findings
This PR adds Mistral Vibe (mistralai/mistral-vibe) as a supported platform for graphify install. It introduces a new vibe platform config, a skill file with user-invocable frontmatter, an AGENTS.md section, and install/uninstall logic that merges two pre_tool hooks (for grep and read_file) into vibe's hooks.toml using tomlkit, honoring VIBE_HOME for global scope and both project/global paths. The surface area spans install.py (new _vibe_* helpers, hook entries, config entry, dispatch in install()), exports in __main__.py, README/CHANGELOG documentation updates, associated skill-generation fragments, and tests covering the vibe dispatch and uninstall behavior.
No blocking issues surfaced. 8 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 880 functions depend on the 605 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_project_uninstall()— 5 callers, 14 callees - worse:
dispatch_install_cli()— 2 callers, 33 callees - worse:
install()— 5 callers, 12 callees - new:
_vibe_install()— 4 callers, 9 callees - worse:
_copy_skill_file()— 9 callers, 4 callees - worse:
_project_install()— 2 callers, 14 callees - worse:
uninstall_all()— 2 callers, 14 callees - new:
_vibe_uninstall()— 4 callers, 5 callees
Verification — 880 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 880 function(s) in the blast radius were not formally verified this run
· 2 grounded finding(s) anchored inline below; 6 more finding(s) on lines outside this diff (see the check run).
a02e474 to
f8758ff
Compare
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.
Graphify review — findings
This PR adds Mistral Vibe as a supported platform for graphify install. It introduces a new vibe platform config, a skill-vibe.md skill file, install/uninstall functions (_vibe_install, _vibe_uninstall), and pre_tool hook management (_install_vibe_hook, _uninstall_vibe_hook) that merge two hooks (for grep and read_file) into vibe's hooks.toml using tomlkit. It also wires up VIBE_HOME-aware path resolution, updates the CLI dispatch and __main__ exports, and adds README/CHANGELOG documentation plus corresponding tests. The surface area spans install.py (new functions and platform config), __main__.py (imports), documentation files, skill/fragment generation tooling, and a test module covering hook installation, comment preservation, and user-authored hook ownership.
Worth a look
- install(platform='vibe') ignores strict flag —
graphify/install.py:612· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 886 functions depend on the 611 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_project_uninstall()— 5 callers, 14 callees - worse:
dispatch_install_cli()— 2 callers, 33 callees - worse:
install()— 5 callers, 12 callees - new:
_vibe_install()— 4 callers, 9 callees - worse:
_copy_skill_file()— 9 callers, 4 callees - worse:
_project_install()— 2 callers, 14 callees - worse:
uninstall_all()— 2 callers, 14 callees - new:
_vibe_uninstall()— 4 callers, 5 callees
Verification — 886 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 886 function(s) in the blast radius were not formally verified this run
· 2 grounded finding(s) anchored inline below; 6 more finding(s) on lines outside this diff (see the check run).
Adds Mistral Vibe (github.com/mistralai/mistral-vibe) as a full-parity platform integration, matching Claude Code's shape: skill file + AGENTS.md always-on section + hooks.toml pre_tool guards. Vibe reads .vibe/skills (project, trusted) and VIBE_HOME/skills (user global, default ~/.vibe/skills) per its Agent Skills-compliant harness manager. `user-invocable: true` in the skill frontmatter exposes /graphify as a native slash command in vibe's autocomplete. Two pre_tool hooks (grep + read_file) nudge toward `graphify query` instead of raw filesystem tools, mirroring the claude/gemini/codex guard pattern. The --strict flag flows to the read_file guard only, matching claude --strict. Matchers use vibe's actual snake-cased tool names (Grep -> grep, ReadFile -> read_file per vibe/core/tools/base.py:get_name) since vibe's hook matcher uses fnmatch. Ownership is decided by hook `name` in a fixed set, NOT a substring match on `command` -- a substring match would silently delete a user's own hooks that shelled out to graphify for unrelated reasons. Uses tomlkit for hooks.toml merges so hand-authored comments, key ordering, and unrelated [[hooks]] entries survive graphify install/upgrade. Command strings are built with shlex.join so exe paths containing shell metacharacters are quoted safely for vibe's asyncio.create_subprocess_shell executor. Honors the VIBE_HOME env var for all three artifacts (skill, hooks, AGENTS.md) so users on non-default vibe setups don't get orphaned installs into a directory vibe never reads. Skillgen registration: vibe is a monolith bucket (its SkillMetadata schema requires extra frontmatter fields user-invocable + allowed-tools that _render_frontmatter emits only name+description for). Post-v8 monoliths opt out of monolith_roundtrip via roundtrip_ref=None (matches _v8_baseline_ref's existing post-v8 handling for the agents platform). CLI: graphify vibe install # global VIBE_HOME (default ~/.vibe/) graphify vibe install --project # project ./.vibe/ + ./AGENTS.md graphify vibe install --strict # block first raw read per session graphify vibe uninstall # symmetric cleanup graphify install --platform vibe # alias for the global install graphify uninstall # uninstall_all sweeps vibe too Tests: 28 covering CLI paths, VIBE_HOME symmetry, name-based ownership, shlex-safe quoting across 9 hostile paths, 4 malformed TOML shapes, and idempotency. Verified end-to-end against real Mistral Vibe 2.24.0: skill discovery, /graphify slash-command execution, pre_tool hooks fire on grep and read_file invocations, and full pipeline runs on a sample repo producing a queryable graph. Adds tomlkit>=0.13 as a runtime dep (comment-preserving TOML round-trip; stdlib tomllib is read-only and needs 3.11+ while requires-python is 3.10).
f8758ff to
caa1460
Compare
|
Fixed in The bot was right — Two changes:
Added regression test Verified end-to-end:
|
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.
Graphify review — findings
This PR adds Mistral Vibe (mistralai/mistral-vibe) as a supported platform for the graphify vibe install / uninstall commands. It introduces a vibe entry in the platform config plus new helper functions for resolving the vibe home directory (honoring VIBE_HOME), destination paths for skill/AGENTS.md files, and merging two pre_tool hooks (grep + read) into .vibe/hooks.toml via tomlkit, with name-based ownership and a --strict option. It also wires these into the installer dispatch, exports the new symbols from __main__.py, and updates the README and CHANGELOG, alongside generated skill fragments and tests.
Worth a look
- _refuse_to_modify does not stop execution, causing UnboundLocalError on unparseable hooks.toml —
graphify/install.py· Escalate · high- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 888 functions depend on the 613 functions this change touches.
Health — this change adds coupling hotspots:
- worse:
_project_uninstall()— 5 callers, 14 callees - worse:
dispatch_install_cli()— 2 callers, 34 callees - worse:
install()— 5 callers, 12 callees - new:
_vibe_install()— 4 callers, 9 callees - worse:
_copy_skill_file()— 9 callers, 4 callees - worse:
_project_install()— 2 callers, 14 callees - worse:
uninstall_all()— 2 callers, 14 callees - new:
_vibe_uninstall()— 4 callers, 5 callees
Verification — 888 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 888 function(s) in the blast radius were not formally verified this run
· 3 grounded finding(s) anchored inline below; 5 more finding(s) on lines outside this diff (see the check run).
| except Exception: | ||
| pass | ||
| def install(platform: str = "claude", *, project: bool = False, project_dir: Path | None = None) -> None: | ||
| def install(platform: str = "claude", *, project: bool = False, project_dir: Path | None = None, strict: bool = False) -> None: |
There was a problem hiding this comment.
install()
fans out to 12 callees (efferent coupling).
Grounded coupling-delta finding (deterministic), not an LLM guess.
| print("one `graphify query` runs (toggle with GRAPHIFY_HOOK_STRICT=0).") | ||
|
|
||
|
|
||
| def _vibe_install(project_dir: Path | None = None, *, project: bool = False, strict: bool = False) -> None: |
There was a problem hiding this comment.
_vibe_install()
fans out to 9 callees (efferent coupling).
Grounded coupling-delta finding (deterministic), not an LLM guess.
| _print_vibe_install_summary(strict) | ||
|
|
||
|
|
||
| def _vibe_uninstall(project_dir: Path | None = None, *, project: bool = False, remove_user_skill: bool | None = None) -> None: |
There was a problem hiding this comment.
_vibe_uninstall()
high coupling complexity (Ca·Ce = 20).
Grounded coupling-delta finding (deterministic), not an LLM guess.
Summary
Adds Mistral Vibe (
mistralai/mistral-vibe) as a full-parity platform integration, matching Claude Code's shape: skill file +AGENTS.mdalways-on section +hooks.tomlpre_toolguards.What's included
CLI
Artifacts installed
VIBE_HOME/skills/graphify/SKILL.md(or./.vibe/skills/…in project scope) withuser-invocable: truefrontmatter — exposes/graphifyas a native slash command in vibe's autocomplete.AGENTS.mdsection with the shared## graphifymarker (uses graphify's existing_replace_or_append_sectionhelper, matches how other AGENTS.md platforms register).pre_toolhooks inhooks.toml— matchersgrepandread_file(vibe's real snake-cased tool names pervibe/core/tools/base.py:get_name) that nudge towardgraphify queryfor search / raw-read operations.Design decisions worth flagging
Hook matchers use vibe's snake-cased class names. Vibe's hook matcher uses
fnmatch, and vibe'sBaseTool.get_name()snake-cases the class (Grep→grep,ReadFile→read_file). Matching on"read"alone would silently never fire against the realread_filetool — this was caught during real-vibe integration testing before landing.VIBE_HOMEhonored for all three artifacts. Vibe's harness manager readsVIBE_HOME/skills,VIBE_HOME/hooks.toml, andVIBE_HOME/AGENTS.md; hardcoding~/.vibewould silently orphan installs for users who setVIBE_HOME=/opt/vibe-shared.Ownership by hook
name, not command substring. Filtering existing[[hooks]]entries by"graphify" in commandwould silently delete a user's own hook that happens to shell out tographifyfor unrelated reasons. Filtering by hookname in {"graphify-nudge-search", "graphify-nudge-read"}is precise.shlex.joinfor hook commands. Vibe runs hooks viaasyncio.create_subprocess_shell, so metacharacters in the exe path ($, backticks,;,(,)) parse as shell operators. The previous "quote only if space" heuristic (still used by the older claude/gemini hook installers) leaves injection open on macOS home dirs containing parentheses.tomlkitforhooks.tomlmerges. Preserves user comments and unrelated[[hooks]]entries across install/upgrade cycles. Stdlibtomllibis read-only and only 3.11+ (graphify supports 3.10), sotomlkit>=0.13is added as a runtime dep — small pure-Python wheel.Skillgen registration as a monolith. Vibe's
SkillMetadataschema requires extra frontmatter fields (user-invocable,allowed-tools) that skillgen's_render_frontmatteremits onlyname+descriptionfor. Registering as a monolith bucket (likeaideranddevin) lets the skill file carry its own frontmatter without extending the shared renderer. Post-v8 monoliths (no pristine baseline to freeze against) opt out ofmonolith_roundtripviaroundtrip_ref = None— mirrors_v8_baseline_ref's existing post-v8 handling for theagentsplatform (4-line skillgen change).uninstall_allsweep.graphify uninstallnow removes vibe artifacts alongside every other platform — otherwise vibe hooks would keep firing after users think they've cleaned up.Files changed (12)
graphify/install.py_PLATFORM_CONFIG["vibe"],_platform_skill_destinationbranch,_install_vibe_hook/_uninstall_vibe_hook,_vibe_install/_vibe_uninstallorchestrators,_vibe_home,_vibe_hooks_path,_vibe_agents_md_path,_vibe_hook_entries,_normalize_toml, CLI dispatch branch,_CLI_INSTALL_COMMANDSentry,_project_install/_project_uninstallbranches,uninstall_alladditiongraphify/__main__.py_vibe_install,_vibe_uninstall,_install_vibe_hook,_uninstall_vibe_hook,_vibe_hooks_path,_vibe_hook_entries)graphify/skill-vibe.mdtests/test_vibe.pytools/skillgen/fragments/core/vibe.mdtools/skillgen/expected/graphify__skill-vibe.mdtools/skillgen/platforms.tomlroundtrip_ref)tools/skillgen/gen.pymonolith_roundtripopt-out for post-v8 monolithspyproject.tomltomlkit>=0.13runtime dep,skill-vibe.mdin package-data, description enumerationREADME.mdCHANGELOG.md0.9.33 (unreleased)uv.lockuv syncTesting
Automated
tests/test_vibe.pycovering CLI paths,VIBE_HOMEsymmetry, name-based ownership,shlex.join-safe quoting across 9 hostile paths, 4 malformed TOML shapes, idempotency (no.graphify-bakchurn on re-install), strict-flag flow.test_ollama.py,test_ollama_retry_cap.py,test_labeling.py::test_label_communities_batches_when_over_batch_size).--check,--audit-coverage,--schema-singleton,--monolith-roundtrip,--always-on-roundtrip).End-to-end against real Mistral Vibe 2.24.0
vibe -p "/graphify --help"executes the skill body verbatimgrepandread_filetool invocations (verified via a disk-tracer hook command that touches a file when triggered)graphify path "handle_login()" "execute()"traced the full login flow (handle_login → login → find_user_by_credentials → execute) across 4 modulesChecklist
v8(active development branch per README)feat: <description>per README §Git workflowuv run pytest tests/ -qpassestools/skillgen/platforms.tomland the blessedexpected/fixture updated0.9.33 (unreleased)descriptionenumeration includes Mistral Vibe