Skip to content

feat(agent): make next-action recommendations repo-specific#30

Merged
JSONbored merged 6 commits into
JSONbored:mainfrom
grnlemon:feat/decision-pack-repo-specific-recommendations
May 29, 2026
Merged

feat(agent): make next-action recommendations repo-specific#30
JSONbored merged 6 commits into
JSONbored:mainfrom
grnlemon:feat/decision-pack-repo-specific-recommendations

Conversation

@grnlemon

Copy link
Copy Markdown
Contributor

Closes #16.

Summary

  • buildRepoDecision now receives the contributor's languageSet + labelHistory and computes per-repo languageMatch (from syncState.primaryLanguageprofile.github.topLanguages) and labelFit (from repo.registryConfig.labelMultipliersprofile.registeredRepoActivity.dominantLabels).
  • whyThisHelpsFor / nextActionsFor rewritten as per-recommendation helpers taking a RepoCopyContext. Direct-PR copy names matching language + label overlap + queue size + prior merged count. Issue-discovery copy names the lane + open-issue count. Cleanup-first copy names the contributor's open PR count. Maintainer-lane copy uses repo-owner framing only.
  • New publicNextActionsFor emits a sanitized variant (no raw counts) for GitHub-public surfaces. RepoDecision + DecisionAction gain publicNextActions: string[]; orchestrator's publicSafeSummary now pulls from decision.publicNextActions[0].
  • recommendationText now prefers action.nextActions[0] (the new per-repo copy) over the hardcoded action-kind fallback, so the API/MCP "recommendation" headline is also concrete.
  • priorityFor exempts the open_pr_pressure blocker from the cleanup_first penalty calc — fixes an ordering inversion where a cleanup_first repo with one critical blocker was outscored by a comparable pursue repo. AC feat(scoring): add situational score projections #3 (cleanup-first outranks new work) now holds end-to-end.

Acceptance criteria → coverage

  • Agent plan names specific repos and work types — per-repo whyThisHelps[0] / nextActions[0] reference repo + lane + concrete signals; asserted in fixtures for direct-PR, issue-discovery, maintainer-lane.
  • Maintainer-owned repo history does not inflate normal contributor-lane evidence — maintainer-lane fixture asserts the contributor's open-PR count is absent from nextActions and publicNextActions even when outcome.openPullRequests = 8.
  • Cleanup-first outranks new work when open PR pressure blocks scoreability — paired-fixture regression asserts pressure.priorityScore > pursueRepo.priorityScore with the priorityFor fix.
  • Direct-PR / issue-discovery / split / maintainer lanes produce different reasoning — lane-specific assertions across 4 fixtures; copy distinct on language hint, lane wording, repo-owner framing, queue/PR counts.
  • Recommendations are deterministic — same-input twice returns identical repoDecisions + topActions ordering (snapshot regression test).

Public/private boundary

  • Private (nextActions, whyThisHelps) may include raw counts (open PR count, merged PR count, open issue count, queue size).
  • Public (publicNextActions) deliberately omits counts and contributor history numerics; regression test asserts no digits appear in publicNextActions[0] for issue-discovery and maintainer-lane fixtures.
  • actionFromDecisionAction.publicSafeSummary now sources from publicNextActions instead of nextActions, closing the prior leak path (sanitizePublicSummary only redacts wallet/reward words — not digits).

Validation

  • npm run typecheck
  • npx vitest run test/unit test/integration — 270 tests pass
  • npx vitest run --config vitest.workers.config.ts — workers suite green
  • npm run changelog — refreshed CHANGELOG.md (single entry added)

Safety

  • Backend-only change
  • No secrets, wallet details, user PATs, raw trust scores, or private rankings exposed
  • Public text avoids compensation-seeking or optimization-tactic language; new publicNextActions audited to avoid leaking counts
  • OpenAPI/MCP behavior updated where needed (ContributorDecisionPackSchema per-decision shape is z.record(z.unknown()) — additive, no schema break)
  • Public docs/changelogs updated where needed

Relationship to #15 / PR #26

PR #26 (issue #15) touched freshness / serving helper and is on a separate branch. This PR touches buildRepoDecision / per-recommendation copy / priorityFor / orchestrator publicSafeSummary. Surfaces overlap (decision-pack.ts, agent-orchestrator.ts, the same test files) but at different functions; expect a rebase-clean merge if PR #26 lands first.

Open questions for review

  • Copy tone: I leaned on "pick a narrow change in {language} (target labels: {a, b}); queue has N open PRs" for direct-PR. Happy to revise wording in any direction — open to a per-lane copy review.
  • priorityFor adjustment: I exempted the open_pr_pressure blocker only when recommendation === "cleanup_first". Alternative: raise the cleanup_first base from 75 → 105 (clamped at 100) — same effect for most repos. Exemption is the more defensible choice but happy to flip.
  • labelFit source: I used repo.registryConfig.labelMultipliers ∩ profile.dominantLabels. Could also be dominantLabels directly. Open to either.

