Files
tech-log-frontend/scripts/test-sample-removal.ts
T
DongHyeonkaandClaude Opus 5 bdee07a93b chore: sync the frontend template from a0fbafb to 5434760
Carries eight template commits: the provider sandbox actually running, release
admission to a named environment, the product feature manifest with its runtime
kill switch, architecture and documentation rules that match what is enforced,
the removability fixtures, and the browser, visual and performance evidence.

Product identity is unchanged. `package.json` keeps `tech-log-frontend` and the
catalog keeps the Tech Log naming; the home page was not in the delta. The
visual baselines are this product's own — the template's were excluded from the
transplant and these were regenerated here, where the only difference is the
platform overview's new product-feature section.

What this repository gains operationally: `config/runtime/{local,development,
staging,production}.json` with `FE-GATE-027` refusing an artifact whose runtime
document does not match the environment it is being admitted to, and
`FEATURE_OVERRIDES` for taking an installed feature out of service without a
rebuild.

Verified here: eight gates green, build green, visual 5/5, and 1,858 of 1,859
tests in the suites that do not need a sandbox — the one failure passes in
isolation and is a jsdom lazy-chunk timeout under parallel load. The provider
suites cannot run on this machine at all: `kernel.apparmor_restrict_unprivileged
_userns=1` makes `bwrap --unshare-net` fail, reproducible without any code from
either repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 21:34:19 +09:00

424 lines
14 KiB
TypeScript

