Skip to content

feat(signals): wire burden forecast through intelligence + MCP with freshness - #61

Merged
JSONbored merged 6 commits into
JSONbored:mainfrom
mkdev5:feat/burden-forecast-wiring
May 29, 2026
Merged

feat(signals): wire burden forecast through intelligence + MCP with freshness#61
JSONbored merged 6 commits into
JSONbored:mainfrom
mkdev5:feat/burden-forecast-wiring

Conversation

@mkdev5

@mkdev5 mkdev5 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes #22.

Summary

  • New getBurdenForecast reader on the existing burden_forecasts table (src/db/repositories.ts).
  • New shared services helper loadOrComputeBurdenForecastResponse (src/services/burden-forecast.ts) returns an envelope with generatedAt, ageSeconds, and a freshness: \"fresh\" | \"stale\" marker (6 h window matching DECISION_PACK_MAX_AGE_MS). Falls back to a computed forecast for known repos that have no cached snapshot yet, so callers see actionable data on first hit.
  • buildRepoIntelligenceResponse (src/api/routes.ts) attaches burdenForecast + a burdenForecastFreshness slice (source, generatedAt, ageSeconds, freshness) to both snapshot and computed branches. Reads from the dedicated PK-indexed table, so request-time scans stay bounded.
  • New MCP tool gittensory_get_burden_forecast (src/mcp/server.ts) for parity with the private intelligence surface; returns not_found for unknown repos.

