Below the human bar by 7 points.
Software Developers · O*NET task 21670 · 9 instances × 3 runs · release 2026-08
Success
93%
Runs passed
25/27
Cost per fix
$0.29
Time per fix
19s
Gap vs human
-7 pts
| Test subject | Minds, open-source social platform, 10+ year Angular codebase, public git history |
| Instance selection | 2,704 merged tickets → 45 ship a runnable test → 9 validated red-to-green for this pilot |
| Resolve criterion | the ticket's own test fails on the bug and passes on the fix, with the existing suite still green; executed, never judged |
| Repetitions | 3 independent runs per ticket per configuration, 27 runs per configuration |
| Model | Claude Opus in the three structure configurations; GPT-5.5 and Gemini 3.1 Pro run the identical one-shot protocol (August 2026 rerun on the same instance set) |
| AI cost basis | token list-price estimate per fix |
| Human baseline basis | success: the shipped fixes (measured). Time and cost: inferred from 2–4h at $75–100/h; not measured |
| Run window | August 2026 |
| Population | well-specified, test-backed, buildable bugs in one Angular codebase; not software bugs in general |
| Resolve | passes the team's own test; a strong proxy for correct, not a proof of it |
| Localization | the agent is handed the right files; real work includes finding the fault |
| Cost and baseline | AI cost is a token list-price estimate; the human figure is inferred, not measured |
| Sample | a 9-bug pilot; production accuracy needs more cases and more repetitions for tighter confidence |
Open any instance for the complete evidence: the ticket as written, the test that judges it, and the exact patch this configuration produced beside the patch the human team shipped. Every patch is checksummed.
base f1e8f68baa0c · test: src/app/modules/media/components/audio/services/audio-player.service.spec.ts · files changed: src/app/modules/media/components/audio/services/audio-player.service.ts · Fix audio pause events triggering on component destroy front#6219
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests https://gitlab.com/minds/front/-/issues/6219 ### Summary of Changes Fix audio pause events triggering on component destroy. ### Testing Considerations 1. Go to a feed with audio 2. Go off the feed 3. Check there are no events in Posthog (may be a delay) 4. Go to a feed with audio 5. Play and pause some audio 6. Check the events appear in Posthog. ### Deployment Considerations Standard deployment. ### Regression Scope - Audio analytics. - Player pausing. ### Platform Affected (web, mobile, etc) …
THIS CONFIGURATION’S PATCH · sha c4d2d54c666a · 3/3 · identical to the shipped human fix, same checksum
--- a/src/app/modules/media/components/audio/services/audio-player.service.ts+++ b/src/app/modules/media/components/audio/services/audio-player.service.ts@@ -145,6 +145,9 @@ * @returns { void } */ public pause(): void {+ if (!this.isActivePlayer || !this.playing$.getValue()) {+ return;+ } this.globalAudioPlayerService.pause(); this.trackPauseEvent(); }
AI QUALITY JUDGE · CLAUDE
–The patch is identical to the fix the human team shipped, byte for byte. Same checksum.
base c52c269ca9cd · test: src/app/common/services/group-membership.service.spec.ts · files changed: src/app/common/services/group-membership.service.ts · Fix joining a group by invite when already on group page front#6202
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests front#6202 ### Summary of Changes Fixes an issue wherein when a user is ALREADY on a group page, and accepts a group invite notification, the group does not automatically reload. ### Testing Considerations - [x] When on a group page and accepting an invite to the same group, the group is reloaded, with me in a joined state. - [x] When on another page and accepting an invite, I am navigated to the group in a joined state. ### Deployment Considerations Standard deployment. ### Regression Scope Grou …
THIS CONFIGURATION’S PATCH · sha ba2ee05be65a · 3/3
--- a/src/app/common/services/group-membership.service.ts+++ b/src/app/common/services/group-membership.service.ts@@ -166,12 +166,19 @@ ); } - // only navigate if requested, and the user is not already on the page.- if (- groupJoinOptions?.navigateOnSuccess &&- !this.router.url.includes(`/group/${groupGuid}`)- ) {- this.router.navigateByUrl(`/group/${groupGuid}`);+ // navigate to the group if requested.+ if (groupJoinOptions?.navigateOnSuccess) {+ const groupUrl = `/group/${groupGuid}`;++ if (this.router.url.includes(groupUrl)) {+ // already on the group page - force a reload by+ // navigating away and back.+ this.router+ .navigateByUrl('/', { skipLocationChange: true })+ .then(() => this.router.navigateByUrl(groupUrl));+ } else {+ this.router.navigateByUrl(groupUrl);+ } } return; }
THE HUMAN TEAM’S PATCH · sha b1fd985b3d88 · shipped
--- a/src/app/common/services/group-membership.service.ts+++ b/src/app/common/services/group-membership.service.ts@@ -167,11 +167,18 @@ } // only navigate if requested, and the user is not already on the page.- if (- groupJoinOptions?.navigateOnSuccess &&- !this.router.url.includes(`/group/${groupGuid}`)- ) {- this.router.navigateByUrl(`/group/${groupGuid}`);+ if (groupJoinOptions?.navigateOnSuccess) {+ if (!this.router.url.includes(`/group/${groupGuid}`)) {+ this.router.navigateByUrl(`/group/${groupGuid}`);+ } else {+ // Force a route refresh if the user is already on the page.+ const currentUrl: string = this.router.url;+ this.router+ .navigateByUrl('/', { skipLocationChange: true })+ .then(() => {+ this.router.navigateByUrl(currentUrl);+ });+ } } return; }
AI QUALITY JUDGE · CLAUDE
–Passed all three runs, with the same idea as the human team: if the user is already on the group page, hop away and back to force a reload.
–The code differs only in small ways, like variable names and the order of the branches. The behavior is the same.
base 4ba331e9a767 · test: src/app/modules/groups/v2/invite/invite.component.spec.ts · files changed: src/app/modules/groups/v2/invite/invite.component.ts · Fix group invite form #6190
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests Closes https://gitlab.com/minds/front/-/issues/6190 ### Summary of Changes Fix issue with group invite form preventing multiple members from being invited in a row. ### Testing Considerations - [x] I can invite a user that I'm subscribed to by clicking their row from the search bar. - [x] I can invite a second user that I'm subscribed to by clicking their row from the search bar. - [x] I can invite a user that I'm subscribed to by typing their name into the search bar and clicking submit without clic …
THIS CONFIGURATION’S PATCH · sha 5677553dddd4 · 3/3
--- a/src/app/modules/groups/v2/invite/invite.component.ts+++ b/src/app/modules/groups/v2/invite/invite.component.ts@@ -19,7 +19,8 @@ EntityResolverService, EntityResolverServiceOptions, } from '../../../../common/services/entity-resolver.service';-import { Subscription, distinctUntilChanged, switchMap } from 'rxjs';+import { Subscription, debounceTime, distinctUntilChanged, of, switchMap } from 'rxjs';+import { ToasterService } from '../../../../common/services/toaster.service'; import { MindsGroup } from '../group.model'; /**@@ -68,12 +69,13 @@ public service: GroupInviteService, private fb: UntypedFormBuilder, private entityResolverService: EntityResolverService,- private changeDetector: ChangeDetectorRef+ private changeDetector: ChangeDetectorRef,+ private toasterService: ToasterService ) {} ngOnInit(): void { this.formGroup = this.fb.group({- username: [+ user: [ '', { validators: [Validators.required],@@ -83,19 +85,21 @@ }); this.subscriptions.push(- this.formGroup.controls.username.valueChanges+ this.formGroup.controls.user.valueChanges .pipe(+ debounceTime(200), distinctUntilChanged(),- switchMap((username: string) => {- if (username === '') {+ switchMap((user: string | MindsUser) => {+ if (!user) { this.invitee = null;- this.refreshEligibilityValidator();- return;+ return of(null);+ } else if (typeof user === 'object') {+ return of(user); } else { this.inProgress = true; let options = new EntityResolverServiceOptions(); options.refType = 'username';- options.ref = username;+ options.ref = user; return this.entityResolverService.get$<MindsUser>(options); }@@ -104,7 +108,7 @@ .subscribe((user) => { this.inProgress = false; this.invitee = user;- this.refreshEligibilityValidator();+ this.changeDetector.detectChanges(); }) ); }@@ -136,19 +140,31 @@ * Submit an invitation to the selected user */ async onSubmit(): Promise<void> {+ if (!this.invitee) {+ console.error('No invitee selected');+ return;+ }++ if (!this.invitee.subscriber) {+ this.toasterService.error(+ 'You can only invite users who are subscribed to you'+ );+ return;+ }+ await this.service.invite(this.invitee); // Reset the form this.invitee = null; this.formGroup.reset( {- username: '',+ user: null, }, { emitEvent: false, } );- this.formGroup.get('username').setErrors(null);+ this.formGroup.get('user').setErrors(null); this.formGroup.markAsPristine(); this.changeDetector.detectChanges(); }
THE HUMAN TEAM’S PATCH · sha c887764c12c6 · shipped
--- a/src/app/modules/groups/v2/invite/invite.component.ts+++ b/src/app/modules/groups/v2/invite/invite.component.ts@@ -8,19 +8,18 @@ import { GroupInviteService } from './invite.service'; import { MindsUser } from '../../../../interfaces/entities'; import {- AbstractControl, UntypedFormBuilder, UntypedFormGroup,- ValidationErrors,- ValidatorFn, Validators, } from '@angular/forms';+import { debounceTime, of, Subscription, switchMap } from 'rxjs';+import { MindsGroup } from '../group.model';+import { AutoCompleteEntityTypeEnum } from '../../../../common/components/forms/autocomplete-entity-input/autocomplete-entity-input.component';+import { ToasterService } from '../../../../common/services/toaster.service'; import { EntityResolverService, EntityResolverServiceOptions, } from '../../../../common/services/entity-resolver.service';-import { Subscription, distinctUntilChanged, switchMap } from 'rxjs';-import { MindsGroup } from '../group.model'; /** * Invite modal component@@ -37,6 +36,10 @@ providers: [GroupInviteService], }) export class GroupInviteComponent implements OnInit, OnDestroy {+ /** Enum for use in template. */+ protected readonly AutoCompleteEntityTypeEnum: typeof AutoCompleteEntityTypeEnum =+ AutoCompleteEntityTypeEnum;+ /** * Modal save handler */@@ -67,13 +70,14 @@ constructor( public service: GroupInviteService, private fb: UntypedFormBuilder,- private entityResolverService: EntityResolverService,- private changeDetector: ChangeDetectorRef+ private changeDetector: ChangeDetectorRef,+ private toasterService: ToasterService,+ private entityResolverService: EntityResolverService ) {} ngOnInit(): void { this.formGroup = this.fb.group({- username: [+ user: [ '', { validators: [Validators.required],@@ -83,28 +87,28 @@ }); this.subscriptions.push(- this.formGroup.controls.username.valueChanges- .pipe(- distinctUntilChanged(),- switchMap((username: string) => {- if (username === '') {- this.invitee = null;- this.refreshEligibilityValidator();- return;- } else {- this.inProgress = true;+ this.formGroup+ .get('user')+ .valueChanges.pipe(+ debounceTime(200),+ switchMap((user: string | MindsUser) => {+ // fallback for if the user does not click on the autocomplete result.+ if (typeof user === 'string') { let options = new EntityResolverServiceOptions(); options.refType = 'username';- options.ref = username;-+ options.ref = user; return this.entityResolverService.get$<MindsUser>(options); }+ return of(user); }) )- .subscribe((user) => {+ .subscribe((user: MindsUser): void => {+ if (!user) {+ this.invitee = null;+ return;+ } this.inProgress = false; this.invitee = user;- this.refreshEligibilityValidator(); }) ); }@@ -136,19 +140,31 @@ * Submit an invitation to the selected user */ async onSubmit(): Promise<void> {- await this.service.invite(this.invitee);+ if (!this.invitee) {+ console.error('No invitee selected');+ return;+ }++ if (!this.invitee.subscriber) {+ this.toasterService.error(+ 'You can only invite users who are subscribed to you'+ );+ return;+ }++ this.service.invite(this.invitee); // Reset the form this.invitee = null; this.formGroup.reset( {- username: '',+ user: null, }, { emitEvent: false, } );- this.formGroup.get('username').setErrors(null);+ this.formGroup.get('user').setErrors(null); this.formGroup.markAsPristine(); this.changeDetector.detectChanges(); }@@ -161,42 +177,4 @@ public isModerator(group: MindsGroup): boolean { return group['is:owner'] || group['is:moderator']; }-- /**- * Ensure we are not trying to invite someone who is not a subscriber- */- private eligibilityValidator(): ValidatorFn {- return (control: AbstractControl): ValidationErrors | null => {- if (this.invitee && !this.invitee.subscriber) {- return {- eligibilityInvalid: true,- };- }- };- }-- private latestEligibilityValidator: ValidatorFn = null;-- private refreshEligibilityValidator(): void {- this.removeEligibilityValidator();-- this.latestEligibilityValidator = this.eligibilityValidator();- this.formGroup.controls.username?.addValidators(- this.latestEligibilityValidator- );-- this.formGroup.controls.username?.updateValueAndValidity({- emitEvent: false,- });-- this.formGroup.controls.username?.markAsDirty();-- this.changeDetector.detectChanges();- }-- private removeEligibilityValidator(): void {- this.formGroup.controls.username?.removeValidators(- this.latestEligibilityValidator- );- } }
AI QUALITY JUDGE · CLAUDE
–Passed all three runs, moving in the same direction as the human team: it renames the field, waits briefly before looking a user up, and adds the error message service.
–It kept the old search box where the humans installed a smarter one. The test passes either way, so this is a smaller change with the same tested behavior.
base 3c8f56a702df · test: src/app/common/components/chatwoot-widget/chatwoot-widget.component.spec.ts · files changed: src/app/common/components/chatwoot-widget/chatwoot-widget.component.ts · Fix Chatwoot emails minds#4948
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests minds#4948 ### Summary of Changes Fixes an issue where Chatwoot user held locally is out of sync with Chatwoot servers, by resetting the user if one is not set locally on bubble click. ### Testing Considerations Note that email will NOT be passed to chatwoot if a user already exists with that email. I strongly recommend using plus addressing (e.g. example+chatwoot1@minds.com) to give your account a new email to test - and you can delete the contact from Chatwoot to retest. Between tests you want to …
THIS CONFIGURATION’S PATCH · sha 6d1d347bd674 · 3/3
--- a/src/app/common/components/chatwoot-widget/chatwoot-widget.component.ts+++ b/src/app/common/components/chatwoot-widget/chatwoot-widget.component.ts@@ -205,9 +205,41 @@ private onBubbleClick(event: Event): void { const currentChatwootUser = this.window.$chatwoot?.user; - if (currentChatwootUser && !currentChatwootUser?.email) {+ if (!currentChatwootUser && this.session.isLoggedIn()) {+ // local user is out of sync with chatwoot - reset and set fresh.+ this.resetAndSetUser(); // async+ } else if (currentChatwootUser && !currentChatwootUser?.email) { this.patchEmail(); // async }+ }++ /**+ * Reset chatwoot and set the currently logged in user, including their+ * email address. Used when the locally held chatwoot user is out of sync+ * with the chatwoot servers.+ * @returns { Promise<void> }+ */+ private async resetAndSetUser(): Promise<void> {+ const loggedInUser: MindsUser = this.session.getLoggedInUser();++ if (!loggedInUser) {+ return;+ }++ const emailAddress: string =+ await this.emailAddressService.getEmailAddress();++ const identifierHash: string = await this.getIdentifierHash();+ const avatarUrl: string = this.userAvatar.getSrc();++ this.resetChatwoot();++ this.window.$chatwoot.setUser(loggedInUser.guid, {+ name: `@${loggedInUser.username}`,+ identifier_hash: identifierHash,+ avatar_url: avatarUrl,+ email: emailAddress,+ }); } /**
THE HUMAN TEAM’S PATCH · sha d695d452d187 · shipped
--- a/src/app/common/components/chatwoot-widget/chatwoot-widget.component.ts+++ b/src/app/common/components/chatwoot-widget/chatwoot-widget.component.ts@@ -174,15 +174,19 @@ /** * Sets user for widget.+ * @param { { email?: string } } additionalProps - additional properties to set on the user. * @returns { Promise<void> } */- private async setUser(): Promise<void> {+ private async setUser(+ additionalProps: { email?: string } = {}+ ): Promise<void> { const user: MindsUser = this.session.getLoggedInUser(); this.window.$chatwoot.setUser(user.guid, { name: `@${user.username}`, identifier_hash: await this.getIdentifierHash(), avatar_url: this.userAvatar.getSrc(),+ ...additionalProps, }); } @@ -202,11 +206,22 @@ * @param { Event } event - click event. * @returns { void } */- private onBubbleClick(event: Event): void {+ private async onBubbleClick(event: Event): Promise<void> {+ if (!this.session.isLoggedIn()) {+ return;+ }+ const currentChatwootUser = this.window.$chatwoot?.user; - if (currentChatwootUser && !currentChatwootUser?.email) {- this.patchEmail(); // async+ if (!currentChatwootUser) {+ // clear any lingering state as it's gotten out of sync.+ this.resetChatwoot();++ // set the user again with the email address.+ this.setUser({ email: await this.emailAddressService.getEmailAddress() });+ return;+ } else if (!currentChatwootUser?.email) {+ this.patchEmail(); } }
AI QUALITY JUDGE · CLAUDE
–Passed all three runs. Same result as the human fix: when the chat widget loses track of the user, reset it and register the user again, this time with their email attached.
–The humans folded this into the existing registration function; the agent wrote a new helper that does the same steps.
base c7a590bf3c58 · test: src/app/modules/auth/reset-password-modal/forms/request/request.component.spec.ts · files changed: src/app/modules/auth/reset-password-modal/forms/request/request.component.ts · Fix incorrect site name in tenant forgot password flow #6209
THE TICKET, AS WRITTEN
<!---
Please read this!
The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done
--->
### Ticket(s) / Related Merge Requests
#6209
### Summary of Changes
The incorrect site name is used in the forgot password flow for Tenants. The text is hard-coded to be `Minds` when it should use the `site_name`.
### Testing Considerations
Bound to https://fausto.oke.minds.io
#### Tenant
- [ ] After entering username in forgot password, the subsequent panel gives me the option to `Log in to {{tenant site name}}`.
#### Non-tenant
- [ ] After entering username in forgot password, the subsequent panel gives me the option to `Log in to …THIS CONFIGURATION’S PATCH · sha a3bbe90e0143 · 3/3
--- a/src/app/modules/auth/reset-password-modal/forms/request/request.component.ts+++ b/src/app/modules/auth/reset-password-modal/forms/request/request.component.ts@@ -12,6 +12,7 @@ ResetPasswordModalPanel, ResetPasswordModalService, } from '../../reset-password-modal.service';+import { SITE_NAME } from '../../../../../common/injection-tokens/common-injection-tokens'; /** * Form for the user to submit a request for a@@ -35,10 +36,13 @@ protected secondsBetweenResends: number; + protected readonly loginToText: string = `to ${this.siteName}`;+ constructor( protected toaster: ToasterService, private formBuilder: FormBuilder,- protected service: ResetPasswordModalService+ protected service: ResetPasswordModalService,+ @Inject(SITE_NAME) protected siteName: string ) {} ngOnInit(): void {
THE HUMAN TEAM’S PATCH · sha 6909acfedf5c · shipped
--- a/src/app/modules/auth/reset-password-modal/forms/request/request.component.ts+++ b/src/app/modules/auth/reset-password-modal/forms/request/request.component.ts@@ -12,6 +12,7 @@ ResetPasswordModalPanel, ResetPasswordModalService, } from '../../reset-password-modal.service';+import { SITE_NAME } from '../../../../../common/injection-tokens/common-injection-tokens'; /** * Form for the user to submit a request for a@@ -34,12 +35,16 @@ protected canSendEmail: boolean = true; protected secondsBetweenResends: number;+ protected readonly loginToText: string; constructor( protected toaster: ToasterService, private formBuilder: FormBuilder,- protected service: ResetPasswordModalService- ) {}+ protected service: ResetPasswordModalService,+ @Inject(SITE_NAME) protected siteName: string+ ) {+ this.loginToText = $localize`:@@RESET_PASSWORD__EMAIL_SENT_PANEL__LOGIN_LINK__TO_SITE:to ${this.siteName || 'Minds'}:site name:`;+ } ngOnInit(): void { // Always show the first panel on load
AI QUALITY JUDGE · CLAUDE
–Passed all three runs with the same core fix as the human team: pull in the site's name and build the 'log in to …' text from it.
–The human version also wraps the text for translation and falls back to 'Minds' if no name is set. The test checks neither, so both versions pass.
base 5420b630517a · test: src/app/modules/media/components/video-player/scrollaware-player.component.spec.ts · files changed: src/app/modules/media/components/video-player/scrollaware-player.component.ts · Fix videos in modals starting muted #6215
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests #6215 ### Summary of Changes When a video is opened in a modal, it was forcing the play of the video MUTED, when the autoplay setting was on. This change will set it to unmuted when opened in a modal, with autoplay on. ### Testing Considerations - [x] Autoplay ON; videos on SEPs open in a modal and autoplay and autoplay unmuted - [x] Autoplay ON; videos in narrow viewports open in a modal and autoplay unmuted - [x] Autoplay OFF; videos open in a modal, and upon pressing play are unmuted (this change …
THIS CONFIGURATION’S PATCH · sha 1e89302756f8 · 3/3
--- a/src/app/modules/media/components/video-player/scrollaware-player.component.ts+++ b/src/app/modules/media/components/video-player/scrollaware-player.component.ts@@ -92,7 +92,7 @@ !user.disable_autoplay_videos ) { this.player.play({- muted: true,+ muted: !this.isModal, hideControls: true, }); this.detectChanges();
THE HUMAN TEAM’S PATCH · sha c9faa10e46da · shipped
--- a/src/app/modules/media/components/video-player/scrollaware-player.component.ts+++ b/src/app/modules/media/components/video-player/scrollaware-player.component.ts@@ -61,7 +61,7 @@ } ngOnDestroy() {- this.scrollSubscription.unsubscribe();+ this.scrollSubscription?.unsubscribe(); } ngAfterViewInit() {@@ -92,7 +92,7 @@ !user.disable_autoplay_videos ) { this.player.play({- muted: true,+ muted: !this.isModal, hideControls: true, }); this.detectChanges();
AI QUALITY JUDGE · CLAUDE
–Passed all three runs with the exact same one-line fix the humans shipped: only mute the video when it is not in the pop-up viewer.
–The only difference from the shipped patch is a small safety guard the humans added elsewhere, outside the tested behavior.
base 5420b630517a · test: src/app/modules/newsfeed/single/single.component.spec.ts · files changed: src/app/modules/newsfeed/single/single.component.ts · Fix audio og:image's front#6216
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests front#6216 ### Summary of Changes Change og:image for audio to be the audio thumbnail for an activity. ### Testing Considerations - [x] With a thumbnail, og:image is the audio thumbnail. - [x] Without a thumbnail, og:image is the default audio thumbnail. ### Deployment Considerations Standard deployment. ### Regression Scope Minor, impacts audio SEP SEO. ### Platform Affected (web, mobile, etc) Web. ### Developer Testing Completed Manual, unit (jasmine / karma). ### Screenshots / Screen Reco …
THIS CONFIGURATION’S PATCH · sha 973a51c74a96 · 2/3
--- a/src/app/modules/newsfeed/single/single.component.ts+++ b/src/app/modules/newsfeed/single/single.component.ts@@ -290,6 +290,10 @@ ? activity.custom_data[0]['src'] : activity.thumbnail_src; + if (activity.custom_type === 'audio') {+ thumbnailSrc = activity.custom_data?.['thumbnail_src'];+ }+ if (activity.site_membership && activity.paywall_thumbnail) { thumbnailSrc = this.siteUrl +
THE HUMAN TEAM’S PATCH · sha 9d527e3b8988 · shipped
--- a/src/app/modules/newsfeed/single/single.component.ts+++ b/src/app/modules/newsfeed/single/single.component.ts@@ -288,7 +288,9 @@ thumbnailSrc = activity.custom_type === 'batch' ? activity.custom_data[0]['src']- : activity.thumbnail_src;+ : activity.custom_type === 'audio'+ ? activity.custom_data['thumbnail_src']+ : activity.thumbnail_src; if (activity.site_membership && activity.paywall_thumbnail) { thumbnailSrc =
AI QUALITY JUDGE · CLAUDE
–Passed two runs of three, one of the two flaky cases in the study. It fixes the same spot the humans fixed: teach the thumbnail picker where audio posts keep their image.
–The humans folded audio into the existing selection logic; the agent bolted an extra step on after it. Close to the shipped fix, just less reliable across runs.
base 4cb39d190eab · test: src/app/modules/payments/select-card/select-card.component.spec.ts · files changed: src/app/modules/payments/new-card-modal/new-card-modal.component.ts, src/app/modules/payments/select-card/select-card.component.ts · Fix add card loop minds#5179
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests minds#5179 ### Summary of Changes Fix loop when adding new card where Stripe window keeps opening. Additionally fixes issue where upon closing window to add a new card, the window was being automatically reopened. ### Testing Considerations Bound to https://olivia.oke.minds.io/ - [x] When adding a new card, when you are back on Minds, the card is loaded in and Stripe does not reopen. - [x] When deciding not to add a new card on Stripe, when you are back on Minds, Stripe isn't automatically reopened. …
THIS CONFIGURATION’S PATCH · sha a11e0e86809f · 2/3
--- a/src/app/modules/payments/select-card/select-card.component.ts+++ b/src/app/modules/payments/select-card/select-card.component.ts@@ -107,12 +107,18 @@ async onAddNewCard(): Promise<void> { const modal = this.modalService.present(NewCardModalComponent, { data: {- onComplete: () => {+ onComplete: async () => {+ this.paymentMethodId = ''; this.selected.next('');- this.loadCards();+ await this.loadCards(); modal.close(); },- },+ onDismissIntent: () => {+ this.paymentMethodId = '';+ this.selected.next('');+ modal.close();+ },+ } as any, }); }
THE HUMAN TEAM’S PATCH · sha 28a32961cdde · shipped
--- a/src/app/modules/payments/new-card-modal/new-card-modal.component.ts+++ b/src/app/modules/payments/new-card-modal/new-card-modal.component.ts@@ -23,12 +23,10 @@ /** * Modal options- *- * @param onComplete- * @param onDismissIntent- * @param defaults+ * @param { any } opts - modal options.+ * @returns { void } */- setModalData({ onComplete, onDismissIntent }) {+ setModalData({ onComplete, onDismissIntent }: any): void { this.onComplete = onComplete || (() => {}); this.onDismissIntent = onDismissIntent || (() => {}); }--- a/src/app/modules/payments/select-card/select-card.component.ts+++ b/src/app/modules/payments/select-card/select-card.component.ts@@ -108,9 +108,15 @@ const modal = this.modalService.present(NewCardModalComponent, { data: { onComplete: () => {+ this.paymentMethodId = ''; this.selected.next(''); this.loadCards();- modal.close();+ modal?.close();+ },+ onDismissIntent: () => {+ this.paymentMethodId = '';+ this.selected.next('');+ modal?.close(); }, }, });
AI QUALITY JUDGE · CLAUDE
–Passed two of three runs, the other flaky case in the study. Behavior matches the human fix: both close paths clear the card, clear the selection, and close the window.
–Small differences in how it waits for the card list to reload made it unreliable on one run. The workflow's version of the same fix held on all three.
base d67c453047e3 · test: src/app/modules/about/product-pages/components/common/button/button.component.spec.ts · files changed: src/app/modules/about/product-pages/components/common/button/button.component.ts, src/app/modules/multi-tenant-network/admin-console/tabs/billing/billing.component.ts · [front] Fix upgrading when domain is misconfigured minds#5113
THE TICKET, AS WRITTEN
<!--- Please read this! The Definition of Done (DoD) can be found at https://developers.minds.com/docs/handbook/how-we-work/#definition-of-done ---> ### Ticket(s) / Related Merge Requests * Issue card: minds#5113 * Engine MR: https://gitlab.com/minds/engine/-/merge_requests/1742 ### Summary of Changes See engine MR.
THIS CONFIGURATION’S PATCH · sha acb337ef6ada · 3/3
--- a/src/app/modules/about/product-pages/components/common/button/button.component.ts+++ b/src/app/modules/about/product-pages/components/common/button/button.component.ts@@ -64,7 +64,10 @@ this.inProgress = true; // if there is a navigationUrl, navigate to it. if (Boolean(this.data.navigationUrl)) {- if (this.data.navigationUrl.startsWith('http')) {+ if (+ this.data.navigationUrl.startsWith('http') ||+ this.data.navigationUrl.startsWith('/api/')+ ) { window.open(this.data.navigationUrl, '_blank'); } else { this.router.navigateByUrl(this.data.navigationUrl);
THE HUMAN TEAM’S PATCH · sha 2dfc8f1f0d52 · shipped
--- a/src/app/modules/about/product-pages/components/common/button/button.component.ts+++ b/src/app/modules/about/product-pages/components/common/button/button.component.ts@@ -64,10 +64,17 @@ this.inProgress = true; // if there is a navigationUrl, navigate to it. if (Boolean(this.data.navigationUrl)) {- if (this.data.navigationUrl.startsWith('http')) {+ if (+ this.data.navigationUrl.startsWith('http') ||+ this.data.navigationUrl.startsWith('/api/')+ ) { window.open(this.data.navigationUrl, '_blank'); } else {- this.router.navigateByUrl(this.data.navigationUrl);+ try {+ await this.router.navigateByUrl(this.data.navigationUrl);+ } catch (e: unknown) {+ console.error(e);+ } } this.inProgress = false; return;--- a/src/app/modules/multi-tenant-network/admin-console/tabs/billing/billing.component.ts+++ b/src/app/modules/multi-tenant-network/admin-console/tabs/billing/billing.component.ts@@ -116,8 +116,7 @@ 'solid': true, 'rounded': null, 'navigationUrl':- siteUrl +- 'api/v3/multi-tenant/billing/upgrade?plan=team&period=' ++ '/api/v3/multi-tenant/billing/upgrade?plan=team&period=' + periodStr, 'stripeProductKey': 'networks:team', 'trialUpgradeRequest': null,@@ -154,8 +153,7 @@ 'solid': true, 'rounded': null, 'navigationUrl':- siteUrl +- 'api/v3/multi-tenant/billing/upgrade?plan=community&period=' ++ '/api/v3/multi-tenant/billing/upgrade?plan=community&period=' + periodStr, 'stripeProductKey': 'networks:community', 'trialUpgradeRequest': null,@@ -193,8 +191,7 @@ 'solid': true, 'rounded': null, 'navigationUrl':- siteUrl +- 'api/v3/multi-tenant/billing/upgrade?plan=enterprise&period=' ++ '/api/v3/multi-tenant/billing/upgrade?plan=enterprise&period=' + periodStr, 'stripeProductKey': 'networks:enterprise', 'trialUpgradeRequest': null,
AI QUALITY JUDGE · CLAUDE
–Passed all three runs with the exact same fix as the human team: treat links starting with /api/ like external links so the browser follows them. Identical to the workflow's patch, same checksum.
–The shipped human patch went two steps further, adding an error catch around navigation and fixing the link's address in a second file, both beyond what the test checks.
| Configuration | Success | Runs passed | Cost/fix | Time/fix |
|---|---|---|---|---|
| Human baseline | 100% | — | ~$225 est. | ~25 min est. |
| Diagnose → fix hand-off · Claude Opus › | 100% | 27/27 | $0.29 | 19s |
| Test-and-retry loop · Claude Opus · this page | 93% | 25/27 | $0.29 | 19s |
| GPT-5.5 › | 22% | 6/27 | $0.03 | 30s |
| Claude Opus › | 11% | 3/27 | $0.04 | 6s |
| Gemini 3.1 Pro › | 0% | 0/27 | $0.01 | 97s |
full dataset: /data/runs/21670-minds-bugfix.json · task instances are public materials (open-source Minds, public git history); anyone can rerun this run · quality-judge comments: a separate Claude pass reads the ticket and both patches; commentary only — the executed test scores the run · measured and published by Recursiv Labs as a working prototype; not an official SPARK AI or UC San Diego publication
Working prototype by Recursiv Labs · not an official SPARK AI or UC San Diego publication · Data · © 2026