Repository navigation
feat(contributor-growth): name contract operations instead of gh; Jira as a tracker backend - #1549
Merged
Merged
Conversation
…ople Add the read-only queries the contributor-growth skills need to the capability contracts, so those skills can stop calling `gh` directly: - contract:change-request gains list_authored, list_reviews_given and list_authored_commits (links, dates, counts and flags; never bodies). - contract:tracker gets a minimal interface spec, tools/tracker/, for list_filed, list_triaged, list_commented, list_created and first_reply. - contract:source-control documents two hosted-repository operations, repository_metadata and put_file, in tools/github/source-control.md. - New contract:people (tools/people/): profile lookup, repository collaborators, and one confirmed write, add_team_member. GitHub implements every new operation (operations.md § People and § Contributor activity); Jira implements the tracker queries and profile lookup. GitLab, Forgejo and Bitbucket are listed as follow-ups. contract:people is registered with the validator, the vendor-neutrality scorer (vendor-backed: GitHub + Atlassian, green), the capability map, the labeler and the adapter registry. Generated-by: Claude Opus 5
Split fetching into a code-host side (PRs authored, reviews, PR threads; contract:change-request) and a tracker side (issues filed, triaged, issue threads; contract:tracker), so the two can come from different systems. Today's GitHub code moves unchanged into backends/github.py. With both sides on GitHub — the default and the only configuration so far — it runs exactly the historical searches and produces the same items and output; every existing test passes untouched. A `streams` argument lets it answer one side only, searching `type:pr` threads when another backend owns the issues. contributor_metrics.fetch is now the dispatcher and keeps its public names (fetch_items, GhError, InvalidLogin, InvalidRepo, the substantive defaults). Shared pieces — the side names, the BackendError base and the generic pushback phrases — live in backends/common.py. Generated-by: Claude Opus 5
A project can review on GitHub and file issues in Jira. With `--tracker-config <project-config>/issue-tracker-config.md` naming `tracker_type: jira` (or `--tracker jira`), GitHub answers PRs, reviews and PR threads, and the new `jira` backend answers issues filed, issues triaged and issue threads, for the contributor's `--tracker-login`. - Issues filed: JQL on reporter and creation date. - Triage: someone else's issue on which the user changed status, labels, component, priority, assignee, resolution or fix version, or commented — read from the issue history, plus a direct `CHANGED BY … DURING` search that reaches beyond the scan cap. - Threads: issues the user commented on, dated by their first comment in the window. Pushback candidates use the tracker roster only, since Jira has no author association; comment bodies stay inside the backend. The URL and project key resolve from issue-tracker-config.md as other skills resolve `<issue-tracker>`, overridable with --jira-url/--jira-project. Output gains a `backends` key and the cache key includes it, only in Jira mode; GitHub-only output is unchanged. The HTTP client is a new stdlib-only, GET-only `jira_bridge.rest` in tools/jira, following the bridge's auth conventions (JIRA_API_TOKEN / JIRA_AUTH_SCHEME, or a token under ~/.config/apache-magpie), so the network surface stays in the tracker adapter. Tests run against recorded responses; no network. Generated-by: Claude Opus 5
Replace every direct `gh` call in the contributor-growth family with the contract operation it performs, with GitHub named as the adapter where it helps and its command shapes kept in tools/github: - candidate-screen: repository visibility and report commit through contract:source-control (repository_metadata, put_file), readers through contract:people (list_collaborators), the merged-change pool and pre-filter counts through contract:change-request. - activity-sweep, contributor-to-committer, nomination, calibrate: repository age and reachability through repository_metadata, adapter auth checks, and contributor-metrics told about a separate tracker (--tracker-config, --tracker-login). - identity-map, real-names, community-signals: profiles and linked accounts through contract:people (get_profile), commit e-mails and names through list_authored_commits. GitHub Discussions stays an optional, clearly marked GitHub-only signal. - sentiment: issues, first replies, changes and reviews through contract:tracker and contract:change-request. - committer-onboarding: the team invite is contract:people add_team_member (GitHub wording kept for the github-codeowners model); the DCO check reads signed_off_by from list_authored_commits. Every gate, confirmation, privacy and injection rule is unchanged, and so is behaviour on a GitHub project. Token counts restamped. Generated-by: Claude Opus 5
The Jira URL comes from project configuration, which anyone with write access can commit, while the token is the user's personal credential. jira_bridge.rest now keeps a changed URL from silently receiving it: - the URL must be https:// (http:// only for localhost, 127.0.0.1, ::1); - the token is sent only to the host the user confirmed for it (JIRA_API_HOST, or a host= line beside token= in ~/.config/apache-magpie/jira-token) and only on requests to that host; otherwise it is withheld, reads go out anonymously, and auth_note — surfaced in contributor-metrics notes — says why; - redirects are refused, naming the target, so the token never follows one; - the token never appears in an error, a note or the client's repr. Tests cover each rule, including a live loopback redirect that must not reach the second server. Generated-by: Claude Opus 5
Add an activity-sweep render case whose PRs and reviews come from GitHub and whose issues come from a Jira tracker; the card keeps its shape. Update the candidate-screen deliver output spec that quoted the old gh command, and regenerate the generated sections. Generated-by: Claude Opus 5
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
The contributor-growth family called
ghdirectly in about 30 places, and its counting engine,contributor-metrics, was hard-wired to GitHub.After this PR the skills name capability-contract operations, GitHub is one adapter for them, and Jira is a second backend for the tracker side.
A project that reviews on GitHub and files issues in Jira now gets correct contributor activity from both.
Follows #1548 (the optimization pass on the same family).
Contract operations added
contract:change-requestlist_authored,list_reviews_given(counts and lengths, never bodies),list_authored_commits(with asigned_off_byflag for DCO)tools/change-request/README.mdcontract:trackerlist_filed,list_triaged,list_commented,list_created,first_replytools/tracker/README.mdcontract:source-controlrepository_metadata,put_filetools/github/source-control.mdcontract:people(new)get_profile,list_collaborators,add_team_member(the one write, confirmation-gated)tools/people/README.mdThe GitHub resolutions of every operation live in
tools/github/operations.md.Adapter coverage
get_profilelist_collaborators,add_team_memberGitLab, Forgejo and Bitbucket already implement the base contracts; their adapters for the new operations are follow-ups using the same seam.
contributor-metricsfetchnow has two sides: the code host (PRs, reviews, PR threads) and the tracker (issues filed, triaged and commented on).<project-config>/issue-tracker-config.mdother skills read; flags and environment variables can override it.--tracker-logincovers a Jira username that differs from the GitHub handle.jira_bridge.restintools/jira. Keeping it there leaves the substrate tool free of network code.Jira token handling
The token is the user's personal credential, while the Jira URL comes from project configuration, which may be committed.
So the client:
https://, allowinghttp://only for loopback;JIRA_API_HOST, or ahost=line in~/.config/apache-magpie/jira-token), and only on requests to that host. Otherwise it reads anonymously and says why;Each rule has a test, including a loopback redirect that must not reach the second server.
Upgrade note: an existing Jira token without a confirmed host is no longer sent. Add
host=or setJIRA_API_HOST.Still GitHub-only
github-codeownersgovernance model, which is GitHub by definition; its operation still goes throughcontract:people.Testing
activity-sweepcase with issues from Jira and PRs from GitHub that keeps the same card shape.tools/contributor-metrics: 77 tests.tools/jirahas new client tests. ruff and mypy are clean.prek run --all-filesis green.contract:peopleis green on GitHub + Atlassian;The
contract:peoplelabel needs creating on the repository.Gen-AI disclosure: prepared with the assistance of Claude Code (Claude Opus 5); reviewed by the author.
🤖 Generated with Claude Code