From 66c402e90eabab613d3467e36ef0ee4533a58cb1 Mon Sep 17 00:00:00 2001 From: Derek Redmond Date: Wed, 3 Jun 2026 22:15:44 -0400 Subject: [PATCH 1/6] docs: rewrite course authoring guide as procedural LLM-facing instructions Convert AGENTS.md prose to rules/tables and trim runtime-internal reference (adapter spec citations, xAPI internals) that course authors never write. 1785 -> 1502 lines; all code examples and prop tables kept. Co-Authored-By: Claude Opus 4.8 --- .changeset/agents-procedural-rewrite.md | 5 + packages/tessera-learn/AGENTS.md | 890 ++++++++---------------- 2 files changed, 309 insertions(+), 586 deletions(-) create mode 100644 .changeset/agents-procedural-rewrite.md diff --git a/.changeset/agents-procedural-rewrite.md b/.changeset/agents-procedural-rewrite.md new file mode 100644 index 0000000..af7554b --- /dev/null +++ b/.changeset/agents-procedural-rewrite.md @@ -0,0 +1,5 @@ +--- +'tessera-learn': patch +--- + +Rewrite the course authoring guide (`AGENTS.md`) into a procedural, LLM-facing instruction set — converting prose to rules/tables and trimming runtime-internal reference that authors never write. diff --git a/packages/tessera-learn/AGENTS.md b/packages/tessera-learn/AGENTS.md index 18cffba..9519932 100644 --- a/packages/tessera-learn/AGENTS.md +++ b/packages/tessera-learn/AGENTS.md @@ -1,14 +1,14 @@ # AGENTS.md: Tessera Course Authoring Guide -Tessera is an **LMS tracking runtime** for interactive learning content. It handles SCORM 1.2 / SCORM 2004 / cmi5 / xAPI statements, progress state, completion and success rollup, persistence, and navigation gating, and gets out of the way for the presentation layer. +Tessera is an LMS-tracking runtime for interactive learning content (SCORM 1.2 / SCORM 2004 4e / cmi5 / static web). It owns tracking, progress, completion/success rollup, persistence, and navigation gating. You own the presentation layer. -Build a course with built-in components, your own (via the hooks), or any mix. This file is the canonical reference for any agent or human author working in a Tessera project. Read it before generating or editing course code. +This is the canonical reference for authoring a Tessera course. Read it before generating or editing course code. You are reading `node_modules/tessera-learn/AGENTS.md`; it updates when you bump `tessera-learn`. --- ## Workspaces -A Tessera project is a **workspace**: one `package.json` and one `node_modules` shared by **many courses**, plus a `shared/` design system. Each course is a self-contained folder under `courses/`. +A Tessera project is a **workspace**: one `package.json` and one `node_modules` shared by many courses, plus a `shared/` design system. Each course is a self-contained folder under `courses/`. ``` my-courses/ @@ -17,31 +17,32 @@ my-courses/ │ ├── Button.svelte │ └── tokens.css ├── courses/ -│ ├── starter-course/ # a course = a content folder (course.config.js, pages/, …) +│ ├── starter-course/ # a course = course.config.js, pages/, … │ └── / └── AGENTS.md / CLAUDE.md # pointers to this guide (workspace root only) ``` -**Everything else in this guide describes a single course** — i.e. the contents of one `courses//` folder (`course.config.js`, `layout.svelte`, `pages/`, `styles/`). +Rules: -**Open the workspace folder** (not an individual course) so this guide stays in scope and `$shared` resolves. +- **Open the workspace folder**, not an individual course — this keeps the guide in scope and `$shared` resolving. +- Everything below "Project Structure" describes a single course: the contents of one `courses//`. +- Name the course on every command. A bare command at the workspace root errors and lists courses; it never picks one. -### Working with courses +### Course commands ```bash -pnpm tessera new # scaffold courses// (no install — deps already here) -pnpm tessera duplicate # copy an existing course to courses// -pnpm tessera dev # run a command against a named course… -cd courses/ && pnpm exec tessera dev # …or cd into the course and run it without a name -pnpm tessera export # each course exports independently to its own LMS package -cd courses/ && pnpm exec tessera export # …this works for every command, not just dev +pnpm tessera new # scaffold courses// +pnpm tessera duplicate # copy a course to courses// +pnpm tessera dev # run a command against a named course +cd courses/ && pnpm exec tessera dev # …or cd in and omit the name +pnpm tessera export # each course exports independently ``` -A **bare command at the workspace root errors** and lists the available courses — it never silently picks one, so its meaning can't change as you add courses. Name the course, or `cd` into its folder. (The scaffolded root scripts — `pnpm dev`, `pnpm export`, … — pass straight through, so `pnpm dev ` runs that course and a bare `pnpm dev` errors just the same.) +The scaffolded root scripts (`pnpm dev`, `pnpm export`, …) pass through: `pnpm dev ` runs that course; bare `pnpm dev` errors. -### Sharing across courses with `$shared` +### `$shared` -`$shared` resolves to the workspace `shared/` directory, so any course can import the shared design system: +`$shared` resolves to the workspace `shared/` directory and is bundled into each course's export. Import from it in any course: ```svelte - -

