fix: preserve native trending through mirror rollout (#3313)

This commit is contained in:
Patrick Erichsen
2026-07-30 10:16:28 -07:00
committed by GitHub
parent 3282ff9ad7
commit dc51281c87
9 changed files with 559 additions and 19 deletions
+25
View File
@@ -829,6 +829,15 @@ describe("canonical Trending snapshot storage", () => {
.unique();
if (!control) throw new Error("catalog control missing");
await ctx.db.patch(control._id, { mirrorPublicVisibilityEnabled: true });
const mirrorControl = await ctx.db
.query("skillsShMirrorControls")
.withIndex("by_key", (q) => q.eq("key", "global"))
.unique();
if (!mirrorControl) throw new Error("mirror control missing");
await ctx.db.patch(mirrorControl._id, {
activationLockToken: "native-only-lock",
activationLockedAt: now,
});
});
const pageResult = await t.query(internal.canonicalTrending.getPageInternal, {
cursor: null,
@@ -866,5 +875,21 @@ describe("canonical Trending snapshot storage", () => {
},
}),
]);
const nativeOnly = await t.action(internal.canonicalTrending.materializeInternal, {
activationLockToken: "native-only-lock",
skillsShMode: "native-only",
});
expect(nativeOnly).toMatchObject({
status: "ready",
totalItems: 1,
sourceCounts: { clawhubTrending: 1, clawhubRising: 1, skillsShTrending: 0 },
});
await expect(
t.query(internal.canonicalTrending.getPageInternal, { cursor: null, limit: 20 }),
).resolves.toMatchObject({
status: "ok",
page: { items: [{ source: "clawhub" }] },
});
});
});
+29 -3
View File
@@ -215,7 +215,10 @@ export const getExternalSourcePageInternal = internalQuery({
});
export const getMaterializationModeInternal = internalQuery({
args: { activationLockToken: v.optional(v.string()) },
args: {
activationLockToken: v.optional(v.string()),
skillsShMode: v.optional(v.literal("native-only")),
},
handler: async (ctx, args) => {
const control = await ctx.db
.query("skillsShMirrorControls")
@@ -331,6 +334,7 @@ export const finalizeSnapshotInternal = internalMutation({
totalItems: v.number(),
sourceCounts: sourceCountsValidator,
operations: operationsValidator,
activationLockToken: v.optional(v.string()),
},
handler: async (ctx, args) => {
const snapshot = await ctx.db
@@ -343,6 +347,17 @@ export const finalizeSnapshotInternal = internalMutation({
if (snapshot.writtenItems !== args.totalItems) {
throw new Error("Trending snapshot item count mismatch");
}
const mirrorControl = await ctx.db
.query("skillsShMirrorControls")
.withIndex("by_key", (q) => q.eq("key", "global"))
.unique();
if (args.activationLockToken) {
if (mirrorControl?.activationLockToken !== args.activationLockToken) {
throw new Error("skills.sh activation lock changed before Trending publication");
}
} else if (mirrorControl?.activationLockToken) {
throw new Error("skills.sh activation started before Trending publication");
}
await ctx.db.patch(snapshot._id, {
status: "ready",
completedAt: args.completedAt,
@@ -421,6 +436,7 @@ export const materializeInternal = internalAction({
args: {
proofSnapshotId: v.optional(v.string()),
activationLockToken: v.optional(v.string()),
skillsShMode: v.optional(v.literal("native-only")),
},
handler: async (ctx, args) => {
if (args.proofSnapshotId !== undefined) {
@@ -429,6 +445,9 @@ export const materializeInternal = internalAction({
throw new Error("Invalid CLAW-590 proof snapshot ID");
}
}
if (args.skillsShMode === "native-only" && !args.activationLockToken) {
throw new Error("native-only Trending materialization requires a visibility lock");
}
const startedAt = Date.now();
const snapshotId = args.proofSnapshotId ?? `skills-${startedAt}`;
let snapshotStarted = false;
@@ -439,7 +458,10 @@ export const materializeInternal = internalAction({
try {
await ctx.runQuery(
internalRefs.canonicalTrending.getMaterializationModeInternal as never,
{ activationLockToken: args.activationLockToken } as never,
{
activationLockToken: args.activationLockToken,
skillsShMode: args.skillsShMode,
} as never,
);
functionCalls += 1;
type HourlyWindow = {
@@ -493,7 +515,10 @@ export const materializeInternal = internalAction({
documentsRead: 0,
functionCalls: 0,
};
if (getRuntimeRolloutCapabilities().skillsSh.runtimeEnabled) {
if (
args.skillsShMode !== "native-only" &&
getRuntimeRolloutCapabilities().skillsSh.runtimeEnabled
) {
const candidateRun = (await ctx.runQuery(
internalRefs.canonicalTrending.getLatestCompletedTrendingRunInternal as never,
{},
@@ -608,6 +633,7 @@ export const materializeInternal = internalAction({
totalItems: blended.length,
sourceCounts,
operations,
activationLockToken: args.activationLockToken,
} as never,
);
functionCalls += 1;
+32
View File
@@ -72,6 +72,8 @@ const internalRefs = internal as unknown as {
storeSourcePageInternal: unknown;
};
skillsShMirrorVisibility: {
deactivateAndMaterializeInternal: unknown;
prepareNativeTrendingInternal: unknown;
setPublicGateInternal: unknown;
verifyAndActivateInternal: unknown;
};
@@ -688,6 +690,36 @@ export async function skillsShCatalogTestV1Handler(ctx: ActionCtx, request: Requ
rate.headers,
);
}
if (operation === "mirror-prepare-native-trending") {
return json(
await runActionRef(
ctx,
internalRefs.skillsShMirrorVisibility.prepareNativeTrendingInternal,
{
actor,
reason: requireString(body, "reason"),
confirm: requireString(body, "confirm"),
},
),
200,
rate.headers,
);
}
if (operation === "mirror-deactivate-native-trending") {
return json(
await runActionRef(
ctx,
internalRefs.skillsShMirrorVisibility.deactivateAndMaterializeInternal,
{
actor,
reason: requireString(body, "reason"),
confirm: requireString(body, "confirm"),
},
),
200,
rate.headers,
);
}
if (operation === "mirror-public-gate") {
return json(
await runMutationRef(ctx, internalRefs.skillsShMirrorVisibility.setPublicGateInternal, {
+155 -4
View File
@@ -347,6 +347,51 @@ describe("skills.sh mirror visibility operations", () => {
reason: "CLAW-603 verification test",
updatedAt: now - 2_000,
});
const nativeOwnerId = await ctx.db.insert("users", {
handle: "native-owner",
displayName: "Native owner",
createdAt: now - 10_000,
updatedAt: now,
});
const nativeSkillId = await ctx.db.insert("skills", {
slug: "native-ready",
displayName: "Native ready",
summary: "Native canonical Trending fixture",
ownerUserId: nativeOwnerId,
tags: {},
statsInstallsAllTime: 900,
stats: { downloads: 1_000, installsAllTime: 900, stars: 20, versions: 1, comments: 0 },
createdAt: now - 10_000,
updatedAt: now,
});
const nativeVersionId = await ctx.db.insert("skillVersions", {
skillId: nativeSkillId,
version: "1.0.0",
changelog: "Initial",
files: [],
parsed: { frontmatter: {} },
createdBy: nativeOwnerId,
createdAt: now - 10_000,
});
await ctx.db.insert("skillSearchDigest", {
skillId: nativeSkillId,
slug: "native-ready",
displayName: "Native ready",
summary: "Native canonical Trending fixture",
ownerUserId: nativeOwnerId,
ownerHandle: "native-owner",
ownerKind: "user",
ownerName: "Native owner",
ownerDisplayName: "Native owner",
latestVersionId: nativeVersionId,
latestVersionSkillId: nativeSkillId,
publicVersion: { status: "available", versionId: nativeVersionId },
tags: {},
statsInstallsAllTime: 900,
stats: { downloads: 1_000, installsAllTime: 900, stars: 20, versions: 1, comments: 0 },
createdAt: now - 10_000,
updatedAt: now,
});
await ctx.db.insert("skillHourlyStatStates", {
key: "canonical_trending",
liveStartedAt: now - 3_600_000,
@@ -357,6 +402,16 @@ describe("skills.sh mirror visibility operations", () => {
lastProcessedEventCreationTime: 100,
updatedAt: now,
});
await ctx.db.insert("skillHourlyStats", {
skillId: nativeSkillId,
hour: window.endHour,
generation: 0,
downloads: 18,
installs: 12,
bookmarks: 4,
updatedAt: now,
expiresAt: now + 72 * 3_600_000,
});
});
await expect(
@@ -402,6 +457,69 @@ describe("skills.sh mirror visibility operations", () => {
}));
expect(activationState.mirrorControl?.activationLockToken).toBeUndefined();
expect(activationState.snapshots).toHaveLength(1);
await expect(
t.query(internal.canonicalTrending.getPageInternal, { cursor: null, limit: 20 }),
).resolves.toMatchObject({
status: "ok",
page: { items: [{ source: "clawhub" }, { source: "skills-sh" }] },
});
await t.run(async (ctx) => {
const state = await ctx.db
.query("skillHourlyStatStates")
.withIndex("by_key", (q) => q.eq("key", "canonical_trending"))
.unique();
if (!state) throw new Error("hourly state missing");
await ctx.db.delete(state._id);
});
await expect(
t.action(internal.skillsShMirrorVisibility.deactivateAndMaterializeInternal, {
actor: "codex-test",
reason: "CLAW-603 fail-closed rollback",
confirm: "deactivate-skills-sh-public-test",
}),
).rejects.toThrow("native-only canonical Trending did not become ready");
await expect(
t.query(internal.canonicalTrending.getPageInternal, { cursor: null, limit: 20 }),
).resolves.toMatchObject({
status: "ok",
page: { items: [{ source: "clawhub" }] },
});
await t.run(async (ctx) => {
await ctx.db.insert("skillHourlyStatStates", {
key: "canonical_trending",
liveStartedAt: now - 3_600_000,
eventBackfillThroughCreationTime: 100,
activeGeneration: 1,
backfillCompletedAt: now - 1_000,
lastAggregationCompletedAt: window.endAt + 1,
lastProcessedEventCreationTime: 100,
updatedAt: now,
});
});
await expect(
t.action(internal.skillsShMirrorVisibility.deactivateAndMaterializeInternal, {
actor: "codex-test",
reason: "CLAW-603 native-only rollback",
confirm: "deactivate-skills-sh-public-test",
}),
).resolves.toMatchObject({
ok: true,
enabled: false,
nativeTrending: {
status: "ready",
sourceCounts: { clawhubTrending: 1, clawhubRising: 1, skillsShTrending: 0 },
},
scansPlanned: 0,
scansAdmitted: 0,
});
await expect(
t.query(internal.canonicalTrending.getPageInternal, { cursor: null, limit: 20 }),
).resolves.toMatchObject({
status: "ok",
page: { items: [{ source: "clawhub" }] },
});
});
it("reclaims an abandoned activation lock after its bounded lease", async () => {
@@ -465,6 +583,39 @@ describe("skills.sh mirror visibility operations", () => {
});
});
it("prepares native-only publication without enabling a missing mirror control", async () => {
const t = convexTest(schema, modules);
await t.mutation(internal.skillsShMirrorVisibility.beginNativeTrendingInternal, {
actor: "codex-test",
reason: "prepare native-only Trending",
confirm: "deactivate-skills-sh-public-test",
lockToken: "native-only-lock",
});
await expect(
t.run(async (ctx) =>
ctx.db
.query("skillsShMirrorControls")
.withIndex("by_key", (q) => q.eq("key", "global"))
.unique(),
),
).resolves.toMatchObject({
enabled: false,
paused: true,
maxRowsPerRun: 0,
maxRowsPerBatch: 0,
maxDetailBytes: 0,
activationLockToken: "native-only-lock",
});
await expect(
t.mutation(internal.skillsShMirrorVisibility.beginActivationInternal, {
actor: "codex-test",
reason: "must wait for native-only snapshot",
confirm: "activate-skills-sh-public-test",
lockToken: "activation-lock",
}),
).rejects.toThrow("skills.sh mirror control is not active");
});
it("rejects a completed Trending run older than the selected leaderboard import", async () => {
const t = convexTest(schema, modules);
await t.run(async (ctx) => {
@@ -533,11 +684,11 @@ describe("skills.sh mirror visibility operations", () => {
};
});
await t.mutation(internal.skillsShMirrorVisibility.setPublicGateInternal, {
enabled: false,
await t.mutation(internal.skillsShMirrorVisibility.beginDeactivationInternal, {
actor: "codex-test",
reason: "systemic rollback",
confirm: "deactivate-skills-sh-public-test",
lockToken: "native-rollback-lock",
});
const control = await t.run(async (ctx) =>
ctx.db
@@ -545,8 +696,8 @@ describe("skills.sh mirror visibility operations", () => {
.withIndex("by_key", (q) => q.eq("key", "global"))
.unique(),
);
expect(control?.activationLockToken).toBeUndefined();
expect(control?.activationLockedAt).toBeUndefined();
expect(control?.activationLockToken).toBe("native-rollback-lock");
expect(control?.activationLockedAt).toEqual(expect.any(Number));
expect(control?.activationLeaderboardRunId).toBeUndefined();
expect(control?.activationTrendingRunId).toBeUndefined();
await expect(
+222
View File
@@ -21,8 +21,11 @@ const internalRefs = internal as unknown as {
canonicalTrending: { materializeInternal: unknown };
skillsShMirrorVisibility: {
beginActivationInternal: unknown;
beginDeactivationInternal: unknown;
beginNativeTrendingInternal: unknown;
finalizeActivationInternal: unknown;
releaseActivationInternal: unknown;
setPublicGateInternal: unknown;
};
};
@@ -298,6 +301,26 @@ function publicGateValue(args: { enabled: boolean; actor: string; reason: string
};
}
function disabledMirrorControl(args: {
actor: string;
reason: string;
now: number;
lockToken: string;
}) {
return {
enabled: false,
paused: true,
maxRowsPerRun: 0,
maxRowsPerBatch: 0,
maxDetailBytes: 0,
activationLockToken: args.lockToken,
activationLockedAt: args.now,
updatedBy: args.actor,
reason: args.reason,
updatedAt: args.now,
};
}
async function writePublicGate(
ctx: Pick<MutationCtx, "db">,
args: { enabled: boolean; actor: string; reason: string; now: number },
@@ -365,6 +388,205 @@ export const setPublicGateInternal = internalMutation({
},
});
export const beginDeactivationInternal = internalMutation({
args: {
actor: v.string(),
reason: v.string(),
confirm: v.string(),
lockToken: v.string(),
},
handler: async (ctx, args) => {
const environment = assertSkillsShPublicVisibilityMutationAllowed({
activate: false,
confirm: args.confirm,
});
const actor = args.actor.trim();
const reason = args.reason.trim();
const lockToken = args.lockToken.trim();
if (!actor || !reason || !lockToken) {
throw new Error("skills.sh deactivation actor, reason, and lock token are required");
}
const now = Date.now();
const mirrorControl = await ctx.db
.query("skillsShMirrorControls")
.withIndex("by_key", (q) => q.eq("key", CONTROL_KEY))
.unique();
await writePublicGate(ctx, { enabled: false, actor, reason, now });
if (mirrorControl) {
await ctx.db.patch(mirrorControl._id, {
activationLockToken: lockToken,
activationLockedAt: now,
activationLeaderboardRunId: undefined,
activationTrendingRunId: undefined,
updatedBy: actor,
reason,
updatedAt: now,
});
} else {
await ctx.db.insert("skillsShMirrorControls", {
key: CONTROL_KEY,
...disabledMirrorControl({ actor, reason, now, lockToken }),
});
}
return {
ok: true as const,
environment,
enabled: false as const,
updatedAt: now,
scansPlanned: 0 as const,
scansAdmitted: 0 as const,
};
},
});
export const beginNativeTrendingInternal = internalMutation({
args: {
actor: v.string(),
reason: v.string(),
confirm: v.string(),
lockToken: v.string(),
},
handler: async (ctx, args) => {
const environment = assertSkillsShPublicVisibilityMutationAllowed({
activate: false,
confirm: args.confirm,
});
const actor = args.actor.trim();
const reason = args.reason.trim();
const lockToken = args.lockToken.trim();
if (!actor || !reason || !lockToken) {
throw new Error("skills.sh native Trending actor, reason, and lock token are required");
}
const now = Date.now();
const [catalogControl, mirrorControl] = await Promise.all([
ctx.db
.query("skillsShCatalogControls")
.withIndex("by_key", (q) => q.eq("key", CONTROL_KEY))
.unique(),
ctx.db
.query("skillsShMirrorControls")
.withIndex("by_key", (q) => q.eq("key", CONTROL_KEY))
.unique(),
]);
if (catalogControl?.mirrorPublicVisibilityEnabled === true) {
throw new Error("skills.sh native Trending preflight requires a closed public gate");
}
if (
mirrorControl?.activationLockToken &&
mirrorControl.activationLockToken !== lockToken &&
mirrorControl.activationLockedAt !== undefined &&
mirrorControl.activationLockedAt > now - ACTIVATION_LOCK_LEASE_MS
) {
throw new Error("another skills.sh public activation is in progress");
}
if (mirrorControl) {
await ctx.db.patch(mirrorControl._id, {
activationLockToken: lockToken,
activationLockedAt: now,
activationLeaderboardRunId: undefined,
activationTrendingRunId: undefined,
updatedBy: actor,
reason,
updatedAt: now,
});
} else {
await ctx.db.insert("skillsShMirrorControls", {
key: CONTROL_KEY,
...disabledMirrorControl({ actor, reason, now, lockToken }),
});
}
return { environment, lockToken };
},
});
async function materializeNativeTrending(ctx: Pick<ActionCtx, "runAction">, lockToken: string) {
const nativeTrending = (await ctx.runAction(
internalRefs.canonicalTrending.materializeInternal as never,
{ activationLockToken: lockToken, skillsShMode: "native-only" } as never,
)) as {
status: "ready" | "unavailable";
snapshotId?: string;
sourceCounts?: { clawhubTrending: number; clawhubRising: number; skillsShTrending: number };
};
if (nativeTrending.status !== "ready" || nativeTrending.sourceCounts?.skillsShTrending !== 0) {
throw new Error("native-only canonical Trending did not become ready");
}
return nativeTrending;
}
async function materializeNativeTrendingWithLock(
ctx: Pick<ActionCtx, "runAction" | "runMutation">,
args: { actor: string; reason: string; confirm: string },
) {
const lockToken = `skills-sh-native-trending:${crypto.randomUUID()}`;
const locked = (await ctx.runMutation(
internalRefs.skillsShMirrorVisibility.beginNativeTrendingInternal as never,
{ ...args, lockToken } as never,
)) as { environment: "test" | "production" };
try {
return {
environment: locked.environment,
nativeTrending: await materializeNativeTrending(ctx, lockToken),
};
} finally {
await ctx.runMutation(
internalRefs.skillsShMirrorVisibility.releaseActivationInternal as never,
{ lockToken } as never,
);
}
}
export const prepareNativeTrendingInternal = internalAction({
args: {
actor: v.string(),
reason: v.string(),
confirm: v.string(),
},
handler: async (ctx, args) => {
const { environment, nativeTrending } = await materializeNativeTrendingWithLock(ctx, args);
return {
ok: true as const,
environment,
nativeTrending,
scansPlanned: 0 as const,
scansAdmitted: 0 as const,
};
},
});
export const deactivateAndMaterializeInternal = internalAction({
args: {
actor: v.string(),
reason: v.string(),
confirm: v.string(),
},
handler: async (ctx, args) => {
const lockToken = `skills-sh-native-trending:${crypto.randomUUID()}`;
// Close the gate and replace any activation lock atomically so an
// in-flight or newly starting activation cannot reopen the lane.
const deactivation = (await ctx.runMutation(
internalRefs.skillsShMirrorVisibility.beginDeactivationInternal as never,
{ ...args, lockToken } as never,
)) as {
ok: true;
environment: "test" | "production";
enabled: false;
updatedAt: number;
scansPlanned: 0;
scansAdmitted: 0;
};
try {
const nativeTrending = await materializeNativeTrending(ctx, lockToken);
return { ...deactivation, nativeTrending };
} finally {
await ctx.runMutation(
internalRefs.skillsShMirrorVisibility.releaseActivationInternal as never,
{ lockToken } as never,
);
}
},
});
export const beginActivationInternal = internalMutation({
args: {
actor: v.string(),
+54 -8
View File
@@ -45,6 +45,17 @@ function completedRun(sourceView: "leaderboard" | "trending", scansPlanned = 0)
};
}
function nativeTrendingPreparation() {
return response({
ok: true,
nativeTrending: {
status: "ready",
snapshotId: "skills-native-before-import",
sourceCounts: { clawhubTrending: 1, clawhubRising: 1, skillsShTrending: 0 },
},
});
}
describe("skills.sh synchronization runner", () => {
it("refreshes GitHub OIDC authorization before the cached token expires", async () => {
let now = 1_000_000;
@@ -80,7 +91,9 @@ describe("skills.sh synchronization runner", () => {
operations.push(String(body.operation));
switch (body.operation) {
case "status":
return response({ runs: [] });
return response({ runs: [], invariants: { publicVisible: false } });
case "prepare-native-trending":
return nativeTrendingPreparation();
case "configure":
return response({ ok: true, enabled: body.enabled });
case "start":
@@ -121,6 +134,12 @@ describe("skills.sh synchronization runner", () => {
}),
).resolves.toMatchObject({
ok: true,
nativeBefore: {
nativeTrending: {
status: "ready",
sourceCounts: { skillsShTrending: 0 },
},
},
leaderboard: { status: "completed" },
trending: { status: "completed" },
activation: { activated: true },
@@ -130,6 +149,7 @@ describe("skills.sh synchronization runner", () => {
expect(operations).toEqual([
"status",
"configure",
"prepare-native-trending",
"start",
"step",
"start-trending",
@@ -163,8 +183,11 @@ describe("skills.sh synchronization runner", () => {
startedAt: 1,
},
],
invariants: { publicVisible: false },
})
: response({ runs: [] });
: response({ runs: [], invariants: { publicVisible: true } });
case "prepare-native-trending":
return nativeTrendingPreparation();
case "configure":
return response({ ok: true, enabled: body.enabled });
case "step":
@@ -193,6 +216,7 @@ describe("skills.sh synchronization runner", () => {
expect(operations).toEqual([
"status",
"configure",
"prepare-native-trending",
"step",
"start-trending",
"verify-activate",
@@ -224,7 +248,9 @@ describe("skills.sh synchronization runner", () => {
);
switch (body.operation) {
case "status":
return response({ runs: [] });
return response({ runs: [], invariants: { publicVisible: false } });
case "prepare-native-trending":
return nativeTrendingPreparation();
case "configure":
return response({ ok: true, enabled: body.enabled });
case "start":
@@ -273,6 +299,7 @@ describe("skills.sh synchronization runner", () => {
expect(requests).toEqual([
"status",
"configure",
"prepare-native-trending",
"start",
"step:9:50",
"step:9:50",
@@ -303,7 +330,9 @@ describe("skills.sh synchronization runner", () => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
switch (body.operation) {
case "status":
return response({ runs: [] });
return response({ runs: [], invariants: { publicVisible: false } });
case "prepare-native-trending":
return nativeTrendingPreparation();
case "configure":
return response({ ok: true, enabled: body.enabled });
case "start":
@@ -346,7 +375,10 @@ describe("skills.sh synchronization runner", () => {
const fetchImpl = vi.fn(async (_url: string, init: RequestInit) => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
operations.push(String(body.operation));
if (body.operation === "status") return response({ runs: [] });
if (body.operation === "status") {
return response({ runs: [], invariants: { publicVisible: false } });
}
if (body.operation === "prepare-native-trending") return nativeTrendingPreparation();
if (body.operation === "configure") return response({ ok: true });
if (body.operation === "start") {
return response({
@@ -371,7 +403,15 @@ describe("skills.sh synchronization runner", () => {
fetchImpl,
}),
).rejects.toThrow("scheduled a ClawHub scan");
expect(operations).toEqual(["status", "configure", "start", "step", "deactivate", "configure"]);
expect(operations).toEqual([
"status",
"configure",
"prepare-native-trending",
"start",
"step",
"deactivate",
"configure",
]);
});
it("closes the skills.sh lane when server-side activation verification fails", async () => {
@@ -379,7 +419,10 @@ describe("skills.sh synchronization runner", () => {
const fetchImpl = vi.fn(async (_url: string, init: RequestInit) => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
operations.push(String(body.operation));
if (body.operation === "status") return response({ runs: [] });
if (body.operation === "status") {
return response({ runs: [], invariants: { publicVisible: false } });
}
if (body.operation === "prepare-native-trending") return nativeTrendingPreparation();
if (body.operation === "configure") return response({ ok: true });
if (body.operation === "start") return response(completedRun("leaderboard"));
if (body.operation === "start-trending") return response(completedRun("trending"));
@@ -401,6 +444,7 @@ describe("skills.sh synchronization runner", () => {
expect(operations).toEqual([
"status",
"configure",
"prepare-native-trending",
"start",
"start-trending",
"verify-activate",
@@ -414,7 +458,9 @@ describe("skills.sh synchronization runner", () => {
const fetchImpl = vi.fn(async (_url: string, init: RequestInit) => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
operations.push(String(body.operation));
if (body.operation === "status") return response({ runs: [] });
if (body.operation === "status") {
return response({ runs: [], invariants: { publicVisible: true } });
}
if (body.operation === "configure") return response({ ok: true });
if (body.operation === "start") return response({ error: "upstream unavailable" }, 503);
throw new Error(`unexpected operation ${String(body.operation)}`);
+19
View File
@@ -266,11 +266,29 @@ export async function runSkillsShSync(options: {
const startedAt = Date.now();
const before = await call({ operation: "status" });
const publicVisible = (before.invariants as Record<string, unknown> | undefined)?.publicVisible;
if (typeof publicVisible !== "boolean") {
throw new Error("skills.sh mirror status is missing the public visibility invariant");
}
const recoverable = findRecoverableMirrorRun(before) as
| (MirrorRun & { sourceView?: "leaderboard" | "trending" })
| null;
let nativeBefore: Record<string, unknown> | null = null;
await call({ operation: "configure", enabled: true, reason: options.reason });
try {
nativeBefore = publicVisible
? null
: await call({
operation: "prepare-native-trending",
reason: `${options.reason} native-only preflight`,
});
if (nativeBefore) {
const nativeTrending = nativeBefore.nativeTrending as Record<string, unknown> | undefined;
const sourceCounts = nativeTrending?.sourceCounts as Record<string, unknown> | undefined;
if (nativeTrending?.status !== "ready" || sourceCounts?.skillsShTrending !== 0) {
throw new Error("native-only canonical Trending preflight did not become ready");
}
}
const recoveredSourceView = recoverable?.sourceView ?? "leaderboard";
const recovered = recoverable ? await completeRun(recoverable, recoveredSourceView) : null;
const leaderboard =
@@ -298,6 +316,7 @@ export async function runSkillsShSync(options: {
completedAt: new Date().toISOString(),
durationMs: Date.now() - startedAt,
before,
...(nativeBefore ? { nativeBefore } : {}),
...(recovered ? { recovered } : {}),
leaderboard,
trending,
@@ -49,6 +49,7 @@ type MirrorRequest = {
operation?:
| "configure"
| "verify-activate"
| "prepare-native-trending"
| "deactivate"
| "start"
| "start-trending"
@@ -295,11 +296,19 @@ export function createSkillsShMirrorRoute(target: keyof typeof ROUTE_CONFIG) {
}),
);
}
if (operation === "prepare-native-trending") {
return jsonResponse(
await callConvexOperator(authorization, {
operation: "mirror-prepare-native-trending",
reason: requireString(body.reason, "reason"),
confirm: config.deactivateConfirm,
}),
);
}
if (operation === "deactivate") {
return jsonResponse(
await callConvexOperator(authorization, {
operation: "mirror-public-gate",
enabled: false,
operation: "mirror-deactivate-native-trending",
reason: requireString(body.reason, "reason"),
confirm: config.deactivateConfirm,
}),
+12 -2
View File
@@ -197,6 +197,12 @@ describe("skills.sh production mirror route", () => {
vi.stubGlobal("fetch", convexFetch);
const handler = (await import("./routes/ops/skills-sh/mirror.post")).default;
readBodyMock.mockResolvedValueOnce({
operation: "prepare-native-trending",
reason: "native-only production preflight",
});
expect(((await handler({} as never)) as Response).status).toBe(200);
readBodyMock.mockResolvedValueOnce({
operation: "verify-activate",
reason: "verified initial production import",
@@ -210,14 +216,18 @@ describe("skills.sh production mirror route", () => {
expect(((await handler({} as never)) as Response).status).toBe(200);
expect(forwarded).toEqual([
{
operation: "mirror-prepare-native-trending",
reason: "native-only production preflight",
confirm: "deactivate-skills-sh-public-production",
},
{
operation: "mirror-verify-activate",
reason: "verified initial production import",
confirm: "activate-skills-sh-public-production",
},
{
operation: "mirror-public-gate",
enabled: false,
operation: "mirror-deactivate-native-trending",
reason: "systemic production rollback",
confirm: "deactivate-skills-sh-public-production",
},