Skip to content

fix(engine): re-trim slugifyAttemptId after truncation to avoid a git-invalid trailing separator - #7563

Closed
shin-core wants to merge 1 commit into
JSONbored:mainfrom
shin-core:fix/slugify-attempt-id-trailing-dot-7528
Closed

fix(engine): re-trim slugifyAttemptId after truncation to avoid a git-invalid trailing separator#7563
shin-core wants to merge 1 commit into
JSONbored:mainfrom
shin-core:fix/slugify-attempt-id-trailing-dot-7528

Conversation

@shin-core

Copy link
Copy Markdown
Contributor

What

slugifyAttemptId (packages/loopover-engine/src/miner/worktree-plan.ts) trimmed leading/trailing -/. before slicing to MAX_SLUG_LENGTH, not after. . is in the allowed character class, so it survives the sanitizing replace. When the pre-truncation slug is longer than 64 chars and its 64th character is a literal ., the truncated slug ends in . — a case the trim step never saw because it ran on the untruncated string.

That slug becomes the worktree branch name (loopover/attempt/<slug>), and addWorktree runs git worktree add -b <branchName> …. Git's ref-name rules reject a ref ending in . (git help check-ref-format), so this fails with fatal: invalid reference. It reproduces from the default attempt id attempt-cli.ts builds (${repoFullName.replace("/","_")}-${issueNumber}-${nowMs}) when a long owner/repo pair (repo names may contain dots, e.g. socket.io) puts a . at the 64-char boundary — no unusual input required.

Fix

Re-trim the trailing separators after truncation:

return slug.slice(0, MAX_SLUG_LENGTH).replace(/[-.]+$/g, "");

Only the trailing edge needs re-trimming: the pre-truncation trim already removed any leading separators, and slice(0, n) never introduces a new leading one, so the truncated slug always keeps its non-separator first char and can never empty (so no extra empty-check branch is added).

Tests

Two REGRESSION (#7528) cases in test/unit/worktree-plan.test.ts, each constructing an attempt id whose slug's 64th char is a separator (. and -) before truncation, asserting the final branch name is the 63-char prefix and ends in neither . nor -. Both are proven to fail against the pre-fix code (received …a./…a-).

Validation

  • npx vitest run test/unit/worktree-plan.test.ts — 10/10 pass.
  • @loopover/engine build + npm run typecheck — clean (exit 0).
  • git diff --check clean.

Closes #7528

…-invalid trailing separator

slugifyAttemptId trimmed leading/trailing `-`/`.` before slicing to
MAX_SLUG_LENGTH, so a slug longer than 64 chars whose 64th character is a `.`
(a valid interior char that survives the character-class replace) was truncated
to a value ending in `.`. That slug feeds the worktree branch name, and git
rejects a ref ending in `.` (`git help check-ref-format`) with
`fatal: invalid reference` -- reproducible today from the default attempt id
built in attempt-cli.ts for a long owner/repo pair with a dot at the boundary.

Re-trim the trailing separators after truncation. Only the trailing edge needs
it: the pre-truncation trim already removed any leading separators and slice
never introduces a new leading one, so the truncated slug keeps its
non-separator first char and never empties.

Closes JSONbored#7528
@shin-core
shin-core requested a review from JSONbored as a code owner July 20, 2026 22:17
@superagent-security superagent-security Bot added the contributor:flagged Contributor flagged for review by trust analysis. label Jul 20, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

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

@superagent-security

Copy link
Copy Markdown
Contributor

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

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.47%. Comparing base (fadb5cc) to head (8759610).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7563      +/-   ##
==========================================
- Coverage   88.48%   88.47%   -0.01%     
==========================================
  Files         720      720              
  Lines       75748    75748              
  Branches    22558    22558              
==========================================
- Hits        67023    67019       -4     
  Misses       7679     7679              
- Partials     1046     1050       +4     
Flag Coverage Δ
shard-1 36.50% <100.00%> (ø)
shard-2 36.47% <0.00%> (-0.03%) ⬇️
shard-3 32.74% <100.00%> (+<0.01%) ⬆️
shard-4 34.06% <0.00%> (ø)
shard-5 32.02% <100.00%> (ø)
shard-6 33.41% <0.00%> (ø)

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

Files with missing lines Coverage Δ
...ackages/loopover-engine/src/miner/worktree-plan.ts 100.00% <100.00%> (ø)

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 20, 2026
@loopover-orb

loopover-orb Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - reject/close recommended

Review updated: 2026-07-20 22:25:54 UTC

2 files · 1 AI reviewer · 1 blocker · CI green · unstable

🛑 Suggested Action - Reject/Close

Review summary
This fixes a real bug: the pre-truncation trim of leading/trailing `-`/`.` in `slugifyAttemptId` never sees separators that only become trailing after `slice(0, MAX_SLUG_LENGTH)`, so a `.` landing exactly at the 64-char boundary produces a git-invalid ref ending in `.`. The one-line fix (re-trim trailing separators after truncation) is correct and minimal, and the two new regression tests construct exactly the boundary condition described (63 safe chars + separator + more chars), verifying the fix is reachable via the documented default attempt-id path. The comment's claim that the result can never empty also holds, since slicing a string whose first char is non-separator can't produce an all-separator prefix.

Nits — 4 non-blocking
  • The inline comment block in worktree-plan.ts:44-48 is fairly long for a one-line fix; could be trimmed to just the git-ref-rejection rationale.
  • Consider also asserting in a test that the resulting slug's first character is never a separator, reinforcing the 'never empties' invariant the comment relies on.
  • Pull request duplicates other open work — Check for an existing pull request or issue covering this change and coordinate or consolidate before continuing.
  • Readiness score is below the configured threshold — Use the readiness panel as advisory maintainer context; the score does not block this PR.

Why this is blocked

  • Linked issue overlaps another open PR — Review the related PRs before spending reviewer time on duplicate work.
📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. Linked issue overlaps another open PR — Review the related PRs before spending reviewer time on duplicate work.
Flagged checks (non-blocking)
  • Contributor trust — Contributor flagged for review

Decision drivers

  • ❌ Code review — 1 blocker (1 reviewer)
  • ❌ Gate result — Blocking (Repo-configured hard blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7528
Related work ⚠️ Same linked issue: #7551 Another open PR references the same linked issue.
Change scope ❌ 8/20 High 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: 75 registered-repo PR(s), 47 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor shin-core; Gittensor profile; 75 PR(s), 0 issue(s).
Improvement ✅ Minor risk: low · value: minor · LLM: moderate
Linked issue satisfaction

Addressed
The diff reorders the fix by applying a trailing `.`/`-` trim after truncation (`slug.slice(0, MAX_SLUG_LENGTH).replace(/[-.]+$/g, "")`), which directly resolves the described trailing-dot-at-boundary bug, and adds regression tests for both `.` and `-` landing at the 64-char boundary as requested.

Review context
Contributor next steps
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 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

LoopOver is closing this pull request on the maintainer's behalf (Linked issue overlaps another open PR; duplicate of open PR #7551). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed.

@loopover-orb loopover-orb Bot closed this Jul 20, 2026
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:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(engine): slugifyAttemptId's trim-then-truncate order can produce a git-invalid worktree branch name ending in "."

1 participant