fix: decouple report checks from legacy snapshots and tolerate slow dependency downloads
Verify database-backed documents / verify (pull_request) Failing after 4m0s

This commit is contained in:
2026-10-30 16:32:16 +08:00
parent d57e9b77d7
commit 534795617d
4 changed files with 23 additions and 20 deletions
+8 -7
View File
@@ -127,9 +127,9 @@ MRR×12仅作为显示单位转换,不改写为公司ARR;公司ARR、估算
平台同步时间、连接过期状态、业务描述的可编辑性和产品/法律主体未去重限制均保留。
覆盖审计页位于 `/docs/other-research/ai-company-research/coverage`,分类链接 `overview?category=<id>` 的筛选数据。
`python3 scripts/audit-ai-research.py --check` 检查候选池逐条计数与覆盖报告一致性;CI在ces-control运行此检查,未更改触发范围。
`python3 scripts/audit-ai-research.py --check` 检查候选池逐条计数与来源审计一致性;CI在ces-control运行此检查。
收入快照报告位于 `/docs/other-research/ai-company-research/income-snapshot`,样本名称链接 `overview?company=<id>` 的公司明细。
`python3 scripts/summarize-ai-income.py --check` 独立复核统计与报告一致性;不触发编译或构建。数据变更后先审查方法,再运行不带参数的命令生成 `.artifacts/reports` 下的候选正文,使用 docs 管理工具显式更新数据库;不再生成受 Git 管理的正文。
`python3 scripts/summarize-ai-income.py --check` 独立复核统计与参考快照一致性;不触发编译或构建。数据变更后先审查方法,再运行不带参数的命令生成 `.artifacts/reports` 下的候选正文,使用 docs 管理工具显式更新数据库;不再生成受 Git 管理的正文。
默认7日样本14个产品;90日窗口新增Gojiberry的8月历史点,营销样本的均值和CV随之明显变化。
这提示先核查时间与样本构成,不能将高离散度直接解释为造假。两个近名营养应用按不同App Store ID分别建档。
@@ -158,17 +158,18 @@ AI 关键词可能出现在业务背景中,收入、买家和交付状态仍
## CI/CD 与缓存
`.gitea/workflows/ci-deploy.yml` 使用已有 ces-control Runner,不修改共享 Runner 配置。
当前工作流仅在 main 推送或针对 main 的手动运行时执行。工作分支PR完成本地静态核查后,
完整类型、测试、构建与容器检查在用户手动合并后的主线CI运行;报告须区分未运行与已通过。
文档内容已退出构建输入。若需对照研究数据检查数据库中的报告正文,可先导出当前文档,再给研究脚本传入 `--document-export`;默认 `--check` 只核对研究数据本身的统计和审计不变量,避免把历史迁移快照继续当作日常正文源。
1. 对实际构建输入计算 SHA-256:前端源码、Markdown、图片、Python 制图源码、依赖锁文件、Dockerfile 和构建脚本。
`.gitea/workflows/ci-deploy.yml` 使用已有 ces-control Runner,不修改共享 Runner 配置。
部署工作流仅在 main 推送或针对 main 的手动运行时执行。迁移分支 `codex/database-docs` 由独立的 `docs-database-verify.yml` 在 PR 或手动触发时执行完整验证,使用 PR 隔离缓存,不部署;报告须区分未运行与已通过。
1. 对实际构建输入计算 SHA-256:前端源码、图片、Python 制图源码、研究业务快照、依赖锁文件、Dockerfile 和构建脚本。
2. 命中 `verified-<scope>-<摘要>` 镜像时跳过依赖安装和 Next.js build,只做认证、实际路由与资源冒烟检查。
3. 输入变化时运行 lint、类型检查、制图一致性检查与构建。pnpm store、uv 和 `.next/cache` 使用持久 Docker 卷,main 与每个 PR 独立;额外保留 Next.js SWC 下载缓存。
4. 生产镜像只包含 Next.js standalone 产物;Python 留在检查容器,不进入运行镜像。镜像通过动态码认证、重放/限流、重启持久化、健康、全部文档、JS/CSS、SVG 和 404 检查后才标记为 verified。
5. 部署前检查是否仍为最新 main,使用 `--no-build` 启动,失败恢复上一版镜像。
根 README、工作流或部署配置等非构建输入变化不会触发 Next.js 重建;Markdown 正文变化会更新静态页面,仍需要一次增量构建。首次构建必须安装依赖并完整生成产物。缓存可能因基础镜像、工具链或锁文件变化而失效;不要清理共享 Docker 缓存或卷。
根 README、工作流或部署配置等非构建输入变化不会触发 Next.js 重建;数据库中的正文和目录变化直接通过请求读取,不触发任何构建。首次构建必须安装依赖并完整生成产物。缓存可能因基础镜像、工具链或锁文件变化而失效;不要清理共享 Docker 缓存或卷。
默认入口为服务器的 **18135** 端口。容器监听 3000,使用独立 Compose 项目 `endorphin-tabularium-docs`。部署前先检查端口是否空闲(或属于本服务),不会停止其他服务以抢占端口。服务器配置位于 `/etc/endorphin-tabularium-docs/production.env`:
+7 -6
View File
@@ -96,15 +96,16 @@ def render():
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--check', action='store_true')
parser.add_argument('--document-export', type=Path, default=ROOT / '.artifacts/documents-migration.json')
parser.add_argument('--document-export', type=Path)
args = parser.parse_args()
content = render()
if args.check:
bundle = json.loads(args.document_export.read_text())
stored = next((d['content'] for d in bundle['documents'] if d['sourceSlug'] == SOURCE_SLUG), None)
if stored != content:
sys.exit('Research coverage report differs; review and regenerate')
print('Research coverage accounting and report are consistent')
if args.document_export is not None:
bundle = json.loads(args.document_export.read_text())
stored = next((d['content'] for d in bundle['documents'] if d['sourceSlug'] == SOURCE_SLUG), None)
if stored != content:
sys.exit('Research coverage report differs; review and regenerate')
print('Research coverage accounting verified; supplied document export compared when requested')
else:
TARGET.parent.mkdir(parents=True, exist_ok=True)
TARGET.write_text(content)
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/sh
set -eu
export CI=true
pnpm install --frozen-lockfile --store-dir /pnpm/store
pnpm install --frozen-lockfile --store-dir /pnpm/store --fetch-timeout 300000
uv sync --project tools/figures --locked
pnpm run lint
pnpm run typecheck
+7 -6
View File
@@ -138,16 +138,17 @@ def render():
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--check', action='store_true')
parser.add_argument('--document-export', type=Path, default=ROOT / '.artifacts/documents-migration.json')
parser.add_argument('--document-export', type=Path)
args = parser.parse_args()
verify()
content = render()
if args.check:
bundle = json.loads(args.document_export.read_text())
stored = next((d['content'] for d in bundle['documents'] if d['sourceSlug'] == SOURCE_SLUG), None)
if stored != content:
sys.exit('Income snapshot differs; regenerate after reviewing data changes')
print('Income reference, samples and report are consistent')
if args.document_export is not None:
bundle = json.loads(args.document_export.read_text())
stored = next((d['content'] for d in bundle['documents'] if d['sourceSlug'] == SOURCE_SLUG), None)
if stored != content:
sys.exit('Income snapshot differs; regenerate after reviewing data changes')
print('Income reference and samples verified; supplied document export compared when requested')
else:
TARGET.parent.mkdir(parents=True, exist_ok=True)
TARGET.write_text(content)