扩展氢能站点、加氢记录与台账原型链路,新增工作台、车辆资产 H5、自营物流等原型,并同步导航注册、PRD 资源与交付技能。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
王冕
2026-07-21 17:15:39 +08:00
parent e39df1c7c8
commit a01d2ab708
242 changed files with 102296 additions and 4866 deletions

View File

@@ -0,0 +1,314 @@
#!/usr/bin/env python3
"""Validate and render a OneOS delivery-model Yunxiao project profile."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from typing import Any
TARGET_LIFECYCLE = [
"待处理", "已确认", "分析中", "分析完成", "设计中", "设计完成",
"待开发", "开发中", "开发完成", "待测试", "测试中", "测试完成",
"发布中", "发布完成", "发布失败", "已关闭",
]
REQUIRED_TASK_LABELS = {"交付", "开发", "测试", "发版"}
REQUIRED_CONTROL_IDS = {
*(f"Y{index:02d}" for index in range(1, 17)),
"Y20", "Y21", "Y22",
*(f"Y{index:02d}" for index in range(30, 36)),
"Y40",
"A01", "A02", "A02B", *(f"A{index:02d}" for index in range(3, 11)),
*(f"TC{index:02d}" for index in range(1, 4)),
*(f"DF{index:02d}" for index in range(1, 4)),
*(f"CI{index:02d}" for index in range(1, 4)),
"L01", "L02",
}
VALID_MODES = {
"manual", "native_rule", "integration_bridge", "disabled_legacy", "not_supported"
}
VALID_PHASES = {"P0", "P1", "P2", "P3"}
VALID_TASK_WORKFLOW_MODES = {"A", "B"}
VALID_TASK_IDENTITY_MODES = {"work_item_type", "task_label", "title_prefix_process_control"}
VALID_LEGACY_DISPOSITIONS = {"keep_until_ready", "disable", "replace", "already_disabled"}
SENSITIVE_FRAGMENTS = (
"password", "passwd", "secret", "token", "cookie", "credential",
"private_key", "otp", "密码", "密钥",
)
def is_text(value: Any) -> bool:
return isinstance(value, str) and bool(value.strip())
def require_text(container: dict[str, Any], key: str, label: str, errors: list[str]) -> None:
if not is_text(container.get(key)):
errors.append(f"{label}.{key} 不能为空")
def walk_sensitive_keys(value: Any, prefix: str = "") -> list[str]:
found: list[str] = []
if isinstance(value, dict):
for key, nested in value.items():
current = f"{prefix}.{key}" if prefix else str(key)
if any(fragment in str(key).lower() for fragment in SENSITIVE_FRAGMENTS):
found.append(current)
found.extend(walk_sensitive_keys(nested, current))
elif isinstance(value, list):
for index, nested in enumerate(value):
found.extend(walk_sensitive_keys(nested, f"{prefix}[{index}]"))
return found
def validate_controls(controls: Any, label: str, errors: list[str]) -> None:
if not isinstance(controls, list):
errors.append(f"{label} 必须是数组")
return
seen: set[str] = set()
for index, control in enumerate(controls):
item_label = f"{label}[{index}]"
if not isinstance(control, dict):
errors.append(f"{item_label} 必须是对象")
continue
control_id = control.get("id")
if not is_text(control_id):
errors.append(f"{item_label}.id 不能为空")
continue
if control_id in seen:
errors.append(f"{label} 控制项重复:{control_id}")
seen.add(control_id)
if control_id not in REQUIRED_CONTROL_IDS:
errors.append(f"{label} 未知控制项:{control_id}")
mode = control.get("mode")
if mode not in VALID_MODES:
errors.append(f"{item_label}.mode 不合法")
if not isinstance(control.get("enabled"), bool):
errors.append(f"{item_label}.enabled 必须是布尔值")
if mode in {"disabled_legacy", "not_supported"} and control.get("enabled") is not False:
errors.append(f"{item_label}{mode} 模式要求 enabled=false")
if control_id in {"L01", "L02"}:
if mode != "disabled_legacy" or control.get("enabled") is not False:
errors.append(f"{item_label} 必须停用,防止发布完成绕过验收")
for key in ("owner", "fallback", "evidence"):
require_text(control, key, item_label, errors)
missing = sorted(REQUIRED_CONTROL_IDS - seen)
if missing:
errors.append(f"{label} 缺少控制项:" + "".join(missing))
def validate_project(project: Any, index: int, errors: list[str]) -> None:
label = f"projects[{index}]"
if not isinstance(project, dict):
errors.append(f"{label} 必须是对象")
return
require_text(project, "name", label, errors)
if project.get("migration_phase") not in VALID_PHASES:
errors.append(f"{label}.migration_phase 必须是 P0/P1/P2/P3")
statuses = project.get("requirement_statuses_observed")
if not isinstance(statuses, list) or not statuses or not all(is_text(v) for v in statuses):
errors.append(f"{label}.requirement_statuses_observed 必须是非空文本数组")
if project.get("task_workflow_mode") not in VALID_TASK_WORKFLOW_MODES:
errors.append(f"{label}.task_workflow_mode 必须是 A 或 B")
if project.get("task_identity_mode") not in VALID_TASK_IDENTITY_MODES:
errors.append(f"{label}.task_identity_mode 不合法")
if not isinstance(project.get("native_rule_can_filter_related_task_identity"), bool):
errors.append(f"{label}.native_rule_can_filter_related_task_identity 必须是布尔值")
for key in (
"main_task_prefix", "development_task_prefix", "test_task_prefix", "release_task_prefix"
):
require_text(project, key, label, errors)
repositories = project.get("repositories")
if not isinstance(repositories, list) or not repositories:
errors.append(f"{label}.repositories 至少包含一个仓库")
else:
for repo_index, repo in enumerate(repositories):
repo_label = f"{label}.repositories[{repo_index}]"
if not isinstance(repo, dict):
errors.append(f"{repo_label} 必须是对象")
continue
for key in ("name", "role", "integration_branch", "evidence"):
require_text(repo, key, repo_label, errors)
if repo.get("integration_branch") not in {"dev", "develop"}:
errors.append(f"{repo_label}.integration_branch 只能是实际存在的 dev/develop")
for key in ("codeup_integrated", "required_for_mr_gate"):
if not isinstance(repo.get(key), bool):
errors.append(f"{repo_label}.{key} 必须是布尔值")
test_plan = project.get("test_plan")
if not isinstance(test_plan, dict):
errors.append(f"{label}.test_plan 必须是对象")
else:
require_text(test_plan, "name", f"{label}.test_plan", errors)
require_text(test_plan, "evidence", f"{label}.test_plan", errors)
for key, required in (
("iteration_formally_related", True),
("cases_partitioned_by_requirement", True),
("fixed_defect_is_terminal", False),
("tester_retest_required", True),
):
if test_plan.get(key) is not required:
errors.append(f"{label}.test_plan.{key} 必须为 {str(required).lower()}")
release = project.get("release")
if not isinstance(release, dict):
errors.append(f"{label}.release 必须是对象")
else:
require_text(release, "evidence", f"{label}.release", errors)
for key in (
"release_task_formally_related_to_iteration",
"production_evidence_separate_from_test",
"acceptance_required_after_release",
"production_pipeline_unchanged",
):
if release.get(key) is not True:
errors.append(f"{label}.release.{key} 必须为 true")
legacy_rules = project.get("legacy_rules")
if not isinstance(legacy_rules, list):
errors.append(f"{label}.legacy_rules 必须是数组")
else:
for legacy_index, rule in enumerate(legacy_rules):
item_label = f"{label}.legacy_rules[{legacy_index}]"
if not isinstance(rule, dict):
errors.append(f"{item_label} 必须是对象")
continue
for key in ("name", "reason", "evidence"):
require_text(rule, key, item_label, errors)
if rule.get("disposition") not in VALID_LEGACY_DISPOSITIONS:
errors.append(f"{item_label}.disposition 不合法")
if not isinstance(rule.get("enabled"), bool):
errors.append(f"{item_label}.enabled 必须是布尔值")
validate_controls(project.get("controls"), f"{label}.controls", errors)
def validate(data: dict[str, Any]) -> list[str]:
errors: list[str] = []
if data.get("schema_version") != 1:
errors.append("schema_version 必须为 1")
if data.get("flow_model") != "oneos_delivery":
errors.append("flow_model 必须为 oneos_delivery")
for key in ("organization", "work_item_type"):
require_text(data, key, "profile", errors)
if data.get("target_lifecycle") != TARGET_LIFECYCLE:
errors.append("target_lifecycle 必须与OneOS终态16状态顺序一致")
labels = data.get("task_labels")
if not isinstance(labels, list) or not REQUIRED_TASK_LABELS.issubset(set(labels)):
errors.append("task_labels 必须包含:交付、开发、测试、发版")
policies = data.get("policies")
if not isinstance(policies, dict):
errors.append("policies 必须是对象")
else:
true_keys = (
"require_formal_relations", "require_current_state_condition",
"require_nonzero_development_tasks",
"require_signed_timestamped_replay_protected_callbacks",
)
false_keys = ("allow_automatic_final_close_without_acceptance", "test_success_is_production_release")
for key in true_keys:
if policies.get(key) is not True:
errors.append(f"policies.{key} 必须为 true")
for key in false_keys:
if policies.get(key) is not False:
errors.append(f"policies.{key} 必须为 false")
parts = policies.get("bridge_idempotency_key_components")
if not isinstance(parts, list) or not parts or not all(is_text(v) for v in parts):
errors.append("policies.bridge_idempotency_key_components 不能为空")
projects = data.get("projects")
if not isinstance(projects, list) or not projects:
errors.append("projects 至少包含一个项目")
else:
for index, project in enumerate(projects):
validate_project(project, index, errors)
sensitive = walk_sensitive_keys(data)
if sensitive:
errors.append("配置中禁止出现敏感字段:" + "".join(sensitive))
if "请填写" in json.dumps(data, ensure_ascii=False):
errors.append("仍存在“请填写”占位符")
return errors
def render(data: dict[str, Any]) -> str:
lines = [
"# OneOS云效终态交付模型执行计划", "",
f"- 组织:{data['organization']}",
f"- 工作项类型:{data['work_item_type']}",
f"- 项目数:{len(data['projects'])}",
"- 完整性口径每项目48项Y/A/测试/缺陷/集成/旧规则控制。",
"- 安全边界:不修改生产流水线;发布完成后保留产品验收门禁。", "",
]
for project in data["projects"]:
missing_statuses = [s for s in TARGET_LIFECYCLE if s not in project["requirement_statuses_observed"]]
lines.extend([
f"## 项目:{project['name']}", "",
f"- 迁移阶段:{project['migration_phase']}",
f"- 任务工作流方案:{project['task_workflow_mode']}",
f"- 任务身份方式:{project['task_identity_mode']}",
f"- 原生规则可过滤关联任务身份:{'' if project['native_rule_can_filter_related_task_identity'] else ''}",
f"- 缺少目标状态:{''.join(missing_statuses) if missing_statuses else ''}", "",
"### 旧规则处置", "",
"| 规则 | 处置 | 启用 | 原因 | 证据 |", "|---|---|---|---|---|",
])
for rule in project["legacy_rules"]:
lines.append(
f"| {rule['name']} | {rule['disposition']} | {'' if rule['enabled'] else ''} | "
f"{rule['reason']} | {rule['evidence']} |"
)
lines.extend([
"", "### 48项控制台账", "",
"| ID | 方式 | 启用 | 负责人 | 回退方案 | 证据 |", "|---|---|---|---|---|---|",
])
for control in sorted(project["controls"], key=lambda item: item["id"]):
lines.append(
f"| {control['id']} | {control['mode']} | {'' if control['enabled'] else ''} | "
f"{control['owner']} | {control['fallback']} | {control['evidence']} |"
)
lines.extend([
"", "### 迁移门禁", "",
"- [ ] 目标状态与流转边已补齐。",
"- [ ] 主任务可可靠识别或已明确交桥接。",
"- [ ] 多仓库需求与开发任务均正式关联分支/MR。",
"- [ ] Testhub按需求分包且缺陷复测闭环。",
"- [ ] test、生产发布和产品验收证据分离。",
"- [ ] L01、L02已停用旧规则已有备份和回滚。", "",
])
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
subparsers = parser.add_subparsers(dest="command", required=True)
validate_parser = subparsers.add_parser("validate")
validate_parser.add_argument("profile", type=Path)
render_parser = subparsers.add_parser("render")
render_parser.add_argument("profile", type=Path)
render_parser.add_argument("--output", required=True, type=Path)
args = parser.parse_args()
try:
with args.profile.open("r", encoding="utf-8-sig") as handle:
data = json.load(handle)
if not isinstance(data, dict):
raise ValueError("配置根节点必须是JSON对象")
errors = validate(data)
except (OSError, json.JSONDecodeError, ValueError) as error:
print(f"配置读取失败:{error}", file=sys.stderr)
return 2
if errors:
for error in errors:
print(f"[错误] {error}", file=sys.stderr)
return 1
if args.command == "validate":
print(f"[通过] OneOS配置有效{len(data['projects'])}个项目每项目48项控制。")
return 0
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_text(render(data), encoding="utf-8")
print(f"[完成] 已生成执行计划:{args.output}")
return 0
if __name__ == "__main__":
raise SystemExit(main())