Skip to content

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

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

andrebrait wants to merge 20 commits into
Graphify-Labs:v8from
andrebrait:feat/omp-native-integration

Conversation

@andrebrait

@andrebrait andrebrait commented Sep 11, 2026 •

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; deliver per-call guidance with each tool result as a leading <system-reminder source="graphify"> block, the way Claude Code labels PreToolUse additionalContext (and OMP labels its own per-tool TTSR reminders), clearing pending deliveries across runs and 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:7 pass,64 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 rejection — graphify/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 guard — graphify/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).

@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 5 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 links the shipped graphify/omp package (containing package.json and a TypeScript index.ts extension) through omp plugin install, with graphify omp path printing the package directory and both commands routed through dispatch_install_cli and silenced from the stale-graph warning. The extension runs the installed graphify hook-guard read|search CLI before native read/glob/grep/search bash calls, turning policy denials into OMP block/reason and guidance into one deduplicated per-run context message; it only inspects local filesystem targets, requires an absolute-PATH graphify outside the project, and fails open on missing commands, oversized I/O, or a two-second timeout. Note the guard relies on ctx.isProjectTrusted(), which current OMP always returns true, so it is not an enforced sandbox and should only be enabled in trusted projects.

Worth a look

  • Command inside project cwd is accepted, contradicting stated security intent — graphify/omp/index.ts:31 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Read guard payload ignores the actual file_path input — graphify/omp/index.ts:79 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Glob pattern is overwritten with resolved directory — graphify/omp/index.ts:92 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Installer executes first omp found on PATH — graphify/install.py:2113 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Concurrent tool_call handlers race on shared guidance state via check-then-act — graphify/omp/index.ts:84 · 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).

Health delta baseline: last indexed commit fe66389 (diverged from this PR's base — delta is approximate).

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, graphify/omp/package.json, 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).

@andrebrait

Copy link
Copy Markdown
Author

Triage of the refreshed automated review on 37dd4ac:

  • Project/PATH executable: installedCommand() resolves the discovered executable with realpathSync, then rejects the resolved target when it is at or inside the real project root (index.ts:25-34). The regression at tests/omp.test.ts:159-167 covers both a project-local PATH entry and an executable created in the project; an external symlink back into the project resolves to the same rejected target.
  • Read input: OMP’s native read tool supplies input.path; the extension deliberately resolves that OMP field and emits Claude-hook-compatible tool_input.file_path. The selector/strict-denial regression at tests/omp.test.ts:81-99 exercises the real CLI boundary.
  • Glob input: OMP’s glob tool supplies its glob in input.path; the extension deliberately emits it as Claude-hook-compatible tool_input.pattern. tests/omp.test.ts:101-113 compares that exact payload against the real CLI output.
  • Concurrency: the controller/guidance state is per extension instance (per AgentSession), not module-global; after each subprocess await, Set membership/byte-limit/add are one synchronous JS segment with no interleaving point.
  • Installer PATH: graphify omp install is an explicit setup command and delegates to the user-selected omp executable from PATH. It never imports or executes project Python as a fallback. This matches the documented installation boundary rather than the runtime hook’s stricter executable policy.

No code changes for those five. Dogfooding did find one real packaging issue: replaying the PR onto a newer Graphify release can leave graphify/omp/package.json stale. 37dd4ac adds a pyproject/package version equality test; the downstream 0.9.61 integration package is now versioned 0.9.61 and graphify omp install registers it as such.

@andrebrait
andrebrait force-pushed the feat/omp-native-integration branch from 37dd4ac to 445ee20 Compare September 16, 2026 19:20

@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 exposed as graphify omp install, which delegates registration to omp plugin install on the wheel-shipped graphify/omp package directory (graphify omp path prints that directory for manual linking); it refuses unless omp is on PATH and rejects any argument other than install/path. The shipped TypeScript extension runs the installed graphify hook-guard read|search CLI before native read/glob/grep/search-bash calls, turning policy denials into OMP block/reason and guidance into a deduplicated, per-run/session context message, with in-flight hooks cancelled on session boundaries. It resolves graphify only from absolute PATH entries outside the project (no project-Python fallback), inspects local paths only, and fails open under a 256 KiB input / 64 KiB output / 2s-kill budget; omp is also added to the silent-command set so it skips the freshness warning.

Worth a look

  • Read tool ignores file_path input — graphify/omp/index.ts:79 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Grep break occurs after processing only first non-remote path, but expandDelimitedPathEntries may yield multiple search roots — graphify/omp/index.ts:111 · 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 — 691 functions depend on the 418 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Test selection

Test selection

288 of 288 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 238 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, graphify/omp/package.json, 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.

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

@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 5 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 installable via graphify omp install, which shells out to omp plugin install against the shipped graphify/omp package directory (omp path prints that directory for manual linking); it registers the omp subcommand in dispatch_install_cli and marks it silent so the freshness check is skipped. The shipped extension runs the existing graphify hook-guard read|search CLI before native read/glob/grep/search-bash calls, turning policy denials into OMP block/reason and guidance into a deduplicated per-run context message, inspecting only local filesystem targets with 256 KiB input / 64 KiB output caps and a two-second subprocess budget, and failing open on missing commands or bad output. Adds a CI omp-bridge job that runs tests/omp.test.ts under bun against the installed CLI, gitignores graphify/omp/node_modules/, and documents that removal goes through omp plugin uninstall graphify-omp rather than graphify uninstall.

