# Stage 7 — Course Composition, Slide Management, and Question Groups

## Status

Implementation is substantially complete and under acceptance validation.

Implemented in the current checkout:

- Additive stable slide documents and course-slide records with safe legacy backfill.
- Course Structure authoring for ordering, menu visibility, inclusion, reversible removal, image/blank slides, and duplication options.
- Stable slide placement for questions, question groups, multimedia, and course flow.
- One-level question groups with move, duplicate, remove, restore, and stable tracking identities.
- Config v5 packaging and v4 learner slide state with v1-v3 decoding retained.
- Atomic replacement-package publication while retaining an outdated prior package until replacement succeeds.

Automated validation currently passes 55 Laravel tests (445 assertions) and the production frontend build. Native Moodle SCORM 1.2 acceptance remains a deployment/UAT check and is not claimed complete here.

Stage 7 must be delivered through additive migrations and backward-compatible readers. Existing presentations, rendered slides, layout corrections, questions, multimedia, course flow, learner state, and downloadable packages must not be deleted or silently reassigned.

## Summary

Add a dedicated **Course structure** workspace where authors can safely change the generated course without directly modifying the original PowerPoint or an exported SCORM ZIP.

Authors will be able to:

- Reorder slides.
- Duplicate an existing slide.
- Add an image-based slide.
- Hide a slide from the learner menu while keeping it in the course.
- Exclude a slide from the learner course without deleting its data.
- Move removed slides into a recoverable Removed slides area and restore them later.
- Duplicate questions.
- Create one-level question groups or categories.
- Move questions between Standalone and named groups.
- Reorder questions inside a group.
- Duplicate a complete group and all its questions.
- Arrange standalone questions, question groups, popup videos, and video steps in the course flow.

The authoring workflow becomes:

```text
Prepare and render PowerPoint → Author slides and interactions
→ Organize course structure → Preview learner course
→ Generate a new SCORM package
```

Stage 7 edits the saved DocuDeck project and regenerates SCORM. It does not open or mutate an already exported ZIP.

## Existing Constraints

The current application derives slides from `1..slide_count` and stores their images with ordinal filenames such as `slides/001.jpg`. Questions, media, course flow, timers, transition overrides, preview state, and learner progress also use numeric slide positions.

Directly deleting or renumbering a slide would therefore risk attaching existing content to the wrong slide. Stage 7 must introduce stable course-slide identities before enabling slide mutations.

Question duplication already exists in the frontend. A duplicated question is saved as a new question and receives new stable question and answer tracking keys. Stage 7 will preserve this behavior while moving duplication into the new grouped question experience.

The current course-flow groups are placement buckets after a numeric slide or at the course end. They are not question categories. Stage 7 question groups are a separate authoring and learner-flow concept.

## 1. Stable and Non-Destructive Course Slides

### Slide document

Add a conversion-owned slide document containing:

- Conversion ID.
- Revision.
- Next stable slide tracking key.
- Document-level timestamps.

Add conversion-owned course-slide records containing:

- UUID.
- Conversion ID.
- Stable, non-reused numeric tracking key.
- Source slide number when based on a rendered PowerPoint slide.
- Asset type: `rendered`, `uploaded_image`, or `blank`.
- Optional private custom image and thumbnail paths.
- Optional duplicated-from slide UUID.
- Author-facing title and accessible learner label.
- Course position.
- `show_in_menu` setting.
- `included_in_course` setting.
- Reversible `removed_at` timestamp.
- Created and updated timestamps.

Keep `conversions.slide_count` as the number of slides extracted from the original PowerPoint. Do not reinterpret it as the authored course-slide count.

### Existing-project backfill

- Use an additive, idempotent migration or bootstrap service.
- Create one course-slide record for every existing source slide in its current order.
- Assign stable tracking keys once and never reuse them.
- Preserve current behavior after backfill: every existing slide is included and shown in the menu.
- Map numeric question, media, timer, transition, and course-flow references to the corresponding backfilled course slide.
- Continue reading the legacy numeric representation until migration and package compatibility are verified.
- Do not reset project tables or regenerate slide images during migration.

