@stage5/lumine 0.3.29 → 0.3.31
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 +37 -2
- package/lib/commands.js +3 -0
- package/package.json +1 -1
package/lib/admin.js
CHANGED
|
@@ -370,7 +370,7 @@ function buildApprovalOperation({ action, target, options }) {
|
|
|
370
370
|
// Code agent passes wrote (no model is called), then review what they could
|
|
371
371
|
// not settle (Mikey 2026-10-06: bulk AI work runs on Claude Code agents).
|
|
372
372
|
const ENGLISH_USAGE =
|
|
373
|
-
"Use: lumine admin english import <verdicts.json> --pass a|b | adjudicate <verdicts.json> | add-questions <questions.json> | relevel <moves.json> | mastery <userId> --reason <why> | backfill-distractors | summary | review [--limit <n>] | accept|retire <questionId> [--reason <text>] | retag <questionId> --skill <code> [--reason <text>] | build-candidates [--after <questionId>] [--limit <n>] | build-import <verdicts.json> | check-candidates [--after <questionId>] [--limit <n>] | check-import <verdicts.json> | check-broken [--after <questionId>] [--limit <n>] | check-apply <fixes.json> | check-verify <checked.json>";
|
|
373
|
+
"Use: lumine admin english import <verdicts.json> --pass a|b | adjudicate <verdicts.json> | add-questions <questions.json> | relevel <moves.json> | mastery <userId> --reason <why> | backfill-distractors | summary | review [--limit <n>] | accept|retire <questionId> [--reason <text>] [--fault] | retag <questionId> --skill <code> [--reason <text>] | build-candidates [--after <questionId>] [--limit <n>] | build-import <verdicts.json> | check-candidates [--after <questionId>] [--limit <n>] | check-import <verdicts.json> | check-broken [--after <questionId>] [--limit <n>] | check-apply <fixes.json> | check-verify <checked.json> | check-follow-faulty [--after <next>] [--limit <n>] | lesson-candidates [--after <skillCode>] [--limit <n>] | lesson-import <lessons.json> | lesson-approve <approvals.json> | lessons [--status draft|approved]";
|
|
374
374
|
const ENGLISH_IMPORT_MAX = 500;
|
|
375
375
|
|
|
376
376
|
function buildEnglishOperation({ action, target, options }) {
|
|
@@ -444,6 +444,34 @@ function buildEnglishOperation({ action, target, options }) {
|
|
|
444
444
|
}
|
|
445
445
|
return writeOperation("english.check_verify", "POST", "/cli/admin/english/item-checks/verify", { items }, { requiresRun: false, timeoutMs: 300000 });
|
|
446
446
|
}
|
|
447
|
+
// the round-21 catch-up (boss misses uncounted, versions found at fault
|
|
448
|
+
// broken for every learner, every check followed again): one page per
|
|
449
|
+
// call, repeat with the reply's `next` until it is null
|
|
450
|
+
if (action === "check-follow-faulty") {
|
|
451
|
+
const after = options.adminAfter ? String(options.adminAfter) : "";
|
|
452
|
+
if (after && !/^(?:[ufc]:)?\d+:\d+$/.test(after)) throw cliValidationError("--after takes the last reply's next (<phase:id:version>).");
|
|
453
|
+
return writeOperation("english.check_follow_faulty", "POST", "/cli/admin/english/item-checks/follow-faulty", { after, limit: limitOf(200, 100) }, { requiresRun: false, timeoutMs: 300000 });
|
|
454
|
+
}
|
|
455
|
+
// Grammar Quest lessons (Mikey 2026-10-11): what the writing pass draws on
|
|
456
|
+
// (each rule-first point with live sound questions on it), importing
|
|
457
|
+
// drafts, approving reviewed versions [{ skillCode, version }], the list
|
|
458
|
+
if (action === "lesson-candidates") {
|
|
459
|
+
const after = options.adminAfter ? String(options.adminAfter) : "";
|
|
460
|
+
return readOperation("english.lesson_candidates", withQuery("/cli/admin/english/lessons/candidates", { after, limit: limitOf(64, 20) }), { requiresRun: false });
|
|
461
|
+
}
|
|
462
|
+
if (action === "lesson-import" || action === "lesson-approve") {
|
|
463
|
+
if (!target) throw cliValidationError(ENGLISH_USAGE);
|
|
464
|
+
const raw = readAdminJsonFile(target, "<file.json>", { maxBytes: 2 * 1024 * 1024 });
|
|
465
|
+
const items = Array.isArray(raw) ? raw : Array.isArray(raw?.items) ? raw.items : null;
|
|
466
|
+
if (!items || !items.length || items.length > 100) throw cliValidationError("The file must hold 1 to 100 entries (an array, or { items: [...] }).");
|
|
467
|
+
const path = action === "lesson-import" ? "/cli/admin/english/lessons/import" : "/cli/admin/english/lessons/approve";
|
|
468
|
+
return writeOperation(action === "lesson-import" ? "english.lesson_import" : "english.lesson_approve", "POST", path, { items }, { requiresRun: false, timeoutMs: 180000 });
|
|
469
|
+
}
|
|
470
|
+
if (action === "lessons") {
|
|
471
|
+
const status = options.adminStatus || "";
|
|
472
|
+
if (status && !["draft", "approved"].includes(status)) throw cliValidationError("--status is draft or approved.");
|
|
473
|
+
return readOperation("english.lessons", withQuery("/cli/admin/english/lessons", status ? { status } : {}), { requiresRun: false });
|
|
474
|
+
}
|
|
447
475
|
if (action === "check-apply") {
|
|
448
476
|
if (!target) throw cliValidationError(ENGLISH_USAGE);
|
|
449
477
|
const raw = readAdminJsonFile(target, "<fixes.json>", { maxBytes: 4 * 1024 * 1024 });
|
|
@@ -487,7 +515,14 @@ function buildEnglishOperation({ action, target, options }) {
|
|
|
487
515
|
"english.decide",
|
|
488
516
|
"POST",
|
|
489
517
|
`/cli/admin/english/review/${ref}`,
|
|
490
|
-
{
|
|
518
|
+
{
|
|
519
|
+
action,
|
|
520
|
+
skillCode: options.adminSkill || undefined,
|
|
521
|
+
reason: String(options.adminReason || "").trim() || undefined,
|
|
522
|
+
// retire --fault (Mikey 10-11): the question was at fault, so Grammar
|
|
523
|
+
// Quest forgives every miss on it; a duplicate or off-topic retire isn't
|
|
524
|
+
...(action === "retire" && options.adminFault ? { fault: true } : {}),
|
|
525
|
+
},
|
|
491
526
|
{ requiresRun: false },
|
|
492
527
|
);
|
|
493
528
|
}
|
package/lib/commands.js
CHANGED
|
@@ -2440,6 +2440,7 @@ export function parseArgs(args) {
|
|
|
2440
2440
|
const positional = [];
|
|
2441
2441
|
const booleanFlags = new Set([
|
|
2442
2442
|
"remove",
|
|
2443
|
+
"fault",
|
|
2443
2444
|
"noAnnounce",
|
|
2444
2445
|
"noLeaseKeeper",
|
|
2445
2446
|
"noOpen",
|
|
@@ -2759,6 +2760,8 @@ export function parseArgs(args) {
|
|
|
2759
2760
|
twinkles: raw.twinkles ? String(raw.twinkles) : "",
|
|
2760
2761
|
adminReason: raw.reason ? String(raw.reason) : "",
|
|
2761
2762
|
adminSkill: raw.skill ? String(raw.skill) : "",
|
|
2763
|
+
// admin english retire --fault: the question was at fault (Grammar Quest forgives its misses)
|
|
2764
|
+
adminFault: Boolean(raw.fault),
|
|
2762
2765
|
// --branch may repeat (a building two branches share); --branches A,B too
|
|
2763
2766
|
adminBranch: [raw.branch, raw.branches].filter(Boolean).join(","),
|
|
2764
2767
|
adminPass: raw.pass ? String(raw.pass) : "",
|