@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-workflows.js
CHANGED
|
@@ -130,7 +130,7 @@ function pathEntryExists(filePath) {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
function acquireCheckpointLock(checkpointPath, operationFingerprint) {
|
|
133
|
+
export function acquireCheckpointLock(checkpointPath, operationFingerprint) {
|
|
134
134
|
const lockPath = `${checkpointPath}.lock`;
|
|
135
135
|
const reclaimPath = `${lockPath}.reclaim`;
|
|
136
136
|
mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
@@ -253,7 +253,7 @@ function removeDeadCheckpointLock(lockPath) {
|
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
function releaseCheckpointLock(lock) {
|
|
256
|
+
export function releaseCheckpointLock(lock) {
|
|
257
257
|
try {
|
|
258
258
|
const fileState = lstatSync(lock.lockPath);
|
|
259
259
|
if (!fileState.isFile() || fileState.isSymbolicLink()) return;
|
|
@@ -282,6 +282,15 @@ function operationFingerprintValue({
|
|
|
282
282
|
apiUrl: String(options.apiUrl || "").replace(/\/$/, ""),
|
|
283
283
|
name: operation.name,
|
|
284
284
|
path: pathWithCursor(operation.path, ""),
|
|
285
|
+
...(operation.pagination.summaryKeys
|
|
286
|
+
? { summaryKeys: operation.pagination.summaryKeys }
|
|
287
|
+
: {}),
|
|
288
|
+
// A completed pre-upgrade scan can still contain the old 30-day cap.
|
|
289
|
+
// Reject that checkpoint too: it would otherwise skip fetching entirely
|
|
290
|
+
// and record truncated coverage as a successful since-run scan.
|
|
291
|
+
...(operation.pagination.coverageMode === "since-run"
|
|
292
|
+
? { discoveryWindowContract: "stored-run-start-v1" }
|
|
293
|
+
: {}),
|
|
285
294
|
...(operation.name === "builds.candidates"
|
|
286
295
|
? {
|
|
287
296
|
resultTransform: {
|
|
@@ -637,6 +646,16 @@ export async function forEachPaginatedResultItem(result, visit) {
|
|
|
637
646
|
"The result does not contain spooled pagination data.",
|
|
638
647
|
);
|
|
639
648
|
}
|
|
649
|
+
if (storage.parts) {
|
|
650
|
+
let index = 0;
|
|
651
|
+
for (const part of storage.parts) {
|
|
652
|
+
await forEachPaginatedResultItem(
|
|
653
|
+
attachPaginationStorage({}, part),
|
|
654
|
+
async (item) => visit(item, index++),
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
640
659
|
verifyCandidateSpool({ ...storage, discardUnconfirmedTail: false });
|
|
641
660
|
const input = createReadStream(storage.spoolPath, { encoding: "utf8" });
|
|
642
661
|
const observedHash = createHash("sha256");
|
|
@@ -706,7 +725,7 @@ export async function writePaginatedResultJson({ result, write }) {
|
|
|
706
725
|
await write("]}}\n");
|
|
707
726
|
}
|
|
708
727
|
|
|
709
|
-
async function writePaginatedResultFile(filePath, result) {
|
|
728
|
+
export async function writePaginatedResultFile(filePath, result) {
|
|
710
729
|
const resolved = path.resolve(String(filePath || "").trim());
|
|
711
730
|
if (!String(filePath || "").trim()) {
|
|
712
731
|
throw validationError("An output file path is required.");
|
|
@@ -743,9 +762,26 @@ async function writePaginatedResultFile(filePath, result) {
|
|
|
743
762
|
return resolved;
|
|
744
763
|
}
|
|
745
764
|
|
|
765
|
+
// Keep large history event sets on disk when combining independently bounded
|
|
766
|
+
// subject batches. Each part retains its own verified spool and snapshot.
|
|
767
|
+
export function combinePaginatedResults(result, parts) {
|
|
768
|
+
const storages = parts.map(getPaginatedResultStorage);
|
|
769
|
+
if (
|
|
770
|
+
!storages.length ||
|
|
771
|
+
storages.some((entry) => !entry || entry.collectionKey !== storages[0].collectionKey)
|
|
772
|
+
) {
|
|
773
|
+
throw validationError("Cannot combine incompatible paginated results.");
|
|
774
|
+
}
|
|
775
|
+
return attachPaginationStorage(result, {
|
|
776
|
+
collectionKey: storages[0].collectionKey,
|
|
777
|
+
candidateCount: storages.reduce((sum, entry) => sum + entry.candidateCount, 0),
|
|
778
|
+
parts: storages,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
|
|
746
782
|
function aggregatePageResult({ operation, lastPage, checkpointPath, state }) {
|
|
747
783
|
const last = lastPage || { ok: true, status: "success", data: {} };
|
|
748
|
-
const lastData = { ...(last.data || {}) };
|
|
784
|
+
const lastData = { ...(last.data || {}), ...state.summaryData };
|
|
749
785
|
delete lastData[operation.pagination.collectionKey];
|
|
750
786
|
const lastPagination = { ...(last.data?.pagination || {}) };
|
|
751
787
|
const pageScannedCount = normalizeScannedCount(
|
|
@@ -809,6 +845,17 @@ function aggregatePageResult({ operation, lastPage, checkpointPath, state }) {
|
|
|
809
845
|
});
|
|
810
846
|
}
|
|
811
847
|
|
|
848
|
+
function retainedSummaryData(operation, data) {
|
|
849
|
+
return Object.fromEntries(
|
|
850
|
+
(operation.pagination.summaryKeys || []).map((key) => {
|
|
851
|
+
if (!data || !Object.hasOwn(data, key)) {
|
|
852
|
+
throw validationError(`History scan is missing ${key} summary metadata. Start a fresh scan.`);
|
|
853
|
+
}
|
|
854
|
+
return [key, data[key]];
|
|
855
|
+
}),
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
|
|
812
859
|
export async function runAutomaticPagination(args) {
|
|
813
860
|
const { options, operation, runId } = args;
|
|
814
861
|
if (!operation.pagination) {
|
|
@@ -929,6 +976,7 @@ async function runAutomaticPaginationWithLock({
|
|
|
929
976
|
filterSummariesComplete: true,
|
|
930
977
|
clientFilter: null,
|
|
931
978
|
operatorViewFilter: null,
|
|
979
|
+
summaryData: {},
|
|
932
980
|
resumed: false,
|
|
933
981
|
updatedAt: new Date().toISOString(),
|
|
934
982
|
};
|
|
@@ -1059,6 +1107,7 @@ async function runAutomaticPaginationWithLock({
|
|
|
1059
1107
|
savedPages > 0 && saved?.filterSummariesComplete === true
|
|
1060
1108
|
? normalizeOperatorViewFilterSummary(saved?.operatorViewFilter)
|
|
1061
1109
|
: null,
|
|
1110
|
+
summaryData: savedPages > 0 ? retainedSummaryData(operation, saved.summaryData) : {},
|
|
1062
1111
|
resumed: true,
|
|
1063
1112
|
};
|
|
1064
1113
|
spoolHash = verifyCandidateSpool({
|
|
@@ -1215,6 +1264,7 @@ async function runAutomaticPaginationWithLock({
|
|
|
1215
1264
|
spoolSha256: appended.spoolSha256,
|
|
1216
1265
|
clientFilter,
|
|
1217
1266
|
operatorViewFilter,
|
|
1267
|
+
summaryData: retainedSummaryData(operation, data),
|
|
1218
1268
|
nextCursor,
|
|
1219
1269
|
exhausted: pagination.exhausted,
|
|
1220
1270
|
updatedAt: new Date().toISOString(),
|