Merge master for final native recovery verification

Preserve native publication documentation alongside the merged skill-storage guide and include the independently verified Cloud maintenance fix.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-30 17:47:07 -05:00
commit 92b7447d68
199 files changed
+8837 -3325

No files matched your search

+2 -2
View File
@@ -216,11 +216,11 @@ test("the trusted PR workflow keeps a stable aggregate check named e2e over the
}
});
test("runner selection has reserved AWS capacity and executes metadata checks only", () => {
test("runner authorization uses hosted capacity and executes metadata checks only", () => {
const workflow = readFileSync(routingWorkflow, "utf8");
const jobs = readWorkflowJobs(workflow.split(/^jobs:\n/m)[1]);
assert.deepEqual([...jobs.keys()], ["gate"]);
assert.match(jobs.get("gate"), /^ {4}runs-on: \$\{\{ vars\.AWS_CI_ENABLED[\s\S]*paperclip-ci-routing-x64/m);
assert.match(jobs.get("gate"), /^ {4}runs-on: ubuntu-latest$/m);
assert.doesNotMatch(jobs.get("gate"), /uses:|actions\/checkout|secrets\./);
assert.match(workflow, /^ {6}runner:\n {8}value: \$\{\{ jobs\.gate\.outputs\.runner \}\}$/m);
assert.match(workflow, /^ {6}full_ci:\n {8}value: \$\{\{ jobs\.gate\.outputs\.full_ci \}\}$/m);
+4 -1
View File
@@ -13,8 +13,11 @@ export function selectionEligibility(plan) {
const changed = productInputs(plan.changed);
if (!changed.length) return "Documentation-only diff";
for (const file of changed) {
// Business modules can contain "config"/"setup" in their names. The graph
// separately tracks actual setup and configuration dependencies.
if (!/^(?:ui\/src|server\/src|cli\/src|packages\/.+\/src)\/.+\.[cm]?[jt]sx?$/.test(file)
|| /(?:config|setup)|\.d\.[cm]?ts$/i.test(file) || file.split("/").includes("..")) return `Broad input: ${file}`;
|| /(?:^|\/)(?:vite|vitest)\.(?:config|setup)\.[cm]?[jt]sx?$|\.d\.[cm]?ts$/i.test(file)
|| file.split("/").includes("..")) return `Broad input: ${file}`;
try {
if (!lstatSync(file).isFile()) return `Non-regular source: ${file}`;
} catch { return `Deleted or missing source: ${file}`; }
@@ -4,9 +4,32 @@ import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
import { stripVTControlCharacters } from "node:util";
import { selectProjectTests } from "./vitest-selection-graph.mjs";
import { selectionHash } from "./test-selection-manifest.mjs";
test("selected server tests can launch independent chat runner fixtures", (t) => {
const directory = mkdtempSync(path.join(tmpdir(), "ci-nested-"));
t.after(() => rmSync(directory, { recursive: true, force: true }));
const manifest = { version: 1,
head: execFileSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).trim(),
lanes: { "general-server-without-chat": { shards: [{ "@paperclipai/server": [
"server/src/__tests__/vitest-chat-shards.test.ts",
] }] } },
};
const file = path.join(directory, "selection.json");
writeFileSync(file, JSON.stringify(manifest));
const result = spawnSync(process.execPath, ["scripts/run-vitest-stable.mjs", "--mode", "general",
"--group", "general-server-without-chat", "--shard-index", "0", "--shard-count", "1"], {
encoding: "utf8", timeout: 180_000, maxBuffer: 4 * 1024 * 1024,
env: { ...process.env, CI: "true", PAPERCLIP_CI_PROFILE: "false",
PAPERCLIP_CI_TEST_SELECTION: file, PAPERCLIP_CI_SELECTION_HASH: selectionHash(manifest) },
});
assert.equal(result.error, undefined);
assert.equal(result.status, 0, result.stdout + result.stderr);
assert.match(stripVTControlCharacters(result.stdout), /Test Files\s+1 passed/);
});
test("production runner catches the filesystem regression that raw Vitest selection misses", async (t) => {
const repo = process.cwd();
const root = realpathSync(mkdtempSync(path.join(tmpdir(), "ci-vr-")));
@@ -20,7 +43,7 @@ test("production runner catches the filesystem regression that raw Vitest select
write("vitest.config.mjs", 'export default {test:{projects:["ui"]}}');
write("ui/vitest.config.mjs", 'export default {test:{name:"@paperclipai/ui",include:["src/**/*.test.mjs"]}}');
write("ui/src/leaf.mjs", "export const value = 42;\n");
write("ui/src/import.test.mjs", 'import {test,expect} from "vitest"; import {value} from "./leaf.mjs"; test("value",()=>expect(value).toBe(42));');
write("ui/src/import.test.mjs", 'import {test,expect} from "vitest"; import {value} from "./leaf.mjs"; test("value",()=>{expect(value).toBe(42); expect(process.env.PAPERCLIP_CI_TEST_SELECTION).toBeUndefined(); expect(process.env.PAPERCLIP_CI_SELECTION_HASH).toBeUndefined();});');
write("ui/src/import.test.mjs.test.mjs", 'throw new Error("UNSELECTED_FILE: substring filters must not execute this file");');
write("ui/src/contract.test.mjs", 'import {test,expect} from "vitest"; import {readFileSync} from "node:fs"; test("filesystem contract",()=>expect(readFileSync(new URL("./leaf.mjs",import.meta.url),"utf8")).not.toContain("FORBIDDEN_MARKER"));');
git("init", "-q"); git("add", ".");
@@ -158,6 +158,25 @@ test("forced modes, config, fixtures, deletions and unknown inputs cannot narrow
assert.ok(selectionEligibility({ ...plan, forceReason: "full-ci" }));
});
test("ordinary source names containing config or setup remain graph eligible", (t) => {
const directory = mkdtempSync(path.join(tmpdir(), "ci-names-"));
t.after(() => { process.chdir(root); rmSync(directory, { recursive: true, force: true }); });
process.chdir(directory);
const plan = fixturePlan().plan;
for (const file of [
"server/src/services/heartbeat/session-config-metadata.test.ts",
"server/src/storage/config.ts",
"ui/src/pages/apps/chat/slack/setup-state.test.ts",
]) {
mkdirSync(path.dirname(file), { recursive: true });
writeFileSync(file, "export {};\n");
assert.equal(selectionEligibility({ ...plan, changed: [file] }), null, file);
}
for (const file of ["ui/src/vitest.setup.ts", "server/src/vitest.config.mts"]) {
assert.equal(selectionEligibility({ ...plan, changed: [file] }), `Broad input: ${file}`);
}
});
test("the CLI publishes the complete coarse plan if setup mutates tracked inputs", (t) => {
const directory = realpathSync(mkdtempSync(path.join(tmpdir(), "ci-vd-")));
t.after(() => rmSync(directory, { recursive: true, force: true }));
+4
View File
@@ -400,6 +400,10 @@ async function runVitest(args, label, testShard = null, exactFiles = false) {
PAPERCLIP_INSTANCE_ID: `vt-${process.pid}-${invocationIndex}`,
TMPDIR: path.join(testRoot, "t"),
};
// The wrapper has already validated and consumed this shard's manifest.
// Tests may launch independent runner fixtures with a different root/inventory.
delete env.PAPERCLIP_CI_TEST_SELECTION;
delete env.PAPERCLIP_CI_SELECTION_HASH;
mkdirSync(env.PAPERCLIP_HOME, { recursive: true });
mkdirSync(env.TMPDIR, { recursive: true });
if (testShard) {