diff --git a/AGENTS.md b/AGENTS.md index 6311ae5..a33f22f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -190,6 +190,16 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才 - 不为单个页面直接改变底层公共组件的全局行为。确需全局修改或同时影响 Sense、Bell 时,必须单独建单并明确受影响页面、兼容方式和回归验证;跨产品影响按协同工单处理。 - UI 验收至少检查:没有多余入口、没有可见但不可用的失效入口、没有重复实现已有组件,并且视觉与交互保持一致。 +### Sense/Bell GoAdmin 技术基线 + +- `goadmin-baseline.json` 是 Sense、Bell 共用的 GoAdmin 上游与工具链版本事实来源;上游 URL 加完整 commit 是可复现标识,tag、`package.json` version、本机目录内容或本机已安装版本都不能替代 commit。 +- `D:\github\goadmin\go-admin`、`go-admin-ui`、`go-admin-doc` 是当前机器的只读参考副本。Agent 可以读取和验证,不得在这些目录开发、修改或提交 yovision 产品代码。 +- Sense、Bell 必须从同一冻结基线分别初始化,保留独立代码、配置、构建、测试、版本和发布;不得通过共同修改参考仓库形成隐藏的共享实现。 +- 复制或派生上游代码时必须保留对应 MIT 许可证和版权声明,并记录实际复制来源的 commit。 +- `go-admin-doc` 只用于理解上游框架用法;yovision 的 Gitea Wiki、`AGENTS.md` 和 `goadmin-baseline.json` 仍是本项目事实来源。 +- 变更任一上游 commit、Go、Node 或 pnpm 版本必须建立 Sense/Bell 协同升级工单,验证两个产品后再更新基线;不得在单端业务工单中静默升级。 +- 当前冻结后端要求 Go 1.26.5;本机 Go 1.23.0 不满足要求,安装隔离的正确工具链并完成构建验证前,不得声称后端基线可构建。 + ### 三项目并行建单顺序 客户交付需要 Sense、Brain、Bell 并行推进时,固定使用以下顺序: diff --git a/Bell/AGENTS.md b/Bell/AGENTS.md index 8ce18f0..441824d 100644 --- a/Bell/AGENTS.md +++ b/Bell/AGENTS.md @@ -22,3 +22,10 @@ - 新页面优先复用 Bell/go-admin-ui 已有的布局、表格、表单、弹窗、上传、权限控制和请求封装;新增组件前在工单中说明现有组件为何不能满足需求。 - 新增组件沿用 Bell 现有颜色、字号、间距、状态反馈、交互方式、命名和目录结构,并验证没有多余入口、失效入口或重复组件。 - 修改底层公共组件的全局行为时,必须单独建单并列出所有受影响页面;同时影响 Sense 或共享基线时升级为协同工单。 + +## GoAdmin 技术基线 + +- 初始化或升级 Bell 前必须读取根 `goadmin-baseline.json`,按其中的 go-admin、go-admin-ui commit 和 Go/Node/pnpm 精确版本实施。 +- `D:\github\goadmin` 下的仓库仅可只读参考;Bell 产品代码只能写入 `Bell/` 或工单授权路径,不得在参考仓库原地开发。 +- 派生上游代码必须保留 MIT 许可证和版权声明;上游 `go-admin-doc` 只作框架用法参考,不覆盖 yovision Wiki 和本目录规则。 +- 变更冻结基线必须升级为 Sense/Bell 协同工单;Bell 可以独立发布,但不得单独漂移上游或工具链版本。 diff --git a/Sense/AGENTS.md b/Sense/AGENTS.md index 347b8d2..734452d 100644 --- a/Sense/AGENTS.md +++ b/Sense/AGENTS.md @@ -22,3 +22,10 @@ - 新页面优先复用 Sense/go-admin-ui 已有的布局、表格、表单、弹窗、上传、权限控制和请求封装;新增组件前在工单中说明现有组件为何不能满足需求。 - 新增组件沿用 Sense 现有颜色、字号、间距、状态反馈、交互方式、命名和目录结构,并验证没有多余入口、失效入口或重复组件。 - 修改底层公共组件的全局行为时,必须单独建单并列出所有受影响页面;同时影响 Bell 或共享基线时升级为协同工单。 + +## GoAdmin 技术基线 + +- 初始化或升级 Sense 前必须读取根 `goadmin-baseline.json`,按其中的 go-admin、go-admin-ui commit 和 Go/Node/pnpm 精确版本实施。 +- `D:\github\goadmin` 下的仓库仅可只读参考;Sense 产品代码只能写入 `Sense/` 或工单授权路径,不得在参考仓库原地开发。 +- 派生上游代码必须保留 MIT 许可证和版权声明;上游 `go-admin-doc` 只作框架用法参考,不覆盖 yovision Wiki 和本目录规则。 +- 变更冻结基线必须升级为 Sense/Bell 协同工单;Sense 可以独立发布,但不得单独漂移上游或工具链版本。 diff --git a/dev_scripts/check_harness.py b/dev_scripts/check_harness.py index 5031c02..b1c2d54 100644 --- a/dev_scripts/check_harness.py +++ b/dev_scripts/check_harness.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse +import json import re from pathlib import Path @@ -47,6 +48,7 @@ CORE_DOCUMENT_REQUIREMENTS = { "## 阅读入口", "## 常用命令", "## 环境、配置与凭据", + "## Sense/Bell GoAdmin 固定技术基线", ), "docs/01-workflow.md": ( "## 面向初级维护者的修改边界", @@ -75,6 +77,7 @@ CORE_DOCUMENT_REQUIREMENTS = { ), "docs/04-local-development-and-verification.md": ( "## 环境要求", + "## Sense/Bell 固定工具链与只读参考源", "## 第一次运行", "## 常用调试方式", "## 完成修改前", @@ -140,6 +143,7 @@ REQUIRED_FILES = ( "docs/templates/task-archive.md", *CORE_DOCUMENT_REQUIREMENTS, "wiki-docs.json", + "goadmin-baseline.json", "dev_scripts/wiki_docs.py", "dev_scripts/sync_wiki_docs.py", ".gitea/issue_template/epic.md", @@ -326,6 +330,131 @@ def check_go_admin_ui_rules(errors: list[str], root: Path = ROOT) -> None: errors.append(f"{relative_path} 缺少 go-admin 规则:{section}") +GOADMIN_BASELINE_REQUIREMENTS = { + "runtimes": { + "go": "1.26.5", + "node": "22.22.1", + "package_manager": "pnpm", + "pnpm": "9.15.1", + }, + "sources": { + "go-admin": { + "commit": "f06540883b41d03782bb6b2c4150f298f328c6b6", + "upstream_url": "https://github.com/go-admin-team/go-admin.git", + "branch": "master", + "describe": "v2.2.0-25-gf065408", + "exact_tag": None, + "local_reference_path": r"D:\github\goadmin\go-admin", + "license": "MIT", + }, + "go-admin-ui": { + "commit": "67d393d713877572fab0b897296a4c1d525fc81d", + "upstream_url": "https://github.com/go-admin-team/go-admin-ui.git", + "branch": "master", + "describe": "v2.0.9-170-g67d393d", + "exact_tag": None, + "local_reference_path": r"D:\github\goadmin\go-admin-ui", + "package_version": "2.0.9", + "package_version_is_authoritative": False, + "license": "MIT", + }, + "go-admin-doc": { + "commit": "424855aacf6905f3fde860c3331385cb25529a0d", + "upstream_url": "https://github.com/go-admin-team/go-admin-doc.git", + "branch": "master", + "describe": "424855a", + "exact_tag": None, + "local_reference_path": r"D:\github\goadmin\go-admin-doc", + "package_version_is_authoritative": False, + "license": "MIT", + }, + }, +} + + +def check_goadmin_baseline(errors: list[str], root: Path = ROOT) -> None: + """检查 Sense/Bell 共用上游和工具链基线可复现且规则完整。""" + + path = root / "goadmin-baseline.json" + if not path.is_file(): + errors.append("缺少 GoAdmin 技术基线:goadmin-baseline.json") + return + try: + baseline = json.loads(path.read_text(encoding="utf-8")) + except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc: + errors.append(f"GoAdmin 技术基线不是有效 JSON:{exc}") + return + + for group, entries in GOADMIN_BASELINE_REQUIREMENTS.items(): + actual_group = baseline.get(group) + if not isinstance(actual_group, dict): + errors.append(f"GoAdmin 技术基线缺少对象:{group}") + continue + for name, expected in entries.items(): + actual = actual_group.get(name) + if isinstance(expected, dict): + if not isinstance(actual, dict): + errors.append(f"GoAdmin 技术基线缺少来源:{name}") + continue + for field, value in expected.items(): + if actual.get(field) != value: + errors.append( + f"GoAdmin 技术基线不匹配:{name}.{field} 应为 {value}" + ) + elif actual != expected: + errors.append( + f"GoAdmin 技术基线不匹配:{group}.{name} 应为 {expected}" + ) + + if baseline.get("authority") != "upstream_url_and_commit": + errors.append("GoAdmin 技术基线必须以上游 URL 和 commit 为权威标识") + rules = baseline.get("rules") + required_rules = ( + "local_repositories_are_read_only", + "product_code_must_not_be_developed_in_reference_repositories", + "preserve_upstream_license_and_copyright", + "upgrades_require_coordination_issue", + "sense_and_bell_release_independently", + ) + if not isinstance(rules, dict): + errors.append("GoAdmin 技术基线缺少 rules") + else: + for rule in required_rules: + if rules.get(rule) is not True: + errors.append(f"GoAdmin 技术基线规则必须为 true:{rule}") + + agent_requirements = { + "AGENTS.md": ( + "### Sense/Bell GoAdmin 技术基线", + "`goadmin-baseline.json`", + "上游 URL 加完整 commit 是可复现标识", + "当前机器的只读参考副本", + "必须建立 Sense/Bell 协同升级工单", + "本机 Go 1.23.0 不满足要求", + ), + "Sense/AGENTS.md": ( + "## GoAdmin 技术基线", + "读取根 `goadmin-baseline.json`", + "不得在参考仓库原地开发", + "不得单独漂移上游或工具链版本", + ), + "Bell/AGENTS.md": ( + "## GoAdmin 技术基线", + "读取根 `goadmin-baseline.json`", + "不得在参考仓库原地开发", + "不得单独漂移上游或工具链版本", + ), + } + for relative_path, required in agent_requirements.items(): + agent_path = root / relative_path + if not agent_path.is_file(): + errors.append(f"缺少 GoAdmin 基线规则文件:{relative_path}") + continue + content = agent_path.read_text(encoding="utf-8") + for section in missing_sections(content, required): + errors.append(f"{relative_path} 缺少 GoAdmin 基线规则:{section}") + + def check_claude_code_entry(errors: list[str], root: Path = ROOT) -> None: """检查 Claude Code 入口直接复用共同 Agent 规则。""" @@ -423,6 +552,7 @@ def main() -> int: check_task_template(errors) check_agent_efficiency_rules(errors) check_go_admin_ui_rules(errors) + check_goadmin_baseline(errors) check_claude_code_entry(errors) check_archives(errors) diff --git a/docs/00-project-profile.md b/docs/00-project-profile.md index 49853a1..26e3d5c 100644 --- a/docs/00-project-profile.md +++ b/docs/00-project-profile.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Project-Profile wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Project-Profile.- -wiki_revision: 4a78dc8673d88b05f1c62b254242180a68465ccd -synchronized_at: 2026-08-11T10:30:26Z +wiki_revision: 5561227400539f0a3ba7713be16c171feb811fcb +synchronized_at: 2026-08-12T01:26:47Z # 项目档案 @@ -42,7 +42,7 @@ synchronized_at: 2026-08-11T10:30:26Z - 证据:客户侧 MinIO/S3 兼容对象存储;常态录像优先留在客户已有 NVR。 - 首期验证平台:NVIDIA x86/Jetson;M1-M3 不承诺 GB/T 28181、信创或原生 App。 -业务代码尚未初始化,具体 Go/Python/Node 版本必须在对应骨架工单中冻结后更新本页。 +业务代码尚未初始化;Sense/Bell 的 Go/Node 基线已冻结并记录于下文,Brain 的 Python/CUDA 版本仍须在对应骨架工单中冻结。 ## 阅读入口 @@ -78,3 +78,17 @@ Sense、Brain、Bell 的构建、运行和测试命令尚待各自骨架工单 - 单仓包含 Sense、Brain、Bell 三个开发项目。 - 计划由三名主 agent 尽量并行处理各自独立工单;需要跨项目协作时再建立协调工单并启用新 agent。 - 旧仓库在新纵切验收前保留,不删除、不覆盖。 + +## Sense/Bell GoAdmin 固定技术基线 + +Sense、Bell 共用的可复现技术基线记录在仓库根 `goadmin-baseline.json`。正式版本标识是上游 URL 与完整 commit 的组合;本机目录、分支名、最近 tag 和 `package.json` version 只作辅助信息。 + +| 参考源 | 用途 | 冻结提交 | 描述版本 | 本机只读位置 | +|---|---|---|---|---| +| go-admin | 后端骨架 | `f06540883b41d03782bb6b2c4150f298f328c6b6` | `v2.2.0-25-gf065408` | `D:\github\goadmin\go-admin` | +| go-admin-ui | 前端骨架 | `67d393d713877572fab0b897296a4c1d525fc81d` | `v2.0.9-170-g67d393d` | `D:\github\goadmin\go-admin-ui` | +| go-admin-doc | 只读用法参考 | `424855aacf6905f3fde860c3331385cb25529a0d` | 无精确 tag | `D:\github\goadmin\go-admin-doc` | + +固定工具链为 Go 1.26.5、Node.js 22.22.1、pnpm 9.15.1。go-admin-ui 的 `package.json` version 仍为 2.0.9,但冻结提交位于 `v2.0.9` 后 170 个提交,因此不得只用“2.0.9”代表当前基线。 + +三个上游仓库均使用 MIT 许可证。派生代码必须保留许可证和版权声明。Sense、Bell 使用同一上游基线,但分别维护代码、配置、构建、测试、版本和发布。任何上游或工具链升级必须建立影响 Sense/Bell 的协同工单。 diff --git a/docs/04-local-development-and-verification.md b/docs/04-local-development-and-verification.md index 9bbd0de..74d471e 100644 --- a/docs/04-local-development-and-verification.md +++ b/docs/04-local-development-and-verification.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Local-Development-and-Verification wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Local-Development-and-Verification.- -wiki_revision: be0864a5bdbe06bd8358f2d013aa7313ab13e73b -synchronized_at: 2026-08-11T10:30:41Z +wiki_revision: 1eb27d082ebf892343c9a5eed6f9363363234903 +synchronized_at: 2026-08-12T01:26:57Z # 本地开发与验证 @@ -17,7 +17,7 @@ synchronized_at: 2026-08-11T10:30:41Z | Gitea | 工单与 Wiki | 浏览仓库或调用 MCP | | Gitea PAT | Wiki 写入 | 仅由 MCP 或 `GITEA_TOKEN` 提供,不打印 | -Go、Node、CUDA、PostgreSQL、MediaMTX 的精确要求将在对应项目骨架工单冻结;当前不把旧仓库环境当作新项目事实。 +Sense/Bell 的 Go、Node 与 pnpm 基线已冻结并记录于下文;Brain 的 Python/CUDA 以及 PostgreSQL、MediaMTX 精确版本仍将在对应骨架工单冻结。旧仓库环境不自动成为新项目事实。 ## 第一次运行 @@ -88,3 +88,25 @@ git status --short ``` 业务工单还必须运行其声明的子项目测试;跨契约工单必须运行所有受影响项目的契约测试。未执行部分写入工单。 + +## Sense/Bell 固定工具链与只读参考源 + +根 `goadmin-baseline.json` 是机器可读基线。开始 Sense/Bell 骨架或升级工作前,先核对: + +```powershell +Get-Content .\goadmin-baseline.json + +git -C D:\github\goadmin\go-admin rev-parse HEAD +git -C D:\github\goadmin\go-admin-ui rev-parse HEAD +git -C D:\github\goadmin\go-admin-doc rev-parse HEAD + +go version +node --version +pnpm --version +``` + +`D:\github\goadmin` 下三个仓库只允许读取和核对,不允许在其中开发或提交 yovision 产品代码。本机路径不是跨机器事实;缺少该路径时,应从清单中的上游 URL 检出相同 commit 到仓库外目录。 + +截至 2026-08-12 的本机核对结果:Go 1.23.0,不满足 go-admin `go.mod` 声明的 Go 1.26.5;Node.js 22.22.1 符合基线;pnpm 尚未安装,Corepack 0.34.6 可用。因此后端构建和 pnpm 前端构建均未完成验证。安装隔离的 Go 1.26.5 并通过 Corepack 启用 pnpm 9.15.1 后,才可执行后续骨架构建验收。 + +`go-admin-doc` 只用于理解上游框架;项目自己的架构、开发规则和版本事实仍以 yovision Wiki、Agent 规则与 `goadmin-baseline.json` 为准。 diff --git a/goadmin-baseline.json b/goadmin-baseline.json new file mode 100644 index 0000000..b8d7a50 --- /dev/null +++ b/goadmin-baseline.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "frozen_at": "2026-08-12", + "authority": "upstream_url_and_commit", + "consumers": [ + "Sense", + "Bell" + ], + "runtimes": { + "go": "1.26.5", + "node": "22.22.1", + "package_manager": "pnpm", + "pnpm": "9.15.1" + }, + "sources": { + "go-admin": { + "role": "backend_baseline", + "local_reference_path": "D:\\github\\goadmin\\go-admin", + "upstream_url": "https://github.com/go-admin-team/go-admin.git", + "branch": "master", + "commit": "f06540883b41d03782bb6b2c4150f298f328c6b6", + "describe": "v2.2.0-25-gf065408", + "exact_tag": null, + "license": "MIT", + "license_file": "LICENSE.md" + }, + "go-admin-ui": { + "role": "frontend_baseline", + "local_reference_path": "D:\\github\\goadmin\\go-admin-ui", + "upstream_url": "https://github.com/go-admin-team/go-admin-ui.git", + "branch": "master", + "commit": "67d393d713877572fab0b897296a4c1d525fc81d", + "describe": "v2.0.9-170-g67d393d", + "exact_tag": null, + "package_version": "2.0.9", + "package_version_is_authoritative": false, + "license": "MIT", + "license_file": "LICENSE" + }, + "go-admin-doc": { + "role": "reference_only_documentation", + "local_reference_path": "D:\\github\\goadmin\\go-admin-doc", + "upstream_url": "https://github.com/go-admin-team/go-admin-doc.git", + "branch": "master", + "commit": "424855aacf6905f3fde860c3331385cb25529a0d", + "describe": "424855a", + "exact_tag": null, + "package_version": "0.0.1", + "package_version_is_authoritative": false, + "license": "MIT", + "license_file": "LICENSE" + } + }, + "rules": { + "local_repositories_are_read_only": true, + "product_code_must_not_be_developed_in_reference_repositories": true, + "preserve_upstream_license_and_copyright": true, + "upgrades_require_coordination_issue": true, + "sense_and_bell_release_independently": true + } +} diff --git a/tests/test_harness_docs.py b/tests/test_harness_docs.py index c8ab0df..2c0b360 100644 --- a/tests/test_harness_docs.py +++ b/tests/test_harness_docs.py @@ -17,6 +17,7 @@ from check_harness import ( # noqa: E402 check_core_documents, check_agent_efficiency_rules, check_go_admin_ui_rules, + check_goadmin_baseline, check_task_template, core_mapping_errors, missing_sections, @@ -213,6 +214,36 @@ class AgentRuleTests(unittest.TestCase): self.assertIn("缺少 go-admin 规则文件:Sense/AGENTS.md", errors) self.assertIn("缺少 go-admin 规则文件:Bell/AGENTS.md", errors) + def test_goadmin_baseline_is_frozen(self) -> None: + errors: list[str] = [] + check_goadmin_baseline(errors) + self.assertEqual(errors, []) + + def test_goadmin_baseline_rejects_unpinned_source(self) -> None: + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + (root / "goadmin-baseline.json").write_text( + '{"authority":"tag","runtimes":{},' + '"sources":{"go-admin":{}},"rules":{}}', + encoding="utf-8", + ) + errors: list[str] = [] + check_goadmin_baseline(errors, root) + self.assertTrue(any("go-admin.commit" in error for error in errors)) + self.assertIn( + "GoAdmin 技术基线必须以上游 URL 和 commit 为权威标识", + errors, + ) + + def test_goadmin_baseline_reports_missing_file(self) -> None: + with tempfile.TemporaryDirectory() as directory: + errors: list[str] = [] + check_goadmin_baseline(errors, Path(directory)) + self.assertEqual( + errors, + ["缺少 GoAdmin 技术基线:goadmin-baseline.json"], + ) + def test_claude_code_entry_requires_exact_import_line(self) -> None: with tempfile.TemporaryDirectory() as directory: root = Path(directory)