Merge pull request '统一 AI 公司研究:504项主营、192项AI候选与6项成立冲突补核' (#38) from codex/ai-research-consolidated into main
Verify and deploy Tabularium / verify-and-deploy (push) Failing after 5m35s
Verify and deploy Tabularium / verify-and-deploy (push) Failing after 5m35s
Reviewed-on: #38
This commit was merged in pull request #38.
This commit is contained in:
@@ -182,10 +182,10 @@ async function main() {
|
||||
assert.equal(researchResponse.status, 200, "authenticated research API");
|
||||
assert.ok(researchResponse.headers.get("cache-control")?.includes("no-store"));
|
||||
const research = await researchResponse.json();
|
||||
assert.equal(research.companies.length, 1051);
|
||||
assert.equal(research.companies.length, 1154);
|
||||
assert.equal(research.categories.length, 11);
|
||||
assert.equal(research.evidence.length, 1858);
|
||||
assert.equal(research.observations.length, 237);
|
||||
assert.equal(research.evidence.length, 3303);
|
||||
assert.equal(research.observations.length, 453);
|
||||
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 });
|
||||
assert.equal(researchPage.status, 200);
|
||||
|
||||
@@ -48,7 +48,7 @@ export type ResearchCandidateBatch = {
|
||||
records: {
|
||||
id: string; name: string; url: string | null; categoryId: string;
|
||||
kind: "product" | "company" | "promotion"; profileStatus: "readable" | "unavailable" | "archive-only";
|
||||
status: "pending-year" | "linked" | "existing-outside-cohort" | "outside-cohort" | "promotion";
|
||||
status: "pending-year" | "pending-ai" | "linked" | "existing-outside-cohort" | "outside-cohort" | "promotion";
|
||||
companyId?: string; evidenceIds?: string[]; note: string;
|
||||
}[];
|
||||
};
|
||||
@@ -125,13 +125,13 @@ export function validateResearch(snapshot: ResearchSnapshot) {
|
||||
if (!row.name.trim() || !row.note.trim() || !categories.has(row.categoryId) ||
|
||||
!["product", "company", "promotion"].includes(row.kind) ||
|
||||
!["readable", "unavailable", "archive-only"].includes(row.profileStatus) ||
|
||||
!["pending-year", "linked", "existing-outside-cohort", "outside-cohort", "promotion"].includes(row.status) ||
|
||||
!["pending-year", "pending-ai", "linked", "existing-outside-cohort", "outside-cohort", "promotion"].includes(row.status) ||
|
||||
(row.kind !== "promotion" && (!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.evidenceIds ?? []).some((id) => !evidence.has(id)) ||
|
||||
(row.status === "outside-cohort" && !row.evidenceIds?.length))
|
||||
(["outside-cohort", "pending-ai"].includes(row.status) && !row.evidenceIds?.length))
|
||||
throw new Error(`Invalid research candidate: ${row.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ test("research revisions share the authentication database and preserve replay l
|
||||
for (let i = 0; i < 20; i++) consumeCode(config, "invalid");
|
||||
assert.equal(consumeCode(config, "invalid"), "limited");
|
||||
const initial = readResearchSnapshot();
|
||||
assert.equal(initial.companies.length, 1051);
|
||||
assert.equal(initial.evidence.length, 1858);
|
||||
assert.equal(initial.observations.length, 237);
|
||||
assert.equal(initial.companies.length, 1154);
|
||||
assert.equal(initial.evidence.length, 3303);
|
||||
assert.equal(initial.observations.length, 453);
|
||||
assert.deepEqual(initial.candidateBatches, seed.candidateBatches, "candidate gaps persist in the same database metadata");
|
||||
assert.deepEqual(initial.directoryRechecks, seed.directoryRechecks, "follow-up classifications persist without rewriting the discovery audit");
|
||||
assert.deepEqual(readResearchSnapshot(), initial, "reopening does not duplicate records");
|
||||
@@ -64,8 +64,8 @@ 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, 115);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "dataset").length, 12);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "companies").length, 198);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "dataset").length, 21);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "excluded-candidate").length, 44);
|
||||
const review = snapshot.reviews.find((r) => r.id === "R4")!;
|
||||
assert.deepEqual(reviewCompanyIds(snapshot, review), ["AI007", "AI013", "AI021", "AI034"]);
|
||||
@@ -85,11 +85,11 @@ test("reviews link explicit companies without turning global or excluded cases i
|
||||
test("disclosure counts exclude client income, biographies, targets and duplicate milestones", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const summary = categorySummary(snapshot);
|
||||
assert.equal(summary.reduce((n, c) => n + c.count, 0), 1051);
|
||||
assert.equal(summary.reduce((n, c) => n + c.self, 0), 43);
|
||||
assert.equal(summary.reduce((n, c) => n + c.count, 0), 1154);
|
||||
assert.equal(summary.reduce((n, c) => n + c.self, 0), 58);
|
||||
assert.equal(summary.reduce((n, c) => n + c.estimate, 0), 2);
|
||||
assert.equal(summary.reduce((n, c) => n + c.platform, 0), 19);
|
||||
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 987);
|
||||
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 1075);
|
||||
assert.equal(snapshot.companies.find((c) => c.name === "Rork")?.revenueStatus, "unknown");
|
||||
assert.equal(snapshot.companies.find((c) => c.name === "Result")?.revenueStatus, "unknown");
|
||||
assert.ok(snapshot.observations.filter((o) => o.selection === "signal").every((o) => o.scope === "公司整体"));
|
||||
@@ -99,10 +99,33 @@ test("disclosure counts exclude client income, biographies, targets and duplicat
|
||||
assert.ok(arena.metric !== "mrr" && arena.metric !== "arr", "a two-week cumulative figure cannot become MRR or ARR");
|
||||
});
|
||||
|
||||
test("service run rates, legacy freight revenue and paid adoption do not become platform ARR", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const runRate = snapshot.observations.find((o) => o.id === "INDUSTRY11-O-LOCKE-RUNRATE")!;
|
||||
assert.equal(runRate.metric, "annualized-revenue");
|
||||
assert.equal(runRate.selection, "historical");
|
||||
assert.equal(runRate.observedAt, undefined);
|
||||
assert.equal(runRate.comparisonGroup, null);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC33283")?.revenueStatus, "self");
|
||||
for (const id of ["TRUEMILE-OLD-REV", "VELTHA-DEMO", "LANTERN-OLD-REV"]) {
|
||||
const observation = snapshot.observations.find((o) => o.id === `INDUSTRY11-O-${id}`)!;
|
||||
assert.equal(observation.selection, "excluded");
|
||||
assert.equal(observation.metric, undefined);
|
||||
assert.equal(observation.comparisonGroup, null);
|
||||
}
|
||||
for (const [id, company] of [["VERDANT-DEPLOY", "YC32189"], ["SUTRIX-PAID", "YC36576"]]) {
|
||||
const observation = snapshot.observations.find((o) => o.id === `INDUSTRY11-O-${id}`)!;
|
||||
assert.equal(observation.selection, "adoption");
|
||||
assert.equal(observation.metric, undefined);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === company)?.revenueStatus, "unknown");
|
||||
}
|
||||
assert.ok(platformIncomeSample(snapshot, { windowDays: 90 }).points.every((point) => !point.observation.id.startsWith("INDUSTRY11-")));
|
||||
});
|
||||
|
||||
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, 59);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 9);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview).length, 138);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 23);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "independent-test").length, 1);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "AI051")?.revenueStatus, "unknown");
|
||||
assert.match(snapshot.companies.find((c) => c.id === "AI051")!.technicalReview!.testScope!, /Sep 2026/);
|
||||
@@ -228,6 +251,10 @@ test("directory coverage reconciles every candidate and keeps profile-only incom
|
||||
assert.equal(row.foundedYear, 2026, "original Native discovery remains unchanged");
|
||||
assert.equal(company.year, null, "a model launch and YC date cannot settle the older business founding year");
|
||||
assert.ok(snapshot.reviews.some((review) => review.id === "NATIVE-R-COHORT" && review.companyIds?.includes(company.id)));
|
||||
} else if (company.id === "YC31470") {
|
||||
assert.equal(row.foundedYear, 2025, "original Tasklet discovery remains unchanged");
|
||||
assert.equal(company.year, null, "a new product cannot establish a new company founding year");
|
||||
assert.ok(snapshot.reviews.some((review) => review.id === "ENTERPRISE3-R-TASKLET" && review.companyIds?.includes(company.id)));
|
||||
} else {
|
||||
assert.equal(company.year, row.foundedYear);
|
||||
assert.ok([2025, 2026].includes(company.year!));
|
||||
@@ -379,7 +406,7 @@ test("unreconciled directory financials remain source reviews instead of income
|
||||
assert.ok(review.evidenceIds.includes("PH-TANA-DR"));
|
||||
assert.equal(reviewCompanyIds(snapshot, review).length, 0);
|
||||
assert.ok(!snapshot.observations.some((o) => o.evidence === "PH-TANA-DR"));
|
||||
assert.equal(snapshot.candidateBatches!.flatMap((b) => b.records).filter((r) => r.status === "pending-year").length, 18);
|
||||
assert.equal(snapshot.candidateBatches!.flatMap((b) => b.records).filter((r) => r.status === "pending-year").length, 24);
|
||||
});
|
||||
|
||||
test("product pivots and founder histories do not become new company years or current revenue", () => {
|
||||
@@ -416,6 +443,336 @@ test("follow-up evidence can admit an uncertain directory candidate without rewr
|
||||
assert.throws(() => validateResearch(snapshot), /directory recheck/);
|
||||
});
|
||||
|
||||
test("AI relevance follow-ups retain unresolved businesses and reuse existing company identities", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-1")!;
|
||||
assert.equal(batch.complete, false);
|
||||
assert.equal(batch.records.length, 24);
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(0, 24);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
const linked = batch.records.filter((r) => r.status === "linked");
|
||||
assert.equal(linked.length, 17);
|
||||
assert.equal(linked.filter((r) => r.companyId!.startsWith("YC")).length, 14);
|
||||
for (const [name, id] of [["Bud", "AI070"], ["Prism", "AI030"], ["Parametric", "AI014"]]) {
|
||||
assert.equal(linked.find((r) => r.name === name)?.companyId, id);
|
||||
}
|
||||
assert.equal(snapshot.companies.filter((c) => c.profileOnly || c.directoryOrigin === "yc-2025-2026").length, 928);
|
||||
for (const row of linked) {
|
||||
const ycId = Number(row.id.replace("YC-AI1-", ""));
|
||||
assert.equal(snapshot.directoryRechecks!.find((r) => r.ycId === ycId)?.companyId, row.companyId);
|
||||
}
|
||||
const pending = batch.records.filter((r) => r.status === "pending-ai");
|
||||
assert.equal(pending.length, 7);
|
||||
assert.ok(pending.every((r) => !r.companyId && r.evidenceIds!.length && /2025/.test(r.note)));
|
||||
assert.match(pending.find((r) => r.name === "Better Auth")!.note, /AI.*模块/);
|
||||
validateResearch(snapshot);
|
||||
pending[0].companyId = "AI014";
|
||||
assert.throws(() => validateResearch(snapshot), /research candidate/);
|
||||
delete pending[0].companyId;
|
||||
pending[0].evidenceIds = [];
|
||||
assert.throws(() => validateResearch(snapshot), /research candidate/);
|
||||
});
|
||||
|
||||
test("historical monthly revenue and customer examples do not enter recurring platform comparisons", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const monthly = snapshot.observations.find((o) => o.id === "UNCLEAR1-O-SCALAR-MONTHLY")!;
|
||||
assert.equal(monthly.value, 74000);
|
||||
assert.equal(monthly.selection, "historical");
|
||||
assert.equal(monthly.metric, undefined, "monthly revenue alone does not establish MRR or ARR");
|
||||
assert.equal(monthly.comparisonGroup, null);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC30514")!.revenueStatus, "self");
|
||||
for (const id of ["AMBY-CLIENT", "NIXO-EXAMPLE", "AUTOSTEP-WASTE"]) {
|
||||
assert.equal(snapshot.observations.find((o) => o.id === `UNCLEAR1-O-${id}`)!.selection, "excluded");
|
||||
}
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR1-")));
|
||||
const cua = snapshot.companies.find((c) => c.id === "YC30420")!;
|
||||
assert.equal(cua.cat, "C03");
|
||||
assert.equal(cua.revenueStatus, "unknown");
|
||||
assert.match(cua.businessModel!, /自备计算机/);
|
||||
assert.equal(cua.technicalReview!.level, "public-artifact");
|
||||
});
|
||||
|
||||
test("a second uncertain cohort admits evidenced AI tasks while preserving autonomy and finance gaps", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-2")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(24, 48);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 13);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 11);
|
||||
for (const name of ["Albacore Inc.", "Perseus Defense", "Munify", "Ruvo", "DeepGrove"]) {
|
||||
const row = batch.records.find((r) => r.name === name)!;
|
||||
assert.equal(row.status, "pending-ai");
|
||||
assert.equal(row.companyId, undefined, "autonomy, a domain or finance automation alone is insufficient");
|
||||
assert.ok(row.evidenceIds!.length);
|
||||
}
|
||||
const signals = snapshot.companies.find((c) => c.id === "YC30639")!;
|
||||
assert.equal(signals.year, 2026, "retain the company year instead of assigning the batch's majority year");
|
||||
assert.equal(signals.cat, "C06");
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC30846")!.cat, "C03");
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC30821")!.business, /远端推理/);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC30933")!.technicalReview!.level, "description",
|
||||
"vendor clinical agreement is not an independent validation");
|
||||
const amounts = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR2-"));
|
||||
assert.equal(amounts.length, 8);
|
||||
assert.ok(amounts.every((o) => ["excluded", "adoption"].includes(o.selection) && !o.metric && o.comparisonGroup === null));
|
||||
assert.equal(amounts.find((o) => o.id.endsWith("WARDSTONE-GRANT"))!.selection, "excluded");
|
||||
assert.equal(amounts.find((o) => o.id.endsWith("SOLVA-OLD-PREMIUM"))!.selection, "excluded");
|
||||
assert.ok(batch.records.filter((r) => r.companyId).every((r) => snapshot.companies.find((c) => c.id === r.companyId)!.revenueStatus === "unknown"));
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR2-")));
|
||||
});
|
||||
|
||||
test("the third uncertain cohort retains shutdowns, unknown scale and mixed data-service economics", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-3")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(48, 72);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 12);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 12);
|
||||
for (const name of ["Voltair", "Mirabelle", "ZeroSettle", "Kyten Technologies"]) {
|
||||
assert.equal(batch.records.find((r) => r.name === name)!.companyId, undefined);
|
||||
}
|
||||
const klaus = snapshot.companies.find((c) => c.id === "YC31084")!;
|
||||
assert.equal(klaus.revenueStatus, "unknown", "a shutdown must not manufacture a zero revenue report");
|
||||
assert.match(klaus.stage, /2026-09-01停服/);
|
||||
assert.ok(!snapshot.observations.some((o) => o.company === klaus.id));
|
||||
const openspec = snapshot.companies.find((c) => c.id === "YC31116")!;
|
||||
assert.equal(openspec.team, null, "missing staff count stays unknown");
|
||||
assert.equal(openspec.year, 2025, "a license copyright line alone is not a company founding date");
|
||||
assert.equal(openspec.technicalReview!.level, "public-artifact");
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC31095")!.businessModel!, /清洁/);
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR3-"));
|
||||
assert.equal(figures.length, 8);
|
||||
assert.ok(figures.every((o) => ["excluded", "adoption"].includes(o.selection) && !o.metric && o.comparisonGroup === null));
|
||||
assert.equal(figures.find((o) => o.id.endsWith("SHORTKIT-OLD-ARR"))!.selection, "excluded");
|
||||
assert.equal(figures.find((o) => o.id.endsWith("KALPA-TRAIN-COST"))!.selection, "excluded");
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR3-")));
|
||||
});
|
||||
|
||||
test("the fourth uncertain cohort distinguishes product pivots, managed labor and pass-through money", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-4")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(72, 96);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 13);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 11);
|
||||
assert.equal(batch.records.find((r) => r.name === "Orthogonal")!.companyId, "AI036");
|
||||
assert.equal(snapshot.companies.filter((c) => c.url.endsWith("/companies/orthogonal")).length, 1);
|
||||
const fern = snapshot.companies.find((c) => c.id === "YC31152")!;
|
||||
assert.equal(fern.cat, "C02");
|
||||
assert.match(fern.notes, /会议/);
|
||||
const mocha = snapshot.companies.find((c) => c.id === "YC31269")!;
|
||||
assert.equal(mocha.year, 2026);
|
||||
assert.match(mocha.businessModel!, /人工/);
|
||||
assert.match(mocha.price, /Platform.*Managed/);
|
||||
assert.match(mocha.notes, /Coming soon/);
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR4-"));
|
||||
assert.equal(figures.length, 7);
|
||||
assert.ok(figures.every((o) => ["excluded", "adoption"].includes(o.selection) && !o.metric && o.comparisonGroup === null));
|
||||
for (const suffix of ["LAURENCE-ADSPEND", "EKPA-CONNECTED-ASSETS", "REGBASE-CLIENT-GRANTS", "MOCHA-FUNDING"]) {
|
||||
assert.equal(figures.find((o) => o.id.endsWith(suffix))!.selection, "excluded");
|
||||
}
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC31199")!.technicalReview!.level, "public-artifact");
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR4-")));
|
||||
});
|
||||
|
||||
test("the fifth uncertain cohort separates dated ARR, service run rates, bookings and previous ventures", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-5")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(96, 120);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 15);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 9);
|
||||
assert.equal(batch.records.find((r) => r.name === "primitive")!.companyId, "AI002");
|
||||
assert.equal(batch.records.find((r) => r.name === "Result")!.companyId, "AI001");
|
||||
const result = snapshot.companies.find((c) => c.id === "AI001")!;
|
||||
assert.equal(result.cat, "C09");
|
||||
assert.equal(result.revenueStatus, "unknown");
|
||||
assert.match(result.notes, /280万美元ARR属于用户/);
|
||||
assert.ok(result.evidenceIds.includes("UNCLEAR5-31438-TERMS"));
|
||||
const andco = snapshot.companies.find((c) => c.id === "YC31411")!;
|
||||
assert.equal(andco.year, 2026, "a founder's previous venture must not replace the new company's stated year");
|
||||
assert.match(andco.notes, /Layup/);
|
||||
assert.equal(snapshot.evidence.find((e) => e.id === "UNCLEAR5-31411-LAUNCH6")!.companyId, null);
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR5-"));
|
||||
assert.equal(figures.length, 18);
|
||||
const dated = figures.find((o) => o.id.endsWith("TRELLIS-ARR-AUG"))!;
|
||||
assert.equal(dated.metric, "arr");
|
||||
assert.equal(dated.observedAt, "2026-08-24");
|
||||
assert.equal(dated.bound, "≥");
|
||||
assert.equal(figures.find((o) => o.id.endsWith("INSTA-RUNRATE"))!.metric, "annualized-revenue");
|
||||
assert.equal(figures.find((o) => o.id.endsWith("INSTA-LAUNCH-ARR"))!.metric, "arr");
|
||||
for (const suffix of ["PARROT-CONTRACT", "KINRO-OLD-CONTRACT", "BENTO-OLD-EMPLOYER", "TRELLIS-OLD-MGMT"]) {
|
||||
assert.equal(figures.find((o) => o.id.endsWith(suffix))!.selection, "excluded");
|
||||
}
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC31423")!.technicalReview!.level, "description",
|
||||
"an internal benchmark subset is not an independent leaderboard result");
|
||||
assert.ok(figures.every((o) => o.comparisonGroup === null));
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR5-")));
|
||||
});
|
||||
|
||||
test("the sixth uncertain cohort preserves namesakes, churn and historical robotics MRR", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-6")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(120, 144);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 13);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 11);
|
||||
const hera = snapshot.companies.find((c) => c.id === "YC32123")!;
|
||||
const videoHera = snapshot.companies.find((c) => c.id === "AI025")!;
|
||||
assert.equal(hera.cat, "C07");
|
||||
assert.equal(hera.year, 2026);
|
||||
assert.equal(videoHera.cat, "C08");
|
||||
assert.equal(videoHera.year, 2025);
|
||||
assert.notEqual(hera.url, videoHera.url, "same-name products with different YC pages must not be merged");
|
||||
for (const name of ["Aernata", "Maquoketa Research", "Fire Wallet", "Eden Robotics", "Edgerun"]) {
|
||||
const row = batch.records.find((r) => r.name === name)!;
|
||||
assert.equal(row.status, "pending-ai");
|
||||
assert.equal(row.companyId, undefined, "historical AI products, agent features and autonomous hardware need current-core evidence");
|
||||
}
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR6-"));
|
||||
assert.equal(figures.length, 13);
|
||||
const churn = figures.find((o) => o.id.endsWith("ARDENT-CHURN"))!;
|
||||
assert.equal(churn.selection, "excluded");
|
||||
assert.equal(churn.metric, undefined, "lost ARR is not a positive current ARR observation");
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC31475")!.revenueStatus, "unknown");
|
||||
const mrr = figures.find((o) => o.id.endsWith("AVEA-MRR"))!;
|
||||
assert.equal(mrr.value, 18000);
|
||||
assert.equal(mrr.metric, "mrr");
|
||||
assert.equal(mrr.selection, "historical");
|
||||
assert.match(mrr.unit, /无币种/);
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC31530")!.notes, /Acquired/);
|
||||
for (const suffix of ["PLAN0-PROJECTS-YC", "PLAN0-PROJECTS-LAUNCH", "SILMARIL-DAMAGE-YC", "SILMARIL-DAMAGE-CASE1", "SILMARIL-DAMAGE-CASE2", "EXPANSE-WASTE"]) {
|
||||
assert.equal(figures.find((o) => o.id.endsWith(suffix))!.selection, "excluded");
|
||||
}
|
||||
const openwork = snapshot.companies.find((c) => c.id === "YC31505")!;
|
||||
assert.equal(openwork.technicalReview!.level, "public-artifact");
|
||||
assert.ok(openwork.technicalReview!.evidenceIds.includes("UNCLEAR6-31505-EE-LICENSE"));
|
||||
assert.match(openwork.notes, /桌面MIT与ee目录/);
|
||||
assert.ok(figures.every((o) => o.comparisonGroup === null));
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR6-")));
|
||||
});
|
||||
|
||||
test("the seventh uncertain cohort separates hardware sales, prepayments and bounded verification", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-7")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear").slice(144, 168);
|
||||
assert.equal(batch.complete, false);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 16);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 8);
|
||||
const robotNori = snapshot.companies.find((c) => c.id === "YC32553")!;
|
||||
const healthNori = snapshot.companies.find((c) => c.id === "YC30657")!;
|
||||
assert.equal(robotNori.cat, "C10");
|
||||
assert.equal(healthNori.cat, "C09");
|
||||
assert.notEqual(robotNori.url, healthNori.url, "same-name hardware and health companies retain distinct identities");
|
||||
assert.equal(batch.records.find((r) => r.name === "Nori")!.companyId, robotNori.id);
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR7-"));
|
||||
assert.equal(figures.length, 18);
|
||||
const sales = figures.find((o) => o.id.endsWith("NORI-SALES"))!;
|
||||
assert.equal(sales.value, 440000);
|
||||
assert.equal(sales.selection, "historical");
|
||||
assert.equal(sales.metric, undefined, "hardware sales with unverified preorder/delivery mix must not become ARR");
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC32164")!.price!, /额度/);
|
||||
for (const suffix of ["GUT-PHARMACY", "MANIFOLD-PICKS", "ATC-CLIENT-FLEET", "OPERON-CLIENT-SAVE", "ANYALPHA-OLD-APPS", "LETTER-DEMO"]) {
|
||||
assert.equal(figures.find((o) => o.id.endsWith(suffix))!.selection, "excluded");
|
||||
}
|
||||
assert.match(figures.find((o) => o.id.endsWith("LETTER-DEMO"))!.scope, /fictional/);
|
||||
assert.equal(snapshot.companies.find((c) => c.id === "YC34899")!.cat, "C06");
|
||||
const kailash = snapshot.companies.find((c) => c.id === "YC34828")!;
|
||||
assert.equal(kailash.cat, "C10");
|
||||
assert.equal(kailash.technicalReview!.level, "description", "an open-weights claim without readable weights or a model card is not a reviewed public artifact");
|
||||
const graphify = snapshot.companies.find((c) => c.id === "YC32583")!;
|
||||
assert.equal(graphify.technicalReview!.level, "public-artifact");
|
||||
const proof = snapshot.evidence.find((e) => e.id === "UNCLEAR7-32583-PROOF")!;
|
||||
assert.match(proof.summary, /unknown/);
|
||||
assert.match(proof.summary, /函数/);
|
||||
assert.match(proof.limitation, /整库正确/);
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC32518")!.notes, /Build标Coming soon/);
|
||||
for (const name of ["Kara", "Molagri", "TareBio", "Atomarine", "Vernius Systems, Inc."]) {
|
||||
const row = batch.records.find((r) => r.name === name)!;
|
||||
assert.equal(row.status, "pending-ai");
|
||||
assert.equal(row.companyId, undefined);
|
||||
}
|
||||
assert.ok(figures.every((o) => o.comparisonGroup === null));
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR7-")));
|
||||
});
|
||||
|
||||
test("all original AI-unclear candidates retain a unique follow-up without counting EveryApp twice", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const rows = snapshot.candidateBatches!.filter((b) => b.id.startsWith("YC-AI-UNCLEAR-")).flatMap((b) => b.records);
|
||||
const original = coverageAudit.records.filter((r) => r.status === "ai-unclear");
|
||||
assert.equal(rows.length, 192);
|
||||
assert.equal(new Set(rows.map((r) => r.url)).size, 192);
|
||||
assert.deepEqual(rows.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(rows.filter((r) => r.status === "linked").length, 110);
|
||||
assert.equal(rows.filter((r) => r.status === "pending-ai").length, 82);
|
||||
assert.equal(snapshot.directoryRechecks!.filter((r) => r.ycId === 36088).length, 1);
|
||||
const everyapp = rows.find((r) => r.name === "EveryApp")!;
|
||||
assert.equal(everyapp.companyId, "AI074");
|
||||
assert.equal(snapshot.companies.filter((c) => c.id === "AI074").length, 1);
|
||||
for (const row of rows.filter((r) => r.status === "pending-ai")) {
|
||||
assert.equal(row.companyId, undefined);
|
||||
assert.ok(row.evidenceIds!.length > 0, "unresolved AI relevance has explicit evidence and gaps");
|
||||
}
|
||||
assert.equal(snapshot.coverage!.newProfiles, 928, "later evidence does not rewrite the original discovery accounting");
|
||||
});
|
||||
|
||||
test("the final uncertain cohort separates delivery-start rentals, reservations and upstream costs", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-AI-UNCLEAR-8")!;
|
||||
assert.equal(batch.complete, false, "reading the full pool does not resolve all AI, year or financial gaps");
|
||||
assert.equal(batch.records.filter((r) => r.status === "linked").length, 11);
|
||||
assert.equal(batch.records.filter((r) => r.status === "pending-ai").length, 13);
|
||||
const rhem = snapshot.companies.find((c) => c.id === "YC35127")!;
|
||||
assert.match(rhem.price!, /确认交付后/);
|
||||
assert.match(rhem.price!, /99 USD/);
|
||||
assert.equal(rhem.revenueStatus, "unknown");
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC37272")!.price!, /预约/);
|
||||
assert.match(snapshot.companies.find((c) => c.id === "AI074")!.price!, /有效订阅/);
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC35396")!.notes, /Coming next/);
|
||||
assert.match(snapshot.companies.find((c) => c.id === "YC36774")!.notes, /Early access/);
|
||||
const figures = snapshot.observations.filter((o) => o.id.startsWith("UNCLEAR8-"));
|
||||
assert.equal(figures.length, 9);
|
||||
assert.ok(figures.every((o) => ["excluded", "adoption"].includes(o.selection) && !o.metric && o.comparisonGroup === null));
|
||||
for (const suffix of ["OASIVE-OLD-WELLS", "OASIVE-OLD-GOOGLE", "OBSESSION-CALCULATOR", "EVERYAPP-UPSTREAM"]) {
|
||||
assert.equal(figures.find((o) => o.id.endsWith(suffix))!.selection, "excluded");
|
||||
}
|
||||
for (const name of ["Clean", "STASIS", "RATLOG", "Inflection Space Systems", "twentyfour26"]) {
|
||||
assert.equal(batch.records.find((r) => r.name === name)!.status, "pending-ai");
|
||||
}
|
||||
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((p) => p.observation.id.startsWith("UNCLEAR8-")));
|
||||
});
|
||||
|
||||
test("founding conflicts preserve old product history without creating new companies or revenue", () => {
|
||||
const snapshot = seed as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "YC-DATE-CONFLICT-1")!;
|
||||
const original = coverageAudit.records.filter((r) => r.status === "date-conflict");
|
||||
assert.equal(batch.complete, false);
|
||||
assert.equal(batch.records.length, 6);
|
||||
assert.deepEqual(batch.records.map((r) => r.url), original.map((r) => r.source));
|
||||
assert.equal(new Set(batch.records.map((r) => r.url)).size, original.length);
|
||||
for (const row of batch.records) {
|
||||
assert.equal(row.status, "pending-year");
|
||||
assert.equal(row.companyId, undefined);
|
||||
const evidence = snapshot.evidence.filter((e) => row.evidenceIds!.includes(e.id));
|
||||
assert.equal(evidence.length, row.evidenceIds!.length);
|
||||
assert.ok(evidence.every((e) => e.companyId === null));
|
||||
assert.ok(evidence.some((e) => e.publishedAt?.startsWith("2025-")), "old product launch remains explicit");
|
||||
assert.ok(!snapshot.companies.some((c) => c.evidenceIds.some((eid) => row.evidenceIds!.includes(eid))));
|
||||
}
|
||||
assert.match(batch.records.find((r) => r.name === "Layers")!.note, /未确认当前AI核心/);
|
||||
assert.ok(!snapshot.observations.some((o) => o.evidence.startsWith("YEARCONFLICT1-")));
|
||||
const excluded = coverageAudit.records.filter((r) => r.status === "year-outside-or-missing");
|
||||
assert.equal(excluded.filter((r) => r.foundedYear === null).length, 54);
|
||||
assert.equal(excluded.filter((r) => r.foundedYear !== null).length, 214);
|
||||
assert.ok(excluded.filter((r) => r.foundedYear !== null).every((r) => ![2025, 2026].includes(r.foundedYear!)));
|
||||
});
|
||||
|
||||
test("Chinese discovery entries preserve unread articles and use separate primary evidence", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
const batch = snapshot.candidateBatches!.find((b) => b.id === "JQ-2026-targeted-1")!;
|
||||
|
||||
+35787
-3910
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "2026-10-31-1",
|
||||
"version": "2026-10-31-founding-conflicts-1",
|
||||
"scopeConfirmedAt": "2026-10-30",
|
||||
"acceptance": "以确认的公开来源清单为边界,逐条核对并标明缺项。",
|
||||
"provenance": "S01—S12恢复自已提交用户的《AI公司研究_来源与分类模板》来源清单;S13—S16单列后续已使用的补充证据渠道,不将使用次数当作全量覆盖。",
|
||||
@@ -15,8 +15,8 @@
|
||||
],
|
||||
"initialAccess": "官网目录可访问",
|
||||
"boundary": "已读取八个2025—2026批次镜像候选池1428条,再核YC官方页面;不声称覆盖全部YC历年或未公开公司。",
|
||||
"nextCheck": "原新增目录中31条深化为个案并保留来源;当前基础项393条主营分类人工复核。本轮23项C06规则初分已读,22项保留、Bluma转创意制作,8项官网资料与Native政府接口缺项分开。软件/人工托管/制作代理及广告预算拆分;Native官网旧经营与YC2026成立冲突,当前year=null,原发现审计保留;2M ARR仅交叉核对。继续核C05/C07及其他非人工资料、主体、技术和财务,不把主营复核当完整来源覆盖。",
|
||||
"limitation": "批次不等于成立年;不代表全部公司"
|
||||
"limitation": "批次不等于成立年;不代表全部公司",
|
||||
"nextCheck": "已统一企业141、行业252、模型标签26、开发标签51、其余标签34项,共504项新增主营复核。当前928条原YC新增记录保留发现来源,其中基础项871条均已做主营人工复核(871条),57条深化个案。C05规则89保留27/移62,C05标签52保留10/移42;C07规则184保留135/移49,C07标签68保留39/移29;模型标签26保留17/移9,开发标签51保留16/移35,其余标签34保留16/移18。主营复核仍含C00/短简介/混合交付缺项,不等完整产品/技术/财务审计。Tasklet及Native新产品与旧业务链保留,发现审计不改;Freya、Epicenter、Stellon许可及公开材料/厂商基准范围分开。客户收入、估价、资产、节省、管线/意向、预订需求、旧公司收入与示例排除自身ARR;Locke服务run-rate不等ARR,Mixy历史MRR/捐赠、Isengard无期间收入分开。各批证据、观测、核查与主体/收费/人工成本缺项均保留;全部确认来源清单的候选范围、AI不明/成立冲突及公司财务技术缺项继续核,不能声称全来源研究完成。 原AI不明192项已按原顺序补核八批192项:103新增、7复用(含此前已核EveryApp)、82保留AI主营待核,共110关联;没有再把EveryApp额外加1,全池192项均有可回查后续记录。原发现审计/928初始新增不回写;已读全池不等82项均确认AI,更不等268年范围外/缺失、6日期冲突和其他来源全部完成。Rhem交付后租赁/旧买断、Subvocal预约、EveryApp托管计划/Cloudflare费/OpenSEO套餐、ObsessionDB资源估算与BYOC年度运维分开,不新增可比MRR;市政债未来模块、原型/健康/倍速演示及Clean模型实现缺项保留。 原268项年份范围外/缺失已按原快照拆为214项列2022—2024(4/30/180)和54项无年,不称214项本轮登记核验。另6项日期冲突全池已补现官网和2025旧发布,均成立年待核,未新增公司;运营者/条款日期不替注册证据,Layers现AI核心待核,客户销售/利润计算器和前事业收入排除。"
|
||||
},
|
||||
{
|
||||
"id": "S02",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"sourceVersion": "2026-10-31-sales-models-1",
|
||||
"sourceVersion": "2026-10-31-founding-conflicts-1",
|
||||
"asOf": "2026-10-31",
|
||||
"metric": "platform-mrr-usd",
|
||||
"sampleUnit": "product-or-business",
|
||||
|
||||
@@ -85,7 +85,7 @@ def candidate_register():
|
||||
all_ids = [r['id'] for b in batches for r in b['records']]
|
||||
assert len(set(all_ids)) == len(all_ids)
|
||||
lines = []
|
||||
statuses = {'pending-year': '成立年待核', 'linked': '已关联公司',
|
||||
statuses = {'pending-year': '成立年待核', 'pending-ai': 'AI主营待核', 'linked': '已关联公司',
|
||||
'existing-outside-cohort': '已有关联,年份范围外',
|
||||
'outside-cohort': '范围外或既有业务,不新增公司', 'promotion': '推广活动,非公司新增'}
|
||||
for batch in batches:
|
||||
@@ -97,13 +97,13 @@ def candidate_register():
|
||||
assert sum(counts.values()) == len(rows)
|
||||
lines += ['', f"## {batch['sourceId']} 候选核对({batch['id']})", '',
|
||||
f"[发现页面]({batch['url']}),读取于{batch['accessedAt']}。{batch['scope']}", '',
|
||||
f"本批{len(rows)}条:{counts['linked']}条关联公司、{counts['existing-outside-cohort']}条关联范围外对照、{counts['outside-cohort']}条范围外不新增公司、{counts['pending-year']}条成立年待核、{counts['promotion']}条推广活动。完整来源覆盖标记:{'已完成' if batch['complete'] else '未完成'}。主营或产品任务的初分类不计入主公司表数量,只有已关联的公司记录进入对应公司明细。候选与缺项随研究版本保存在文档站同一SQLite的研究元数据中。", '',
|
||||
f"本批{len(rows)}条:{counts['linked']}条关联公司、{counts['existing-outside-cohort']}条关联范围外对照、{counts['outside-cohort']}条范围外不新增公司、{counts['pending-year']}条成立年待核、{counts['pending-ai']}条AI主营待核、{counts['promotion']}条推广活动。完整来源覆盖标记:{'已完成' if batch['complete'] else '未完成'}。主营或产品任务的初分类不计入主公司表数量,只有已关联的公司记录进入对应公司明细。候选与缺项随研究版本保存在文档站同一SQLite的研究元数据中。", '',
|
||||
'| 发现条目 | 主营或产品任务初分 | 核对状态 | 关联公司 | 核对证据 | 限制 |', '| --- | --- | --- | --- | --- | --- |']
|
||||
for row in rows:
|
||||
assert row['categoryId'] in categories
|
||||
assert row['status'] in statuses
|
||||
assert all(eid in evidence for eid in row.get('evidenceIds', []))
|
||||
if row['status'] == 'outside-cohort':
|
||||
if row['status'] in {'outside-cohort', 'pending-ai'}:
|
||||
assert row.get('evidenceIds') and not row.get('companyId')
|
||||
name = f"[{row['name']}]({row['url']})" if row['url'] else row['name']
|
||||
company = '—'
|
||||
@@ -121,6 +121,49 @@ def candidate_register():
|
||||
return lines
|
||||
|
||||
|
||||
def uncertain_ai_followups():
|
||||
original = {row['source']: row for row in AUDIT['records'] if row['status'] == 'ai-unclear'}
|
||||
rows = [row for batch in DATA.get('candidateBatches', [])
|
||||
if batch['id'].startswith('YC-AI-UNCLEAR-') for row in batch['records']]
|
||||
if not rows:
|
||||
return []
|
||||
urls = [row['url'] for row in rows]
|
||||
assert len(set(urls)) == len(urls), 'Duplicate AI-relevance follow-up URL'
|
||||
rechecks = {row['ycId']: row for row in DATA.get('directoryRechecks', [])}
|
||||
counts = Counter(row['status'] for row in rows)
|
||||
assert set(counts) <= {'linked', 'pending-ai'}
|
||||
for row in rows:
|
||||
assert row['url'] in original and row.get('evidenceIds')
|
||||
baseline = original[row['url']]
|
||||
if row['status'] == 'linked':
|
||||
assert rechecks[baseline['ycId']]['companyId'] == row['companyId']
|
||||
else:
|
||||
assert not row.get('companyId') and baseline['ycId'] not in rechecks
|
||||
unread = len(original) - len(rows)
|
||||
assert unread >= 0
|
||||
return ['', '## 原AI主营不明名单的后续覆盖', '',
|
||||
f"原名单{len(original)}项,已有后续记录{len(rows)}项:{counts['linked']}项关联公司、{counts['pending-ai']}项仍待核AI主营,{unread}项尚无本批系列的后续记录。计数按原始YC页面去重;EveryApp此前的独立复核与末批记录不重复相加。", '',
|
||||
'读完名单只证明每项有可回查的处理记录,不证明待核项均为AI公司,也不证明法律主体、收入或技术效果已独立验证。原始发现审计保持不变,成立年范围外/缺失、成立冲突及其他来源的缺项仍单列。', '']
|
||||
|
||||
|
||||
def founding_year_followups():
|
||||
original = {row['source']: row for row in AUDIT['records'] if row['status'] == 'date-conflict'}
|
||||
rows = [row for batch in DATA.get('candidateBatches', [])
|
||||
if batch['id'].startswith('YC-DATE-CONFLICT-') for row in batch['records']]
|
||||
urls = [row['url'] for row in rows]
|
||||
assert len(set(urls)) == len(urls), 'Duplicate founding-conflict follow-up URL'
|
||||
assert set(urls) <= set(original), 'Unknown founding-conflict follow-up URL'
|
||||
evidence = {row['id']: row for row in DATA['evidence']}
|
||||
for row in rows:
|
||||
assert row['status'] == 'pending-year' and not row.get('companyId')
|
||||
assert row.get('evidenceIds') and all(eid in evidence for eid in row['evidenceIds'])
|
||||
assert all(evidence[eid]['companyId'] is None for eid in row['evidenceIds'])
|
||||
unread = len(original) - len(rows)
|
||||
return ['', '## 原成立年冲突名单的后续覆盖', '',
|
||||
f"原名单{len(original)}项,已有后续记录{len(rows)}项,均保留成立年待核,{unread}项尚无本系列后续记录。当前业务初分类见候选表,不计入主公司表及收入统计。", '',
|
||||
'2025旧品牌发布可证明当时已有产品材料;当前目录的2026字段、批次、条款日期和运营者名称不能单独证明法律主体成立或新旧主体连续。未据此强改成立年。Layers当前AI核心仍另待核。', '']
|
||||
|
||||
|
||||
def directory_rechecks():
|
||||
rows = DATA.get('directoryRechecks', [])
|
||||
if not rows:
|
||||
@@ -167,6 +210,11 @@ def render():
|
||||
'year-outside-or-missing': cov['otherOrMissingYear'],
|
||||
'ai-unclear': cov['unclearAI'], 'date-conflict': cov['dateConflicts']}
|
||||
assert len({x['ycId'] for x in AUDIT['records']}) == len(AUDIT['records'])
|
||||
excluded_years = Counter(x['foundedYear'] for x in AUDIT['records'] if x['status'] == 'year-outside-or-missing')
|
||||
outside_years = {year: count for year, count in excluded_years.items() if year is not None}
|
||||
assert all(year not in (2025, 2026) for year in outside_years)
|
||||
assert sum(outside_years.values()) + excluded_years[None] == cov['otherOrMissingYear']
|
||||
year_detail = '、'.join(f'{year}年{count}项' for year, count in sorted(outside_years.items()))
|
||||
lines = ['# AI 公司资料覆盖与缺项', '',
|
||||
f"截至 {DATA['asOf']},研究表含{len(companies):,}条公司或产品记录。YC候选池有逐条读取审计;其他来源为定向补充。清单尚不能作为全球AI公司普查,也不能将收入未知解释为零。", '',
|
||||
'验收范围已于2026-10-30确认为:以确认的公开来源清单为边界,逐条核对并标明缺项。下方区分已逐条审计的候选池与定向补充来源;已使用某来源不代表该来源已被完整覆盖。', '',
|
||||
@@ -178,7 +226,8 @@ def render():
|
||||
f"| 初筛匹配 | {cov['matchingProfiles']:,} | 成立年及AI相关描述通过初筛,尚非逐家商业验证 |",
|
||||
f"| 与原表重合 | {cov['existingProfiles']} | URL匹配,未再次新增 |",
|
||||
f"| 新增目录记录 | {cov['newProfiles']:,} | 原始入表来源,后续深化不改变发现计数 |",
|
||||
f"| 年份不符或缺失 | {cov['otherOrMissingYear']} | 此轮不作为成立年匹配项 |",
|
||||
f"| 原目录列为范围外年份 | {sum(outside_years.values())} | {year_detail};原快照自述,不是独立登记核验 |",
|
||||
f"| 原目录未给成立年 | {excluded_years[None]} | 与已列范围外年份分开,仍待补证 |",
|
||||
f"| AI业务待确认 | {cov['unclearAI']} | 不强行把背景关键词当主营 |",
|
||||
f"| 成立年与批次冲突 | {cov['dateConflicts']} | 另保留核查记录 |", '',
|
||||
f"全表由{depth}条目录基础项和{len(companies)-depth}条个案或平台记录组成。候选池已匹配项之外另有{len(companies)-cov['matchingProfiles']}条记录,包含其他来源及发布/转型对照;其中已有{promoted}条原目录记录深化为个案,仍保留目录来源。两种统计边界不同。候选池数字只是该镜像快照的覆盖,Bud等后续定向补充不回填为原候选池已覆盖。", '',
|
||||
@@ -217,13 +266,15 @@ def render():
|
||||
lines.append(f"| {name} | {len(entries)} | {len({e['url'] for e in entries})} | {note} |")
|
||||
others = [e for e in DATA['evidence'] if urlsplit(e['url']).netloc not in included]
|
||||
lines.append(f"| 其他官网、评测及公开资料 | {len(others)} | {len({e['url'] for e in others})} | 按每条来源限制理解,不能统一当作独立证据 |")
|
||||
lines += uncertain_ai_followups()
|
||||
lines += founding_year_followups()
|
||||
lines += directory_rechecks()
|
||||
lines += source_register()
|
||||
lines += context_methods()
|
||||
lines += candidate_register()
|
||||
lines += ['', '## 尚未满足的研究条件', '',
|
||||
'行业ARR比较仍缺统一业务截止日、币种、经常性定义和业务边界。现有平台MRR可描述已采集产品,不足以代表全部新公司。技术评测只覆盖所列版本与任务,不宜跨领域汇总为统一强弱分数。', '',
|
||||
'下一轮优先补收入线索的日期及合同定义、非YC和非英文来源、规则初分的人工复核,以及停止服务或被收购案例。这样能减少“只见赢家”和“只见融资公司”的偏差。公开来源池之外的未披露公司仍无法证明已被穷尽。', '',
|
||||
'下一轮优先补收入线索的日期及合同定义、成立年冲突、AI主营仍待核项、非YC和非英文来源,以及停止服务或被收购案例。这样能减少“只见赢家”和“只见融资公司”的偏差。公开来源池之外的未披露公司仍无法证明已被穷尽。', '',
|
||||
]
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user