Skip to content

feat(groomer): add title rewriting and body enrichment#490

Merged
joryirving merged 1 commit into
mainfrom
feat/groomer-title-body-enrichment
Jun 29, 2026
Merged

feat(groomer): add title rewriting and body enrichment#490
joryirving merged 1 commit into
mainfrom
feat/groomer-title-body-enrichment

Conversation

@itsmiso-ai

Copy link
Copy Markdown
Contributor

Summary

Extend the hosted groomer (POST /api/groomer/run) to rewrite bad issue titles and enrich sparse issue bodies, with guardrail logic to prevent unnecessary changes.

Title Rewriting

  • Trigger: Only when current title is "bad": length <10 chars, single-word generic token (P0, TODO, bug, fix), or clearly a priority/label token
  • Behavior: Proposes an imperative verb form, 10-200 chars, derived from body content
  • Guardrail: Descriptive titles (>=10 chars, real sentence/phrase) are left alone

Body Enrichment

  • Trigger: Only when body is missing, empty, or <100 chars (excluding HTML/markdown comments)
  • Behavior: Adds structured context (brief description, what's known, suggested approach)
  • Guardrail: Substantial bodies are never clobbered; append-only if any meaningful content exists

Schema Validation

  • proposedTitle: 10-200 chars, optional with null tolerance
  • proposedBody: under 10000 chars, optional with null tolerance

Files Changed

File Change
src/lib/github.ts Added updateIssueTitleAndBody() API helper
src/lib/groomer/schema.ts Added proposedTitle, proposedBody to output + validation
src/lib/groomer/llm.ts Updated system prompt with enrichment instructions
src/lib/groomer/run.ts Guardrail checks + mutation application in pipeline
src/lib/groomer/schema.test.ts 10 new tests for proposedTitle/proposedBody validation
src/lib/groomer/run.test.ts 10 new tests for guardrails and mutation application

Example

Issue title "P0" → rewritten to "Fix SSO/OIDC callback state verification mismatch causing 400 errors" based on body content.

Verification

  • npx tsc --noEmit passes
  • ✅ All 184 groomer tests pass (incl. 20 new)
  • ✅ All 20 route tests pass

…peline

Extend the hosted groomer to rewrite bad issue titles and enrich sparse
issue bodies, with guardrail logic to prevent unnecessary changes.

Title rewriting:
- Only triggers when title is <10 chars, single-word generic token
  (P0, TODO, bug, fix), or clearly a priority/label token
- Proposes imperative verb form, 10-200 chars, based on body content

Body enrichment:
- Only triggers when body is missing, empty, or <100 chars
  (excluding HTML/markdown comments)
- Adds structured context without clobbering existing content

Schema validation:
- proposedTitle must be 10-200 chars
- proposedBody must be under 10000 chars
- Both optional with null tolerance

Implementation:
- Added updateIssueTitleAndBody() to GitHub API helpers
- Updated LLM prompt with title/body enrichment instructions
- Guardrail checks in run pipeline before applying mutations
- Mutation plan tracks originalTitle, proposedTitle, proposedBody
- appliedMutations includes titleUpdated and bodyUpdated flags
- Full test coverage for guardrails and mutation application

@its-saffron its-saffron Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI Automated Review

Full PR review.

Analysis engine: MiniMax-M2.7@https://litellm.jory.dev/v1 (anthropic) — routed smart (risk match: db_or_migration_changes)

PR Review: feat(groomer): add title rewriting and body enrichment

Recommendation: Approve

This PR adds title rewriting and body enrichment to the hosted groomer pipeline. The implementation is well-structured with comprehensive test coverage. CI (tests, lint, build, typecheck, Docker) passed.


Change-by-Change Findings

src/lib/github.ts (+28 lines)

Added updateIssueTitleAndBody() — a thin PATCH wrapper around the GitHub Issues API. Accepts title and body fields. Proper error handling with status-check and response text on failure. No secrets, no file serving, no auth-bypass concerns. Clean addition.

src/lib/groomer/llm.ts (+17, -2 lines)

Updated the LLM system prompt with:

  • Title rewriting rules: Triggers only for bad titles (<10 chars, single-word generics like P0/TODO/bug/fix, or priority tokens). New title must be 10–200 chars, imperative verb, derived from body/labels/comments.
  • Body enrichment rules: Triggers only for missing/empty/<100-char bodies. Adds structured context; append-only rather than clobbering existing content. Under 10,000 chars.

The prompts are precise and include explicit guardrails baked into the LLM instructions.

src/lib/groomer/schema.ts (+27, -1 lines)

Extended GroomerOutput with proposedTitle?: string and proposedBody?: string. Added validation:

  • proposedTitle: 10–200 chars, null-tolerant
  • proposedBody: under 10,000 chars, null-tolerant
  • Non-string values are rejected with structured errors

src/lib/groomer/run.ts (+92, -2 lines)

Key logic additions:

  • shouldRewriteTitle(): returns true for empty, <10-char, or single-word generic tokens. Defensive — good titles are left alone.
  • shouldEnrichBody(): returns true for null/empty or <100 visible chars (strips HTML/markdown comments).
  • computeTitleBodyMutations(): combines LLM proposals with guardrail checks, only returning mutations that pass both.
  • Mutation application: title and body updates are called via updateTitleAndBody() only when guardrails pass. Both can be applied in a single PATCH call.
  • Dry-run mode is respected — no GitHub API calls when dryRun: true.
  • Both appliedMutations.titleUpdated and bodyUpdated are set correctly.

src/lib/groomer/schema.test.ts (+94 lines)

10 new tests covering:

  • Valid/invalid proposedTitle (boundary: 10 and 200 chars)
  • Valid/invalid proposedBody (boundary: 10,000 chars)
  • Null tolerance for both fields
  • Rejects non-string values
  • Both fields together

src/lib/groomer/run.test.ts (+186 lines)

10 new tests covering:

  • Good titles are not rewritten
  • Bad short titles (<10 chars) are rewritten
  • Single-word generic titles (TODO, P0) are rewritten
  • Empty titles are rewritten
  • Substantial bodies are not enriched
  • Sparse bodies are enriched
  • Null bodies are enriched
  • Both title rewrite + body enrichment applied together
  • Dry-run includes mutation plan but skips API calls
  • Skips update when LLM doesn't propose changes

Required Checks

✅ review migration for data loss risk

Does not apply. This PR contains no database migrations or schema changes. The changed files are exclusively application logic (github.ts, llm.ts, run.ts, schema.ts) and their tests. There is no Prisma migration, no prisma/schema.prisma change, and no data model modification. The db_or_migration_changes classification appears to be a false positive from the classifier; the PR only touches library code. No data loss risk exists in this change.

✅ test migration on a copy of production schema

Does not apply. As noted above, there are no migrations in this PR. Testing on a production schema copy is not relevant to this change.


Standards Compliance

From AGENTS.md conventions verified:

  • Prisma schema — Not modified; no foreign key or relation changes
  • API routes — No route changes; the POST /api/groomer/run behavior is extended via existing dependency injection without changing the route surface
  • Error handlingupdateIssueTitleAndBody() uses response.ok check and throws meaningful errors with status + response text
  • Validation — Input validation is enforced at the schema level (validateGroomerOutput) before mutations are applied
  • No secrets — No .env, credentials, or tokens added
  • No agent-specific names in generic docs — N/A; no docs changed

Linked Issue Fit

No linked issue was provided in the corpus. The PR body describes the feature comprehensively with trigger conditions, guardrails, schema validation rules, file manifest, and example. Implementation aligns with the described behavior.


Evidence Provider Findings

No evidence providers configured for this PR.


Tool Harness Findings

No tool harness findings — the corpus was reviewed directly.


Unknowns / Needs Verification

None identified. The PR is self-contained, well-tested, CI-green, and the implementation logic is verifiable from the diff alone.


Conclusion

This is a solid feature addition. The groomer now rewrites bad issue titles and enriches sparse issue bodies with appropriate guardrails. The dual-layer protection (LLM prompt rules + application-level shouldRewriteTitle/shouldEnrichBody checks) ensures safe, non-destructive mutations. Comprehensive tests cover all paths including dry-run and combined mutations. No blockers.

@joryirving joryirving merged commit 720795b into main Jun 29, 2026
6 checks passed
@joryirving joryirving deleted the feat/groomer-title-body-enrichment branch June 29, 2026 16:05
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.

2 participants