Skip to content

Binding diagnostics as a core artifact#336

Open
koriym wants to merge 2 commits into
ray-di:2.xfrom
koriym:extract-bindings-package
Open

Binding diagnostics as a core artifact#336
koriym wants to merge 2 commits into
ray-di:2.xfrom
koriym:extract-bindings-package

Conversation

@koriym

@koriym koriym commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

Make composed bindings a first-class, readable artifact of Ray.Di, and move rich
visualization out of core.

  • Move binding diagnostics out of core — the Ray\Bindings namespace (HTML
    viewer, bindings-html CLI, viewer assets) and the deprecated
    Ray\Di\BindingsMarkdown shim are removed. Rich visualization moves to the
    ray/object-visual-grapher package. Ray\Di\ModuleVisitorInterface becomes
    the stable route for tools to visit a module's composed container via
    AbstractModule::accept().
  • Write bindings.md at composition time — an Injector created with an
    explicit tmpDir writes {tmpDir}/bindings.md: a deterministic, human- and
    agent-readable snapshot of every resolved binding, the composing modules, and
    the binding provenance. The writer is best-effort and atomic (tmp file +
    rename), the file carries its own signature trailer so an unchanged binding
    surface skips rewriting, and getInstance() performs no diagnostics I/O. The
    shared sys_get_temp_dir() fallback is not application-owned, so nothing is
    written there.

Not in this PR

Runtime just-in-time (JIT) binding is intentionally left untouched here. Its
future is tracked separately as a soft-deprecation (keep resolving, emit
E_USER_DEPRECATED, no scheduled removal) in #337 (EN) / #338 (JA). Keeping it
out of this PR lets binding diagnostics land independently of that discussion —
bindings.md is a composition-time snapshot and does not depend on the JIT
outcome.

Commits

  1. Move binding diagnostics out of core
  2. Write bindings.md at composition time

Test plan

  • 264 tests / 435 assertions green
  • Coverage 100% (classes, methods, lines)
  • PHPStan / Psalm / phpcs / phpmd pass
  • PHP 8.2–8.5

Notes

Intended as a Ray.Di minor (2.23.0); the public API is unchanged. Removing the
Ray\Bindings\* classes shipped in 2.22.2 is a small BC break covered by the
migration to ray/object-visual-grapher.

Summary by CodeRabbit

  • New Features

    • Added a “binding diagnostics” workflow: when you create an Injector with an explicit existing temp directory, it writes an atomic bindings.md snapshot during composition and refreshes it only when composed bindings change.
    • Added documentation guidance to visualize composed bindings/object graphs with Ray.ObjectGrapher.
  • Bug Fixes

    • Ensured getInstance() performs no diagnostics file I/O.
    • Improved interceptor reporting to include interceptor class names for instance-based interceptors.
  • Documentation

    • Replaced prior manual snapshot/HTML viewer instructions with the new workflow and an Injector(new AppModule(), $tmpDir) example.
  • Chores

    • Removed the legacy bindings HTML renderer, viewer assets, and associated CLI.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Binding diagnostics are implemented directly in Ray\Di, using signature-based, atomic bindings.md snapshots generated during explicit-directory composition. Legacy bindings rendering, CLI, assets, autoload mappings, and related test scopes are removed.

Changes

Binding diagnostics

Layer / File(s) Summary
Deterministic snapshot writer and lifecycle tests
src/di/BindingsMarkdown.php, tests/di/BindingsMarkdownTest.php
BindingsMarkdown renders provenance diagnostics, embeds a signature, skips unchanged files, rewrites stale snapshots, and writes atomically. Tests cover composition-time output, modification-time stability, and interceptor instances.
Composition-time integration and contracts
src/di/Injector.php, src/di/ModuleVisitorInterface.php, src/di/AbstractModule.php, src/di/SpyCompiler.php, tests/di/AbstractModuleTest.php
Injector writes diagnostics only for explicit existing directories; ModuleVisitorInterface moves to Ray\Di; module visitor handling and interceptor-name formatting support the updated namespace and object values.
Package, tooling, and documentation scope
composer.json, phpstan.neon, phpunit.xml.dist, psalm.xml, README.md
Legacy bindings autoloading, executable, renderer assets, source files, and tests are removed. Analysis targets are narrowed, ObjectGrapher is suggested, and README documents explicit-directory diagnostics.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Application
  participant Injector
  participant Container
  participant BindingsMarkdown
  participant bindingsmd as bindings.md
  Application->>Injector: construct with explicit tmpDir
  Injector->>Container: compose modules
  Injector->>BindingsMarkdown: generate diagnostics
  BindingsMarkdown->>Container: read bindings and provenance
  BindingsMarkdown->>bindingsmd: atomically write changed snapshot
  Application->>Injector: call getInstance()
  Injector-->>Application: return instance without diagnostics I/O
Loading

