feat(FN-3189): add explicit slow-lane CI gating and inline priority picker

Merges FN-3183/FN-3186 (priority picker in quick-entry box) and FN-3189 (CLI slow-lane test gating and CI lane) into the codebase. The quick-entry box gains inline priority selection, while the test suite introduces explicit slow/pre-release lane classification and a corresponding CI gate in the wor

Fusion-Task-Id: FN-3189
This commit is contained in:
Fusion
2026-05-02 03:44:51 -07:00
committed by gsxdsm
parent 19142cfc98
commit e3f2cab798
8 changed files with 102 additions and 18 deletions

View File

@@ -41,7 +41,9 @@ function nativeTarget(): string | null {
// Cross-compiling native binaries pegs CPU for ~60s per target. Skip by
// default locally; opt in with FUSION_TEST_BUILD_EXE=1 or run on CI.
const SHOULD_RUN_BUILD_EXE =
Boolean(process.env.FUSION_TEST_BUILD_EXE) || Boolean(process.env.CI);
process.env.FUSION_TEST_BUILD_EXE === "1" ||
process.env.FUSION_TEST_BUILD_EXE === "true" ||
Boolean(process.env.CI);
describe.skipIf(!SHOULD_RUN_BUILD_EXE)("build-exe-cross: single target", () => {
beforeAll(() => {

View File

@@ -24,6 +24,10 @@ describe("CI workflow (.github/workflows/ci.yml)", () => {
let content: string;
let ciSteps: any[];
let contributingContent: string;
let cliPackageJsonContent: string;
let extensionSuiteContent: string;
let agentExportSuiteContent: string;
let buildExeSuiteContent: string;
beforeAll(() => {
const result = loadWorkflow("ci.yml");
@@ -31,10 +35,26 @@ describe("CI workflow (.github/workflows/ci.yml)", () => {
content = result.content;
ciSteps = workflow.jobs?.ci?.steps ?? [];
contributingContent = readFileSync(join(workspaceRoot, "docs", "contributing.md"), "utf-8");
cliPackageJsonContent = readFileSync(join(workspaceRoot, "packages", "cli", "package.json"), "utf-8");
extensionSuiteContent = readFileSync(
join(workspaceRoot, "packages", "cli", "src", "__tests__", "extension.test.ts"),
"utf-8",
);
agentExportSuiteContent = readFileSync(
join(workspaceRoot, "packages", "cli", "src", "commands", "__tests__", "agent-export.test.ts"),
"utf-8",
);
buildExeSuiteContent = readFileSync(
join(workspaceRoot, "packages", "cli", "src", "__tests__", "build-exe-cross.test.ts"),
"utf-8",
);
});
const findStepByRun = (runSnippet: string) => ciSteps.find((step) => typeof step.run === "string" && step.run.includes(runSnippet));
const findStepByRunExact = (runCommand: string) =>
ciSteps.find((step) => typeof step.run === "string" && step.run.trim() === runCommand);
const findStepIndexByRun = (runSnippet: string) =>
ciSteps.findIndex((step) => typeof step.run === "string" && step.run.includes(runSnippet));
@@ -63,33 +83,58 @@ describe("CI workflow (.github/workflows/ci.yml)", () => {
expect(verifyStep).toBeDefined();
expect(verifyStep.name).toContain("bootstrap contract");
const directLintStep = findStepByRun("pnpm lint");
const directTestStep = findStepByRun("pnpm test");
const directBuildStep = findStepByRun("pnpm build");
const directLintStep = findStepByRunExact("pnpm lint");
const directTestStep = findStepByRunExact("pnpm test");
const directBuildStep = findStepByRunExact("pnpm build");
expect(directLintStep).toBeUndefined();
expect(directTestStep).toBeUndefined();
expect(directBuildStep).toBeUndefined();
});
it("runs workspace verification before binary packaging", () => {
it("runs workspace verification before slow lane and binary packaging", () => {
const verifyIdx = findStepIndexByRun("pnpm verify:workspace");
const slowLaneIdx = findStepIndexByRun("pnpm test:slow-cli");
const buildExeIdx = findStepIndexByRun("build:exe");
expect(verifyIdx).toBeGreaterThanOrEqual(0);
expect(buildExeIdx).toBeGreaterThan(verifyIdx);
expect(slowLaneIdx).toBeGreaterThan(verifyIdx);
expect(buildExeIdx).toBeGreaterThan(slowLaneIdx);
});
it("keeps contributing docs aligned with the clean-worktree verification contract", () => {
it("keeps contributing docs aligned with verification and slow-lane contracts", () => {
expect(contributingContent).toContain("pnpm test` must be runnable in a clean worktree without requiring a prior `pnpm build`.");
expect(contributingContent).toContain("`pnpm verify:workspace` is the canonical pre-merge gate");
expect(contributingContent).toContain("1. `pnpm lint`");
expect(contributingContent).toContain("2. `pnpm test`");
expect(contributingContent).toContain("3. `pnpm build`");
expect(contributingContent).toContain("pnpm test:slow-cli");
expect(contributingContent).toContain("test:pre-release");
expect(contributingContent).toContain("test:extension-integration");
});
it("includes binary build step", () => {
expect(content).toContain("build:exe");
});
it("keeps explicit gating for audited CLI integration suites", () => {
expect(cliPackageJsonContent).toContain('"test:slow-cli"');
expect(cliPackageJsonContent).toContain("FUSION_TEST_SLOW_CLI=1");
expect(cliPackageJsonContent).toContain('"test:extension-integration"');
expect(cliPackageJsonContent).toContain("FUSION_TEST_EXTENSION_INTEGRATION=1");
expect(cliPackageJsonContent).toContain('"test:build-exe"');
expect(cliPackageJsonContent).toContain("FUSION_TEST_BUILD_EXE=1");
expect(extensionSuiteContent).toContain("describe.skipIf(!SHOULD_RUN_EXTENSION_INTEGRATION)");
expect(extensionSuiteContent).toContain("FUSION_TEST_EXTENSION_INTEGRATION");
expect(agentExportSuiteContent).toContain("describe.skipIf(!SHOULD_RUN_SLOW_CLI)");
expect(agentExportSuiteContent).toContain("FUSION_TEST_SLOW_CLI");
expect(buildExeSuiteContent).toContain('process.env.FUSION_TEST_BUILD_EXE === "1"');
expect(buildExeSuiteContent).toContain('process.env.FUSION_TEST_BUILD_EXE === "true"');
expect(buildExeSuiteContent).not.toContain("Boolean(process.env.FUSION_TEST_BUILD_EXE)");
});
it("includes Bun setup", () => {
expect(content).toContain("oven-sh/setup-bun");
});

View File

@@ -118,12 +118,15 @@ async function removeDirWithRetries(path: string) {
// ── Tests ──────────────────────────────────────────────────────────
// Skipped: 39 tests × ~1-4s each (~62s total) exercise every fn pi tool
// through the real ExtensionAPI + TaskStore/MissionStore stack with
// per-test temp workspaces. Coverage overlaps with command-level tests
// (task.test.ts, mission-related suites). Re-enable for full pre-release
// validation or when adding new extension tools.
describe.skip("fn pi extension", () => {
// Audited in FN-3189: this suite is expensive (~62s) and currently stale
// against modern extension behavior/tooling (see FN-3204). Keep an explicit,
// discoverable gate so it never silently disappears behind unconditional skip,
// but do not include it in the default slow lane until the failures are fixed.
const SHOULD_RUN_EXTENSION_INTEGRATION =
process.env.FUSION_TEST_EXTENSION_INTEGRATION === "1" ||
process.env.FUSION_TEST_EXTENSION_INTEGRATION === "true";
describe.skipIf(!SHOULD_RUN_EXTENSION_INTEGRATION)("fn pi extension", () => {
let tmpDir: string;
let api: ReturnType<typeof createMockAPI>;