### Slide visibility states

Expose three distinct author actions:

1. **Hide from menu**
   - The slide remains in learner sequence.
   - It remains part of progress and completion.
   - It is omitted from thumbnail/menu navigation.

2. **Exclude from course**
   - The slide is omitted from learner sequence and completion calculations.
   - Its source image and attached content remain stored.
   - It can be included again later.

3. **Remove slide**
   - The slide moves to a recoverable Removed slides area.
   - It is excluded from the course and learner menu.
   - Questions, media, hotspots, settings, and source assets are not cascade-deleted.
   - Restoring it restores its previous relationships and preferred position when possible.

Permanent slide deletion is deferred. Project deletion continues to remove all project-owned data through the existing cleanup process.

### Reordering

- Reorder active course slides through drag and drop, keyboard controls, and explicit Move actions.
- Persist ordering atomically with the slide-document revision.
- Reordering must not change a slide's stable tracking key or its attached content.
- Hidden slides remain reorderable.
- Removed slides are not part of active ordering until restored.
- Course preview and package generation must use the authored active order rather than source slide number.

## 2. Adding and Duplicating Slides

### Add slide

Stage 7 supports:

- Uploading a JPG or PNG as an image-based slide.
- Creating a simple blank slide with a background color and accessible title.
- Duplicating an existing course slide.

Uploaded images must be stored privately, validated by real MIME/image inspection, normalized to the project aspect ratio according to an explicit fit mode, and packaged as local course assets.

Fit modes:

- Contain without cropping.
- Cover with cropping.
- Stretch only after an explicit warning.

Full PowerPoint-style text and object creation for a new slide is deferred. A blank slide in Stage 7 is a simple course surface, not a new editable PowerPoint page.

### Duplicate slide

Duplicating creates a new course-slide UUID and stable tracking key and inserts the copy directly after the source slide.

The duplication dialog contains:

- Visual: always duplicated or referenced safely.
- Player/timer/transition settings: selected by default.
- Questions: optional, off by default.
- Multimedia: optional, off by default.
- Hotspots: optional, off by default.

All duplicated questions, answers, media items, and hotspots receive new UUIDs and new stable tracking keys. Immutable normalized media assets may be shared through references, but their metadata records and learner tracking identities must be independent.

A duplicated rendered PowerPoint slide references the same rendered source visual. If Stage 6 corrections later regenerate that source slide, linked duplicates update to the regenerated visual. The UI must label this relationship. Independent PowerPoint-layout editing of only one duplicate is deferred.

## 3. Attachment and Dependency Safety

Before excluding or removing a slide, display a dependency summary containing:

- Number of standalone questions.
- Number of question groups.
- Number of popup and separate-step videos.
- Number of overlay media items.
- Number of audio/narration items.
- Number of hotspots.
- Timer and transition overrides.

Available actions:

- Cancel.
- Exclude/remove the slide and keep its attachments inactive.
- Move eligible attachments to another active slide.

Keeping attachments inactive is the default. Nothing is silently reassigned to a neighbouring numeric slide.

Moving attachments must be explicit, validated, and atomic. Same-slide media trigger dependencies and hotspots must either move together or block the operation with a concrete explanation.

Restoring a slide reactivates retained attachments unless an attachment was explicitly moved elsewhere.

## 4. Question Groups and Categories

### Data model

Add conversion-owned question-group records containing:

- UUID.
- Conversion ID.
- Stable, non-reused numeric tracking key.
- Title.
- Optional description.
- Course-slide anchor UUID or end-of-course placement.
- Position within the placement.
- Optional learner introduction setting.
- Presentation settings where applicable.
- Required/optional group behavior where applicable.
- Reversible `removed_at` timestamp.
- Created and updated timestamps.

