Skip to content

fix(review): let bug/feature labels propagate from maintainer-authored linked issues - #3938

Merged
JSONbored merged 5 commits into
mainfrom
fix/linked-issue-label-propagation-ownership
Jul 7, 2026
Merged

fix(review): let bug/feature labels propagate from maintainer-authored linked issues#3938
JSONbored merged 5 commits into
mainfrom
fix/linked-issue-label-propagation-ownership

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • linkedIssueLabelPropagation (the feature that lets a PR inherit its linked issue's gittensor:* label) only fired when the PR author had directly opened or been assigned the linked issue. In practice our issues are almost always maintainer-authored for open community pickup and rarely formally assigned, so gittensor:bug/gittensor:feature mirroring effectively never worked — PR labels came from title-classification alone, independent of the linked issue.
  • Splits the ownership check by label sensitivity: a mapping can opt into trustMaintainerAuthoredIssue to also unlock for an issue authored by the repo owner/admin/write-collaborator (generic permission check, not a hardcoded login — mirrors the existing hasMaintainerOrOwnerPermission pattern). gittensor:priority (the scarce, maintainer-hand-picked reward label) intentionally keeps the strict direct-author-or-assignee requirement, since the title-classification fallback provides zero equivalent verification for bug/feature but there's no such fallback for priority.
  • Adds a structured log line whenever a linked issue's labels get filtered, so a future "why didn't my PR inherit the label" report is diagnosable from logs instead of a source read.
  • Enables propagation on this repo's own .gittensory.yml (bug/feature relaxed, priority strict) as a live, working example.
  • Mirrors the same field into packages/gittensory-engine's hand-synced copy of these types/normalizer (surfaced by rebasing onto feat(engine): extract focus-manifest parse/compile core (#2280) #3891's focus-manifest extraction mid-PR).

Closes #3903.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • 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 a currently open issue this PR resolves (Closes #3903).

Validation

  • git diff --check
  • npm run actionlint (via npm run test:ci)
  • npm run typecheck
  • npm run test:coverage locally — 100% line/branch coverage on every new line in src/review/linked-issue-label-propagation-fetch.ts and src/review/linked-issue-label-propagation.ts's new normalizer block
  • npm run test:workers (via npm run test:ci)
  • npm run build:mcp (via npm run test:ci)
  • npm run test:mcp-pack (via npm run test:ci)
  • npm run ui:openapi:check (regenerated after the trustMaintainerAuthoredIssue schema addition)
  • npm run ui:lint (via npm run test:ci)
  • npm run ui:typecheck (via npm run test:ci)
  • npm run ui:build (via npm run test:ci)
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries — added coverage for: literal-owner match, ADMIN_GITHUB_LOGINS match, live write-collaborator match, read-only/denied collaborator, collaborator-permission-check error (fails closed), null/ghost issue author, no-mapping-opted-in default (byte-identical to pre-fix behavior), and the manifest-level end-to-end resolution of this repo's own new config.

Full npm run test:ci run locally green end-to-end (twice, across two rebases onto a fast-moving main).

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.
  • Auth/permission-relevant change (the ownership check) includes negative-path tests (denied collaborator, error, ghost author, no-mapping-opted-in default).
  • API/OpenAPI/MCP behavior is updated and tested where needed (trustMaintainerAuthoredIssue added to the linkedIssueLabelPropagation OpenAPI schema).
  • No UI changes — backend/config only, no UI Evidence section needed.
  • Public docs/changelogs: none needed; this is an internal engine/config change with no public-facing doc surface.

Notes

  • The ownership-check design (strict-for-priority, relaxable-for-bug/feature via a generic maintainer-permission check rather than a hardcoded login) was worked through with @JSONbored before implementation.

@cloudflare-workers-and-pages

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

Branch Preview URL
Jul 07 2026, 07:55 AM

@superagent-security

Copy link
Copy Markdown
Contributor

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

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

loopover-orb Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Warning

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

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-07 07:47:14 UTC

15 files · 1 AI reviewer · 1 blocker · readiness 100/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Possible leaked secret in the diff (private_key_block) — Remove the secret from the diff, rotate the exposed credential, then re-run the gate.

Review summary
This PR relaxes linked-issue label propagation so bug/feature labels also fire when the linked issue was authored by a repo maintainer/owner/write-collaborator (via a new opt-in `trustMaintainerAuthoredIssue` per-mapping flag), while keeping `gittensor:priority` on the strict direct-author-or-assignee path. The maintainer check (`isRepoMaintainerLogin`) fails closed on API errors, the relaxed path only unlocks labels explicitly listed as relaxable (not the full issue label set), and the change is mirrored consistently across the app's type/schema/openapi/engine-package copies plus the repo's own `.gittensory.yml` as a live example. Test coverage is thorough across the new branches (owner, admin-list, write-collaborator, read-only-denied, fetch-error, no-author, no-opt-in), and the `queue.test.ts` repo-name swap is correctly reasoned to avoid the self-repo manifest now dogfooding this feature.

Nits — 6 non-blocking
  • src/review/linked-issue-label-propagation-fetch.ts: `resolveIssueLabelsForPropagation` can trigger one `getRepositoryCollaboratorPermission` API call per linked issue (up to the existing 50-issue cap) with no de-dup across issues sharing the same author — consider memoizing by login within a single fetch call.
  • src/review/linked-issue-label-propagation-fetch.ts:75 — the `console.log` structured-log line is intentional per the PR description, but confirm the repo doesn't have a shared logger wrapper (other modules might expect structured logs to go through a common helper for redaction/formatting consistency).
  • test/unit/linked-issue-label-propagation-fetch.test.ts generates a fresh RSA keypair per test needing collaborator-permission checks — works but adds real crypto cost per test run; a shared/cached key across these tests would be cheaper.
  • The `reason` field naming in the filtered-labels log (`strict_label_requires_direct_ownership` vs `no_direct_ownership_match`) is a bit terse for future debugging; a short comment mapping each reason string to its trigger condition would help.
  • Consider caching collaborator-permission lookups within `fetchLinkedIssueLabelsForPropagation` keyed by issue author login, since multiple linked issues could share the same author.
  • 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.

Concerns raised — review before merging

  • Possible leaked secret in the diff (private_key_block) — Remove the secret from the diff, rotate the exposed credential, then re-run the gate.
