扩展中英文 AI 公司分类与收入核查 #29
@@ -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, 1023);
|
||||
assert.equal(research.companies.length, 1029);
|
||||
assert.equal(research.categories.length, 11);
|
||||
assert.equal(research.evidence.length, 1318);
|
||||
assert.equal(research.observations.length, 189);
|
||||
assert.equal(research.evidence.length, 1412);
|
||||
assert.equal(research.observations.length, 192);
|
||||
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);
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
|
||||
const pageSize = 12;
|
||||
const evidencePageSize = 30;
|
||||
const revenueLabels = { self: "公司披露,待核口径", estimate: "仅第三方估算", platform: "仅支付平台记录", unknown: "暂无可用收入数字" };
|
||||
const revenueLabels = { self: "企业披露,待核口径", estimate: "仅第三方估算", platform: "仅支付平台记录", unknown: "暂无可用收入数字" };
|
||||
const useLabels: Record<string, string> = {
|
||||
platform: "支付平台记录", signal: "公司披露信号", estimate: "第三方估算", historical: "历史里程碑",
|
||||
platform: "支付平台记录", signal: "企业披露信号", estimate: "第三方估算", historical: "历史里程碑",
|
||||
"historical-estimate": "其他时点估算", excluded: "排除收入比较", scale: "团队规模", adoption: "采用规模",
|
||||
funding: "融资", technical: "第三方技术评测", crosscheck: "同一里程碑的其他资料",
|
||||
};
|
||||
@@ -138,7 +138,7 @@ export default function AICompanyResearch() {
|
||||
<label>资料深度<select value={depth} onChange={(e) => { setDepth(e.target.value); setPage(0); }}><option value="">全部资料</option><option value="case">原有个案研究</option><option value="profile">目录基础资料</option></select></label>
|
||||
<label>记录团队规模<select value={teamBand} onChange={(e) => { setTeamBand(e.target.value); setPage(0); }}><option value="">全部规模</option><option value="small">1—5 人</option><option value="medium">6—20 人</option><option value="large">21—50 人</option><option value="xl">至少 51 人</option><option value="unknown">未披露或分组不确定</option></select></label>
|
||||
<label>技术验证证据<select value={technicalLevel} onChange={(e) => { setTechnicalLevel(e.target.value); setPage(0); }}><option value="">全部验证层级</option>{Object.entries(technicalReviewLabels).map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
|
||||
<label>收入资料<select value={income} onChange={(e) => { setIncome(e.target.value); setPage(0); }}><option value="">全部状态</option><option value="self">找到公司披露</option><option value="estimate">仅第三方估算</option><option value="platform">仅支付平台记录</option><option value="unknown">暂无可用数字</option></select></label>
|
||||
<label>收入资料<select value={income} onChange={(e) => { setIncome(e.target.value); setPage(0); }}><option value="">全部状态</option><option value="self">找到企业披露</option><option value="estimate">仅第三方估算</option><option value="platform">仅支付平台记录</option><option value="unknown">暂无可用数字</option></select></label>
|
||||
</div>
|
||||
<p className="research-muted">技术验证层级记录我们查到了什么,不是能力强弱评分。技术专项评审与业务分类复核分别记录。</p>
|
||||
<div className="research-result-count" role="status">{filtered.length} 条匹配记录<button onClick={() => { setCategory(""); setQuery(""); setCohort(""); setIncome(""); setDepth(""); setTeamBand(""); setTechnicalLevel(""); setPage(0); }}>清除筛选</button></div>
|
||||
@@ -154,14 +154,14 @@ export default function AICompanyResearch() {
|
||||
</>}
|
||||
{tab === "revenue" && <>
|
||||
<IncomeDistribution data={data} onSelect={setSelected} />
|
||||
<h3>公司披露与估算的历史里程碑</h3>
|
||||
<p className="research-notice">这一组包含 {disclosedCompanies} 家公司的披露或估算信号,多为异时点历史里程碑,ARR 与年化收入口径仍待核对,暂不计算其同期领域均值。币种未确认的记录仅显示原值,不绘制美元长度条。上面的平台MRR统计与这一组分开。</p>
|
||||
<h3>企业披露与估算的历史里程碑</h3>
|
||||
<p className="research-notice">这一组包含 {disclosedCompanies} 家公司的披露或估算信号;企业披露含公司或交易当事方公开材料,披露主体与审计状态见证据。多为异时点历史里程碑,期间收入不直接年化,ARR 与年化收入口径仍待核对,暂不计算其同期领域均值。币种未确认的记录仅显示原值,不绘制美元长度条。上面的平台MRR统计与这一组分开。</p>
|
||||
<div className="research-revenue-chart" aria-label="不同时间的公开收入里程碑,线性长度,非同行排名">{observed.map((o) => <div key={o.id}>
|
||||
<div><button onClick={() => setSelected(o.company)}>{o.name}</button><strong>{o.bound !== "=" && o.bound}{money(o.value, o.unit)}</strong></div>
|
||||
{o.unit === "USD" && <span className="research-bar" data-estimate={o.selection === "estimate" || undefined} aria-hidden="true"><i style={{width: `${o.value / Math.max(1, ...observed.filter((v) => v.unit === "USD").map((v) => v.value)) * 100}%`}} /></span>}
|
||||
<small>{o.kind} · {useLabels[o.selection]} · {o.timing}</small>
|
||||
</div>)}</div>
|
||||
<div className="research-table-wrap"><table><caption>当前研究数据中的收入可得性,目录项未逐一检索;未建立同期、同龄、同口径比较组</caption><thead><tr><th>业务分类</th><th>公司披露数</th><th>仅估算数</th><th>仅平台数</th><th>暂无可用数字</th><th>同期均值 / 离散度</th></tr></thead><tbody>{summaries.map((c) => <tr key={c.id}><td><button onClick={() => chooseCategory(c.id)}>{c.name}</button></td><td>{c.self}</td><td>{c.estimate}</td><td>{c.platform}</td><td>{c.unknown}</td><td>条件不足</td></tr>)}</tbody></table></div>
|
||||
<div className="research-table-wrap"><table><caption>当前研究数据中的收入可得性,目录项未逐一检索;未建立同期、同龄、同口径比较组</caption><thead><tr><th>业务分类</th><th>企业披露数</th><th>仅估算数</th><th>仅平台数</th><th>暂无可用数字</th><th>同期均值 / 离散度</th></tr></thead><tbody>{summaries.map((c) => <tr key={c.id}><td><button onClick={() => chooseCategory(c.id)}>{c.name}</button></td><td>{c.self}</td><td>{c.estimate}</td><td>{c.platform}</td><td>{c.unknown}</td><td>条件不足</td></tr>)}</tbody></table></div>
|
||||
<p className="research-muted">离散度用于筛选值得核查的异常,还需排除公司年龄、口径和披露偏差;不能据此认定财务造假。</p>
|
||||
</>}
|
||||
{tab === "sources" && <><p className="research-muted">来源链接保留原始位置。相同 URL 的记录可能属于同一披露,不能按记录数计算独立证据数量。</p><ul className="research-evidence-list">{data.evidence.slice(sourcePage * evidencePageSize, (sourcePage + 1) * evidencePageSize).map((e) => <Evidence key={e.id} item={e} />)}</ul>{data.evidence.length > evidencePageSize && <nav className="research-pagination" aria-label="原始证据分页"><button disabled={sourcePage === 0} onClick={() => setSourcePage((n) => n - 1)}>上一页</button><span>{sourcePage + 1} / {Math.ceil(data.evidence.length / evidencePageSize)}</span><button disabled={(sourcePage + 1) * evidencePageSize >= data.evidence.length} onClick={() => setSourcePage((n) => n + 1)}>下一页</button></nav>}</>}
|
||||
|
||||
@@ -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, 1023);
|
||||
assert.equal(initial.evidence.length, 1318);
|
||||
assert.equal(initial.observations.length, 189);
|
||||
assert.equal(initial.companies.length, 1029);
|
||||
assert.equal(initial.evidence.length, 1412);
|
||||
assert.equal(initial.observations.length, 192);
|
||||
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, 60);
|
||||
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, 31);
|
||||
assert.equal(snapshot.reviews.filter((r) => r.scope === "excluded-candidate").length, 37);
|
||||
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,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), 1023);
|
||||
assert.equal(summary.reduce((n, c) => n + c.self, 0), 26);
|
||||
assert.equal(summary.reduce((n, c) => n + c.estimate, 0), 1);
|
||||
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.estimate, 0), 2);
|
||||
assert.equal(summary.reduce((n, c) => n + c.platform, 0), 16);
|
||||
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 980);
|
||||
assert.equal(summary.reduce((n, c) => n + c.unknown, 0), 983);
|
||||
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 === "公司整体"));
|
||||
@@ -97,8 +97,8 @@ test("disclosure counts exclude client income, biographies, targets and duplicat
|
||||
|
||||
test("technical reviews keep accessible materials separate from tested capabilities", () => {
|
||||
const snapshot = structuredClone(seed) as ResearchSnapshot;
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview).length, 16);
|
||||
assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 6);
|
||||
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?.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/);
|
||||
@@ -307,7 +307,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, 11);
|
||||
assert.equal(snapshot.candidateBatches!.flatMap((b) => b.records).filter((r) => r.status === "pending-year").length, 10);
|
||||
});
|
||||
|
||||
test("product pivots and founder histories do not become new company years or current revenue", () => {
|
||||
|
||||
+2159
-149
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "2026-10-30-22",
|
||||
"version": "2026-10-30-29",
|
||||
"scopeConfirmedAt": "2026-10-30",
|
||||
"acceptance": "以确认的公开来源清单为边界,逐条核对并标明缺项。",
|
||||
"provenance": "S01—S12恢复自已提交用户的《AI公司研究_来源与分类模板》来源清单;S13—S16单列后续已使用的补充证据渠道,不将使用次数当作全量覆盖。",
|
||||
@@ -15,7 +15,7 @@
|
||||
],
|
||||
"initialAccess": "官网目录可访问",
|
||||
"boundary": "已读取八个2025—2026批次镜像候选池1428条,再核YC官方页面;不声称覆盖全部YC历年或未公开公司。",
|
||||
"nextCheck": "当前快照三条原待分类经官网方向补证归类;继续复核规则初分、具体产品与财务缺项,不把领域粗分类当独立能力或收入验证。",
|
||||
"nextCheck": "原新增目录中22条深化为个案并保留来源;当前基础项175条主营分类人工复核。继续核其余资料与财务缺项,估算、卖家收益展示和数据供给方估价不当公司ARR。",
|
||||
"limitation": "批次不等于成立年;不代表全部公司"
|
||||
},
|
||||
{
|
||||
@@ -28,8 +28,8 @@
|
||||
"techcrunch.com"
|
||||
],
|
||||
"initialAccess": "AI栏目可读取",
|
||||
"boundary": "2026首页定向3项已登记。另已读2025年度档案入口与AI第二页,并完整登记一篇2025企业竞赛名单32项:复用1项、范围外25项、待核6项;每项均尝试原始链接,未知与不可读保留。单篇32项不等全部200参赛者、全部分页或两年全量;RSS/API普通请求受限。",
|
||||
"nextCheck": "继续核本篇6项的成立、主体及AI主营,优先解决Sponstar原始年份冲突、域名更名与不可读项;沿普通2025档案和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。",
|
||||
"limitation": "需追溯原始披露,部分文章受访问限制",
|
||||
"accessRecheckedAt": "2026-10-30"
|
||||
},
|
||||
@@ -44,7 +44,7 @@
|
||||
"app.dealroom.co"
|
||||
],
|
||||
"initialAccess": "官网可读取",
|
||||
"boundary": "已读Tana与Wabi公开公司档案:前者财务字段不一致留缺,后者2025成立字段与官方业务关联入表;尚未取得两年成立筛选结果集,两个个案不等于目录全量。",
|
||||
"boundary": "已读Tana、Wabi及Laplace公开公司档案:Tana财务字段不一致留缺,Wabi2025字段与官方业务关联入表,Laplace未取得成立字段而保留候选;尚未取得两年成立筛选结果集,三个个案不等目录全量。",
|
||||
"nextCheck": "确认公开可取得的两年成立筛选清单;逐项追溯财务原始凭证及字段口径,受权限限制保留缺项。",
|
||||
"limitation": "完整档案需权限;概览及财务表不能未经勾稽直接导入ARR",
|
||||
"accessRecheckedAt": "2026-10-30"
|
||||
@@ -214,15 +214,16 @@
|
||||
"name": "36氪",
|
||||
"url": "https://www.36kr.com/",
|
||||
"role": "reporting",
|
||||
"status": "access-limited",
|
||||
"status": "targeted",
|
||||
"hosts": [
|
||||
"www.36kr.com",
|
||||
"36kr.com"
|
||||
"36kr.com",
|
||||
"eu.36kr.com"
|
||||
],
|
||||
"initialAccess": "安全检测,内容未核验",
|
||||
"boundary": "2026-10-30仍返回安全检测页面,未把首页作为已读文章。",
|
||||
"nextCheck": "使用可公开读取的具体文章或其他原始来源;不绕过访问保护。",
|
||||
"limitation": "暂不作为已读取内容证据",
|
||||
"boundary": "此前首页安全检测仍保留;本轮4项定向检索及相关段落补查,3项据政府/公司/交易当事方资料关联、1项按原始登记归范围外。清析检索与直达正文不一致未确认关联,其他文章为平台发布/授权转载,不代表两年全量。",
|
||||
"nextCheck": "墨甲已由交易当事方原始公告补足2025成立及历史期间收入,母公司项目沿革和当前财务仍待核;继续补清析发现文章关联及未读正文,建两年公开文章台账,不绕过访问保护。",
|
||||
"limitation": "仅核具体相关段落,检索和直达差异、转载与原始披露分别记录。",
|
||||
"accessRecheckedAt": "2026-10-30"
|
||||
},
|
||||
{
|
||||
@@ -285,9 +286,11 @@
|
||||
"url": null,
|
||||
"role": "supplement",
|
||||
"status": "targeted",
|
||||
"hosts": [],
|
||||
"hosts": [
|
||||
"getlatka.com"
|
||||
],
|
||||
"initialAccess": "见具体证据访问记录",
|
||||
"boundary": "未归入上述来源的公开材料按原始证据链接逐条保留;不视为新增已批准的完整候选池。",
|
||||
"boundary": "未归入上述来源的公开材料按原始证据链接逐条保留;不视为新增已批准的完整候选池。 本轮读取GetLatka单页历史年收入估算,方法底表未取得,不视为新增完整候选池。",
|
||||
"nextCheck": "逐项核来源归属、可靠性及可读正文,不能将搜索摘要当全文。",
|
||||
"limitation": "来源可读不等于声明已独立验证。"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"sourceVersion": "2026-10-30-battlefield-3",
|
||||
"sourceVersion": "2026-10-30-tc-p56-1",
|
||||
"asOf": "2026-10-30",
|
||||
"metric": "platform-mrr-usd",
|
||||
"sampleUnit": "product-or-business",
|
||||
|
||||
@@ -191,8 +191,8 @@ def render():
|
||||
f"| 其他目录基础项 | {depth-reviewed} | 规则初分或资料不足,继续待复核 |",
|
||||
f"| 有团队数字 | {sum(c['team'] is not None for c in companies)} | 多为自报Team Size或Employees,时点与口径不统一 |",
|
||||
f"| 专项技术证据记录 | {len(companies)-technical['unreviewed']} | 其中{technical['description']}条自述、{technical['public-artifact']}条公开材料、{technical['independent-test']}条第三方评测 |",
|
||||
f"| 公司披露收入线索 | {income['self']} | 含历史、下界、币种不明及产品业务声明,不等于可比ARR |",
|
||||
f"| 仅平台收入线索 | {income['platform']} | 同时有公司披露者计入上一行,不重复计数 |",
|
||||
f"| 企业披露收入线索 | {income['self']} | 含公司或交易当事方披露、历史、下界及币种不明,不等于可比ARR |",
|
||||
f"| 仅平台收入线索 | {income['platform']} | 同时有企业披露者计入上一行,不重复计数 |",
|
||||
f"| 仅第三方估算 | {income['estimate']} | 不与直接披露混合 |",
|
||||
f"| 暂无可用收入数字 | {income['unknown']} | 包含尚未逐家搜索的目录项,不代表没有收入 |", '',
|
||||
'## 业务分类与数据入口', '',
|
||||
|
||||
Reference in New Issue
Block a user