补2025产品候选并核对成立年与Trace主体
This commit is contained in:
@@ -187,7 +187,7 @@ async function main() {
|
||||
const research = await researchResponse.json();
|
||||
assert.equal(research.companies.length, 1016);
|
||||
assert.equal(research.categories.length, 11);
|
||||
assert.equal(research.evidence.length, 1101);
|
||||
assert.equal(research.evidence.length, 1124);
|
||||
assert.equal(research.observations.length, 187);
|
||||
assert.equal((await request("/api/research/ai-companies", { method: "POST", headers })).status, 405);
|
||||
const researchPage = await request("/docs/other-research/ai-company-research/overview", { headers });
|
||||
|
||||
@@ -48,8 +48,8 @@ export type ResearchCandidateBatch = {
|
||||
records: {
|
||||
id: string; name: string; url: string | null; categoryId: string;
|
||||
kind: "product" | "promotion"; profileStatus: "readable" | "unavailable" | "archive-only";
|
||||
status: "pending-year" | "linked" | "existing-outside-cohort" | "promotion";
|
||||
companyId?: string; note: string;
|
||||
status: "pending-year" | "linked" | "existing-outside-cohort" | "outside-cohort" | "promotion";
|
||||
companyId?: string; evidenceIds?: string[]; note: string;
|
||||
}[];
|
||||
};
|
||||
export type ResearchSnapshot = {
|
||||
@@ -121,11 +121,13 @@ export function validateResearch(snapshot: ResearchSnapshot) {
|
||||
if (!row.name.trim() || !row.note.trim() || !categories.has(row.categoryId) ||
|
||||
!["product", "promotion"].includes(row.kind) ||
|
||||
!["readable", "unavailable", "archive-only"].includes(row.profileStatus) ||
|
||||
!["pending-year", "linked", "existing-outside-cohort", "promotion"].includes(row.status) ||
|
||||
!["pending-year", "linked", "existing-outside-cohort", "outside-cohort", "promotion"].includes(row.status) ||
|
||||
(row.kind === "product" && (!row.url || !evidenceUrl(row.url))) ||
|
||||
(row.url !== null && !evidenceUrl(row.url)) ||
|
||||
linked !== !!row.companyId || (row.companyId && !companies.has(row.companyId)) ||
|
||||
(row.kind === "promotion") !== (row.status === "promotion"))
|
||||
(row.kind === "promotion") !== (row.status === "promotion") ||
|
||||
(row.evidenceIds ?? []).some((id) => !evidence.has(id)) ||
|
||||
(row.status === "outside-cohort" && !row.evidenceIds?.length))
|
||||
throw new Error(`Invalid research candidate: ${row.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ test("research revisions share the authentication database and preserve replay l
|
||||
assert.equal(consumeCode(config, "invalid"), "limited");
|
||||
const initial = readResearchSnapshot();
|
||||
assert.equal(initial.companies.length, 1016);
|
||||
assert.equal(initial.evidence.length, 1101);
|
||||
assert.equal(initial.evidence.length, 1124);
|
||||
assert.equal(initial.observations.length, 187);
|
||||
assert.deepEqual(initial.candidateBatches, seed.candidateBatches, "candidate gaps persist in the same database metadata");
|
||||
assert.deepEqual(readResearchSnapshot(), initial, "reopening does not duplicate records");
|
||||
@@ -63,7 +63,7 @@ test("research validation rejects broken evidence and unsafe source links", () =
|
||||
|
||||
test("reviews link explicit companies without turning global or excluded cases into companies", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "companies").length, 46);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "companies").length, 47);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "dataset").length, 3);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "excluded-candidate").length, 8);
|
||||
const review = snapshot.reviews.find((r) => r.id === "R4")!;
|
||||
@@ -96,7 +96,7 @@ test("disclosure counts exclude client income, biographies, targets and duplicat
|
||||
|
||||
test("technical reviews keep accessible materials separate from tested capabilities", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview).length, 8);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview).length, 9);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 4);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "independent-test").length, 1);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "AI051")?.revenueStatus, "unknown");
|
||||
@@ -271,3 +271,23 @@ test("product launch candidates preserve unresolved years and many launches per
|
||||
kilo[0].companyId = "missing-company";
|
||||
assert.throws(() => validateResearch(snapshot), /research candidate/);
|
||||
});
|
||||
|
||||
test("annual launch archives exclude older companies only with evidence and reuse existing records", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "PH-2025-visible-1")!;
|
||||
assert.equal(batch.complete, false);
|
||||
assert.equal(batch.records.length, 19);
|
||||
const older = batch.records.filter((r) => r.status === "outside-cohort");
|
||||
assert.equal(older.length, 3);
|
||||
assert.ok(older.every((r) => !r.companyId && r.evidenceIds?.length));
|
||||
assert.equal(batch.records.find((r) => r.name === "Trace")?.companyId, "YC30687");
|
||||
const trace = snapshot.companies.find((c) => c.id === "YC30687")!;
|
||||
assert.equal(trace.profileOnly, false);
|
||||
assert.equal(trace.directoryOrigin, "yc-2025-2026");
|
||||
assert.equal(trace.revenueStatus, "unknown");
|
||||
assert.ok(!snapshot.observations.some((o) => o.evidence === "TRACE-HOME"), "demo metrics must not become reported results");
|
||||
older[0].evidenceIds = [];
|
||||
assert.throws(() => validateResearch(snapshot), /research candidate/);
|
||||
older[0].evidenceIds = ["missing-proof"];
|
||||
assert.throws(() => validateResearch(snapshot), /research candidate/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user