import {
access,
mkdir,
mkdtemp,
readFile,
rm,
writeFile,
} from "node:fs/promises";
import path from "node:path";
import { isProductionModulePath } from "./lib/risk-coverage.ts";
import {
filesBelow,
prepareRemovalFixture,
pruneRemovalFixtureCiContract,
pruneScriptOrchestration,
regenerateRemovalFixtureWorkflow,
requireRemovalFixtureEnvironment,
runRemovalFixturePnpm,
} from "./lib/removal-fixture.ts";
const fixtureParent = path.resolve(".tmp");
await mkdir(fixtureParent, { recursive: true });
const fixtureRoot = await mkdtemp(
path.join(fixtureParent, "reference-feature-removal-"),
);
const pnpmCli = requireRemovalFixtureEnvironment("npm_execpath");
const featureSource = "src/features/reference-feature";
const featureTests = "tests/features/reference-feature";
/**
* Platform tests that must survive the sample feature's removal. Asserting they
* are still present is what stops the removal fixture from "passing" by having
* quietly deleted the platform's own coverage along with the feature.
*/
const commonTestPaths = [
"tests/unit/external-contract-runtime.test.ts",
"tests/unit/http-execution-v3.test.ts",
"tests/unit/runtime-adapters.test.ts",
"tests/integration/http-execution-v3-observability.test.ts",
];
const featureOwnedPaths = [
featureSource,
featureTests,
"tests/integration/http-scenario-catalog.test.ts",
"tests/e2e/reference-form.spec.ts",
"tests/e2e/reference-route.spec.ts",
"tests/mocks",
"tests/fixtures/typecheck/invalid-feature-input.ts",
"tests/fixtures/typecheck/invalid-reference-operation.ts",
];
const emptyContracts = `import { PLATFORM_ROUTE_RUNTIME_CONTRACT } from "../contracts/route-runtime-contract.ts";
import { PLATFORM_ROUTE_REGISTRY, type RouteDefinition } from "../contracts/routes.ts";
import { PLATFORM_SCHEMA_REGISTRY } from "../contracts/schema-registry.ts";
export const INSTALLED_FEATURE_CONTRACTS: readonly unknown[] = Object.freeze([]);
export const ROUTE_REGISTRY = PLATFORM_ROUTE_REGISTRY;
export const ROUTE_RUNTIME_CONTRACT = PLATFORM_ROUTE_RUNTIME_CONTRACT;
export const API_OPERATIONS = Object.freeze({});
export const INVALIDATION_REGISTRY = Object.freeze({
topics: Object.freeze([]),
namespaces: Object.freeze([]),
edges: Object.freeze([]),
});
export const INVALIDATION_TOPIC_VERSIONS = Object.freeze([]);
export const SCHEMA_REGISTRY = PLATFORM_SCHEMA_REGISTRY;
export const NAVIGATION_ROUTES = Object.freeze(
Object.values(ROUTE_REGISTRY)
.filter((definition) => definition.navigationOrder !== null)
.sort(
(left, right) =>
left.navigationOrder! - right.navigationOrder!,
),
);
export function getRoute(routeId: string): RouteDefinition {
const registry = ROUTE_REGISTRY as Readonly<Record<string, RouteDefinition>>;
const selected = registry[routeId];
if (!selected) throw new Error(\`Unregistered route: \${routeId}\`);
return selected;
}
export function routePath(routeId: string): string {
return getRoute(routeId).path;
}
`;
const emptyRuntimes = `import { PLATFORM_ROUTE_CODECS } from "../presentation/routes/platform-route-codecs.ts";
import { PLATFORM_ROUTE_RUNTIME } from "../presentation/routes/route-runtime.tsx";
export const ROUTE_CODECS = PLATFORM_ROUTE_CODECS;
export const ROUTE_RUNTIME = PLATFORM_ROUTE_RUNTIME;
`;
const emptyAdapters = `export function createInstalledFeatureInputs(_context: unknown) {
void _context;
return Object.freeze({});
}
`;
const emptyContractContributions = `import {
composeContractContributions,
type InstalledContractContribution,
type InstalledContractPackageIdentity,
} from "../contracts/external-contract-runtime.ts";
export const INSTALLED_CONTRACT_CONTRIBUTIONS: readonly InstalledContractContribution[] =
Object.freeze([]);
export const COMPOSED_CONTRACT_CONTRIBUTIONS = composeContractContributions(
INSTALLED_CONTRACT_CONTRIBUTIONS,
);
export const EXPECTED_CONTRACT_SET_PACKAGES: readonly InstalledContractPackageIdentity[] =
COMPOSED_CONTRACT_CONTRIBUTIONS.externalPackages;
`;
const emptyMessages = `export const INSTALLED_MESSAGE_CATALOGS = Object.freeze({
"ko-KR": Object.freeze({}),
"en-US": Object.freeze({}),
});
`;
type CoveragePolicy = {
repositoryBaseline: number;
generatedPaths: string[];
criticalModules: Array<{
path?: string;
minimum?: Record<string, number>;
}>;
highRiskPaths: string[];
waivers: Array<{ path?: string }>;
};
type EvidenceContribution = Readonly<{ owner?: string }>;
type EvidencePolicy = Record<
"scenarioCatalogs" | "sourceContracts",
unknown
>;
type GovernanceConsumer = Readonly<{ path?: string }>;
type GovernanceRegistry = Record<string, unknown> & {
consumers?: unknown;
consumerDirectories?: unknown;
};
type RemovalGovernance = { registries: GovernanceRegistry[] };
function runPnpm(script: string, extra: string[] = []): boolean {
return runRemovalFixturePnpm(fixtureRoot, pnpmCli, script, extra);
}
try {
await prepareRemovalFixture(fixtureRoot);
for (const excludedFixtureTest of [
"tests/unit/ci-workflow-generation.test.ts",
"tests/unit/__snapshots__/ci-workflow-generation.test.ts.snap",
"tests/unit/removal-fixture.test.ts",
"tests/unit/http-scenario-evidence.test.ts",
]) {
await rm(path.join(fixtureRoot, excludedFixtureTest), { force: true });
}
const coveragePolicyFile = path.join(
fixtureRoot,
"config/testing/risk-coverage.json",
);
const coveragePolicy = JSON.parse(
await readFile(coveragePolicyFile, "utf8"),
) as CoveragePolicy;
const generatedProductionModules = new Set(coveragePolicy.generatedPaths);
const removedProductionModuleCount = (
await filesBelow(path.join(fixtureRoot, featureSource))
)
.map((file) => path.relative(fixtureRoot, file).split(path.sep).join("/"))
.filter(
(file) =>
isProductionModulePath(file) && !generatedProductionModules.has(file),
).length;
for (const ownedPath of featureOwnedPaths) {
await rm(path.join(fixtureRoot, ownedPath), {
recursive: true,
force: true,
});
}
await writeFile(
path.join(fixtureRoot, "src/features/installed-feature-contracts.ts"),
emptyContracts,
);
await writeFile(
path.join(fixtureRoot, "src/features/installed-feature-runtimes.tsx"),
emptyRuntimes,
);
await writeFile(
path.join(fixtureRoot, "src/features/installed-feature-adapters.ts"),
emptyAdapters,
);
await writeFile(
path.join(fixtureRoot, "src/features/installed-feature-messages.ts"),
emptyMessages,
);
await writeFile(
path.join(fixtureRoot, "src/features/installed-contract-contributions.ts"),
emptyContractContributions,
);
const retainedCriticalModules = coveragePolicy.criticalModules.filter(
(modulePolicy) => !modulePolicy.path?.startsWith(`${featureSource}/`),
);
if (
retainedCriticalModules.length === coveragePolicy.criticalModules.length
) {
throw new Error("Reference feature coverage policy is not registered");
}
coveragePolicy.criticalModules = retainedCriticalModules;
coveragePolicy.highRiskPaths = coveragePolicy.highRiskPaths.filter(
(modulePath) => !modulePath.startsWith(`${featureSource}/`),
);
coveragePolicy.waivers = coveragePolicy.waivers.filter(
(waiver) => !waiver.path?.startsWith(`${featureSource}/`),
);
coveragePolicy.generatedPaths = coveragePolicy.generatedPaths.filter(
(modulePath) => !modulePath.startsWith(`${featureSource}/`),
);
coveragePolicy.repositoryBaseline -= removedProductionModuleCount;
if (coveragePolicy.repositoryBaseline <= 0) {
throw new Error("Reference feature removal produced an invalid coverage baseline");
}
await writeFile(
coveragePolicyFile,
`${JSON.stringify(coveragePolicy, null, 2)}\n`,
);
const evidencePolicyFile = path.join(
fixtureRoot,
"config/testing/test-evidence.json",
);
const evidencePolicy = JSON.parse(
await readFile(evidencePolicyFile, "utf8"),
) as EvidencePolicy;
let removedEvidenceContributions = 0;
for (const policyKey of ["scenarioCatalogs", "sourceContracts"] as const) {
const contributions = evidencePolicy[policyKey];
if (!Array.isArray(contributions)) {
throw new Error(`Test evidence policy is missing ${policyKey}`);
}
evidencePolicy[policyKey] = contributions.filter((candidate: unknown) => {
const contribution = candidate as EvidenceContribution;
const retained = contribution.owner !== "reference-feature";
if (!retained) removedEvidenceContributions += 1;
return retained;
});
}
if (removedEvidenceContributions === 0) {
throw new Error("Reference feature test evidence policy is not registered");
}
await writeFile(
evidencePolicyFile,
`${JSON.stringify(evidencePolicy, null, 2)}\n`,
);
const governanceFile = path.join(
fixtureRoot,
"config/contracts/registry-governance.json",
);
const removalGovernance = JSON.parse(
await readFile(governanceFile, "utf8"),
) as RemovalGovernance;
removalGovernance.registries = removalGovernance.registries.map(
(registry) => ({
...registry,
...(Array.isArray(registry.consumers)
? {
consumers: registry.consumers.filter(
(candidate: unknown) => {
const consumer = candidate as GovernanceConsumer;
return !consumer.path?.includes("features/reference-feature");
},
),
}
: {}),
...(Array.isArray(registry.consumerDirectories)
? {
consumerDirectories: registry.consumerDirectories.filter(
(directory: unknown) =>
typeof directory !== "string" ||
!directory.includes("features/reference-feature"),
),
}
: {}),
}),
);
await writeFile(
governanceFile,
`${JSON.stringify(removalGovernance, null, 2)}\n`,
);
const removedCiScripts = new Set([
"check:types:fixture:feature-input",
"check:types:fixture:reference-operation",
"test:http-scenario-evidence",
"test:reference-feature",
]);
const fixturePackagePath = path.join(fixtureRoot, "package.json");
const fixturePackage = JSON.parse(await readFile(fixturePackagePath, "utf8")) as {
scripts: Record<string, string>;
};
pruneScriptOrchestration(fixturePackage.scripts, "test:all", removedCiScripts);
fixturePackage.scripts["test:coverage"] = fixturePackage.scripts["test:coverage"]
.replace(" tests/features/reference-feature", "");
delete fixturePackage.scripts["check:http-scenario-evidence"];
delete fixturePackage.scripts["check:http-scenario-evidence:fixture"];
await writeFile(fixturePackagePath, `${JSON.stringify(fixturePackage, null, 2)}\n`);
await pruneRemovalFixtureCiContract({
root: fixtureRoot,
removedScripts: removedCiScripts,
removedEvidencePathFragments: [
"reference-feature.xml",
"http-scenario-executions",
"http-scenario-evidence",
],
});
await regenerateRemovalFixtureWorkflow(fixtureRoot);
const residue: string[] = [];
for (const root of ["src", "tests"]) {
for (const file of await filesBelow(path.join(fixtureRoot, root))) {
const relative = path.relative(fixtureRoot, file);
const content = await readFile(file, "utf8");
if (
/REFERENCE_RESOURCE|reference-feature|reference-resource/i.test(
`${relative}\n${content}`,
)
) {
residue.push(relative);
}
}
}
const checks: Array<[string, boolean]> = [
[
"common-test-evidence",
(
await Promise.all(
commonTestPaths.map(async (testPath) => {
try {
await access(path.join(fixtureRoot, testPath));
return true;
} catch {
return false;
}
}),
)
).every(Boolean),
],
["typecheck", runPnpm("check:types")],
["architecture", runPnpm("check:architecture")],
["registry-structure", runPnpm("check:registries:structure")],
["unit-integration", runPnpm("test:all")],
["coverage", runPnpm("test:coverage")],
["test-evidence-source", runPnpm("check:test-evidence:source")],
["ci-contract", runPnpm("check:ci")],
[
"home-smoke",
runPnpm("exec", [
"vitest",
"run",
"tests/component/router.test.tsx",
"--reporter=default",
]),
],
["build", runPnpm("build")],
];
const builtResidue: string[] = [];
for (const file of await filesBelow(path.join(fixtureRoot, "dist"))) {
if (!/\.(?:js|css|html|json)$/.test(file)) continue;
const content = await readFile(file, "utf8");
if (
/REFERENCE_RESOURCE|reference-feature|reference-resource/i.test(content)
) {
builtResidue.push(path.relative(fixtureRoot, file));
}
}
const routeCatalog = await import(
`${new URL(
"../src/features/installed-feature-contracts.ts",
`file://${fixtureRoot}/scripts/`,
).href}?removed=${Date.now()}`
) as { ROUTE_REGISTRY: Readonly<Record<string, unknown>> };
const routeIds = Object.keys(routeCatalog.ROUTE_REGISTRY);
const routeAbsent = routeIds.every((routeId) => !routeId.startsWith("REFERENCE_"));
checks.push(["route-absent", routeAbsent]);
checks.push(["fixture-id-residue", residue.length === 0]);
checks.push(["built-fixture-id-residue", builtResidue.length === 0]);
const passed = checks.every(([, result]) => result);
await mkdir("artifacts/tests", { recursive: true });
await writeFile(
"artifacts/tests/sample-removal.xml",
`<?xml version="1.0" encoding="UTF-8"?>\n` +
`<testsuite name="reference-feature-removal" tests="${checks.length}" failures="${passed ? 0 : 1}">` +
checks
.map(
([name, result]) =>
`<testcase name="${name}">${result ? "" : `<failure>${[...residue, ...builtResidue].join(", ")}</failure>`}</testcase>`,
)
.join("") +
`</testsuite>\n`,
);
if (!passed) {
const failures = checks
.filter(([, result]) => !result)
.map(([name]) => name);
process.stderr.write(
`Reference feature removal failed: ${failures.join(", ")}; residue: ${[...residue, ...builtResidue].join(", ")}\n`,
);
process.exitCode = 1;
} else {
process.stdout.write(
`Reference feature removal: PASS (${checks.length} checks, no fixture IDs)\n`,
);
}
} finally {
await rm(fixtureRoot, { recursive: true, force: true });
}