Phase 5C Memory Compaction
Daily compaction deterministically turns reviewed/captured memory into versioned profiles, open loops, and daily context packs. It does not call models, create embeddings, enable retrieval, or expose public reads/writes.
Safety status
{safe.map(([label,value])=>- {label}: {value?"enabled":"disabled"}
)}
Internal job
POST /api/memory/jobs/daily-digest with Authorization: Bearer $PANDORA_INTERNAL_JOB_TOKEN.
{JSON.stringify({namespace:"real_life",dry_run:true,since:new Date(Date.now()-86400000).toISOString()},null,2)}Operator notes
- Keep model calls, embeddings, semantic retrieval, public read/write, and permanent auto-capture off.
- Run dry runs first, inspect profiles/open loops/context pack output, then run per namespace.
}
diff --git a/app/api/memory/jobs/daily-digest/route.ts b/app/api/memory/jobs/daily-digest/route.ts
new file mode 100644
index 0000000..c82333d
--- /dev/null
+++ b/app/api/memory/jobs/daily-digest/route.ts
@@ -0,0 +1,8 @@
+import { NextRequest, NextResponse } from "next/server";
+import { z } from "zod";
+import { resolvePandoraRuntimeSafetyConfig } from "@/lib/config/pandora-runtime-safety-config";
+import { createSupabaseBridgeAdminClient } from "@/lib/supabase/bridge-admin";
+import { runDailyMemoryCompaction } from "@/lib/services/memory-compaction-service";
+const schema=z.object({namespace:z.enum(["real_life","au"]),since:z.string().datetime().optional(),dry_run:z.boolean().optional(),user_id:z.string().min(1).optional()});
+function bearer(request:NextRequest){const [scheme,token]=(request.headers.get("authorization")??"").split(" "); return scheme?.toLowerCase()==="bearer"?token:undefined;}
+export async function POST(request:NextRequest){const token=process.env.PANDORA_INTERNAL_JOB_TOKEN; if(!token||bearer(request)!==token)return NextResponse.json({ok:false,blockers:["internal_job_token_required"]},{status:401}); const runtime=resolvePandoraRuntimeSafetyConfig(); if(!runtime.config.memoryDistillationEnabled)return NextResponse.json({ok:false,blockers:["memoryDistillationEnabled_disabled"],warnings:[],next_step:"Set PANDORA_ENABLE_MEMORY_DISTILLATION=true in a reviewed environment."},{status:403}); const parsed=schema.safeParse(await request.json().catch(()=>({}))); if(!parsed.success)return NextResponse.json({ok:false,blockers:["invalid_request"],issues:parsed.error.flatten()},{status:400}); const user_id=parsed.data.user_id??process.env.PANDORA_MEMORY_BRIDGE_USER_ID; if(!user_id)return NextResponse.json({ok:false,blockers:["job_user_id_required"],next_step:"Send user_id with the internal token or configure PANDORA_MEMORY_BRIDGE_USER_ID."},{status:400}); const result=await runDailyMemoryCompaction(createSupabaseBridgeAdminClient() as never,{user_id,namespace:parsed.data.namespace,since:parsed.data.since,dry_run:parsed.data.dry_run}); return NextResponse.json({ok:result.ok,namespace:result.namespace,dry_run:result.dry_run,daily_pack:result.daily_pack,updated_profiles:result.updated_profiles,opened_or_updated_loops:result.opened_or_updated_loops,warnings:result.warnings,blockers:result.blockers,next_step:result.next_step});}
diff --git a/docs/pandora-memory-autopilot.md b/docs/pandora-memory-autopilot.md
index 7878315..fb83e5e 100644
--- a/docs/pandora-memory-autopilot.md
+++ b/docs/pandora-memory-autopilot.md
@@ -55,3 +55,22 @@ Phase 5A is deterministic and keyword-based. It does not implement the future re
## Phase 5B Candidate Review
Phase 5A queues durable memory candidates automatically, but it does not make them permanent memory by default. Phase 5B adds the operator review console at `/admin/memory/candidates`, where Joven can approve, reject, edit, mark duplicate, or capture candidates. This keeps Pandora teachable: autopilot surfaces what might matter, while human review prevents noisy, sensitive, wrong, duplicate, or wrong-namespace items from polluting durable memory.
+
+## Phase 5C Daily Compaction
+
+Phase 5A queues candidates. Phase 5B reviews and captures candidates. Phase 5C compacts reviewed/captured memory into versioned profiles, open loops, and daily context packs. This is the deterministic compounding layer that lets Pandora improve over time without enabling model calls, embeddings, semantic retrieval, public reads, public writes, or permanent auto-capture.
+
+Recommended environment posture:
+
+```bash
+PANDORA_ENABLE_MEMORY_DISTILLATION=true
+PANDORA_INTERNAL_JOB_TOKEN=