增加按分类与成立年份浏览的 ARR 披露表

This commit is contained in:
2026-10-31 17:36:03 +08:00
parent 6410535ed9
commit f99a354db2
7 changed files with 141 additions and 32 deletions
@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/router";
import IncomeDistribution from "./IncomeDistribution";
import ArrDisclosures from "./ArrDisclosures";
import {
categorySummary, evidenceUrl, technicalReviewLabels, reviewCompanyIds, type ResearchEvidence, type ResearchReview, type ResearchSnapshot,
} from "@/lib/ai-research";
@@ -154,6 +155,7 @@ export default function AICompanyResearch() {
</>}
{tab === "revenue" && <>
<IncomeDistribution data={data} onSelect={setSelected} />
<ArrDisclosures data={data} onSelect={setSelected} />
<h3>企业披露与估算的历史里程碑</h3>
<p className="research-notice">这一组包含 {disclosedCompanies} 家公司的披露或估算信号;企业披露含公司或交易当事方公开材料,披露主体与审计状态见证据。多为异时点历史里程碑,期间收入不直接年化,ARR 与年化收入口径仍待核对,暂不计算其同期领域均值。币种未确认的记录仅显示原值,不绘制美元长度条。上面的平台MRR统计与这一组分开。</p>
<div className="research-revenue-chart" aria-label="不同时间的公开收入里程碑,线性长度,非同行排名">{observed.map((o) => <div key={o.id}>
@@ -0,0 +1,41 @@
import { useState } from "react";
import { evidenceUrl, type ResearchSnapshot } from "@/lib/ai-research";
import { arrDisclosures } from "@/lib/research-statistics";
const labels: Record<string, string> = {
signal: "企业或当事方披露", estimate: "第三方估算",
historical: "历史披露", "historical-estimate": "历史估算",
};
export default function ArrDisclosures({ data, onSelect }: { data: ResearchSnapshot; onSelect: (id: string) => void }) {
const [category, setCategory] = useState("");
const [year, setYear] = useState("");
const rows = arrDisclosures(data, { category, foundedYear: year ? Number(year) : undefined });
const companies = new Set(rows.map((row) => row.company.id));
const categories = new Map(data.categories.map((item) => [item.id, item.name]));
const evidence = new Map(data.evidence.map((item) => [item.id, item]));
return <section aria-label="ARR披露分类表">
<h3>2025—2026 年成立公司的 ARR 披露</h3>
<p className="research-notice">这是跨时点证据表,共 {companies.size} 家公司、{rows.length} 条记录;同一公司的历史里程碑逐条保留,不能相加或视为独立公司。ARR 标签沿用原始披露,未证明经常性收入定义或审计状态;不纳入 MRR 图表,不计算同期行业均值或造假概率。仅收录明确标注的 ARR;定义冲突、目标、承诺、客户和前雇主收入排除,缺失不作零。</p>
<div className="research-filters">
<label>业务分类<select value={category} onChange={(event) => setCategory(event.target.value)}><option value="">全部分类</option>{data.categories.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}</select></label>
<label>成立年份<select value={year} onChange={(event) => setYear(event.target.value)}><option value="">2025 与 2026</option><option value="2025">2025</option><option value="2026">2026</option></select></label>
</div>
<div className="research-table-wrap"><table>
<caption>金额保留原币种、下界和估算身份;日期栏保留业务截至日缺项</caption>
<thead><tr><th>公司 / 分类</th><th>收费与交付模式</th><th>原始 ARR 声明</th><th>时点</th><th>身份 / 限制</th><th>证据</th></tr></thead>
<tbody>{rows.map(({ company, observation: item }) => {
const source = evidence.get(item.evidence);
const url = source && evidenceUrl(source.url);
return <tr key={item.id}>
<td><button onClick={() => onSelect(company.id)}>{company.name}</button><small>{categories.get(company.cat)} · {company.year}</small></td>
<td>{company.businessModel ?? company.price}</td>
<td>{item.bound !== "=" && item.bound}{new Intl.NumberFormat("zh-CN", { maximumFractionDigits: 2 }).format(item.value)} {item.unit}<small>{item.kind}</small></td>
<td>{item.timing}</td><td>{labels[item.selection]}<small>{item.reason}</small></td>
<td>{url ? <a href={url} target="_blank" rel="noopener noreferrer">{item.evidence} ↗</a> : item.evidence}</td>
</tr>;
})}</tbody>
</table></div>
{!rows.length && <p>当前筛选没有符合条件的已记录 ARR 声明;不代表这些公司收入为零。</p>}
</section>;
}
+14
View File
@@ -1,6 +1,20 @@
import type { ResearchCompany, ResearchObservation, ResearchSnapshot } from "./ai-research";
export type IncomePoint = { company: ResearchCompany; observation: ResearchObservation; value: number };
/** An evidence ledger, never a comparable sample: retain historical claims and estimates separately. */
export function arrDisclosures(snapshot: ResearchSnapshot, options: { category?: string; foundedYear?: number } = {}) {
const companies = new Map(snapshot.companies.map((company) => [company.id, company]));
return snapshot.observations.flatMap((observation) => {
const company = companies.get(observation.company);
if (!company || ![2025, 2026].includes(company.year ?? 0) || observation.metric !== "arr" ||
!["signal", "estimate", "historical", "historical-estimate"].includes(observation.selection) ||
!Number.isFinite(observation.value) || observation.value < 0 ||
(options.category && company.cat !== options.category) ||
(options.foundedYear && company.year !== options.foundedYear)) return [];
return [{ company, observation }];
});
}
export type IncomeStats = {
n: number; mean: number; median: number; min: number; max: number;
sampleDeviation: number | null; cv: number | null; meanMedianRatio: number | null;
+25 -1
View File
@@ -11,7 +11,31 @@ import { openSiteDatabase } from "../src/lib/site-database";
import { categorySummary, evidenceUrl, reviewCompanyIds, validateResearch, type ResearchSnapshot } from "../src/lib/ai-research";
import { consumeCode, initializeStore } from "../src/lib/auth-store";
import { newAuthConfig } from "../src/lib/auth";
import { describeIncome, groupIncome, platformIncomeSample } from "../src/lib/research-statistics";
import { arrDisclosures, describeIncome, groupIncome, platformIncomeSample } from "../src/lib/research-statistics";
test("ARR ledger preserves historical estimates without promoting targets, run rates or outside-cohort claims", () => {
const snapshot = structuredClone(seed) as ResearchSnapshot;
const rows = arrDisclosures(snapshot);
const ids = new Set(rows.map((row) => row.observation.id));
for (const id of ["O064", "O065", "O066", "O069", "O070", "O071", "O046"])
assert.ok(ids.has(id), `${id}: historical claims, estimates and unknown currencies remain visible`);
for (const id of ["O050", "O052", "O053", "O055", "SR-O-AI067-runrate", "ROCKET-O-arr", "AQ-O-RUNRATE"])
assert.ok(!ids.has(id), `${id}: excluded or ambiguous records cannot enter the ARR ledger`);
assert.equal(rows.find((row) => row.observation.id === "O066")?.observation.selection, "historical-estimate");
assert.equal(rows.find((row) => row.observation.id === "O046")?.observation.unit, "原文$,币种待核");
const category = snapshot.companies.find((company) => company.id === "AI055")!.cat;
const filtered = arrDisclosures(snapshot, { category, foundedYear: 2025 });
assert.ok(filtered.length > 0);
assert.ok(filtered.every((row) => row.company.cat === category && row.company.year === 2025));
// A future mistakenly typed target still must not enter the ledger.
const target = snapshot.observations.find((item) => item.id === "O052")!;
target.metric = "arr";
target.company = "AI055";
assert.ok(!arrDisclosures(snapshot).some((row) => row.observation.id === target.id));
const claim = snapshot.observations.find((item) => item.id === "O065")!;
claim.value = Number.NaN;
assert.ok(!arrDisclosures(snapshot).some((row) => row.observation.id === claim.id));
});
test("research revisions share the authentication database and preserve replay limits", () => {
const dir = mkdtempSync(join(tmpdir(), "site-research-"));
+57 -29
View File
@@ -1,5 +1,5 @@
{
"version": "2026-10-31-tc-consumer-1",
"version": "2026-10-31-arr-types-1",
"asOf": "2026-10-31",
"scope": "全球公开资料研究:保留首批个案,并扩展核查2025—2026八个YC批次候选池;成立年份以官方公司页面字段为依据。",
"limitations": [
@@ -36576,7 +36576,8 @@
"selection": "signal",
"reason": "统计时点未知,不进入同期ARR排名",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O044",
@@ -36591,7 +36592,8 @@
"selection": "historical",
"reason": "保留历史里程碑,不与250万美元重复计公司",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O045",
@@ -36606,7 +36608,8 @@
"selection": "signal",
"reason": "统计时点未知,经常性定义待核",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O046",
@@ -36621,7 +36624,8 @@
"selection": "signal",
"reason": "投资方资料使用$但未明确USD;更正旧币种推断,未经审计且无具体日历截至日,不进同期比较",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O047",
@@ -36636,7 +36640,8 @@
"selection": "signal",
"reason": "创始人自述,保留时点不确定性",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O048",
@@ -36892,7 +36897,8 @@
"selection": "historical",
"reason": "较早披露,保留历史;超过值不当作精确值",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O065",
@@ -36907,7 +36913,8 @@
"selection": "signal",
"reason": "本轮有明确公告时点的公司美元披露;招聘另有1500万声明但币种与业务截止日待核,非当前10月值",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O066",
@@ -36922,7 +36929,8 @@
"selection": "historical-estimate",
"reason": "后续估算单列,不覆盖公司披露",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O067",
@@ -36967,7 +36975,8 @@
"selection": "historical",
"reason": "非2025年末指标;保留历史",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O070",
@@ -36982,7 +36991,8 @@
"selection": "historical",
"reason": "近似值;后有新披露",
"bound": "≈",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O071",
@@ -36997,7 +37007,8 @@
"selection": "signal",
"reason": "媒体转述,未审计;已收购业务单列",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O072",
@@ -37027,7 +37038,8 @@
"selection": "signal",
"reason": "投资机构资料,含义及经常性待确认",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "O074",
@@ -38058,7 +38070,8 @@
"selection": "signal",
"reason": "历史自述,非公告时点当前值;经常性定义与留存待核验",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "RUN-O-FUND",
@@ -38133,7 +38146,8 @@
"selection": "signal",
"reason": "私测三周里程碑,币种与日期未核;不是当前统一时点值",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR-O-AI063-pipeline",
@@ -38163,7 +38177,8 @@
"selection": "signal",
"reason": "前11周里程碑,日期及币种未核",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR-O-AI065-arr",
@@ -38178,7 +38193,8 @@
"selection": "signal",
"reason": "仅表示原文七位数的数量级下界,非精确100万;上界小于1000万,币种与合同口径未知",
"bound": "≥",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR-O-AI065-impact",
@@ -38283,7 +38299,8 @@
"selection": "signal",
"reason": "约五个月后的历史披露下界,币种与日期未核",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR-O-AI068-early",
@@ -38298,7 +38315,8 @@
"selection": "historical",
"reason": "同一公司较早阶段,不作第二家公司或第二笔收入",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR-O-AI068-customers",
@@ -38328,7 +38346,8 @@
"selection": "signal",
"reason": "两周里程碑;日期、币种和经常性定义未核",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "TECH-GRAD-O-elo",
@@ -38388,7 +38407,8 @@
"selection": "historical",
"reason": "转型产品历史里程碑,不能视为前身全部业务或2026当前公司ARR",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "ROCKET-O-subscribers",
@@ -38980,7 +39000,8 @@
"selection": "historical",
"reason": "招聘自述非独立审计;不由发布日期推业务时点,不与Sacra估算合并或作为同期美元ARR",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "PEEC-JOB-TEAM",
@@ -39101,7 +39122,8 @@
"selection": "signal",
"reason": "推出8周里程碑,具体截至日、币种、硬件/项目/运维经常性分摊未核",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR26-O-LAZYWEB-ARR",
@@ -39116,7 +39138,8 @@
"selection": "signal",
"reason": "推出两个月相对里程碑;币种、日历时点、折扣退款与订阅合同未核,不进同期比较",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR26-O-BOTA-CARR",
@@ -39176,7 +39199,8 @@
"selection": "signal",
"reason": "三周里程碑的下界;合同、币种及具体截至日未知;试点和管线不直接算ARR",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR26-O-PREMAN-ARR",
@@ -39191,7 +39215,8 @@
"selection": "signal",
"reason": "未给财务截至日、币种与订阅定义;不把创始人旧Surt AI收入归PreMan",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "DAYJOB-O-ARR-LAUNCH",
@@ -39371,7 +39396,8 @@
"selection": "signal",
"reason": "当前公司三应用合计自述,收入是否扣平台费、币种与时点未核",
"bound": "=",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR25-O-DRS-SECOND-APP",
@@ -39431,7 +39457,8 @@
"selection": "signal",
"reason": "履历明确指当前Loops,仍为自述;币种、具体截至日及软件/部署费拆分未核",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "SR25-O-LOOPS-CUSTOMER-SALES",
@@ -39461,7 +39488,8 @@
"selection": "signal",
"reason": "公司发布自述,软件与定制部署/服务收入未拆;品牌/法律主体边界、币种和合同底表待核,不进入同期比较",
"bound": ">",
"comparisonGroup": null
"comparisonGroup": null,
"metric": "arr"
},
{
"id": "MR2-O-LLM-MRR",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"version": "2026-10-31-tc-consumer-1",
"version": "2026-10-31-arr-types-1",
"scopeConfirmedAt": "2026-10-30",
"acceptance": "以确认的公开来源清单为边界,逐条核对并标明缺项。",
"provenance": "S01—S12恢复自已提交用户的《AI公司研究_来源与分类模板》来源清单;S13—S16单列后续已使用的补充证据渠道,不将使用次数当作全量覆盖。",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"sourceVersion": "2026-10-31-tc-consumer-1",
"sourceVersion": "2026-10-31-arr-types-1",
"asOf": "2026-10-31",
"metric": "platform-mrr-usd",
"sampleUnit": "product-or-business",