Skip to content

Internalize Compete and React Doctor as two Beta features - #11

Closed
2233admin wants to merge 9 commits into
mainfrom
codex/compete-react-doctor
Closed

Internalize Compete and React Doctor as two Beta features#11
2233admin wants to merge 9 commits into
mainfrom
codex/compete-react-doctor

Conversation

@2233admin

Copy link
Copy Markdown
Owner

What changed

  • adds first-party competitive-intelligence and react-diagnostics Beta feature surfaces
  • emits normalized JSON and Markdown problem/recommendation reports with no score
  • keeps Compete and React Doctor behind pinned provider and A04 admission boundaries
  • registers both optional features without changing default normal or full execution
  • marks prerelease tags correctly in the release workflow

Why

The two upstream projects are implementation engines for two Code Intel product features, not the product-facing feature model itself. This change makes the Code Intel report contract and CLI the public surface while retaining upstream provenance, diagnostic IDs, coverage, freshness, and snapshot validation.

Validation

  • cargo test --workspace — 35 passed
  • test-evidence-providers.ps1 — 2 providers, 2 Beta features, 4 schemas, zero target-repo writes
  • test-integration-orchestration.ps1 — passed
  • test-atomic-capability-contract.ps1 — passed
  • sentrux gate . — no degradation
  • test-code-intel-pipeline.ps1 -RepoPath . — normal pipeline exit code 0

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44e2d6a2-3892-49ff-8b69-a8144b92829a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces on-demand advisory evidence providers (compete and react-doctor) and experimental Beta features (competitive-intelligence and react-diagnostics) to the Code Intel pipeline, along with strict 'fail-closed' trust contracts for Hospital scoring and scoped Repowise egress validation. Feedback on these changes highlights a performance bottleneck in Run-ScopedRepowiseDocs.py caused by spawning git subprocesses in a loop, a compatibility issue in Invoke-EvidenceProvider.ps1 with Windows PowerShell 5.1, and a potential strict-mode runtime crash if JSON parsing returns null.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread Run-ScopedRepowiseDocs.py
Comment on lines +91 to +154
def _validate_file_entries(
repo_path: Path,
entries: object,
policy: str,
label: str,
) -> dict[str, str]:
if not isinstance(entries, list):
raise RuntimeError(f"egress manifest {label} list is missing")

seen: dict[str, str] = {}
ordered_paths: list[str] = []
for entry in entries:
if not isinstance(entry, dict):
raise RuntimeError(f"egress manifest contains an invalid {label} entry")
relative = entry.get("path")
expected_hash = entry.get("sha256")
if not isinstance(relative, str) or not isinstance(expected_hash, str):
raise RuntimeError(f"egress manifest {label} entry is incomplete")
if len(expected_hash) != 64 or any(char not in "0123456789abcdefABCDEF" for char in expected_hash):
raise RuntimeError(f"egress manifest contains an invalid SHA-256: {relative}")
posix_path = PurePosixPath(relative)
if posix_path.is_absolute() or ".." in posix_path.parts or relative in {"", "."}:
raise RuntimeError(f"egress manifest contains unsafe path: {relative}")
try:
candidate = (repo_path / Path(*posix_path.parts)).resolve(strict=True)
except OSError as exc:
raise RuntimeError(f"egress manifest path is unavailable: {relative}") from exc
if not candidate.is_relative_to(repo_path) or not candidate.is_file():
raise RuntimeError(f"egress manifest path escapes the scoped repository: {relative}")
actual_hash = hashlib.sha256(candidate.read_bytes()).hexdigest()
if actual_hash != expected_hash.lower():
raise RuntimeError(f"egress manifest hash mismatch: {relative}")
if relative in seen:
raise RuntimeError(f"egress manifest contains duplicate path: {relative}")
seen[relative] = expected_hash.lower()
ordered_paths.append(relative)

if policy == "head-tracked-only":
try:
head_blob_oid = subprocess.check_output(
["git", "-C", str(repo_path), "rev-parse", f"HEAD:{relative}"],
text=True,
stderr=subprocess.STDOUT,
).strip()
working_blob_oid = subprocess.check_output(
[
"git",
"-C",
str(repo_path),
"hash-object",
f"--path={relative}",
str(candidate),
],
text=True,
stderr=subprocess.STDOUT,
).strip()
except (OSError, subprocess.CalledProcessError) as exc:
raise RuntimeError(f"egress manifest file is not tracked at HEAD: {relative}") from exc
if working_blob_oid != head_blob_oid:
raise RuntimeError(f"egress manifest file does not match HEAD blob: {relative}")

