Skip to content

feat(agent): auto-match PRs to open GitHub Milestones in suggest-mode (#3183) - #3256

Merged
loopover-orb[bot] merged 3 commits into
mainfrom
feat/auto-milestone-match
Jul 4, 2026
Merged

feat(agent): auto-match PRs to open GitHub Milestones in suggest-mode (#3183)#3256
loopover-orb[bot] merged 3 commits into
mainfrom
feat/auto-milestone-match

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • Adds a ProjectTrackerAdapter interface (src/integrations/project-tracker-adapter.ts) with a GitHubMilestonesAdapter implementation, so feat(agent): auto-match PRs to open GitHub Projects v2 (suggest-mode) #3184 (Projects v2) and feat(agent): Linear adapter for project/milestone matching #3186 (Linear) slot in later without reshaping the matching/suggestion logic.
  • Matching reuses the existing tokenize/termOverlap primitives from the duplicate-PR collision detector (src/signals/engine.ts, now exported) at a stricter threshold (0.65 score + 3 shared terms vs. the duplicate-PR gate's 0.58/2) — misattaching tracked progress is worse than an advisory-only duplicate note.
  • New tri-state autoProjectMilestoneMatch setting (off/suggest/auto, default off), wired through the full config-as-code chain (migration, Drizzle schema, DB resolver, OpenAPI, .gittensory.yml parity) mirroring the reviewCheckMode template. "auto" behaves identically to "suggest" until feat(agent): promote project/milestone matching to auto-apply mode #3185 wires real milestone attachment — no attach code exists yet, so treating it as silently inert would be worse than degrading to the safe, visible suggest behavior.
  • Hooked into the main PR-webhook path right after the existing linked-issue evidence gathering, entirely independent of the gate/disposition — a missed or wrong match never affects CI or merge. All gating (installed app, PR still open, feature opted in) and error-swallowing lives in one maybeSuggestMilestoneMatchForPr function so the webhook handler's own call site stays a single unconditional call, easy to reason about and outside the huge webhook file's own test burden.
  • Closes feat(agent): auto-match PRs to open GitHub Milestones (suggest-mode) #3183.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked an issue, or this is small enough that the summary explains why an issue is not needed.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; codecov/patch requires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Ran targeted validation instead of the full local gate: typecheck, git diff --check, db:migrations:check, ui:openapi:check (regenerated + verified), and every affected suite directly (test/unit/project-tracker-adapter.test.ts — 20 tests, 100% branch/line coverage locally on the new adapter file; test/unit/repository-settings-project-milestone-match.test.ts — 5 tests; test/unit/focus-manifest.test.ts, test/unit/settings-preview.test.ts, test/unit/openapi.test.ts, test/unit/ci-openapi-settings-parity.test.ts, test/unit/selfhost-config-examples.test.ts, test/unit/signals*.test.ts) plus npm run test:changed (232 files / 5888 tests, all green — this touches src/queue/processors.ts so it covers test/unit/queue.test.ts, 482 tests, too). No UI/MCP/workers files touched, so ui:*/test:workers/build:mcp/test:mcp-pack are out of scope. CI runs the full gate on push.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics. (Suggestion comment is a plain milestone-name + confidence-percent note.)
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests. (N/A — no auth/CORS/session surface touched; the new GitHub API calls are covered by fetch-stub tests including invalid-repo-name, no-match, and idempotency paths.)
  • API/OpenAPI/MCP behavior is updated and tested where needed. (autoProjectMilestoneMatch added to all 4 reviewCheckMode-sibling locations in src/openapi/schemas.ts, regenerated via npm run ui:openapi.)
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. (N/A — no UI changes.)
  • Visible UI changes include a UI Evidence section below... (N/A — backend-only change, no visible UI.)
  • Public docs/changelogs are updated where needed... (N/A — no changelog edit per house rule.)

UI Evidence

N/A — backend-only change, no visible UI.

Notes

@superagent-security

Copy link
Copy Markdown
Contributor

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 4, 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 1335a70 Commit Preview URL

Branch Preview URL
Jul 04 2026, 11:24 PM

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.12%. Comparing base (15e308c) to head (f20f1be).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3256      +/-   ##
==========================================
+ Coverage   94.11%   94.12%   +0.01%     
==========================================
  Files         275      276       +1     
  Lines       30120    30191      +71     
  Branches    10993    11010      +17     
==========================================
+ Hits        28347    28418      +71     
  Misses       1127     1127              
  Partials      646      646              
Files with missing lines Coverage Δ
src/db/repositories.ts 96.38% <100.00%> (+<0.01%) ⬆️
src/db/schema.ts 69.46% <ø> (ø)
src/integrations/project-tracker-adapter.ts 100.00% <100.00%> (ø)
src/openapi/schemas.ts 100.00% <ø> (ø)
src/queue/processors.ts 92.93% <100.00%> (+<0.01%) ⬆️
src/signals/engine.ts 97.35% <ø> (ø)
src/signals/focus-manifest.ts 98.56% <100.00%> (+<0.01%) ⬆️
🚀 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:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 4, 2026
@loopover-orb

loopover-orb Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review result - approve/merge recommended

Review updated: 2026-07-04 23:43:10 UTC

13 files · 1 AI reviewer · no blockers · readiness 82/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
The change adds an opt-in milestone suggestion path with schema/migration/config/OpenAPI wiring and keeps it outside gate disposition, which is the right boundary for suggest-mode behavior. The main production path is gated on installation, open PR state, and the new setting, and the migration/schema pairing is present. I do not see a reachable correctness blocker in the visible diff, though the comment idempotency is best-effort and worth tightening if duplicate webhook delivery/concurrency matters.

Nits — 6 non-blocking
  • nit: src/integrations/project-tracker-adapter.ts:191 uses a read-then-post marker check, so two concurrent webhook deliveries for the same PR can both miss the marker and post duplicate suggestions; this is not new-class data loss, but the comment should say best-effort under concurrency or use an existing serialized/comment-upsert pattern if one exists.
  • nit: src/integrations/project-tracker-adapter.ts:57 accepts numeric strings like "1e2" and whitespace-padded values as milestone IDs because it uses Number(value); prefer a decimal-only regex before parsing so the adapter contract stays narrow.
  • nit: src/integrations/project-tracker-adapter.ts:72 and src/integrations/project-tracker-adapter.ts:179 each create an installation token for one suggestion pass; consider passing the already-created Octokit/token through the helper to avoid an avoidable extra access-token request per matched PR.
  • nit: src/openapi/schemas.ts:591 marks autoProjectMilestoneMatch optional even the DB resolver always returns a populated default, so confirm API clients intentionally see this as optional rather than required like reviewCheckMode.
  • src/integrations/project-tracker-adapter.ts:57 could use `if (!/^[1-9]\d*$/.test(value)) return null;` before `Number(value)` to keep malformed IDs out of the PATCH path.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #3183
Related work ⚠️ 1 scoped overlap Top overlaps are listed below; lower-confidence bulk is hidden.
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: 56 registered-repo PR(s), 46 merged, 429 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 56 PR(s), 429 issue(s).
Gate result ✅ Passing No configured blocker found.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 56 PR(s), 429 issue(s).
  • Related work: Titles/paths share 7 meaningful terms. (issue #3183, issue #3185)
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Review top overlaps.
  • Add a concise scope and risk note.
  • No action.
  • Check active issues and PRs before submitting.
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.

🟩 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 4, 2026
JSONbored added 2 commits July 4, 2026 16:21
…#3183)

Adds a ProjectTrackerAdapter interface (src/integrations/project-tracker-adapter.ts)
with a GitHubMilestonesAdapter implementation, so #3184 (Projects v2)
and #3186 (Linear) slot in without reshaping the matching/suggestion
logic. Matching reuses the existing tokenize/termOverlap primitives
from the duplicate-PR collision detector (now exported), at a stricter
threshold than that gate since misattaching tracked progress is worse
than an advisory-only duplicate note.

New tri-state autoProjectMilestoneMatch setting (off/suggest/auto,
default off), wired through the full config-as-code chain: migration,
Drizzle schema, DB resolver, OpenAPI, and .gittensory.yml parity,
mirroring the reviewCheckMode template. "auto" behaves like "suggest"
until #3185 wires real milestone attachment.

Hooked into the main PR-webhook path right after the existing
linked-issue evidence gathering, entirely independent of the
gate/disposition -- a missed or wrong match never affects CI or merge.
… handler

The processors.ts call site passed an inline onError closure whose
console.error body lived in the huge webhook file and was only
reachable through a full pipeline test, leaving it uncovered
(codecov/patch: 50% on that file). maybeSuggestMilestoneMatchForPr now
takes deliveryId directly and does its own logging internally, where
it already has dedicated, isolated test coverage -- the processors.ts
call site is now a plain data object literal with no logic of its own.
… comment

Gate review found a real gap: GitHub milestones and issue comments both
paginate at 100 per page, but listOpenMilestones and the suggest
comment's marker search only ever read page 1 -- a repo with >100 open
milestones, or a busy PR with >100 comments, could silently miss a
match or double-post. Both now page up to a bounded limit (mirroring
the same pattern already used in src/github/comments.ts).

Also: attachToMilestone now rejects a non-positive-integer milestoneId
instead of sending NaN to GitHub, and the suggestion comment
code-formats the milestone title (stripping literal backticks) so a
maintainer-authored title containing @mentions or markdown emphasis
can't leak into the rendered comment.

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

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

@loopover-orb
loopover-orb Bot merged commit d48c681 into main Jul 4, 2026
12 checks passed
@loopover-orb
loopover-orb Bot deleted the feat/auto-milestone-match branch July 4, 2026 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(agent): auto-match PRs to open GitHub Milestones (suggest-mode)

1 participant