recess-cli 1.6.0 → 1.7.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 CHANGED
@@ -128,6 +128,8 @@ recess --json goals pdf upload --student <kid-id> --draft <draft-slug> --source-
128
128
  recess --json goal-templates capture-snapshot <id-or-slug> --source-draft <draft-slug> --student <kid-id> --dry-run
129
129
  recess --json goal-templates apply <id-or-slug> --answers-file ./answers.json --dry-run
130
130
  recess --json goals create --student <kid-id> --title "..." --description-file ./goal.md
131
+ recess --json goals create --student <kid-id> --draft <draft-slug> --title "..." \
132
+ --description-file ./goal.md --enable-applet-follow-ups
131
133
  recess --json goals files list --student <kid-id> --goal <goal-id>
132
134
  ```
133
135
 
@@ -183,10 +185,11 @@ previews the per-student outcome. `set-metadata` and `delete` require `--expecte
183
185
  it always runs the backend's guarded preview first and requires the preview's exact loss token in
184
186
  addition to `--confirm` when protected template data would be removed.
185
187
 
186
- MODULE_BACKED BLUEPRINT content is authored as a local workspace tree, batch-upserted to a named
187
- goal draft, then attached with `capture-snapshot`. Both mutations run server previews before the
188
- confirmation gate. Goal-content upserts are compare-and-set against the previewed revision; capture is
189
- fenced to both that source change and the template version. Direct live-goal `modules/` and
190
- `state/` writes are blocked because those files have database projections.
188
+ Module-backed content is authored as a local workspace tree and batch-upserted to a named goal
189
+ draft. For a personal one-off goal, `goals create --draft` validates and materializes that draft
190
+ directly. For reusable content, attach it to a BLUEPRINT with `capture-snapshot`. Every mutation
191
+ runs a server preview before the confirmation gate and is compare-and-set against the previewed
192
+ revision. Direct live-goal `modules/` and `state/` writes remain blocked because those files have
193
+ database projections.
191
194
 
192
195
  See `recess --help` for the complete command surface. The raw escape hatch is intentionally read-only: `recess --json request get /path`.
