Skip to content

Study Plans

Admin-defined study plan templates resolve when a user creates a study. Steps are snapshotted into per-study rows so template edits do not change in-flight studies.

Terminology: use study step in API/DB (not “TODO”) to avoid confusion with deferred mentorship tasks (Product Scope).

ConceptTableGraphQL
Plan templatestudy_plan_templatesStudyPlanTemplate (admin)
Template stepstudy_plan_template_stepsStudyPlanTemplateStep (admin)
Study step (instance)study_stepsStudyStep

Guided studies: published templates with study_method = guided are the catalog (title, description, spiritual phases). Users pick a template id as focus; see Study Methods.

Spiritual phases: each template has one or more spiritualPhases (pivot study_plan_template_spiritual_phases). Resolution matches when the user’s spiritual_phase is in that set (explicit allowlist, not a ladder).

On createStudy:

  1. Resolve a published template from method, user spiritual_phase, and focus.
  2. Set studies.plan_template_id and plan_applied_at.
  3. Copy each template step into study_steps (title, instructions, flow fields, step_key frozen).
  4. All steps in wave 1 are available; others remain pending until their wave unlocks.

Template changes affect new studies only.

Template and study step instructions are stored as the same rich text envelope JSON string used for note CRDT bodies (column type remains text). Admins edit instructions in the TipTap-based admin editor; clients render with RichTextPreview.

Filter blocks (filterBlock nodes) hold conditional content keyed by user personality and learning style. At step materialization (snapshot onto study_steps), the server evaluates filters against the creating user’s profile and strips non-matching blocks so each study step stores only the instructions that user should see.

Legacy markdown instructions import via fromMarkdown() on read; new content is always envelope JSON.

MethodResolution order
Book (milk)Published template for (book, user phase) — strict; create fails if missing. UI lists books via availableBookStudyBooks.
Book (meat)Book-specific template if any → else generic meat template; if user already completed a study on the same book, variant=repeat template.
Book (transition)Book-specific if any → else generic transition → phase fallback.
GuidedPublished template for id in focus — strict if missing or phase-inaccessible. UI lists plans via availableGuidedStudyPlans.
Topical / word / character / hypotheticalGeneric template for (method, phase) with phase fallback; create allowed without steps if unpublished (soft).

Book focus is normalized to canonical USFM ids (e.g. JnJhn) at create.

Templates maintain separate step lists for mentored and individual participation (mentoredSteps / individualSteps in admin GraphQL). Materialization copies only the list matching the study’s participation_mode.

Each step declares:

FieldPurpose
waveSteps in the same wave unlock together; the next wave opens when all steps in the current wave are completed
completionModewrite_note, review_note, meet, acknowledge, assign_track, answer_quiz, grade_quiz, review_quiz, attest_outcomes, or promote_phase
primaryActormentee, mentor, or pair — who must act to complete
completionConfigMode-specific options (e.g. review reject target, meet stub note flags)

Wave progression: wave 1 steps are available at create; others start pending. Completing every step in a wave unlocks the next wave. During parallel waves (e.g. meeting prep), mentor and mentee each see their own actionable step; the other party may see a waitingReason until the wave completes.

Review rejection: mentors can rejectStudyStepReview on a review_note step (when allowReject is true). A mentor note is required; the prior write_note step reopens for revision while the review step returns to pending.

Meet steps (stub): authored as meet; runtime behaves as acknowledge plus optional lane notes until study sessions ship.

Mentor private notes: optional per-step reminders on mentor_private_note_id — mentor read/write only, excluded from discipleship lane sharing.

  • Visibility: clients query study.nextSteps(limit) for viewer-actionable steps in the active wave (may return multiple during parallel work).
  • Complete: completeStudyStep validates against snapshotted completionMode (optional lane note ids, quizAttemptId, or outcomeChecks).
  • Mentorship: mentored studies use mentee and mentor note lanes per step; individual studies use the individual lane. See Mentorship.
  • Study ended: updateStudy with endedAt cancels pending/available steps (cancelled). Notes and log entries remain the source of truth.

Curriculum designers and platform administrators manage templates at /admin/plans. Designer guide: Study plans. Platform-only routes (users, audit, feature flags, AI config) require a platform administrator.

RoutePurpose
/admin/plansList, filters, resolution simulator
/admin/plans/new, /admin/plans/[id]Template form (dual mentored/individual steps, AI review)
/admin/plans/new/assistantAI wizard — platform admin + admin_study_plan_ai
/admin/plans/rubricRubric dimension CRUD
/admin/plans/outcomesLearning outcome CRUD
/admin/quizzesQuiz bank list
/admin/quizzes/[id]Quiz authoring (questions, draw config, AI review)
/admin/curriculum/reviewsReview queue — submit, approve, request changes

