@playcademy/sdk 0.16.1-beta.2 → 0.16.1-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -139,9 +139,25 @@ const completed = await client.timeback.assessments.submit(attempt.attemptId, {
139
139
  })
140
140
  ```
141
141
 
142
- `start()` resumes an unfinished attempt or selects the next live test. Save payloads are
143
- question deltas, but each included question replaces its complete response state; use `null` to
144
- clear an answer. Keep the returned `responseVersion` and send it with the next mutation.
142
+ `start()` resumes a compatible unfinished attempt or selects content for a fixed test or standards
143
+ review. Save payloads merge at both the item and response levels; omitted values remain unchanged,
144
+ and `null` clears one response. Keep the returned `responseVersion` and send it with the next
145
+ mutation.
146
+
147
+ The returned `flow` is authoritative and is derived from `purpose`; callers do not configure
148
+ navigation, feedback, and submission independently:
149
+
150
+ - `attempt-submit` is used for diagnostic, end-of-course, and mastery attempts. Responses remain
151
+ editable through `save()` until `submit()` finalizes the whole attempt and returns feedback.
152
+ - `item-submit` is used for review attempts. Submit each administered item with `submitItem()`.
153
+ That operation atomically saves the item's responses, locks them, and returns safe immediate
154
+ feedback. Give each item request its own stable `submissionId` and reuse that ID for an ambiguous
155
+ retry; the returned canonical `itemSubmissions` ledger identifies committed items after retry or
156
+ resume.
157
+
158
+ The host rejects `submitItem()` for attempt-submit flows, rejects `submit()` until an item-submit
159
+ attempt has administered at least one item, and enforces `expectedResponseVersion` for every
160
+ mutation.
145
161
 
146
162
  For local development, import the current ordered catalog before starting the dev host:
147
163
 
@@ -172,6 +188,46 @@ OAuth provider connections (Discord, Google, etc.).
172
188
  await client.identity.connect({ provider: 'discord' })
173
189
  ```
174
190
 
191
+ ### `client.embed`
192
+
193
+ Launch other Playcademy games as embedded children (platform mode only). With `timeback`, the child's play time and completion are recorded on this game's Timeback course. Interrupted launches resume automatically when the child streams checkpoints; the `resume` option tunes or disables the persistence.
194
+
195
+ ```typescript
196
+ const session = client.embed.launch({
197
+ slug: 'math-cakes',
198
+ container: overlayEl,
199
+ intent: { lessonId: 'two-digit-add', eLevel: 'E2' },
200
+ timeback: { activityId: 'two-digit-add-e2', grade: 2, subject: 'Math' },
201
+ })
202
+
203
+ const activity = await session.finished
204
+
205
+ if (activity.status === 'completed') {
206
+ await activity.end({
207
+ correctQuestions: activity.correct,
208
+ totalQuestions: activity.total,
209
+ xpAwarded: 10,
210
+ })
211
+ }
212
+
213
+ await session.closed // iframe unmounted; dismiss surrounding UI
214
+ ```
215
+
216
+ ### `client.parent`
217
+
218
+ The launch context when this game was launched by a parent game (`mode: 'child'`); `null` in every other mode. In child mode, activity reporting is relayed to the parent automatically, and `xpAwarded` becomes a suggestion the parent may override. Stream `client.parent.checkpoint(state)` to make interrupted launches resumable; the state comes back as `client.parent.resume`. Narrow with `isChildLaunched()` to get the relaxed types.
219
+
220
+ ```typescript
221
+ import { isChildLaunched } from '@playcademy/sdk'
222
+
223
+ if (isChildLaunched(client)) {
224
+ const { lessonId, eLevel } = client.parent.intent
225
+ startLesson(lessonId, eLevel)
226
+ // ...later: xpAwarded may be omitted; the parent decides the award
227
+ await client.timeback.endActivity({ correctQuestions, totalQuestions })
228
+ }
229
+ ```
230
+
175
231
  ### `client.demo`
176
232
 
177
233
  Demo mode for anonymous players on the landing page.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The child-catalog contract: what a child game publishes about its
3
+ * deliverable lessons, per lesson id and level. A parent course authority
4
+ * resolves its lesson references against this document at compile time and
5
+ * fails closed at runtime on anything not `ready` in production.
6
+ *
7
+ * Ownership and flow: each child repo generates `.playcademy/catalog.json`
8
+ * from its own registry (`playcademy catalog generate`); a sync workflow
9
+ * carries copies into parent repos. Children never read the parent's
10
+ * compiled authority — this file and the launch payload are the entire
11
+ * surface between them.
12
+ *
13
+ * The document deliberately carries no app identity. The consuming repo
14
+ * assigns the namespace key (e.g. 'form', 'math-cakes') from sync
15
+ * provenance via its own repo → app map, so a child cannot misdeclare
16
+ * who it is and a typo cannot mint a phantom namespace.
17
+ */
18
+ /** Contract identifier carried by every catalog document. */
19
+ declare const CHILD_CATALOG_CONTRACT: 'playcademy-child-catalog-v1';
20
+ /** The completion-evidence contract a catalog declares its runs report. */
21
+ declare const CHILD_ATTEMPT_CONTRACT: 'playcademy-child-attempt-v1';
22
+ /** Delivery levels a catalog may declare (serving-id dialect, lowercase). */
23
+ declare const CATALOG_LEVELS: readonly ['e1', 'e2', 'e3', 'e4'];
24
+ type CatalogLevel = (typeof CATALOG_LEVELS)[number];
25
+ /**
26
+ * ready: real content. simulated: placeholder — playable for preview and
27
+ * simulation, never creditable in production. unavailable: intentionally
28
+ * absent at this level. Consumers must treat unknown values and missing
29
+ * levels as unavailable (fail closed).
30
+ */
31
+ declare const CATALOG_READINESS: readonly ['ready', 'simulated', 'unavailable'];
32
+ type CatalogReadiness = (typeof CATALOG_READINESS)[number];
33
+ interface ChildCatalog {
34
+ /** The contract identifier. */
35
+ contract: typeof CHILD_CATALOG_CONTRACT;
36
+ /** The completion-evidence contract a catalog declares its runs report. */
37
+ evidence: typeof CHILD_ATTEMPT_CONTRACT;
38
+ /** The tool that generated this document (repo-relative path). */
39
+ generatedBy: string;
40
+ /** The in-repo source of truth the document was derived from. */
41
+ generatedFrom: string;
42
+ /** Lesson id → level → readiness. */
43
+ deliveries: Record<string, Partial<Record<CatalogLevel, CatalogReadiness>>>;
44
+ }
45
+
46
+ export { CATALOG_LEVELS, CATALOG_READINESS, CHILD_ATTEMPT_CONTRACT, CHILD_CATALOG_CONTRACT };
47
+ export type { CatalogLevel, CatalogReadiness, ChildCatalog };
@@ -0,0 +1,23 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
13
+ // src/contracts/child-catalog.ts
14
+ var CHILD_CATALOG_CONTRACT = "playcademy-child-catalog-v1";
15
+ var CHILD_ATTEMPT_CONTRACT = "playcademy-child-attempt-v1";
16
+ var CATALOG_LEVELS = ["e1", "e2", "e3", "e4"];
17
+ var CATALOG_READINESS = ["ready", "simulated", "unavailable"];
18
+ export {
19
+ CHILD_CATALOG_CONTRACT,
20
+ CHILD_ATTEMPT_CONTRACT,
21
+ CATALOG_READINESS,
22
+ CATALOG_LEVELS
23
+ };