@stage5/lumine 0.2.67 → 0.2.69
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/README.md +26 -1
- package/lib/admin-featured-history.js +185 -0
- package/lib/admin-featured.js +559 -0
- package/lib/admin-runtime-logs.js +23 -3
- package/lib/admin-workflows.js +54 -4
- package/lib/admin.js +371 -101
- package/lib/commands.js +19 -8
- package/lib/constants.js +21 -0
- package/lib/sdk.js +6 -0
- package/lib/sponsor-duty.js +15 -2
- package/package.json +1 -1
- package/sdk/BUILD_SDK_INDEX.md +68 -6
- package/sdk/LUMINE_ADMIN.md +542 -48
package/lib/admin.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
readAdminJsonFile,
|
|
9
9
|
validateNewsEditorial,
|
|
10
10
|
writeNewsClaimArtifacts,
|
|
11
|
+
writeAdminJsonFile,
|
|
11
12
|
} from "./admin-news.js";
|
|
12
13
|
import {
|
|
13
14
|
forEachPaginatedResultItem,
|
|
@@ -21,6 +22,8 @@ import {
|
|
|
21
22
|
runManagedBuildReview,
|
|
22
23
|
} from "./build-review.js";
|
|
23
24
|
import { runAdminRuntimeLogWorkflow } from "./admin-runtime-logs.js";
|
|
25
|
+
import { readApprovedFeaturedPlan, runFeaturedWorkflow } from "./admin-featured.js";
|
|
26
|
+
import { FEATURED_HISTORY_BATCH_SIZE, runBatchedFeaturedHistory } from "./admin-featured-history.js";
|
|
24
27
|
|
|
25
28
|
const MAX_EDITORIAL_FILE_BYTES = 256 * 1024;
|
|
26
29
|
const MAX_COMPOSED_TEXT_FILE_BYTES = 64 * 1024;
|
|
@@ -270,7 +273,9 @@ export async function adminCommand(options) {
|
|
|
270
273
|
recommendationContentTypes,
|
|
271
274
|
viewFilter,
|
|
272
275
|
});
|
|
273
|
-
if (operation.
|
|
276
|
+
if (operation.featuredWorkflow) {
|
|
277
|
+
result = await runFeaturedWorkflow({ options, operation, authToken: auth.token, runId });
|
|
278
|
+
} else if (operation.name === "build.review") {
|
|
274
279
|
result = await runManagedBuildReview({
|
|
275
280
|
options,
|
|
276
281
|
authToken: auth.token,
|
|
@@ -296,7 +301,10 @@ export async function adminCommand(options) {
|
|
|
296
301
|
"Use --resume with the scan checkpoint instead of combining --all with --cursor.",
|
|
297
302
|
);
|
|
298
303
|
}
|
|
299
|
-
|
|
304
|
+
const paginate = operation.name === "featured.history" &&
|
|
305
|
+
operation.pagination.filters.subjectIds.length > FEATURED_HISTORY_BATCH_SIZE
|
|
306
|
+
? runBatchedFeaturedHistory : runAutomaticPagination;
|
|
307
|
+
result = await paginate({
|
|
300
308
|
options,
|
|
301
309
|
operation,
|
|
302
310
|
runId,
|
|
@@ -325,9 +333,35 @@ export async function adminCommand(options) {
|
|
|
325
333
|
result = transformResult(await fetchOperation());
|
|
326
334
|
}
|
|
327
335
|
} catch (error) {
|
|
336
|
+
if (operation.name === "runtime.evidence" && error.status === 404) {
|
|
337
|
+
error.code = "CLI_ADMIN_RUNTIME_EVIDENCE_NOT_DEPLOYED";
|
|
338
|
+
error.message = "The runtime evidence route is not deployed on the requested host. Evidence is unknown; deploy the matching API and activate the collector in an authorized primary-generation release. No restart or host substitution was attempted.";
|
|
339
|
+
error.data = {
|
|
340
|
+
ok: false,
|
|
341
|
+
status: "unavailable",
|
|
342
|
+
error: { code: error.code, message: error.message, details: { httpStatus: 404 } },
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (operation.featuredWorkflow && error.featuredProgress) {
|
|
346
|
+
const serverError = error.data?.error;
|
|
347
|
+
error.data = {
|
|
348
|
+
ok: false,
|
|
349
|
+
status: "partial_failure",
|
|
350
|
+
error: {
|
|
351
|
+
code: serverError?.code || error.code || "LUMINE_ADMIN_FEATURED_WORKFLOW_FAILED",
|
|
352
|
+
message: error.message,
|
|
353
|
+
details: {
|
|
354
|
+
...(serverError && typeof serverError === "object" ? serverError.details : {}),
|
|
355
|
+
...error.featuredProgress,
|
|
356
|
+
retryInstruction: "Resume the exact command with --resume; confirmed items are not replayed.",
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
328
361
|
if (
|
|
329
362
|
operation.mutates &&
|
|
330
363
|
requestId &&
|
|
364
|
+
!operation.featuredWorkflow &&
|
|
331
365
|
operation.name !== "post.skip-batch"
|
|
332
366
|
) {
|
|
333
367
|
const retryInstruction = `Retry with --idempotency-key ${requestId}.`;
|
|
@@ -367,6 +401,9 @@ export async function adminCommand(options) {
|
|
|
367
401
|
typeof operation.body.buildReviewUnderstanding === "string",
|
|
368
402
|
});
|
|
369
403
|
}
|
|
404
|
+
if (operation.name === "comment.edit") {
|
|
405
|
+
assertComposedCommentEditResult({ result, body: operation.body });
|
|
406
|
+
}
|
|
370
407
|
if (operation.name === "ai-email-policy.set") {
|
|
371
408
|
assertAiEmailPolicySetResult({ operation, result });
|
|
372
409
|
}
|
|
@@ -402,6 +439,7 @@ function transformAdminResult({
|
|
|
402
439
|
assertSubjectWindowResult({ operation, result: transformed });
|
|
403
440
|
}
|
|
404
441
|
if (operation.name === "builds.candidates") {
|
|
442
|
+
assertBuildWindowResult({ operation, result: transformed });
|
|
405
443
|
transformed = normalizeAdminBuildCandidatesResult({
|
|
406
444
|
result: transformed,
|
|
407
445
|
siteUrl: options.siteUrl,
|
|
@@ -480,6 +518,14 @@ export function assertSubjectWindowResult({ operation, result }) {
|
|
|
480
518
|
|
|
481
519
|
async function finishAdminOutput({ options, operation, result }) {
|
|
482
520
|
const paginationStorage = getPaginatedResultStorage(result);
|
|
521
|
+
if (
|
|
522
|
+
options.adminOutput &&
|
|
523
|
+
!paginationStorage &&
|
|
524
|
+
operation.name !== "news.claim" &&
|
|
525
|
+
operation.name !== "post.skip-batch"
|
|
526
|
+
) {
|
|
527
|
+
writeAdminResultOutput({ filePath: options.adminOutput, result, operation });
|
|
528
|
+
}
|
|
483
529
|
if (options.json) {
|
|
484
530
|
if (paginationStorage) {
|
|
485
531
|
await writePaginatedResultJson({
|
|
@@ -507,13 +553,33 @@ async function finishAdminOutput({ options, operation, result }) {
|
|
|
507
553
|
return result;
|
|
508
554
|
}
|
|
509
555
|
|
|
556
|
+
export function writeAdminResultOutput({ filePath, result, operation }) {
|
|
557
|
+
try {
|
|
558
|
+
return writeAdminJsonFile(filePath, result, { privateFile: true });
|
|
559
|
+
} catch (cause) {
|
|
560
|
+
const error = new Error(
|
|
561
|
+
`The canonical ${operation.name} result was received, but --output could not be saved: ${cause.message}. Do not repeat a successful mutation just to save its output.`,
|
|
562
|
+
);
|
|
563
|
+
error.code = "LUMINE_ADMIN_OUTPUT_WRITE_FAILED";
|
|
564
|
+
error.data = {
|
|
565
|
+
ok: false,
|
|
566
|
+
status: "error",
|
|
567
|
+
error: {
|
|
568
|
+
code: error.code,
|
|
569
|
+
message: error.message,
|
|
570
|
+
details: { canonicalResult: result, outputPath: String(filePath) },
|
|
571
|
+
},
|
|
572
|
+
};
|
|
573
|
+
throw error;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
510
577
|
export function normalizeAdminBuildCandidatesResult({ result, siteUrl }) {
|
|
511
|
-
const builds =
|
|
512
|
-
const nextCursor = String(result?.cursor || "").trim() || null;
|
|
578
|
+
const builds = result.data.builds;
|
|
513
579
|
return {
|
|
514
|
-
|
|
515
|
-
status: "success",
|
|
580
|
+
...result,
|
|
516
581
|
data: {
|
|
582
|
+
...result.data,
|
|
517
583
|
builds: builds.map((build) => {
|
|
518
584
|
const id = Number(build?.id || 0);
|
|
519
585
|
return {
|
|
@@ -530,15 +596,128 @@ export function normalizeAdminBuildCandidatesResult({ result, siteUrl }) {
|
|
|
530
596
|
},
|
|
531
597
|
};
|
|
532
598
|
}),
|
|
533
|
-
pagination: {
|
|
534
|
-
nextCursor,
|
|
535
|
-
hasMore: Boolean(nextCursor),
|
|
536
|
-
exhausted: !nextCursor,
|
|
537
|
-
},
|
|
538
599
|
},
|
|
539
600
|
};
|
|
540
601
|
}
|
|
541
602
|
|
|
603
|
+
export function assertBuildWindowResult({ operation, result }) {
|
|
604
|
+
const p = result?.data?.pagination;
|
|
605
|
+
const mode = operation?.pagination?.coverageMode;
|
|
606
|
+
if (
|
|
607
|
+
result?.ok !== true ||
|
|
608
|
+
!Array.isArray(result?.data?.builds) ||
|
|
609
|
+
!p ||
|
|
610
|
+
p.mode !== mode ||
|
|
611
|
+
!Number.isSafeInteger(p.snapshotMaxId) ||
|
|
612
|
+
p.snapshotMaxId < 0 ||
|
|
613
|
+
!Number.isSafeInteger(p.snapshotTimeStamp) ||
|
|
614
|
+
p.snapshotTimeStamp < 0 ||
|
|
615
|
+
(mode === "legacy"
|
|
616
|
+
? p.after !== null
|
|
617
|
+
: !Number.isSafeInteger(p.after) || p.after < 0) ||
|
|
618
|
+
(mode === "after" && p.after !== operation.pagination.after) ||
|
|
619
|
+
typeof p.exhausted !== "boolean" ||
|
|
620
|
+
p.hasMore !== !p.exhausted ||
|
|
621
|
+
(p.exhausted
|
|
622
|
+
? p.nextCursor !== null
|
|
623
|
+
: typeof p.nextCursor !== "string" || !p.nextCursor)
|
|
624
|
+
) {
|
|
625
|
+
const error = new Error(
|
|
626
|
+
"The API did not confirm the requested published-Build window and snapshot. Deploy the matching API; do not substitute an unbounded public browser scan.",
|
|
627
|
+
);
|
|
628
|
+
error.code = "LUMINE_ADMIN_BUILD_WINDOW_UNSUPPORTED";
|
|
629
|
+
throw error;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export function assertComposedCommentEditResult({ result, body }) {
|
|
634
|
+
const edit = result?.data?.edit;
|
|
635
|
+
if (
|
|
636
|
+
result?.ok === true &&
|
|
637
|
+
result?.data?.comment?.content === body.content &&
|
|
638
|
+
(!body.buildReviewUnderstanding ||
|
|
639
|
+
(edit?.buildReviewContextStored === true &&
|
|
640
|
+
edit?.reviewedBuildVersionId === body.reviewedBuildVersionId &&
|
|
641
|
+
Number.isSafeInteger(edit?.managementDraftId) &&
|
|
642
|
+
edit.managementDraftId > 0))
|
|
643
|
+
)
|
|
644
|
+
return;
|
|
645
|
+
const error = new Error(
|
|
646
|
+
"The API did not confirm the exact comment edit and its required Build review context. Inspect the canonical result before retrying; deploy the matching API if unsupported.",
|
|
647
|
+
);
|
|
648
|
+
error.code = "LUMINE_ADMIN_COMMENT_EDIT_UNCONFIRMED";
|
|
649
|
+
error.data = {
|
|
650
|
+
ok: false,
|
|
651
|
+
status: "validation_error",
|
|
652
|
+
error: {
|
|
653
|
+
code: error.code,
|
|
654
|
+
message: error.message,
|
|
655
|
+
details: { canonicalResult: result },
|
|
656
|
+
},
|
|
657
|
+
};
|
|
658
|
+
throw error;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function readAdminBuildReviewEvidence(options, parsedTarget) {
|
|
662
|
+
const version = options.adminReviewedBuildVersion
|
|
663
|
+
? parseRequiredInteger(
|
|
664
|
+
options.adminReviewedBuildVersion,
|
|
665
|
+
"--reviewed-version",
|
|
666
|
+
1,
|
|
667
|
+
)
|
|
668
|
+
: undefined;
|
|
669
|
+
const method = options.adminBuildReviewMethod
|
|
670
|
+
? parseAdminBuildReviewMethod(options.adminBuildReviewMethod)
|
|
671
|
+
: undefined;
|
|
672
|
+
const receipt = options.adminReviewReceipt
|
|
673
|
+
? parseBuildReviewReceipt(options.adminReviewReceipt)
|
|
674
|
+
: null;
|
|
675
|
+
const understanding = options.adminReviewContext
|
|
676
|
+
? readBuildReviewContextFile(options.adminReviewContext)
|
|
677
|
+
: undefined;
|
|
678
|
+
if (receipt && (version || method)) {
|
|
679
|
+
throw cliValidationError(
|
|
680
|
+
"Pass either --review-receipt or manual --reviewed-version/--reviewed-via evidence, not both.",
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
const reviewedBuildVersionId = receipt
|
|
684
|
+
? Number(receipt.publishedArtifactVersionId)
|
|
685
|
+
: version;
|
|
686
|
+
const buildReviewMethod = receipt ? "runtime" : method;
|
|
687
|
+
if (understanding && (!reviewedBuildVersionId || !buildReviewMethod)) {
|
|
688
|
+
throw cliValidationError(
|
|
689
|
+
"--review-context requires confirmed Build review evidence.",
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
if ((reviewedBuildVersionId || buildReviewMethod) && !understanding) {
|
|
693
|
+
throw cliValidationError(
|
|
694
|
+
"Build review evidence requires --review-context <context.json>.",
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
if (
|
|
698
|
+
receipt &&
|
|
699
|
+
parsedTarget.type === "build" &&
|
|
700
|
+
Number(receipt.buildId) !== parsedTarget.id
|
|
701
|
+
) {
|
|
702
|
+
throw cliValidationError(
|
|
703
|
+
"The review receipt belongs to a different Build.",
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
if (
|
|
707
|
+
!["build", "comment"].includes(parsedTarget.type) &&
|
|
708
|
+
(reviewedBuildVersionId || buildReviewMethod)
|
|
709
|
+
) {
|
|
710
|
+
throw cliValidationError(
|
|
711
|
+
"Build review evidence applies only to build:<id> or a comment:<id> inside a Build.",
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
return {
|
|
715
|
+
...(reviewedBuildVersionId ? { reviewedBuildVersionId } : {}),
|
|
716
|
+
...(buildReviewMethod ? { buildReviewMethod } : {}),
|
|
717
|
+
...(understanding ? { buildReviewUnderstanding: understanding } : {}),
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
|
|
542
721
|
export function assertComposedCommentDraftResult({
|
|
543
722
|
result,
|
|
544
723
|
expectedContent,
|
|
@@ -756,7 +935,7 @@ export function canonicalAdminRunScope(run) {
|
|
|
756
935
|
const raw = run?.runScope;
|
|
757
936
|
if (raw === undefined || raw === null || raw === "") return "full";
|
|
758
937
|
const scope = String(raw);
|
|
759
|
-
if (
|
|
938
|
+
if (["full", "featured", "newspaper"].includes(scope)) return scope;
|
|
760
939
|
throw cliValidationError(
|
|
761
940
|
"The API returned an invalid administrator run scope.",
|
|
762
941
|
);
|
|
@@ -778,6 +957,12 @@ const FEATURED_RUN_OPERATIONS = new Set([
|
|
|
778
957
|
"featured.add",
|
|
779
958
|
"featured.reorder",
|
|
780
959
|
"featured.rotate",
|
|
960
|
+
"featured.plan",
|
|
961
|
+
"featured.apply",
|
|
962
|
+
"featured.comments.scan",
|
|
963
|
+
"featured.comments.acknowledge",
|
|
964
|
+
"featured.comments.recommend",
|
|
965
|
+
"featured.comments.report",
|
|
781
966
|
"daily-run.complete",
|
|
782
967
|
"daily-run.fail",
|
|
783
968
|
]);
|
|
@@ -786,6 +971,14 @@ export function assertAdminOperationAllowedForRunScope({
|
|
|
786
971
|
operation,
|
|
787
972
|
runScope,
|
|
788
973
|
}) {
|
|
974
|
+
if (runScope === "newspaper") {
|
|
975
|
+
if (
|
|
976
|
+
["news.status", "news.claim", "news.submit", "news.print", "daily-run.complete", "daily-run.fail"].includes(operation.name)
|
|
977
|
+
) return;
|
|
978
|
+
throw cliValidationError(
|
|
979
|
+
`A newspaper-only run does not authorize ${operation.name}.`,
|
|
980
|
+
);
|
|
981
|
+
}
|
|
789
982
|
if (runScope !== "featured") return;
|
|
790
983
|
const subjectCommentAlias =
|
|
791
984
|
operation.name === "post.comments" &&
|
|
@@ -794,7 +987,7 @@ export function assertAdminOperationAllowedForRunScope({
|
|
|
794
987
|
return;
|
|
795
988
|
}
|
|
796
989
|
throw cliValidationError(
|
|
797
|
-
`A Featured-only run does not authorize ${operation.name}.
|
|
990
|
+
`A Featured-only run does not authorize ${operation.name}. Use the review-bound Featured comment workflow for encouragement; do not start unrelated daily work to bypass scope.`,
|
|
798
991
|
);
|
|
799
992
|
}
|
|
800
993
|
|
|
@@ -809,6 +1002,7 @@ function adminOperationRequiresRun(operation) {
|
|
|
809
1002
|
"identity.use",
|
|
810
1003
|
"identity.inspect",
|
|
811
1004
|
"economy.trace",
|
|
1005
|
+
"bot.context",
|
|
812
1006
|
"rescue.wordle.audit",
|
|
813
1007
|
"daily-run.start",
|
|
814
1008
|
"daily-run.status",
|
|
@@ -1216,17 +1410,17 @@ export function parseAdminOperation(options) {
|
|
|
1216
1410
|
if (action === "start") {
|
|
1217
1411
|
const runScope = parseDailyRunScope(options.adminScope || "full");
|
|
1218
1412
|
const commentMode = parseCommentMode(options.commentMode || "off");
|
|
1219
|
-
if (runScope
|
|
1413
|
+
if (runScope !== "full" && commentMode !== "off") {
|
|
1220
1414
|
throw cliValidationError(
|
|
1221
|
-
"A
|
|
1415
|
+
"A scoped run requires --comment-mode off.",
|
|
1222
1416
|
);
|
|
1223
1417
|
}
|
|
1224
1418
|
return writeOperation(
|
|
1225
1419
|
"daily-run.start",
|
|
1226
1420
|
"POST",
|
|
1227
|
-
runScope === "
|
|
1228
|
-
? "/cli/admin/daily-runs/start
|
|
1229
|
-
:
|
|
1421
|
+
runScope === "full"
|
|
1422
|
+
? "/cli/admin/daily-runs/start"
|
|
1423
|
+
: `/cli/admin/daily-runs/start/${runScope}`,
|
|
1230
1424
|
{
|
|
1231
1425
|
identity: options.adminIdentity
|
|
1232
1426
|
? parseIdentity(options.adminIdentity)
|
|
@@ -1381,11 +1575,13 @@ export function parseAdminOperation(options) {
|
|
|
1381
1575
|
}
|
|
1382
1576
|
|
|
1383
1577
|
if (namespace === "builds" && action === "candidates") {
|
|
1578
|
+
const window = parseBuildWindow(options);
|
|
1384
1579
|
return readOperation(
|
|
1385
1580
|
"builds.candidates",
|
|
1386
|
-
withQuery("/
|
|
1387
|
-
|
|
1388
|
-
|
|
1581
|
+
withQuery("/cli/admin/builds/candidates", {
|
|
1582
|
+
sinceRun: window.mode === "since-run" ? "true" : "",
|
|
1583
|
+
after: window.mode === "after" ? window.after : "",
|
|
1584
|
+
includeLegacy: window.mode === "legacy" ? "true" : "",
|
|
1389
1585
|
cursor: options.adminCursor,
|
|
1390
1586
|
limit: options.limit,
|
|
1391
1587
|
}),
|
|
@@ -1393,9 +1589,12 @@ export function parseAdminOperation(options) {
|
|
|
1393
1589
|
pagination: {
|
|
1394
1590
|
collectionKey: "builds",
|
|
1395
1591
|
coverageQueue: "builds",
|
|
1396
|
-
coverageMode:
|
|
1397
|
-
after:
|
|
1398
|
-
|
|
1592
|
+
coverageMode: window.mode,
|
|
1593
|
+
after:
|
|
1594
|
+
window.mode === "after"
|
|
1595
|
+
? parseAfterForCoverage(window.after)
|
|
1596
|
+
: null,
|
|
1597
|
+
filters: { sort: "published-release", scope: "all" },
|
|
1399
1598
|
},
|
|
1400
1599
|
},
|
|
1401
1600
|
);
|
|
@@ -1414,6 +1613,9 @@ export function parseAdminOperation(options) {
|
|
|
1414
1613
|
body: undefined,
|
|
1415
1614
|
mutates: false,
|
|
1416
1615
|
buildId: parsed.id,
|
|
1616
|
+
// Public artifact inspection also supports a one-comment correction;
|
|
1617
|
+
// it never needs a full daily-management authorization envelope.
|
|
1618
|
+
requiresRun: false,
|
|
1417
1619
|
};
|
|
1418
1620
|
}
|
|
1419
1621
|
|
|
@@ -1483,6 +1685,30 @@ export function parseAdminOperation(options) {
|
|
|
1483
1685
|
}
|
|
1484
1686
|
|
|
1485
1687
|
if (namespace === "featured") {
|
|
1688
|
+
if (action === "comments") {
|
|
1689
|
+
if (!["scan", "acknowledge", "recommend", "report"].includes(target)) {
|
|
1690
|
+
throw cliValidationError("Usage: featured comments scan|acknowledge|recommend|report --checkpoint <file>.");
|
|
1691
|
+
}
|
|
1692
|
+
if (options.adminAll || options.adminCursor || options.adminUnviewed || options.adminViewed || options.adminAfter) {
|
|
1693
|
+
throw cliValidationError("The Featured review covers every comment; filtered or caller-supplied cursors are not supported.");
|
|
1694
|
+
}
|
|
1695
|
+
return { ...writeOperation(`featured.comments.${target}`, "POST", "/cli/admin/subjects/featured/reviews", {}),
|
|
1696
|
+
mutates: target !== "report", featuredWorkflow: target };
|
|
1697
|
+
}
|
|
1698
|
+
if (action === "plan") {
|
|
1699
|
+
if (!options.adminPostedAfter) throw cliValidationError("A Featured plan requires --posted-after <timestamp>.");
|
|
1700
|
+
return writeOperation("featured.plan", "POST", "/cli/admin/subjects/featured/plan", {
|
|
1701
|
+
removeIds: parseFeaturedSubjectIds(options.adminRemoveIds, "--remove-subject-ids"),
|
|
1702
|
+
addIds: parseFeaturedSubjectIds(options.adminAddIds, "--add-subject-ids"),
|
|
1703
|
+
...(options.adminIds ? { finalIds: parseOrderedIds(options.adminIds) } : {}),
|
|
1704
|
+
postedAfter: options.adminPostedAfter,
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
if (action === "apply") {
|
|
1708
|
+
readApprovedFeaturedPlan(options.adminFile, options.adminApprove);
|
|
1709
|
+
return { ...writeOperation("featured.apply", "POST", "/cli/admin/subjects/featured/plan/apply", {}),
|
|
1710
|
+
featuredWorkflow: "apply" };
|
|
1711
|
+
}
|
|
1486
1712
|
if (action === "list") {
|
|
1487
1713
|
return readOperation("featured.list", "/cli/admin/subjects/featured");
|
|
1488
1714
|
}
|
|
@@ -1491,6 +1717,12 @@ export function parseAdminOperation(options) {
|
|
|
1491
1717
|
options.adminIds,
|
|
1492
1718
|
"--subject-ids",
|
|
1493
1719
|
);
|
|
1720
|
+
if (subjectIds.length > 20_000) {
|
|
1721
|
+
throw cliValidationError("Featured history accepts at most 20000 subject IDs per CLI scan.");
|
|
1722
|
+
}
|
|
1723
|
+
if (subjectIds.length > FEATURED_HISTORY_BATCH_SIZE && !options.adminAll) {
|
|
1724
|
+
throw cliValidationError("Pass --all to automatically batch history reads larger than 100 subjects.");
|
|
1725
|
+
}
|
|
1494
1726
|
return readOperation(
|
|
1495
1727
|
"featured.history",
|
|
1496
1728
|
withQuery("/cli/admin/subjects/featured/history", {
|
|
@@ -1501,6 +1733,7 @@ export function parseAdminOperation(options) {
|
|
|
1501
1733
|
{
|
|
1502
1734
|
pagination: {
|
|
1503
1735
|
collectionKey: "events",
|
|
1736
|
+
summaryKeys: ["coverage", "subjects"],
|
|
1504
1737
|
filters: { subjectIds },
|
|
1505
1738
|
},
|
|
1506
1739
|
},
|
|
@@ -1528,7 +1761,7 @@ export function parseAdminOperation(options) {
|
|
|
1528
1761
|
if (namespace === "post") {
|
|
1529
1762
|
if (action === "get") return postGetOperation(target, options);
|
|
1530
1763
|
if (action === "comments") {
|
|
1531
|
-
const parsedTarget =
|
|
1764
|
+
const parsedTarget = parseAdminCommentTarget({
|
|
1532
1765
|
target,
|
|
1533
1766
|
explicitType: options.adminType,
|
|
1534
1767
|
});
|
|
@@ -1729,7 +1962,9 @@ export function parseAdminOperation(options) {
|
|
|
1729
1962
|
"ai-costs monthly uses UTC calendar months and does not accept --days.",
|
|
1730
1963
|
);
|
|
1731
1964
|
}
|
|
1732
|
-
return readOperation("ai-costs.monthly", "/cli/admin/ai-costs/monthly"
|
|
1965
|
+
return readOperation("ai-costs.monthly", "/cli/admin/ai-costs/monthly", {
|
|
1966
|
+
requiresRun: false,
|
|
1967
|
+
});
|
|
1733
1968
|
}
|
|
1734
1969
|
if (action === "day" && !extra) {
|
|
1735
1970
|
if (options.adminDays) {
|
|
@@ -1770,10 +2005,23 @@ export function parseAdminOperation(options) {
|
|
|
1770
2005
|
);
|
|
1771
2006
|
}
|
|
1772
2007
|
|
|
2008
|
+
if (namespace === "runtime") {
|
|
2009
|
+
if (action !== "evidence" || !["primary", "target"].includes(target) || extra) {
|
|
2010
|
+
throw cliValidationError("Usage: lumine admin runtime evidence primary|target [--days 1..7].");
|
|
2011
|
+
}
|
|
2012
|
+
return readOperation(
|
|
2013
|
+
"runtime.evidence",
|
|
2014
|
+
withQuery(`/cli/admin/runtime-logs/hosts/${target}/evidence`, {
|
|
2015
|
+
days: parseRequiredInteger(options.adminDays || "7", "--days", 1, 7),
|
|
2016
|
+
}),
|
|
2017
|
+
{ requiresRun: false },
|
|
2018
|
+
);
|
|
2019
|
+
}
|
|
2020
|
+
|
|
1773
2021
|
if (namespace === "runtime-logs") {
|
|
1774
2022
|
if (
|
|
1775
2023
|
(action === "start" || action === "status" || action === "read") &&
|
|
1776
|
-
!target &&
|
|
2024
|
+
(!target || (action === "start" && ["primary", "target"].includes(target))) &&
|
|
1777
2025
|
!extra
|
|
1778
2026
|
) {
|
|
1779
2027
|
if (
|
|
@@ -1793,6 +2041,7 @@ export function parseAdminOperation(options) {
|
|
|
1793
2041
|
mutates: action !== "status",
|
|
1794
2042
|
requiresRun: false,
|
|
1795
2043
|
runtimeLogAction: action === "read" ? "capture" : action,
|
|
2044
|
+
...(action === "start" && target ? { runtimeLogHost: target } : {}),
|
|
1796
2045
|
};
|
|
1797
2046
|
}
|
|
1798
2047
|
if ((action === "resume" || action === "abandon") && !target && !extra) {
|
|
@@ -1888,6 +2137,36 @@ export function parseAdminOperation(options) {
|
|
|
1888
2137
|
});
|
|
1889
2138
|
}
|
|
1890
2139
|
|
|
2140
|
+
if (namespace === "bot-output" && action === "context") {
|
|
2141
|
+
const messageId = parseRequiredInteger(target, "bot message ID", 1);
|
|
2142
|
+
const reason = String(options.adminReason || "").trim();
|
|
2143
|
+
if (!reason || reason.length > MAX_IDENTITY_INSPECTION_REASON_LENGTH) {
|
|
2144
|
+
throw cliValidationError(
|
|
2145
|
+
"Explain the private bot investigation with --reason (1–500 characters).",
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
if (options.adminAll || options.adminDays) {
|
|
2149
|
+
throw cliValidationError(
|
|
2150
|
+
"Bot context is a narrow message-ID investigation, not an --all or --days scan.",
|
|
2151
|
+
);
|
|
2152
|
+
}
|
|
2153
|
+
return writeOperation(
|
|
2154
|
+
"bot.context",
|
|
2155
|
+
"POST",
|
|
2156
|
+
`/cli/admin/bot-output/${messageId}/context`,
|
|
2157
|
+
{
|
|
2158
|
+
reason,
|
|
2159
|
+
cursor: options.adminCursor || undefined,
|
|
2160
|
+
limit: parseRequiredInteger(
|
|
2161
|
+
options.adminContextLimit ?? 20,
|
|
2162
|
+
"--limit",
|
|
2163
|
+
1,
|
|
2164
|
+
40,
|
|
2165
|
+
),
|
|
2166
|
+
},
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
1891
2170
|
if (namespace === "bot-output" && !action) {
|
|
1892
2171
|
if (options.adminDays && options.adminCursor) {
|
|
1893
2172
|
throw cliValidationError(
|
|
@@ -1939,58 +2218,10 @@ export function parseAdminOperation(options) {
|
|
|
1939
2218
|
"comment reply targets a comment: lumine admin comment reply comment:<id>.",
|
|
1940
2219
|
);
|
|
1941
2220
|
}
|
|
1942
|
-
const
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
1,
|
|
1947
|
-
)
|
|
1948
|
-
: undefined;
|
|
1949
|
-
const buildReviewMethod = options.adminBuildReviewMethod
|
|
1950
|
-
? parseAdminBuildReviewMethod(options.adminBuildReviewMethod)
|
|
1951
|
-
: undefined;
|
|
1952
|
-
const reviewReceipt = options.adminReviewReceipt
|
|
1953
|
-
? parseBuildReviewReceipt(options.adminReviewReceipt)
|
|
1954
|
-
: null;
|
|
1955
|
-
const buildReviewUnderstanding = options.adminReviewContext
|
|
1956
|
-
? readBuildReviewContextFile(options.adminReviewContext)
|
|
1957
|
-
: undefined;
|
|
1958
|
-
if (reviewReceipt && (reviewedBuildVersionId || buildReviewMethod)) {
|
|
1959
|
-
throw cliValidationError(
|
|
1960
|
-
"Pass either --review-receipt or manual --reviewed-version/--reviewed-via evidence, not both.",
|
|
1961
|
-
);
|
|
1962
|
-
}
|
|
1963
|
-
const confirmedBuildVersionId = reviewReceipt
|
|
1964
|
-
? Number(reviewReceipt.publishedArtifactVersionId)
|
|
1965
|
-
: reviewedBuildVersionId;
|
|
1966
|
-
const confirmedBuildReviewMethod = reviewReceipt
|
|
1967
|
-
? "runtime"
|
|
1968
|
-
: buildReviewMethod;
|
|
1969
|
-
if (
|
|
1970
|
-
buildReviewUnderstanding &&
|
|
1971
|
-
(!confirmedBuildVersionId || !confirmedBuildReviewMethod)
|
|
1972
|
-
) {
|
|
1973
|
-
throw cliValidationError(
|
|
1974
|
-
"--review-context requires confirmed Build review evidence.",
|
|
1975
|
-
);
|
|
1976
|
-
}
|
|
1977
|
-
if (
|
|
1978
|
-
(confirmedBuildVersionId || confirmedBuildReviewMethod) &&
|
|
1979
|
-
!buildReviewUnderstanding
|
|
1980
|
-
) {
|
|
1981
|
-
throw cliValidationError(
|
|
1982
|
-
"Build review evidence requires --review-context <context.json>.",
|
|
1983
|
-
);
|
|
1984
|
-
}
|
|
1985
|
-
if (
|
|
1986
|
-
reviewReceipt &&
|
|
1987
|
-
parsedTarget.type === "build" &&
|
|
1988
|
-
Number(reviewReceipt.buildId) !== parsedTarget.id
|
|
1989
|
-
) {
|
|
1990
|
-
throw cliValidationError(
|
|
1991
|
-
"The review receipt belongs to a different Build.",
|
|
1992
|
-
);
|
|
1993
|
-
}
|
|
2221
|
+
const reviewEvidence = readAdminBuildReviewEvidence(
|
|
2222
|
+
options,
|
|
2223
|
+
parsedTarget,
|
|
2224
|
+
);
|
|
1994
2225
|
if (parsedTarget.type === "build") {
|
|
1995
2226
|
if (!options.adminFile) {
|
|
1996
2227
|
throw cliValidationError(
|
|
@@ -1998,21 +2229,14 @@ export function parseAdminOperation(options) {
|
|
|
1998
2229
|
);
|
|
1999
2230
|
}
|
|
2000
2231
|
if (
|
|
2001
|
-
!
|
|
2002
|
-
!
|
|
2003
|
-
!buildReviewUnderstanding
|
|
2232
|
+
!reviewEvidence.reviewedBuildVersionId ||
|
|
2233
|
+
!reviewEvidence.buildReviewMethod ||
|
|
2234
|
+
!reviewEvidence.buildReviewUnderstanding
|
|
2004
2235
|
) {
|
|
2005
2236
|
throw cliValidationError(
|
|
2006
2237
|
"After reviewing the project, pass review evidence and --review-context <context.json>.",
|
|
2007
2238
|
);
|
|
2008
2239
|
}
|
|
2009
|
-
} else if (
|
|
2010
|
-
parsedTarget.type !== "comment" &&
|
|
2011
|
-
(confirmedBuildVersionId || confirmedBuildReviewMethod)
|
|
2012
|
-
) {
|
|
2013
|
-
throw cliValidationError(
|
|
2014
|
-
"Build review evidence applies only to build:<id> or a comment:<id> inside a Build.",
|
|
2015
|
-
);
|
|
2016
2240
|
}
|
|
2017
2241
|
return writeOperation(
|
|
2018
2242
|
"comment.draft",
|
|
@@ -2027,13 +2251,7 @@ export function parseAdminOperation(options) {
|
|
|
2027
2251
|
...(options.adminFile
|
|
2028
2252
|
? { content: readComposedTextFile(options.adminFile) }
|
|
2029
2253
|
: {}),
|
|
2030
|
-
...
|
|
2031
|
-
? { reviewedBuildVersionId: confirmedBuildVersionId }
|
|
2032
|
-
: {}),
|
|
2033
|
-
...(confirmedBuildReviewMethod
|
|
2034
|
-
? { buildReviewMethod: confirmedBuildReviewMethod }
|
|
2035
|
-
: {}),
|
|
2036
|
-
...(buildReviewUnderstanding ? { buildReviewUnderstanding } : {}),
|
|
2254
|
+
...reviewEvidence,
|
|
2037
2255
|
},
|
|
2038
2256
|
);
|
|
2039
2257
|
}
|
|
@@ -2058,7 +2276,13 @@ export function parseAdminOperation(options) {
|
|
|
2058
2276
|
"comment.edit",
|
|
2059
2277
|
"PUT",
|
|
2060
2278
|
`/cli/admin/comments/${commentId}`,
|
|
2061
|
-
{
|
|
2279
|
+
{
|
|
2280
|
+
content: readComposedTextFile(options.adminFile),
|
|
2281
|
+
...readAdminBuildReviewEvidence(options, {
|
|
2282
|
+
type: "comment",
|
|
2283
|
+
id: commentId,
|
|
2284
|
+
}),
|
|
2285
|
+
},
|
|
2062
2286
|
{
|
|
2063
2287
|
correctionEligible: true,
|
|
2064
2288
|
correctionCommentId: commentId,
|
|
@@ -2243,6 +2467,7 @@ function featuredRotateOperation(options) {
|
|
|
2243
2467
|
{
|
|
2244
2468
|
removeIds,
|
|
2245
2469
|
addIds,
|
|
2470
|
+
...(options.adminPostedAfter ? { postedAfter: options.adminPostedAfter } : {}),
|
|
2246
2471
|
},
|
|
2247
2472
|
);
|
|
2248
2473
|
}
|
|
@@ -2303,6 +2528,22 @@ export function parseSubjectWindow(options) {
|
|
|
2303
2528
|
return { mode, after: mode === "after" ? options.adminAfter : "" };
|
|
2304
2529
|
}
|
|
2305
2530
|
|
|
2531
|
+
export function parseBuildWindow(options) {
|
|
2532
|
+
const selected = [
|
|
2533
|
+
options.adminSinceRun ? "since-run" : "",
|
|
2534
|
+
options.adminAfter ? "after" : "",
|
|
2535
|
+
options.adminIncludeLegacy ? "legacy" : "",
|
|
2536
|
+
].filter(Boolean);
|
|
2537
|
+
if (selected.length > 1) {
|
|
2538
|
+
throw cliValidationError(
|
|
2539
|
+
"Choose one Build window: --since-run, --after, or --include-legacy.",
|
|
2540
|
+
);
|
|
2541
|
+
}
|
|
2542
|
+
const mode = selected[0] || "since-run";
|
|
2543
|
+
if (mode === "after") parseAfterForCoverage(options.adminAfter);
|
|
2544
|
+
return { mode, after: mode === "after" ? options.adminAfter : "" };
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2306
2547
|
function parseUtcDayKey(value) {
|
|
2307
2548
|
const dayKey = String(value || "").trim();
|
|
2308
2549
|
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(dayKey);
|
|
@@ -2524,7 +2765,7 @@ export function assertAdminTodoHandoffResult(result, expectedRunScope = null) {
|
|
|
2524
2765
|
throw error;
|
|
2525
2766
|
}
|
|
2526
2767
|
const handoff = result?.data?.carryoverTodos;
|
|
2527
|
-
if (runScope
|
|
2768
|
+
if (runScope !== "full") {
|
|
2528
2769
|
if (
|
|
2529
2770
|
!runId ||
|
|
2530
2771
|
!handoff ||
|
|
@@ -2536,7 +2777,7 @@ export function assertAdminTodoHandoffResult(result, expectedRunScope = null) {
|
|
|
2536
2777
|
Number(handoff.newlySurfacedCount) !== 0
|
|
2537
2778
|
) {
|
|
2538
2779
|
const error = cliValidationError(
|
|
2539
|
-
"The API did not confirm that carry-over telemetry was suppressed for the
|
|
2780
|
+
"The API did not confirm that carry-over telemetry was suppressed for the scoped run.",
|
|
2540
2781
|
);
|
|
2541
2782
|
error.code = "LUMINE_ADMIN_SCOPED_RUN_UNSUPPORTED";
|
|
2542
2783
|
throw error;
|
|
@@ -2617,8 +2858,8 @@ function parseDailyRunScope(value) {
|
|
|
2617
2858
|
const scope = String(value || "full")
|
|
2618
2859
|
.trim()
|
|
2619
2860
|
.toLowerCase();
|
|
2620
|
-
if (!["full", "featured"].includes(scope)) {
|
|
2621
|
-
throw cliValidationError("--scope must be full or
|
|
2861
|
+
if (!["full", "featured", "newspaper"].includes(scope)) {
|
|
2862
|
+
throw cliValidationError("--scope must be full, featured, or newspaper.");
|
|
2622
2863
|
}
|
|
2623
2864
|
return scope;
|
|
2624
2865
|
}
|
|
@@ -3156,6 +3397,28 @@ async function printSpooledAdminResult({ operation, result, storage }) {
|
|
|
3156
3397
|
|
|
3157
3398
|
function printAdminResult({ operation, result }) {
|
|
3158
3399
|
const data = result?.data || {};
|
|
3400
|
+
if (operation.name === "runtime.evidence") {
|
|
3401
|
+
const evidence = data.evidence || {};
|
|
3402
|
+
console.log(`Runtime evidence (${data.host?.requested || "unknown"}): ${evidence.status || "unknown"}.`);
|
|
3403
|
+
console.log(`Samples: ${evidence.coverage?.samples ?? "unknown"}; latest: ${evidence.coverage?.lastAtMs ?? "unknown"}; age ms: ${evidence.coverage?.ageMs ?? "unknown"}.`);
|
|
3404
|
+
for (const recycle of evidence.recycles || []) {
|
|
3405
|
+
console.log(` ${recycle.id}: ${recycle.outcome}; under load: ${recycle.observedUnderLoad ?? "unknown"}.`);
|
|
3406
|
+
}
|
|
3407
|
+
console.log("Missing evidence is unknown, not healthy. A recovered topology does not verify interrupted user work. Use --json for full evidence.");
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3410
|
+
if (operation.name === "featured.plan") {
|
|
3411
|
+
for (const pair of data.plan?.replacements || []) {
|
|
3412
|
+
console.log(`${pair.remove.id} ${pair.remove.title} -> ${pair.add.id} ${pair.add.title}`);
|
|
3413
|
+
}
|
|
3414
|
+
console.log(`Proposed final order: ${(data.plan?.finalIds || []).join(",")}`);
|
|
3415
|
+
console.log(`Plan hash: ${data.planHash}. Obtain Mikey's approval before using featured apply --file <plan.json> --approve ${data.planHash}.`);
|
|
3416
|
+
return;
|
|
3417
|
+
}
|
|
3418
|
+
if (operation.featuredWorkflow) {
|
|
3419
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3159
3422
|
if (Array.isArray(data.applications)) {
|
|
3160
3423
|
console.log(`${data.applications.length} sponsor application(s):`);
|
|
3161
3424
|
for (const application of data.applications) {
|
|
@@ -3300,6 +3563,13 @@ function printAdminResult({ operation, result }) {
|
|
|
3300
3563
|
` ${coverage.queue}: ${coverage.candidateCount} candidate(s), ${coverage.scannedCount} row(s) scanned across ${coverage.pages} page(s).`,
|
|
3301
3564
|
);
|
|
3302
3565
|
}
|
|
3566
|
+
for (const item of report.featuredReviews || []) {
|
|
3567
|
+
const coverage = item.coverage;
|
|
3568
|
+
const counts = item.encouragement || {};
|
|
3569
|
+
console.log(
|
|
3570
|
+
` Featured review #${item.review?.id || coverage?.reviewId}: ${coverage?.reviewed ? `${coverage.coveredSubjectIds.length}/${coverage.subjectCount} Subjects read, ${coverage.commentsRead} comments` : "not acknowledged as read"}; ${coverage?.complete ? "complete" : "incomplete"}; ${counts.newBasicRecommendations || 0} confirmed new basic recommendations, ${counts.alreadyDone || 0} already done, ${counts.rewardEligibilityGrants || 0} reward-permission grants, ${counts.directRewardsCreated || 0} direct rewards.`,
|
|
3571
|
+
);
|
|
3572
|
+
}
|
|
3303
3573
|
for (const escalation of report.escalations) {
|
|
3304
3574
|
const target =
|
|
3305
3575
|
escalation.url ||
|