@grnlemon
grnlemon requested a review from JSONbored as a code owner May 29, 2026 01:18
Weave language fit, label overlap, queue size, and prior outcome
counts into per-repo whyThisHelps / nextActions. Add publicNextActions
for sanitized GitHub surfaces so counts stay private. Stop priorityFor
from penalizing cleanup_first for the open_pr_pressure blocker that
triggered the recommendation in the first place.

Closes #16.
@grnlemon
grnlemon force-pushed the feat/decision-pack-repo-specific-recommendations branch from 249d779 to 71bf866 Compare May 29, 2026 01:19
mkdev11 added 2 commits May 29, 2026 03:44
recommendationText now distinguishes cleanup_existing_prs,
land_existing_prs, file_issue_discovery, and maintainer-lane action
kinds again (falling through to per-repo nextActions only as a last
resort). whyThisHelpsFor / nextActionsFor / publicNextActionsFor gain
a split-lane arm so AC #4 covers all four lanes. Drop dead code in
RepoCopyContext and labelFit, unify the defensive ?. on profile.github.
Add split-lane and avoid_for_now fixtures. Add maintainer-vs-outside
separation test (same outcome.openPullRequests surfaces in cleanup
copy, not maintainer copy). Add end-to-end buildContributorDecisionPack
test so a regression in languageSet threading fails. Replace the noop
/\b8 open PR/ guard with a structural noStructuralCountLeak check
applied across all 5 recommendation tiers. Tighten the orchestrator
integration assertion to require per-lane phrasing. Strengthen the
determinism test to also assert priorityScore and nextActions equality.
@dosubot dosubot Bot added the size:L label May 29, 2026

@JSONbored JSONbored left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #30 - feat(agent): make next-action recommendations repo-specific
Signal: REQUEST CHANGES

Required changes:

  • Fix branch coverage drop: CI reports 94.94% branches, below 95%.
  • Add tests for languageMatch false/true, labelFit empty/non-empty, publicNextActions for every recommendation type, and cleanup_first priority without open_pr_pressure penalty.
  • Keep private numeric lane/share reasoning out of publicNextActions.
  • Re-run validate after branch tests are added.
  • Expect possible conflicts with #26 because both modify decision-pack and agent-orchestrator.

Push branches over the 95% gate (94.94 -> 95.03). New cases:

- languageMatch true/false and labelFit empty/non-empty paths.
- cleanup_first triggered via openPullRequests >= 3 (no open_pr_pressure
  blocker) still outranks pursue baseline.
- scoreBlockersFor with outcome undefined exercises the nullish guards.
- whyThisHelpsFor / nextActionsFor cleanup_first + watch (split lane)
  with outcome undefined.
- withSnapshotMetadata falls back to nowIso when both generatedAt
  fields are absent.
- publicNextActions sanitization asserted for every recommendation
  tier: no decimals, no share/emission/priority words, no field-name
  leaks.
@grnlemon

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Addressed each item in 0c61546:

  • Branch coverage: 94.94 → 95.03% (above the 95% gate). New tests target the previously uncovered branches in decision-pack.ts: scoreBlockersFor with outcome undefined, whyThisHelpsFor/nextActionsFor cleanup-first + watch (split) with undefined outcome, withSnapshotMetadata both-generatedAt-null fallback.
  • languageMatch true/false + labelFit empty/non-empty: new dedicated test exercising all four combinations; asserts copy includes/omits in TypeScript and target labels: … accordingly.
  • publicNextActions per recommendation type: new tier-loop test covering cleanup_first, maintainer_lane, pursue (direct), pursue (split), watch, avoid_for_now. Each tier asserts noStructuralCountLeak + no decimals + no share|emission|priority words.
  • cleanup_first priority without open_pr_pressure penalty: new test triggers cleanup_first via outcome.openPullRequests = 3 (no blocker emitted) and asserts it still outranks a paired pursue baseline, locking the priorityFor exemption invariant from both sides.
  • No private numeric lane/share reasoning in publicNextActions: the tier-loop regex /\b\d+(\.\d+)?\b/ plus /share|emission|priority/i is now applied to every tier's publicNextActions (and reused via noStructuralCountLeak on six per-lane fixtures).
  • Re-ran validate: npm run typecheck clean, 279/279 unit + integration tests pass, vitest --coverage reports branches at 95.03%.
  • Conflicts with feat(agent): serve stale decision packs with freshness marker and background rebuild #26: acknowledged. Happy to rebase whichever lands second; the surfaces overlap (decision-pack.ts, agent-orchestrator.ts) but at different functions, so I'm expecting a rebase-clean (not auto-clean) merge.

Pushed to the same branch.

@grnlemon

Copy link
Copy Markdown
Contributor Author

@JSONbored could you please review the update again?

…ions

Signed-off-by: ghost <49853598+JSONbored@users.noreply.github.com>
@JSONbored
JSONbored merged commit 638e311 into JSONbored:main May 29, 2026
3 checks passed
@grnlemon

Copy link
Copy Markdown
Contributor Author

Thank you!

@JSONbored JSONbored added gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. and removed gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. labels Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(agent): make next-action recommendations repo-specific

2 participants