Skip to content

feat(omp): bridge hook-guard denials and context through native hooks - #3506

Open
andrebrait wants to merge 1 commit into
Graphify-Labs:v8from
andrebrait:feat/omp-native-integration
Open

feat(omp): bridge hook-guard denials and context through native hooks#3506
andrebrait wants to merge 1 commit into
Graphify-Labs:v8from
andrebrait:feat/omp-native-integration

Conversation

@andrebrait

Copy link
Copy Markdown

Summary

Bridge Graphify's existing hook-guard policy into OMP's native tool_call/context hooks, including strict denials. Ship the extension inside the Python distribution and register it through OMP's plugin manager with graphify omp install.

  • Translate native read selectors and search targets, skip remote/internal resources, and retain hook-guard as the policy owner.
  • Propagate permission denials before tool execution; deduplicate additional context and clear it across runs/session navigation.
  • Bound subprocess input/output/runtime, cancel stale generations, and resolve an installed executable outside the current project.
  • Ship explicit OMP metadata in both wheel/sdist; canonical Graphify skills remain a separate existing installation, with no copied bodies or extraction/index changes.

Related work

Related to #1937, which adds OMP nudges on tool results. This patch targets a different runtime contract: reuse hook-guard before execution so strict denials, native grep, path selectors, and policy context actually work. It does not duplicate hardcoded tool-result guidance. There is installation/documentation overlap; happy to coordinate the landing order.

Verification

  • Focused Python installer/guard/strict/path tests:115 pass,4 existing skips.
  • Native Bun tests:6 pass,51 assertions, using the real Python CLI/path helpers plus bounded subprocess fixtures.
  • Wheel and source distribution build; both ship native entry/manifest.
  • Installed built wheel in an isolated environment; graphify omp install successfully linked its shipped package using the real OMP plugin manager in an isolated home.
  • Actual OMP loader/ExtensionRunner/AgentSession: three user-run entry modes, strict selector-read refusal, subsequent guidance, and session reset pass against the installed wheel (scripted model response; disposable graph metadata fixture).

No existing project index was built or changed. OMP's isProjectTrusted() currently always returns true and is not a sandbox; docs say so. Tested host: OMP18.1.17 integration SHA6aef0e8ad51b3bc5ea7a5f2a255c3d48e4c5af72, not a promise about all published builds with that version. The installed executable policy excludes a project-local .venv; docs recommend uv tool/pipx.

AI-assisted implementation, independently reviewed for contracts, hostile input, test honesty and unnecessary complexity.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

Formal verification. 2 change(s) tested, no difference found (not proven).


Graphify review — findings

Adds a native Oh My Pi guard integration via graphify omp install, which delegates registration to omp plugin install on the shipped graphify/omp package directory (with graphify omp path printing that directory for manual linking); the omp command is silenced from the stale-graph warning and rejects args other than install/path. The graphify TypeScript extension runs the installed hook-guard read|search CLI before native read/glob/grep/search bash calls on local paths, turning policy denials into OMP block/reason and guidance into a single deduplicated context message that resets on new user runs and session boundaries; it resolves graphify only from an absolute PATH entry outside the project, caps input/output/time per call, and fails open on any error. Trust gating relies on ctx.isProjectTrusted(), which current OMP reports as always-true, so it is not an enforced sandbox — OMP links must be removed with omp plugin uninstall graphify-omp since graphify uninstall does not touch OMP's registry.

Worth a look

  • Project-controlled PATH symlink can bypass graphify executable rejectiongraphify/omp/index.ts:28 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Shared abort controller lets one session cancel another session's guardgraphify/omp/index.ts:56 · 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 — 680 functions depend on the 413 functions this change touches.

Health — this change adds coupling hotspots:

  • new: dispatch_command() — 2 callers, 124 callees
  • new: dispatch_install_cli() — 6 callers, 31 callees
  • new: codebuddy_install() — 20 callers, 5 callees
  • new: claude_install() — 19 callers, 4 callees
  • new: gemini_install() — 10 callers, 7 callees
  • new: claude_uninstall() — 17 callers, 4 callees
  • new: _project_uninstall() — 5 callers, 13 callees
  • new: _copy_skill_file() — 12 callers, 5 callees
  • …and 13 more — each is listed as a finding

Verification — 680 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: 680 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

270 of 270 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/omp.test.ts — impact, changed-test, full-run-safety
  • tests/test_affected_cli.py — impact, full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_agents_platform.py — impact, full-run-safety
  • tests/test_analyze.py — full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — full-run-safety
  • tests/test_astro_import_ids.py — full-run-safety
  • tests/test_atomic_canvas_export.py — full-run-safety
  • tests/test_atomic_version_stamp.py — impact, full-run-safety
  • tests/test_atomic_writes.py — full-run-safety
  • tests/test_backend_env_isolation.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_build.py — full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — full-run-safety
  • tests/test_build_merge_shrink_guard.py — full-run-safety
  • tests/test_builtin_global_type_refs.py — full-run-safety
  • tests/test_cache.py — full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — full-run-safety
  • tests/test_case_sensitive_resolution.py — full-run-safety
  • tests/test_charmap_encoding.py — full-run-safety
  • tests/test_chunking.py — full-run-safety
  • tests/test_cjs_module_extension.py — full-run-safety
  • tests/test_claude_cli_backend.py — full-run-safety
  • tests/test_claude_md.py — impact, full-run-safety
  • tests/test_cli_broken_pipe.py — full-run-safety
  • tests/test_cli_export.py — full-run-safety
  • tests/test_cli_help.py — full-run-safety
  • tests/test_cluster.py — full-run-safety
  • tests/test_codebuddy.py — impact, full-run-safety
  • tests/test_community_hub_labels.py — full-run-safety
  • tests/test_community_labels_skill.py — full-run-safety
  • tests/test_confidence.py — full-run-safety
  • tests/test_corrupt_graph_json.py — full-run-safety
  • tests/test_cpp_nested_and_cli.py — full-run-safety
  • tests/test_cpp_objc_cross_file_calls.py — full-run-safety
  • tests/test_cpp_preprocess.py — full-run-safety
  • tests/test_cross_extension_reexport_self_cycle.py — full-run-safety
  • tests/test_cross_language_call_resolution.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • tests/test_csharp_call_site_generic_args.py — full-run-safety
  • tests/test_csharp_enum_members.py — full-run-safety
  • … and 220 more

non-code file(s) changed (CHANGELOG.md, README.md, graphify/omp/package.json, pyproject.toml) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (CHANGELOG.md, README.md, pyproject.toml) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

No difference found (not proven): No behavior difference found in dispatch\_install\_cli (not a proof).

The verifier ran both versions of dispatch\_install\_cli on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

No difference found (not proven): No behavior difference found in \_run\_cli (not a proof).

The verifier ran both versions of \_run\_cli on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

· 21 more finding(s) on lines outside this diff (see the check run).

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