MolinoPro

20260422_readmeMLV

Master Codebase Guidebook
Markdown + HTML Dev-Docs Renderer - Frontend Client Module

Default Index
Open README.md
Root: README.mdarchive
Milestones

✅ EXECUTION PLAN — REDUCED (ACTIONABLE)

🔴 STEP 0 — FREEZE (DO FIRST)

H1NO CHANGES TO:
  • Prisma schema
  • Folio engine
  • Pagination
  • DocumentPage
  • ensureBlocks

🟢 STEP 1 — MODE CLEANUP (30 min)

1.1 Create canonical type

// app/assistant/modes/types.ts export type AIMode = "general" | "coaching";

1.2 Update ALL usage

Replace everywhere:

type Mode = "general" | "dev" | "mlv" | "autopilot" | ...

WITH:

import type { AIMode } from "@/app/assistant/modes/types";

1.3 Fix AssistantContext

const VALID_MODES: AIMode[] = ["general", "coaching"];

1.4 Fix UI (document ChatPanel)

REMOVE buttons:

❌ dev ❌ mlv ❌ feature ❌ docs ❌ autopilot

KEEP:

✔ general ✔ coaching

✅ STOP CHECK

✔ only 2 modes visible ✔ no TS errors

🟢 STEP 2 — AI WRITE FIX (CRITICAL)

2.1 NEVER WRITE TITLE

title: data.title ?? "Untitled Document",

2.2 FORCE TOP SURFACE ONLY

Replace NON-MLV block:

nextTopSurfaceSection = chunks.map((chunk) => ({ id: uid(), type: "text", content: chunk, }));

nextcontentSections = [];

2.3 DO NOT TOUCH

❌ pagination ❌ rendering

✅ STOP CHECK

✔ AI output visible in document body ✔ title unchanged ✔ pagination stable

🟢 STEP 3 — DATA CONTRACT FIX (15 min)

3.1 Fix typo globally

conentSection → contentSections

3.2 Add guard

function assertDocumentShape(data: Document2Data) { if (!Array.isArray(data.topSurfaceSection)) { throw new Error("Invalid topSurfaceSection"); } }

CALL before persist.

✅ STOP CHECK

✔ no undefined fields ✔ no runtime crashes

🟢 STEP 4 — COACHING ROUTER (SAFE)

4.1 Add router

// app/assistant/runCoachingMode.ts export async function runCoachingMode(input) { if (input.context?.type === "trip") { return generateTripPlan(input); }

if (input.context?.type === "document") { return generateDocStructure(input); }

return runDevLayerAction({ ...input, mode: "general", }); }

4.2 Plug into document action

const ai = mode === "coaching" ? await runCoachingMode({ ...input }) : await runDevLayerAction({ ...input });

✅ STOP CHECK

✔ general still works ✔ coaching works same or better ✔ no regression

🟢 STEP 5 — CHAT UNIFICATION (LIGHT)

5.1 Shared type

// app/assistant/types/chat.ts export type ChatMode = "general" | "coaching";

5.2 Use in BOTH ChatPanels

import type { ChatMode } from "@/app/assistant/types/chat";

✅ STOP CHECK

✔ both panels compile ✔ no duplicated types

🟢 STEP 6 — CONTINUE PRODUCT (MAIN ROADMAP)

PHASE A — SPONSOR SYSTEM

  1. Add WeekAssignment model
  2. createAssignment()
  3. assignAssignmentToWeek()
  4. Build:

/app/(pages)/sponsor/page.tsx

  • ActivitySelector
  • ForecastPreview
  • WeekGrid
  • ActiveWeek

PHASE B — TRIPS UI

/app/(pages)/trips/

  • page.tsx
  • [tripId]/page.tsx

Components:

  • TripCalendar
  • AvailabilityList
  • SessionList
  • OfferBuilderBridge

PHASE C — DOCUMENT → MAGAZINE

DocumentPage.surface → blocks → html → MagazineSection

RULE:

NO duplication ONLY transform

PHASE D — EXPORT

exportToGoogleDoc(documentId)

PHASE E — CSS

.page .section .card .label .cta

