Skip to content

v0.9.0

Choose a tag to compare

@guimatheus92 guimatheus92 released this 27 Aug 03:42
· 14 commits to main since this release
1ae0309

Added

  • Local branch dogfood without opening a PR: npm run dogfood -- --base origin/main --include-untracked converts the complete branch/working-tree diff (including opted-in untracked text files) into a temporary GatherOutput under ~/.pr-review/runs/ and drives the real bundled CLI with --from-gather --dry-run. URL-based companions are disabled for this synthetic PR; exercise them on a real-PR dry-run. The generated dist/cli.cjs remains recorded but is excluded from LLM context; npm run build is its validation surface.
  • Synthetic eval fixtures also disable URL-based companions; their pass/stack/finding assertions exercise the bundled pipeline, while companion dispatch is validated on real-PR dry-runs.
  • --force-skill <file> is the explicit escape hatch for bypassing a skill's applyTo/paths scope. --skill <file> now keeps the declared scope.
  • Installed plugins are discovered generically from their manifests in both supported hosts — Copilot CLI and Claude Code (whose extra <version> directory level is resolved through the authoritative installPath in installed_plugins.json, so a stale side-by-side version is never picked). Relevant review-oriented skills may become capped plugin passes from repository/path/topic evidence, while declared user, repository, and plugin MCP servers are recorded in capabilities.json. Plugin passes write audited available/attempted/used MCP evidence; no technology-to-reviewer lookup table is involved.

