Skip to content

feat(agent): add duplicate and stale-work scenario blockers - #346

Merged
JSONbored merged 2 commits into
JSONbored:mainfrom
Lobster-0429:feat/scenario-blockers
Jun 3, 2026
Merged

feat(agent): add duplicate and stale-work scenario blockers#346
JSONbored merged 2 commits into
JSONbored:mainfrom
Lobster-0429:feat/scenario-blockers

Conversation

@Lobster-0429

Copy link
Copy Markdown
Contributor

Summary

  • Closes feat(signals): include duplicate and stale-work scenario blockers #289: adds duplicate_risk and stale_work scenario blockers to the scoring pipeline so contributors are warned about conflicting or low-value work before opening a PR
  • Both blockers integrate into every ScoreScenarioPreview via blockedByFor() — no new surface or routing needed
  • reducer severity means blockers appear in public scenario summaries with generic phrasing and in private surfaces with the exact count and action text
  • Adds test/unit/scenario-blockers.test.ts (14 tests): duplicate, stale PR, stale branch, no-blocker + sanitizer fixtures

Scope

  • 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 — clean
  • npm run test:coverage locally — 786 pass (1 skipped); pre-existing Windows failures confirmed on main before this branch; coverage stays above 97%
  • 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:

  • UI/MCP/worker checks not applicable — this PR touches only src/scoring/preview.ts and adds a test file; no UI, MCP, or worker surface changed

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, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests. (not applicable)
  • API/OpenAPI/MCP behavior is updated and tested where needed. (new blocker codes appear in blockedBy arrays already exposed by existing MCP tools; no protocol change)
  • Visible UI changes include screenshots or a short recording. (not applicable)
  • Public docs/changelogs are updated where needed. (not applicable)

Notes

New ScoreGateBlocker codes:

Code Severity Trigger condition Detail text
stale_work reducer observedStalePrCount > 0 N stale open PR(s) detected; consider closing stale work before opening new contributions.
duplicate_risk reducer duplicateRiskCount > 0 N duplicate-risk issue(s) or PR(s) detected; verify there is no conflicting work before proceeding.

New ScorePreviewInput field:

  • duplicateRiskCount?: number — count of duplicate-risk issues/PRs, intended to be populated from buildCollisionReport() results in calling code.

Severity rationale: Both new codes use "reducer" (not "context") so they appear in the public blockers list. The pending feat/scenario-summaries PR's PUBLIC_BLOCKER_TEXT map will need entries for these two codes when that branch merges; the detail strings above are their intended public-safe generic equivalents.

Test structure (14 tests):

  • stale_work: emits with count, absent when zero/missing, propagates into scenario previews, detail sanitizable
  • duplicate_risk: emits with count, absent when zero/missing, exact count in detail, detail sanitizable
  • Combined: both independent when both signals set; existing gate blockers not displaced
  • No-blocker: neither code emitted when inputs absent
  • Public sanitizer fixtures (3): individual detail strings + full blockedBy array pass sanitizePublicComment

Extends the scenario planning pipeline with two new advisory blockers so
contributors are warned about conflicting or low-value work before opening
a PR. Both blockers are reducer-severity (visible in public summaries via
generic text, exact counts in private surfaces) and integrate directly
into every ScoreScenarioPreview via blockedByFor().

src/scoring/preview.ts:
- ScorePreviewInput: add duplicateRiskCount (count of duplicate-risk
  issues or PRs, e.g. from buildCollisionReport).
- ScoreGateBlocker["code"]: add "stale_work" and "duplicate_risk".
- blockedByFor(): emit stale_work when observedStalePrCount > 0 and
  duplicate_risk when duplicateRiskCount > 0. Both use "reducer"
  severity so they appear in public scenario output with generic phrasing
  and in private surfaces with the exact count and action text.

test/unit/scenario-blockers.test.ts (new, 14 tests):
- stale_work fixture: emits reducer blocker with count; absent when zero
  or missing; propagates into scenario previews; detail is sanitizable.
- duplicate_risk fixture: emits reducer blocker with count; absent when
  zero or missing; count in detail matches input; detail is sanitizable.
- Combined fixture: both blockers present independently when both signals
  set; existing gate blockers (open_pr_threshold) are not displaced.
- No-blocker baseline: neither code emitted when inputs are absent.
- Public sanitizer fixtures: stale_work and duplicate_risk detail text
  passes sanitizePublicComment without leaking forbidden language;
  full blockedBy array on a combined preview is fully sanitizable.

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

@web-dev0521 this lands the right kind of guardrail.

A few notes:

  • The duplicate and stale-work cases are modeled as blockers instead of soft hints.
  • The tests make the expected behavior concrete.
  • The PR stays focused on the scenario-blocker surface.

No code changes requested.

Validation expected:

  • Keep the current CI suite green through merge.

@dosubot dosubot Bot added the lgtm label Jun 3, 2026
@JSONbored
JSONbored merged commit f9a11c9 into JSONbored:main Jun 3, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jun 3, 2026
Lobster-0429 added a commit to Lobster-0429/gittensory that referenced this pull request Jun 3, 2026
…ker text

The ScoreGateBlocker code union grew to include duplicate_risk and
stale_work (from JSONbored#346). PUBLIC_BLOCKER_TEXT is keyed by every blocker
code, so the map must cover both new codes or the Record literal fails
typecheck (TS2739).
@github-actions github-actions Bot mentioned this pull request Jun 3, 2026
12 tasks
@JSONbored JSONbored added gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. and removed feature labels Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

feat(signals): include duplicate and stale-work scenario blockers

2 participants