You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: resolve member contributors for unknown ecosystems via llm repo inference - #5000
Purls from ecosystems CDP does not track are now accepted by POST /akrites-external/packages/member-contributors/jobs and routed to a new collection path instead of 400. Malformed purls (pkg:, pkg:hackage) still get 400.
A new workflow collectMemberContributorsFromInferredRepo asks Claude Sonnet 5.5 on Bedrock for up to three ranked candidate GitHub repositories, keeps those with confidence ≥ 0.7, takes the first that exists on GitHub, fetches its contributors without storing them, resolves affiliations for new identities, and returns the sync body with repoUrlSource: "llm_inferred" as the workflow result. Below-threshold, unknown, non-GitHub or missing repositories end the job as unresolvable with a reason. Truncated or refused LLM answers are retried or surfaced, never recorded as a confident unresolvable.
The poll endpoint serves unresolvable, reads inferred-repo done bodies from Temporal, and answers failed with a resubmit reason once the result has left Temporal retention. A resubmission while a result is still readable gets 409 with error.context.jobId.
Job rows record the repository used, its source, LLM confidence, per-call token usage and estimated cost, and a submission counter for repeat requests. Each LLM call is also logged with tokens, cost and stop reason. At most two LLM calls per job.
No repos, packages, package_repos or repo_contributors row is created or updated from an LLM answer. Supported-ecosystem jobs are unchanged apart from counting repeat submissions.
The response body builder moved from the backend into @crowd/data-access-layer so the worker and the API share it.
Migration
V1792150054__member_contributor_jobs_llm_repo_resolution.sql widens the two CHECK constraints on member_contributor_jobs and adds typed columns. Apply it before deploying the backend: the poll handler now selects the new columns on every path. Constraint names were verified against prod.
Medium Risk
Changes external job submit/poll semantics, adds LLM and Temporal-dependent result retention, and requires a DB migration before deploy; supported-ecosystem GitHub collection path is largely unchanged.
Overview Member-contributors jobs now accept purls from ecosystems CDP does not track, routing them to a new llm_repo_resolution collection path instead of 400. Malformed purls are validated with isWellFormedPurl; only those still return 400.
For unknown ecosystems, submit creates jobs without a package/repo lookup, starts collectMemberContributorsFromInferredRepo, and tracks repeat submissions (incrementMemberContributorJobSubmissions). 409 responses use a ConflictError with error.context.jobId when a prior inferred-repo result is still readable in Temporal. Poll adds unresolvable, serves inferred done bodies from the workflow result (not DB tables), and maps expired/missing workflow results to failed with a resubmit reason.
The worker adds Bedrock-based repo inference (confidence threshold + GitHub existence checks), contributor fetch/affiliation for inferred repos, and job metadata writes (LLM usage, inferred repo_url, submission count). No package/repo/contributor rows are persisted for the LLM path beyond job state.
OpenAPI documents the new statuses, repoUrlSource: llm_inferred, and conflict shape. A migration widens member_contributor_jobs constraints and adds LLM/repo columns. Response shaping moves into @crowd/data-access-layer (memberContributorsBody) for API/worker sharing.
Reviewed by Cursor Bugbot for commit dbf88c8. Bugbot is set up for automated code reviews on this repo. Configure here.
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You have signed the CLA already but the status is still pending? Let us recheck it.
Extends member-contributor collection to unsupported ecosystems through LLM-based GitHub repository inference, without persisting inferred package/repository mappings or contributor rows.
Changes:
Adds inference, repository verification, contributor fetching, and affiliation resolution.
Extends job submission, polling, usage tracking, and result-retention handling.
Shares response builders between the API and worker, with tests and API documentation.
The workflow commits done before returning its Temporal result. If it is terminated or cancelled in that interval, the row stays done because failMemberContributorJob excludes done rows. result() then rejects with WorkflowFailedError, so subsequent polls return HTTP 500 instead of a job status. Catch terminal workflow failures and return failed with a resubmit reason, consistent with submission allowing replacement of these executions. Continue propagating transient Temporal errors, and add a polling test for this case.
The reason will be displayed to describe this comment to others. Learn more.
Purl type case breaks job dedup
Medium Severity
Active-job reuse and the still-readable 409 both key inferred-repo jobs on the raw purl string, while purlType already treats the type as case-insensitive. pkg:hackage/aeson and pkg:Hackage/aeson therefore miss each other, so a second inference can start while the first job is pending or its Temporal result is still readable.
The reason will be displayed to describe this comment to others. Learn more.
Fixed in #5010 (commit 744e699 there): on the inferred-repo path the purl type is lowercased before the active-job lookup, the readable-result check, the row insert and the workflow id. The fix was pushed to this branch after it had been merged, so it ships in that follow-up PR rather than in #5000.
The reason will be displayed to describe this comment to others. Learn more.
Large repos fail inferred jobs
Medium Severity
fetchGithubRepoContributors turns every error from fetchRepoContributors into a retryable failure, including the helper’s 10-page cap. A correctly inferred repo with more than 1000 contributors never completes: the job fails after retries, and a resubmit spends another LLM call and fails the same way.
The reason will be displayed to describe this comment to others. Learn more.
Not reachable in practice: the GitHub contributors endpoint links only the first 500 author emails to GitHub users and omits anonymous contributors unless anon=1 is passed, which this code never does (docs: https://docs.github.com/en/rest/repos/repos#list-repository-contributors). With per_page=100 that is at most 5 pages, so the 10-page cap cannot trigger for this call. The same helper and cap already serve the supported-ecosystem path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /akrites-external/packages/member-contributors/jobsand routed to a new collection path instead of 400. Malformed purls (pkg:,pkg:hackage) still get 400.collectMemberContributorsFromInferredRepoasks Claude Sonnet 5.5 on Bedrock for up to three ranked candidate GitHub repositories, keeps those with confidence ≥ 0.7, takes the first that exists on GitHub, fetches its contributors without storing them, resolves affiliations for new identities, and returns the sync body withrepoUrlSource: "llm_inferred"as the workflow result. Below-threshold, unknown, non-GitHub or missing repositories end the job asunresolvablewith a reason. Truncated or refused LLM answers are retried or surfaced, never recorded as a confidentunresolvable.unresolvable, reads inferred-repodonebodies from Temporal, and answersfailedwith a resubmit reason once the result has left Temporal retention. A resubmission while a result is still readable gets 409 witherror.context.jobId.repos,packages,package_reposorrepo_contributorsrow is created or updated from an LLM answer. Supported-ecosystem jobs are unchanged apart from counting repeat submissions.@crowd/data-access-layerso the worker and the API share it.Migration
V1792150054__member_contributor_jobs_llm_repo_resolution.sqlwidens the two CHECK constraints onmember_contributor_jobsand adds typed columns. Apply it before deploying the backend: the poll handler now selects the new columns on every path. Constraint names were verified against prod.Closes linuxfoundation/lfx-cdp-insights-ops#502