Changed

  • Pack routing now distinguishes evidence: canonical Linguist language names, manifest ecosystems, full dependency names, and dependency tokens stay separate. Dependency-backed skills outrank generic language matches; product skills such as Azure Functions, MCP, or Copilot SDK no longer qualify from *.cs, *.ts, *.csproj, or package.json alone. Generic manifest globs are weak evidence, and SKILL.md is container format rather than an identity token.
  • Product-specific identity tokens must co-occur in one dependency group; unrelated packages can no longer combine azure and functions into false Azure Functions evidence. Original package casing is retained while tokenizing, so NuGet compounds such as DurableTask remain detectable.
  • Project rules are also discovered from .github/instructions/ (applyTo) and .claude/rules/ (paths). Semantically identical mirrors dedupe silently; divergent same-name rules still warn.
  • A repository rule file added or modified by the PR is excluded from both authoritative context and the on-demand index for that review, then named as degraded coverage. Branch-authored instructions cannot tell reviewers how to judge their own change.
  • Rule trust filtering runs before same-name dedupe and checks lexical plus real paths. A changed later mirror cannot evict its unchanged counterpart; in-repo --skill files remain scoped/untrusted when changed, --force-skill is the explicit override, and linked rules resolving outside the checkout fail closed.
  • Linguist aliases no longer become independent stack technologies. Exact filenames override ambiguous extensions, and manifest evidence resolves shared extensions (for example .cs to C# rather than Smalltalk when a C# project owns the change).

Fixed

  • Windows 8.3 short paths no longer make a checkout look like a different directory. Every containment check compared a path from one source (git rev-parse, a manifest) against one from another (os.tmpdir(), a directory walk), and realpathSync folds symlinks but not 8.3 components — so C:\Users\RUNNER~1\... and C:\Users\runneradmin\... read as different directories and a legitimate --skill, manifest or plugin file was silently refused. All five comparison sites now go through realpathCanonical (realpathSync.native first). Invisible to anyone whose username is 8 characters or fewer, which is why it only surfaced on CI.
  • A repository MCP server is refused when it would launch code from the reviewed checkout. Refusing only a changed .mcp.json left a hole: the config can be untouched while the PR rewrites the script it points at (node ./scripts/mcp-server.js), and reviewing a PR means the checkout already sits at that branch's head. In-repo launch paths (explicitly relative, absolute-inside-repo, or an existing repo file) are now refused per server, with the reason surfaced; external tooling (npx -y @scope/pkg, docker run …, a bare PATH command) is unaffected.
  • Installed-plugin discovery is no longer Copilot-only. Under Claude Code the plugin cache adds a <version> level and can hold several versions at once, so nothing was discovered there at all — pr-review supports both hosts and must behave the same in each.
  • The extra_skills_dirs example no longer points at .claude/skills. A forced directory bypasses the rule-trust check, so recommending the reviewed repo's own rule directory re-admitted exactly the branch-authored input that check exists to reject.
  • The directory trust gate is case-insensitive. normalizedRelative() lowercases paths only on win32, so a case-sensitive skill.md test matched nothing on Linux/macOS and silently disabled the gate there. Caught by dogfooding this branch against itself; skillDirPrefix is now unit-tested in both casings so the regression is detectable on any platform.
  • A SKILL.md is now untrusted when the PR changed any file in its directory, not only SKILL.md itself. Only SKILL.md loads as a skill, but every pass is handed a Source: line saying relative references/ resolve from that directory — so a PR could ship branch-authored instructions beside an unchanged SKILL.md and have them read as authoritative project context. Found on a live dry-run of Preco-Pratico/PrecoPratico-Docs#269, which changes .claude/skills/backend-guide/create-database.md. Flat <dir>/<name>.md rules share a directory with unrelated rules, so for those the file stays the unit.
  • Legacy Azure DevOps remotes such as https://contoso.visualstudio.com/DefaultCollection/Platform/_git/infra-core now match canonical dev.azure.com PR identity, so local manifests and project rules are not discarded.
  • Checkout identity includes the ADO project and recognizes encoded HTTPS paths plus ssh.dev.azure.com:v3/<org>/<project>/<repo> remotes, preventing same-name repositories in another project from supplying manifests or rules.
  • Deep monorepo projects contribute their owning manifests without a full recursive scan: changed manifests and manifests beside/above changed files are read in addition to the shallow root scan. A deeply nested MSTest project now dispatches csharp-mstest instead of unrelated C# product guides.
  • Companion reporting now separates every installed plugin from recognized companion plugins, planned dispatches (six toolkit agents plus one code-review command), and completed output rows. Each run persists companions.json; missing companions are recorded as degraded coverage in the summary, while detection failures remain unknown rather than being mislabeled as not installed.
  • Planned companion reviewer IDs are reconciled against delivered outputs. Missing or duplicate outputs, failed/unverified posts, and failed review prerequisites now return exit 2 with error.txt; parseable findings still receive a diagnostic summary, and detached status reports the run as failed rather than done.
  • Every pass and companion persists its own raw-<reviewer>.json before returning. If the orchestrator ends after its tasks finish but before consolidation, the CLI recovers only when every planned sidecar is valid; partial delivery still fails closed. Valid empty arrays override synthetic “unparseable output” findings.
  • Copilot dispatches the installed pr-review-toolkit agents by their registered short names, so all six companion agents run once instead of first failing under Claude-style qualified names and being relaunched generically.
  • Installed-plugin skill paths are constrained lexically and by real path to the plugin root, and repository MCP configuration is admitted only when checkout identity matches the PR repository. Changed repository MCP files remain untrusted.
  • Trusted repository MCP definitions from root .mcp.json and .vscode/mcp.json are normalized into the isolated run's .mcp.json (root definitions win duplicate names), so every advertised repo capability is actually available to reviewer processes.
  • Dogfood derives GitHub fork identity from origin, rejects unsupported providers and internal/flow-control flags, refuses stale bundles, and includes untracked files only with --include-untracked. Secret-bearing names and high-confidence credential content are refused before artifacts are written; opted-in paths are real-path validated, and binary/empty files are recorded without pretending they contain reviewable lines.
  • Dogfood checks both previousPath and path for tracked renames before excluding generated bundle content, so renaming .env, credentials, keys, or token files to a benign name cannot place the old sensitive path in local review artifacts.
  • ADO gather caches are scoped by the authoritative project as well as organization/repository/PR, stale payload identities are refreshed on cache hits, and unresolved project identities bypass cache reuse.
  • Project-omitted ADO refs are hydrated inside the shared PR resolver, so changed-file, full-diff, comment-read, and comment-post operations retain the authoritative project even when callers do not invoke metadata first; the hydrated cache alias avoids a second PR fetch.
  • Manifest discovery validates real-path containment, ascends past deleted directories to existing owning manifests, and surfaces unexpected discovery/read failures in stack notes. Package diffs only derive dependency evidence from dependency sections or semver-like entries in truncated dependency hunks.
  • The verifier renders as skipped (no HIGH/CRITICAL) when its conditional phase did not run, and no longer inflates the reviewer count. A successful run without --fail-on explicitly says how many findings were retained and why the exit code is 0.
  • The C# contract-test eval now uses a causal defective/control pair: the defective test derives route-filter expectations from production metadata and omits policy/scheme assertions, while the safe control pins published values. Eval expectations can require distinct findings and may be negative-only, preventing one generic finding or a vacuous fixture from passing the quality gate.