if ordered_paths != sorted(ordered_paths):
raise RuntimeError(f"egress manifest {label} list must be sorted by path")
return seen

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Spawning two git subprocesses (git rev-parse and git hash-object) inside a loop for every file in the egress manifest is a significant performance bottleneck, especially on Windows where process creation overhead is high.\n\nWe can optimize this to O(1) subprocess calls by:\n1. Running git ls-tree -r HEAD once before the loop to retrieve all tracked file OIDs at HEAD.\n2. Computing the Git blob OID directly in Python using hashlib.sha1 on the file content, which we already read in memory.\n\nThis completely eliminates 2 * N process spawns and file reads.

def _validate_file_entries(\n    repo_path: Path,\n    entries: object,\n    policy: str,\n    label: str,\n) -> dict[str, str]:\n    if not isinstance(entries, list):\n        raise RuntimeError(f"egress manifest {label} list is missing")\n\n    head_blobs: dict[str, str] = {}\n    if policy == "head-tracked-only":\n        try:\n            ls_tree_out = subprocess.check_output(\n                ["git", "-C", str(repo_path), "ls-tree", "-r", "HEAD"],\n                text=True,\n            )\n            for line in ls_tree_out.splitlines():\n                if line:\n                    parts = line.split(None, 2)\n                    if len(parts) >= 3:\n                        oid_path = parts[2].split('\t', 1)\n                        if len(oid_path) == 2:\n                            head_blobs[oid_path[1]] = oid_path[0]\n        except (OSError, subprocess.CalledProcessError) as exc:\n            raise RuntimeError(f"cannot read HEAD tree: {exc}") from exc\n\n    seen: dict[str, str] = {}\n    ordered_paths: list[str] = []\n    for entry in entries:\n        if not isinstance(entry, dict):\n            raise RuntimeError(f"egress manifest contains an invalid {label} entry")\n        relative = entry.get("path")\n        expected_hash = entry.get("sha256")\n        if not isinstance(relative, str) or not isinstance(expected_hash, str):\n            raise RuntimeError(f"egress manifest {label} entry is incomplete")\n        if len(expected_hash) != 64 or any(char not in "0123456789abcdefABCDEF" for char in expected_hash):\n            raise RuntimeError(f"egress manifest contains an invalid SHA-256: {relative}")\n        posix_path = PurePosixPath(relative)\n        if posix_path.is_absolute() or ".." in posix_path.parts or relative in {"", "."}:\n            raise RuntimeError(f"egress manifest contains unsafe path: {relative}")\n        try:\n            candidate = (repo_path / Path(*posix_path.parts)).resolve(strict=True)\n        except OSError as exc:\n            raise RuntimeError(f"egress manifest path is unavailable: {relative}") from exc\n        if not candidate.is_relative_to(repo_path) or not candidate.is_file():\n            raise RuntimeError(f"egress manifest path escapes the scoped repository: {relative}")\n        content = candidate.read_bytes()\n        actual_hash = hashlib.sha256(content).hexdigest()\n        if actual_hash != expected_hash.lower():\n            raise RuntimeError(f"egress manifest hash mismatch: {relative}")\n        if relative in seen:\n            raise RuntimeError(f"egress manifest contains duplicate path: {relative}")\n        seen[relative] = expected_hash.lower()\n        ordered_paths.append(relative)\n\n        if policy == "head-tracked-only":\n            head_blob_oid = head_blobs.get(relative)\n            if head_blob_oid is None:\n                raise RuntimeError(f"egress manifest file is not tracked at HEAD: {relative}")\n            hasher = hashlib.sha1()\n            hasher.update(f'blob {len(content)}\x00'.encode("utf-8"))\n            hasher.update(content)\n            working_blob_oid = hasher.hexdigest()\n            if working_blob_oid != head_blob_oid:\n                raise RuntimeError(f"egress manifest file does not match HEAD blob: {relative}")\n\n    if ordered_paths != sorted(ordered_paths):\n        raise RuntimeError(f"egress manifest {label} list must be sorted by path")\n    return seen

