Skip to content

feat(miner): wire real git worktree preparation into the attempt pipeline (#5132) - #5237

Merged
JSONbored merged 2 commits into
mainfrom
feat/miner-worktree-preparation
Jul 12, 2026
Merged

feat(miner): wire real git worktree preparation into the attempt pipeline (#5132)#5237
JSONbored merged 2 commits into
mainfrom
feat/miner-worktree-preparation

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Advances Wire CLI dispatch for the real attempt pipeline (attempt command) #5132 (maintainer-only, epic Epic: Miner Wave 3.5 — Wire the autonomous loop end-to-end #5130, Wave 3.5). Found while building the coding-task-spec builder: packages/gittensory-miner/lib/worktree-allocator.js — given "its first real caller" in feat(miner): wire the attempt CLI subcommand's real dependencies (#5132) #5152 — only does SQLite slot bookkeeping (a bounded pool of fixed slot-N directories) plus mkdirSync. It runs zero git commands. workingDirectory handed to runIterateLoop would have been an empty, non-git directory: the coding agent driver would have nothing real to check out or edit, even with everything else in Wire CLI dispatch for the real attempt pipeline (attempt command) #5132's chain wired correctly.
  • Adds repo-clone.js: a per-repo base-clone cache. First use clones the target repo; every subsequent use does git fetch origin + git reset --hard origin/<baseBranch>, so an attempt always branches off fresh content, not a stale prior checkout (verified by a test: an uncommitted local edit in the cached clone is discarded on the next ensureRepoCloned call, and a new upstream commit shows up).
  • Adds attempt-worktree.js, which composes repo-clone.js with @jsonbored/gittensory-engine's addWorktree/removeWorktree/shouldRetainWorktree primitives (packages/gittensory-engine/src/miner/worktree-allocator.ts, feat(miner-hands): git-worktree-per-attempt isolation primitive #4269) — these already existed, are already tested, but were never called from packages/gittensory-miner anywhere (confirmed via git grep -n "addWorktree\|planWorktree" -- packages/gittensory-miner → zero hits before this PR). prepareAttemptWorktree is this package's first real caller of them; cleanupAttemptWorktree wires the engine's own retention policy (retain a failed attempt's worktree for post-mortem, remove a succeeded one's).
  • Relies entirely on whatever git/gh credentials are already configured on the machine — same assumption execute-local-write.js's gh pr create already makes; never embeds a token in a clone URL.

A real bug this caught

prepareAttemptWorktree initially forgot to forward its own remoteUrl/runGit test-injection options through to ensureRepoCloned — every call silently fell through to the real https://github.com/{owner}/{repo}.git URL regardless of what the caller passed. The "REGRESSION" integration test (a real local git repo as the clone source, a real git worktree add, asserting real repo content lands on a real branch) failed with a real remote: Repository not found error and caught it immediately — before any review, and before this could have silently broken every attempt in production.

Validation

  • npm run typecheck
  • npm run test:coverage locally (743 test files, 0 failures, 14,690 tests). 16 new tests across the two files — including real integration tests against a genuine local git repo (clone, fetch+reset with an upstream commit added between calls, a non-default base branch, git worktree add producing real checked-out content on a real branch, cleanup retaining/removing per the engine's policy) plus DI-based unit tests for each failure path (clone/fetch/checkout/reset failures, missing stderr fallback messages).
  • npx tsx scripts/check-engine-parity.ts
  • npm run build:miner + npm run test:miner-pack (added both new files to the hand-maintained check list)
  • npm audit --audit-level=moderate
  • npm run test:workers / npm run build:mcp / npm run test:mcp-pack / npm run ui:* — skipped, no src/**, apps/**, or MCP-surface files touched.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • N/A — no auth/cookie/CORS/GitHub App/Cloudflare/session changes; git operations use only locally-configured credentials, never a token embedded in code.
  • N/A — no UI changes.

Notes

  • This module is not yet wired into attempt-cli.js's runAttempt — that's the final assembly step (separate follow-up, along with the coding-task-content-derivation piece this same investigation surfaced).

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui 5b523df Commit Preview URL

Branch Preview URL
Jul 12 2026, 10:52 AM

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

const configHome = typeof env.XDG_CONFIG_HOME === "string" && env.XDG_CONFIG_HOME.trim() ? env.XDG_CONFIG_HOME.trim() : join(homedir(), ".config");
return join(configHome, "gittensory-miner", DEFAULT_CLONE_DIR_NAME);
}

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.

P2: repoFullName path traversal allows cloning repositories outside intended clone directory

normalizeRepoFullName does not reject .. segments in owner or repo, allowing repoPath to escape cloneBaseDir.

Validate owner and repo with a regex or explicit .. rejection to prevent path traversal.

AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.

<file name="packages/gittensory-miner/lib/repo-clone.js">
<violation number="1" location="packages/gittensory-miner/lib/repo-clone.js:30">
<priority>P2</priority>
<title>repoFullName path traversal allows cloning repositories outside intended clone directory</title>
<evidence>normalizeRepoFullName validates only that repoFullName contains exactly one slash, but does not reject path-traversal segments like ".." in owner or repo. For example, repoFullName="../foo" passes validation, and ensureRepoCloned then builds repoPath = join(cloneBaseDir, "..", "foo"), which escapes the intended clone directory. An attacker who controls repoFullName (and optionally remoteUrl) can clone arbitrary repository content to any filesystem location writable by the process.</evidence>
<recommendation>Add validation in normalizeRepoFullName to reject owner or repo segments that equal "." or "..", or use a stricter regex like /^[a-zA-Z0-9._-]+$/ for each segment. Also consider resolving the final path and verifying it is still under cloneBaseDir.</recommendation>
</violation>
</file>

…line (#5132)

packages/gittensory-miner/lib/worktree-allocator.js (given "its first
real caller" in #5152) only does SQLite slot bookkeeping + mkdir --
it runs zero git commands. workingDirectory handed to runIterateLoop
would have been an empty, non-git directory: the coding agent driver
would have nothing real to edit.

Adds repo-clone.js (a per-repo base-clone cache: git clone once,
then fetch + hard-reset to the base branch on every subsequent
attempt so content stays fresh) and attempt-worktree.js, which
composes it with @jsonbored/gittensory-engine's addWorktree/
removeWorktree/shouldRetainWorktree primitives -- these already
existed, tested, but were never called from this package (confirmed
via git grep: zero production call sites anywhere in
packages/gittensory-miner before this).

A test caught a real wiring bug before this ever shipped:
prepareAttemptWorktree initially forgot to forward its own
remoteUrl/runGit test-injection options through to ensureRepoCloned,
so every call silently hit the real GitHub URL regardless of what
the caller passed -- caught by the REGRESSION integration test
(a real local repo, real git worktree add, asserting real repo
content lands on a real branch), not by review.
normalizeRepoFullName only checked for exactly one "/" separator, so a
value like "../foo" passed validation and resolveRepoCloneDir/ensureRepoCloned
would join it straight into the clone base dir, escaping the intended
clone directory. Reject "."/".." segments and restrict owner/repo to
GitHub's actual allowed character set.
@JSONbored
JSONbored force-pushed the feat/miner-worktree-preparation branch from 221272f to 5b523df Compare July 12, 2026 10:50
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent did not 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 12, 2026
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.34%. Comparing base (a5123cc) to head (5b523df).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5237   +/-   ##
=======================================
  Coverage   94.34%   94.34%           
=======================================
  Files         473      473           
  Lines       39982    39982           
  Branches    14576    14576           
=======================================
  Hits        37722    37722           
  Misses       1585     1585           
  Partials      675      675           
Flag Coverage Δ
shard-1 46.29% <ø> (-0.15%) ⬇️
shard-2 34.60% <ø> (+0.03%) ⬆️
shard-3 30.99% <ø> (-1.01%) ⬇️
shard-4 32.93% <ø> (+0.73%) ⬆️
shard-5 33.58% <ø> (-0.16%) ⬇️
shard-6 45.18% <ø> (+0.30%) ⬆️

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

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-12 10:56:59 UTC

7 files · 2 AI reviewers · 2 blockers · readiness 100/100 · CI green · unstable

⏸️ Suggested Action - Manual Review

  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
  • AI reviewers agree on a likely critical defect: packages/gittensory-miner/lib/repo-clone.js:85 only runs plain `git clone` on first use and returns immediately, so `ensureRepoCloned(..., { baseBranch: "develop" })` can leave the cache on the remote default branch with no local `develop`
  • change the clone path to checkout/reset the requested base branch too, for example by running the same `checkout ${baseBranch}` + `reset --hard origin/${baseBranch}` sequence before returning or by cloning with `--branch ${baseBranch}` and failing closed if it does not exist. — Resolve the flagged defect, or override if the AI reviewers are mistaken, then re-run the gate.

Review summary
This wires the previously-inert worktree-allocator engine primitives into gittensory-miner via two new modules: repo-clone.js (per-repo base-clone cache with fetch+hard-reset) and attempt-worktree.js (composes it with the engine's addWorktree/removeWorktree). The path-traversal guard on owner/repo segments is real and tested, error propagation through each git step is handled distinctly, and the test suite exercises real git repos rather than fully mocked ones, including a genuine regression test for stale-checkout discard. The most notable gap is that ensureRepoCloned's existing-clone path never handles a local branch that has diverged in a way `checkout <baseBranch>` can't resolve (e.g., if a prior attempt's worktree branch collides with baseBranch name) — not tested but plausible given worktree branches share the same repo clone.

Blockers

  • packages/gittensory-miner/lib/repo-clone.js:85 only runs plain `git clone` on first use and returns immediately, so `ensureRepoCloned(..., { baseBranch: "develop" })` can leave the cache on the remote default branch with no local `develop`; change the clone path to checkout/reset the requested base branch too, for example by running the same `checkout ${baseBranch}` + `reset --hard origin/${baseBranch}` sequence before returning or by cloning with `--branch ${baseBranch}` and failing closed if it does not exist.
Nits — 5 non-blocking
  • packages/gittensory-miner/lib/repo-clone.js:81 and :85 use unexplained magic numbers (120_000 timeout, 0o700 mode) that could be named constants for clarity.
  • packages/gittensory-miner/lib/repo-clone.js's ensureRepoCloned has real branching complexity (~14) from the sequential clone/fetch/checkout/reset error-handling chain; consider extracting the fetch+checkout+reset sequence into a helper for readability.
  • No test exercises the case where a prior attempt's worktree branch (`gittensory/attempt/<id>`) still exists in the shared base clone when a new attempt runs `git checkout <baseBranch>` — worth confirming this can't collide since all attempts share one cached clone.
  • attempt-worktree.js's createRealWorktreeExec duplicates the resolve-never-reject child_process pattern from execute-local-write.js's executeLocalWrite almost verbatim; consider a shared helper if a third caller appears.
  • Consider extracting a shared 'spawn with timeout, resolve-never-reject' helper used by both execute-local-write.js and attempt-worktree.js's createRealWorktreeExec to avoid drift between the two near-identical implementations.

Concerns raised — review before merging

  • packages/gittensory-miner/lib/repo-clone.js:85 only runs plain `git clone` on first use and returns immediately, so `ensureRepoCloned(..., { baseBranch: "develop" })` can leave the cache on the remote default branch with no local `develop`; change the clone path to checkout/reset the requested base branch too, for example by running the same `checkout ${baseBranch}` + `reset --hard origin/${baseBranch}` sequence before returning or by cloning with `--branch ${baseBranch}` and failing closed if it does not exist.
  • No linked issue detected — If this PR is intended to solve an issue, link it explicitly in the PR body.
Signal Result Evidence
Code review ❌ 2 blockers 2 reviewers, synthesized
Linked issue ✅ No-issue rationale PR body explains why no issue is linked.
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 (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 44 registered-repo PR(s), 36 merged, 470 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 44 PR(s), 470 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence. LLM value judgment: moderate — The change directly addresses the empty-working-directory gap by adding a real clone cache and worktree composition, which is a concrete improvement even though one branch-selection path needs correction.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 44 PR(s), 470 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
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.
[BETA] Chat with Gittensory

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

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

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 12, 2026
@JSONbored
JSONbored merged commit 69e8d81 into main Jul 12, 2026
20 checks passed
@JSONbored
JSONbored deleted the feat/miner-worktree-preparation branch July 12, 2026 10:57
JSONbored added a commit that referenced this pull request Jul 12, 2026
…5252)

Advances #5132

worktree-allocator.js only reserves a concurrency SLOT (its own
`slot-N` placeholder directories never receive real git content) --
attempt-cli.js never called attempt-worktree.js's prepareAttemptWorktree
(#5237) to actually clone/fetch and create a real `git worktree`, so
the worktreePath reported by a blocked attempt pointed at an empty
directory, not real repo content. Wires it in: prepared right after the
coding-agent driver is confirmed configured, its real path replaces the
allocator's slot path in every reported result, a new
"blocked_worktree_preparation_failed" outcome (exit code 6) reports a
real clone/fetch failure, and the worktree is cleaned up in `finally`
since no real attempt runs in it yet.
JSONbored added a commit that referenced this pull request Jul 12, 2026
…rktree

Advances #5132

runMinerAttempt's killSwitchScope needs MinerGoalSpec.killSwitch.paused
from the target repo's real .gittensory-miner.yml. checkMinerKillSwitch
(governor-kill-switch.js, #2341) already resolves the scope once given
that value, but nothing in this package ever fetched/parsed the file
itself. Unlike self-review-context.js/rejection-signal.js/ams-policy.js
(which fetch live over raw.githubusercontent.com before any clone
exists), this reads the file from an ALREADY-CLONED repo on disk --
by the time a real attempt reaches this point, attempt-worktree.js's
prepareAttemptWorktree (#5237/#5252) has already cloned it, so no
extra network round trip is needed.

KNOWN GAP, same discipline as this epic's other standalone pieces:
not yet wired into attempt-cli.js's runAttempt, since that wiring
needs a real repoPath from #5252's worktree preparation (open,
CI-green, not yet merged as of this PR). Follow-up once it lands.
JSONbored added a commit that referenced this pull request Jul 12, 2026
…rktree (#5255)

Advances #5132

runMinerAttempt's killSwitchScope needs MinerGoalSpec.killSwitch.paused
from the target repo's real .gittensory-miner.yml. checkMinerKillSwitch
(governor-kill-switch.js, #2341) already resolves the scope once given
that value, but nothing in this package ever fetched/parsed the file
itself. Unlike self-review-context.js/rejection-signal.js/ams-policy.js
(which fetch live over raw.githubusercontent.com before any clone
exists), this reads the file from an ALREADY-CLONED repo on disk --
by the time a real attempt reaches this point, attempt-worktree.js's
prepareAttemptWorktree (#5237/#5252) has already cloned it, so no
extra network round trip is needed.

KNOWN GAP, same discipline as this epic's other standalone pieces:
not yet wired into attempt-cli.js's runAttempt, since that wiring
needs a real repoPath from #5252's worktree preparation (open,
CI-green, not yet merged as of this PR). Follow-up once it lands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. manual-review Gittensor contributor context

Development

Successfully merging this pull request may close these issues.

1 participant