Add a nullable `question_group_id` to conversion questions. Replace or supplement numeric `anchor_slide` with a stable course-slide anchor.

A question is either:

- Standalone with no group.
- A member of exactly one question group.

Nested groups are not supported in Stage 7.

### Placement behavior

- A group has one course placement: after a selected course slide or at course end.
- All child questions inherit the group's placement.
- Moving a question into a group applies that group's placement.
- Moving a question to Standalone retains the current placement unless the author selects another one.
- A question that needs a different placement must be standalone or moved into another group.

### Learner behavior

A question group is one course-flow block. When the learner reaches the block, its active questions are presented consecutively in their authored or shuffled order.

The optional group introduction can display the group title and description before its first question. Group introduction is disabled by default.

Existing scoring remains question-based. Grouping must not silently change points, correct answers, required state, attempts, feedback, pass/fail calculations, or final submission rules.

### Question operations

Support:

- Add a standalone question.
- Add a question directly to a group.
- Duplicate a question directly after its source.
- Move a question between Standalone and a group.
- Reorder questions inside their current container.
- Remove and restore a question.
- Create, rename, reorder, remove, and restore a group.
- Duplicate a group and every question and answer it contains.

Every duplicate receives new UUIDs and stable tracking keys. Never reuse identifiers from removed questions, answers, or groups.

Group duplication is atomic. If any child cannot be duplicated, no partial group copy is saved.

## 5. Unified Course Flow

Extend the current course-flow model so each active course slide is followed by an ordered set of eligible interactions.

Eligible course-flow items become:

- Standalone question.
- Question group.
- Popup video.
- Separate video step.

Questions inside a group do not also appear as root course-flow items.

Overlay video and slide-attached audio remain part of the slide and do not appear as separate flow items.

Flow anchors must use stable course-slide identities. Provide a compatibility reader for existing numeric `anchor_slide` groups and normalize them to stable slide references.

For every active slide and the end-of-course group:

- Every eligible item occurs exactly once.
- Duplicate or cross-project references are rejected.
- Missing new items are appended to their valid placement group.
- Removed or ineligible references are removed from active flow without deleting their underlying records.
- Excluding a slide deactivates its placement group until the slide is restored or its content is explicitly moved.

## 6. APIs and Revision Safety

Add authenticated, ownership-protected endpoints under `/api/v1/powerpoint-to-scorm`.

### Slide endpoints

| Endpoint | Behavior |
| --- | --- |
| `GET /conversions/{id}/slides` | Return the revisioned authored slide document, active/removed slides, relationships, and dependency summaries |
| `PUT /conversions/{id}/slides` | Atomically save ordering, titles, menu visibility, and inclusion state |
| `POST /conversions/{id}/slides/uploads` | Upload and create an image-based slide |
| `POST /conversions/{id}/slides/blank` | Create a simple blank course slide |
| `POST /conversions/{id}/slides/{slide}/duplicate` | Duplicate a slide with selected attachment options |
| `POST /conversions/{id}/slides/{slide}/remove` | Reversibly remove a slide |
| `POST /conversions/{id}/slides/{slide}/restore` | Restore a removed slide |
| `POST /conversions/{id}/slides/{slide}/move-attachments` | Atomically move selected eligible attachments |

### Question-group endpoints

| Endpoint | Behavior |
| --- | --- |
| `POST /conversions/{id}/question-groups` | Create a group |
| `PATCH /conversions/{id}/question-groups/{group}` | Rename or update group settings |
| `POST /conversions/{id}/question-groups/{group}/duplicate` | Atomically duplicate the group, questions, and answers |
| `POST /conversions/{id}/question-groups/{group}/remove` | Reversibly remove a group |
| `POST /conversions/{id}/question-groups/{group}/restore` | Restore a group |
| `POST /conversions/{id}/questions/{question}/duplicate` | Duplicate one question |
| `PATCH /conversions/{id}/questions/{question}/group` | Move a question to Standalone or a group |

