@stage5/lumine 0.3.28 → 0.3.30
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 +39 -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>]";
|
|
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>]";
|
|
374
374
|
const ENGLISH_IMPORT_MAX = 500;
|
|
375
375
|
|
|
376
376
|
function buildEnglishOperation({ action, target, options }) {
|
|
@@ -431,6 +431,36 @@ function buildEnglishOperation({ action, target, options }) {
|
|
|
431
431
|
? readOperation("english.check_candidates", withQuery("/cli/admin/english/item-checks/candidates", { after, limit: limitOf(1000, 200) }), { requiresRun: false })
|
|
432
432
|
: readOperation("english.check_broken", withQuery("/cli/admin/english/item-checks/broken", { after, limit: limitOf(500, 100) }), { requiresRun: false });
|
|
433
433
|
}
|
|
434
|
+
// Mikey's approved fixes: [{ questionId, version, fix? }] — the stored
|
|
435
|
+
// proposed fix, or one given (a tidy), applied as a new version
|
|
436
|
+
// checks from before fingerprints: [{ questionId, version, question,
|
|
437
|
+
// choices, key }] as the pass saw them; matches are kept, the rest dropped
|
|
438
|
+
if (action === "check-verify") {
|
|
439
|
+
if (!target) throw cliValidationError(ENGLISH_USAGE);
|
|
440
|
+
const raw = readAdminJsonFile(target, "<checked.json>", { maxBytes: 8 * 1024 * 1024 });
|
|
441
|
+
const items = Array.isArray(raw) ? raw : Array.isArray(raw?.items) ? raw.items : null;
|
|
442
|
+
if (!items || !items.length || items.length > ENGLISH_IMPORT_MAX) {
|
|
443
|
+
throw cliValidationError(`The file must hold 1 to ${ENGLISH_IMPORT_MAX} items (an array, or { items: [...] }).`);
|
|
444
|
+
}
|
|
445
|
+
return writeOperation("english.check_verify", "POST", "/cli/admin/english/item-checks/verify", { items }, { requiresRun: false, timeoutMs: 300000 });
|
|
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
|
+
if (action === "check-apply") {
|
|
456
|
+
if (!target) throw cliValidationError(ENGLISH_USAGE);
|
|
457
|
+
const raw = readAdminJsonFile(target, "<fixes.json>", { maxBytes: 4 * 1024 * 1024 });
|
|
458
|
+
const items = Array.isArray(raw) ? raw : Array.isArray(raw?.items) ? raw.items : null;
|
|
459
|
+
if (!items || !items.length || items.length > 200) {
|
|
460
|
+
throw cliValidationError("The file must hold 1 to 200 fixes (an array, or { items: [...] }).");
|
|
461
|
+
}
|
|
462
|
+
return writeOperation("english.check_apply", "POST", "/cli/admin/english/item-checks/apply", { items }, { requiresRun: false, timeoutMs: 300000 });
|
|
463
|
+
}
|
|
434
464
|
if (action === "check-import") {
|
|
435
465
|
if (!target) throw cliValidationError(ENGLISH_USAGE);
|
|
436
466
|
const raw = readAdminJsonFile(target, "<verdicts.json>", { maxBytes: 4 * 1024 * 1024 });
|
|
@@ -465,7 +495,14 @@ function buildEnglishOperation({ action, target, options }) {
|
|
|
465
495
|
"english.decide",
|
|
466
496
|
"POST",
|
|
467
497
|
`/cli/admin/english/review/${ref}`,
|
|
468
|
-
{
|
|
498
|
+
{
|
|
499
|
+
action,
|
|
500
|
+
skillCode: options.adminSkill || undefined,
|
|
501
|
+
reason: String(options.adminReason || "").trim() || undefined,
|
|
502
|
+
// retire --fault (Mikey 10-11): the question was at fault, so Grammar
|
|
503
|
+
// Quest forgives every miss on it; a duplicate or off-topic retire isn't
|
|
504
|
+
...(action === "retire" && options.adminFault ? { fault: true } : {}),
|
|
505
|
+
},
|
|
469
506
|
{ requiresRun: false },
|
|
470
507
|
);
|
|
471
508
|
}
|
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) : "",
|