Helpful information.

-
+

Helpful information.

``` --- ## Component Reference -All components import from `tessera-learn`. Nothing is loaded automatically; import only what you use. +All components import from `tessera-learn`. Nothing loads automatically. ### Callout -Styled box for highlighting information. +Styled box. A11y: `role="note"` with type-appropriate `aria-label`. Children become the body. | Prop | Type | Default | | ------ | --------------------------------------------- | -------- | | `type` | `"info" \| "warning" \| "tip" \| "important"` | `"info"` | -Children become the body. A11y: `role="note"` with type-appropriate `aria-label`. - ```svelte

Be careful.

``` ### Image -Lazy-loaded image with optional caption. Renders as `
`/`
`. +Lazy-loaded image, renders as `
`/`
`. -| Prop | Type | Description | -| ------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `src` | `string` | Image URL. `$assets/` prefix supported | -| `alt` | `string` | **Required unless `decorative`.** Alt text describing the image | -| `decorative` | `boolean` | Set `decorative={true}` for a purely ornamental image — renders an empty `alt` + `aria-hidden` so assistive tech skips it. Use this _instead of_ `alt`, not alongside it | -| `caption` | `string` | Optional caption | +| Prop | Type | Description | +| ------------ | --------- | ----------------------------------------------------------------------- | +| `src` | `string` | Image URL. `$assets/` prefix supported | +| `alt` | `string` | **Required unless `decorative`.** Alt text | +| `decorative` | `boolean` | Ornamental image — empty `alt` + `aria-hidden`. Use _instead of_ `alt` | +| `caption` | `string` | Optional caption | -Every `` must resolve to exactly one of: meaningful `alt` text, or `decorative={true}`. The validator errors if neither is present (a missing/empty `alt` is the most common accessibility miss). `decorative` is a **boolean** — write `decorative` or `decorative={true}`, never `decorative="true"` (a string is always truthy, so the validator rejects it). +Rules: -```svelte -System architecture diagram +- Every `` needs exactly one of: meaningful `alt`, or `decorative={true}`. The validator errors if neither is present. +- `decorative` is a boolean — write `decorative` or `decorative={true}`, never `decorative="true"` (a string is truthy and rejected). - +```svelte +System architecture diagram ``` ### Accordion / AccordionItem -Expandable panels. Only one open at a time. A11y: `aria-expanded`, `aria-controls`, `role="region"`, keyboard Enter/Space. +Expandable panels, one open at a time. A11y: `aria-expanded`, `aria-controls`, `role="region"`, Enter/Space. ```svelte @@ -296,28 +270,24 @@ Expandable panels. Only one open at a time. A11y: `aria-expanded`, `aria-control ### Carousel / CarouselSlide -Slide-based viewer. A11y: `role="region"`, `aria-roledescription="carousel"`, arrow keys, mobile swipe. +Slide viewer. A11y: `role="region"`, `aria-roledescription="carousel"`, arrow keys, swipe. ```svelte -

Step 1

-

Plan.

-

Step 2

-

Build.

-

Step 3

-

Deploy.

+ +

Step 1

+

Plan.

+
+ +

Step 2

+

Build.

+
``` ### RevealModal -Modal triggered by user interaction. Uses Svelte 5 snippets for `trigger` and `content`. A11y: `role="dialog"`, `aria-modal="true"`, focus trap, Escape to close. +Modal triggered by interaction. Uses Svelte 5 snippets. A11y: `role="dialog"`, `aria-modal`, focus trap, Escape to close. | Prop | Type | Description | | --------- | --------- | --------------------------------- | @@ -339,37 +309,25 @@ Modal triggered by user interaction. Uses Svelte 5 snippets for `trigger` and `c YouTube/Vimeo iframe (auto-detected, responsive 16:9) or native `