diff --git a/README.md b/README.md index be9bc75..768f757 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ AUTH_CONFIG_FILE=/private/tmp/tabularium-auth/config.json AUTH_COOKIE_SECURE=fal 同一版本内容变化会拒绝导入,避免静默读取旧数据。回退代码时继续读取对应旧版本。 所有修改都经过工作分支和 PR,部署仍等待人工合并主线。 -当前资料包含 1,006 条公司/产品记录、10 类业务及待分类组、1,067 条证据记录和 129 条经营观测。 +当前资料包含 1,006 条公司/产品记录、10 类业务及待分类组、1,069 条证据记录和 129 条经营观测。 其中保留 62 家个案资料、928 条目录基础资料,并新增 16 个平台产品/业务样本;目录项不等于完成财务和技术核验。 补充ThinkWheel与中国NaiveAI;MiroMind成立年未核,公开研发年份单列。保留灵初智能成立年排除、深度原理日期待核和Naive近名实体复核记录。 它是定向试样,收入披露不足且统计时点不统一,不代表全部 AI 公司。 @@ -133,7 +133,9 @@ MRR×12仅作为显示单位转换,不改写为公司ARR;公司ARR、估算 其中121条原待分类记录已按YC官方业务介绍人工复核主营业务,分类理由保存在公司字段与对应证据摘要中; 仍有3条因简介不足保留待分类。人工复核分类不代表独立验证技术水平、客户效果或财务数据。 AI 关键词可能出现在业务背景中,收入、买家和交付状态仍须逐家深查,不能把目录项的未知收入当作未披露。 -界面支持按资料深度、记录团队规模筛选;证据列表每页 30 条,避免一次渲染全部来源。 +技术专项评审用独立字段记录层级、日期、摘要与证据:未评审、已读技术自述、公开代码/模型材料可访问、有独立测试记录。 +当前仅5条完成该字段的专项记录,其中2条确认材料可访问;没有独立测试记录。缺字段不表示无技术能力,代码或模型卡可读不证明性能。 +界面支持按资料深度、记录团队规模和技术验证证据筛选;证据列表每页 30 条,避免一次渲染全部来源。 `pnpm test:research` 在远程 Runner 上验证同库持久化、重复读取、版本导入与回退、 登录限流保留、引用完整性及收入排除规则。镜像冒烟检查会验证研究页面与 API 的认证、 diff --git a/apps/docs/scripts/auth-cli.ts b/apps/docs/scripts/auth-cli.ts index 356cbc3..05f1f62 100644 --- a/apps/docs/scripts/auth-cli.ts +++ b/apps/docs/scripts/auth-cli.ts @@ -187,7 +187,7 @@ async function main() { const research = await researchResponse.json(); assert.equal(research.companies.length, 1006); assert.equal(research.categories.length, 11); - assert.equal(research.evidence.length, 1067); + assert.equal(research.evidence.length, 1069); assert.equal(research.observations.length, 129); 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 }); diff --git a/apps/docs/src/components/AICompanyResearch.tsx b/apps/docs/src/components/AICompanyResearch.tsx index dbf4f7d..d3031a7 100644 --- a/apps/docs/src/components/AICompanyResearch.tsx +++ b/apps/docs/src/components/AICompanyResearch.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import IncomeDistribution from "./IncomeDistribution"; import { - categorySummary, evidenceUrl, type ResearchEvidence, type ResearchSnapshot, + categorySummary, evidenceUrl, technicalReviewLabels, type ResearchEvidence, type ResearchSnapshot, } from "@/lib/ai-research"; const pageSize = 12; @@ -41,6 +41,7 @@ export default function AICompanyResearch() { const [sourcePage, setSourcePage] = useState(0); const [depth, setDepth] = useState(""); const [teamBand, setTeamBand] = useState(""); + const [technicalLevel, setTechnicalLevel] = useState(""); const [selected, setSelected] = useState(null); const [tab, setTab] = useState<"companies" | "revenue" | "sources" | "reviews">("companies"); const companySection = useRef(null); @@ -63,9 +64,9 @@ export default function AICompanyResearch() { const depthMatch = !depth || (depth === "profile" ? c.profileOnly : !c.profileOnly); const teamMatch = !teamBand || (teamBand === "unknown" ? c.team === null || (!!c.teamBound && c.team < 51) : c.team !== null && (teamBand === "xl" ? c.team >= 51 : !c.teamBound && (teamBand === "small" ? c.team <= 5 : teamBand === "medium" ? c.team >= 6 && c.team <= 20 : c.team >= 21 && c.team <= 50))); - return depthMatch && teamMatch && (!category || c.cat === category) && yearMatch && (!income || c.revenueStatus === income) + return (!technicalLevel || (c.technicalReview?.level ?? "unreviewed") === technicalLevel) && depthMatch && teamMatch && (!category || c.cat === category) && yearMatch && (!income || c.revenueStatus === income) && search.includes(query.trim().toLocaleLowerCase()); - }) ?? [], [data, query, category, cohort, income, depth, teamBand]); + }) ?? [], [data, query, category, cohort, income, depth, teamBand, technicalLevel]); if (error) return
研究数据库暂时不可用。
; if (!data) return

