@stage5/lumine 0.3.36 → 0.3.37
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 +74 -1
- package/lib/commands.js +1 -0
- package/package.json +1 -1
- package/sdk/LUMINE_ADMIN.md +24 -0
package/lib/admin.js
CHANGED
|
@@ -3509,7 +3509,7 @@ export function parseAdminOperation(options) {
|
|
|
3509
3509
|
// long as two GPT-6.1 Sol calls, so it gets its own timeout. The daily
|
|
3510
3510
|
// website management run calls it in a bounded loop (Mikey, 2026-09-28).
|
|
3511
3511
|
const usage =
|
|
3512
|
-
"Usage: lumine admin reward-bank coverage <buildId> [--max-step 3] | seed <buildId> [--max-step 3] [--identity zero|ciel|auto] | report <buildId> [--days 1].";
|
|
3512
|
+
"Usage: lumine admin reward-bank coverage <buildId> [--max-step 3] | seed <buildId> [--max-step 3] [--identity zero|ciel|auto] | report <buildId> [--days 1] | question <buildId> --question-id <id> | repair <buildId> --file <repair.json> [--dry-run].";
|
|
3513
3513
|
const buildId = parseRequiredInteger(
|
|
3514
3514
|
target || options.adminBuild,
|
|
3515
3515
|
"Build ID",
|
|
@@ -3519,6 +3519,59 @@ export function parseAdminOperation(options) {
|
|
|
3519
3519
|
? parseRequiredInteger(options.adminMaxStep, "--max-step", 1)
|
|
3520
3520
|
: 3;
|
|
3521
3521
|
if (maxStep > 10) throw cliValidationError("--max-step must be at most 10.");
|
|
3522
|
+
if (action === "question") {
|
|
3523
|
+
const questionId = parseRequiredInteger(
|
|
3524
|
+
options.adminQuestionId,
|
|
3525
|
+
"--question-id",
|
|
3526
|
+
1,
|
|
3527
|
+
);
|
|
3528
|
+
return readOperation(
|
|
3529
|
+
"reward-bank.question",
|
|
3530
|
+
withQuery("/cli/admin/reward-bank/question", {
|
|
3531
|
+
buildId: String(buildId),
|
|
3532
|
+
questionId: String(questionId),
|
|
3533
|
+
}),
|
|
3534
|
+
{ requiresRun: false },
|
|
3535
|
+
);
|
|
3536
|
+
}
|
|
3537
|
+
if (action === "repair") {
|
|
3538
|
+
const repair = readAdminJsonFile(
|
|
3539
|
+
options.adminFile,
|
|
3540
|
+
"--file <repair.json>",
|
|
3541
|
+
{ maxBytes: 16 * 1024 },
|
|
3542
|
+
);
|
|
3543
|
+
const fields = ["questionId", "expectedFingerprint", "answer", "reason"];
|
|
3544
|
+
if (
|
|
3545
|
+
!repair ||
|
|
3546
|
+
typeof repair !== "object" ||
|
|
3547
|
+
Array.isArray(repair) ||
|
|
3548
|
+
Object.keys(repair).some((key) => !fields.includes(key)) ||
|
|
3549
|
+
!Number.isSafeInteger(repair.questionId) ||
|
|
3550
|
+
repair.questionId <= 0 ||
|
|
3551
|
+
typeof repair.answer !== "number" ||
|
|
3552
|
+
!Number.isFinite(repair.answer) ||
|
|
3553
|
+
typeof repair.expectedFingerprint !== "string" ||
|
|
3554
|
+
!/^[a-f0-9]{64}$/.test(repair.expectedFingerprint) ||
|
|
3555
|
+
typeof repair.reason !== "string" ||
|
|
3556
|
+
!repair.reason.trim() ||
|
|
3557
|
+
repair.reason.length > 2000
|
|
3558
|
+
) {
|
|
3559
|
+
throw cliValidationError(
|
|
3560
|
+
"Repair JSON needs questionId, the inspected expectedFingerprint, a finite numeric answer and a reason (1–2000 characters); no other fields.",
|
|
3561
|
+
);
|
|
3562
|
+
}
|
|
3563
|
+
return writeOperation(
|
|
3564
|
+
"reward-bank.repair",
|
|
3565
|
+
"POST",
|
|
3566
|
+
"/cli/admin/reward-bank/repair",
|
|
3567
|
+
{
|
|
3568
|
+
buildId,
|
|
3569
|
+
repair,
|
|
3570
|
+
dryRun: Boolean(options.adminDryRun),
|
|
3571
|
+
},
|
|
3572
|
+
{ requiresRun: false, mutates: !options.adminDryRun },
|
|
3573
|
+
);
|
|
3574
|
+
}
|
|
3522
3575
|
if (action === "report") {
|
|
3523
3576
|
const days = options.adminDays
|
|
3524
3577
|
? parseRequiredInteger(options.adminDays, "--days", 1)
|
|
@@ -7385,6 +7438,26 @@ function printAdminResult({ operation, result }) {
|
|
|
7385
7438
|
}
|
|
7386
7439
|
}
|
|
7387
7440
|
if (operation.name.startsWith("reward-bank.")) {
|
|
7441
|
+
if (
|
|
7442
|
+
["reward-bank.question", "reward-bank.repair"].includes(operation.name)
|
|
7443
|
+
) {
|
|
7444
|
+
const question = data.question;
|
|
7445
|
+
console.log(
|
|
7446
|
+
`Question #${question.id} · Build ${question.buildId} · ${question.mode} · ${question.status}`,
|
|
7447
|
+
);
|
|
7448
|
+
console.log(question.prompt);
|
|
7449
|
+
console.log(`Stored answer: ${question.answer}`);
|
|
7450
|
+
if (question.hint) console.log(`Hint: ${question.hint}`);
|
|
7451
|
+
if (question.guide) console.log(`Guide: ${question.guide}`);
|
|
7452
|
+
console.log(`Fingerprint: ${data.fingerprint}`);
|
|
7453
|
+
console.log(`History: ${JSON.stringify(data.impact)}`);
|
|
7454
|
+
if (Object.hasOwn(data, "proposedAnswer"))
|
|
7455
|
+
console.log(
|
|
7456
|
+
`Proposed answer: ${data.proposedAnswer} · would change: ${data.wouldChange}`,
|
|
7457
|
+
);
|
|
7458
|
+
console.log(data.historyPolicy);
|
|
7459
|
+
return;
|
|
7460
|
+
}
|
|
7388
7461
|
if (operation.name === "reward-bank.seed") {
|
|
7389
7462
|
console.log(
|
|
7390
7463
|
data.seeded
|
package/lib/commands.js
CHANGED
|
@@ -2803,6 +2803,7 @@ export function parseArgs(args) {
|
|
|
2803
2803
|
adminEditionId: raw.editionId ? String(raw.editionId) : "",
|
|
2804
2804
|
adminLeaseToken: raw.leaseToken ? String(raw.leaseToken) : "",
|
|
2805
2805
|
adminFile: raw.file ? String(raw.file) : "",
|
|
2806
|
+
adminQuestionId: raw.questionId ? String(raw.questionId) : "",
|
|
2806
2807
|
rewardPreflight: Boolean(raw.preflight),
|
|
2807
2808
|
rewardApprovalFile: raw.approvalFile ? String(raw.approvalFile) : "",
|
|
2808
2809
|
// admin craft revise --item <id|name> [--why] [--emoji] [--category]
|
package/package.json
CHANGED
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -1714,8 +1714,32 @@ them so the first learner on a unit never waits or pays.
|
|
|
1714
1714
|
lumine admin reward-bank coverage <buildId> [--max-step 3] [--json] # read-only, no run
|
|
1715
1715
|
lumine admin reward-bank seed <buildId> [--max-step 3] [--json] # delegated full run
|
|
1716
1716
|
lumine admin reward-bank report <buildId> [--days 1] [--json] # read-only telemetry
|
|
1717
|
+
lumine admin reward-bank question <buildId> --question-id <id> [--json]
|
|
1718
|
+
lumine admin reward-bank repair <buildId> --file <repair.json> --dry-run [--json]
|
|
1719
|
+
lumine admin reward-bank repair <buildId> --file <repair.json> [--json]
|
|
1717
1720
|
```
|
|
1718
1721
|
|
|
1722
|
+
`question` returns the complete prompt, answer, hint and guide, question
|
|
1723
|
+
statistics, a canonical `fingerprint`, and aggregate challenge history. It is
|
|
1724
|
+
owner-only and does not need a daily run. A report excerpt is not an exact
|
|
1725
|
+
question inspection.
|
|
1726
|
+
|
|
1727
|
+
`repair` accepts exactly `{ "questionId": 41, "expectedFingerprint": "<hash
|
|
1728
|
+
from inspection>", "answer": 0.5, "reason": "Verified explanation and arithmetic" }`.
|
|
1729
|
+
Inspect and verify the mathematics before preparing a repair. `--dry-run`
|
|
1730
|
+
checks the same guard without writing. The real command locks and rechecks the
|
|
1731
|
+
question, changes only its numeric answer, returns canonical readback and
|
|
1732
|
+
records an idempotent transaction audit. A stale fingerprint is rejected;
|
|
1733
|
+
inspect again instead of guessing a new hash. Unknown plan fields are rejected.
|
|
1734
|
+
No model call or AI Energy charge is involved.
|
|
1735
|
+
|
|
1736
|
+
The repaired answer governs subsequent attempts, including already-issued
|
|
1737
|
+
unsolved challenges. Past attempts, grades, ladders, question statistics and
|
|
1738
|
+
rewards stay unchanged; the receipt states this explicitly. The history counts
|
|
1739
|
+
are observations, not a lock over every learner's activity. If the old answer
|
|
1740
|
+
affected a learner, inspect that history and prepare a separate, exact remedy;
|
|
1741
|
+
this command never guesses compensating rewards or rewrites past grades.
|
|
1742
|
+
|
|
1719
1743
|
`report` covers the last `--days` (1-31): generation rounds by source
|
|
1720
1744
|
(learner or seed) with outcomes (`accepted`, `off_brief`: the checker judged
|
|
1721
1745
|
the question outside the brief's language, level or LaTeX rule;
|