Signal Result Evidence
Code review ❌ 1 blocker 1 reviewer
Linked issue ✅ Linked #3903
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 (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 51 registered-repo PR(s), 43 merged, 343 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 51 PR(s), 343 issue(s).
Gate result ❌ Blocking Repo-configured hard blocker found.
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: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 51 PR(s), 343 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.

🟩 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

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

❌ 5 Tests Failed:

Tests completed Failed Passed Skipped
11005 5 11000 7
View the full list of 5 ❄️ flaky test(s)
test/unit/slop.test.ts > buildNonSubstantivePaddingFinding (#561 path-matcher signal) > contributes to the aggregate slop assessment without colliding with trivial-churn

Flake rate in main: 100.00% (Passed 0 times, Failed 1 times)

Stack Traces | 0.00173s run time
AssertionError: expected 'low' to be 'elevated' // Object.is equality

Expected: "elevated"
Received: "low"

 ❯ test/unit/slop.test.ts:628:25
test/unit/slop.test.ts > buildSlopAssessment > raises trivial-churn slop for high-churn diffs with minimal source lines

Flake rate in main: 100.00% (Passed 0 times, Failed 1 times)

Stack Traces | 0.00171s run time
AssertionError: expected 'low' to be 'elevated' // Object.is equality

Expected: "elevated"
Received: "low"

 ❯ test/unit/slop.test.ts:199:25
test/unit/slop.test.ts > buildSlopAssessment > reaches the high band when multiple strong signals stack

Flake rate in main: 100.00% (Passed 0 times, Failed 1 times)

Stack Traces | 0.00141s run time
AssertionError: expected 'low' to be 'elevated' // Object.is equality

Expected: "elevated"
Received: "low"

 ❯ test/unit/slop.test.ts:312:27
test/unit/slop.test.ts > buildSlopAssessment > stacks the duplicate-cluster weight with another signal into the expected band (#563)

Flake rate in main: 100.00% (Passed 0 times, Failed 1 times)

Stack Traces | 0.0247s run time
AssertionError: expected 'low' to be 'elevated' // Object.is equality

Expected: "elevated"
Received: "low"

 ❯ test/unit/slop.test.ts:124:25
test/unit/slop.test.ts > slop golden fixtures & determinism (#565) > scores the 'elevated — untested code change insid…' fixture to its documented band

Flake rate in main: 100.00% (Passed 0 times, Failed 1 times)

Stack Traces | 0.00132s run time
AssertionError: expected 'low' to be 'elevated' // Object.is equality

Expected: "elevated"
Received: "low"

 ❯ test/unit/slop.test.ts:664:25

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

JSONbored added 5 commits July 7, 2026 00:50
…d linked issues (#3903)

Linked-issue label propagation only ever fired when the PR author had directly
opened or been assigned the linked issue, so gittensor:bug/gittensor:feature
almost never mirrored the issue's label in practice -- our issues are nearly
always maintainer-authored for open community pickup, and rarely formally
assigned. Split the ownership check by label sensitivity: a mapping can opt
into trustMaintainerAuthoredIssue so it also unlocks for an issue authored by
the repo owner/admin/write-collaborator, while gittensor:priority (the scarce,
maintainer-hand-picked reward label) keeps the strict direct-ownership
requirement. Also logs a structured event whenever a linked issue's labels get
filtered, so a future "why didn't my PR inherit the label" report doesn't need
a source read.

Enables propagation on this repo's own .gittensory.yml (bug/feature relaxed,
priority strict) as a live example for other gated repos to copy.
…ngine package

Rebasing onto #3891 (extract focus-manifest parse/compile core) surfaced that
packages/gittensory-engine keeps its own hand-synced copies of
LinkedIssueLabelPropagationMapping and its normalizer, predating this PR's new
field. Without this, the engine package's manifest parser would silently drop
trustMaintainerAuthoredIssue from any .gittensory.yml it parses, including
this repo's own.
…e normalizer mirror

codecov/patch flagged 2 missing lines in packages/gittensory-engine's copy of
normalizeMapping -- test/unit/linked-issue-label-propagation-engine.test.ts
mirrors the app-side suite but predates this PR's new field. Adds the same
3 cases (true passthrough, omitted stays undefined, malformed warns without
defaulting to true) already covered on the src/ side.
…the ephemeral test PEM helper

generatePrivateKeyPem() builds a valid PEM string from a freshly-generated
in-memory key for test-only JWT signing -- no real credential is ever
embedded. The literal "-----BEGIN PRIVATE KEY-----" marker text still
matched the review-safety secrets scanner's private_key_block pattern
(a pure text match with no awareness the bytes between the markers are
generated per test run), hard-blocking the gate. Splits the marker text
across a join() so it never appears contiguous in source; the produced
PEM string (and all runtime behavior) is byte-identical.
…#3939)

#3939 lowered the live .gittensory.yml readiness minScore from 60 to 40 but
didn't update this bundled fallback copy, leaving the two byte-mismatched --
already broken on main independent of this branch, just first surfaced here
because this PR also touches this file. Incidental fix, bundled in since a
separate branch/rebase cycle for a one-line sync isn't worth the overhead.
@JSONbored
JSONbored force-pushed the fix/linked-issue-label-propagation-ownership branch from 69ac7c5 to b8607bd Compare July 7, 2026 07:53
@JSONbored
JSONbored merged commit 9707578 into main Jul 7, 2026
8 of 9 checks passed
@JSONbored
JSONbored deleted the fix/linked-issue-label-propagation-ownership branch July 7, 2026 07:56
JSONbored added a commit that referenced this pull request Jul 7, 2026
Rebasing onto #3938's own new settings: block (linkedIssueLabelPropagation)
left two top-level settings: keys in .gittensory.yml and its bundled
fallback -- invalid YAML that would have silently dropped one of the
two setting groups depending on parser behavior. Merge into one block.
JSONbored added a commit that referenced this pull request Jul 7, 2026
…3962)

* fix(review): close repeated ready<->draft cycling as review evasion

Enable reviewEvasionProtection for our own repos and add a new guard
that fires on the second (and every later) draft conversion for a PR,
independent of whether an active review or a recorded gate failure is
present. The two existing draft guards only catch dodging DURING a
still-running review or AFTER a stored gate block — a contributor who
drafts before either fires (e.g. immediately on open, or before CI
settles) can otherwise cycle ready<->draft indefinitely to harvest free
AI-review/CI feedback while sidestepping the one-shot disposition.

* test(slop): update golden fixtures for the #3939 band recalibration

#3939 raised the elevated-band floor from 25 to 31, so two stacked
weak signals (30) now land in low, not elevated. Five fixtures still
asserted the pre-recalibration boundary; adjust the genuine multi-
signal cases to a real 3-signal stack (45) and the single-signal
cases to their now-correct low band, per the recalibration's own
stated design (elevated requires >=45 or 3x weak).

* fix(config): merge the duplicate settings: block the rebase produced

Rebasing onto #3938's own new settings: block (linkedIssueLabelPropagation)
left two top-level settings: keys in .gittensory.yml and its bundled
fallback -- invalid YAML that would have silently dropped one of the
two setting groups depending on parser behavior. Merge into one block.
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

Development

Successfully merging this pull request may close these issues.

fix(review): linked-issue label propagation is disabled everywhere + ownership check would block it anyway

1 participant