PHASE F — DEPLOY

docker build -t molino-app . docker push gcr.io/YOUR_PROJECT/molino-app

🔴 FINAL ORDER (STRICT)

  1. Mode cleanup
  2. AI write fix
  3. Data contract fix
  4. Coaching router

STOP → VALIDATE

  1. Sponsor system
  2. Trips UI
  3. Magazine
  4. Export
  5. CSS
  6. Deploy

⚠️ NON-NEGOTIABLE RULES

  • no schema redesign
  • no new entities (except Assignment)
  • no changes to Folio
  • no parallel work
  • no partial fixes

🎯 SUCCESS CHECK

✔ AI writes clean documents ✔ pagination stable ✔ 2 modes only ✔ sponsor system works ✔ trips UI works ✔ export works

🔑 FINAL PRINCIPLE

AI = content Document = structure Folio = rendering Actions = persistence

//END and more details

H1📘 MOLINO — FULL SYSTEM ARCHITECTURE (LOCKED)

H10. SYSTEM IDENTITY

System = Document Instrument + Entity Graph

  • Document → controller + projection surface
  • Entities → canonical distributed truth
  • Folio → deterministic rendering engine
  • Actions → single persistence authority

H11. GLOBAL EXECUTION MODEL

External Truth (Trips, Offers, Cards, etc.) ↓ Document (projection + orchestration) ↓ Blocks (structure) ↓ FlowUnits (distribution) ↓ Pagination (engine → wagon) ↓ Render (UI) ↓ User Intent ↓ queueSave ↓ Server Actions ↓ Prisma ↓ Revalidate ↓ Rebuild (full cycle)


H12. DOCUMENT SYSTEM (CORE)
H22.1 DATABASE MODEL
Document {
  docId
  section
  data (JSON)
  rawBlocks (JSON)
  renderedHtml
  contentHash
}


⸻

2.2 ROLE
	•	projection container
	•	orchestration surface
	•	working state buffer

NOT:
	•	canonical truth
	•	domain authority

⸻

2.3 INPUTS
	•	user edits
	•	AI structured outputs
	•	external entities (Trip, Offer, etc.)

⸻

2.4 OUTPUTS
	•	Folio rendering
	•	exports (PDF / HTML / Docs)
	•	triggers (Offer, Order, etc.)

⸻

3. FOLIO ENGINE (DETAILED)

⸻

3.1 STRUCTURE — buildBlocks

persisted → registry → full block list

Guarantees:
	•	all section types exist
	•	deterministic order
	•	stable IDs

⸻

3.2 FLOW — normalizeToFlowUnits

Block + DocumentData → FlowUnit[]

Responsibilities:
	•	extract content
	•	split overflow (FLOW_LIMITS)
	•	attach metrics
	•	ensure ≥1 unit per block
	•	deterministic IDs

⸻

FlowUnit

FlowUnit {
  id: `${blockId}::index`
  sectionType
  role: primary | continuation
  content
  rows
  chars
}


⸻

3.3 PAGINATION

FlowUnit[]
→ measure
→ split
→ EnginePage + WagonPage

Rules:
	•	engine = live
	•	wagon = static
	•	pagination = pure

⸻

3.4 RENDER — renderBlock

Block → Region → UI

Rules:
	•	no mutation
	•	no Prisma
	•	all changes → queueSave

⸻

3.5 EDIT LOOP (LOCKED)

User Input
→ emitIntent
→ compute helpers
→ queueSave

→ commitUpdate

→ buildBlocks
→ normalizeFlow
→ paginate

→ renderBlock
→ UI

→ onSave
→ action
→ Prisma
→ revalidate

→ server rebuild


⸻

3.6 SAVE SYSTEM

queueSave = ONLY authority

Rules:
	•	full document write
	•	no partial persistence
	•	no dual state

⸻

4. DOCUMENT SUBSYSTEMS

⸻

4.1 LINE ITEMS
	•	canonical pricing unit
	•	bridges Document ↔ Offer ↔ Order

⸻

4.2 TRIP
	•	external truth
	•	document consumes and edits projection

⸻

