@happyvertical/smrt-education 0.57.39 → 0.57.41
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/AGENTS.md +4 -0
- package/agents/enrollment-notes.md +42 -0
- package/agents/learner-plan.md +66 -0
- package/agents/submission-service.md +6 -1
- package/agents/workbook-service.md +39 -3
- package/dist/chunks/{workbook-photo-service-DCmqeWLd.js → workbook-photo-service-D5DUgh-C.js} +527 -217
- package/dist/chunks/workbook-photo-service-D5DUgh-C.js.map +1 -0
- package/dist/enrollment-note-service.d.ts +24 -0
- package/dist/enrollment-note-service.d.ts.map +1 -0
- package/dist/enrollment-notes.d.ts +22 -0
- package/dist/enrollment-notes.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +297 -50
- package/dist/index.js.map +1 -1
- package/dist/ingestion.js +1 -1
- package/dist/learner-plan-service.d.ts +46 -0
- package/dist/learner-plan-service.d.ts.map +1 -0
- package/dist/learner-service.d.ts +1 -1
- package/dist/learner-service.d.ts.map +1 -1
- package/dist/manifest.json +2338 -1377
- package/dist/smrt-knowledge.json +360 -14
- package/dist/submission-service.d.ts +1 -0
- package/dist/submission-service.d.ts.map +1 -1
- package/dist/workbook-completion.d.ts +38 -0
- package/dist/workbook-completion.d.ts.map +1 -0
- package/dist/workbook-contracts.d.ts +33 -0
- package/dist/workbook-contracts.d.ts.map +1 -1
- package/dist/workbook-service.d.ts +6 -1
- package/dist/workbook-service.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/chunks/workbook-photo-service-DCmqeWLd.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -45,3 +45,7 @@ assignment alone never creates learning history or grants learner inbox access.
|
|
|
45
45
|
Publisher catalog previews use [the preview contract](agents/catalog-previews.md).
|
|
46
46
|
Keep independent image rights and source revisions; serve via `CatalogPreviewService`
|
|
47
47
|
with live actor/tenant authorization, never direct provider image URLs.
|
|
48
|
+
|
|
49
|
+
Enrollment Plan projections and guardian-only parent notes use
|
|
50
|
+
[the Plan contract](agents/learner-plan.md). Keep awaiting review separate from
|
|
51
|
+
Continue; note authority/provenance never grants learner access or learning evidence.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Enrollment parent notes
|
|
2
|
+
|
|
3
|
+
`LearnerPlanService` provides `listEnrollmentNotes` and `addEnrollmentNote` on
|
|
4
|
+
its existing actor-bound learner transaction boundary. Both require an exact
|
|
5
|
+
owning tenant, learner and enrollment plus a verified directed guardian
|
|
6
|
+
relationship. Own learners are always denied, even with a permissive host grant.
|
|
7
|
+
The host must authorize `education.learner.notes.read` and
|
|
8
|
+
`education.learner.notes.add`, verifying the current relationship type, terms,
|
|
9
|
+
session and permission using the supplied exact `executor`. Membership alone
|
|
10
|
+
never grants note access. Catalog access does not grant note authority.
|
|
11
|
+
|
|
12
|
+
Add accepts `{ ...LearnerRequest, enrollmentId, text, requestKey }`. Text is
|
|
13
|
+
nonblank, at most `ENROLLMENT_NOTE_MAX_LENGTH` (4000 UTF-16 code units), and
|
|
14
|
+
retained verbatim as plain text; render with text escaping, never as HTML or
|
|
15
|
+
markdown. Control characters other than tab/newline/carriage return are rejected.
|
|
16
|
+
The request key is nonblank, at most 200 code units, without control characters.
|
|
17
|
+
Author, author label and creation time are server-derived; extra request properties are ignored.
|
|
18
|
+
The data-only result is `{ id, enrollmentId, learnerId, text, authorUserId, authorLabel,
|
|
19
|
+
createdAt: Date }`. List order is creation time then id.
|
|
20
|
+
|
|
21
|
+
Notes are append-only. Retrying the same tenant/enrollment/requestKey and text
|
|
22
|
+
returns the original row, author, label and time; changing text rejects. PostgreSQL
|
|
23
|
+
serializes writes on the enrollment row and uses a natural-key unique index;
|
|
24
|
+
embedded databases use the owning service transaction queue. Notes share
|
|
25
|
+
`withTransaction` / `withExecutor`, including rollback and poisoned mutations.
|
|
26
|
+
No progress, submission, assessment, feedback or learning history changes occur.
|
|
27
|
+
|
|
28
|
+
`EnrollmentParentNote` and its collection are trusted persistence APIs, never
|
|
29
|
+
request handlers. Generated REST, CLI, MCP and AI surfaces are closed. Persisted
|
|
30
|
+
model saves and deletes reject; creation uses strict insert so natural-key
|
|
31
|
+
collisions cannot rewrite provenance. The internal persisted `recordedAt` maps
|
|
32
|
+
to DTO `createdAt`. Hosts must use the service to derive provenance and authority.
|
|
33
|
+
Normal additive manifest migration creates `enrollment_parent_notes`.
|
|
34
|
+
|
|
35
|
+
`src/__tests__/enrollment-note-workflows.ts` contains shared SQLite/PostgreSQL
|
|
36
|
+
assertions for authority, provenance, validation, concurrency and transactions.
|
|
37
|
+
No full DuckDB workflow support is claimed.
|
|
38
|
+
|
|
39
|
+
`authorLabel` snapshots only the validated actor User's linked Profile name on
|
|
40
|
+
creation, using the same executor. Trim it and cap it at 200 code units; absent
|
|
41
|
+
or blank names use `Parent`. List and retry return the persisted label without
|
|
42
|
+
looking up previous authors, so later profile renames never rewrite history.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Enrollment Plan reads
|
|
2
|
+
|
|
3
|
+
`LearnerPlanService(db, authorizeLearner, authorizeCatalog)` extends the existing
|
|
4
|
+
LearnerService transaction/active actor boundary and adds private parent notes
|
|
5
|
+
([notes contract](enrollment-notes.md)). Its `withTransaction` and `withExecutor`
|
|
6
|
+
services retain the Plan methods. Root exports `EnrollmentPlanView` and
|
|
7
|
+
`PlanLessonView`; all results are data only.
|
|
8
|
+
|
|
9
|
+
`listPlan(request)` returns exact learner enrollments ordered by sortOrder/id.
|
|
10
|
+
`getEnrollmentPlan({...request,enrollmentId})` verifies that exact tenant,
|
|
11
|
+
learner, enrollment and curriculum before reading its course. Missing or denied
|
|
12
|
+
course visibility returns `availability: 'unavailable'`, `course: null`, and
|
|
13
|
+
empty lessons/evidence; it does not interrupt other authorized enrollments.
|
|
14
|
+
Actor/enrollment denial still rejects the request. Operational database errors
|
|
15
|
+
are not disguised as missing material.
|
|
16
|
+
|
|
17
|
+
The course DTO contains only id, title, subject, summary, modality and sourceKey.
|
|
18
|
+
Technical unfiled capture scaffolding has sourceKey exactly `unfiled-work`;
|
|
19
|
+
consumers exclude it by identity, never by title. The DTO does not invent a cover
|
|
20
|
+
or claim any source/asset preview binding. It returns no teacher or answer-key
|
|
21
|
+
assets. Lessons preserve catalog section/lesson order and existing role-filtered
|
|
22
|
+
progress, including private workbook feedback rules. Optional workbookActivityId
|
|
23
|
+
is resolved for the exact tenant/learner/enrollment/lesson; consumers route that
|
|
24
|
+
work to their workbook interface, not generic scan capture.
|
|
25
|
+
|
|
26
|
+
Workbook progress uses the same explicit parent completion projection as Work.
|
|
27
|
+
Old grade-derived complete/skipped rows without a current decision project in
|
|
28
|
+
progress with completedAt null; they cannot contribute a completion timestamp to
|
|
29
|
+
progressEvidence. Later analysis of the same attempt retains a parent's decision;
|
|
30
|
+
a new correction or practice attempt reopens it. Ordinary lesson progress is
|
|
31
|
+
unchanged. See [the workbook contract](workbook-service.md).
|
|
32
|
+
|
|
33
|
+
For required-online lessons, optional sourceUrl comes only from the same
|
|
34
|
+
catalog-authorized Lesson.externalUrl and must be HTTPS without credentials.
|
|
35
|
+
Answer URLs and asset locations are never projected. A missing or unsafe online
|
|
36
|
+
URL is unavailable to Continue and cannot block a later usable lesson. Consumers
|
|
37
|
+
revalidate links at their own browser boundary and display honest unavailable
|
|
38
|
+
material states.
|
|
39
|
+
|
|
40
|
+
`nextActionableLessonId` considers planned/active enrollments and only unstarted
|
|
41
|
+
or in-progress lessons with usable material. Planned is usable because normal
|
|
42
|
+
`enroll` creates planned enrollments and the base workflow has no activation API.
|
|
43
|
+
Paused/completed/dropped enrollments have no next action. Complete/skipped lessons
|
|
44
|
+
and submitted/needs_review work never instruct rework. `awaitingReviewLessonIds`
|
|
45
|
+
is separate from Continue. Reads never change progress or create learning history.
|
|
46
|
+
|
|
47
|
+
`progressEvidence` is nullable `{kind: 'started'|'completed',at,lessonId}` from
|
|
48
|
+
visible durable progress start/completion timestamps. It is the newest such
|
|
49
|
+
recorded timestamp, **not** latest actual work. Repeated starts preserve the
|
|
50
|
+
original startedAt. Display it as “Last recorded start/completion”, never infer
|
|
51
|
+
activity from updatedAt, enrollment ordering, notes, or missing timestamps.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { LearnerPlanService, ENROLLMENT_NOTE_MAX_LENGTH, validateEnrollmentNote }
|
|
55
|
+
from '@happyvertical/smrt-education';
|
|
56
|
+
const service = new LearnerPlanService(db, authorizeLearner, authorizeCatalog);
|
|
57
|
+
const plan = await service.listPlan(serverLearnerRequest);
|
|
58
|
+
validateEnrollmentNote(text, requestKey); // input validation, not authorization
|
|
59
|
+
const note = await service.addEnrollmentNote({
|
|
60
|
+
...serverGuardianRequest, enrollmentId, text, requestKey,
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Build before consuming the public package; deploy its ordinary additive manifest
|
|
65
|
+
migration before using notes. No runtime handler creates application schema.
|
|
66
|
+
Shared Plan and note workflows run against SQLite and PostgreSQL.
|
|
@@ -45,7 +45,12 @@ non-authoritative Grade until guardian review.
|
|
|
45
45
|
`reviewSubmission` accepts an existing authorized submission and optional score
|
|
46
46
|
and feedback. `attestLesson` creates/reuses an Attestation for a matching progress
|
|
47
47
|
item without requiring uploads. Both require a verified guardian and create a
|
|
48
|
-
new guardian Grade
|
|
48
|
+
new guardian Grade and set submission to `graded`. Ordinary non-workbook progress
|
|
49
|
+
becomes `complete`. Workbook-backed progress instead uses its explicit parent
|
|
50
|
+
completion decision; grading alone leaves it in progress, including through a
|
|
51
|
+
plain SubmissionService instance. Existing explicit completion on the current
|
|
52
|
+
attempt is retained. The owning workbook join determines this policy, never a
|
|
53
|
+
caller flag.
|
|
49
54
|
Omitted/null score is unscored; zero is a real score. The latest guardian grade
|
|
50
55
|
wins over auto/AI/instructor proposals, and its score replaces progress's score.
|
|
51
56
|
Review history is retained. ExternalCompletion is available for trusted server
|
|
@@ -187,12 +187,48 @@ the authorized education timeline independently of optional scratch processing.
|
|
|
187
187
|
Workbook feedback is projected only from the revision/release workflow. The base
|
|
188
188
|
`SubmissionService` recognizes authoritative `WorkbookActivity` lesson ownership,
|
|
189
189
|
including calls through a plain service instance. Own-learner compatibility views
|
|
190
|
-
withhold Grade and
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
withhold Grade and bestScore. Every workbook progress projection uses the explicit
|
|
191
|
+
parent decision for status and completedAt; historical grade-derived completion
|
|
192
|
+
alone is Doing with no completion date. Ordinary non-workbook projections retain
|
|
193
|
+
their existing behavior.
|
|
193
194
|
This applies in both feedback policy modes; direct feedback remains provisional
|
|
194
195
|
and does not authorize compatibility Grade disclosure.
|
|
195
196
|
|
|
197
|
+
## Explicit parent completion
|
|
198
|
+
|
|
199
|
+
`completeWorkbookActivity` requires the current verified guardian, exact activity,
|
|
200
|
+
submissionId, expectedAttemptId, explicit expectedHeadId (including null), and a
|
|
201
|
+
bounded requestKey. The SDK independently denies own learners for
|
|
202
|
+
`education.learner.complete`, even when a host callback grants it. The head token
|
|
203
|
+
is the latest guardian revision, otherwise latest AI revision, otherwise null;
|
|
204
|
+
null permits a parent's judgment without any assessment. The decision and progress
|
|
205
|
+
update share the authorized transaction and learner serialization lock. No grade,
|
|
206
|
+
assessment, feedback release, or learner visibility is created by completion.
|
|
207
|
+
Generic guardian grading of workbook submissions also cannot complete work.
|
|
208
|
+
|
|
209
|
+
`WorkbookCompletionDecision` retains immutable server actor/time, attempt,
|
|
210
|
+
submission, head provenance, and retry key. Exact retries return that historical
|
|
211
|
+
decision even after a correction; changed retries and stale selectors reject with
|
|
212
|
+
`WorkbookCompletionConflictError` (changed_retry, stale_attempt, stale_head, or
|
|
213
|
+
already_complete). Hosts should acknowledge recording and reread current state,
|
|
214
|
+
never interpret a historical retry as completing a newer attempt.
|
|
215
|
+
|
|
216
|
+
Completion persists across later assessment or guardian review on the same
|
|
217
|
+
attempt. A newly captured correction or independent practice attempt makes the
|
|
218
|
+
previous decision historical and returns the current work to Doing. Corrections
|
|
219
|
+
retain their episode and must name the current predecessor; fresh practice keeps
|
|
220
|
+
its existing separate episode path. No legacy Grade is converted into a decision.
|
|
221
|
+
|
|
222
|
+
Activity lists and timelines expose own-safe `completion` (status and nullable
|
|
223
|
+
completedAt), currentAttemptId, and latestSubmissionId. These current pointers
|
|
224
|
+
are independent of history pagination. Timeline completionContext is guardian-only
|
|
225
|
+
and carries the selectors to display and later submit verbatim; own learners
|
|
226
|
+
receive null. Per-attempt completionDecision provenance is also guardian-only.
|
|
227
|
+
The existing attempt headId continues to mean guardian review head.
|
|
228
|
+
|
|
229
|
+
Deploy the ordinary additive manifest migration before recording decisions. Reads
|
|
230
|
+
of an unmigrated decision table report Doing; runtime handlers never create it.
|
|
231
|
+
|
|
196
232
|
Generic capture/resubmission rejects workbook enrollment or lesson scaffolding,
|
|
197
233
|
including idempotent retries. Only the protected exact-activity owning workflow
|
|
198
234
|
can capture workbook work. Hosts must call public
|