Skip to content

Feature Matrix

The feature matrix is a generated report that records, for every supported flag and behavior, whether the native tool and the Greph wrapper produce equivalent output. It is the source of truth for "does Greph support this?" questions.

The matrix is regenerated from real command probes against a deterministic fixture workspace. The raw evidence lives in FEATURE_MATRIX.json and the rendered table lives in FEATURE_MATRIX.md.

Status legend

Status Meaning
Pass The probe ran and matched the expected behavior
Fail The probe ran but did not satisfy the expected behavior
Unavailable The provider command was not present in this environment

Sections

The matrix is organized into six sections:

  1. rg Compatibility Surface: every probe is run against both the upstream rg binary and bin/rg. Both must Pass for the row to be marked as supported.
  2. sg Compatibility Surface: every probe is run against both the upstream sg binary and bin/sg. Both must Pass for the row to be marked as supported.
  3. sg Wrapper-only Surface: probes that only target bin/sg (extras the wrapper exposes that ast-grep itself does not have).
  4. Native greph Surface: probes that exercise bin/greph directly. There is no upstream tool to compare against; the probes assert the expected behavior on the fixture workspace.
  5. Indexed greph Surface: probes that exercise bin/greph-index (build, refresh and warmed text search).
  6. Indexed AST Library Surface: probes that call the PHP API (Greph::buildAstIndex(), Greph::searchAstIndexed(), Greph::buildAstCache(), Greph::searchAstCached()) and check build, search and refresh.

Regenerating the matrix

Shell
php bin/feature-matrix

Run it from a clone of the repository with rg and sg on the PATH; bin/feature-matrix is not part of the Composer package. It builds the fixture workspace, runs each compatibility probe against the upstream binary (when it is installed) and against the Greph wrapper, records the structured result, and writes both FEATURE_MATRIX.json and FEATURE_MATRIX.md. Pass --stdout to print the Markdown without writing either file.

The committed files are regenerated by hand; CI does not regenerate them. The PHPUnit suite that CI runs includes a test that generates the matrix with the upstream tools marked unavailable and checks the shape of the report, so a single probe that starts failing does not fail CI. Regenerate the matrix and review the diff before a release.

What lives in the matrix vs the docs

The CLI reference and the Compatibility / rg and Compatibility / sg pages describe the intended surface. The feature matrix records the verified surface, with the exact probe arguments next to each row.

If something is documented but missing from the matrix, the docs are out of date. If something is in the matrix but not documented, the docs need a backfill. Both should match.

Example rows

rg compatibility (excerpt)

Feature rg bin/rg Notes
Fixed-string search Pass Pass Probe: -F needle single.txt
Case-insensitive fixed-string search Pass Pass Probe: -F -i needle single.txt
Whole-word search Pass Pass Probe: -F -w needle words.txt
Glob filter Pass Pass Probe: --glob *.php function .
Hidden files Pass Pass Probe: --hidden -F secret .
Structured JSON output Pass Pass Probe: --json -F needle single.txt using ripgrep JSON-event semantics

sg compatibility (excerpt)

Feature sg bin/sg Notes
Pattern search with run --pattern Pass Pass Probe: run --pattern array($$$ITEMS) src/App.php
Rewrite via run --rewrite Pass Pass Probe: run --pattern array($$$ITEMS) --rewrite [$$$ITEMS] src/App.php
Structured JSON stream output Pass Pass Probe: run --json=stream --pattern dispatch($EVENT) src/App.php
Update-all rewrite Pass Pass Probe: run --pattern array($$$ITEMS) --rewrite [$$$ITEMS] --update-all src/App.php

For the full table, see FEATURE_MATRIX.md.

Why probe-driven

A hand-maintained compatibility table drifts. The whole point of the wrappers is "drop them in where you used to call rg or sg and they keep working", and the only way to keep that promise is to actually run the upstream tool and the wrapper side by side and diff the results. The probe runner does exactly that each time the matrix is regenerated.