feat: expand outreach targeting and messaging

This commit is contained in:
jjbrunton committed 2026-08-10 17:31:05 +01:00
1 parent 7defff422d
commit d0a8bd0e2f
40 files changed
+890 -82

No files matched your search

+40
View File
@@ -109,3 +109,43 @@ describe('config route conversation kill controls', () => {
expect(config.conversations.aiReplyScreening.enabled).toBe(false);
});
});
describe('config route physique targeting', () => {
it('hot-updates and persists the image-candidate score range', async () => {
const { app, config, saved } = harness();
const targetingRef = config.reddit.physiqueTargeting;
const response = await request(app, '/api/config', {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
reddit: {
physiqueTargeting: { enabled: true, minScore: 3, maxScore: 7 },
},
}),
});
expect(response.status).toBe(200);
expect(config.reddit.physiqueTargeting).toBe(targetingRef);
expect(config.reddit.physiqueTargeting).toEqual({ enabled: true, minScore: 3, maxScore: 7 });
expect(saved.at(-1)?.reddit.physiqueTargeting).toEqual({ enabled: true, minScore: 3, maxScore: 7 });
});
it('rejects an inverted physique range without mutating configuration', async () => {
const { app, config, saved } = harness();
const response = await request(app, '/api/config', {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
reddit: {
physiqueTargeting: { enabled: true, minScore: 8, maxScore: 4 },
},
}),
});
expect(response.status).toBe(400);
expect(config.reddit.physiqueTargeting).toEqual({ enabled: false, minScore: 1, maxScore: 10 });
expect(saved).toHaveLength(0);
});
});
+25 -3
View File
@@ -20,7 +20,7 @@ afterEach(async () => {
});
describe('outreach route', () => {
it('publishes active candidates and queue outcomes without prepared message content', async () => {
it('publishes prepared candidate context without leaking worker lease internals', async () => {
const candidateQueue = {
getStats: vi.fn(() => ({
total: 9,
@@ -37,7 +37,22 @@ describe('outreach route', () => {
title: '[25F] Hello', url: 'https://i.redd.it/post-1.jpg', permalink: '/r/example/comments/post-1/hello/',
thumbnail: '', is_self: false, created_utc: 100, over_18: true, spoiler: false,
},
prepared: { generatedMessage: 'private prepared text' }, priority: 2, status: 'sending',
prepared: {
generatedMessage: 'Prepared opener for Alice',
imageAnalysis: 'VISIBLE_FACTS:\nBODY: VISIBLE - full-body pose',
detectedGender: 'female',
attractivenessScore: 68,
physiqueScore: 6,
physiqueTargeting: { enabled: true, minScore: 4, maxScore: 7 },
sourceImageUrl: 'https://i.redd.it/post-1.jpg',
strategyId: 'direct-observation',
experimentId: 'strategies:direct-observation:abc123',
promptVersion: 'abc123',
selectionReason: 'exploit',
modelId: 'example/image-model',
toneId: 'direct',
scripted: false,
}, priority: 2, status: 'sending',
discoveredAt: 1_000, updatedAt: 2_000, availableAt: 2_000,
leaseOwner: 'worker-secret', leaseExpiresAt: 3_000, assignedAccountId: 'account-a',
attemptCount: 2, lastError: null,
@@ -64,9 +79,16 @@ describe('outreach route', () => {
postId: 'post-1', status: 'sending', hasPreparedMessage: true,
postUrl: 'https://www.reddit.com/r/example/comments/post-1/hello/',
owner: { accountId: 'account-a', redditUsername: 'operator' },
preparation: {
message: 'Prepared opener for Alice',
attractivenessScore: 68,
physiqueScore: 6,
physiqueTargeting: { enabled: true, minScore: 4, maxScore: 7 },
sourceImageUrl: 'https://i.redd.it/post-1.jpg',
strategyId: 'direct-observation',
},
}],
});
expect(JSON.stringify(body)).not.toContain('private prepared text');
expect(JSON.stringify(body)).not.toContain('worker-secret');
});