Skip to content

feat(miner): add a dry-run full-execution mode to the cross-repo evaluation harness - #7668

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
shin-core:feat/cross-repo-full-execution-7634
Jul 21, 2026
Merged

feat(miner): add a dry-run full-execution mode to the cross-repo evaluation harness#7668
JSONbored merged 1 commit into
JSONbored:mainfrom
shin-core:feat/cross-repo-full-execution-7634

Conversation

@shin-core

Copy link
Copy Markdown
Contributor

What

The cross-repo evaluation harness (#4788) is readiness-only: it proves the miner can form a plan for a benchmark repo (detectRepoStackresolveMinerGoalSpecbuildCodingTaskSpec), not that the plan produces working code. This adds the --full-execution mode to the existing CLI (scripts/cross-repo-evaluation.mjs) and its underlying lib module — running the real discover → plan → code → test loop, dry-run only.

How it works (and stays dry-run)

For each repo that passes the readiness gate:

  1. Scratch workspace — the local benchmark clone is copied into a discardable temp tree (defaultPrepareExecutionWorkspace); the clone itself is never mutated. The copy is removed in every outcome (finally), including when cleanup itself throws.
  2. Spec re-composition inside the copybuildCodingTaskSpec writes its acceptance-criteria document into its working directory, so the spec is re-built against the scratch tree (the copy's inherited ACCEPTANCE_CRITERIA.md from the readiness pass is cleared first — writeAcceptanceCriteriaFile opens O_EXCL).
  3. Agent run — the driver resolves from MINER_CODING_AGENT_PROVIDER via constructProductionCodingAgentDriver (lazily imported, so readiness-only consumers never pay for it), failing closed to a categorized agent_run_failed when unconfigured. No live PR submission, no forge APIs.
  4. Validation — the stack's inferred buildCommand (when present) and testCommand run inside the scratch copy via a shell-string runner mirroring createRealCliSubprocessSpawn (resolve-never-reject, hard timeout, both streams captured).

Report taxonomy: extended, not replaced

New execution categories flow through the existing summarizeCrossRepoEvaluation / formatCrossRepoEvaluationReport unchanged (both are data-driven over category strings):

Category Meaning
agent_run_failed No runnable driver configured, or the agent errored / did not succeed
noop_diff Agent reported success but changed no files
build_failed Diff generated but the inferred build command failed (didn't compile)
test_failed Build fine, but the repo's own test suite failed against the diff

A repo whose stack infers no test command fails with the existing execution_gap — an unvalidatable diff is not a pass.

Tests

15 new cases in test/unit/miner-cross-repo-evaluation.test.ts (59/59 pass), exercising every new branch on both sides with the package's existing fixture + injection conventions: readiness pass-through, workspace-prep failures (Error and non-Error), spec failures inside the workspace (throw / null / unready verdict), the default driver construction path (provider pinned empty via vi.stubEnv, both the injected-env and process.env sides), driver throw/malformed-result fallbacks, empty and missing changedFiles, build fail/timeout/skip, test fail/timeout, missing test command, option plumbing (maxTurns, commandTimeoutMs), the real defaultPrepareExecutionWorkspace (copy + discard) and the real command runner (exit codes, output capture, timeout kill, spawn error), manifest/filter handling, the CLI flag, and the new categories rendering through the existing report format. The dry-run posture is asserted directly: the agent's task is rooted in a real scratch copy, the acceptance file is written inside it, and the tree is gone afterward while the clone survives.

Validation

  • npx vitest run test/unit/miner-cross-repo-evaluation.test.ts — 59/59.
  • npm run typecheck — exit 0 (fresh @loopover/engine build).
  • npm run test:miner-pack, docs:drift-check, engine-parity:drift-check, command-reference:check — all pass; git diff --check clean.
  • CLI smoke: --help documents the flag; --full-execution against a fixture manifest reports a clean categorized agent_run_failed (unconfigured provider) through the existing report format, exit 0.

packages/loopover-miner/docs/cross-repo-evaluation.md documents the mode, its prerequisites, and the extended taxonomy.

Closes #7634

@shin-core
shin-core requested a review from JSONbored as a code owner July 21, 2026 06:47
@superagent-security superagent-security Bot added the contributor:flagged Contributor flagged for review by trust analysis. label Jul 21, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

🚨 Contributor flagged. Click here for more info: Superagent Dashboard

@superagent-security superagent-security Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Superagent found 1 security concern(s).

Comment thread packages/loopover-miner/lib/cross-repo-evaluation.ts Outdated
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label Jul 21, 2026
…uation harness

The cross-repo harness (JSONbored#4788) is readiness-only: it proves the miner can
FORM a plan for a benchmark repo, not that the plan produces working code.
Add a --full-execution mode to the existing CLI that runs the real
discover -> plan -> code -> test loop, still dry-run: each repo that passes
readiness is copied into a discardable scratch workspace, the coding agent
(resolved from MINER_CODING_AGENT_PROVIDER, failing closed to a categorized
agent_run_failed when unconfigured) works the harness's synthetic issue inside
that copy, and the repo's own inferred build and test commands validate the
generated diff there. No PR submission, no forge APIs, no writes to the
benchmark clone; the scratch tree is removed in every outcome.

Build/test commands are tokenized and exec'd directly (never via a shell), so
nothing in a benchmark repo's manifest can smuggle shell metacharacters into
an interpreted command line.

Execution failures extend the existing taxonomy -- agent_run_failed,
noop_diff (agent succeeded but changed nothing), build_failed (diff didn't
compile), test_failed (repo's own suite failed) -- and flow through the
existing summary/report format unchanged, since both are data-driven over
category strings. A repo whose stack infers no test command fails with the
existing execution_gap: an unvalidatable diff is not a pass.

The scratch copy inherits the ACCEPTANCE_CRITERIA.md the readiness pass wrote
into the clone, and writeAcceptanceCriteriaFile opens O_EXCL, so the
inherited file is cleared from the copy before the spec is re-composed there.

Closes JSONbored#7634
@shin-core
shin-core force-pushed the feat/cross-repo-full-execution-7634 branch from 7aef5f8 to 5ff2585 Compare July 21, 2026 06:55
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@superagent-security superagent-security Bot removed the pr:flagged PR flagged for review by security analysis. label Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.52%. Comparing base (3629080) to head (5ff2585).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #7668    +/-   ##
========================================
  Coverage   88.51%   88.52%            
========================================
  Files         724      724            
  Lines       76020    76120   +100     
  Branches    22629    22654    +25     
========================================
+ Hits        67291    67384    +93     
- Misses       7681     7688     +7     
  Partials     1048     1048            
Flag Coverage Δ
shard-1 35.84% <100.00%> (+0.12%) ⬆️
shard-2 32.90% <0.00%> (-0.08%) ⬇️
shard-3 28.55% <0.00%> (-0.10%) ⬇️
shard-4 40.45% <0.00%> (-0.18%) ⬇️
shard-5 33.93% <0.00%> (-0.07%) ⬇️
shard-6 35.88% <0.00%> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ckages/loopover-miner/lib/cross-repo-evaluation.ts 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 21, 2026
@loopover-orb

loopover-orb Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-21 07:38:58 UTC

7 files · 1 AI reviewer · no blockers · CI green · unstable

⏸️ Suggested Action - Manual Review

Review summary
This adds a `--full-execution` dry-run mode on top of the existing readiness-only cross-repo harness, running discover→plan→code→test inside a scratch copy of the benchmark clone that is copied via `cpSync` and always removed in a `finally`. The design is sound: no shell:true in the command runner (tokenized exec avoids injection), the acceptance-criteria file is cleared with `rmSync` before re-composing the spec in the scratch tree (correct given `writeAcceptanceCriteriaFile` opens O_EXCL), and the driver construction is lazily imported so readiness-only consumers don't pay for it. The `.js`/`.d.ts` compiled artifacts are consistently regenerated alongside the `.ts` source, and the taxonomy extension is genuinely data-driven as claimed.

Nits — 5 non-blocking
  • `runExecutionPhases` in cross-repo-evaluation.ts is a large, deeply-branching function (~79 added lines, approx complexity 25 per the external brief); consider extracting the build/test-command validation phase into a helper for readability.
  • packages/loopover-miner/lib/cross-repo-evaluation.ts and its compiled .js counterpart now exceed 400/800 lines respectively — worth a pass to see if the execution-mode logic could live in a sibling module instead of growing this one further.
  • `createDefaultCrossRepoExecutionRunCommand`'s whitespace-tokenized command split (cross-repo-evaluation.ts) can't express quoted args (e.g. a path with a space) even though it's documented as only handling simple `tool subcommand` forms — worth a one-line comment caveat or an assertion if `detectRepoStack` ever emits something more complex.
  • The scratch workspace copy via `cpSync(repoPath, path, { recursive: true })` will also copy `node_modules`/`.git` if present in the benchmark clone, which could be slow for large repos; consider filtering if that's a real concern for the target benchmark set.
  • Extract the build-command and test-command runner branches in `runExecutionPhases` into a shared `runValidationCommand` helper that returns a discriminated result, cutting the duplicated `buildExecutionFailure` call shape.
Flagged checks (non-blocking)
  • Contributor trust — Contributor flagged for review

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7634
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 83 registered-repo PR(s), 47 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor shin-core; Gittensor profile; 83 PR(s), 0 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Review context
  • Author: shin-core
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: TypeScript, JavaScript, Solidity, Dart, Python, CSS, PHP, Rust
  • Official Gittensor activity: 83 PR(s), 0 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LoopOver approves — the gate is satisfied and CI is green.

@JSONbored

Copy link
Copy Markdown
Owner

Moving forward, we should be able to eliminate .js and .d.ts files, as that was a main reason for refactoring to .ts.

@JSONbored
JSONbored merged commit b764880 into JSONbored:main Jul 21, 2026
14 of 15 checks passed
JSONbored added a commit that referenced this pull request Jul 21, 2026
…ge (#7690)

* ci(build): catch stale committed miner/mcp compiled output before merge

packages/loopover-miner and packages/loopover-mcp compile real TypeScript
in place and commit the emitted .js/.d.ts (both ship as installable CLIs,
so a runnable .js has to exist without a build step). Nothing enforced
that the committed output actually matched a fresh build: root-level
tests import the emitted .js by its literal specifier, and the job that
builds these packages runs as a separate GitHub Actions job from the one
that tests them, so a contributor who edited .ts without rebuilding got
tests silently running old behavior with zero CI signal -- the same
drift class the Selfhost/Miner env-reference checks were previously
added to close.

Adds scripts/check-build-drift.mjs (git-status-based, so a compiled file
that was never committed at all is caught too, not just a stale one),
wires it into ci.yml right after each package's real build step, and
into package.json's local test:ci for pre-push parity. Also fixes three
comments left stale by the #7290/#7291 TypeScript migrations completing,
and adds loopover-mcp's missing migration-complete guard test (mirroring
loopover-miner's existing one).

* fix(miner): canonicalize the cross-repo-evaluation scratch workspace path

defaultPrepareExecutionWorkspace built its scratch directory straight
from mkdtempSync, but coding-task-spec.ts's writeAcceptanceCriteriaFile
separately realpath's the working directory before writing into it (a
deliberate containment-check canonicalization, not something to
remove). On macOS, os.tmpdir() resolves under a symlink
(/var/folders/... -> /private/var/folders/...), so the two disagreed on
which string names the same directory: a plain
acceptanceCriteriaPath.startsWith(workingDirectory) check failed even
though the file genuinely was inside the working directory.

Resolving once at the source, right after mkdtempSync, keeps every
downstream path in the same canonical form with no other changes
needed, and is a no-op on Linux CI runners where /tmp isn't itself a
symlink.

Discovered while validating the build-drift check against #7668's own
newly-merged full-execution mode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor:flagged Contributor flagged for review by trust analysis. gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend the cross-repo evaluation harness from readiness-only to full execution on benchmark repos

2 participants