Comment on lines +27 to +31
function Get-Sha256Text([string]$Text) {
$bytes = [Text.Encoding]::UTF8.GetBytes($Text)
$hash = [Security.Cryptography.SHA256]::HashData($bytes)
return [Convert]::ToHexString($hash).ToLowerInvariant()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The static method [Security.Cryptography.SHA256]::HashData and the [Convert]::ToHexString method are only available in .NET Core / .NET 5+ (PowerShell 6+). If this script is executed under Windows PowerShell 5.1 (which uses .NET Framework 4.8), it will fail with a MethodNotFound exception.\n\nTo maintain compatibility with Windows PowerShell 5.1 (as indicated by the fallback to powershell in install-code-intel-pipeline.ps1), use the standard .NET Framework compatible APIs.

function Get-Sha256Text([string]$Text) {\n    $bytes = [Text.Encoding]::UTF8.GetBytes($Text)\n    $sha = [System.Security.Cryptography.SHA256]::Create()\n    $hash = $sha.ComputeHash($bytes)\n    $sha.Dispose()\n    return [System.BitConverter]::ToString($hash).Replace('-', '').ToLowerInvariant()\n}

Comment on lines +210 to +214
$report = Get-Content -LiteralPath $reportPath -Raw | ConvertFrom-Json
if ($report.schemaVersion -ne 3) { throw "unsupported JSON schema" }
$notApplicable = $report.ok -eq $false -and
$null -ne $report.error -and
$report.error.name -eq "ProjectNotFoundError"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In PowerShell strict mode (Set-StrictMode -Version Latest), referencing properties on a null value throws a runtime exception. If ConvertFrom-Json returns $null (e.g., if the report file is empty or invalid), accessing $report.schemaVersion or $report.ok will crash the script.\n\nAdding an explicit $null -eq $report check prevents this crash.

                $report = Get-Content -LiteralPath $reportPath -Raw | ConvertFrom-Json\n                if ($null -eq $report) { throw 'React Doctor report is empty or invalid' }\n                if ($report.schemaVersion -ne 3) { throw 'unsupported JSON schema' }\n                $notApplicable = $report.ok -eq $false -and\n                    $null -ne $report.error -and\n                    $report.error.name -eq 'ProjectNotFoundError'

@2233admin

Copy link
Copy Markdown
Owner Author

Closing after a merge-readiness review at main HEAD 384617f (2026-07-28).

Why close rather than merge:

  • Mechanically blocked: draft, GitHub reports CONFLICTING/DIRTY, and git merge-tree confirms 9 content conflicts plus one modify/delete against current main (ci.yml, CHANGELOG.md, Cargo.lock, Cargo.toml, main.rs, providers.rs, docs/artifact-data-contract.md, orchestration files).
  • Largely superseded: main already ships the atomic capability contract, capability-envelope schema, and centralized artifact-ref/SHA-256 machinery this PR re-implements (evidence.rs, hand-rolled sha256.rs); main also already ships Compete as intelligence.compete-project-score with an advisory-score contract that collides semantically with this PR's no-score contract for the same feature.
  • Supply-chain regression: React Doctor scan executes npx --yes react-doctor@0.7.8 at runtime inside the target repo; the recorded sha512 integrity constant is never enforced.
  • Probable logic bug in the diff: surgeryTargetResolved was inverted to require both SurgeryTarget and CurrentTopHotspot non-empty, and postOpOk now depends on it — runs with no surgery target could never satisfy post_op.
  • Direction conflict: adds ~360 lines of new PS1 orchestration to run-code-intel.ps1 — a file whose PS1-vs-Rust parity contract docs+test(ps1-exit): T1 contract freeze + PS1-vs-Rust parity harness #57 just froze — while the ps1-exit campaign ([ps1-exit] T1 契约冻结:巨石行为盘点 + golden parity harness #46[ps1-exit] T8 退役闸门 + ratchet 自动收紧 + mac/linux 全管线自扫 #53) is retiring that surface. Cargo metadata would also regress (0.2.2-beta.1 / Apache-2.0 vs main's 0.6.0 / MIT).

Salvageable idea: React Doctor as a Beta feature is still a reasonable concept — if wanted, re-spec it against main's current capability contract, with a pinned/verified toolchain instead of runtime npx, as a fresh issue + PR.

@2233admin 2233admin closed this Jul 28, 2026
@2233admin
2233admin deleted the codex/compete-react-doctor branch August 7, 2026 10:37
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