Acceptance criteria → coverage

  • AC1 "Large queue fixtures complete within Worker-safe bounds" — ragflow/sure-scale fixture (120 open PRs + 1 stale) at burden-forecast.test.ts:16-24 asserts level: \"critical\" and runs in unit-test time.
  • AC2 "Forecasts identify top burden sources and cleanup actions" — duplicate-trend and stale-PR fixtures assert forecast.duplicateTrend and findings[*].code for queue_growth_risk + stale_review_load; the existing builder also emits finding.action for cleanup hints.
  • AC3 "Repo intelligence includes freshness and data-quality warnings" — integration test at api.test.ts:723-735 asserts the intelligence response carries burdenForecast + burdenForecastFreshness: { source: \"snapshot\", freshness: \"stale\", ageSeconds: > 0 } when the cached row is older than 6 h.
  • AC4 "No broad request-time scans are needed" — new spy regression in burden-forecast.test.ts:103-122 asserts listIssueSignalSample, listOpenPullRequests, and listRecentMergedPullRequests are NOT called when a cached forecast exists.

Validation

  • npm run typecheck
  • npx vitest run test/unit test/integration — 352 tests pass
  • npx vitest run --coverage — branches at 95.07% (over the 95% gate)

Safety

  • Backend-only change
  • Private MCP/API surface only; no public-comment changes
  • No new public-facing copy
  • Reuses existing dedicated burden_forecasts table; no migration
  • CHANGELOG.md unchanged (per CONTRIBUTING.md rule)

Open questions for review

  • Standalone REST route: deliberately NOT added a GET /v1/repos/:owner/:repo/burden-forecast handler — test/unit/openapi.test.ts keeps the path on the "removed" list, matching the project pattern of exposing repo signals via the /intelligence aggregator + MCP tools rather than dedicated GET endpoints. Happy to add it if you'd rather expose it separately.
  • Freshness threshold: defaulted to 6 h matching DECISION_PACK_MAX_AGE_MS. Open to a different value.
  • Storage shape: kept the dedicated burden_forecasts table (one row per repo, primary-key access). Could move to signal_snapshots for consistency with other signals, but that's a refactor beyond this PR's scope.

Relationship to other in-flight work

mkdev11 added 4 commits May 29, 2026 11:06
New getBurdenForecast reader on the existing burden_forecasts table
plus a services/burden-forecast loader that returns an envelope with
generatedAt, ageSeconds, and a freshness marker (fresh | stale, 6h
window). Falls back to a computed forecast for known repos that have
no cached snapshot yet, so callers see actionable data on first hit
without waiting for the scheduled job.
…onse

buildRepoIntelligenceResponse now attaches the cached burden forecast
plus a burdenForecastFreshness slice (source, generatedAt, ageSeconds,
freshness) to both the snapshot and computed branches. Reads from the
dedicated burden_forecasts table, so request-time scans are limited
to the indexed PK lookup.
Returns the cached or freshly-computed burden forecast for a repo
along with its freshness marker so MCP consumers can decide whether
to retry once the next scheduled rebuild lands. Falls back to a
not_found payload when the repo is unknown.
- Builder fixtures: small clean queue, ragflow/sure-scale critical
  queue, duplicate-cluster trend, stale PR trend.
- Service fixtures: snapshot freshness fresh/stale, computed fallback
  for known but uncached repos, broad-lister spy regression so the
  cached path never triggers request-time scans.
- Queue.test.ts now asserts a burden forecast row was persisted after
  the build-burden-forecasts job.
- api.test.ts asserts the intelligence response includes the cached
  forecast plus its freshness slice, and that the MCP tool round-trips
  through cache + missing-repo branches.
@mkdev5
mkdev5 requested a review from JSONbored as a code owner May 29, 2026 09:07
@dosubot dosubot Bot added the size:L label May 29, 2026
@mkdev5

mkdev5 commented May 29, 2026

Copy link
Copy Markdown
Contributor Author

@JSONbored please review the PR when you have a chance and let me know your feedback.

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

#61 feat(signals): wire burden forecast through intelligence + MCP with freshness
action: merge
required:

  • None obvious. Snapshot-first with bounded computed fallback and passing validate.

@JSONbored
JSONbored merged commit 6e26ffe into JSONbored:main May 29, 2026
3 checks passed
@mkdev5

mkdev5 commented May 29, 2026

Copy link
Copy Markdown
Contributor Author

thank you for your review!

@dosubot dosubot Bot added the lgtm label May 29, 2026
jony376 pushed a commit to jony376/gittensory that referenced this pull request May 31, 2026
…reshness (JSONbored#61)

* feat(signals): add burden forecast reader and cache-or-compute helper

New getBurdenForecast reader on the existing burden_forecasts table
plus a services/burden-forecast loader that returns an envelope with
generatedAt, ageSeconds, and a freshness marker (fresh | stale, 6h
window). Falls back to a computed forecast for known repos that have
no cached snapshot yet, so callers see actionable data on first hit
without waiting for the scheduled job.

* feat(intelligence): include burden forecast in repo intelligence response

buildRepoIntelligenceResponse now attaches the cached burden forecast
plus a burdenForecastFreshness slice (source, generatedAt, ageSeconds,
freshness) to both the snapshot and computed branches. Reads from the
dedicated burden_forecasts table, so request-time scans are limited
to the indexed PK lookup.

* feat(mcp): add gittensory_get_burden_forecast tool

Returns the cached or freshly-computed burden forecast for a repo
along with its freshness marker so MCP consumers can decide whether
to retry once the next scheduled rebuild lands. Falls back to a
not_found payload when the repo is unknown.

* test(signals): cover burden forecast fixtures and wiring

- Builder fixtures: small clean queue, ragflow/sure-scale critical
  queue, duplicate-cluster trend, stale PR trend.
- Service fixtures: snapshot freshness fresh/stale, computed fallback
  for known but uncached repos, broad-lister spy regression so the
  cached path never triggers request-time scans.
- Queue.test.ts now asserts a burden forecast row was persisted after
  the build-burden-forecasts job.
- api.test.ts asserts the intelligence response includes the cached
  forecast plus its freshness slice, and that the MCP tool round-trips
  through cache + missing-repo branches.

* fix(signals): tighten burden forecast contract

---------

Co-authored-by: mkdev11 <MkDev11@users.noreply.github.com>
@JSONbored JSONbored added gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. and removed feature 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(signals): build maintainer burden forecast snapshots

2 participants