Initial commit: Inner OS v1

Full-stack inner development operating system built on Next.js 16 + Prisma 7 + PostgreSQL + OpenAI + Clerk.
Generates personalized daily mental training tasks, collects reflection, updates user state, and provides internal reward feedback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jackyu66git
2026-05-20 12:11:27 +08:00
co-authored by Claude Opus 4.6
commit cef29d40bd
49 changed files with 4723 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
import type { RewardEventType } from "@/generated/prisma/client";
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
export interface RewardEvent {
type: RewardEventType;
message: string;
}
interface RewardContext {
isFirstSession: boolean;
streakMilestone: boolean;
streakDays: number;
stageAdvanced: boolean;
newStage: number;
totalSessionsCompleted: number;
}
// ---------------------------------------------------------------------------
// Reward messages
// ---------------------------------------------------------------------------
const FIRST_SESSION_MESSAGES = [
"Your first practice is complete. This is where the path begins — not with a destination, but with a single step.",
"Day one. You didn't just think about it — you did it. That's the difference that makes all the difference.",
"Welcome to your practice. The door is open now. Walk through it again tomorrow.",
];
const STREAK_3_MESSAGES = [
"Three days in a row. A pattern is forming. Your mind is starting to expect this — that's the habit taking root.",
"Day three. The first two days were willpower. Today is the beginning of momentum.",
];
const STREAK_7_MESSAGES = [
"Seven days. A full week of showing up for yourself. Most people never make it this far. You did.",
"One week of daily practice. Your brain is literally rewiring. Neuroplasticity isn't a metaphor — it's what's happening right now.",
];
const STREAK_14_MESSAGES = [
"Two weeks. Research says it takes 21 days to form a habit — you're two-thirds there, and it already feels different, doesn't it?",
"Fourteen consecutive days. You're not 'trying to meditate' anymore. You're someone who practices. The identity has shifted.",
];
const STREAK_30_MESSAGES = [
"Thirty days. A month of daily practice. Whatever you were before you started — anxious, scattered, reactive — you're becoming someone else now. Someone who can watch their own mind and choose.",
"One month. This isn't a streak anymore. It's a practice. It's part of who you are. The question is no longer 'will I practice today?' but 'when?'",
];
const STAGE_UP_MESSAGES: Record<number, string[]> = {
1: [
"You've reached the Foundation stage. The basics are in place. Now we build depth — longer sessions, subtler awareness.",
"Stage up: Foundation. You've moved from trying to training. The practice is becoming familiar territory.",
],
2: [
"Growing stage reached. Your consistency is solid and your awareness is sharpening. This is where practice starts to change how you move through the world.",
"Stage up: Growing. You're past the awkward beginner phase. Your sessions have texture and depth now.",
],
3: [
"Established. Fifteen sessions and strong consistency. Your inner world is becoming legible to you. This is emotional literacy in action.",
"Stage up: Established. Your practice has roots. What started as a daily exercise is becoming a way of being.",
],
4: [
"Advanced. This is rare territory. Most people never develop this level of inner awareness. Your practice now informs everything you do.",
"Stage up: Advanced. You're not just practicing awareness — you're living it. The boundary between 'practice' and 'life' is dissolving.",
],
};
const GENERIC_COMPLETION_MESSAGES = [
"Done. You showed up, you practiced, you reflected. That's the whole game — and you're playing it.",
"Practice complete. Notice how you feel right now compared to before. That shift is the point.",
"Another session in the books. Not every practice will feel profound — but every practice counts.",
"You did the work today. Not tomorrow, not 'when things calm down' — today. That's discipline, and discipline is self-love.",
"Session finished. Your future self — the one with more clarity, more calm, more choice — thanks you.",
];
// ---------------------------------------------------------------------------
// Reward generation
// ---------------------------------------------------------------------------
function pick<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
export function generateRewards(ctx: RewardContext): RewardEvent[] {
const rewards: RewardEvent[] = [];
// First session — highest priority reward
if (ctx.isFirstSession) {
rewards.push({
type: "first_session",
message: pick(FIRST_SESSION_MESSAGES),
});
// Also give a daily completion reward
rewards.push({
type: "daily_completion",
message: pick(GENERIC_COMPLETION_MESSAGES),
});
return rewards;
}
// Always give daily completion
rewards.push({
type: "daily_completion",
message: pick(GENERIC_COMPLETION_MESSAGES),
});
// Streak milestones (only one per session, highest applicable)
if (ctx.streakMilestone) {
if (ctx.streakDays === 30) {
rewards.push({ type: "streak_30", message: pick(STREAK_30_MESSAGES) });
} else if (ctx.streakDays === 14) {
rewards.push({ type: "streak_14", message: pick(STREAK_14_MESSAGES) });
} else if (ctx.streakDays === 7) {
rewards.push({ type: "streak_7", message: pick(STREAK_7_MESSAGES) });
} else if (ctx.streakDays === 3) {
rewards.push({ type: "streak_3", message: pick(STREAK_3_MESSAGES) });
}
}
// Stage advancement
if (ctx.stageAdvanced && ctx.newStage > 0) {
const messages = STAGE_UP_MESSAGES[ctx.newStage];
if (messages) {
rewards.push({ type: "stage_up", message: pick(messages) });
}
}
return rewards;
}
// ---------------------------------------------------------------------------
// Persist rewards to database
// ---------------------------------------------------------------------------
export async function persistRewards(
userId: string,
rewards: RewardEvent[],
prisma: { rewardEvent: { create: (args: { data: any }) => Promise<any> } }
): Promise<void> {
await Promise.all(
rewards.map((r) =>
prisma.rewardEvent.create({
data: {
userId,
type: r.type,
message: r.message,
},
})
)
);
}