The existing complete quiz document remains supported. Extend it with groups and stable course-slide placement while retaining backward-compatible fields during migration.

### Concurrency and saves

- Slide structure, quiz, media, and course flow keep independent revisions.
- Every mutation requires the applicable current revision.
- Return `409` for stale revisions, archived projects, active final rendering, active packaging, and incompatible concurrent mutations.
- Use transactions and row locks for duplicate, remove, restore, reorder, and attachment-move operations.
- Autosave valid structure changes after 800 ms through the existing serialized save coordinator.
- Provide Save now and retry controls.
- Edits made during an active save remain dirty and trigger another save.
- Warn before leaving with unsaved changes.

Any successful structural change marks the generated package outdated. Keep the previous successful package downloadable until a replacement package is generated successfully.

## 7. Course Structure UX

Add a **Course structure** category beside Player, Questions, Media, Animations, and Fonts & rendering.

### Slide workspace

Provide:

- Responsive thumbnail rail or grid.
- Drag handles and keyboard Move actions.
- Add slide menu.
- Duplicate action.
- Show in menu toggle.
- Include in course toggle.
- Removed slides drawer.
- Search by slide number or title.
- Current selection inspector.
- Dependency summary.
- Undo toast for reversible actions.

Slide badges include:

- Visible in menu.
- Hidden from menu.
- Excluded.
- Removed.
- Has questions.
- Has media.
- Has hotspots.
- Package needs regeneration.

### Question workspace

Use a responsive three-panel layout:

1. Group tree containing Standalone, active groups, and Removed.
2. Question list for the selected container.
3. Existing question inspector/editor.

Support pointer dragging plus keyboard and menu alternatives. On mobile, show the panels as navigable stacked screens rather than narrow columns.

Group cards show:

- Title.
- Placement.
- Question count.
- Required question count.
- Total points.
- Duplicate, rename, move, and remove actions.

Before duplicating a group, show the number of questions and answers that will be copied.

### Accessibility and localization

- Add all Stage 7 labels, confirmations, validation, loading states, and error messages to the English and Arabic dictionaries.
- Apply logical CSS and respect application RTL without changing course coordinates.
- Do not mirror slide images or reverse the authored slide order automatically.
- Provide visible focus, keyboard reordering, live-region save messages, and accessible names for icon-only actions.
- Use `dir="auto"` for authored titles and question text.

## 8. Preview, Packaging, and Learner Runtime

### Preview

- Full preview uses only active, included course slides.
- Hidden-menu slides remain in learner sequence but are omitted from the menu.
- Excluded and removed slides are absent from sequence, counters, progress, and completion.
- Preview uses stable slide identities for media, questions, flow, navigation, and completion.
- Authoring preview must match packaged learner behavior.

### Package configuration

Increment package configuration from version 4 to version 5.

Each packaged slide contains:

- Stable slide ID derived from its tracking key.
- Authored sequence position.
- Source or custom image path.
- Thumbnail path.
- Menu visibility.
- Accessible label.

Use stable package paths for new custom slide assets. Referenced rendered source images may be copied into stable package slide paths during packaging.

Do not include removed, excluded, orphaned, or original private source assets in the ZIP.

### Learner state

Add backward-compatible `v4` course state:

- Continue decoding `v1`, `v2`, and `v3` state.
- Map legacy viewed slide positions to the backfilled stable slide keys.
- Track new slide progress by stable tracking key rather than array index.
- Preserve existing stable question, option, and media tracking.
- Preserve progress when slides are reordered.
- Do not count excluded or removed slides toward completion.
- Restored slides recover matching progress when their stable key exists in learner state.
- Recalculate and enforce the portable 4,096-character SCORM 1.2 `suspend_data` ceiling.

Existing exported packages remain immutable. A new package version must not modify ZIP files that learners may already have uploaded to an LMS.