GraphQL: adminStudyPlanTemplates, create/update/delete; learningOutcomes (authenticated catalog); admin createLearningOutcome / updateLearningOutcome / deleteLearningOutcome; adminQuizzes, adminQuiz, createQuiz, updateQuiz, deleteQuiz, question/variant CRUD, reviewQuiz; review mutations submitCurriculumReview, approveCurriculumReview, requestCurriculumChanges, withdrawCurriculumReview, mergeCurriculumRevision; queries curriculumReviewQueue, curriculumReviewRequest, curriculumRevision.

Unpublished templates follow a draft → in review → approved → publish flow (editorial CMS pattern):

  1. Designer edits a draft (is_published = false).
  2. Designer calls submitCurriculumReview — fingerprint snapshot stored on the review request.
  3. A different curriculum designer or platform administrator calls approveCurriculumReview (self-approval blocked).
  4. Designer calls updateStudyPlanTemplate with isPublished: true — allowed only when an approved fingerprint matches the current entity state.

Published templates: live rows stay visible to learners. Attribute edits on a published template are staged in curriculum_revisions (JSON payload) until mergeCurriculumRevision applies them. StudyPlanTemplate exposes reviewStatus, hasStagedChanges, and activeRevisionId for admin UI.

Platform administrators may publish or merge without a prior review.

Local dev: StudyPlanTemplateSeeder — sample book plans, generic method plans, guided catalog templates, mentorship intro pairing plans. LearningOutcomesAndCheckupSeeder — Milk→Transition outcomes, promotion quiz, checkup template, and implicit outcomes on guided Foundations steps.

See Learning outcomes.

Quiz bank rows live in quizzes with ordered quiz_questions (multiple choice, true/false, short answer, etc.). Study steps with completion_mode = answer_quiz reference a quiz id in completion_config; attempts are stored per study step (quiz_attempts / quiz_responses).

Admin: curriculum designers and platform administrators author quizzes at /admin/quizzes (list) and /admin/quizzes/{id} (metadata, questions, learning-style variants, random draw config, async AI review). Unpublished quizzes follow the same review-before-publish gate as templates. Plan template steps pick a quiz via dropdown and link out to the editor — questions are not edited inline on the plan form.

Runtime: mentees call startQuizAttempt to draw questions (respecting pool config and prior attempts on retry), then submitQuizAttempt. Snapshots and raw answers are purged after grading completes; scores and outcome evidence are retained. Passing score ratio is compared to the step or quiz threshold.

Subjective questions (essay and future types that return needs_review) trigger an automatic pipeline at study materialization: companion steps grade_quiz and review_quiz are injected after the answer_quiz step in the same wave. Flow: submit → async AI pre-grade (AnalyzeQuizAttemptJob) → analyzed → grader confirms (grade_quiz; mentor in mentored studies, study owner in individual) → graded → mentee acknowledges results (review_quiz) → reviewed. Auto-only quizzes skip injection and complete on pass as before.

study_plan_rubric_dimensions holds the canonical checklist for template quality (seeded in dev and prod via StudyPlanRubricSeeder). Each dimension has a human-facing description and separate ai_instructions for agent prompts. Humans and AI agents share the same dimensions via StudyPlanRubric (forHumans(), forAgentPrompt()).

Public transparency (API): unauthenticated query studyPlanRubricDimensions { slug title description sortOrder } exposes rubric descriptions. aiInstructions is returned only for authenticated users with curriculum or platform admin access.

Admin AI assistance (platform administrator)

Section titled “Admin AI assistance (platform administrator)”

Behind the admin_study_plan_ai feature flag (feature_flags.default_enabled). See AI Guidelines. External agents use the same flows via Study plan template MCP.

FlowRoute / UIGraphQL mutationPoll queryMutates draft?
Wizard draft/admin/plans/new/assistant → prefills /admin/plans/newgenerateStudyPlanTemplateDraftstudyPlanTemplateDraft(requestId)Yes (once, unpublished)
Step instructionsPer-step actions in step editorgenerateStudyPlanStepInstructionsstudyPlanStepInstructions(requestId)Yes, after diff + Apply; single-level undo
Plan reviewReview plan on template formreviewStudyPlanTemplatestudyPlanTemplateReview(requestId)No — criticism only

Async job pattern: each mutation returns a handle type (StudyPlanTemplateDraftRequest, StudyPlanTemplateReviewRequest, or StudyPlanStepInstructionsRequest) with requestId. The admin UI subscribes to Laravel Echo for progress, then polls the matching query until the job completes or fails. MCP tools mirror the same operations (kebab-case tool names on the study-plan-templates server).

Draft agent may fetch optional wizard referenceUrls via WebFetch and search public examples (capped). Review and step agents do not use web tools in v1. All agents load rubric dimensions into their prompts. Usage is logged to ai_usage.

  • completion_rule automation (auto-complete from logs/notes).
  • Dynamic steps added after create.
  • Non-linear prerequisites, skip.
  • Template versioning (immutable publish versions) — partially addressed by staging revisions for published templates; full immutable version history remains in planning backlog.
  • Track runtime is documented in Tracks (assignment, skip/noop, electives, inferred progress). Still deferred: user_course_progress table and programmatic prerequisite graphs beyond phase — Architecture Questions.