Worth a look

  • Read tool ignores file_path and guards cwd instead — graphify/omp/index.ts:79 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Read/Glob guard ignores native path fields — graphify/omp/index.ts:79 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Stale generation write into shared guidance set after reset — graphify/omp/index.ts · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Oversized tool input fails open — graphify/omp/index.ts:75 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • GRAPHIFY_TEST_CLI can recurse after PATH is replaced — tests/omp.test.ts:64 · 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 — 699 functions depend on the 426 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Test selection

Test selection

288 of 288 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 238 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

@andrebrait
andrebrait force-pushed the feat/omp-native-integration branch from 585baed to f38f25b Compare September 16, 2026 20:21
@andrebrait

Copy link
Copy Markdown
Author

Rebased onto the latest v8 (26b02b5) — head is now f38f25b, no conflicts.

Since the last push, the OMP bridge tests (tests/omp.test.ts) are now wired into CI as an omp-bridge job: bun resolves the real @oh-my-pi/pi-coding-agent path-utils via a pinned devDependency in graphify/omp/package.json, and the policy assertions run against the real installed Python CLI (GRAPHIFY_TEST_CLI).

The upstream checks for this PR are sitting in action_required, so a maintainer will need to approve the workflow run. The identical workflow is already green on our fork, including the new job: https://github.com/pfBlockerNG/graphify/actions/runs/35141102644 — could someone approve the run here so the PR shows its own CI signal? Thanks!

@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 behind graphify omp: graphify omp install delegates to omp plugin install on the shipped graphify/omp/ package directory (erroring if omp is absent), and graphify omp path prints that directory for manual linking. The shipped OMP extension runs the installed graphify hook-guard read|search CLI before native read/glob/grep/search-bash calls, translating the existing Python policy's decisions into OMP block/reason and deduplicated per-run context guidance under 256 KiB/64 KiB/2s caps that fail open, and requires graphify on an absolute PATH outside the project with no fallback. Registers omp as a silent install command, wires an omp-bridge CI job that runs tests/omp.test.ts against the pinned @oh-my-pi/pi-coding-agent devDependency and the real installed CLI, and documents that OMP links must be removed via omp plugin uninstall graphify-omp before uninstalling the Python package.

Worth a look

  • Generation check bypasses guidance mutation after await — graphify/omp/index.ts · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Guard bypass: 'Bash' tool payload never has command inspected, only path — graphify/omp/index.ts · 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 — 699 functions depend on the 426 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Test selection

Test selection

288 of 288 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 238 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

@andrebrait
andrebrait force-pushed the feat/omp-native-integration branch from a99e1ac to 50b4d73 Compare September 18, 2026 20:06
@andrebrait

Copy link
Copy Markdown
Author

Pushed 50b4d73 — the guidance delivery changed from a deduplicated per-run context-transform message to Claude PreToolUse additionalContext parity: tool_call still runs the guard (strict deny path, budgets, trust gating, and reset wiring unchanged), but the nudge is now appended to that call's persisted tool result. Every qualifying call carries its own guidance inline, so it survives compaction like any tool output and no longer disappears from the session transcript. Multi-target calls (e.g. delimited globs) accumulate their targets' messages instead of dropping all but one — the old dedup Set silently lost that; /node_modules is now gitignored for the local bun-test symlink.

Change went through a condensed adversarial review round before push. Findings addressed: multi-target accumulation (fixed + regression test with a varying-output fixture), and a trust recheck at delivery time (restored the distrust watchdog the context handler used to provide). Declined, with rationale: restoring the cumulative remainingOutput budget — that budget existed for the shared per-run context message; per-call delivery gets the same 64 KiB cap per call with the identical overflow-fails-open behavior (the overflow fixture still passes). Known/bounded, no action: a pending entry for a call denied at the approval gate is dropped at the next reset.

Bun suite: 7 pass / 0 fail (64 assertions) against the real installed CLI. Fork CI: https://github.com/pfBlockerNG/graphify/actions — upstream runs still need a maintainer's workflow approval.

@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 1 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 to omp plugin install against the shipped graphify/omp package directory; graphify omp path prints that directory for manual linking, and both commands are silenced from the freshness-warning check. Before native read/glob/grep and search-style bash calls the extension runs the installed graphify hook-guard CLI to reuse the existing fresh/stale policy — turning block/reason and per-call guidance appended to tool results, with strict-mode denials gated on GRAPHIFY_HOOK_STRICT=1 — and only inspects local filesystem targets, with size/time caps that fail open on missing commands or errors. Adds a CI omp-bridge job that installs both uv and bun to run tests/omp.test.ts against the real CLI and the pinned @oh-my-pi/pi-coding-agent devDependency, and ignores the extension's node_modules.

