@stage5/lumine 0.2.96 → 0.2.98

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/lib/admin.js CHANGED
@@ -724,7 +724,8 @@ export async function adminCommand(options) {
724
724
  : {}),
725
725
  ...(requestId ? { "x-lumine-idempotency-key": requestId } : {}),
726
726
  },
727
- timeoutMs: options.timeoutMs,
727
+ // Long operations (reward-bank seed) carry their own timeout.
728
+ timeoutMs: operation.timeoutMs || options.timeoutMs,
728
729
  signal,
729
730
  });
730
731
  const transformResult = (rawResult) =>
@@ -2237,6 +2238,45 @@ export function parseAdminOperation(options) {
2237
2238
  );
2238
2239
  }
2239
2240
 
2241
+ if (namespace === "reward-bank" || namespace === "reward-banks") {
2242
+ // Seed questions for an approved app's reward question bank (generated-quiz
2243
+ // rules). coverage is read-only; seed writes ONE missing question per call
2244
+ // (lowest step first) as the daily run's Zero/Ciel identity and takes as
2245
+ // long as two GPT-6 Sol calls, so it gets its own timeout. The daily
2246
+ // website management run calls it in a bounded loop (Mikey, 2026-09-28).
2247
+ const usage =
2248
+ "Usage: lumine admin reward-bank coverage <buildId> [--max-step 3] | seed <buildId> [--max-step 3].";
2249
+ const buildId = parseRequiredInteger(
2250
+ target || options.adminBuild,
2251
+ "Build ID",
2252
+ 1,
2253
+ );
2254
+ const maxStep = options.adminMaxStep
2255
+ ? parseRequiredInteger(options.adminMaxStep, "--max-step", 1)
2256
+ : 3;
2257
+ if (maxStep > 10) throw cliValidationError("--max-step must be at most 10.");
2258
+ if (action === "coverage" || action === "status") {
2259
+ return readOperation(
2260
+ "reward-bank.coverage",
2261
+ withQuery("/cli/admin/reward-bank/coverage", {
2262
+ buildId: String(buildId),
2263
+ maxStep: String(maxStep),
2264
+ }),
2265
+ { requiresRun: false },
2266
+ );
2267
+ }
2268
+ if (action === "seed") {
2269
+ return writeOperation(
2270
+ "reward-bank.seed",
2271
+ "POST",
2272
+ "/cli/admin/reward-bank/seed",
2273
+ { buildId, maxStep },
2274
+ { timeoutMs: 240000 },
2275
+ );
2276
+ }
2277
+ throw cliValidationError(usage);
2278
+ }
2279
+
2240
2280
  if (namespace === "reward-activity" || namespace === "reward-telemetry") {
2241
2281
  // Read-only claim telemetry for the daily run: no run lease, no mutation.
2242
2282
  const date = options.adminDate
@@ -5097,6 +5137,27 @@ function printAdminResult({ operation, result }) {
5097
5137
  printRewardActivity(data);
5098
5138
  return;
5099
5139
  }
5140
+ if (operation.name.startsWith("reward-bank.")) {
5141
+ if (operation.name === "reward-bank.seed") {
5142
+ console.log(
5143
+ data.seeded
5144
+ ? `Seeded question #${data.seeded.questionId}: ${data.seeded.ruleId} · ${data.seeded.topicKey} · step ${data.seeded.step}.`
5145
+ : "Every slot is already seeded.",
5146
+ );
5147
+ }
5148
+ const coverage = data.coverage || data;
5149
+ console.log(
5150
+ `Coverage: ${Number(coverage.filled || 0)} / ${Number(coverage.total || 0)} topic-step slots have a question${data.maxStep ? ` (steps 1-${data.maxStep})` : ""}.`,
5151
+ );
5152
+ if (data.missingByStep && Object.keys(data.missingByStep).length) {
5153
+ console.log(
5154
+ `Missing by step: ${Object.entries(data.missingByStep)
5155
+ .map(([step, count]) => `step ${step}: ${count}`)
5156
+ .join(", ")}.`,
5157
+ );
5158
+ }
5159
+ return;
5160
+ }
5100
5161
  if (operation.name.startsWith("review.")) {
5101
5162
  printReviewRequestResult({ operation, data, result });
5102
5163
  return;
package/lib/commands.js CHANGED
@@ -2612,6 +2612,7 @@ export function parseArgs(args) {
2612
2612
  adminActions: raw.actions ? String(raw.actions) : "",
2613
2613
  adminDate: raw.date ? String(raw.date) : "",
2614
2614
  adminDays: raw.days ? String(raw.days) : "",
2615
+ adminMaxStep: raw.maxStep ? String(raw.maxStep) : "",
2615
2616
  adminBuild: raw.build ? String(raw.build) : "",
2616
2617
  adminEditionId: raw.editionId ? String(raw.editionId) : "",
2617
2618
  adminLeaseToken: raw.leaseToken ? String(raw.leaseToken) : "",
@@ -3053,6 +3054,8 @@ export function printHelp() {
3053
3054
  lumine admin post skip <target> [--type comment|aiStory|dailyReflection] [--reason <text>] [--json]
3054
3055
  lumine admin post skip-batch --target-file <json-or-lines> [--reason <text>] [--checkpoint <file> [--resume]] [--json]
3055
3056
  lumine admin post reward <target> [--type subject|comment|aiStory|dailyReflection] --twinkles 3 [--json]
3057
+ lumine admin reward-bank coverage <buildId> [--max-step 3] [--json]
3058
+ lumine admin reward-bank seed <buildId> [--max-step 3] [--json] (daily run: writes ONE missing seed question, lowest step first, billed to Zero/Ciel's AI Energy)
3056
3059
  lumine admin comment draft <target> [--type subject|comment|build|aiStory|dailyReflection] [--file <comment.md>] [--review-receipt <review.json>|--reviewed-version <id> --reviewed-via runtime|code] [--review-context <context.json>] [--identity zero|ciel|auto] [--json]
3057
3060
  lumine admin comment reply comment:<id> [--file <reply.md>] [--reviewed-version <id> --reviewed-via runtime|code] [--review-context <context.json>] [--identity zero|ciel|auto] [--json]
3058
3061
  lumine admin comment post --draft-id <id> [--json]
package/lib/constants.js CHANGED
@@ -181,9 +181,12 @@ Lumine CLI as the source of truth for saving this workspace back to Twinkle.
181
181
  ## Workflow
182
182
 
183
183
  - When planning a new app or a substantial improvement, read the AI decision design
184
- guidance in ${SDK_REFERENCE_FILE}. Consider whether JEV through Twinkle.ai.decide
185
- would improve the requested experience, and choose ordinary code or a text model
186
- when those fit better. Make this judgment from the app's needs; do not wait for
184
+ guidance in ${SDK_REFERENCE_FILE} and decide explicitly whether JEV through
185
+ Twinkle.ai.decide improves the requested experience. JEV is free for viewers (it
186
+ never uses their AI Energy). Strong fits: an AI opponent or boss that reads the
187
+ player's habits and picks a counter-plan, NPCs that understand typed requests,
188
+ classifying submissions, and adaptive difficulty. Choose ordinary code or a text
189
+ model when those fit better. Make this judgment from the app's needs; do not wait for
187
190
  the creator to know the technology or add it automatically to every app.
188
191
  - Edit only project files in this workspace.
189
192
  - Keep /index.html or /index.htm as the entry file.
@@ -355,6 +358,8 @@ ${LUMINE_WORLD_UPDATE_GUIDANCE}
355
358
 
356
359
  Report the changed files, any SDK methods used, the lumine save result, the
357
360
  build or branch id, and whether the result is published or unpublished changes.
361
+ Include one line on JEV: "JEV: used for <decision>" or "JEV: not used because
362
+ <reason>".
358
363
  `;
359
364
  export const LUMINE_REFERENCE_INSTRUCTIONS = `${LUMINE_REFERENCE_INSTRUCTIONS_MARKER}
360
365
  # Lumine Reference Guide
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage5/lumine",
3
- "version": "0.2.96",
3
+ "version": "0.2.98",
4
4
  "description": "Command line tools for launching Lumine builds on Twinkle.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,7 +2,7 @@
2
2
 
3
3
  Version: 1.63.0
4
4
  Updated: 2026-09-28
5
- Generated: 2026-09-28T07:33:56.595Z
5
+ Generated: 2026-09-28T08:22:20.133Z
6
6
 
7
7
  ## Notes
8
8
  - This SDK is injected into Build iframes via the Build preview/runtime.
@@ -39,7 +39,7 @@ Generated: 2026-09-28T07:33:56.595Z
39
39
  - Optional reward rule controls: maxLifetimeClaims caps one learner’s receipts for that rule across every day and release; completionProof: classic-tower-v1 requires a server-simulated Classic Tower finish in addition to minSeconds. These are server-enforced controls. Existing completion rules without completionProof still verify elapsed time only. Registered proof profiles also include breadface-v1, breadface-v2 and breadface-v3 (server-simulated Breadface inputs; each is one reviewed release's exact physics, chosen by the reviewer) study-record-v1 (a private study record reviewed by JEV, billed to the learner’s AI Energy), and Groove Lab's groove-lab-song-v1 (a song the learner published today, checked on the server for length, notes and originality) and groove-lab-heard-v1 (three established accounts finished the learner's songs today), Ashen Vigil's vigil-guest-coplay-v1 (a new guest spent 10 minutes with the learner in a private world room, measured by the world relay; each guest pays once) and minecraft-first-link-v1 (the learner is the first Twinkle account ever linked to that Minecraft player; each player pays once). Profiles are platform-owned; an app cannot invent a verifier or authorize its own reward.
40
40
 
41
41
  ## AI decision design
42
- - When planning a new app or an improvement, consider whether model-based judgments would materially improve the requested experience. Twinkle.ai.decide runs JEV, a model for narrow decisions over supplied text or structured state. Potential uses include interpreting a player's request to an NPC, choosing among legal game actions, classifying user content, ranking supplied candidates, and adapting an activity to evidence about the learner. These are examples to reason from, not a keyword checklist or a requirement to add AI to every app.
42
+ - Twinkle.ai.decide runs JEV, a model for narrow decisions over supplied text or structured state, and it is free for viewers: decisions are covered by Twinkle and never use their AI Energy. Whenever an app makes a judgment that ordinary code can only approximate, consider JEV first. Proven patterns: an opponent or boss coach that reads the player's habits (favourite lane, repeated trick, cheese move) and picks a counter-plan from a fixed list, as in Red Square's boss and Open Football's opponent coach; NPCs that understand what a player types and choose an action; classifying or scoring user submissions; ranking supplied candidates; and picking the next exercise or difficulty from evidence about the learner. Any app with an AI opponent, NPC, or adaptive difficulty should decide explicitly whether JEV improves it. These are examples to reason from, not a keyword checklist or a requirement to add AI to every app.
43
43
  - Choose the mechanism by the work: use ordinary code for known rules, arithmetic, physics, legal moves, storage, and permissions; use ai.decide for contextual choices, yes/no probabilities, and scores; use ai.chat or ai.generateObject for generated dialogue, explanations, open-ended content, and multi-step reasoning. JEV does not generate text, browse the web, inspect images, or supply missing app data. Combine these tools when it benefits the actual request, without silently turning every decision into a more expensive text-model call.
44
44
  - Before adopting JEV, identify the concrete decision, the context available at that moment, the allowed outcomes, and why the added latency is worthwhile. Use your model judgment to make that choice. Do not substitute regex or keyword matching for understanding human-language intent. Explain the user-visible benefit simply; the creator does not need to select a provider, enter an API key, or design question schemas.
45
45
  - Send related independent questions about the same state together in one ai.decide request (up to 32). Write complete instructions and distinct option or level descriptions. Include an other/uncertain option when the choices might not cover the input. A second call is useful only when it needs newly obtained context or choices that depend on the first result; answers in one batch do not see each other.
@@ -1293,6 +1293,39 @@ those exact files and does not depend on keeping the review copy. Re-offers
1293
1293
  reuse the media; a failed transaction cleans up its copied objects. Declining
1294
1294
  leaves the offered media as unused uploads in the creator's library.
1295
1295
 
1296
+ ### Reward question-bank seeding (every full daily review; added 2026-09-28)
1297
+
1298
+ `generated-quiz` rules fill a question bank on the server: a question is
1299
+ written for one declared topic at one ladder step (GPT-6 Sol) and kept only
1300
+ when an independent second solve agrees. Learners write missing questions
1301
+ themselves on their own AI Energy; seeding writes the gentlest steps ahead of
1302
+ them so the first learner on a unit never waits or pays.
1303
+
1304
+ ```bash
1305
+ lumine admin reward-bank coverage <buildId> [--max-step 3] [--json] # read-only, no run
1306
+ lumine admin reward-bank seed <buildId> [--max-step 3] [--json] # delegated full run
1307
+ ```
1308
+
1309
+ - `seed` writes ONE question per call into the first missing slot, lowest
1310
+ step first across every topic of every generated-quiz rule, up to
1311
+ `--max-step` (default 3, at most 10). A slot is a (rule, topic, step) with
1312
+ no active live question. The call takes as long as two model calls
1313
+ (about 20–40 s; the CLI allows 4 minutes) and returns `seeded`
1314
+ (`questionId`, `ruleId`, `topicKey`, `step`) or `complete: true`, plus
1315
+ `coverage` (`filled` / `total`).
1316
+ - It needs the `reward:bank-seed` scope, which only full delegated runs carry.
1317
+ The question is written as the run identity (Zero or Ciel) and billed to
1318
+ that account's own AI Energy. It never pays anyone and opens no challenge.
1319
+ - It refuses unless the app's rewards are approved and published
1320
+ (`CLI_ADMIN_BUILD_REWARD_BANK_NOT_LIVE`), and refuses to store a question
1321
+ if the approval changed while it was being written
1322
+ (`CLI_ADMIN_BUILD_REWARD_BANK_REVIEW_CHANGED`: run it again).
1323
+ `CLI_ADMIN_BUILD_REWARD_BANK_UNVERIFIED` means the two solves disagreed
1324
+ twice; nothing was stored.
1325
+ - Which apps to seed, how many steps and how many per run are Mikey's
1326
+ decisions, recorded in the agent guide (Math Studio #2655: steps 1–3, at
1327
+ most 20 per run).
1328
+
1296
1329
  ### Reward activity report (standing duty, every full daily review; added 2026-09-12)
1297
1330
 
1298
1331
  Completion rewards (Arcade Typing's stage clears) prove nothing but elapsed