recess-cli 1.0.1 → 1.3.0
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 +56 -3
- package/dist/args.js +43 -2
- package/dist/cli.js +1090 -2
- package/dist/setup.js +40 -2
- package/dist/skill-update.js +150 -0
- package/dist/skills-cache.js +0 -0
- package/package.json +9 -2
- package/scripts/postinstall.mjs +44 -0
- package/skill/recess-cli/SKILL.md +204 -14
- package/skill/recess-cli/reference/cancellation-credits.md +1 -1
- package/skill/recess-cli/reference/class-ops-reschedule.md +1 -1
- package/skill/recess-cli/reference/goal-authoring.md +274 -0
|
@@ -14,7 +14,7 @@ CLI cannot toggle the flag — web admin course settings only. Do not stop at "e
|
|
|
14
14
|
|
|
15
15
|
## Worked example (2026-07-23)
|
|
16
16
|
|
|
17
|
-
- Cohort: Space Technology & Rocket Launches (`
|
|
17
|
+
- Cohort: Space Technology & Rocket Launches (resolve its id with `cohorts search`)
|
|
18
18
|
- Course: Current Events in Space Tech & Rockets — `allowFlexibleScheduling: false`
|
|
19
19
|
- Ask: move today up 10 minutes (Starship)
|
|
20
20
|
- Usual slot: Thu 15:45 America/Edmonton → UTC `21:45`
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Authoring learning content from the CLI
|
|
2
|
+
|
|
3
|
+
The workflow behind `skills`, `goal-templates`, `goals`, and `mesa files`. Read this before the
|
|
4
|
+
first write; the tool→command mapping and the one-way rules live in `SKILL.md` under "Learning-content
|
|
5
|
+
contract".
|
|
6
|
+
|
|
7
|
+
The point of this surface is not that an agent *can* create a template — the API always allowed
|
|
8
|
+
that. It is that an agent can create a template **as good as one authored through `recess.gg/ai`**,
|
|
9
|
+
because it loads the same authoring skills the in-product tutor loads. Skipping step 0 gives you a
|
|
10
|
+
structurally valid template that is pedagogically wrong, and nothing downstream will catch it.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 0. Load the authoring skills. Always. First.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
recess --json skills get os-v2-goal-template-builder --all-references
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`--all-references` pulls `references/deterministic-workflow-setup.md` in the same call — that
|
|
21
|
+
document is the catalog of what the deterministic handlers can express, and you cannot author a
|
|
22
|
+
correct spec without it. Without the flag you get SKILL.md plus a reference *index*, and each
|
|
23
|
+
reference is a separate `--reference <name>` call (the same two-step the in-product agent uses).
|
|
24
|
+
|
|
25
|
+
Responses cache for about an hour under `~/.recess-cli/skills-cache/`. Pass `--refresh` when someone
|
|
26
|
+
has just edited a skill.
|
|
27
|
+
|
|
28
|
+
These documents are proprietary and are served, never shipped. Do not copy their text anywhere.
|
|
29
|
+
|
|
30
|
+
### Which research doc, for what
|
|
31
|
+
|
|
32
|
+
"Deep research" is not one method here — pick by what you are researching. Every one of these assumes
|
|
33
|
+
OSAgent research tools you do not have; SKILL.md's "Research tools → your own harness" says what to
|
|
34
|
+
substitute, and names the one real gap (`fetch_page_structure`).
|
|
35
|
+
|
|
36
|
+
| Researching | Load |
|
|
37
|
+
|---|---|
|
|
38
|
+
| An external platform's assignable content, to bake a queue into a template | `os-v2-goal-template-builder --all-references` → §"The research loop" + §"The validation loop" |
|
|
39
|
+
| Content for a module-backed goal workspace | `os-v2-goal-builder --all-references` → `research-protocol.md` (wave dispatch, lookup order, verification rules, output file shape) |
|
|
40
|
+
| A goal from an uploaded curriculum (PDF, scope-and-sequence) | `os-v2-goal-builder --reference curriculum-source` |
|
|
41
|
+
| A goal for one kid, from scratch, in depth | `goal-creation --reference structured-plan` (S1–S6; S4 is the parallel deep research, S2 carries the depth cascade) + `--reference subagent-tasks` for the five researcher prompts |
|
|
42
|
+
| The same, but the ask is small | `goal-creation --reference quick-discovery` — it names its own escalation trigger into the structured flow |
|
|
43
|
+
| One platform, deeply (pedagogy, reviews) | `pipeline-platform-research --all-references` |
|
|
44
|
+
| The kid, before any of the above | `student-research` |
|
|
45
|
+
|
|
46
|
+
Research before you draft, not after. The spec's `handler.config` must arrive **fully materialized** —
|
|
47
|
+
the apply endpoint never fetches anything, so whatever you did not bake in does not exist at apply
|
|
48
|
+
time, and there is no later pass that fills it in.
|
|
49
|
+
|
|
50
|
+
**If the request cannot be expressed by a supported handler, report that and stop.** The skill says
|
|
51
|
+
this explicitly and it is the single most important instruction in it. A template that "sort of"
|
|
52
|
+
does the job becomes a global record every future apply reads.
|
|
53
|
+
|
|
54
|
+
## 1. Decide the kind before drafting
|
|
55
|
+
|
|
56
|
+
`kind` is the real decision; `setupMode` is not a choice (see §5).
|
|
57
|
+
|
|
58
|
+
| Kind | What a student gets | Use when |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `SIMPLE` | a description-only goal plus linked todos — no modules, no Mesa workspace | ongoing habits, platform practice targets, score/streak goals, free-choice reading |
|
|
61
|
+
| `BLUEPRINT` | a finishable learning path, built per student by the planner or copied from a snapshot | a course with a sequence and an end |
|
|
62
|
+
|
|
63
|
+
The skill phrases this as a tutor-facing question with three options (the third, "Prebuilt", is a
|
|
64
|
+
BLUEPRINT that also carries an instant-apply snapshot). You have no `ask_user_question` tool — ask
|
|
65
|
+
the human directly, in the skill's language, and wait. Do not say "materialize",
|
|
66
|
+
"module-backed", or "snapshot" to a tutor.
|
|
67
|
+
|
|
68
|
+
A MODULE_BACKED spec **requires** `BLUEPRINT`; the server enforces it, and it additionally refuses to
|
|
69
|
+
apply a MODULE_BACKED template that has no snapshot. Build a complete Mesa draft and capture it with
|
|
70
|
+
the CLI workflow in §8 before applying the template.
|
|
71
|
+
|
|
72
|
+
## 2. Write one template file
|
|
73
|
+
|
|
74
|
+
`validate-spec` and `create` read the same document, so you iterate on one artifact:
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
{
|
|
78
|
+
"slug": "kebab-case-unique", // required, immutable-ish: it is the human handle
|
|
79
|
+
"title": "Daily Reading Habit", // required
|
|
80
|
+
"description": "One line a tutor reads in the library.", // required
|
|
81
|
+
"kind": "SIMPLE", // SIMPLE | BLUEPRINT (default SIMPLE)
|
|
82
|
+
"setupAudience": "KID_FRIENDLY", // KID_FRIENDLY | PARENT_SETUP
|
|
83
|
+
"emoji": "📚",
|
|
84
|
+
"category": "reading",
|
|
85
|
+
"tags": ["reading", "ela"], // an array, or a comma string
|
|
86
|
+
"sortOrder": 0,
|
|
87
|
+
"isStarter": false,
|
|
88
|
+
"agentInstructions": "…", // required
|
|
89
|
+
"outputTemplate": "…",
|
|
90
|
+
"setupWorkflowSpec": { /* the fixed wizard — a real object, never a JSON string */ }
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Unknown keys are dropped, so a file made by editing `goal-templates get <id>` output works —
|
|
95
|
+
`version`, `createdById`, `createdAt` are ignored rather than rejected. `setupMode` must be absent
|
|
96
|
+
(or `DETERMINISTIC_WORKFLOW`); anything else is refused locally.
|
|
97
|
+
|
|
98
|
+
## 3. Iterate on `validate-spec` — it writes nothing
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
recess --json goal-templates validate-spec --file ./template.json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Valid:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{"ok":true,"data":{"slug":"…","kind":"SIMPLE","valid":true,
|
|
108
|
+
"setupHandler":"TOOL_GENERATED_TODO_SETUP","goalShape":"SIMPLE",
|
|
109
|
+
"stepKeys":["students"],"sha256":"…",
|
|
110
|
+
"totals":{"subjects":0,"recipes":0,"plans":0,"queueItems":0,"sourceUrls":0,"missingCoverage":0}}}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Invalid returns `"valid": false` with the backend's verbatim message — read it and fix the file.
|
|
114
|
+
`ok` stays `true` because an invalid spec is an expected step in an authoring loop, not a failure of
|
|
115
|
+
the command. Handler configs are `.strict()`, so a guessed config fails with both missing-field and
|
|
116
|
+
`unrecognized_keys` errors at once; that is your cue to go back to
|
|
117
|
+
`references/deterministic-workflow-setup.md` rather than guessing again.
|
|
118
|
+
|
|
119
|
+
`stepKeys` is the contract for §6: those are exactly the keys your answers file must carry.
|
|
120
|
+
|
|
121
|
+
## 4. Create — read the server-resolved preview
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
recess --json goal-templates create --file ./template.json # preview, exit 2
|
|
125
|
+
recess --json goal-templates create --file ./template.json --confirm
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The unconfirmed run performs one read-only validation and puts its result in `preview.details`:
|
|
129
|
+
|
|
130
|
+
| Field | Why it is in the approval request |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `resolvedSetupHandler` | which handler actually runs — derived from the spec, not from what you wrote in the file |
|
|
133
|
+
| `resolvedGoalShape` | `SIMPLE` vs `MODULE_BACKED`; decides whether a snapshot is required to apply |
|
|
134
|
+
| `wizardStepKeys` | the questions a tutor will be asked, and the answer keys `apply` will demand |
|
|
135
|
+
| `specInventory` | subjects / recipes / plans / queue items / source URLs the template starts with |
|
|
136
|
+
|
|
137
|
+
Show all of it. `action` alone does not tell a human what the template does.
|
|
138
|
+
|
|
139
|
+
If the spec is invalid at this point the command fails with `invalid_spec` and creates nothing —
|
|
140
|
+
even with `--confirm`. That ordering is deliberate: an approved-but-broken template must not land.
|
|
141
|
+
|
|
142
|
+
## 5. What is permanent
|
|
143
|
+
|
|
144
|
+
**Every template created here is `setupMode: DETERMINISTIC_WORKFLOW` and cannot be converted back.**
|
|
145
|
+
There is no AI_CHAT creation path and no downgrade — the server refuses the conversion outright.
|
|
146
|
+
Legacy AI_CHAT templates remain readable and editable; you will never create one.
|
|
147
|
+
|
|
148
|
+
So the confirmation gate carries more weight here than on a reversible write. What *is* recoverable:
|
|
149
|
+
metadata (`set-metadata`) and the row itself (`delete` is a soft delete, and goals already applied
|
|
150
|
+
from the template are unaffected).
|
|
151
|
+
|
|
152
|
+
## 6. Apply to a kid or a roster
|
|
153
|
+
|
|
154
|
+
Answers are a JSON file keyed by the spec's `stepKeys`:
|
|
155
|
+
|
|
156
|
+
```jsonc
|
|
157
|
+
{ "students": ["<kid-uuid>", "<kid-uuid>"], "grade": "5" }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
recess --json goal-templates apply <id-or-slug> --answers-file ./answers.json --dry-run
|
|
162
|
+
recess --json goal-templates apply <id-or-slug> --answers-file ./answers.json # preview
|
|
163
|
+
recess --json goal-templates apply <id-or-slug> --answers-file ./answers.json --confirm
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`--dry-run` is a read and does not gate. The unconfirmed form runs the same backend dry run to build
|
|
167
|
+
its preview, so `details.counts` and `details.results` are the backend's own plan, per student:
|
|
168
|
+
|
|
169
|
+
- `created` — a new goal + todo
|
|
170
|
+
- `skipped_existing` — idempotent; re-applying does not duplicate
|
|
171
|
+
- `error` — that student failed; the others still committed (failure is per item, never per batch)
|
|
172
|
+
|
|
173
|
+
`details.missingCoverage` lists content the planner could not resolve. Surface it — an apply that
|
|
174
|
+
"succeeded" with missing coverage produced a thinner goal than intended.
|
|
175
|
+
|
|
176
|
+
`apply-starter` is the one-tap starter path: one template, one student, no dry run, so its preview is
|
|
177
|
+
offline. It is gated per acting admin behind the `school-onboarding-v1` flag and **404s when the flag
|
|
178
|
+
is off** — which reads like a missing template but is not.
|
|
179
|
+
|
|
180
|
+
## 7. A goal directly on a kid
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
recess --json goals list --student <kid-id>
|
|
184
|
+
recess --json goals create --student <kid-id> --title "…" --description-file ./goal.md --confirm
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
This creates a **description-only** goal: no GoalModules, no Mesa workspace. For a real course,
|
|
188
|
+
apply a BLUEPRINT template instead. `--description-file` exists because a good goal description is
|
|
189
|
+
long and prose-shaped; a shell mangles it.
|
|
190
|
+
|
|
191
|
+
A 409 `GOAL_LIMIT_REACHED` means the kid is at capacity and nothing was created — do not retry, ask
|
|
192
|
+
the human which goal to retire.
|
|
193
|
+
|
|
194
|
+
Load `goal-creation` (and `student-research` to read the kid first) before writing the description.
|
|
195
|
+
An unresearched goal is the failure mode this whole surface exists to prevent.
|
|
196
|
+
|
|
197
|
+
## 8. Author, capture, and read workspaces
|
|
198
|
+
|
|
199
|
+
For a new Prebuilt/instant-apply course, author the complete OS-V2 tree locally and upsert it into a
|
|
200
|
+
named draft. The directory root becomes `drafts/<slug>/workspace` in the student's Mesa repo:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
recess --json mesa files write --student <kid-id> --draft <draft-slug> --source-dir ./workspace
|
|
204
|
+
# show the preview, obtain approval, then rerun unchanged:
|
|
205
|
+
recess --json mesa files write --student <kid-id> --draft <draft-slug> --source-dir ./workspace --confirm
|
|
206
|
+
|
|
207
|
+
recess --json goal-templates capture-snapshot <id-or-slug> --source-draft <draft-slug> --student <kid-id> --dry-run
|
|
208
|
+
recess --json goal-templates capture-snapshot <id-or-slug> --source-draft <draft-slug> --student <kid-id>
|
|
209
|
+
# show the preview, obtain approval, then rerun unchanged:
|
|
210
|
+
recess --json goal-templates capture-snapshot <id-or-slug> --source-draft <draft-slug> --student <kid-id> --confirm
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The draft must pass the full goal-builder contract: required top-level instructions, required fresh
|
|
214
|
+
`state/` files, directory content, and at least one parseable runtime module. Capture validates that
|
|
215
|
+
tree, then excludes `state/`, `conversations/`, and `.recess/` from the reusable snapshot. Its
|
|
216
|
+
preview carries the template version, Mesa change id, module/file inventory, size, and SHA-256; the
|
|
217
|
+
confirmed request is compare-and-set against both fences. If either changed, preview again and get
|
|
218
|
+
fresh approval.
|
|
219
|
+
|
|
220
|
+
Use `--source-file <local-file> --path <workspace-relative-path>` for one-file upserts. A live goal
|
|
221
|
+
may be targeted with `--goal <goal-id>`, but the CLI rejects direct `modules/` and `state/` writes
|
|
222
|
+
because those paths have database projections. Structural course changes belong in a draft, then a
|
|
223
|
+
captured/applied template.
|
|
224
|
+
|
|
225
|
+
An already-built OS-V2 goal can be captured directly:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
recess --json goal-templates capture-snapshot <id-or-slug> --source-goal <goal-id> --dry-run
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Read the resulting workspaces and snapshot with:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
recess --json mesa files list --student <kid-id> --goal <goal-id>
|
|
235
|
+
recess --json mesa files read --student <kid-id> --goal <goal-id> --path modules/01/index.md
|
|
236
|
+
recess --json goal-templates snapshot-files <id-or-slug>
|
|
237
|
+
recess --json goal-templates snapshot-files <id-or-slug> --path modules/01/index.md
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
`mesa files list` returning `{"files":[]}` means the goal has no Mesa workspace at all — expected for
|
|
241
|
+
a SIMPLE goal, and the signal that a BLUEPRINT goal has not been built yet.
|
|
242
|
+
|
|
243
|
+
## 9. Spec patches, metadata edits, and deletes are fenced
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
recess --json goal-templates get <id-or-slug> # read `version`
|
|
247
|
+
recess --json goal-templates patch-spec <id-or-slug> --expected-version 7 --patches-file ./patches.json
|
|
248
|
+
recess --json goal-templates set-metadata <id> --expected-version 7 --title "…" --confirm
|
|
249
|
+
recess --json goal-templates delete <id> --expected-version 7 --confirm
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`--expected-version` is mandatory. A stale one returns 409 `STALE_WRITE` (server) or `stale_write`
|
|
253
|
+
(the CLI's own pre-check) and **nothing is written** — re-read, rebuild the edit, and get a fresh
|
|
254
|
+
approval. Never reuse an approval across a stale-write refresh.
|
|
255
|
+
|
|
256
|
+
`patches.json` is a non-empty JSON array (maximum 50 operations) using `add`, `copy`, `replace`, and
|
|
257
|
+
`remove` with RFC 6901 JSON Pointer paths. The unconfirmed command sends `dryRun:true` to the server,
|
|
258
|
+
which applies the operations in memory, strict-validates the complete result, and returns
|
|
259
|
+
`details.safety` with before/after hashes, inventory totals, removals, and (when destructive) a
|
|
260
|
+
token. Show that exact preview to the human. After approval, rerun the same command with `--confirm`;
|
|
261
|
+
if `destructiveChanges` is true, also pass `--confirm-destructive-changes` and the preview's exact
|
|
262
|
+
`--destructive-change-token`. The confirmed run obtains a fresh preview before writing, and a stale
|
|
263
|
+
version or token writes nothing.
|
|
264
|
+
|
|
265
|
+
`set-metadata` cannot send a `setupWorkflowSpec` at all. Never replace a whole live spec through a
|
|
266
|
+
generic update or raw request; `patch-spec` is the only CLI path for an existing spec.
|
|
267
|
+
|
|
268
|
+
## Verify after every write
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
recess --json goal-templates get <id-or-slug> # version bumped? metadata right?
|
|
272
|
+
recess --json goal-templates versions <id-or-slug> # a new frozen version row exists
|
|
273
|
+
recess --json goals list --student <kid-id> # the goal actually landed on the kid
|
|
274
|
+
```
|