app/lib/social/routine.server.ts
30 lines and 2 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| routineConfig | 14 to 19 | 5 | 100% | OkCRAP 5 | No data: mutation testing has not run on this repo yet |
| routinePrompt | 22 to 34 | 4 | 88% | OkCRAP 4 | No data: mutation testing has not run on this repo yet |
Imports
It imports no other module of this repo. Imported by app/lib/social/queue.server.ts, app/routes/social.tsx.
Source
// The Claude Code routine that drafts brand posts when no session drafted them ahead (design decision
// 5, second step). Carrel only fires it: a POST to the routine's API trigger with the waiting items
// as text. The routine runs on Dustin's subscription, drafts each post in the account's voice, and
// stores it through Carrel's MCP tools; Carrel sends it later with no AI at runtime. No API key and no
// subscription token is ever stored: the trigger token reaches this one routine and can read nothing.
//
// The fire itself, and the check that the URL is Anthropic's, are site-runtime's ./routine, shared with
// germomics' drafting routine.
import { routineConfig as checkRoutine, type RoutineConfig } from "@dustinedwards/site-runtime/routine";
export { fireRoutine, type FireResult } from "@dustinedwards/site-runtime/routine";
export function routineConfig(env: Env): RoutineConfig | { missing: string } {
const url = env.SOCIAL_ROUTINE_URL?.trim() ?? "";
const token = env.SOCIAL_ROUTINE_TOKEN?.trim() ?? "";
if (!url || !token) return { missing: "SOCIAL_ROUTINE_URL and SOCIAL_ROUTINE_TOKEN are not both set." };
return checkRoutine(url, token);
}
/** What the routine is told: the items waiting, per account, and how to store a draft for each. */
export function routinePrompt(items: { eventId: number; account: string; platform: string; voiceGuide: string; title: string; url: string; summary: string }[]): string {
const lines = [
"Draft one social post for each item below, in that account's voice, and store each with Carrel's carrel_draft_social_post tool (event id, text). Do not post anything and do not reply to anyone.",
"Rules: the post announces the item and links it; plain, direct sentences; no AI-writing tells; no em dashes; nothing the item does not say.",
"",
];
for (const i of items) {
lines.push(`- event ${i.eventId} for ${i.account} (${i.platform}): "${i.title}" ${i.url}`);
if (i.summary) lines.push(` Dustin's summary: ${i.summary}`);
if (i.voiceGuide) lines.push(` Voice: ${i.voiceGuide}`);
}
return lines.join("\n");
}