refactor: 本仓升为唯一源(原 sap-cli 源码仓归档)

方向反转:此前 SKILL.md 是「模板渲染产物」、sap-cli 是源;现 sap-cli 归档,
sap-cli-skill 承接开发与分发,SKILL.md 回归手工维护的正本。

迁移(来自 sap-cli,共 104 文件):
- tests/           692 例测试(15 个文件的内联 sys.path 改指 assets/)
- openspec/        SDD 规格与归档变更(42 文件)
- docs/            开发文档与 ADT 原理(含 dev/CLAUDE.md、AGENTS.md)
- .claude/         rules 副本 + settings.json(供 Claude Code)
- .github/ .hermes/ .pre-commit-config.yaml .editorconfig CLAUDE.md
- scripts/ 保持仅 setup.py(pack_skill.py 已随旧仓归档,不迁)

修复(迁移暴露的真实缺陷):
- assets/pyproject.toml 的 build-backend 写作 `setuptools.backends._legacy:_Backend`,
  该模块在 setuptools 中不存在 → `pip install -e` 从来装不上。改为 build_meta。
  实测:临时 venv 安装成功,sap-cli --help 正常列出 31 个命令
- pyproject readme 指向不存在的 assets/README.md(editable 安装会失败)→ 改内联文本
- pyproject urls 改指 sap-cli-skill

机制调整:
- .github/workflows/ci.yml 适配 assets/ 布局;顶部注明该工作流仅 GitHub 执行,
  本仓在 Gitee 不会自动跑
- pre-commit 增本地测试门禁(Gitee 上真正生效的那道)
- .gitignore 合并旧仓完整规则(保留 log/ 下 md 知识库入库,只忽略运行日志)
- 大文件上限 100KB→1MB(架构图 512KB)

守卫测试 tests/unit/test_repo_guards.py(10 → 18 例):
- SKILL.md 须记录 parser 全部 CLI 命令 / 铁律 1-5 须为真实小节标题 / 示例不得违反铁律 5
- references/ 规则齐备;.claude/rules 与 references 必须一致(实测抓到一次真实漂移)
- VERSION == sapcli.__version__ == README 版本
- 仓内不得再出现 pack_skill.py / skill-src(防废弃流程回潮)

