增加按分类与成立年份浏览的 ARR 披露表
This commit is contained in:
@@ -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>;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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-"));
|
||||
|
||||
@@ -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,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,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",
|
||||
|
||||
Reference in New Issue
Block a user