4.3 EXPORT / MAGAZINE
	•	projection only
	•	no duplication
	•	no divergence

⸻

5. CORE ENTITY GRAPH (SUMMARY)

⸻

Project
	•	root container
	•	owns all business entities

⸻

Trip / Experience
	•	structured offering
	•	generates pricing

⸻

Offer
	•	collection of line items

⸻

Order
	•	immutable transaction

⸻

LineItem (CRITICAL)

connects everything:
Document / Trip / Offer / Order / Asset


⸻

6. KNOWLEDGE SYSTEM

⸻

ConceptCard
	•	knowledge unit

CardContent
	•	steps[]
	•	materials[]

Deliverable
	•	projection output

⸻

7. SESSION / PATH
	•	SessionStack → execution
	•	SessionPath → sequence
	•	ConceptGroup → structured grouping

⸻

8. SPONSOR SYSTEM

⸻

WeekSlot
	•	revenue unit

WeekAssignment
	•	defines work

Donation
	•	funding layer

⸻

9. ACTION SYSTEM

Location:

app/(entity)/actions/

Rules:
	•	ONLY Prisma access
	•	ONLY mutation layer
	•	must revalidate

⸻

10. CRITICAL INVARIANTS

⸻

Document Engine
	•	deterministic
	•	full rebuild
	•	no partial reuse

⸻

Flow
	•	pure
	•	derived
	•	never stored

⸻

IDs
	•	stable
	•	deterministic

⸻

State
	•	single authority
	•	no duplication

⸻

Pagination
	•	layout only
	•	no mutation

⸻

11. KNOWN RISKS
	•	DocumentContext duplication
	•	non-deterministic IDs
	•	unsafe HTML
	•	incomplete FLOW_LIMITS
	•	bypassing queueSave

⸻

12. SYSTEM BOUNDARIES

⸻

Document
	•	render + control

Entities
	•	truth

Folio
	•	transform

Actions
	•	persist

⸻

13. FINAL MODEL

Truth → Document → Folio → UI → Intent → Actions → DB → Rebuild


⸻

14. FINAL LOCK

You are stabilizing:

a deterministic document engine
over a multi-entity system


⸻

🚀 DEPLOYMENT PLAN — FINAL STAGE (LOCKED ORDER)

⸻

🔴 PHASE 0 — FREEZE CORE

- Prisma schema → LOCK
- Actions → LOCK
- Routing → LOCK


⸻

🟢 PHASE 1 — WEEKLY SPONSOR SYSTEM (C)

Domain

WeekSlot ✅
Assignment 🔴
Donation ✅
LineItem ✅
Deliverable ✅


⸻

Actions

createAssignment()
assignAssignmentToWeek()


⸻

UI

app/(pages)/sponsor/page.tsx

- ActivitySelector
- ForecastPreview
- WeekGrid
- ActiveWeek


⸻

Done When

✔ pick activity
✔ assign week
✔ sponsor
✔ unlock donations


⸻

🟢 PHASE 2 — TRIPS UI (A)

Constraint

DO NOT TOUCH BACKEND


⸻

Pages

app/(pages)/trips/
- page.tsx
- [tripId]/page.tsx


⸻

Components

TripCalendar
AvailabilityList
SessionList
OfferBuilderBridge


⸻

Flow

Availability → UI
Session → UI
LineItem → pricing


⸻

Done When

✔ view availability
✔ select slot
✔ generate offer


⸻

🟢 PHASE 3 — AI MODES (B)

Final Modes

type Mode = "general" | "coaching";


⸻

Router

runCoachingMode(input, context)


⸻

Routing

trip → generateTripPlan()
document → generateDocStructure()


⸻

Remove

❌ multiple modes
❌ UI complexity


⸻

🟢 PHASE 4 — DOCUMENT → MAGAZINE (D)

DocumentPage.surface
→ blocks
→ html
→ MagazineSection

Rules:

NO duplication
ONLY transformation


⸻

🟢 PHASE 5 — APPSCRIPT EXPORT (E)

Client

exportToGoogleDoc(documentId)


⸻

Payload

{
  title
  content
  email?
}