## 9. Validation and Failure Behavior

- Reject ownership and cross-conversion references.
- Reject duplicated stable tracking keys.
- Reject moving content to removed or excluded slides unless inclusion is restored in the same transaction.
- Reject deleting the final included slide; a course must contain at least one learner slide.
- Validate custom images by decoded dimensions and MIME, not filename alone.
- Block package generation when required custom slide assets are missing or processing failed.
- Failed duplication or attachment movement leaves the original project unchanged.
- Failed package generation retains the last successful downloadable package.
- Queued jobs exit safely when the project or referenced record is deleted.
- Removing a slide never deletes uploaded media files or the original rendered PowerPoint slide.

## 10. Verification and Acceptance

### Migration and compatibility

- Backfill existing projects without changing their learner order or output.
- Run the backfill repeatedly to prove idempotency.
- Verify existing questions, media, flow, timers, transitions, and layout corrections remain associated with the same visual slides.
- Verify old projects without slide documents continue to load during rollout.
- Verify archived projects remain read-only.

### Slide operations

- Add image and blank slides.
- Duplicate a slide with every attachment-option combination.
- Reorder without changing stable identifiers.
- Hide from menu while retaining sequential playback and completion.
- Exclude and restore without data loss.
- Remove and restore slides with questions, media, hotspots, timers, and transitions.
- Reject invalid moves and preserve all records after transactional failure.
- Test non-16:9 projects and Arabic/RTL authoring.

### Questions and groups

- Create standalone and grouped questions.
- Move questions into and out of groups.
- Reorder questions and groups.
- Duplicate questions with fresh question and answer keys.
- Duplicate complete groups atomically with fresh group, question, and answer keys.
- Remove and restore questions and groups.
- Preserve scoring, attempts, feedback, shuffle, required state, and final submission.
- Verify group flow ordering with popup and separate-step videos.

### Runtime and packaging

- Verify config version 5 and stable slide paths.
- Test `v1`/`v2`/`v3` decode and `v4` round trips.
- Test resume after reorder, exclusion, restoration, and duplication.
- Test the 4,096-character state limit.
- Verify hidden-menu slides remain reachable through Previous and Next.
- Verify excluded slides do not affect progress or completion.
- Verify preview and packaged SCORM produce the same flow.
- Run Stage 1–6, multimedia, layout, RTL, scoring, resume, and package regressions.
- Run Moodle SCORM 1.2 acceptance for slide operations, standalone questions, grouped questions, duplication, completion, pass/fail, and resume.

## Implementation Order

1. Add stable slide persistence and existing-project backfill.
2. Switch read paths, preview, and packaging to the authored slide sequence without changing visible behavior.
3. Migrate anchors and per-slide settings to stable slide references with compatibility aliases.
4. Add slide reorder, visibility, exclusion, removal, restoration, duplication, and image/blank slide creation.
5. Add question-group persistence and safe question duplication/movement operations.
6. Extend normalized course flow with group items and stable slide anchors.
7. Build the Course structure and grouped Questions experiences.
8. Add package config version 5 and course-state version 4.
9. Complete automated regressions and real Moodle acceptance.

## Locked Defaults and Deferred Work

- Slide removal is reversible; permanent slide deletion is deferred.
- Hide from menu and exclude from course are separate settings.
- Existing PowerPoint images remain immutable source assets.
- Duplicate rendered slides are linked to the same regenerated source visual.
- Image uploads and simple blank slides are supported; full new-slide content editing is deferred.
- Question groups are one level deep and act as learner course-flow blocks.
- Group introduction is optional and disabled by default.
- Duplicated attachments always receive new learner tracking identities.
- Direct modification or re-import of an exported SCORM ZIP is deferred.
- Nested groups, question banks shared across projects, random question pools, PowerPoint slide insertion, independent layout editing of linked duplicates, and collaborative multi-user editing are deferred.