Possibly related PRs

  • ray-di/Ray.Di#323: Adds the binding provenance and collision data consumed by the new markdown diagnostics.
  • ray-di/Ray.Di#327: Also modifies signature-based bindings.md caching and rewrite behavior.
  • ray-di/Ray.Di#331: Relates to the explicit visitor workflow and composition-time snapshot generation.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is related to the PR, but it is too vague to clearly convey the main change. Use a more specific title such as "Make bindings diagnostics a core artifact via explicit tmpDir snapshots".
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (236ac26) to head (ab660d7).

Additional details and impacted files
@@             Coverage Diff              @@
##                 2.x      #336    +/-   ##
============================================
  Coverage     100.00%   100.00%            
+ Complexity       460       413    -47     
============================================
  Files             53        50     -3     
  Lines           1184      1072   -112     
============================================
- Hits            1184      1072   -112     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@koriym
koriym force-pushed the extract-bindings-package branch 2 times, most recently from 1daea41 to ccefb7b Compare July 22, 2026 09:14
@koriym koriym changed the title Binding diagnostics as a core artifact, and remove runtime JIT binding Binding diagnostics as a core artifact Jul 22, 2026
@koriym
koriym marked this pull request as ready for review July 23, 2026 18:19

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plan.md`:
- Around line 94-108: Update the caching contract around BindingsMarkdown to
state that reuse is signature-based, using only resolved bindings and pointcuts,
rather than content-based. Explicitly note that provenance is intentionally
excluded from the signature even though it appears in rendered Markdown, so
matching signatures may reuse existing content; preserve the existing
deterministic-output and best-effort runtime-path requirements.
- Around line 162-164: Update the namespace count in the sentence beginning “1
package 2 namespace” to reflect the three configured prefixes:
Ray\ObjectGrapher, Ray\Bindings, and Ray\Di. Preserve the existing explanation
about the three output formats.

In `@README.md`:
- Around line 17-23: Update the README Injector example and surrounding
description to state that the explicit $tmpDir must already exist and be
writable; clarify that nonexistent paths fall back to sys_get_temp_dir() and do
not receive bindings.md, or create the directory before constructing Injector.

In `@tests/di/BindingsMarkdownTest.php`:
- Around line 146-149: Update the temporary-file setup in the bindings markdown
test to stop unlinking the shared /tmp/bindings.md path. Assert its expected
absent or unchanged state without deleting an existing file, preserving the
test’s cleanup and validation behavior otherwise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f6338e97-efa1-41ee-8799-ee93dbdf23bb

📥 Commits

Reviewing files that changed from the base of the PR and between 236ac26 and ccefb7b.

📒 Files selected for processing (22)
  • README.md
  • bin/bindings-html
  • composer.json
  • docs/bindings/bindings.css
  • docs/bindings/bindings.js
  • phpstan.neon
  • phpunit.xml.dist
  • plan.md
  • psalm.xml
  • src-bindings/Bindings.php
  • src-bindings/BindingsHtml.php
  • src-bindings/BindingsMarkdown.php
  • src-bindings/Exception/BindingsNotCollected.php
  • src/di/AbstractModule.php
  • src/di/BindingsMarkdown.php
  • src/di/Injector.php
  • src/di/ModuleVisitorInterface.php
  • src/di/SpyCompiler.php
  • tests-bindings/BindingsHtmlTest.php
  • tests-bindings/BindingsTest.php
  • tests/di/AbstractModuleTest.php
  • tests/di/BindingsMarkdownTest.php
💤 Files with no reviewable changes (13)
  • docs/bindings/bindings.css
  • psalm.xml
  • src-bindings/Bindings.php
  • src-bindings/Exception/BindingsNotCollected.php
  • bin/bindings-html
  • phpstan.neon
  • docs/bindings/bindings.js
  • src-bindings/BindingsMarkdown.php
  • src-bindings/BindingsHtml.php
  • tests-bindings/BindingsTest.php
  • src/di/AbstractModule.php
  • phpunit.xml.dist
  • tests-bindings/BindingsHtmlTest.php

Comment thread plan.md Outdated
Comment thread plan.md Outdated
Comment thread README.md Outdated
Comment thread tests/di/BindingsMarkdownTest.php Outdated
Drop the Ray\Bindings namespace (Bindings, BindingsMarkdown, BindingsHtml,
the bindings-html CLI and its viewer assets) and the deprecated
Ray\Di\BindingsMarkdown shim. Rich visualization moves to the
ray/object-visual-grapher package; composition provenance (BindingLog)
stays in core.

Ray\Di\ModuleVisitorInterface replaces Ray\Bindings\ModuleVisitorInterface
as the stable route for tools to visit a module's composed container via
AbstractModule::accept().
@koriym
koriym force-pushed the extract-bindings-package branch from ccefb7b to 13d4ccb Compare July 24, 2026 07:54

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/di/BindingsMarkdown.php`:
- Around line 72-73: Update the cache signature used by
BindingsMarkdown::render() in src/di/BindingsMarkdown.php lines 72-73 to include
all module and provenance inputs that affect the rendered markdown, so
provenance-only composition changes invalidate the existing diagnostics file. In
tests/di/BindingsMarkdownTest.php lines 215-231, update the second-composition
expectation to assert that the snapshot reflects SecondModule.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 37574515-81f5-4416-a4ab-3e2da13db5dc