Worth a look

  • OMP installer executes first omp found on PATH — graphify/install.py:2121 · 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 — 699 functions depend on the 426 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Test selection

Test selection

288 of 288 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 238 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

@andrebrait

Copy link
Copy Markdown
Author

Pushed a fix (2904921) for a load-bearing import break plus a CI hardening step.

The break: graphify/omp/index.ts imported isReadableUrlPath from @oh-my-pi/pi-coding-agent/tools/path-utils. Upstream OMP moved that export to @oh-my-pi/pi-tui/tools/read; by 18.2.6 (current latest) path-utils.ts only imports the symbol internally and no longer re-exports it. Any OMP install past that move throws SyntaxError: Export named 'isReadableUrlPath' not found while loading the extension module, before api.on("tool_call", ...) ever registers — the hook-guard bridge silently no-ops with no error surfaced to the user.

Why CI didn't catch it: the omp-bridge job runs bun install --frozen-lockfile, and the committed lockfile pinned @oh-my-pi/pi-coding-agent@18.2.2, where the export still lived at the old path. tests/omp.test.ts imports the bridge directly and does exercise this — it just never saw a current OMP.

The fix:

  • Import isReadableUrlPath from @oh-my-pi/pi-tui/tools/read directly.
  • Raise the @oh-my-pi/pi-coding-agent devDependency floor to ^18.2.6 and declare @oh-my-pi/pi-tui@^18.2.6 as its own devDependency (the bridge now imports from it directly, so it shouldn't ride along as an undeclared transitive dep of pi-coding-agent).
  • Added an advisory omp-bridge CI step that installs whatever OMP is currently published (ignoring the lockfile) and re-runs tests/omp.test.ts against it, continue-on-error: true so an unrelated upstream release can't block a merge, while still surfacing a future symbol move instead of shipping it silently again.

Verified: bun test tests/omp.test.ts fails with the missing-export SyntaxError at 18.2.6 before this change, and passes (7 pass, 64 assertions) after.

@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 1 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 integration: graphify omp install delegates to omp plugin install on the shipped graphify/omp package directory (erroring if omp isn't on PATH), and graphify omp path prints that directory for manual linking. Before native read/glob/grep/search-bash calls the OMP extension runs the installed graphify hook-guard CLI against local filesystem targets only, turning policy decisions into block/reason denials and appending per-call guidance to tool results, with 256 KiB input / 64 KiB output caps, a two-second subprocess budget, and fail-open on any error — no graph is built or updated. Adds a CI omp-bridge job that runs tests/omp.test.ts against both the pinned OMP devDeps (blocking) and @latest (advisory, continue-on-error) to catch upstream symbol moves.

Worth a look

  • PATH-resolved hook executable inherits full secret environment — graphify/omp/index.ts:28 · 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 — 701 functions depend on the 428 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 701 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit b9cd957 (diverged from this PR's base — delta is approximate).

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

Test selection

Test selection

288 of 288 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 238 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

@andrebrait

Copy link
Copy Markdown
Author

Pushed a guard fix + bridge simplification on top of this branch (SHA ea3e24054487d125596022c0c2c95830a07c7ee1).

Guard fix (fix(hooks)): _is_cwd_relative answered "no root and no drive" to decide whether a file_path/path value from the PreToolUse read hook is cwd-anchored. A URL is rootless and driveless by that exact same test (https://x, myscheme://x, even a bare www.host/path), so it short-circuited straight to "in project" and the containment check never ran — producing a false nudge on any URL-shaped read target. file:// is handled as the deliberate exception (OMP's own pipeline resolves it to a local path, not an external URL, so it must still nudge on an in-project file). The containment check, extension allow-list, and staleness/strict-deny logic are all untouched.

Bridge simplification (refactor(omp)): now that the guard defends itself, isRemote gets a file:// carve-out (previously every file:// read was silently dropped by the bridge before ever reaching the guard); resolveReadPath → resolveReadPathAsync (non-blocking probes on the tool_call hot path, matching read.ts's own usage); and a redundant { splitter: parseSearchPath } argument is dropped (already expandDelimitedPathEntries's default).

Full test coverage (new tests/test_hook_url_paths.py, plus a bridge-level regression test in tests/omp.test.ts) and verification details are in the commit messages.

@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 5 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Adds an omp command that installs a native Oh My Pi guard package via OMP's supported omp plugin install <dir> route (with an omp path subcommand to print the shipped directory), and suppresses Graphify's staleness warning for omp runs. The OMP extension runs the existing hook-guard read|search CLI before native read/glob/grep/search-bash calls, turning policy denials into OMP block/reason and appending per-call guidance to tool results, while inspecting only local filesystem targets and failing open on missing commands, bad output, or timeouts. Tightens hook-guard path classification so a bare www.host/... value counts as remote only when no identically named local path exists (mirroring OMP's local-wins precedence), and wires up a CI omp-bridge job that runs the bridge tests against both the pinned and latest OMP versions, the latter advisory-only so an upstream release can't block a merge.

Worth a look

  • file:// authority is dropped during hook path normalization — graphify/cli.py:983 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Hook guard executable is selected from PATH — graphify/omp/index.ts:38 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Runtime OMP imports are declared only as devDependencies — graphify/omp/package.json:8 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Read input ignores file_path and falls back to project root — graphify/omp/index.ts:92 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • CI executes unpinned latest npm packages — .github/workflows/ci.yml:116 · 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 — 833 functions depend on the 520 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 833 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit b9cd957 (diverged from this PR's base — delta is approximate).

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

Test selection

Test selection

289 of 289 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 239 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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 \_is\_cwd\_relative (not a proof).

The verifier ran both versions of \_is\_cwd\_relative 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\_hook\_guard (not a proof).

The verifier ran both versions of \_run\_hook\_guard 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 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.

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

@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. 4 change(s) tested, no difference found (not proven).


Graphify review — findings

Adds a native Oh My Pi guard integration: graphify omp install links the shipped graphify/omp package via OMP's omp plugin install, and graphify omp path prints that directory for manual linking. The extension runs the installed graphify hook-guard read|search CLI before native read/glob/grep/search-bash calls, turning strict-mode policy denials into OMP block/reason and appending per-call guidance to each tool result — inspecting only local filesystem targets and failing open on missing commands, oversized I/O, or the two-second budget. Silences the update-nudge for omp commands, teaches the search-scope guard to treat a bare www.host/... target as remote only when no identically-named local path exists (_is_external_www_target), and gates the new bridge behind a dedicated CI job that runs tests/omp.test.ts against both the pinned and latest OMP (the latter advisory).

Worth a look

  • Read tool target is ignored when input uses file_path — graphify/omp/index.ts:104 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • CI executes mutable latest npm package code — .github/workflows/ci.yml:123 · 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 — 832 functions depend on the 519 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 832 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit b9cd957 (diverged from this PR's base — delta is approximate).

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

Test selection

Test selection

289 of 289 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 239 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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 \_is\_cwd\_relative (not a proof).

The verifier ran both versions of \_is\_cwd\_relative 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\_hook\_guard (not a proof).

The verifier ran both versions of \_run\_hook\_guard 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 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.

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

@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 4 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Adds a native Oh My Pi guard integration exposed via graphify omp install (delegating to omp plugin install on the shipped graphify/omp/ package) and graphify omp path, which runs the installed hook-guard before native read/glob/grep/search-bash calls, turns policy denials into OMP block/reason, and appends per-call guidance to tool results without ever building or updating a graph. Tightens remote-vs-local path handling in _run_hook_guard so a bare www.host/... target is treated as external only when no identically named local path exists (mirroring OMP's resolveToolSearchScope precedence), and vendors isReadableUrlPath locally in graphify/omp/index.ts rather than importing it from an upstream package that has moved the symbol between releases. Wires up CI with an omp-bridge job that runs the bun bridge tests against both the pinned OMP devDependency (blocking) and the latest published OMP (advisory), and silences the startup version check for omp commands. Note: the extension checks ctx.isProjectTrusted(), but current OMP hardcodes that to true, so this is trust-gated in name only — enable only in trusted projects, and graphify uninstall does not remove the OMP link (omp plugin uninstall graphify-omp must run first).

Worth a look

  • CI installs mutable npm package code at @latest — .github/workflows/ci.yml:124 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Remote file:// authorities bypass URL guard — graphify/omp/index.ts:41 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Read events ignore file_path and inspect cwd instead — graphify/omp/index.ts:107 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • file:// host component is silently discarded — graphify/cli.py:985 · 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 — 832 functions depend on the 519 functions this change touches.

Health — this change adds coupling hotspots:

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

Verification — 832 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit b9cd957 (diverged from this PR's base — delta is approximate).

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

Test selection

Test selection

289 of 289 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 239 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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 \_is\_cwd\_relative (not a proof).

The verifier ran both versions of \_is\_cwd\_relative 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\_hook\_guard (not a proof).

The verifier ran both versions of \_run\_hook\_guard 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 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.

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

@andrebrait

Copy link
Copy Markdown
Author

Thanks for the review — going through all four findings below. Two were genuine bugs (both stemming from the same root cause), one CI hardening item is now addressed differently, and one is refuted with evidence. Appreciate the flag on all of them; the bot was right to mark them unverified and ask for human review.

#2 and #4 — remote file:// authorities bypassing the guard: APPLIED

Both findings were the same bug in the two layers that classify file:// values: _normalize_hook_path in graphify/cli.py and isRemote in graphify/omp/index.ts. Both unconditionally treated any file:// value as a local path, discarding the authority entirely. file://evil.com/<in-project path> therefore classified identically to file:///<in-project path> — a remote host aliasing a real local file just by sharing its path component.

The rule now applied, mirroring the host rather than inventing one: a file:// URL is local only when its authority is empty or localhost (RFC 8089; Node's own url.fileURLToPath enforces exactly this, throwing ERR_INVALID_FILE_URL_HOST for any other host). Any other authority now falls through to the existing foreign-scheme handling on both layers, the same path an https:// or any other remote scheme already took.

Before (pre-fix, reproduced against the installed guard):

file:///root/git/pfBlockerNG/src/.../pfb_unbound.py         -> NUDGE   (correct)
file://evil.com/root/git/pfBlockerNG/src/.../pfb_unbound.py -> NUDGE   (WRONG — remote host treated as an in-project file)

After (rebuilt guard, same probe plus the localhost row):

file:///root/git/pfBlockerNG/src/.../pfb_unbound.py         -> NUDGE      (unchanged — still local)
file://evil.com/root/git/pfBlockerNG/src/.../pfb_unbound.py -> silent     (fixed — remote host, not aliased)
file://localhost/root/git/pfBlockerNG/src/.../pfb_unbound.py -> NUDGE     (localhost is local per RFC 8089 / Node)

Both layers, plus RED→GREEN tests for both, are covered in graphify/cli.py (_normalize_hook_path), graphify/omp/index.ts (isRemote), tests/test_hook_url_paths.py, and tests/omp.test.ts.

#1 — unpinned @latest execution in the CI advisory step: APPLIED

The step existed to catch upstream symbol moves without waiting for the frozen lockfile to notice (it's happened before: isReadableUrlPath moved from pi-coding-agent to pi-tui). But the mechanism for catching that was "install whatever OMP publishes today and execute the bridge suite against it" — unpinned, mutable third-party code running unconditionally on every CI invocation.

Replaced with a download-only check: fetch the package with install scripts disabled (bun add --ignore-scripts), then statically compare the set of named symbols graphify/omp/index.ts imports from @oh-my-pi/pi-coding-agent/tools/path-utils against the exports that file actually declares — as plain text, via regex, the same way tests/omp.test.ts already checks the oldest host-provided copy. The downloaded package is never imported or executed; only its source text is read. This still catches the exact upstream move that motivated the step (verified locally by simulating a renamed export against a real downloaded copy — the check fails as expected), while removing the arbitrary-code-execution surface. continue-on-error: true is unchanged, so an unrelated upstream release still can't block a merge.

#3 — read events ignoring file_path: SKIPPED (refuted)

OMP's native read tool has no file_path field. From packages/coding-agent/src/tools/read.ts:633-649 (all four schema variants the tool can be constructed with):

const readSchema = type({
	path: type("string").describe("Local path, internal URI (e.g. memory://), or URL. Inline selectors are supported."),
});

const readSchemaWithSkills = type({
	path: type("string").describe(
		"Local path, internal URI (e.g. memory://, skill://), or URL. Inline selectors are supported.",
	),
});

const readSchemaWithoutMemory = type({
	path: type("string").describe("Local path, internal URI, or URL. Inline selectors are supported."),
});

const readSchemaWithoutMemoryWithSkills = type({
	path: type("string").describe("Local path, internal URI (e.g. skill://), or URL. Inline selectors are supported."),
});

Every variant is path; file_path does not appear anywhere in that file. event.input.path is therefore always the correct field for a native OMP read event, and the : "." fallback in index.ts never fires for one. The likely source of the confusion: the bridge itself emits file_path — as the field name in the Claude-shaped payload it constructs for the hook-guard CLI (if (toolName === "Read") input.file_path = resolved;), which is the correct field name in that direction, not the field OMP's own read event carries.


No code change for #3; #1, #2, and #4 are applied on this branch (feat/omp-native-integration) and cherry-picked onto integration.

@andrebrait
andrebrait force-pushed the feat/omp-native-integration branch from fd869d8 to 22caf5e Compare September 22, 2026 14:27

@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 3 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Adds an Oh My Pi native guard shipped as a linkable package, installed via graphify omp install (with graphify omp path for manual linking and omp plugin uninstall graphify-omp to remove it). Before native read/glob/grep/search bash calls the extension runs the installed graphify hook-guard CLI to reuse the existing fresh/stale policy for bounded denials and per-call guidance appended to tool results, inspecting only local filesystem targets with 256 KiB input / 64 KiB output caps and a two-second subprocess budget, and failing open on missing commands or bad output. Adds an omp-bridge CI job that runs the bridge tests against the pinned OMP plus a non-blocking advisory step that statically checks whether @latest still exports the path-utils symbols index.ts imports.

Worth a look

  • OMP guard ignores Read/Glob canonical path fields — graphify/omp/index.ts:111 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Import allow-list test misses side-effect imports — tests/omp.test.ts · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Test leaks mutated PATH into the rest of the test process — tests/omp.test.ts · 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 — 842 functions depend on the 529 functions this change touches.

Health — this change adds coupling hotspots:

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

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

Test selection

Test selection

293 of 293 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_dedup_scope.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_external_call_guards.py — full-run-safety
  • tests/test_cross_repo_member_calls.py — full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • … and 243 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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 \_is\_cwd\_relative (not a proof).

The verifier ran both versions of \_is\_cwd\_relative 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\_hook\_guard (not a proof).

The verifier ran both versions of \_run\_hook\_guard 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 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.

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

Claude PreToolUse additionalContext parity: run the guard in tool_call as before (strict deny path unchanged), but deliver the nudge by appending it to that call's tool_result content instead of accumulating a deduped context-transform message. Every qualifying call now carries its own guidance inline, persisted across compaction like any tool output; the before_agent_start reset now only clears pending deliveries.
Copilot review finding: the README still described the replaced deduplicated context message. Describe the actual behavior: each qualifying call's guidance is appended to that call's persisted tool result.
Upstream OMP moved isReadableUrlPath from
@oh-my-pi/pi-coding-agent/tools/path-utils to @oh-my-pi/pi-tui/tools/read.
At the 18.2.2 devDependency floor path-utils still re-exported it, so CI
stayed green, but every OMP install past that point (18.2.6 is current)
throws SyntaxError: Export named 'isReadableUrlPath' not found before the
extension's api.on("tool_call", ...) ever registers, silently disabling
the hook-guard nudge.

Import it from @oh-my-pi/pi-tui/tools/read directly, raise the
@oh-my-pi/pi-coding-agent floor to ^18.2.6 (the first version pinned by
this fix where the export lives at its new home), and declare
@oh-my-pi/pi-tui ^18.2.6 as its own devDependency since the bridge now
imports from it directly rather than relying on it as an undeclared
transitive dependency of pi-coding-agent.
bun install --frozen-lockfile in the omp-bridge job pins an exact known-good
OMP version, so CI can never observe a future upstream symbol move (this is
exactly how the pi-tui export move shipped unnoticed: the lockfile pinned
18.2.2, where isReadableUrlPath still lived in pi-coding-agent). Add a step
that installs whatever OMP publishes today and re-runs the suite against it,
continue-on-error like the security-scan job's advisory checks, so an
unrelated upstream release cannot block a merge while still surfacing a
real break.
…oject guard

_is_cwd_relative answered "no root and no drive" to decide whether a
file_path/path value is cwd-anchored. A URL is rootless and driveless by
that exact same test (https://x, myscheme://x, and a bare www.host/path
all have no root/drive), so it short-circuited straight to "in project"
and the containment check below never ran.

- _normalize_hook_path: trims/de-quotes input and strips a leading
  file:// scheme to the local path it names (OMP's own pipeline resolves
  file:// to a local path, not an external URL -- it must still nudge).
- _is_foreign_url_scheme: rejects any other whole-value scheme://
  prefix. Deliberately does not enumerate a harness's internal-scheme
  vocabulary (local://, artifact://, ...) -- an unrecognized scheme is
  simply treated as not-a-local-source-file.
- _has_embedded_url_scheme_segment: catches the same URL after an
  upstream host has already glued it onto an absolute prefix
  (<root>/local:/x), which looks exactly like a real file to the
  (unchanged) containment check.
- _is_external_www_target: a bare www.host/path carries no :// at all,
  so it is handled separately, existence-gated to mirror OMP's own
  "an existing local path wins over URL" precedence.

Containment, the extension allow-list, and staleness/strict-deny logic
are untouched.
- isRemote gets a file:// carve-out: OMP's own resolveReadPathAsync
  already reduces file:// to the real local path (its
  strictExternalUrlRe deliberately excludes file), so routing it
  through yields the correct absolute path instead of silently
  dropping every file:// read. isInternalUrlPath/isReadableUrlPath
  keep earning their place -- resolveReadPathAsync still pre-resolves
  a rootless *foreign*-scheme value onto cwd into something that reads
  as a real in-project file, so the bridge still must not hand it
  those.
- resolveReadPath -> resolveReadPathAsync: same variant order/winner
  semantics, non-blocking probes instead of statSync per candidate on
  the tool_call hot path (read.ts itself already uses the async
  variant).
- Drop the explicit { splitter: parseSearchPath } argument to
  expandDelimitedPathEntries -- already its default.

Adds one bridge-level regression test: an in-project file:// target
still nudges, an out-of-project one still stays silent.
The OMP host loads graphify/omp/index.ts from its installed site-packages
location, which ships no node_modules (see package.json's "files" list).
The host provides @oh-my-pi/pi-coding-agent to legacy extensions but never
@oh-my-pi/pi-tui, so the bridge's `isReadableUrlPath` import from
@oh-my-pi/pi-tui/tools/read failed at runtime with
`Cannot find package '@oh-my-pi/pi-tui'`, disabling the extension entirely.

Vendor the two-line isReadableUrlPath predicate locally instead of
importing it, drop the now-unused @oh-my-pi/pi-tui devDependency and
regenerate bun.lock, and update the CI advisory step that used to bump
both packages. Add a regression test asserting index.ts only imports
@oh-my-pi/pi-coding-agent and node: builtins, so a future reintroduction
of an unresolvable package fails the suite instead of only the host.
…er host copies

Two @oh-my-pi/pi-coding-agent copies are reachable on this machine
(18.1.17 and 18.2.6) and we cannot determine from outside the host
which one it binds. Auditing every bridge import against the older
18.1.17 copy found resolveReadPathAsync missing -- it was only added
in a later release as a non-blocking-probe performance optimization
(per its own upstream docstring: "identical variant order and winner
semantics, but non-blocking probes"), not a correctness fix.

Revert to the synchronous resolveReadPath, present in both copies, so
the extension loads regardless of which copy the host binds. A
marginally faster extension that fails to load is worth nothing.

Strengthen the import allow-list test with a version-floor check:
every named import the bridge takes from
@oh-my-pi/pi-coding-agent/tools/path-utils must be exported by the
oldest host-provided copy. Parses the real import list out of
index.ts rather than hardcoding it, so a future added symbol is
checked automatically. Skips cleanly when that copy is not present
on the machine running the suite.
…ct file

_normalize_hook_path unconditionally reduced any file:// value to its
path component, discarding the authority. file://evil.com/<in-project
path> then classified identically to file:///<in-project path>: the
same absolute path, silently treated as local.

RFC 8089 / Node's url.fileURLToPath (ERR_INVALID_FILE_URL_HOST) say a
file:// URL is local only when its authority is empty or localhost.
Reduce only those two forms; leave any other authority intact so
_is_foreign_url_scheme classifies it as the remote reference it is.
isRemote's file:// carve-out matched the scheme alone: any authority
was treated as local, so file://evil.com/<in-project path> reached
resolveReadPath, resolved to the real local path, and reached the
guard as if it named a file in the project.

Mirror Node's own url.fileURLToPath (ERR_INVALID_FILE_URL_HOST): only
an empty or localhost authority is local. Any other authority now
falls through to the generic scheme:// remote check, same as it would
for https:// or any other foreign scheme.
The advisory job installed @oh-my-pi/pi-coding-agent@latest and ran
the bridge suite against it on every CI run -- mutable, unpinned
third-party code executing unconditionally. Replace the install-and-
run with a download-only check: fetch the package with install scripts
disabled, then statically compare index.ts's imported path-utils
symbols against that file's declared exports as plain text. The
downloaded package is never imported or executed, but the same
upstream symbol move (isReadableUrlPath, pi-coding-agent -> pi-tui)
that motivated this step still surfaces.
@andrebrait
andrebrait force-pushed the feat/omp-native-integration branch 2 times, most recently from 22caf5e to ed70c8b Compare September 23, 2026 20:29
andrebrait added a commit to pfBlockerNG/graphify that referenced this pull request Sep 23, 2026
…xt through native hooks

Squashed from origin/feat/omp-native-integration (96d155e) onto upstream/v8.

@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. 4 change(s) tested, no difference found (not proven).


Graphify review — findings

Adds first-class Oh My Pi (OMP) support via a native guard extension: graphify omp install delegates to omp plugin install on the shipped graphify/omp/ package directory (linked, not vendored as npm/shell shims), graphify omp path prints that directory, and uninstall is done through omp plugin uninstall graphify-omp. The extension gates native read/glob/grep/search-bash calls through the installed graphify hook-guard CLI, translating policy denials into OMP block/reason and appending per-call guidance to tool results (with local-only path inspection, size/time caps, fail-open on error, and cancellation on session boundaries); it checks ctx.isProjectTrusted() but that method is currently always-true, so it's not an enforced sandbox. Adds a CI omp-bridge job that runs the tests/omp.test.ts suite against the pinned host plus real Python CLI, and an advisory static check that flags when @oh-my-pi/pi-coding-agent@latest stops exporting the path-utils symbols index.ts imports.

Worth a look

  • Glob tool contract drops the user glob pattern — graphify/omp/index.ts:125 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Test mutates global PATH without restoring it — tests/omp.test.ts · 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 — 869 functions depend on the 533 functions this change touches.

Health — this change adds coupling hotspots:

  • new: main() — 98 callers, 3 callees
  • new: dispatch_command() — 2 callers, 125 callees
  • new: dispatch_install_cli() — 6 callers, 31 callees
  • new: install() — 13 callers, 11 callees
  • new: codebuddy_install() — 20 callers, 5 callees
  • new: gemini_install() — 11 callers, 7 callees
  • new: claude_install() — 19 callers, 4 callees
  • new: _copy_skill_file() — 12 callers, 6 callees
  • …and 17 more — each is listed as a finding

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

Test selection

Test selection

303 of 303 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_dedup_scope.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_cargo_missing_manifest.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_cobol_extractor.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_external_call_guards.py — full-run-safety
  • … and 253 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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 \_is\_cwd\_relative (not a proof).

The verifier ran both versions of \_is\_cwd\_relative 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\_hook\_guard (not a proof).

The verifier ran both versions of \_run\_hook\_guard 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 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.

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

Claude Code wraps PreToolUse additionalContext in a system reminder that
names the hook; the OMP bridge appended the bare guidance after the tool
output, where it read as text the tool printed and agents discounted it as
untrusted. Lead each qualifying result with one
<system-reminder source="graphify"> block instead, the shape OMP's own
per-tool TTSR reminders use, and keep the tool output unchanged after it.
andrebrait added a commit to pfBlockerNG/graphify that referenced this pull request Sep 24, 2026
…xt through native hooks

Squashed from origin/feat/omp-native-integration (25e46e5) onto upstream/v8.

@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.


Graphify review — findings

Adds a native Oh My Pi guard integration installed via graphify omp install, which links the shipped graphify/omp package through OMP's own omp plugin install route and runs the existing hook-guard read|search policy before native read/glob/grep/search-bash calls, injecting per-call guidance as a leading <system-reminder source="graphify"> block on each tool result and honoring GRAPHIFY_HOOK_STRICT=1 denials without ever building a graph. Hooks only inspect local filesystem targets, require an absolute-PATH graphify outside the project with no fallback, and enforce 256 KiB input / 64 KiB output / two-second budgets that fail open; omp is now silenced from the stale-graph warning path and graphify omp path prints the package directory for manual linking. Adds an omp-bridge CI job that runs the bridge tests against the pinned OMP version as the blocking gate plus an advisory, non-executing static check that a @latest download still exports the path-utils symbols index.ts imports.

Worth a look

  • Read tool guard ignores file_path and inspects cwd — graphify/omp/index.ts:123 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Test mutates process.env.PATH without restoration — tests/omp.test.ts · 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 — 871 functions depend on the 535 functions this change touches.

Health — this change adds coupling hotspots:

  • new: main() — 98 callers, 3 callees
  • new: dispatch_command() — 2 callers, 125 callees
  • new: dispatch_install_cli() — 6 callers, 31 callees
  • new: install() — 13 callers, 11 callees
  • new: codebuddy_install() — 20 callers, 5 callees
  • new: gemini_install() — 11 callers, 7 callees
  • new: claude_install() — 19 callers, 4 callees
  • new: _copy_skill_file() — 12 callers, 6 callees
  • …and 17 more — each is listed as a finding

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

Test selection

Test selection

303 of 303 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_dedup_scope.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_cargo_missing_manifest.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_cobol_extractor.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_external_call_guards.py — full-run-safety
  • … and 253 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

OMP reads its agent skills from ~/.omp/agent/skills, not the legacy ~/.pi path the pi platform writes, so the installer had no OMP target even though 'omp' was already reserved in the CLI command set. Adds the omp platform reusing pi's skill bundle (OMP mirrors pi's agent layout), the pi-twin 'graphify omp' subcommand, and the project-scope groups; tests lock destinations, bundle reuse, install/uninstall, and uninstall_all pi parity.
…staller

The merged omp-platform branch added a pi-twin 'graphify omp [install|uninstall]' dispatch branch, unreachable behind the bridge PR's 'graphify omp [path|install]' plugin branch. The subcommand surface belongs to the plugin installer: drop the duplicate, and carry the user-scope skill removal in uninstall_all (like amp/agents) since omp has no subcommand twin.
andrebrait added a commit to pfBlockerNG/graphify that referenced this pull request Sep 24, 2026
…xt through native hooks

Squashed from origin/feat/omp-native-integration (0fd7486) onto upstream/v8.

@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 5 advisory finding(s) below merit a look before merge.


Graphify review — findings

Adds an Oh My Pi native guard integration: graphify omp install links the shipped graphify/omp package (with package.json declaring omp.extensions) via OMP's omp plugin install, and graphify omp path prints that directory for manual linking. The extension runs the installed graphify hook-guard before native read/glob/grep/search bash calls, turning policy denials into OMP block/reason and appending per-call guidance as a leading <system-reminder source="graphify"> block on tool results, inspecting only local filesystem targets and failing open on missing commands, bad output, or the 2s/256 KiB/64 KiB budgets. Adds an omp-bridge CI job that runs the bun bridge tests against the frozen pinned OMP plus a non-blocking advisory step that statically checks whether @latest still exports the path-utils symbols index.ts imports; index.ts now vendors isReadableUrlPath locally rather than importing it.

Worth a look

  • Glob hook payload overwrites the user's glob pattern with a resolved path — graphify/omp/index.ts:132 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • New CI job executes mutable third-party GitHub Actions — .github/workflows/ci.yml:88 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • omp platform config duplicates 'pi' skill_dst under project scope but user-scope uses ~/.omp/agent/skills — graphify/install.py:1934 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Relative GRAPHIFY_TEST_CLI is shadowed by the fixture — tests/omp.test.ts:10 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Test mutates global PATH without restoring it — tests/omp.test.ts · 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 — 889 functions depend on the 553 functions this change touches.

Health — this change adds coupling hotspots:

  • new: main() — 99 callers, 3 callees
  • new: dispatch_command() — 2 callers, 125 callees
  • new: dispatch_install_cli() — 6 callers, 31 callees
  • new: install() — 13 callers, 11 callees
  • new: codebuddy_install() — 20 callers, 5 callees
  • new: gemini_install() — 11 callers, 7 callees
  • new: claude_install() — 19 callers, 4 callees
  • new: _copy_skill_file() — 12 callers, 6 callees
  • …and 17 more — each is listed as a finding

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

Test selection

Test selection

304 of 304 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_dedup_scope.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_cargo_missing_manifest.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_cobol_extractor.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_external_call_guards.py — full-run-safety
  • … and 254 more

non-code file(s) changed (.github/workflows/ci.yml, .gitignore, CHANGELOG.md, README.md, graphify/omp/bun.lock …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (.github/workflows/ci.yml, CHANGELOG.md, README.md, graphify/omp/package.json, 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.

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

This branch has not been deployed

No deployments
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