package/dist/args.js CHANGED
@@ -12,6 +12,8 @@ const BOOLEAN_FLAGS = new Set([
12
12
  "archived",
13
13
  "confirm",
14
14
  "dry-run",
15
+ "disable-applet-follow-ups",
16
+ "enable-applet-follow-ups",
15
17
  "full",
16
18
  "help",
17
19
  "immediate",
package/dist/cli.js CHANGED
@@ -153,7 +153,7 @@ Usage:
153
153
  recess [--json] goal-templates delete <template-id> --expected-version N [--confirm]
154
154
  recess [--json] goal-templates snapshot-files <template-id> [--path P]
155
155
  recess [--json] goal-templates capture-snapshot <template-id|slug>
156
- (--source-goal <goal-id> | --source-draft <draft-slug> --student <kid-id>)
156
+ (--source-goal <goal-id> | --source-draft <draft-slug> --student <goal-owner-id>)
157
157
  [--dry-run] [--confirm]
158
158
  recess [--json] goal-templates apply <template-id> --answers-file <path>
159
159
  [--dry-run] [--confirm --approval-token TOKEN]
@@ -162,7 +162,9 @@ Usage:
162
162
  recess [--json] goals list --student <kid-id>
163
163
  recess [--json] goals create --student <kid-id> --title TEXT
164
164
  (--description TEXT | --description-file <path>) [--target-date <iso>]
165
- [--schedule TEXT] [--confirm]
165
+ [--schedule TEXT] [--draft <draft-slug>
166
+ (--enable-applet-follow-ups | --disable-applet-follow-ups)]
167
+ [--confirm --approval-token TOKEN]
166
168
  recess [--json] goals edit <goal-id> --student <kid-id> --patch-file <path/patch.json>
167
169
  --delta TEXT [--confirm --approval-token TOKEN]
168
170
  recess [--json] todos create --student <kid-id> --title TEXT
@@ -174,13 +176,13 @@ Usage:
174
176
  recess [--json] rocky get --student <kid-id>
175
177
  recess [--json] rocky set --student <kid-id> --patch-file <path/patch.json>
176
178
  --expected-updated-at ISO|none [--confirm]
177
- recess [--json] goals files list --student <kid-id> --goal <goal-id>
178
- recess [--json] goals files read --student <kid-id> --goal <goal-id> --path P
179
- recess [--json] goals files write --student <kid-id>
179
+ recess [--json] goals files list --student <goal-owner-id> --goal <goal-id>
180
+ recess [--json] goals files read --student <goal-owner-id> --goal <goal-id> --path P
181
+ recess [--json] goals files write --student <goal-owner-id>
180
182
  (--goal <goal-id> | --draft <draft-slug>)
181
183
  (--source-dir <local-dir> | --source-file <local-file> --path P)
182
184
  [--message TEXT] [--confirm --approval-token TOKEN]
183
- recess [--json] goals pdf upload --student <kid-id>
185
+ recess [--json] goals pdf upload --student <goal-owner-id>
184
186
  (--goal <goal-id> | --draft <draft-slug>) --source-file <local.pdf>
185
187
  [--path uploads/name.pdf] [--message TEXT]
186
188
  [--confirm --approval-token TOKEN]
@@ -191,6 +193,13 @@ bundled into this npm package. Load os-v2-goal-template-builder and its
191
193
  references/deterministic-workflow-setup.md BEFORE authoring a template; that is
192
194
  the same guidance the recess.gg/ai agent follows, so there is exactly one
193
195
  standard. Responses cache under ~/.recess-cli/skills-cache/ (--refresh re-fetches).
196
+ For goal workspace and PDF commands, --student names the goal owner. A
197
+ full_admin session may use a KID or ADMIN user id, including its own ADMIN id;
198
+ family_ai sessions remain limited to managed KID profiles.
199
+ "goals create --draft" materializes that validated draft directly as a personal
200
+ module-backed goal; it does not create or apply a reusable template. Its preview
201
+ is bound to the exact workspace revision, hash, module inventory, and applet
202
+ follow-up choice.
194
203
  Every template created here is setupMode DETERMINISTIC_WORKFLOW and CANNOT be
195
204
  converted back, so "validate-spec" against the same file until it passes, then
196
205
  "create". "create" runs a real server-side validation before its gate, so the
@@ -2901,6 +2910,65 @@ export async function runCommand(argv) {
2901
2910
  throw new CliError("invalid_arguments", "--target-date must be an ISO 8601 datetime.");
2902
2911
  }
2903
2912
  const schedule = flagString(parsed, "schedule");
2913
+ const draftSlug = flagString(parsed, "draft");
2914
+ const enablesAppletFollowUps = hasFlag(parsed, "enable-applet-follow-ups");
2915
+ const disablesAppletFollowUps = hasFlag(parsed, "disable-applet-follow-ups");
2916
+ if (draftSlug && enablesAppletFollowUps === disablesAppletFollowUps) {
2917
+ throw new CliError("invalid_arguments", "A module-backed goal requires exactly one of --enable-applet-follow-ups or --disable-applet-follow-ups.");
2918
+ }
2919
+ if (!draftSlug && (enablesAppletFollowUps || disablesAppletFollowUps)) {
2920
+ throw new CliError("invalid_arguments", "Applet follow-up flags are used with --draft for direct module-backed goals.");
2921
+ }
2922
+ if (draftSlug) {
2923
+ const body = {
2924
+ studentUserId: userId,
2925
+ draftSlug,
2926
+ title,
2927
+ description,
2928
+ enableAppletFollowUps: enablesAppletFollowUps,
2929
+ ...(targetDate ? { targetDate } : {}),
2930
+ ...(schedule ? { schedule } : {}),
2931
+ };
2932
+ const preflight = unwrap(await api.client.POST("/tutor/browser/mesa/goals", {
2933
+ body: { ...body, dryRun: true },
2934
+ }));
2935
+ if (preflight.action !== "preview_module_goal_create") {
2936
+ throw new CliError("unexpected_response", "Direct module goal creation did not return a preview; no goal was created.");
2937
+ }
2938
+ const preview = {
2939
+ action: "create a module-backed goal directly from a validated draft workspace",
2940
+ target: preflight.target,
2941
+ request: {
2942
+ title,
2943
+ descriptionChars: description.length,
2944
+ descriptionSha256: createHash("sha256")
2945
+ .update(description)
2946
+ .digest("hex"),
2947
+ targetDate: targetDate ?? null,
2948
+ schedule: schedule ?? null,
2949
+ enableAppletFollowUps: enablesAppletFollowUps,
2950
+ },
2951
+ details: {
2952
+ currentChangeId: preflight.currentChangeId,
2953
+ workspaceSha256: preflight.workspaceSha256,
2954
+ fileCount: preflight.fileCount,
2955
+ sizeBytes: preflight.sizeBytes,
2956
+ modules: preflight.modules,
2957
+ warnings: preflight.warnings,
2958
+ currentGoalCount: preflight.currentGoalCount,
2959
+ goalLimit: preflight.goalLimit,
2960
+ note: "Creates a personal module-backed goal directly. It does not create, capture, or apply a reusable template. After success, Recess removes the draft only when no newer Mesa edit has landed; otherwise it preserves the draft.",
2961
+ },
2962
+ };
2963
+ requirePreviewBoundConfirmation(parsed, preview);
2964
+ return unwrap(await api.client.POST("/tutor/browser/mesa/goals", {
2965
+ body: {
2966
+ ...body,
2967
+ dryRun: false,
2968
+ expectedWorkspaceChangeId: preflight.currentChangeId,
2969
+ },
2970
+ }));
2971
+ }
2904
2972
  const body = {
2905
2973
  title,
2906
2974
  description,
@@ -2917,7 +2985,7 @@ export async function runCommand(argv) {
2917
2985
  schedule: schedule ?? null,
2918
2986
  },
2919
2987
  details: {
2920
- note: "Creates a description-only goal with no modules or course workspace. For a module-backed course, apply a BLUEPRINT template instead. A 409 GOAL_LIMIT_REACHED means the kid is at capacity and nothing was created.",
2988
+ note: "Creates a description-only goal with no modules or course workspace. Pass --draft to create a personal module-backed goal directly. A 409 GOAL_LIMIT_REACHED means the kid is at capacity and nothing was created.",
2921
2989
  },
2922
2990
  }, async () => unwrap(await api.client.POST("/tutor/browser/students/{userId}/goals/", {
2923
2991
  params: { path: { userId } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recess-cli",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Safe Recess administration and family AI tools from the command line.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {