扩展 AI 公司目录覆盖并保留逐条核查台账
Verify and deploy Tabularium / verify-and-deploy (pull_request) Successful in 11m10s

This commit is contained in:
2026-10-30 04:31:33 +08:00
parent 3e2183798d
commit d50281a1e9
8 changed files with 49662 additions and 21 deletions
+16 -1
View File
@@ -6,6 +6,7 @@ export type ResearchCompany = {
price: string; stage: string; sourceType: string; evidenceIds: string[];
revenueStatus: "self" | "estimate" | "unknown";
extraUrl?: string; pricingEvidence?: string;
profileOnly?: boolean; classificationBasis?: string; directoryTags?: string[];
};
export type ResearchObservation = {
id: string; company: string; name: string; kind: string; value: number;
@@ -21,11 +22,17 @@ export type ResearchReview = {
id: string; type: string; company: string; summary: string;
evidenceIds: string[]; handling: string;
};
export type ResearchCoverage = {
source: string; accessedAt: string; candidateRecords: number; profilesRead: number;
matchingProfiles: number; existingProfiles: number; newProfiles: number;
otherOrMissingYear: number; unclearAI: number; dateConflicts: number; failedProfiles: number;
discoverySha256: string;
};
export type ResearchSnapshot = {
version: string; asOf: string; scope: string; limitations: string[];
categories: ResearchCategory[]; companies: ResearchCompany[];
observations: ResearchObservation[]; evidence: ResearchEvidence[];
reviews: ResearchReview[];
reviews: ResearchReview[]; coverage?: ResearchCoverage;
};
export function evidenceUrl(value: string): string | undefined {
@@ -49,6 +56,8 @@ 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) {
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) ||
c.evidenceIds.some((id) => !evidence.has(id)) ||
(c.pricingEvidence && !evidence.has(c.pricingEvidence)))
@@ -63,6 +72,12 @@ export function validateResearch(snapshot: ResearchSnapshot) {
!Number.isFinite(o.value))
throw new Error(`Invalid research observation: ${o.id}`);
}
const coverage = snapshot.coverage;
if (coverage && (coverage.profilesRead + coverage.failedProfiles !== coverage.candidateRecords ||
coverage.matchingProfiles !== coverage.existingProfiles + coverage.newProfiles ||
coverage.matchingProfiles + coverage.otherOrMissingYear + coverage.unclearAI + coverage.dateConflicts !== coverage.profilesRead ||
snapshot.companies.filter((c) => c.profileOnly).length !== coverage.newProfiles || !evidenceUrl(coverage.source)))
throw new Error("Invalid research coverage accounting");
for (const r of snapshot.reviews)
if (r.evidenceIds.some((id) => !evidence.has(id)))
throw new Error(`Invalid research review: ${r.id}`);