扩展 AI 公司研究并修复收入统计表布局 #31

Merged
Zayden-Jung merged 18 commits from codex/ai-research-cn-sme into main 2026-10-30 16:11:48 +00:00
8 changed files with 11233 additions and 1844 deletions
+3 -3
View File
@@ -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, 1029);
assert.equal(research.companies.length, 1051);
assert.equal(research.categories.length, 11);
assert.equal(research.evidence.length, 1412);
assert.equal(research.observations.length, 192);
assert.equal(research.evidence.length, 1858);
assert.equal(research.observations.length, 237);
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);
@@ -75,7 +75,7 @@ export default function IncomeDistribution({ data, onSelect }: {
</svg></div>
<figcaption>圆点:产品观测 竖线:样本均值 菱形:样本中位数。业务类别标题下各行按支付平台{splitModels && "及收费与交付模式"}分别统计;n为该组产品数。点击点或下表产品名可看原始证据。</figcaption>
</figure>
<div className="research-table-wrap"><table><caption>{metric}样本统计;每行是类别下的一个统计组,CV使用样本标准差</caption><thead><tr><th scope="col">业务类别</th><th scope="col">支付平台 / 收费模式</th><th scope="col">n</th><th scope="col">均值</th><th scope="col">中位数</th><th scope="col">均值/中位数</th><th scope="col">CV</th><th scope="col">去除最大值后的均值 / 下降幅度</th><th scope="col">产品与限制</th></tr></thead>{categoryGroups.map(({ category, rows }) => <tbody key={category}>{rows.map((group, index) => <tr key={group.key}>
<div className="research-table-wrap"><table className="income-statistics"><caption>{metric}样本统计;每行是类别下的一个统计组,CV使用样本标准差</caption><thead><tr><th scope="col">业务类别</th><th scope="col">支付平台 / 收费模式</th><th scope="col">n</th><th scope="col">均值</th><th scope="col">中位数</th><th scope="col">均值/中位数</th><th scope="col">CV</th><th scope="col">去除最大值后的均值 / 下降幅度</th><th scope="col">产品与限制</th></tr></thead>{categoryGroups.map(({ category, rows }) => <tbody key={category}>{rows.map((group, index) => <tr key={group.key}>
{index === 0 && <th scope="rowgroup" rowSpan={rows.length}>{categories.get(category)}<small>{rows.length}个统计组</small></th>}
<td>{group.provider}<small>{group.model}</small></td><td>{group.stats.n}</td><td>{usd(group.stats.mean)}</td><td>{usd(group.stats.median)}</td><td>{group.stats.meanMedianRatio?.toFixed(2) ?? "—"}</td><td>{group.stats.cv?.toFixed(2) ?? "—"}</td><td>{usd(group.stats.meanWithoutLargest)}<small>{percent(group.stats.largestRemovalDrop)}</small></td>
<td>{group.points.map((point) => <span key={point.company.id}><button className="research-company-name" onClick={() => onSelect(point.company.id)}>{point.company.name}</button>{" "}</span>)}<small>{group.stats.n < 3 ? "样本少于3,不能据此判断领域典型收入。" : "自选的小样本,须结合产品年龄、成本与留存评估。"}</small></td>
+7
View File
@@ -1473,6 +1473,13 @@ svg { flex-shrink: 0; }
.research-distribution { margin: 24px 0 38px; }
.research-distribution figure { margin: 20px 0; }
.ai-research .income-statistics { min-width: 1200px; }
/* Row-spanning category headings shift cell indexes between rows. */
.ai-research .income-statistics td { min-width: 0; }
.ai-research .income-statistics th[scope="rowgroup"] { min-width: 150px; white-space: nowrap; }
.ai-research .income-statistics th[scope="rowgroup"] small { display: block; margin-top: 5px; }
.ai-research .income-statistics td:not(:last-child) { white-space: nowrap; }
.ai-research .income-statistics td:last-child { min-width: 220px; }
.income-distribution-chart { display: block; width: 100%; min-width: 900px; height: auto; }
.income-distribution-chart [role="button"] { cursor: pointer; outline: none; }
.income-distribution-chart [role="button"]:focus circle:last-child { stroke: #b17725; stroke-width: 3; }
+100 -19
View File
@@ -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, 1029);
assert.equal(initial.evidence.length, 1412);
assert.equal(initial.observations.length, 192);
assert.equal(initial.companies.length, 1051);
assert.equal(initial.evidence.length, 1858);
assert.equal(initial.observations.length, 237);
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,9 +64,9 @@ 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, 74);
assert.equal(snapshot.reviews.filter((r) => r.scope === "dataset").length, 10);
assert.equal(snapshot.reviews.filter((r) => r.scope === "excluded-candidate").length, 37);
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 === "excluded-candidate").length, 44);
const review = snapshot.reviews.find((r) => r.id === "R4")!;
assert.deepEqual(reviewCompanyIds(snapshot, review), ["AI007", "AI013", "AI021", "AI034"]);
assert.deepEqual(reviewCompanyIds(snapshot, snapshot.reviews.find((r) => r.id === "CN-R-PSI")!), []);
@@ -85,20 +85,24 @@ 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), 1029);
assert.equal(summary.reduce((n, c) => n + c.self, 0), 28);
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.estimate, 0), 2);
assert.equal(summary.reduce((n, c) => n + c.platform, 0), 16);
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 983);
assert.equal(summary.reduce((n, c) => n + c.platform, 0), 19);
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 987);
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 === "公司整体"));
const arena = snapshot.observations.find((o) => o.id === "COARENA-O-CUMULATIVE")!;
assert.equal(arena.selection, "historical", "cumulative launch revenue is not a recurring company-wide signal");
assert.equal(arena.comparisonGroup, null);
assert.ok(arena.metric !== "mrr" && arena.metric !== "arr", "a two-week cumulative figure cannot become MRR or ARR");
});
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, 28);
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 7);
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?.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/);
@@ -137,6 +141,43 @@ test("ambiguous ARR claims retain currency, precision and attribution limits", (
assert.equal(snapshot.companies.find((c) => c.id === "AI070")?.revenueStatus, "unknown");
assert.equal(snapshot.observations.filter((o) => o.company === "AI070").length, 0,
"unreadable announcement summaries do not become numeric ARR");
const waitlist = snapshot.observations.find((o) => o.id === "SR25-O-OMI-WAITLIST")!;
assert.equal(waitlist.selection, "excluded", "waitlist conversions are not paid recurring revenue");
assert.equal(snapshot.companies.find((c) => c.id === waitlist.company)?.revenueStatus, "unknown");
const bluma = snapshot.observations.find((o) => o.id === "BLUMA-O-HISTORICAL-MRR")!;
assert.equal(bluma.selection, "historical");
assert.ok(bluma.unit !== "USD" && !bluma.observedAt && bluma.comparisonGroup === null);
const native = snapshot.observations.find((o) => o.id === "NATIVE-O-ARR-CLAIM")!;
assert.equal(native.selection, "crosscheck");
assert.ok(!native.metric && !native.observedAt && native.comparisonGroup === null);
const marketVolume = snapshot.observations.find((o) => o.id === "PALISADE-O-GMV")!;
assert.equal(marketVolume.selection, "excluded", "customer GMV must not establish company revenue or ARR");
assert.equal(snapshot.companies.find((c) => c.id === marketVolume.company)?.revenueStatus, "unknown");
const pingo = snapshot.observations.find((o) => o.id === "PINGO-O-MRR-JUL25")!;
assert.equal(pingo.selection, "historical", "a July 2025 self-report is not a current payment-platform sample");
assert.ok(pingo.unit !== "USD" && !pingo.observedAt && pingo.comparisonGroup === null);
const designService = snapshot.observations.find((o) => o.id === "SEMIOTIC-O-LAUNCH-REVENUE")!;
assert.equal(designService.selection, "historical");
assert.ok(!designService.metric && designService.comparisonGroup === null, "four-week service revenue is not MRR or ARR");
const restaurantAdoption = snapshot.observations.filter((o) => o.company === "YC32815");
assert.ok(restaurantAdoption.length > 0 && restaurantAdoption.every((o) => o.selection === "adoption" && !o.metric),
"restaurant count and list price must not produce an invented MRR observation");
const fishPilot = snapshot.observations.find((o) => o.id === "OCTAPULSE-O-CONTRACT")!;
assert.equal(fishPilot.selection, "excluded", "a paid pilot or annual contract does not establish recognized recurring revenue");
assert.equal(snapshot.companies.find((c) => c.id === fishPilot.company)?.revenueStatus, "unknown");
assert.equal(fishPilot.comparisonGroup, null);
assert.notEqual(fishPilot.unit, "USD", "six-figure wording does not establish the currency");
assert.ok(!fishPilot.metric && !fishPilot.observedAt, "the publication date is not the financial reporting date");
const cedar = snapshot.observations.filter((o) => o.company === "AI102");
assert.ok(cedar.every((o) => o.selection !== "signal" && o.comparisonGroup === null),
"closed and contracted amounts without recognition or period do not establish ARR");
assert.equal(snapshot.observations.find((o) => o.id === "SR25-O-LOOPS-CUSTOMER-SALES")?.selection, "excluded");
const portfolio = snapshot.observations.filter((o) => o.company === "AI100");
assert.deepEqual(portfolio.filter((o) => o.selection === "signal").map((o) => o.id), ["SR25-O-DRS-PORTFOLIO"],
"a product milestone must not be added to its company portfolio as another company");
assert.ok(snapshot.observations.filter((o) => o.id.startsWith("SR25-O-")).every((o) =>
o.unit !== "USD" && !o.metric && !o.observedAt && o.comparisonGroup === null),
"access dates and dollar symbols must not invent dated USD income samples");
});
// Retractions and forecasts must stay visible for review without becoming revenue signals.
@@ -179,8 +220,18 @@ test("directory coverage reconciles every candidate and keeps profile-only incom
assert.ok(company.profileOnly || company.directoryOrigin === "yc-2025-2026");
assert.equal(company.url, row.source);
if (company.profileOnly) assert.equal(company.revenueStatus, "unknown");
assert.equal(company.year, row.foundedYear);
assert.ok([2025, 2026].includes(company.year!));
if (company.id === "YC31370") {
assert.equal(row.foundedYear, 2025, "original discovery remains unchanged");
assert.equal(company.year, null, "a pivot year cannot settle the company founding year");
assert.ok(snapshot.reviews.some((review) => review.id === "DAYJOB-R-COHORT" && review.companyIds?.includes(company.id)));
} else if (company.id === "YC36279") {
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 {
assert.equal(company.year, row.foundedYear);
assert.ok([2025, 2026].includes(company.year!));
}
}
const invalid = structuredClone(snapshot);
invalid.coverage!.newProfiles += 1;
@@ -194,6 +245,20 @@ test("directory coverage reconciles every candidate and keeps profile-only incom
assert.throws(() => validateResearch(lostOrigin), /coverage accounting/);
});
test("business pivots and procurement volume do not become comparable startup ARR", () => {
const snapshot = seed as ResearchSnapshot;
const dayjob = snapshot.companies.find((company) => company.id === "YC31370")!;
assert.equal(dayjob.year, null);
assert.equal(dayjob.directoryOrigin, "yc-2025-2026");
const milestones = snapshot.observations.filter((observation) => observation.company === dayjob.id);
assert.deepEqual(milestones.filter((observation) => observation.selection === "crosscheck").map((observation) => observation.value).sort(), [496000, 653000]);
assert.ok(milestones.every((observation) => observation.comparisonGroup === null && !observation.metric && !observation.observedAt));
assert.ok(milestones.filter((observation) => [150000, 800000].includes(observation.value)).every((observation) => observation.selection === "excluded"));
const procurement = snapshot.observations.find((observation) => observation.id === "SAUDARA-O-SOURCING")!;
assert.equal(procurement.selection, "excluded");
assert.equal(procurement.comparisonGroup, null);
});
test("income descriptions report sample dispersion and maximum-value sensitivity", () => {
const stats = describeIncome([100, 200, 300])!;
assert.equal(stats.mean, 200);
@@ -215,14 +280,21 @@ test("income descriptions report sample dispersion and maximum-value sensitivity
test("platform samples exclude stale data and keep ARR, estimates and collections separate", () => {
const snapshot = seed as ResearchSnapshot;
const recent = platformIncomeSample(snapshot, { windowDays: 7 });
assert.equal(recent.points.length, 14);
assert.equal(recent.excluded.length, 3);
assert.equal(recent.points.length, 16);
assert.equal(recent.excluded.length, 4);
assert.ok(recent.points.every((p) => p.observation.metric === "mrr" && p.observation.selection === "platform"));
assert.deepEqual(new Set(recent.excluded.map((p) => p.observation.company)), new Set(["AI016", "MR013", "MR014"]));
assert.deepEqual(new Set(recent.excluded.map((p) => p.observation.company)), new Set(["AI016", "MR013", "MR014", "MR017"]));
assert.ok(recent.points.some((p) => p.company.name === "TrackAI" && p.observation.connectionExpired), "dated recent value is not a claim of active connection");
const older = platformIncomeSample(snapshot, { windowDays: 90 });
assert.equal(older.points.length, 15);
assert.equal(older.points.length, 18);
assert.ok(older.points.some((p) => p.company.id === "AI016"));
assert.ok(!recent.points.some((p) => p.company.id === "MR017"));
assert.ok(older.points.some((p) => p.company.id === "MR017" && p.observation.connectionExpired),
"an expired connection retains its historical observation date in the wider window");
assert.equal(recent.points.find((p) => p.company.id === "MR018")?.value, 67864,
"an older Markdown cache must not replace or duplicate the later web snapshot");
assert.equal(recent.points.find((p) => p.company.id === "MR019")?.value, 65431,
"period-table revenue and revenue snapshots must not replace MRR");
const scaled = platformIncomeSample(snapshot, { windowDays: 7, annualize: true });
const monthlyGroups = groupIncome(recent.points);
const annualGroups = groupIncome(scaled.points);
@@ -307,7 +379,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, 10);
assert.equal(snapshot.candidateBatches!.flatMap((b) => b.records).filter((r) => r.status === "pending-year").length, 18);
});
test("product pivots and founder histories do not become new company years or current revenue", () => {
@@ -320,6 +392,15 @@ test("product pivots and founder histories do not become new company years or cu
assert.equal(candidate.companyId, pivot.id);
assert.ok(!platformIncomeSample(snapshot, { windowDays: null }).points.some((point) => point.company.id === pivot.id));
assert.ok(!snapshot.observations.some((o) => ["PH-FUNDRAISLY-ABOUT", "LF-PIVOT", "LF-HISTORY"].includes(o.evidence)), "other ventures' ARR, users and funding must not transfer");
const candidates = snapshot.candidateBatches!.flatMap((b) => b.records);
assert.equal(candidates.find((r) => r.id === "PH26-12")?.status, "outside-cohort",
"a brand iteration with an earlier business chain is not a new company");
const happycapy = candidates.find((r) => r.id === "PH26-04")!;
assert.ok(happycapy.evidenceIds?.includes("FOLLOWUP-CAPY-ACRA"));
assert.equal(happycapy.status, "pending-year", "a seller's registration does not establish a new global business");
assert.equal(happycapy.companyId, undefined);
assert.ok(!snapshot.observations.some((o) => o.evidence.startsWith("FOLLOWUP-")),
"registration, funding, app-store prices and client amounts are not company income");
});
test("follow-up evidence can admit an uncertain directory candidate without rewriting its original status", () => {
File diff suppressed because it is too large Load Diff
+14 -14
View File
@@ -1,5 +1,5 @@
{
"version": "2026-10-30-29",
"version": "2026-10-31-1",
"scopeConfirmedAt": "2026-10-30",
"acceptance": "以确认的公开来源清单为边界,逐条核对并标明缺项。",
"provenance": "S01—S12恢复自已提交用户的《AI公司研究_来源与分类模板》来源清单;S13—S16单列后续已使用的补充证据渠道,不将使用次数当作全量覆盖。",
@@ -15,7 +15,7 @@
],
"initialAccess": "官网目录可访问",
"boundary": "已读取八个2025—2026批次镜像候选池1428条,再核YC官方页面;不声称覆盖全部YC历年或未公开公司。",
"nextCheck": "原新增目录中22条深化为个案并保留来源;当前基础项175条主营分类人工复核。继续核其余资料与财务缺项,估算、卖家收益展示和数据供给方估价不当公司ARR。",
"nextCheck": "原新增目录中31条深化为个案并保留来源;当前基础项393条主营分类人工复核。本轮23项C06规则初分已读,22项保留、Bluma转创意制作,8项官网资料与Native政府接口缺项分开。软件/人工托管/制作代理及广告预算拆分;Native官网旧经营与YC2026成立冲突,当前year=null,原发现审计保留;2M ARR仅交叉核对。继续核C05/C07及其他非人工资料、主体、技术和财务,不把主营复核当完整来源覆盖。",
"limitation": "批次不等于成立年;不代表全部公司"
},
{
@@ -28,8 +28,8 @@
"techcrunch.com"
],
"initialAccess": "AI栏目可读取",
"boundary": "2026首页定向3项已登记,另从AI第3—4页登记5项:3项关联公司、1项范围外、1项待核;不等全部卡片核验。另已读2025年度档案入口与AI第二页,并完整登记一篇2025企业竞赛名单32项:复用1项、范围外29项、待核2项;每项均尝试原始链接,未知与不可读保留。单篇32项不等全部200参赛者、全部分页或两年全量;RSS/API普通请求受限。 另从AI第5—6页定向4项:2项原始资料归范围外,2项原始成立/年份待核;不是全部卡片、参赛者或档案。",
"nextCheck": "继续核本篇2项的成立、主体及AI主营,优先解决Billow批次与发现年份时序、Sponstar原始年份冲突;既有业务的法律沿革及不可读项仍留缺;沿普通2025档案和AI分页扩展其余来源台账,区分参赛年、批次与公司成立年。 继续核Laplace原始年份及Eka精确注册主体;Recursive的2025/2026年份冲突保留。 继续核Honeyjar主字段与转载的年份差异、Blueprints原始可读资料与旧建筑业务主体;不把包价、演示金额或建设项目价值当ARR。",
"boundary": "2026首页定向3项已登记,另从AI第3—4页登记5项:3项关联公司、1项范围外、1项待核;不等全部卡片核验。另已读2025年度档案入口与AI第二页,并完整登记一篇2025企业竞赛名单32项:复用1项、范围外29项、待核2项;每项均尝试原始链接,未知与不可读保留。单篇32项不等全部200参赛者、全部分页或两年全量;RSS/API普通请求受限。 另从AI第5—6页定向4项:2项原始资料归范围外,2项原始成立/年份待核;不是全部卡片、参赛者或档案。 首次登记2025政府/法律名单正文11项(标题称10)时:7项范围外或既有业务、4项成立/主体待核;当时未新增主公司或ARR,非全部200或两年档案。 另将2025金融/地产名单14项全部登记:11项范围外/既有业务,3项年份/主体/AI待核;不新增公司或收入,不等其余竞赛类别。 另将2025生物技术名单9项全部登记:8项范围外或既有业务,1项产品与主体对应待核;不新增公司或收入,非全部竞赛类别。 后续补证:政府/法律名单Aparti关联2025主公司,Pytho按既有业务排除;该11项现1关联、8范围外、2待核,原始访问记录保留。",
"nextCheck": "继续核本篇2项的成立、主体及AI主营,优先解决Billow批次与发现年份时序、Sponstar原始年份冲突;既有业务的法律沿革及不可读项仍留缺;沿普通2025档案和AI分页扩展其余来源台账,区分参赛年、批次与公司成立年。 继续核Laplace原始年份及Eka精确注册主体;Recursive的2025/2026年份冲突保留。 继续核Honeyjar主字段与转载的年份差异、Blueprints原始可读资料与旧建筑业务主体;不把包价、演示金额或建设项目价值当ARR。 本篇待核Aparti精确注册、JustiGuide的2024/2026语义、orchestraos主体与年份及Pytho原始登记;补其余竞赛类别和年度档案,不用同名链接替代核查。 补ticker原始可读页面、Investwise主营及主体、Soundspace成立与AI实际交付;保留Genia结果收费与首页套餐的合同缺项,不把交易、返佣或客户资产年化为ARR。 补Avara可读条款和Lumos登记号对应、其他生物技术候选的AI实际作用及地域主体链;研发、临床、审批计划和药企赞助与当前商业收入分开。 Aparti已补公司自述成立,精确注册/付费及Amie收入仍待核;Pytho已由官网链接原始采访补范围外,不再列年份待核,精确注册留缺。",
"limitation": "需追溯原始披露,部分文章受访问限制",
"accessRecheckedAt": "2026-10-30"
},
@@ -44,7 +44,7 @@
"app.dealroom.co"
],
"initialAccess": "官网可读取",
"boundary": "已读Tana、Wabi及Laplace公开公司档案:Tana财务字段不一致留缺,Wabi2025字段与官方业务关联入表,Laplace未取得成立字段而保留候选;尚未取得两年成立筛选结果集,三个个案不等目录全量。",
"boundary": "已读Tana、Wabi及Laplace公开公司档案:Tana财务字段不一致留缺,Wabi2025字段与官方业务关联入表,Laplace未取得成立字段而保留候选;尚未取得两年成立筛选结果集,三个个案不等目录全量。 另读取Aparti公开档案并以公司自述成立关联;四个个案仍不等两年筛选全集,AI生成简介、上线与融资估值分开。",
"nextCheck": "确认公开可取得的两年成立筛选清单;逐项追溯财务原始凭证及字段口径,受权限限制保留缺项。",
"limitation": "完整档案需权限;概览及财务表不能未经勾稽直接导入ARR",
"accessRecheckedAt": "2026-10-30"
@@ -60,8 +60,8 @@
"producthunt.com"
],
"initialAccess": "官网可读取",
"boundary": "两年公开响应各19条,共38条。当前5条关联公司、2条范围外对照、25条范围外/既有业务、4条年份待核、2条推广。旧版本、品牌与法律主体分开,Tapflow据2024原版记录排除,Happycapy仍待核;非两年全量。",
"nextCheck": "继续补两年其余分页/日期、仅图片位置及4条年份待核候选;保留Pazi日期冲突,核清品牌与主体,避免转移历史业绩。",
"boundary": "两年公开响应各19条,共38条。当前5条关联公司、2条范围外对照、26条范围外/既有业务、3条年份待核、2条推广。旧版本、品牌与法律主体分开,Tapflow据2024原版记录排除,Happycapy仍待核;非两年全量。 Pazi补既有业务链后范围外,保留字段冲突;Happycapy iOS销售方与ACRA注册日已核,全球产品/旧业务沿革仍待核。",
"nextCheck": "继续补两年其余分页/日期、仅图片位置及3条年份待核候选;保留Pazi日期冲突与旧业务排除依据,核清其余品牌与主体,避免转移历史业绩。 Happycapy的新加坡销售法人不自动等新创业;继续补网页签约方与集团业务沿革。",
"limitation": "上线时间不等于成立时间",
"accessRecheckedAt": "2026-10-30"
},
@@ -221,8 +221,8 @@
"eu.36kr.com"
],
"initialAccess": "安全检测,内容未核验",
"boundary": "此前首页安全检测仍保留;本轮4项定向检索及相关段落补查,3项据政府/公司/交易当事方资料关联、1项按原始登记归范围外。清析检索与直达正文不一致未确认关联,其他文章为平台发布/授权转载,不代表两年全量。",
"nextCheck": "墨甲已由交易当事方原始公告补足2025成立及历史期间收入,母公司项目沿革和当前财务仍待核;继续补清析发现文章关联及未读正文,建两年公开文章台账,不绕过访问保护。",
"boundary": "此前首页安全检测仍保留;本轮4项定向检索及相关段落补查,3项据政府/公司/交易当事方资料关联、1项按原始登记归范围外。清析检索与直达正文不一致未确认关联,其他文章为平台发布/授权转载,不代表两年全量。 另登记合木、昆腾动力、寰宇心生3项报道相关段落,原始成立/主体留缺,未新增主公司表;不是全量。",
"nextCheck": "墨甲已由交易当事方原始公告补足2025成立及历史期间收入,母公司项目沿革和当前财务仍待核;继续补清析发现文章关联及未读正文,建两年公开文章台账,不绕过访问保护。 补本组三项公司/孵化/投资原始资料,避免融资与研究院、母体业绩归属混淆。",
"limitation": "仅核具体相关段落,检索和直达差异、转载与原始披露分别记录。",
"accessRecheckedAt": "2026-10-30"
},
@@ -234,7 +234,7 @@
"status": "per-company",
"hosts": [],
"initialAccess": "按公司逐一核验",
"boundary": "公司官网和官方材料逐条绑定证据;不是可预先列尽的全站候选池。",
"boundary": "公司官网和官方材料逐条绑定证据;不是可预先列尽的全站候选池。 定向新增企智芯与九昇智能的2025成立自述及交付资料,精确注册、实际客户与收入未核;两个官网不代表中文公司全集。",
"nextCheck": "核定价、主体、交付与收入定义,自述与独立验证分开。",
"limitation": "自述不等于独立审计"
},
@@ -248,8 +248,8 @@
"trustmrr.com"
],
"initialAccess": "见具体证据访问记录",
"boundary": "已采集产品与支付快照;公开者自选,不是全部商户或独立财务审计。",
"nextCheck": "核同步日、连接失效、支付平台公式及产品/法人归属。",
"boundary": "已采集产品与支付快照;公开者自选,不是全部商户或独立财务审计。 另定向登记LLM Gateway、Gomotion AI(iker)及Promptwise,补官网、条款、公开Markdown与缓存差异;API文档明确USD分单位,未调用认证接口,不等全平台。",
"nextCheck": "核同步日、连接失效、支付平台公式及产品/法人归属。 补网关充值/供应商成本/订阅收入勾稽、Gomotion独立主体与官网、Promptwise期间表和快照窗口;保留过期连接及不同缓存时点,不用当前访问日刷新财务日期。",
"limitation": "来源可读不等于声明已独立验证。"
},
{
@@ -262,8 +262,8 @@
"speedrun.a16z.com"
],
"initialAccess": "见具体证据访问记录",
"boundary": "投资机构公司介绍定向样本,收入数字仍多来自公司。",
"nextCheck": "核币种、相对时间及管线/履历;未读取的页面保持缺项。",
"boundary": "投资机构公司介绍定向样本,收入数字仍多来自公司。 新增8项2026名录定向核查并登记候选台账(7项SR007、Bota SR006),不等全部批次或两年目录。 另登记8项2025年定向公司(SR005一项、SR006五项、SR007两项);动态目录静态仅外壳、浏览器超时,不认定全量。",
"nextCheck": "核币种、相对时间及管线/履历;未读取的页面保持缺项。 区分live ARR、signed/contracted ARR、固定法律承诺费用、管线、目标交易量及客户收益;Nexor原$不自动当USD,财务日历截至日和合同底表留缺。 补Hotbox两个ARR时点、OneGC试点包含关系及律所/平台收入拆分、Omi等待名单付费转化、DRS应用与合并口径、Cedar签约履行和Loops可读官网。",
"limitation": "来源可读不等于声明已独立验证。"
},
{
+52 -28
View File
@@ -1,6 +1,6 @@
{
"sourceVersion": "2026-10-30-tc-p56-1",
"asOf": "2026-10-30",
"sourceVersion": "2026-10-31-sales-models-1",
"asOf": "2026-10-31",
"metric": "platform-mrr-usd",
"sampleUnit": "product-or-business",
"note": "独立Python复算参考值,仅验证样本计算;不是行业估计或财务审计。",
@@ -21,7 +21,9 @@
"MR011",
"MR012",
"MR015",
"MR016"
"MR016",
"MR018",
"MR019"
],
"groups": [
{
@@ -35,7 +37,7 @@
"MR016"
],
"n": 4,
"mean": 34815.0,
"mean": 34815,
"median": 36723.0,
"sampleDeviation": 16334.54845820151,
"cv": 0.46918134304758036,
@@ -50,7 +52,7 @@
"MR001"
],
"n": 1,
"mean": 53101.0,
"mean": 53101,
"median": 53101,
"sampleDeviation": null,
"cv": null,
@@ -65,7 +67,7 @@
"MR002"
],
"n": 1,
"mean": 62423.0,
"mean": 62423,
"median": 62423,
"sampleDeviation": null,
"cv": null,
@@ -79,15 +81,17 @@
"products": [
"MR003",
"MR004",
"MR005"
"MR005",
"MR018",
"MR019"
],
"n": 3,
"mean": 41693.0,
"median": 49069,
"sampleDeviation": 28111.375064197768,
"cv": 0.6742468775141575,
"meanWithoutLargest": 29849.0,
"largestRemovalDrop": 0.2840764636749574
"n": 5,
"mean": 51674.8,
"median": 65381,
"sampleDeviation": 24138.82269705795,
"cv": 0.4671294847209461,
"meanWithoutLargest": 47627.5,
"largestRemovalDrop": 0.07832250923080501
},
{
"category": "C09",
@@ -105,7 +109,7 @@
"median": 20483,
"sampleDeviation": 11942.947278624319,
"cv": 0.4711370488466823,
"meanWithoutLargest": 20046.0,
"meanWithoutLargest": 20046,
"largestRemovalDrop": 0.20920581320120557
}
]
@@ -127,9 +131,27 @@
"MR012",
"MR015",
"MR016",
"AI016"
"AI016",
"MR017",
"MR018",
"MR019"
],
"groups": [
{
"category": "C02",
"provider": "Stripe",
"model": "模型网关订阅与用量",
"products": [
"MR017"
],
"n": 1,
"mean": 78764,
"median": 78764,
"sampleDeviation": null,
"cv": null,
"meanWithoutLargest": null,
"largestRemovalDrop": null
},
{
"category": "C06",
"provider": "Stripe",
@@ -146,7 +168,7 @@
"median": 40112,
"sampleDeviation": 174786.78744916618,
"cv": 1.5505509613536426,
"meanWithoutLargest": 34815.0,
"meanWithoutLargest": 34815,
"largestRemovalDrop": 0.6911526751687284
},
{
@@ -157,7 +179,7 @@
"MR001"
],
"n": 1,
"mean": 53101.0,
"mean": 53101,
"median": 53101,
"sampleDeviation": null,
"cv": null,
@@ -172,7 +194,7 @@
"MR002"
],
"n": 1,
"mean": 62423.0,
"mean": 62423,
"median": 62423,
"sampleDeviation": null,
"cv": null,
@@ -186,15 +208,17 @@
"products": [
"MR003",
"MR004",
"MR005"
"MR005",
"MR018",
"MR019"
],
"n": 3,
"mean": 41693.0,
"median": 49069,
"sampleDeviation": 28111.375064197768,
"cv": 0.6742468775141575,
"meanWithoutLargest": 29849.0,
"largestRemovalDrop": 0.2840764636749574
"n": 5,
"mean": 51674.8,
"median": 65381,
"sampleDeviation": 24138.82269705795,
"cv": 0.4671294847209461,
"meanWithoutLargest": 47627.5,
"largestRemovalDrop": 0.07832250923080501
},
{
"category": "C09",
@@ -212,7 +236,7 @@
"median": 20483,
"sampleDeviation": 11942.947278624319,
"cv": 0.4711370488466823,
"meanWithoutLargest": 20046.0,
"meanWithoutLargest": 20046,
"largestRemovalDrop": 0.20920581320120557
}
]
+22 -3
View File
@@ -89,23 +89,42 @@ def link(cid):
def render():
points, excluded = sample(7)
grouped = groups(points)
described = [(key, stats(values)) for key, values in sorted(grouped.items())]
sizes = [value['n'] for _, value in described]
eligible = [(key, value) for key, value in described if value['n'] >= 3]
interpretation = '各组均不足3个样本,暂不比较分组离散度或收入高低。'
if eligible:
highest_key, highest = max(eligible, key=lambda item: item[1]['mean'])
sensitive_key, sensitive = max(eligible, key=lambda item: item[1]['largestRemovalDrop'] or 0)
cvs = [value['cv'] for _, value in eligible if value['cv'] is not None]
cv_text = f"CV范围为{min(cvs):.3f}—{max(cvs):.3f}。" if cvs else '各组CV均不可计算。'
interpretation = (
f"在至少3个样本的组内,当前均值最高的是{CATEGORIES[highest_key[0]]} · {highest_key[2]}"
f"({highest_key[1]},{money(highest['mean'])}美元每月)。{cv_text}"
f"剔除最大值后均值下降最多的是{CATEGORIES[sensitive_key[0]]} · {sensitive_key[2]}"
f"({sensitive_key[1]},下降{sensitive['largestRemovalDrop'] or 0:.1%})。"
'这些只是当前采集点的描述,不据微小CV差异宣称某领域更稳定。'
)
size_text = f"各组目前只有{min(sizes)}至{max(sizes)}个产品" if sizes else '当前没有可比较的产品'
lines = [
'# AI 公司收入样本分布快照', '',
f"截至 {DATA['asOf']},7日窗口内有 {len(points)} 个产品的美元平台MRR可纳入分组描述。创意软件订阅组的样本均值较高、CV也较大;营销软件组与消费者个人应用组的CV接近。各组只有1至5个产品,尚不足以估计行业总体或造假概率。", '',
f"截至 {DATA['asOf']},7日窗口内有 {len(points)} 个产品的美元平台MRR可纳入分组描述。按业务、支付平台和收费模式分别计算均值、中位数与离散度。{size_text},尚不足以估计行业总体或造假概率。", '',
f"这是已采集资料的固定快照。[动态工作台]({BASE})提供筛选与原始证据。窗口按最后同步日计算,不保证所有点同日,也不是{len(DATA['companies']):,}条公司/产品记录的收入普查。", '',
'## 7日窗口的分组结果', '',
'MRR单位为美元每月。CV为样本标准差除以均值;最大值剔除降幅表示移除最高收入产品后均值下降的比例。单个样本不计算离散度。', '',
'| 业务及收费模式 | 平台 | 样本数 | 均值 | 中位数 | CV | 最大值剔除降幅 |',
'| --- | --- | --- | --- | --- | --- | --- |',
]
for key, values in sorted(groups(points).items()):
for key, values in sorted(grouped.items()):
cat, provider, model = key
v = stats(values)
cv = f"{v['cv']:.3f}" if v['cv'] is not None else '不计算'
drop = f"{v['largestRemovalDrop']:.1%}" if v['largestRemovalDrop'] is not None else '不计算'
lines.append(f"| {CATEGORIES[cat]} · {model} | {provider} | {v['n']} | {money(v['mean'])} | {money(v['median'])} | {cv} | {drop} |")
lines += ['',
'在至少3个样本的组内,内容创意软件订阅的均值较高,但移除最大样本后的下降也最大。营销软件与个人应用的CV仅有微小差别,不据此宣称哪个领域更稳定。两个内容类单样本组虽有更高数值,不能作为典型收入或领域排名。', '',
interpretation, '',
'单个样本不计算离散度,也不能作为典型收入或领域排名;不同收费模式和支付平台的分组保留各自含义。', '',
'均值和中位数接近只描述当前采集点,并不证明样本具有代表性。平台公开者、成立年、规模、获客渠道与收费方式均可能影响结果。', '',
'## 样本与证据入口', '',
'点击产品名称可打开公司明细,再查看平台记录及其限制。连接已过期的近期快照仍按所标日期保留,并不表示连接当前有效。', '',