正在读取研究数据库…

; const categories = new Map(data.categories.map((c) => [c.id, c])); @@ -76,6 +77,7 @@ export default function AICompanyResearch() { const selectedObservations = data.observations.filter((o) => o.company === selected); const selectedEvidenceIds = new Set([ ...(selectedCompany?.evidenceIds ?? []), ...(selectedCompany?.pricingEvidence ? [selectedCompany.pricingEvidence] : []), + ...(selectedCompany?.technicalReview?.evidenceIds ?? []), ...selectedObservations.map((o) => o.evidence), ]); const selectedEvidence = data.evidence.filter((e) => e.companyId === selected || selectedEvidenceIds.has(e.id)); @@ -118,14 +120,16 @@ export default function AICompanyResearch() { + -
{filtered.length} 条匹配记录
-
+

技术验证层级记录我们查到了什么,不是能力强弱评分。技术专项评审与业务分类复核分别记录。

+
{filtered.length} 条匹配记录
+
公司/产品分类与经营资料。选择名称查看指标和原始证据。
公司或产品 / 地区业务与买家成立 / 发布组别团队规模商业成熟度收入资料
{filtered.slice(page * pageSize, (page + 1) * pageSize).map((c) => - - + + )}
公司/产品分类与经营资料。选择名称查看指标和原始证据。
公司或产品 / 地区业务与买家成立 / 发布组别团队规模交付与技术验证证据收入资料
{c.location ?? "地区未注明"}{categories.get(c.cat)?.name}{c.profileOnly && 规则初分 · 待复核}

{c.business}

买家:{c.buyer}
{c.cohort}{c.team !== null && c.teamBound}{c.team ?? "未披露"}{c.team !== null && " 人"}{c.stage}{c.profileOnly ? "收入尚未逐一核验" : revenueLabels[c.revenueStatus]}{categories.get(c.cat)?.name}{c.profileOnly && 目录基础资料 · 分类依据见明细}

{c.business}

买家:{c.buyer}
{c.cohort}{c.team !== null && c.teamBound}{c.team ?? "未披露"}{c.team !== null && " 人"}{c.stage}{technicalReviewLabels[c.technicalReview?.level ?? "unreviewed"]}{c.profileOnly ? "收入尚未逐一核验" : revenueLabels[c.revenueStatus]}
{!filtered.length &&

没有匹配公司,请调整筛选条件。

} @@ -149,7 +153,7 @@ export default function AICompanyResearch() { {selectedCompany &&

{selectedCompany.name}

资料入口 {selectedCompany.extraUrl && 额外核验入口}

-
主营业务
{selectedCompany.business}
样本组别
{selectedCompany.cohort}
买家
{selectedCompany.buyer}
收费/交付模式
{selectedCompany.businessModel ?? "待进一步核验"}
收费方式
{selectedCompany.price}
交付证据
{selectedCompany.delivery}
团队口径
{selectedCompany.teamBasis ?? "本轮未核验人数"}
分类依据
{selectedCompany.classificationBasis ?? "原有个案分类;随研究复核"}
技术水平
尚未独立测试,不据融资或收入作能力排名。
观测主体
{selectedCompany.entityBasis ?? "公司或经营品牌,法律主体未逐一核验"}
身份与限制
{selectedCompany.notes}
+
主营业务
{selectedCompany.business}
样本组别
{selectedCompany.cohort}
买家
{selectedCompany.buyer}
收费/交付模式
{selectedCompany.businessModel ?? "待进一步核验"}
收费方式
{selectedCompany.price}
交付证据
{selectedCompany.delivery}
团队口径
{selectedCompany.teamBasis ?? "本轮未核验人数"}
分类依据
{selectedCompany.classificationBasis ?? "原有个案分类;随研究复核"}
技术验证证据
{technicalReviewLabels[selectedCompany.technicalReview?.level ?? "unreviewed"]}

{selectedCompany.technicalReview?.summary ?? "本轮未形成专项技术评审记录;不表示公司没有技术能力。"}

{selectedCompany.technicalReview && 评审日期:{selectedCompany.technicalReview.reviewedAt}}{selectedCompany.technicalReview?.testScope &&

测试范围:{selectedCompany.technicalReview.testScope}

}

材料可访问仅确认可查看,不证明性能、可靠性或商业交付质量;不同任务不作统一能力排名。

观测主体
{selectedCompany.entityBasis ?? "公司或经营品牌,法律主体未逐一核验"}
身份与限制
{selectedCompany.notes}

经营指标与排除记录

{selectedObservations.length ?
{selectedObservations.map((o) => )}
指标 / 归属原始数值数据时点用途及限制证据
{o.kind}{o.scope}{o.bound !== "=" && o.bound}{money(o.value,o.unit)}{o.timing}{useLabels[o.selection] ?? o.selection}{o.reason}{o.evidence}
:

本轮尚未找到可记录的量化经营指标。收入保持未知。

}

原始证据

    {selectedEvidence.map((e) => )}
diff --git a/apps/docs/src/lib/ai-research.ts b/apps/docs/src/lib/ai-research.ts index 8d3282a..465eeb5 100644 --- a/apps/docs/src/lib/ai-research.ts +++ b/apps/docs/src/lib/ai-research.ts @@ -1,4 +1,10 @@ export type ResearchCategory = { id: string; name: string; description: string }; +export const technicalReviewLabels = { + unreviewed: "技术证据尚未专项评审", + description: "已读技术自述", + "public-artifact": "公开代码/模型材料可访问", + "independent-test": "有独立测试记录", +}; export type ResearchCompany = { id: string; name: string; url: string; cat: string; year: number | null; team: number | null; teamBound?: ">" | "≥"; location: string | null; business: string; buyer: string; @@ -8,6 +14,10 @@ export type ResearchCompany = { extraUrl?: string; pricingEvidence?: string; businessModel?: string; entityBasis?: string; profileOnly?: boolean; classificationBasis?: string; directoryTags?: string[]; + technicalReview?: { + level: "description" | "public-artifact" | "independent-test"; + reviewedAt: string; summary: string; evidenceIds: string[]; testScope?: string; + }; }; export type ResearchObservation = { id: string; company: string; name: string; kind: string; value: number; @@ -59,6 +69,15 @@ export function validateResearch(snapshot: ResearchSnapshot) { unique(snapshot.observations.map((o) => o.id), "observations"); unique(snapshot.reviews.map((r) => r.id), "reviews"); for (const c of snapshot.companies) { + const technical = c.technicalReview; + if (technical && (!["description", "public-artifact", "independent-test"].includes(technical.level) || + !/^\d{4}-\d{2}-\d{2}$/.test(technical.reviewedAt) || + Number.isNaN(Date.parse(technical.reviewedAt)) || + new Date(technical.reviewedAt).toISOString().slice(0, 10) !== technical.reviewedAt || + technical.reviewedAt > snapshot.asOf || !technical.summary.trim() || + !technical.evidenceIds.length || technical.evidenceIds.some((id) => !evidence.has(id)) || + (technical.level === "independent-test" && !technical.testScope?.trim()))) + throw new Error(`Invalid technical review: ${c.id}`); if (c.profileOnly && (c.revenueStatus !== "unknown" || !c.classificationBasis)) throw new Error(`Invalid profile-only research record: ${c.id}`); if (!categories.has(c.cat) || !evidenceUrl(c.url) || diff --git a/apps/docs/tests/research.test.ts b/apps/docs/tests/research.test.ts index 35c309a..1410ce1 100644 --- a/apps/docs/tests/research.test.ts +++ b/apps/docs/tests/research.test.ts @@ -24,7 +24,7 @@ test("research revisions share the authentication database and preserve replay l assert.equal(consumeCode(config, "invalid"), "limited"); const initial = readResearchSnapshot(); assert.equal(initial.companies.length, 1006); - assert.equal(initial.evidence.length, 1067); + assert.equal(initial.evidence.length, 1069); assert.equal(initial.observations.length, 129); assert.deepEqual(readResearchSnapshot(), initial, "reopening does not duplicate records"); const db = openSiteDatabase(); @@ -73,6 +73,26 @@ test("disclosure counts exclude client income, biographies, targets and duplicat assert.ok(snapshot.observations.filter((o) => o.selection === "signal").every((o) => o.scope === "公司整体")); }); +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, 5); + assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "public-artifact").length, 2); + assert.equal(snapshot.companies.filter((c) => c.technicalReview?.level === "independent-test").length, 0); + const company = snapshot.companies.find((c) => c.id === "AI061")!; + const review = company.technicalReview!; + review.evidenceIds = ["missing-technical-evidence"]; + assert.throws(() => validateResearch(snapshot), /technical review/); + review.evidenceIds = ["TECH-NAIVE-HF"]; + review.reviewedAt = "2026-02-30"; + assert.throws(() => validateResearch(snapshot), /technical review/); + review.reviewedAt = "2099-01-01"; + assert.throws(() => validateResearch(snapshot), /technical review/); + review.reviewedAt = snapshot.asOf; + review.level = "independent-test"; + assert.throws(() => validateResearch(snapshot), /technical review/, + "an accessible artifact cannot become a test record without a stated test scope"); +}); + // Retractions and forecasts must stay visible for review without becoming revenue signals. test("retracted ARR and projected margins remain excluded", () => { const snapshot = seed as ResearchSnapshot; diff --git a/content/research/ai-companies.seed.json b/content/research/ai-companies.seed.json index 4ce909a..7ba8630 100644 --- a/content/research/ai-companies.seed.json +++ b/content/research/ai-companies.seed.json @@ -1,5 +1,5 @@ { - "version": "2026-10-30-global-1", + "version": "2026-10-30-technical-1", "asOf": "2026-10-30", "scope": "全球公开资料研究:保留首批个案,并扩展核查2025—2026八个YC批次候选池;成立年份以官方公司页面字段为依据。", "limitations": [ @@ -142,7 +142,15 @@ "evidenceIds": [ "E003" ], - "revenueStatus": "unknown" + "revenueStatus": "unknown", + "technicalReview": { + "level": "description", + "reviewedAt": "2026-10-30", + "summary": "已读取YC关于自主公司运行时的描述;未测试真实任务成功率、授权控制或人工接管。", + "evidenceIds": [ + "E003" + ] + } }, { "id": "AI004", @@ -28195,7 +28203,15 @@ "revenueStatus": "self", "businessModel": "订阅与用量额度", "entityBasis": "公司品牌;注册实体及地区登记尚未核验", - "classificationBasis": "公司定位为小企业综合经营平台,主类C05;营销和内容生成为次级功能。" + "classificationBasis": "公司定位为小企业综合经营平台,主类C05;营销和内容生成为次级功能。", + "technicalReview": { + "level": "description", + "reviewedAt": "2026-10-30", + "summary": "已读取综合Agent产品说明;未独立执行网站、营销及运营任务,不将产品宣传当作测试结果。", + "evidenceIds": [ + "RUN-ANN" + ] + } }, { "id": "AI060", @@ -28220,7 +28236,15 @@ "revenueStatus": "unknown", "businessModel": "具身平台与硬件;收入结构待核", "entityBasis": "品牌与注册实体对应关系见证据限制;未独立核验登记原件", - "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。" + "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。", + "technicalReview": { + "level": "description", + "reviewedAt": "2026-10-30", + "summary": "已读取主动交互具身平台介绍;未独立测试感知、决策或硬件可靠性。", + "evidenceIds": [ + "CN-TW" + ] + } }, { "id": "AI061", @@ -28241,12 +28265,21 @@ "sourceType": "公司官方资料;部分成立信息为二手工商资料", "evidenceIds": [ "CN-NAIVE-MODEL", - "CN-NAIVE-REG" + "CN-NAIVE-REG", + "TECH-NAIVE-HF" ], "revenueStatus": "unknown", "businessModel": "开放权重与API;实际付费收入未知", "entityBasis": "品牌与注册实体对应关系见证据限制;未独立核验登记原件", - "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。" + "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。", + "technicalReview": { + "level": "public-artifact", + "reviewedAt": "2026-10-30", + "summary": "已打开官方链接指向的模型卡,查看架构、部署和许可证说明;未下载权重或运行推理,基准结果仍为开发方自报。", + "evidenceIds": [ + "TECH-NAIVE-HF" + ] + } }, { "id": "AI062", @@ -28267,12 +28300,21 @@ "sourceType": "公司官方资料;部分成立信息为二手工商资料", "evidenceIds": [ "CN-MIRO-2025", - "CN-MIRO-PRICE" + "CN-MIRO-PRICE", + "TECH-MIRO-CODE" ], "revenueStatus": "unknown", "businessModel": "订阅与一次性额度包", "entityBasis": "品牌与注册实体对应关系见证据限制;未独立核验登记原件", - "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。" + "classificationBasis": "按官方主营描述人工归类;不构成技术水平排名。", + "technicalReview": { + "level": "public-artifact", + "reviewedAt": "2026-10-30", + "summary": "已打开官方MiroFlow仓库,查看源码目录、配置及部署说明;未运行Agent或复现榜单,代码存在不代表端到端任务可靠。", + "evidenceIds": [ + "TECH-MIRO-CODE" + ] + } } ], "observations": [ @@ -42170,6 +42212,28 @@ "kind": "公司自述", "summary": "官方介绍材料化学AI业务,但可读取正文未列成立日期。", "limitation": "本轮未取得直接成立日期证据,暂不新增为2025—2026成立公司;2025备案号不能替代成立年。" + }, + { + "id": "TECH-NAIVE-HF", + "companyId": "AI061", + "title": "NaiveAI官方模型卡与部署资料", + "url": "https://huggingface.co/NaiveAI/Naive-N0.5-Flash", + "publishedAt": null, + "accessedAt": "2026-10-30", + "kind": "公开模型材料", + "summary": "可访问模型卡、架构表、部署示例及许可证说明;官方站点指向该组织。", + "limitation": "仅检查公开材料可访问,未下载模型、运行代码或复测基准;不把下载次数或组织成员数当作客户数或员工数。" + }, + { + "id": "TECH-MIRO-CODE", + "companyId": "AI062", + "title": "MiroFlow官方公开代码仓库", + "url": "https://github.com/MiroMindAI/MiroFlow", + "publishedAt": null, + "accessedAt": "2026-10-30", + "kind": "公开代码材料", + "summary": "公开仓库包含源码目录、配置、启动脚本和部署说明,官方站点可到达所属组织。", + "limitation": "未执行代码或复现性能;榜单成绩为维护方声明,star和fork不代表客户或收入。" } ], "reviews": [ diff --git a/content/research/ai-income-analysis.json b/content/research/ai-income-analysis.json index 532895b..e5e2970 100644 --- a/content/research/ai-income-analysis.json +++ b/content/research/ai-income-analysis.json @@ -1,5 +1,5 @@ { - "sourceVersion": "2026-10-30-global-1", + "sourceVersion": "2026-10-30-technical-1", "asOf": "2026-10-30", "metric": "platform-mrr-usd", "sampleUnit": "product-or-business",