Skip to content

Phase 3.3 — premiumStructuredStrategy + persistent save + review queue wiring #1740

@CraigBuckmaster

Description

@CraigBuckmaster

Part of epic #1725. Depends on #1739. Phase 3 — Premium synthesis + review.

Objective

The premium experience that ships even with the Amicus flag off. Premium users get a mode-shaped structured form (already built in Phase 2.6 + 2.7), but their synthesis persists to the spaced review queue and is retrievable from My Study. Free users get the same form but no persistence.

Files

Create

  • app/src/services/guidedStudy/synthesis/premiumStructured.ts
  • app/src/services/guidedStudy/review/artifacts.ts — artifact builders per mode
  • app/src/services/guidedStudy/synthesis/__tests__/premiumStructured.test.ts
  • app/src/services/guidedStudy/review/__tests__/artifacts.test.ts

Modify

  • app/src/services/guidedStudy/synthesis/strategy.tschooseStrategy returns premiumStructured for the appropriate path

Hook into

  • Existing guided_review_items table + spaced review queue (review system already exists; verify the table shape in userDatabase.ts migration v19 area)

premiumStructured run() behavior

async run(ctx) {
  const artifact = buildArtifact(ctx.plan.mode, ctx.captured);
  if (ctx.sessionId != null) {
    await setModeArtifact(ctx.sessionId, artifact);
    await setSynthesisStrategy(ctx.sessionId, 'premium_structured');
    await enqueueReviewItem(ctx.sessionId, artifact);
  }
  return {
    kind: 'premium_structured',
    output: buildOutputBlocks(ctx.plan.mode, ctx.captured, /* showAmicusTeaser */ false),
    artifact,
  };
}

Artifact builders

buildArtifact(mode, captured): ReviewArtifact — one builder per ReviewArtifactType. All return a typed shape persisted as mode_artifact_json.

export type ReviewArtifact =
  | {
      type: 'memory_verse';     // quick
      verseRef: string;          // e.g. "Romans 8:28"
      verseText: string;
      takeaway: string;
    }
  | {
      type: 'analytical_claim';  // deep
      claim: string;
      evidence: string;
      tension: string | null;
    }
  | {
      type: 'teaching_outline';  // teaching
      audience: string;
      mainPoint: string;
      moves: string[];
      application: string;
      discussionQuestion: string;
    }
  | {
      type: 'returning_prayer';  // devotional
      arrival: string;
      wordOrPhrase: string;
      prayer: string;
      carryForward: string;
    };

Each builder reads from captured defensively (NULL-tolerant) and produces an artifact with whatever the user filled in. Empty fields become empty strings, not undefined, so persistence is consistent.

Review queue integration

The existing guided_review_items table is already used by guided study's existing premium review feature. This card extends enqueueReviewItem to accept the new typed artifacts and stash them in the existing schema (likely as JSON in an existing column — check schema in userDatabase.ts).

If the existing schema cannot accommodate the new artifact shapes cleanly, propose (do not execute) a follow-up migration card. The default assumption is the existing schema accepts JSON in a notes/payload column.

Output blocks

buildOutputBlocks for premium_structured returns:

  • Recap sections (same as free, the user's own writing)
  • "Saved for review" confirmation block
  • "View in My Study" CTA button → navigates to MyStudy screen
  • NO upgrade footer (they already have it)

Acceptance

  1. Premium user completing synthesis → artifact persisted → appears in spaced review queue.
  2. Reopening My Study shows the new artifact retrievable.
  3. Free user path is unchanged from Phase 2.7 (no save).
  4. Re-completing the same session updates rather than duplicates the artifact.
  5. tsc, lint, test clean.

Out of scope

  • premiumAmicus (Phase 4).
  • Subscription screen rewrite (Phase 4).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions