feat(analytics): classify rejected recommendation outcomes#330
Open
bittoby wants to merge 1 commit into
Open
Conversation
|
Related Knowledge 1 document with suggested updates is ready for review. gittensory ArchitectureView Suggested Changes@@ -301,7 +301,7 @@
- **agentRuns** — Agent orchestration runs with objective and status ([src/db/schema.ts](https://github.com/JSONbored/gittensory/blob/f63f125e2126dc58ac5a63e88f4f33d1e13b2979/src/db/schema.ts#L408-L428))
- **agentActions** — Agent action recommendations with risk impact ([src/db/schema.ts](https://github.com/JSONbored/gittensory/blob/f63f125e2126dc58ac5a63e88f4f33d1e13b2979/src/db/schema.ts#L430-L457))
- **agentContextSnapshots** — Agent context with decision pack and signal snapshot IDs ([src/db/schema.ts](https://github.com/JSONbored/gittensory/blob/f63f125e2126dc58ac5a63e88f4f33d1e13b2979/src/db/schema.ts#L459-L474))
-- **agentRecommendationOutcomes** — Tracks deterministic recommendation outcome classifications (merged, closed, improved, accepted, ignored, stale) for agent actions, including target details (repo/PR/issue), confidence levels, and maintainer-lane flag. Indexed by action ID, actor/state, target, and maintainer-lane.
+- **agentRecommendationOutcomes** — Tracks deterministic recommendation outcome classifications (merged, closed, improved, accepted, rejected, ignored, stale) for agent actions, including target details (repo/PR/issue), confidence levels, source metadata (explicit or inferred), and maintainer-lane flag. Explicit outcomes (from direct user feedback) cannot be overwritten by later inferred outcomes. Indexed by action ID, actor/state, target, maintainer-lane, and (actor_login, source, updated_at).
- **githubAgentCommandAnswers** — Stores command invocations and responses from the GitHub agent (@gittensory), including repo, issue number, command name, request/response comment IDs, actor kind, and metadata. Indexed by (repo_full_name, issue_number) and (command, updated_at).
- **githubAgentCommandFeedback** — Records usefulness votes (thumbs-up/thumbs-down reactions) on command answers, with unique constraint on (answer_id, actor_hash) to deduplicate feedback per actor. Tracks vote, source (reaction or app feedback), actor kind, and links to github_agent_command_answers via foreign key. Indexed by (answer_id, actor_hash), (command, updated_at), and (repo_full_name, issue_number).
- **syncRuns** — Sync job execution tracking ([src/db/schema.ts](https://github.com/JSONbored/gittensory/blob/f63f125e2126dc58ac5a63e88f4f33d1e13b2979/src/db/schema.ts#L523-L533))
@@ -492,18 +492,21 @@
#### Recommendation Outcomes (`src/services/recommendation-outcomes.ts`)
-The recommendation outcome service evaluates the fate of agent action recommendations by matching them against later PR and issue activity. The `evaluateRecommendationOutcomes()` function fetches recent agent runs and contributor PR/issue history, then deterministically classifies each action into one of six outcome states:
+The recommendation outcome service evaluates the fate of agent action recommendations by matching them against later PR and issue activity. The `evaluateRecommendationOutcomes()` function fetches recent agent runs and contributor PR/issue history, then deterministically classifies each action into one of seven outcome states:
- **merged** — The recommended PR was merged after the recommendation.
- **closed** — The recommended PR was closed without merging, or the recommended issue was closed.
- **improved** — The recommended PR remains open but now has approval or clean mergeability evidence.
- **accepted** — Later cached activity matches the recommendation target (PR/issue created or updated).
+- **rejected** — Recommendation was explicitly rejected or dismissed through direct user feedback.
- **stale** — No activity past the stale-outcome window (default 14 days).
- **ignored** — No matching activity after the ignored-outcome window (default 7 days), but not yet stale.
+Each outcome record includes a `source` field that distinguishes between **explicit** and **inferred** outcomes. Explicit outcomes are derived from direct user feedback (e.g., thumbs-down reactions or explicit dismissal), while inferred outcomes are derived from PR/issue lifecycle events. Explicit outcomes are protected from later inferred lifecycle overwrite—once an outcome is marked as explicit, it cannot be replaced by an inferred classification.
+
The classification logic in `classifyRecommendationOutcome()` uses deterministic matching rules: exact target PR/issue match, linked issue match, or later repo activity. The `isMaintainerLane()` function identifies maintainer-lane outcomes by checking if the actor is the repo owner, or if the PR/issue has a maintainer-associated author association (OWNER, MEMBER, COLLABORATOR). Maintainer-lane outcomes are tracked but kept separate from public contributor feedback.
-The service persists outcome records to the `agentRecommendationOutcomes` table with confidence levels (high for exact matches, medium for partial matches, low for no-match). Aggregate feedback is consumed by the decision pack system to adjust priority scores and provide private feedback signals for contributor decisions and repo decision confidence/risk indicators.
+The service persists outcome records to the `agentRecommendationOutcomes` table with confidence levels (high for exact matches, medium for partial matches, low for no-match). Aggregate feedback is consumed by the decision pack system to adjust priority scores and provide private feedback signals for contributor decisions and repo decision confidence/risk indicators. Summary statistics track counts of explicit vs inferred outcomes in addition to state-based counts.
## Testing
✅ Accepted |
2f2ada8 to
545daa9
Compare
JSONbored
requested changes
Jun 3, 2026
Owner
JSONbored
left a comment
There was a problem hiding this comment.
@bittoby thanks, this is the right area for #302, but one behavior gap needs fixing.
A few notes:
- Explicit accepted vs rejected feedback is a good addition.
- The tests cover the explicit feedback path, but the summary output still needs to expose rejected outcomes consistently.
Required changes:
- Retitle the PR to a scoped Conventional Commit title, for example
feat(analytics): classify rejected recommendation outcomes. - Include
rejectedin the outcome state bucket output, not just the totals. - Check migration numbering against the other open analytics PRs before merge so we do not land colliding migration filenames.
Validation expected:
- Add or update a focused test proving rejected outcomes appear in the state bucket summary.
- Keep
npm run test:cigreen.
545daa9 to
bd647c1
Compare
bd647c1 to
3509a6f
Compare
Contributor
Author
|
@JSONbored I've updated. pls review again. |
JSONbored
requested changes
Jun 4, 2026
Owner
JSONbored
left a comment
There was a problem hiding this comment.
@bittoby this needs a migration sequencing cleanup.
A few notes:
- Explicit accepted/rejected recommendation outcomes are useful and the inferred-vs-explicit guard is the right behavior.
- The branch is clean at merge-tree level, but migration numbering is stale.
- Current
mainalready has0018_recommendation_outcome_surface_snapshot.sqland0019_product_usage_event_role.sql.
Required changes:
- Rebase onto current
main. - Renumber
migrations/0018_agent_recommendation_outcome_source.sqlto the next available migration. - Re-run schema and recommendation-outcome tests after renumbering.
Validation expected:
git diff --checknpm run typechecknpm run test:coverage
50a3afc to
b707bdc
Compare
Contributor
Author
|
@JSONbored I've addressed your feedback all. pls review again. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #302
rejected.explicitversusinferredsource.Scope
CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally; global coverage stays at or above 97% for lines, statements, functions, and branches (aim for 98%+ branch coverage locally so CI variance does not fail near the threshold)npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
npm run actionlintbecause this PR does not change GitHub Actions workflows.npm run test:workers,npm run build:mcp, andnpm run test:mcp-packbecause this PR does not change worker packaging or MCP behavior.npm audit --audit-level=moderate; no dependency changes were made.npm run test:coveragepassed with 64 files passed, 1 skipped, 835 tests passed, 1 skipped, and branch coverage at 97.12%.Safety
Notes
rejectedas a persisted recommendation outcome state.sourcemetadata forexplicitversusinferredrecommendation outcomes.openapi.jsonor the public UI/OpenAPI contract.