From 3db4ad6a27a841dc3aae123d191dc4fd0c5b1f5f Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Wed, 24 Jun 2026 17:45:35 +0800 Subject: [PATCH] Add ordinary user delivery preflight --- Dockerfile | 1 + README.md | 11 ++++ progress.md | 3 + scripts/deployment_preflight.py | 95 +++++++++++++++++++++++++++ scripts/run_quality_gate.py | 3 + task_plan.md | 3 +- tests/test_frontend_productization.py | 41 ++++++++++++ 7 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 scripts/deployment_preflight.py diff --git a/Dockerfile b/Dockerfile index 8b78fc6f..9c933727 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,7 @@ COPY assets/ ./assets/ # ─── Verify installation ─── RUN python -c "from jyotish_vedic import __version__; print(f'Jyotish v{__version__} ready')" +RUN python3 scripts/deployment_preflight.py # ─── Ports ─── # 5200: REST API server diff --git a/README.md b/README.md index 339982cd..793c056e 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,17 @@ This is a **Vedic (Jyotish) astrology analysis system** designed for deep, audit 4. 如果只安装 PWA:PWA 安装壳只包装网页服务,本地 API 服务仍需单独启动;无 API 时网页会保留基础浏览器 fallback,但 PDF/高级技法需要本地 API 服务。 5. 开发者做完整自检时运行:`python3 scripts/run_quality_gate.py --frontend-click-timeout 240`。 +### 普通用户交付形态 + +| 形态 | 入口 | 命令 | 能力边界 | +|------|------|------|----------| +| Local dev | `http://127.0.0.1:5173` | `cd jyotish-app && npm run dev -- --host 127.0.0.1 --port 5173` + `python3 scripts/jyotish_api_server.py --host 127.0.0.1 --port 5200` | 完整网页/app 用户端,适合本机普通用户试用。 | +| Docker Compose | `http://localhost:5300` | `docker compose up -d` | 同时启动 Web shell 与本地 API,适合低门槛本机部署。 | +| Static demo / PWA | 静态站点 URL | `cd jyotish-app && npm run build` | 公开演示环境只能完整展示静态壳;完整高级技法需要本地 API 服务。 | +| Desktop shell | PWA / Pake / Tauri | `python3 scripts/desktop_packaging_preflight.py` | PWA/Pake 当前可用;Tauri sidecar 需等 API 生命周期、签名和权限策略固定。 | + +发布前检查交付矩阵:`python3 scripts/deployment_preflight.py`。如果该命令失败,不要把当前构建交给普通用户。 + ### 质量门分层 - quick:快速开发守门,适合普通代码/文案修改后先跑:`python3 scripts/run_quality_gate.py --profile quick` diff --git a/progress.md b/progress.md index f10c6c64..6f070bb1 100644 --- a/progress.md +++ b/progress.md @@ -308,3 +308,6 @@ - 云端 CI 收口完成:推送 `925e73e` 后,GitHub PR #6 最新 head 的 `validate`、`test`、`release-quality-gate` 三条检查均为 success;release-only browser/release 守门已在云端可运行。 - 完成准确率透明度页面:Trust Center 新增 Validation Transparency,直接展示 `references/validation_logic_report.json` 当前 Yoga 对照口径:60 charts、82 comparable rules、Precision 96.48%、Recall 93.99%、F1 95.22%、unmapped_pyjhora 718,并明确这些是 Yoga 规则对照指标,不是个人事件预测准确率。 - TDD/验证完成:先让 `test_trust_center_exposes_validation_transparency` 红灯确认缺口,再实现转绿;修复移动端 selector 回归后,`python3 -B -m pytest tests/test_frontend_productization.py::test_first_use_onboarding_is_actionable tests/test_frontend_productization.py::test_mobile_layout_keeps_dense_sections_single_column tests/test_frontend_productization.py::test_trust_center_exposes_validation_transparency -q` 通过;`npm run build --prefix jyotish-app` 通过;`python3 scripts/run_quality_gate.py --profile quick --skip-yoga-logic` 通过,覆盖 201 个核心 pytest、npm build 与 runtime smoke。 +- 完成普通用户交付形态矩阵:新增 `scripts/deployment_preflight.py`,输出 local-dev、docker-compose、static-demo-pwa、desktop-shell 四条 delivery_matrix,明确公开演示环境只能完整展示静态壳、完整高级技法需要本地 API 服务;README 增加“普通用户交付形态”表格;Dockerfile build 阶段运行 deployment preflight。 +- 交付矩阵纳入质量门:`scripts/run_quality_gate.py` 编译并执行 `scripts/deployment_preflight.py`,release hygiene 追踪该新文件,避免部署/公开演示路径漂移。 +- TDD/验证完成:`test_user_delivery_matrix_is_documented_and_checkable` 先红灯确认缺 `deployment_preflight.py`,实现后转绿;`python3 scripts/deployment_preflight.py` 输出 `valid: true`;`python3 scripts/run_quality_gate.py --profile quick --skip-yoga-logic` 通过,覆盖 202 个核心 pytest、npm build 与 runtime smoke。 diff --git a/scripts/deployment_preflight.py b/scripts/deployment_preflight.py new file mode 100644 index 00000000..1f36f0a9 --- /dev/null +++ b/scripts/deployment_preflight.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +"""Check ordinary-user delivery paths before publishing a Jyotish build.""" + +from __future__ import annotations + +import json +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +APP = ROOT / "jyotish-app" + + +def read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def require(condition: bool, label: str, failures: list[str]) -> None: + if not condition: + failures.append(label) + + +def delivery_matrix() -> list[dict]: + return [ + { + "id": "local-dev", + "label": "Local dev", + "user_url": "http://127.0.0.1:5173", + "commands": [ + "cd jyotish-app && npm run dev -- --host 127.0.0.1 --port 5173", + "python3 scripts/jyotish_api_server.py --host 127.0.0.1 --port 5200", + ], + "api_required": True, + "scope": "Full web/app user experience with local API.", + }, + { + "id": "docker-compose", + "label": "Docker Compose", + "user_url": "http://localhost:5300", + "commands": ["docker compose up -d"], + "api_required": True, + "scope": "Bundled API + web shell for local ordinary-user trials.", + }, + { + "id": "static-demo-pwa", + "label": "Static demo / PWA", + "user_url": "https:///", + "commands": ["cd jyotish-app && npm run build"], + "api_required": False, + "scope": "public demo shell; full advanced techniques require a local API service.", + }, + { + "id": "desktop-shell", + "label": "Desktop shell", + "user_url": "pwa://installed-app or pake://local-url", + "commands": [ + "cd jyotish-app && npm run build && npm run preview -- --host 127.0.0.1 --port 4173", + "python3 scripts/desktop_packaging_preflight.py", + ], + "api_required": True, + "scope": "PWA/Pake now; Tauri sidecar only after API lifecycle and signing are fixed.", + }, + ] + + +def main() -> int: + failures: list[str] = [] + readme = read(ROOT / "README.md") + dockerfile = read(ROOT / "Dockerfile") + compose = read(ROOT / "docker-compose.yml") + package = json.loads(read(APP / "package.json")) + manifest = json.loads(read(APP / "public" / "manifest.webmanifest")) + sw = read(APP / "public" / "sw.js") + + require("普通用户交付形态" in readme, "README missing ordinary-user delivery matrix", failures) + require("python3 scripts/deployment_preflight.py" in readme, "README missing deployment preflight command", failures) + require("http://localhost:5300" in compose, "docker-compose missing ordinary web URL note", failures) + require("python3 scripts/deployment_preflight.py" in dockerfile, "Dockerfile must run deployment preflight", failures) + require("build" in package.get("scripts", {}), "jyotish-app missing build script", failures) + require("preview" in package.get("scripts", {}), "jyotish-app missing preview script", failures) + require(manifest.get("display") == "standalone", "PWA manifest must remain standalone", failures) + require("url.pathname.startsWith('/api/')" in sw, "service worker must bypass API requests", failures) + + result = { + "valid": not failures, + "failures": failures, + "delivery_matrix": delivery_matrix(), + "ordinary_user_note": "公开演示环境只能完整展示静态壳;完整高级技法需要本地 API 服务。", + } + print(json.dumps(result, ensure_ascii=False, indent=2)) + return 0 if not failures else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/run_quality_gate.py b/scripts/run_quality_gate.py index 867ffd45..cd6435db 100644 --- a/scripts/run_quality_gate.py +++ b/scripts/run_quality_gate.py @@ -23,6 +23,7 @@ COMPILE_DIRS = [ EXTRA_COMPILE_TARGETS = [ ROOT / "mcp_server.py", ROOT / "scripts" / "audit_fragments.py", + ROOT / "scripts" / "deployment_preflight.py", ROOT / "tests" / "run_golden_cases.py", ROOT / "tests" / "run_frontend_runtime_smoke.py", ] @@ -55,6 +56,7 @@ RELEASE_CRITICAL_UNTRACKED_PATHS = [ "progress.md", "scripts/audit_fragments.py", "scripts/deep_varga_avastha.py", + "scripts/deployment_preflight.py", "scripts/desktop_packaging_preflight.py", "scripts/ephemeris_adapter_contract.py", "scripts/ephemeris_backend_probe.py", @@ -278,6 +280,7 @@ def main() -> int: validate_json_files() run([PYTHON, "scripts/audit_capabilities.py", "--mode", "validate"]) run([PYTHON, "scripts/audit_fragments.py", "--strict"]) + run([PYTHON, "scripts/deployment_preflight.py"]) if profile["check_release_hygiene"]: release_hygiene_check() run([PYTHON, "scripts/validate_bphs_invariants.py"]) diff --git a/task_plan.md b/task_plan.md index b9f6c54d..4960d206 100644 --- a/task_plan.md +++ b/task_plan.md @@ -101,4 +101,5 @@ - [x] CI 失败 artifact 诊断:pytest 改为 `-vv --maxfail=1 --junitxml`,quick/release quality gate 输出 tee 到 artifact,避免云端只暴露 exit code。 - [x] 云端 CI 收口:PR #6 head `925e73e` 的 `validate`、`test`、`release-quality-gate` 三条 GitHub Actions 检查均已通过。 - [x] 准确率透明度页面:Trust Center 新增 Validation Transparency 面板,展示 Yoga logic benchmark 的 60 charts、82 comparable rules、Precision/Recall/F1、unmapped_pyjhora 与“不是个人事件预测准确率”的边界说明。 -- [ ] 下一步:进入成品化最后一批缺口,优先补普通用户交付形态(部署/桌面打包/公开演示环境)。 +- [x] 普通用户交付形态:新增 deployment preflight 与 README 交付矩阵,明确 Local dev、Docker Compose、Static demo/PWA、Desktop shell 的入口、命令和 API 边界,并纳入 quick/release 守门。 +- [ ] 下一步:继续公开演示环境 polish,优先增加静态 demo 的离线/无 API 文案和部署目标示例。 diff --git a/tests/test_frontend_productization.py b/tests/test_frontend_productization.py index 1c215072..520340d7 100644 --- a/tests/test_frontend_productization.py +++ b/tests/test_frontend_productization.py @@ -1684,6 +1684,47 @@ def test_desktop_packaging_spike_is_documented_and_checkable() -> None: assert "python3 scripts/jyotish_api_server.py --host 127.0.0.1 --port 5200" in quality_gate +def test_user_delivery_matrix_is_documented_and_checkable() -> None: + preflight_path = ROOT / "scripts" / "deployment_preflight.py" + assert preflight_path.exists() + preflight = preflight_path.read_text(encoding="utf-8") + readme = (ROOT / "README.md").read_text(encoding="utf-8") + dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8") + compose = (ROOT / "docker-compose.yml").read_text(encoding="utf-8") + + for token in [ + "delivery_matrix", + "local-dev", + "docker-compose", + "static-demo-pwa", + "desktop-shell", + "public demo shell", + "api_required", + "python3 scripts/jyotish_api_server.py --host 127.0.0.1 --port 5200", + "npm run preview -- --host 127.0.0.1 --port 4173", + "http://localhost:5300", + ]: + assert token in preflight + + for token in [ + "普通用户交付形态", + "Local dev", + "Docker Compose", + "Static demo / PWA", + "Desktop shell", + "python3 scripts/deployment_preflight.py", + "公开演示环境只能完整展示静态壳", + "完整高级技法需要本地 API 服务", + ]: + assert token in readme + + assert "python3 scripts/deployment_preflight.py" in dockerfile + assert "http://localhost:5300" in compose + quality_gate = (ROOT / "scripts" / "run_quality_gate.py").read_text(encoding="utf-8") + assert '"scripts/deployment_preflight.py"' in quality_gate + assert '[PYTHON, "scripts/deployment_preflight.py"]' in quality_gate + + def test_user_startup_labels_are_consistent_across_recovery_surfaces() -> None: readme = (ROOT / "README.md").read_text(encoding="utf-8") quality_gate = (ROOT / "scripts" / "run_quality_gate.py").read_text(encoding="utf-8")