📥 Commits

Reviewing files that changed from the base of the PR and between ccefb7b and 13d4ccb.

📒 Files selected for processing (21)
  • README.md
  • bin/bindings-html
  • composer.json
  • docs/bindings/bindings.css
  • docs/bindings/bindings.js
  • phpstan.neon
  • phpunit.xml.dist
  • psalm.xml
  • src-bindings/Bindings.php
  • src-bindings/BindingsHtml.php
  • src-bindings/BindingsMarkdown.php
  • src-bindings/Exception/BindingsNotCollected.php
  • src/di/AbstractModule.php
  • src/di/BindingsMarkdown.php
  • src/di/Injector.php
  • src/di/ModuleVisitorInterface.php
  • src/di/SpyCompiler.php
  • tests-bindings/BindingsHtmlTest.php
  • tests-bindings/BindingsTest.php
  • tests/di/AbstractModuleTest.php
  • tests/di/BindingsMarkdownTest.php
💤 Files with no reviewable changes (14)
  • docs/bindings/bindings.js
  • psalm.xml
  • phpunit.xml.dist
  • bin/bindings-html
  • src-bindings/BindingsHtml.php
  • docs/bindings/bindings.css
  • src-bindings/Bindings.php
  • README.md
  • src-bindings/Exception/BindingsNotCollected.php
  • tests-bindings/BindingsTest.php
  • phpstan.neon
  • src/di/AbstractModule.php
  • tests-bindings/BindingsHtmlTest.php
  • src-bindings/BindingsMarkdown.php
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/di/SpyCompiler.php
  • composer.json
  • src/di/Injector.php

Comment thread src/di/BindingsMarkdown.php
An Injector created with an explicit tmpDir writes the composed bindings
to {tmpDir}/bindings.md: a deterministic, human- and agent-readable
snapshot of every resolved binding, the modules that composed them, and
the binding provenance. The shared sys_get_temp_dir() fallback is not
application-owned, so no file is written there.

Ray\Di\BindingsMarkdown keeps the 2.22 API (__invoke(Container, string)
and render(Container)) as the real implementation instead of a shim.
The writer is best-effort and atomic (tmp file + rename), and the file
carries its own signature trailer: an unchanged binding surface skips
rendering and writing, resolution performs no diagnostics I/O, and a
container revived with an empty provenance log keeps the richer
snapshot written at composition time.

SpyCompiler now names interceptor instances by their class so a
pointcut bound to an interceptor object renders instead of silently
skipping the write.
@koriym
koriym force-pushed the extract-bindings-package branch from 13d4ccb to ab660d7 Compare July 24, 2026 08:20
@koriym

koriym commented Jul 24, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai No outstanding blockers. Please resolve all open conversations and approve this PR.

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

🧹 Nitpick comments (1)
tests/di/BindingsMarkdownTest.php (1)

60-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a helper to remove the repeated markdown-read boilerplate.

The $markdown = file_get_contents(...); assert(is_string($markdown)); pair is duplicated across essentially every test method. A small private helper would cut the repetition and keep assertions focused on the interesting part.

♻️ Proposed helper
 class BindingsMarkdownTest extends TestCase
 {
     private string $classDir;
+
+    private function readMarkdown(): string
+    {
+        $markdown = file_get_contents($this->classDir . '/bindings.md');
+        assert(is_string($markdown));
+
+        return $markdown;
+    }

Then, e.g.:

-        $markdown = file_get_contents($this->classDir . '/bindings.md');
-        assert(is_string($markdown));
+        $markdown = $this->readMarkdown();

applied at each of the flagged call sites.

Also applies to: 91-92, 105-106, 125-126, 136-137, 179-182, 211-213, 228-231, 262-264, 276-278

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/di/BindingsMarkdownTest.php` around lines 60 - 61, Extract a private
helper in the test class that reads bindings.md from classDir and asserts the
result is a string, then replace the duplicated file_get_contents/assert pairs
in the flagged test methods with calls to that helper. Keep each test’s existing
assertions and behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/di/BindingsMarkdownTest.php`:
- Around line 60-61: Extract a private helper in the test class that reads
bindings.md from classDir and asserts the result is a string, then replace the
duplicated file_get_contents/assert pairs in the flagged test methods with calls
to that helper. Keep each test’s existing assertions and behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c72134d-846c-48f1-a04f-3e5ea6a3aafd

📥 Commits

Reviewing files that changed from the base of the PR and between 13d4ccb and ab660d7.

📒 Files selected for processing (4)
  • src/di/BindingsMarkdown.php
  • src/di/Injector.php
  • src/di/SpyCompiler.php
  • tests/di/BindingsMarkdownTest.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/di/Injector.php
  • src/di/SpyCompiler.php

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

@koriym Resolved the open conversations and approved PR #336. 🐇

✅ Action performed

Comments resolved. Approval is disabled; enable reviews.request_changes_workflow to allow explicit top-level @coderabbitai resolve or @coderabbitai approve commands.

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