698 tests OK;editable 安装与 CLI 入口经临时 venv 实测通过。
docs/RELEASING.md 重写为单源开发流程。
This commit is contained in:
吴让宇
2026-09-11 00:40:15 +08:00
parent e786742bcb
commit c5905a5b1e
104 changed files with 20744 additions and 10 deletions
+83
View File
@@ -0,0 +1,83 @@
# Batch Operations Specification
## Purpose
定义 sap-cli 的项目级批量操作行为,包括项目初始化、清单管理、目录扫描、依赖排序和批量同步。
## Requirements
### Requirement: Project Initialization
系统 SHALL 初始化一个 ABAP 项目目录结构。
#### Scenario: Init new project
- **WHEN** 用户执行 init 命令并指定项目路径
- **THEN** 系统创建标准目录结构(reports/、classes/ 等约定目录)和空的 manifest.json
### Requirement: Manifest Management
系统 SHALL 管理项目清单文件,记录所有开发对象的状态。
#### Scenario: Manifest tracks objects
- **WHEN** 对象被创建、同步或删除后
- **THEN** 清单文件自动更新对象的状态、最后同步时间和同步结果
#### Scenario: Query pending objects
- **WHEN** 清单中存在未成功同步的对象
- **THEN** 系统能够识别并列出这些待处理对象
### Requirement: Directory Scanning
系统 SHALL 扫描本地项目目录,自动识别 ABAP 开发对象文件。
#### Scenario: Scan standard directories
- **WHEN** 项目目录包含约定命名的子目录(reports/、classes/、functions/ 等)及其中的 .abap 文件
- **THEN** 系统识别每个文件对应的对象名称、类型和路径
#### Scenario: Function directory structure
- **WHEN** 扫描 functions/ 目录
- **THEN** 子目录名解析为函数组名,文件名解析为函数模块名
#### Scenario: Skip hidden files
- **WHEN** 目录中存在以 . 开头的文件
- **THEN** 系统跳过这些隐藏文件
### Requirement: Dependency Sorting
系统 SHALL 根据对象间依赖关系确定正确的执行顺序。
#### Scenario: Sort by dependency
- **WHEN** 对象之间存在依赖关系
- **THEN** 被依赖的对象排在前面(如接口在类之前)
#### Scenario: Detect cyclic dependency
- **WHEN** 对象间存在循环依赖
- **THEN** 系统报告循环依赖错误并显示循环链
#### Scenario: Ignore external dependencies
- **WHEN** 对象依赖了不在当前项目中的外部对象
- **THEN** 系统忽略该外部依赖,不报错
### Requirement: Batch Sync
系统 SHALL 支持项目级批量同步操作。
#### Scenario: Sync all objects
- **WHEN** 用户执行 sync --all 命令
- **THEN** 系统扫描项目、按依赖排序、逐个同步所有对象
#### Scenario: Dry run mode
- **WHEN** 用户执行 sync --all --dry-run
- **THEN** 系统仅显示将要同步的对象列表,不实际执行
#### Scenario: Fail fast mode
- **WHEN** 用户执行 sync --all --fail-fast
- **THEN** 任一对象同步失败时立即停止,不继续后续对象
### Requirement: Status Refresh
系统 SHALL 刷新项目清单中所有对象在 SAP 系统中的状态。
#### Scenario: Refresh object status
- **WHEN** 用户执行 refresh 命令
- **THEN** 系统查询每个对象在 SAP 中的最新状态并更新清单
+47
View File
@@ -0,0 +1,47 @@
# Configuration Management Specification
## Purpose
定义 sap-cli 的配置管理功能行为,包括配置查看、设置和多 profile 管理。
## Requirements
### Requirement: Configuration Display
系统 SHALL 显示当前的 SAP 连接配置。
#### Scenario: Show current config
- **WHEN** 用户执行 config show 命令
- **THEN** 系统显示当前生效的配置项(主机、客户端、用户名),密码以掩码显示
### Requirement: Configuration Setting
系统 SHALL 支持通过命令行设置配置项。
#### Scenario: Set config value
- **WHEN** 用户执行 config set 命令并指定键和值
- **THEN** 系统将配置值保存到配置文件中
### Requirement: Multi-Profile Management
系统 SHALL 支持多 SAP 系统配置 profile。
#### Scenario: List profiles
- **WHEN** 用户执行 config list 命令
- **THEN** 系统显示所有已配置的 profile 列表
#### Scenario: Use specific profile
- **WHEN** 用户通过 --profile 参数指定 profile
- **THEN** 系统使用该 profile 的配置连接对应的 SAP 系统
### Requirement: Secure Password Storage
系统 SHALL 支持通过系统密钥环安全存储 SAP 密码。
#### Scenario: Save password to keyring
- **WHEN** 用户配置密码存储选项
- **THEN** 密码保存到操作系统密钥环而非明文配置文件
#### Scenario: Load password from keyring
- **WHEN** 配置文件中未指定密码但密钥环中存在
- **THEN** 系统从密钥环读取密码
+55
View File
@@ -0,0 +1,55 @@
# Connection Specification
## Purpose
定义 sap-cli 与 SAP 系统建立连接、完成身份认证和会话管理的行为。
## Requirements
### Requirement: User Authentication
系统 SHALL 通过 SAP ADT REST API 使用 HTTP Basic Auth 进行身份认证。
#### Scenario: Successful login
- **WHEN** 用户提供有效的 SAP 主机地址、客户端编号、用户名和密码
- **THEN** 系统打印 "登录成功" 并建立可用会话
#### Scenario: Login failure
- **WHEN** 用户提供了无效的 SAP 凭据
- **THEN** 系统打印错误信息并以非零退出码退出
#### Scenario: Config not found
- **WHEN** 用户未提供配置文件且未设置环境变量
- **THEN** 系统打印配置缺失提示,列出需要的环境变量名称,并以非零退出码退出
### Requirement: Configuration Loading
系统 SHALL 支持 config.ini 文件和环境变量两种配置方式,环境变量优先于配置文件。
#### Scenario: Load from config file
- **WHEN** 用户运行命令且当前目录或指定路径存在有效的 config.ini
- **THEN** 系统从配置文件读取 SAP 连接参数
#### Scenario: Environment variable override
- **WHEN** 同时存在配置文件和环境变量
- **THEN** 环境变量值覆盖配置文件中的对应项
#### Scenario: Profile selection
- **WHEN** 用户通过 --profile 参数指定配置 section
- **THEN** 系统从 config.ini 的对应 section 读取配置
#### Scenario: Client number default
- **WHEN** 配置中未指定 SAP 客户端编号
- **THEN** 系统使用默认值 "100"
### Requirement: Global Options
系统 SHALL 支持全局命令行选项。
#### Scenario: Custom config path
- **WHEN** 用户通过 --config 指定配置文件路径
- **THEN** 系统从指定路径加载配置
#### Scenario: No command specified
- **WHEN** 用户运行程序但未指定任何子命令
- **THEN** 系统打印帮助信息并以退出码 1 退出
+186
View File
@@ -0,0 +1,186 @@
# Object Lifecycle Specification
## Purpose
定义 sap-cli 对 SAP 开发对象的创建、读取(下载源码和信息查询)、更新(同步)、删除操作行为。
涵盖所有支持的对象类型:report、class、interface、function、functiongroup、domain、dataelement、table、structure、tabletype、messageclass、view、searchhelp、lockobject、cdsview、include。
## Requirements
### Requirement: Object Creation
系统 SHALL 在 SAP 系统中创建开发对象,支持 16 种对象类型。
#### Scenario: Create with default template
- **WHEN** 用户执行 create 命令,指定对象名称和类型,未提供自定义源码
- **THEN** 系统使用内置模板生成源码并在 SAP 中创建对象
#### Scenario: Create with custom source file
- **WHEN** 用户通过 --source 参数指定本地 .abap 文件
- **THEN** 系统读取文件内容作为源码并在 SAP 中创建对象
#### Scenario: Create DDIC object with definition
- **WHEN** 用户通过 --definition 参数指定 .json 文件创建 DDIC 对象(domain、dataelement、table、structure、tabletype
- **THEN** 系统将 JSON 定义转换为 SAP 所需格式并创建对象
#### Scenario: Create message class
- **WHEN** 用户执行 create 命令,指定类型为 messageclass,并提供名称和描述
- **THEN** 系统在 SAP 中创建消息类对象
#### Scenario: Create database view
- **WHEN** 用户执行 create 命令,指定类型为 view,并提供 JSON 定义文件
- **THEN** 系统将 JSON 转换为 DDIC XML 并在 SAP 中创建数据库视图
#### Scenario: Create search help
- **WHEN** 用户执行 create 命令,指定类型为 searchhelp,并提供 JSON 定义文件
- **THEN** 系统将 JSON 转换为 DDIC XML 并在 SAP 中创建搜索帮助
#### Scenario: Create lock object
- **WHEN** 用户执行 create 命令,指定类型为 lockobject,并提供 JSON 定义文件
- **THEN** 系统将 JSON 转换为 DDIC XML 并在 SAP 中创建锁对象
#### Scenario: Create already existing object
- **WHEN** SAP 系统中已存在同名同类型对象
- **THEN** 系统报告对象已存在的错误
#### Scenario: Create with transport request
- **WHEN** 用户通过 --corr_nr 指定传输请求号
- **THEN** 创建的对象绑定到指定的传输请求
### Requirement: Source Code Download
系统 SHALL 从 SAP 系统下载对象源代码并保存到本地文件。
#### Scenario: Download existing object
- **WHEN** 用户执行 download 命令,SAP 系统存在该对象
- **THEN** 系统下载源码并保存到指定目录,文件名为小写对象名+.abap
#### Scenario: Download non-existent object
- **WHEN** 用户执行 download 命令,SAP 系统不存在该对象
- **THEN** 系统报告对象不存在的错误
#### Scenario: Download function type
- **WHEN** 用户下载 function 类型对象,名称格式为 "组名/模块名"
- **THEN** 系统正确下载函数模块源码
#### Scenario: Download type without source
- **WHEN** 用户尝试下载不支持源码的类型(如 functiongroup、messageclass、lockobject
- **THEN** 系统报告该类型不支持下载操作
#### Scenario: Download database view source
- **WHEN** 用户下载 view 类型对象
- **THEN** 系统下载视图的 DDL 定义源码
### Requirement: Source Code Sync
系统 SHALL 将本地源代码同步到 SAP 系统,执行完整的锁定→写入→解锁→检查→激活流程。
#### Scenario: Full sync success
- **WHEN** 用户执行 sync 命令,本地文件和 SAP 对象均有效
- **THEN** 系统依次执行锁定、写入、解锁、语法检查、激活,每步报告进度
#### Scenario: Auto-create on sync
- **WHEN** 用户同步一个 SAP 中不存在的对象
- **THEN** 系统自动创建空对象后继续同步流程
#### Scenario: Syntax check failure
- **WHEN** 源码包含语法错误
- **THEN** 系统报告语法错误详情(行号和描述)
#### Scenario: Activation failure
- **WHEN** 语法检查通过但激活失败
- **THEN** 系统报告激活错误详情
#### Scenario: Sync with specified transport request
- **WHEN** 用户通过 --corr_nr 指定传输请求号
- **THEN** 系统在整个同步流程中使用该传输请求
### Requirement: Object Information Query
系统 SHALL 查询 SAP 系统中所有支持类型的开发对象元数据。
#### Scenario: Query existing object
- **WHEN** 用户执行 info 命令,SAP 系统存在该对象
- **THEN** 系统显示对象的名称、类型、描述、激活状态、负责人等元数据
#### Scenario: Query non-existent object
- **WHEN** 用户执行 info 命令,SAP 系统不存在该对象
- **THEN** 系统报告对象不存在的错误
#### Scenario: Query message class info
- **WHEN** 用户执行 info 命令查询消息类
- **THEN** 系统显示消息类的名称、描述、消息数量等元数据
#### Scenario: Query view info
- **WHEN** 用户执行 info 命令查询数据库视图
- **THEN** 系统显示视图的名称、描述、关联表等元数据
### Requirement: Object Deletion
系统 SHALL 从 SAP 系统中删除所有支持类型的开发对象。
#### Scenario: Delete with confirmation
- **WHEN** 用户执行 delete 命令并确认删除操作
- **THEN** 系统锁定、删除对象并报告成功
#### Scenario: Delete cancelled
- **WHEN** 用户执行 delete 命令但未确认删除
- **THEN** 系统取消操作,不执行删除
#### Scenario: Delete non-existent object
- **WHEN** 用户尝试删除 SAP 中不存在的对象
- **THEN** 系统报告对象不存在的错误
#### Scenario: Delete message class
- **WHEN** 用户执行 delete 命令删除消息类并确认
- **THEN** 系统删除该消息类
#### Scenario: Delete lock object
- **WHEN** 用户执行 delete 命令删除锁对象并确认
- **THEN** 系统删除该锁对象及其自动生成的函数模块
### Requirement: Source Code Upload
系统 SHALL 上传本地源代码到 SAP 系统,执行锁定→写入→解锁流程,不执行语法检查和激活。
upload 不会自动创建对象——上传前对象必须已存在于 SAP 系统中。
#### Scenario: Upload success
- **WHEN** 用户执行 upload 命令,对象已存在于 SAP,本地文件有效
- **THEN** 系统执行锁定、写入源码、解锁,报告写入的字符数和行数,不执行语法检查和激活
#### Scenario: Upload non-existent object
- **WHEN** 用户上传一个 SAP 中不存在的对象
- **THEN** 系统报告对象不存在的错误(不自动创建,区别于 sync)
#### Scenario: Upload with transport request
- **WHEN** 用户通过 --corr_nr 指定传输请求号
- **THEN** 系统使用该传输请求号进行锁定和写入
#### Scenario: Upload type without source
- **WHEN** 用户尝试上传不支持源码的类型(如 functiongroup、tabletype、messageclass、searchhelp、lockobject
- **THEN** 系统报告该类型不支持上传操作
#### Scenario: Upload local file not found
- **WHEN** 用户指定的本地源码文件路径不存在
- **THEN** 系统报告文件不存在的错误
### Requirement: Syntax Check
系统 SHALL 对 SAP 远程对象的源代码执行语法检查,不上传代码、不激活。
syntax-check 检查 SAP 上现有对象的源码(通常是 active 状态),用于验证结构变更后的依赖影响。
#### Scenario: Syntax check passed
- **WHEN** 用户执行 syntax-check 命令,对象的源码无语法错误
- **THEN** 系统报告语法检查通过
#### Scenario: Syntax check failed
- **WHEN** 对象源码包含语法错误
- **THEN** 系统报告语法检查未通过,显示每个错误的行号和描述
#### Scenario: Syntax check non-existent object
- **WHEN** 用户对 SAP 中不存在的对象执行语法检查
- **THEN** 系统报告对象不存在的错误
#### Scenario: Syntax check type without source
- **WHEN** 用户对不支持源码的类型(如 functiongroup、tabletype)执行语法检查
- **THEN** 系统报告该类型不支持语法检查操作
+47
View File
@@ -0,0 +1,47 @@
# Code Quality Specification
## Purpose
定义 sap-cli 的代码质量相关功能行为,包括 ATC 检查和代码格式化。
## Requirements
### Requirement: ATC Code Check
系统 SHALL 对 SAP 开发对象执行 ABAP Test Cockpit (ATC) 代码检查。
#### Scenario: Check with findings
- **WHEN** 用户执行 check 命令并指定对象名称和类型
- **THEN** 系统显示 ATC 检查发现的问题列表(优先级、位置、描述)
#### Scenario: Check clean
- **WHEN** ATC 检查未发现任何问题
- **THEN** 系统显示检查通过的信息
### Requirement: Code Formatting
系统 SHALL 对 SAP 开发对象执行 ABAP Pretty Printer 格式化。
#### Scenario: Format source code
- **WHEN** 用户执行 format 命令并指定对象名称和类型
- **THEN** 系统对 SAP 中的源码执行格式化并报告结果
### Requirement: Dependency Analysis
系统 SHALL 自动分析项目中对象的依赖关系。
#### Scenario: Analyze project dependencies
- **WHEN** 用户执行 analyze 命令并指定项目路径
- **THEN** 系统扫描源码中的依赖引用并生成依赖报告
### Requirement: Project Scaffolding
系统 SHALL 根据预定义模板创建 ABAP 项目结构。
#### Scenario: Scaffold from template
- **WHEN** 用户执行 scaffold 命令并指定名称和模板类型
- **THEN** 系统基于模板生成包含源码文件的项目结构
#### Scenario: List available templates
- **WHEN** 用户执行 scaffold 命令但未指定模板
- **THEN** 系统显示可用的模板列表
+79
View File
@@ -0,0 +1,79 @@
# Search and Browse Specification
## Purpose
定义 sap-cli 的搜索和浏览功能行为,包括对象列表、引用查询和源码搜索。
## Requirements
### Requirement: Object Listing
系统 SHALL 列出 SAP 系统中指定类型的开发对象。
#### Scenario: List by type with prefix
- **WHEN** 用户执行 list 命令并指定对象类型和前缀筛选
- **THEN** 系统显示匹配的对象名称列表
#### Scenario: List without filter
- **WHEN** 用户执行 list 命令但未指定筛选条件
- **THEN** 系统显示该类型的所有可访问对象
### Requirement: Where-Used Query
系统 SHALL 查询指定对象在其他开发对象中的引用关系。
#### Scenario: Find references
- **WHEN** 用户执行 whereused 命令并指定对象名称和类型
- **THEN** 系统显示所有引用该对象的开发对象列表
#### Scenario: No references found
- **WHEN** 指定对象没有被任何其他对象引用
- **THEN** 系统显示无引用结果的信息
### Requirement: Source Code Search
系统 SHALL 在 SAP 系统中搜索源代码内容。
#### Scenario: Search by keyword
- **WHEN** 用户执行 search 命令并提供搜索关键词
- **THEN** 系统显示包含该关键词的对象名称、类型和匹配行
#### Scenario: Search no results
- **WHEN** 搜索关键词没有匹配结果
- **THEN** 系统显示无搜索结果的信息
### Requirement: Code Diff
系统 SHALL 对比本地源码与 SAP 系统中当前版本的差异。
#### Scenario: Diff with differences
- **WHEN** 用户执行 diff 命令,本地文件与 SAP 版本存在差异
- **THEN** 系统显示差异内容(新增、删除、修改的行)
#### Scenario: Diff identical
- **WHEN** 本地文件与 SAP 版本完全一致
- **THEN** 系统显示无差异的信息
### Requirement: CDS View Operations
系统 SHALL 支持 CDS View 的下载和创建操作。
#### Scenario: Download CDS view
- **WHEN** 用户执行 cds download 命令并指定 CDS View 名称
- **THEN** 系统下载 CDS View 定义并保存到本地
#### Scenario: Create CDS view
- **WHEN** 用户执行 cds create 命令并指定名称和描述
- **THEN** 系统在 SAP 中创建新的 CDS View
### Requirement: Package Operations
系统 SHALL 支持 ABAP 包的查询和创建操作。
#### Scenario: Query package info
- **WHEN** 用户执行 package info 命令并指定包名
- **THEN** 系统显示包的描述、包含的对象数量等信息
#### Scenario: Create package
- **WHEN** 用户执行 package create 命令并指定包名和描述
- **THEN** 系统在 SAP 中创建新的 ABAP 包
+39
View File
@@ -0,0 +1,39 @@
# Transport Management Specification
## Purpose
定义 sap-cli 的 SAP 传输请求管理功能行为。
## Requirements
### Requirement: Transport Request Listing
系统 SHALL 列出 SAP 系统中的传输请求。
#### Scenario: List transport requests
- **WHEN** 用户执行 transport list 命令
- **THEN** 系统显示当前用户的传输请求列表(请求号、描述、状态)
### Requirement: Transport Request Info
系统 SHALL 查询指定传输请求的详细信息。
#### Scenario: Query transport info
- **WHEN** 用户执行 transport info 命令并指定传输请求号
- **THEN** 系统显示传输请求的所有者、状态、包含的对象数量等信息
### Requirement: Transport Request Release
系统 SHALL 释放传输请求。
#### Scenario: Release transport request
- **WHEN** 用户执行 transport release 命令并指定传输请求号
- **THEN** 系统释放该传输请求
### Requirement: Transport Objects Listing
系统 SHALL 列出传输请求中包含的对象。
#### Scenario: List objects in transport
- **WHEN** 用户执行 transport objects 命令并指定传输请求号
- **THEN** 系统显示该传输请求中包含的所有开发对象列表