⸻

Script

function doPost(e) {
  const { title, content, email } = JSON.parse(e.postData.contents);

  const doc = DocumentApp.create(title);
  doc.getBody().setText(content);

  if (email) {
    DriveApp.getFileById(doc.getId()).addEditor(email);
  }

  return ContentService.createTextOutput(
    JSON.stringify({ success: true, docId: doc.getId() })
  );
}


⸻

Done When

✔ export works
✔ user gets access


⸻

🟢 PHASE 6 — CSS

styles/theme.css

.page
.section
.card
.label
.cta


⸻

🟢 PHASE 7 — DEPLOYMENT

Docker

FROM node:20-alpine

WORKDIR /app
COPY . .

RUN npm install
RUN npm run build

EXPOSE 3000
CMD ["npm", "start"]


⸻

Commands

docker build -t molino-app .
docker push gcr.io/YOUR_PROJECT/molino-app


⸻

Deploy

Cloud Run


⸻

🔴 FINAL ORDER

1. Sponsor
2. Trips
3. AI
4. Magazine
5. Export
6. CSS
7. Deploy


⸻

⚠️ RULES

- no parallel phases
- no schema redesign
- no new entities (except Assignment)
- no breaking actions


⸻

✅ SUCCESS

✔ sponsor system works
✔ trips UI works
✔ AI outputs structured
✔ export works
✔ magazine works


⸻

FINAL STATEMENT

integration > invention


⸻

NEXT

→ Assignment model
→ ActivitySelector UI


⸻


//SPECIFICS ON AI ASSISTANT - GENERAL VS COACHING MODE AND DOCUMENT VERSION VS CHAT

# 🔧 AI → DOCUMENT INTEGRATION PLAN (SAFE REFACTOR — LOCKED)

---

# 0. OBJECTIVE

Stabilize and simplify:

AI → Document generation → Persistence → Rendering

WITHOUT:

❌ breaking Folio
❌ breaking actions
❌ introducing new paradigms

---

# 1. CURRENT ISSUES (CONFIRMED)

## 1.1 Mode System Fragmentation

- Mode defined in:
  - ChatPanel (local union)
  - AssistantContext (VALID_MODES)
  - modeRegistry
- UI exposes deprecated modes

---

## 1.2 Document Write Bug

Observed:

AI writes into:
→ title (incorrect)

instead of:
→ topSurfaceSection (correct)

---

## 1.3 Surface Contract Drift

Inconsistencies:

topSurfaceSection ✅
contentSections ✅
conentSection ❌ (typo present)

---

## 1.4 Mixed Responsibilities

applyAssistantToDocument currently:

	•	runs AI
	•	resolves cache
	•	transforms markdown
	•	decides structure
	•	persists
	•	forks document

→ too much responsibility (but do NOT refactor yet)

---

## 1.5 Duplicate Chat Systems

Two panels:

/documents → ChatPanel (writes document)
/assistant → ChatPanel (thread chat)

Different:

mode handling ❌
types ❌
validation ❌

---

# 2. TARGET STATE (LOCKED)

## 2.1 Modes

type AIMode = “general” | “coaching”;

---

## 2.2 Internal Pipelines (hidden)

mlv
dev
feature
docs
autopilot

→ NOT user selectable  
→ ONLY invoked by coaching

---

## 2.3 Document Write Contract

AI → ALWAYS writes to:

topSurfaceSection[]

NEVER:

title

---

## 2.4 Flow

UI → coaching/general
↓
runDevLayerAction
↓
applyAssistantToDocument
↓
Document2Data
↓
Folio

---

# 3. PHASE PLAN (STRICT ORDER)

---

# 🟢 PHASE 1 — MODE NORMALIZATION (NO BEHAVIOR CHANGE)

## 3.1 Create canonical type

