@stage5/lumine 0.2.96 → 0.2.97
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 +143 -1
- package/lib/commands.js +6 -0
- package/lib/constants.js +8 -3
- package/package.json +1 -1
- package/sdk/BUILD_SDK_INDEX.md +2 -2
- package/sdk/LUMINE_ADMIN.md +33 -0
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
|
-
|
|
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) =>
|
|
@@ -1934,6 +1935,44 @@ export function parseAdminOperation(options) {
|
|
|
1934
1935
|
if (note.length > 1000) {
|
|
1935
1936
|
throw cliValidationError("--note must be at most 1000 characters.");
|
|
1936
1937
|
}
|
|
1938
|
+
if (action === "story" || action === "stories") {
|
|
1939
|
+
// A crew's Bridge Builder story page: Mikey's final approval (the
|
|
1940
|
+
// admin bar on the story page does the same). Publishing copies only
|
|
1941
|
+
// the photos/clips every tagged member's parent allowed.
|
|
1942
|
+
const storyUsage =
|
|
1943
|
+
"Usage: lumine admin meetup story list | show <crewId> | approve <crewId> [--note <text>] [--no-announce] | send-back <crewId> --note <text> | unpublish <crewId> --note <text>.";
|
|
1944
|
+
const storyAction = target || "list";
|
|
1945
|
+
if (storyAction === "list") {
|
|
1946
|
+
return readOperation("meetup.story.list", "/cli/admin/meetup-quest/stories", {
|
|
1947
|
+
requiresRun: false,
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
if (!["show", "approve", "send-back", "unpublish"].includes(storyAction)) {
|
|
1951
|
+
throw cliValidationError(storyUsage);
|
|
1952
|
+
}
|
|
1953
|
+
const crewId = parseRequiredInteger(extra, "Crew ID", 1);
|
|
1954
|
+
if (storyAction === "show") {
|
|
1955
|
+
return readOperation(
|
|
1956
|
+
"meetup.story.show",
|
|
1957
|
+
`/cli/admin/meetup-quest/stories/by-crew/${crewId}`,
|
|
1958
|
+
{ requiresRun: false },
|
|
1959
|
+
);
|
|
1960
|
+
}
|
|
1961
|
+
if (storyAction !== "approve" && !note) {
|
|
1962
|
+
throw cliValidationError(
|
|
1963
|
+
`lumine admin meetup story ${storyAction} <crewId> needs --note <text> (the crew sees it).`,
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
return writeOperation(
|
|
1967
|
+
`meetup.story.${storyAction}`,
|
|
1968
|
+
"POST",
|
|
1969
|
+
`/cli/admin/meetup-quest/stories/by-crew/${crewId}/${storyAction}`,
|
|
1970
|
+
storyAction === "approve"
|
|
1971
|
+
? { note, announce: !options.adminNoAnnounce }
|
|
1972
|
+
: { note },
|
|
1973
|
+
{ requiresRun: false },
|
|
1974
|
+
);
|
|
1975
|
+
}
|
|
1937
1976
|
if (!action || action === "list") {
|
|
1938
1977
|
return readOperation(
|
|
1939
1978
|
"meetup.list",
|
|
@@ -2237,6 +2276,45 @@ export function parseAdminOperation(options) {
|
|
|
2237
2276
|
);
|
|
2238
2277
|
}
|
|
2239
2278
|
|
|
2279
|
+
if (namespace === "reward-bank" || namespace === "reward-banks") {
|
|
2280
|
+
// Seed questions for an approved app's reward question bank (generated-quiz
|
|
2281
|
+
// rules). coverage is read-only; seed writes ONE missing question per call
|
|
2282
|
+
// (lowest step first) as the daily run's Zero/Ciel identity and takes as
|
|
2283
|
+
// long as two GPT-6 Sol calls, so it gets its own timeout. The daily
|
|
2284
|
+
// website management run calls it in a bounded loop (Mikey, 2026-09-28).
|
|
2285
|
+
const usage =
|
|
2286
|
+
"Usage: lumine admin reward-bank coverage <buildId> [--max-step 3] | seed <buildId> [--max-step 3].";
|
|
2287
|
+
const buildId = parseRequiredInteger(
|
|
2288
|
+
target || options.adminBuild,
|
|
2289
|
+
"Build ID",
|
|
2290
|
+
1,
|
|
2291
|
+
);
|
|
2292
|
+
const maxStep = options.adminMaxStep
|
|
2293
|
+
? parseRequiredInteger(options.adminMaxStep, "--max-step", 1)
|
|
2294
|
+
: 3;
|
|
2295
|
+
if (maxStep > 10) throw cliValidationError("--max-step must be at most 10.");
|
|
2296
|
+
if (action === "coverage" || action === "status") {
|
|
2297
|
+
return readOperation(
|
|
2298
|
+
"reward-bank.coverage",
|
|
2299
|
+
withQuery("/cli/admin/reward-bank/coverage", {
|
|
2300
|
+
buildId: String(buildId),
|
|
2301
|
+
maxStep: String(maxStep),
|
|
2302
|
+
}),
|
|
2303
|
+
{ requiresRun: false },
|
|
2304
|
+
);
|
|
2305
|
+
}
|
|
2306
|
+
if (action === "seed") {
|
|
2307
|
+
return writeOperation(
|
|
2308
|
+
"reward-bank.seed",
|
|
2309
|
+
"POST",
|
|
2310
|
+
"/cli/admin/reward-bank/seed",
|
|
2311
|
+
{ buildId, maxStep },
|
|
2312
|
+
{ timeoutMs: 240000 },
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
throw cliValidationError(usage);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2240
2318
|
if (namespace === "reward-activity" || namespace === "reward-telemetry") {
|
|
2241
2319
|
// Read-only claim telemetry for the daily run: no run lease, no mutation.
|
|
2242
2320
|
const date = options.adminDate
|
|
@@ -4852,6 +4930,49 @@ function printMeetupCrew(crew) {
|
|
|
4852
4930
|
}
|
|
4853
4931
|
|
|
4854
4932
|
function printMeetupResult({ operation, data, result }) {
|
|
4933
|
+
if (operation.name === "meetup.story.list") {
|
|
4934
|
+
const stories = Array.isArray(data.stories) ? data.stories : [];
|
|
4935
|
+
console.log(`${stories.length} Bridge Builder stor${stories.length === 1 ? "y" : "ies"} waiting for approval:`);
|
|
4936
|
+
for (const story of stories) {
|
|
4937
|
+
console.log(
|
|
4938
|
+
` crew #${story.crewId} · "${story.title}" · ${story.crewName} (${(story.people || []).join(", ")}) · ${story.itemsPublic} public / ${story.itemsPrivate} private`,
|
|
4939
|
+
);
|
|
4940
|
+
}
|
|
4941
|
+
if (stories.length) console.log("Approve: lumine admin meetup story approve <crewId> (or send-back <crewId> --note).");
|
|
4942
|
+
return;
|
|
4943
|
+
}
|
|
4944
|
+
if (operation.name === "meetup.story.show") {
|
|
4945
|
+
const story = data.story || {};
|
|
4946
|
+
const items = [...(story.photos || []), ...(story.clips || [])];
|
|
4947
|
+
console.log(`Story #${story.storyId} (crew #${story.crewId}) · ${story.status} · "${story.title}"`);
|
|
4948
|
+
console.log(` People: ${(story.people || []).map((p) => `${p.username} (${p.branch})`).join(", ")}`);
|
|
4949
|
+
for (const consent of story.review?.consents || []) {
|
|
4950
|
+
const person = (story.people || []).find((p) => p.userId === consent.userId);
|
|
4951
|
+
console.log(` Parent of ${person?.username || consent.userId}: ${consent.state}`);
|
|
4952
|
+
}
|
|
4953
|
+
for (const item of items) {
|
|
4954
|
+
const gate = item.gate || {};
|
|
4955
|
+
console.log(
|
|
4956
|
+
` ${item.kind} #${item.id}: ${gate.publishable ? "PUBLIC" : `private (${gate.reason || "live"})`}${item.caption ? ` · ${item.caption}` : ""}${item.url ? ` · ${item.url}` : ""}`,
|
|
4957
|
+
);
|
|
4958
|
+
}
|
|
4959
|
+
if ((story.review?.nameWarnings || []).length) {
|
|
4960
|
+
console.log(` Possible real names: ${story.review.nameWarnings.join(", ")}`);
|
|
4961
|
+
}
|
|
4962
|
+
if (story.body) console.log(`\n${story.body}\n`);
|
|
4963
|
+
return;
|
|
4964
|
+
}
|
|
4965
|
+
if (operation.name.startsWith("meetup.story.")) {
|
|
4966
|
+
const r = data.result || {};
|
|
4967
|
+
if (operation.name === "meetup.story.approve") {
|
|
4968
|
+
console.log(
|
|
4969
|
+
`Published story #${r.storyId} (crew #${r.crewId}): ${(r.publicMediaIds || []).length} public, ${(r.privateMediaIds || []).length} private.${r.announcementSubjectId ? ` Announcement: subject #${r.announcementSubjectId}.` : ""}${(r.failed || []).length ? ` FAILED to process: ${r.failed.map((f) => `#${f.mediaId} ${f.error}`).join("; ")}.` : ""}`,
|
|
4970
|
+
);
|
|
4971
|
+
} else {
|
|
4972
|
+
console.log(`${operation.name === "meetup.story.unpublish" ? "Unpublished" : "Sent back"} story #${r.storyId} (crew #${r.crewId}).`);
|
|
4973
|
+
}
|
|
4974
|
+
return;
|
|
4975
|
+
}
|
|
4855
4976
|
if (operation.name === "meetup.list") {
|
|
4856
4977
|
const crews = Array.isArray(data.crews) ? data.crews : [];
|
|
4857
4978
|
console.log(`${crews.length} meetup crew(s) (${data.filter || "review"}):`);
|
|
@@ -5097,6 +5218,27 @@ function printAdminResult({ operation, result }) {
|
|
|
5097
5218
|
printRewardActivity(data);
|
|
5098
5219
|
return;
|
|
5099
5220
|
}
|
|
5221
|
+
if (operation.name.startsWith("reward-bank.")) {
|
|
5222
|
+
if (operation.name === "reward-bank.seed") {
|
|
5223
|
+
console.log(
|
|
5224
|
+
data.seeded
|
|
5225
|
+
? `Seeded question #${data.seeded.questionId}: ${data.seeded.ruleId} · ${data.seeded.topicKey} · step ${data.seeded.step}.`
|
|
5226
|
+
: "Every slot is already seeded.",
|
|
5227
|
+
);
|
|
5228
|
+
}
|
|
5229
|
+
const coverage = data.coverage || data;
|
|
5230
|
+
console.log(
|
|
5231
|
+
`Coverage: ${Number(coverage.filled || 0)} / ${Number(coverage.total || 0)} topic-step slots have a question${data.maxStep ? ` (steps 1-${data.maxStep})` : ""}.`,
|
|
5232
|
+
);
|
|
5233
|
+
if (data.missingByStep && Object.keys(data.missingByStep).length) {
|
|
5234
|
+
console.log(
|
|
5235
|
+
`Missing by step: ${Object.entries(data.missingByStep)
|
|
5236
|
+
.map(([step, count]) => `step ${step}: ${count}`)
|
|
5237
|
+
.join(", ")}.`,
|
|
5238
|
+
);
|
|
5239
|
+
}
|
|
5240
|
+
return;
|
|
5241
|
+
}
|
|
5100
5242
|
if (operation.name.startsWith("review.")) {
|
|
5101
5243
|
printReviewRequestResult({ operation, data, result });
|
|
5102
5244
|
return;
|
package/lib/commands.js
CHANGED
|
@@ -2355,6 +2355,7 @@ export function parseArgs(args) {
|
|
|
2355
2355
|
const raw = {};
|
|
2356
2356
|
const positional = [];
|
|
2357
2357
|
const booleanFlags = new Set([
|
|
2358
|
+
"noAnnounce",
|
|
2358
2359
|
"noLeaseKeeper",
|
|
2359
2360
|
"noOpen",
|
|
2360
2361
|
"open",
|
|
@@ -2606,12 +2607,14 @@ export function parseArgs(args) {
|
|
|
2606
2607
|
storageSize: raw.size ? String(raw.size) : "",
|
|
2607
2608
|
adminAttended: raw.attended ? String(raw.attended) : "",
|
|
2608
2609
|
adminConfirm: raw.confirm === undefined ? "" : String(raw.confirm),
|
|
2610
|
+
adminNoAnnounce: Boolean(raw.noAnnounce),
|
|
2609
2611
|
adminContextLimit: raw.limit === undefined ? 20 : Number(raw.limit),
|
|
2610
2612
|
adminRun: raw.run ? String(raw.run) : "",
|
|
2611
2613
|
adminTarget: raw.target ? String(raw.target) : "",
|
|
2612
2614
|
adminActions: raw.actions ? String(raw.actions) : "",
|
|
2613
2615
|
adminDate: raw.date ? String(raw.date) : "",
|
|
2614
2616
|
adminDays: raw.days ? String(raw.days) : "",
|
|
2617
|
+
adminMaxStep: raw.maxStep ? String(raw.maxStep) : "",
|
|
2615
2618
|
adminBuild: raw.build ? String(raw.build) : "",
|
|
2616
2619
|
adminEditionId: raw.editionId ? String(raw.editionId) : "",
|
|
2617
2620
|
adminLeaseToken: raw.leaseToken ? String(raw.leaseToken) : "",
|
|
@@ -3011,6 +3014,7 @@ export function printHelp() {
|
|
|
3011
3014
|
lumine admin cardcraft-review list [--status pending|approved|all] [--cursor <id>] | show <id> | approve|reject|revoke <id> [--reason <text>]
|
|
3012
3015
|
lumine admin storage list [--status pending|approved|rejected|all] [--cursor <id>] | show <user-id-or-username> | approve <request-id> [--size <500MB|1GB|2GB|n MB>] [--reason <text>] | reject <request-id> [--reason <text>] | grant <user-id-or-username> --size <500MB|1GB|2GB|n MB> [--reason <text>]
|
|
3013
3016
|
lumine admin meetup list [--status review|active|completed|all] | show <crewId> | approve-plan <crewId> [--note <text>] | send-back <crewId> --note <text> | approve <crewId> --attended <userId,userId,...> [--note <text>] | slot <crewId> --confirm <slotIndex> | resend-email <crewId> (Bridge Builder meetup quest)
|
|
3017
|
+
lumine admin meetup story list | show <crewId> | approve <crewId> [--note <text>] [--no-announce] | send-back <crewId> --note <text> | unpublish <crewId> --note <text> (Bridge Builder story pages: publishes only what every tagged member's parent allowed)
|
|
3014
3018
|
lumine admin reward-activity [--date YYYY-MM-DD] [--days <1..31>] [--build <id>] [--json]
|
|
3015
3019
|
lumine admin chat-reports list [--status pending|open|reviewing|resolved|dismissed|all] [--cursor <id>] [--json]
|
|
3016
3020
|
lumine admin chat-reports show <report-id> [--json] (reported message snapshot + surrounding context)
|
|
@@ -3053,6 +3057,8 @@ export function printHelp() {
|
|
|
3053
3057
|
lumine admin post skip <target> [--type comment|aiStory|dailyReflection] [--reason <text>] [--json]
|
|
3054
3058
|
lumine admin post skip-batch --target-file <json-or-lines> [--reason <text>] [--checkpoint <file> [--resume]] [--json]
|
|
3055
3059
|
lumine admin post reward <target> [--type subject|comment|aiStory|dailyReflection] --twinkles 3 [--json]
|
|
3060
|
+
lumine admin reward-bank coverage <buildId> [--max-step 3] [--json]
|
|
3061
|
+
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
3062
|
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
3063
|
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
3064
|
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}
|
|
185
|
-
|
|
186
|
-
|
|
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
package/sdk/BUILD_SDK_INDEX.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Version: 1.63.0
|
|
4
4
|
Updated: 2026-09-28
|
|
5
|
-
Generated: 2026-09-
|
|
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
|
-
-
|
|
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.
|
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -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
|