```ts
// app/assistant/modes/types.ts

export type AIMode = "general" | "coaching";


⸻

3.2 Update AssistantContext

const VALID_MODES: AIMode[] = ["general", "coaching"];


⸻

3.3 ChatPanel (document)

REPLACE:

type Mode = "general" | "coaching" | "mlv" | "dev" | "autopilot"

WITH:

import type { AIMode } from "@/app/assistant/modes/types";


⸻

3.4 UI

REMOVE mode buttons:

❌ dev
❌ mlv
❌ feature
❌ docs
❌ autopilot

KEEP:

✔ general
✔ coaching


⸻

3.5 DO NOT TOUCH

modeRegistry.ts
runDevLayerAction


⸻

🟢 PHASE 2 — DOCUMENT WRITE FIX (CRITICAL)

4.1 HARD RULE

AI NEVER writes into title


⸻

4.2 Patch applyAssistantToDocument

REPLACE:

title: data.title?.trim()
  ? data.title
  : bundle?.title ?? prompt.slice(0, 120),

WITH:

title: data.title ?? "Untitled Document",


⸻

4.3 FORCE SURFACE WRITE

Replace entire non-MLV branch:

nextTopSurfaceSection = [
  {
    id: uid(),
    type: "text",
    content: fullContent,
  },
];

nextcontentSections = [];

WITH:

nextTopSurfaceSection = chunks.map((chunk) => ({
  id: uid(),
  type: "text",
  content: chunk,
}));

nextcontentSections = [];


⸻

4.4 RESULT

✔ no title pollution
✔ clean pagination
✔ predictable rendering


⸻

🟢 PHASE 3 — DATA CONTRACT FIX

5.1 Fix typo (CRITICAL)

SEARCH:

conentSection

REPLACE:

contentSections


⸻

5.2 Enforce schema (add guard)

function assertDocumentShape(data: Document2Data) {
  if (!Array.isArray(data.topSurfaceSection)) {
    throw new Error("Invalid topSurfaceSection");
  }
}

CALL before persist.

⸻

🟢 PHASE 4 — COACHING ROUTER (MINIMAL)

6.1 Add router

// app/assistant/runCoachingMode.ts

export async function runCoachingMode(input) {
  const { context } = input;

  if (context?.type === "trip") {
    return generateTripPlan(input);
  }

  if (context?.type === "document") {
    return generateDocStructure(input);
  }

  return runDevLayerAction({
    ...input,
    mode: "general",
  });
}


⸻

6.2 applyAssistantToDocument

REPLACE:

const ai = await runDevLayerAction(...)

WITH:

const ai =
  mode === "coaching"
    ? await runCoachingMode({ ...input })
    : await runDevLayerAction({ ...input });


⸻

🟢 PHASE 5 — CHAT UNIFICATION (NO UI CHANGE)

7.1 Extract shared type

// app/assistant/types/chat.ts

export type ChatMode = "general" | "coaching";


⸻

7.2 Use in BOTH panels

document ChatPanel
assistant ChatPanel


⸻

🟢 PHASE 6 — CLEAN MODE SOURCE

8.1 MODE_CATALOG stays

8.2 MODE_REGISTRY stays

8.3 Add rule

// MODE_CATALOG = authority
// MODE_REGISTRY = behavior


⸻

4. VALIDATION CHECKLIST

⸻

After Phase 1

✔ only 2 modes visible
✔ no TS duplication


⸻

After Phase 2

✔ AI output always in topSurfaceSection
✔ title never overwritten
✔ pagination stable


⸻

After Phase 3

✔ no undefined fields
✔ no typo drift


⸻

After Phase 4

✔ coaching routes correctly
✔ no behavior regression


⸻

5. DO NOT TOUCH (IMPORTANT)

❌ Folio engine
❌ pagination
❌ ensureBlocks
❌ DocumentPage
❌ Prisma schema


⸻

6. ROOT CAUSE (FOR CONTEXT)

Bug origin:

AI → single string
→ forced into single block
→ rendering mismatch
→ fallback writes title

Fix:

AI → splitMarkdown
→ multiple blocks
→ stable render


⸻

7. NEXT STEP (EXECUTE NOW)

1. Phase 1 (mode normalization)
2. Phase 2 (write fix)

STOP.

Do not proceed further until validated.

⸻

FINAL PRINCIPLE

AI does not decide document structure
AI provides content

Document system owns structure


⸻