harbor-spec 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. harbor_spec-1.0.0/LICENSE +21 -0
  2. harbor_spec-1.0.0/PKG-INFO +211 -0
  3. harbor_spec-1.0.0/README.md +175 -0
  4. harbor_spec-1.0.0/harbor/__init__.py +2 -0
  5. harbor_spec-1.0.0/harbor/adapters/__init__.py +2 -0
  6. harbor_spec-1.0.0/harbor/adapters/python/__init__.py +2 -0
  7. harbor_spec-1.0.0/harbor/adapters/python/parser.py +269 -0
  8. harbor_spec-1.0.0/harbor/cli/__init__.py +2 -0
  9. harbor_spec-1.0.0/harbor/cli/main.py +216 -0
  10. harbor_spec-1.0.0/harbor/core/__init__.py +2 -0
  11. harbor_spec-1.0.0/harbor/core/audit.py +133 -0
  12. harbor_spec-1.0.0/harbor/core/ddt.py +172 -0
  13. harbor_spec-1.0.0/harbor/core/diary.py +211 -0
  14. harbor_spec-1.0.0/harbor/core/index.py +191 -0
  15. harbor_spec-1.0.0/harbor/core/l2.py +170 -0
  16. harbor_spec-1.0.0/harbor/core/sync.py +173 -0
  17. harbor_spec-1.0.0/harbor/core/utils.py +56 -0
  18. harbor_spec-1.0.0/harbor/test_utils.py +11 -0
  19. harbor_spec-1.0.0/harbor/utils/__init__.py +2 -0
  20. harbor_spec-1.0.0/harbor/utils/formatting.py +36 -0
  21. harbor_spec-1.0.0/harbor_spec.egg-info/PKG-INFO +211 -0
  22. harbor_spec-1.0.0/harbor_spec.egg-info/SOURCES.txt +32 -0
  23. harbor_spec-1.0.0/harbor_spec.egg-info/dependency_links.txt +1 -0
  24. harbor_spec-1.0.0/harbor_spec.egg-info/entry_points.txt +2 -0
  25. harbor_spec-1.0.0/harbor_spec.egg-info/requires.txt +6 -0
  26. harbor_spec-1.0.0/harbor_spec.egg-info/top_level.txt +1 -0
  27. harbor_spec-1.0.0/pyproject.toml +27 -0
  28. harbor_spec-1.0.0/setup.cfg +4 -0
  29. harbor_spec-1.0.0/tests/test_adapter_basic.py +45 -0
  30. harbor_spec-1.0.0/tests/test_audit.py +43 -0
  31. harbor_spec-1.0.0/tests/test_ddt_validate.py +61 -0
  32. harbor_spec-1.0.0/tests/test_index_builder.py +99 -0
  33. harbor_spec-1.0.0/tests/test_sync_engine.py +68 -0
  34. harbor_spec-1.0.0/tests/test_utils_format.py +28 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 李健
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,211 @@
1
+ Metadata-Version: 2.4
2
+ Name: harbor-spec
3
+ Version: 1.0.0
4
+ Summary: Harbor-spec v1.0.2 reference implementation (Python-only)
5
+ License: MIT License
6
+
7
+ Copyright (c) 2025 李健
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: pyyaml
31
+ Requires-Dist: openai>=1.0.0
32
+ Requires-Dist: python-dotenv>=1.0.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ <div align="center">
38
+
39
+ # ⚓ Harbor
40
+ ### The Context Governance Engine for Vibe Coding
41
+
42
+ [![CI Status](https://img.shields.io/github/actions/workflow/status/your-org/harbor-spec/ci.yml?style=flat-square)](https://github.com/your-org/harbor-spec/actions)
43
+ [![Python Version](https://img.shields.io/badge/python-3.9%2B-blue?style=flat-square)](https://www.python.org/)
44
+ [![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
45
+ [![Strictness](https://img.shields.io/badge/Harbor-L3%20Strict-purple?style=flat-square)](https://github.com/your-org/harbor-spec)
46
+
47
+ **让 AI 像代码一样被管理,让上下文像 Git 一样可追溯。**
48
+
49
+ [理念 (Philosophy)] • [架构 (Architecture)] • [快速开始 (Quick Start)] • [工作流 (Workflow)]
50
+
51
+ </div>
52
+
53
+ ---
54
+
55
+ ## 🌌 The Era of Vibe Coding
56
+
57
+ 编程正在经历一场范式转移。我们正在从 "Writing Code"(逐行编写)转向 **"Vibe Coding"**(通过自然语言与 AI 协作生成)。
58
+
59
+ 在这个新时代,**代码生成的边际成本趋近于零,但上下文维护的成本却在指数级上升。**
60
+ - AI 改了代码,Docstring 还没改?👉 **Context Drift (上下文漂移)**
61
+ - 测试用例还在测旧版本的逻辑?👉 **Validation Gap (验证断层)**
62
+ - 为什么上周我们要把这个参数改成 Optional?👉 **Memory Loss (决策遗忘)**
63
+
64
+ **Harbor** 应运而生。它不是另一个 Copilot,它是 **Copilot 的监管者**。它是一套用于治理 AI 生成代码的 **"良知" (Conscience)** 与 **"记忆" (Memory)** 系统。它是“程序员到上下文工程师”这一革命性转变的关键工具,它的目标是成为vibe coding时代的Git。
65
+
66
+ ## 🛡️ Core Philosophy
67
+
68
+ Harbor 的核心设计理念基于 **L3 Contract Theory**:
69
+
70
+ 1. **Code is Volatile, Contract is Immutable**: 实现代码可以由 AI 随意重写,但 L3 级 Docstring(契约)是锚点,必须由人类或高级审计确认。
71
+ 2. **Noise is Signal**: 未经索引的代码、未同步的文档、未绑定的测试,都是系统中的“噪音”。Harbor 不会静默处理,而是将其显性化。
72
+ 3. **Trust, but Verify**: 我们信任 AI 的编码能力,但必须通过 AST 静态分析和 LLM 语义审计来验证其产出。
73
+
74
+ ## 🏗️ Architecture
75
+
76
+ Harbor 通过六大核心子系统构建了一个闭环的治理体系:
77
+
78
+ ```mermaid
79
+ graph TD
80
+ Source[Source Code] -->|AST Parse| Adapter(Adapter)
81
+ Adapter -->|Contract Hash| Index(L3 Index / Memory)
82
+
83
+ Index -->|Compare| Sync(Sync Engine)
84
+ Source -->|Body Hash| Sync
85
+
86
+ Sync -->|Drift Detected| Status[CLI Status]
87
+ Sync -->|Diff Target| Audit(Semantic Guard)
88
+
89
+ Env[.env / LLM] --> Audit
90
+ Audit -->|Semantic Check| Report[Audit Report]
91
+
92
+ Tests[Test Cases] -->|DDT Binding| Validator(DDT Validator)
93
+ Index -->|Version Match| Validator
94
+
95
+ Index -->|Aggregation| L2(L2 Generator)
96
+ Validator -->|Status| L2
97
+
98
+ User[Developer] -->|Log Decision| Diary(Diary / History)
99
+ ````
100
+
101
+ - **🧠 Index (Memory)**: 这里的 `.harbor/cache` 是大脑,记录了代码的每一次“快照”与指纹。
102
+ - **⚖️ Sync (Conscience)**: 实时监测 "Implementation Drift"(代码变了,但契约没变)。
103
+ - **🌉 DDT (Bridge)**: **D**ecorator-driven **D**ata **T**esting。将测试用例与 L3 版本强绑定,拒绝“假绿灯”。
104
+ - **🤖 Audit (Guard)**: 集成 DeepSeek/OpenAI,对代码进行语义级审计,揪出逻辑与文档的违背之处。
105
+ - **📊 L2 (Dashboard)**: 自动生成 Markdown 视图,诚实地展示模块的测试覆盖率与契约状态。
106
+ - **📜 Diary (History)**: 结构化的决策日志,记录每一次变革背后的 "Why"。
107
+
108
+ ## ⚡ Quick Start
109
+
110
+ ### 1\. Installation
111
+
112
+ Harbor 是一个纯 Python 工具,推荐在开发模式下安装:
113
+
114
+ ```bash
115
+ git clone [https://github.com/your-org/harbor-spec.git](https://github.com/your-org/harbor-spec.git)
116
+ cd harbor-spec
117
+ pip install -e .
118
+ ```
119
+
120
+ 可选pypi安装:
121
+
122
+ ```bash
123
+ pip install harbor-spec
124
+ ```
125
+
126
+ ### 2\. Configuration
127
+
128
+ 配置 LLM 以启用 AI 语义审计(支持 Ernie, DeepSeek, OpenAI 等兼容接口):
129
+
130
+ ```bash
131
+ cp .env.example .env
132
+ # 编辑 .env 文件:
133
+ # HARBOR_LLM_PROVIDER=openai
134
+ # HARBOR_LLM_API_KEY=
135
+ # HARBOR_LLM_BASE_URL=https://api.openai.com/v1
136
+ # HARBOR_LANGUAGE=zh (可选,开启中文审计)
137
+ ```
138
+
139
+ ### 3\. Initialize
140
+
141
+ 构建初始索引,接管当前代码库:
142
+
143
+ ```bash
144
+ harbor build-index
145
+ ```
146
+
147
+ ## 🎮 Workflow: A Day with Harbor
148
+
149
+ ### 1\. Check Status
150
+
151
+ 开始工作前,看看代码库是否干净。
152
+
153
+ ```bash
154
+ harbor status
155
+ # 输出: No changes detected. (Or list of drifts)
156
+ ```
157
+
158
+ ### 2\. Vibe Coding
159
+
160
+ 使用你喜欢的 AI 助手(Cursor, Windsurf, Copilot)修改代码。
161
+ *假设你修改了 `harbor/utils.py` 的逻辑,但忘记更新 Docstring。*
162
+
163
+ ### 3\. Detect Drift
164
+
165
+ Harbor 会发现你的代码实现了“偷跑”。
166
+
167
+ ```bash
168
+ harbor status
169
+ # 输出: M harbor.utils.func (Body changed, Contract static)
170
+ ```
171
+
172
+ ### 4\. AI Audit
173
+
174
+ 让 Harbor 的 AI 审计员检查你的修改是否违背了契约。
175
+
176
+ ```bash
177
+ harbor audit --semantic
178
+ # 输出: POSSIBLE_SEMANTIC_DRIFT ... [MISMATCH]: 代码抛出了 ValueError 但文档中未声明...
179
+ ```
180
+
181
+ ### 5\. Lock & Record
182
+
183
+ 修复问题后,更新索引并记录决策日志。
184
+
185
+ ```bash
186
+ harbor build-index
187
+ harbor diary log --summary "Refactor utils validation logic" --type refactor --importance high
188
+ ```
189
+
190
+ ## 🧩 Commands Cheatsheet
191
+
192
+ | Command | Description |
193
+ | :--- | :--- |
194
+ | `harbor status` | 检查代码与索引的差异(Drift检测) |
195
+ | `harbor build-index` | 更新 L3 索引缓存 (类似 `git commit`) |
196
+ | `harbor audit --semantic` | 调用 LLM 进行语义一致性检查 |
197
+ | `harbor ddt validate` | 验证测试用例与代码版本的绑定关系 |
198
+ | `harbor gen l2` | 自动生成模块级的 README 文档 |
199
+ | `harbor diary log` | 写入结构化的决策日志 |
200
+
201
+ ## 🤝 Contribution
202
+
203
+ Harbor 遵循 **Strict L3** 开发规范。
204
+
205
+ - 所有 Public API 必须包含完整的 Google-style Docstring。
206
+ - 所有新增功能必须包含 DDT 测试绑定。
207
+ - 提交前请运行 `harbor audit --semantic` 自测。
208
+
209
+ ## 📄 License
210
+
211
+ MIT © 2025 Harbor-spec Authors.
@@ -0,0 +1,175 @@
1
+ <div align="center">
2
+
3
+ # ⚓ Harbor
4
+ ### The Context Governance Engine for Vibe Coding
5
+
6
+ [![CI Status](https://img.shields.io/github/actions/workflow/status/your-org/harbor-spec/ci.yml?style=flat-square)](https://github.com/your-org/harbor-spec/actions)
7
+ [![Python Version](https://img.shields.io/badge/python-3.9%2B-blue?style=flat-square)](https://www.python.org/)
8
+ [![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
9
+ [![Strictness](https://img.shields.io/badge/Harbor-L3%20Strict-purple?style=flat-square)](https://github.com/your-org/harbor-spec)
10
+
11
+ **让 AI 像代码一样被管理,让上下文像 Git 一样可追溯。**
12
+
13
+ [理念 (Philosophy)] • [架构 (Architecture)] • [快速开始 (Quick Start)] • [工作流 (Workflow)]
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## 🌌 The Era of Vibe Coding
20
+
21
+ 编程正在经历一场范式转移。我们正在从 "Writing Code"(逐行编写)转向 **"Vibe Coding"**(通过自然语言与 AI 协作生成)。
22
+
23
+ 在这个新时代,**代码生成的边际成本趋近于零,但上下文维护的成本却在指数级上升。**
24
+ - AI 改了代码,Docstring 还没改?👉 **Context Drift (上下文漂移)**
25
+ - 测试用例还在测旧版本的逻辑?👉 **Validation Gap (验证断层)**
26
+ - 为什么上周我们要把这个参数改成 Optional?👉 **Memory Loss (决策遗忘)**
27
+
28
+ **Harbor** 应运而生。它不是另一个 Copilot,它是 **Copilot 的监管者**。它是一套用于治理 AI 生成代码的 **"良知" (Conscience)** 与 **"记忆" (Memory)** 系统。它是“程序员到上下文工程师”这一革命性转变的关键工具,它的目标是成为vibe coding时代的Git。
29
+
30
+ ## 🛡️ Core Philosophy
31
+
32
+ Harbor 的核心设计理念基于 **L3 Contract Theory**:
33
+
34
+ 1. **Code is Volatile, Contract is Immutable**: 实现代码可以由 AI 随意重写,但 L3 级 Docstring(契约)是锚点,必须由人类或高级审计确认。
35
+ 2. **Noise is Signal**: 未经索引的代码、未同步的文档、未绑定的测试,都是系统中的“噪音”。Harbor 不会静默处理,而是将其显性化。
36
+ 3. **Trust, but Verify**: 我们信任 AI 的编码能力,但必须通过 AST 静态分析和 LLM 语义审计来验证其产出。
37
+
38
+ ## 🏗️ Architecture
39
+
40
+ Harbor 通过六大核心子系统构建了一个闭环的治理体系:
41
+
42
+ ```mermaid
43
+ graph TD
44
+ Source[Source Code] -->|AST Parse| Adapter(Adapter)
45
+ Adapter -->|Contract Hash| Index(L3 Index / Memory)
46
+
47
+ Index -->|Compare| Sync(Sync Engine)
48
+ Source -->|Body Hash| Sync
49
+
50
+ Sync -->|Drift Detected| Status[CLI Status]
51
+ Sync -->|Diff Target| Audit(Semantic Guard)
52
+
53
+ Env[.env / LLM] --> Audit
54
+ Audit -->|Semantic Check| Report[Audit Report]
55
+
56
+ Tests[Test Cases] -->|DDT Binding| Validator(DDT Validator)
57
+ Index -->|Version Match| Validator
58
+
59
+ Index -->|Aggregation| L2(L2 Generator)
60
+ Validator -->|Status| L2
61
+
62
+ User[Developer] -->|Log Decision| Diary(Diary / History)
63
+ ````
64
+
65
+ - **🧠 Index (Memory)**: 这里的 `.harbor/cache` 是大脑,记录了代码的每一次“快照”与指纹。
66
+ - **⚖️ Sync (Conscience)**: 实时监测 "Implementation Drift"(代码变了,但契约没变)。
67
+ - **🌉 DDT (Bridge)**: **D**ecorator-driven **D**ata **T**esting。将测试用例与 L3 版本强绑定,拒绝“假绿灯”。
68
+ - **🤖 Audit (Guard)**: 集成 DeepSeek/OpenAI,对代码进行语义级审计,揪出逻辑与文档的违背之处。
69
+ - **📊 L2 (Dashboard)**: 自动生成 Markdown 视图,诚实地展示模块的测试覆盖率与契约状态。
70
+ - **📜 Diary (History)**: 结构化的决策日志,记录每一次变革背后的 "Why"。
71
+
72
+ ## ⚡ Quick Start
73
+
74
+ ### 1\. Installation
75
+
76
+ Harbor 是一个纯 Python 工具,推荐在开发模式下安装:
77
+
78
+ ```bash
79
+ git clone [https://github.com/your-org/harbor-spec.git](https://github.com/your-org/harbor-spec.git)
80
+ cd harbor-spec
81
+ pip install -e .
82
+ ```
83
+
84
+ 可选pypi安装:
85
+
86
+ ```bash
87
+ pip install harbor-spec
88
+ ```
89
+
90
+ ### 2\. Configuration
91
+
92
+ 配置 LLM 以启用 AI 语义审计(支持 Ernie, DeepSeek, OpenAI 等兼容接口):
93
+
94
+ ```bash
95
+ cp .env.example .env
96
+ # 编辑 .env 文件:
97
+ # HARBOR_LLM_PROVIDER=openai
98
+ # HARBOR_LLM_API_KEY=
99
+ # HARBOR_LLM_BASE_URL=https://api.openai.com/v1
100
+ # HARBOR_LANGUAGE=zh (可选,开启中文审计)
101
+ ```
102
+
103
+ ### 3\. Initialize
104
+
105
+ 构建初始索引,接管当前代码库:
106
+
107
+ ```bash
108
+ harbor build-index
109
+ ```
110
+
111
+ ## 🎮 Workflow: A Day with Harbor
112
+
113
+ ### 1\. Check Status
114
+
115
+ 开始工作前,看看代码库是否干净。
116
+
117
+ ```bash
118
+ harbor status
119
+ # 输出: No changes detected. (Or list of drifts)
120
+ ```
121
+
122
+ ### 2\. Vibe Coding
123
+
124
+ 使用你喜欢的 AI 助手(Cursor, Windsurf, Copilot)修改代码。
125
+ *假设你修改了 `harbor/utils.py` 的逻辑,但忘记更新 Docstring。*
126
+
127
+ ### 3\. Detect Drift
128
+
129
+ Harbor 会发现你的代码实现了“偷跑”。
130
+
131
+ ```bash
132
+ harbor status
133
+ # 输出: M harbor.utils.func (Body changed, Contract static)
134
+ ```
135
+
136
+ ### 4\. AI Audit
137
+
138
+ 让 Harbor 的 AI 审计员检查你的修改是否违背了契约。
139
+
140
+ ```bash
141
+ harbor audit --semantic
142
+ # 输出: POSSIBLE_SEMANTIC_DRIFT ... [MISMATCH]: 代码抛出了 ValueError 但文档中未声明...
143
+ ```
144
+
145
+ ### 5\. Lock & Record
146
+
147
+ 修复问题后,更新索引并记录决策日志。
148
+
149
+ ```bash
150
+ harbor build-index
151
+ harbor diary log --summary "Refactor utils validation logic" --type refactor --importance high
152
+ ```
153
+
154
+ ## 🧩 Commands Cheatsheet
155
+
156
+ | Command | Description |
157
+ | :--- | :--- |
158
+ | `harbor status` | 检查代码与索引的差异(Drift检测) |
159
+ | `harbor build-index` | 更新 L3 索引缓存 (类似 `git commit`) |
160
+ | `harbor audit --semantic` | 调用 LLM 进行语义一致性检查 |
161
+ | `harbor ddt validate` | 验证测试用例与代码版本的绑定关系 |
162
+ | `harbor gen l2` | 自动生成模块级的 README 文档 |
163
+ | `harbor diary log` | 写入结构化的决策日志 |
164
+
165
+ ## 🤝 Contribution
166
+
167
+ Harbor 遵循 **Strict L3** 开发规范。
168
+
169
+ - 所有 Public API 必须包含完整的 Google-style Docstring。
170
+ - 所有新增功能必须包含 DDT 测试绑定。
171
+ - 提交前请运行 `harbor audit --semantic` 自测。
172
+
173
+ ## 📄 License
174
+
175
+ MIT © 2025 Harbor-spec Authors.
@@ -0,0 +1,2 @@
1
+ __version__ = "1.0.2"
2
+
@@ -0,0 +1,2 @@
1
+ """Adapters package."""
2
+
@@ -0,0 +1,2 @@
1
+ """Python language adapter."""
2
+
@@ -0,0 +1,269 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+ import hashlib
5
+ import os
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+ from typing import List, Optional, Tuple, Union, Literal
9
+
10
+
11
+ @dataclass
12
+ class FunctionContract:
13
+ id: str
14
+ name: str
15
+ qualified_name: str
16
+ signature_hash: str
17
+ docstring: Optional[str]
18
+ docstring_raw_hash: Optional[str]
19
+ contract_hash: Optional[str]
20
+ lineno: int
21
+ col_offset: int
22
+ scope: Optional[Literal["public", "internal"]] = None
23
+ strictness: Optional[Literal["strict", "standard", "light"]] = None
24
+ is_method: bool = False
25
+ parent_class: Optional[str] = None
26
+
27
+
28
+ class PythonAdapter:
29
+ def parse_file(self, file_path: str) -> List[FunctionContract]:
30
+ """解析并提取指定 Python 文件中的函数/方法契约元数据。
31
+
32
+ 功能:
33
+ - 读取并解析 Python 源文件的 AST。
34
+ - 提取所有顶层函数与类方法的名称、签名哈希与 Docstring 双哈希。
35
+ - 识别 Docstring 中的 `@harbor.*` 标签与契约区 (Args/Returns/Raises) 文本。
36
+
37
+ 使用场景:
38
+ - Harbor 索引构建(Phase 1)基座;为 `build-index` 提供 L3 解析能力。
39
+ - `harbor sync l3 --check` 的前置分析。
40
+
41
+ 依赖:
42
+ - Python 标准库 `ast`、`hashlib`。
43
+
44
+ @harbor.scope: public
45
+ @harbor.l3_strictness: strict
46
+ @harbor.idempotency: read-only
47
+
48
+ Args:
49
+ file_path (str): 需要解析的 Python 源文件路径。
50
+
51
+ Returns:
52
+ List[FunctionContract]: 函数/方法契约元数据列表。
53
+
54
+ Raises:
55
+ IOError: 当文件读取失败。
56
+ SyntaxError: 当源文件存在语法错误,无法解析为 AST。
57
+ """
58
+ p = Path(file_path)
59
+ if not p.exists():
60
+ raise IOError(f"file not found: {file_path}")
61
+ try:
62
+ source = p.read_text(encoding="utf-8")
63
+ except Exception as e:
64
+ raise IOError(str(e))
65
+ try:
66
+ tree = ast.parse(source)
67
+ except SyntaxError:
68
+ raise
69
+ module_qual = self._module_qual_from_path(p)
70
+ return self._extract_functions(tree, module_qual)
71
+
72
+ def _extract_functions(self, tree: ast.AST, module_qual: str) -> List[FunctionContract]:
73
+ """提取顶层函数与类方法的契约元数据。
74
+
75
+ @harbor.scope: internal
76
+ @harbor.l3_strictness: standard
77
+
78
+ Args:
79
+ tree (ast.AST): 已解析的抽象语法树。
80
+ module_qual (str): 模块的点分限定名。
81
+
82
+ Returns:
83
+ List[FunctionContract]: 契约元数据列表。
84
+ """
85
+ items: List[FunctionContract] = []
86
+ for node in getattr(tree, "body", []):
87
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
88
+ items.append(self._contract_from_function(node, module_qual, None))
89
+ elif isinstance(node, ast.ClassDef):
90
+ for sub in node.body:
91
+ if isinstance(sub, (ast.FunctionDef, ast.AsyncFunctionDef)):
92
+ items.append(self._contract_from_function(sub, module_qual, node.name))
93
+ return items
94
+
95
+ def _contract_from_function(
96
+ self,
97
+ fn: Union[ast.FunctionDef, ast.AsyncFunctionDef],
98
+ module_qual: str,
99
+ parent_class: Optional[str],
100
+ ) -> FunctionContract:
101
+ """根据函数节点生成契约元数据。
102
+
103
+ @harbor.scope: internal
104
+ @harbor.l3_strictness: standard
105
+
106
+ Args:
107
+ fn: 函数或方法的 AST 节点。
108
+ module_qual: 模块限定名。
109
+ parent_class: 若为方法,则为父类名,否则为 None。
110
+
111
+ Returns:
112
+ FunctionContract: 契约元数据。
113
+ """
114
+ name = fn.name
115
+ is_method = parent_class is not None
116
+ qualified_name = (
117
+ f"{module_qual}.{parent_class}.{name}" if is_method else f"{module_qual}.{name}"
118
+ )
119
+ doc = ast.get_docstring(fn)
120
+ raw_hash, contract_hash = self._docstring_hashes(doc)
121
+ scope, strictness = self._parse_tags(doc) if doc else (None, None)
122
+ return FunctionContract(
123
+ id=qualified_name,
124
+ name=name,
125
+ qualified_name=qualified_name,
126
+ signature_hash=self._signature_hash(fn),
127
+ docstring=doc,
128
+ docstring_raw_hash=raw_hash,
129
+ contract_hash=contract_hash,
130
+ lineno=getattr(fn, "lineno", 0),
131
+ col_offset=getattr(fn, "col_offset", 0),
132
+ scope=scope,
133
+ strictness=strictness,
134
+ is_method=is_method,
135
+ parent_class=parent_class,
136
+ )
137
+
138
+ def _signature_hash(self, fn: Union[ast.FunctionDef, ast.AsyncFunctionDef]) -> str:
139
+ """计算函数签名的稳定哈希。
140
+
141
+ @harbor.scope: internal
142
+ @harbor.l3_strictness: standard
143
+
144
+ Args:
145
+ fn: 函数或方法的 AST 节点。
146
+
147
+ Returns:
148
+ str: 签名的 sha256 哈希。
149
+ """
150
+ a = fn.args
151
+ parts = [
152
+ "posonly:" + ",".join([x.arg for x in getattr(a, "posonlyargs", [])]),
153
+ "args:" + ",".join([x.arg for x in a.args]),
154
+ "vararg:" + (a.vararg.arg if a.vararg else ""),
155
+ "kwonly:" + ",".join([x.arg for x in a.kwonlyargs]),
156
+ "kwarg:" + (a.kwarg.arg if a.kwarg else ""),
157
+ "defaults:" + str(len(a.defaults)) + "|" + str(len(a.kw_defaults)),
158
+ ]
159
+ norm = "|".join(parts)
160
+ return hashlib.sha256(norm.encode("utf-8")).hexdigest()
161
+
162
+ def _docstring_hashes(self, doc: Optional[str]) -> Tuple[Optional[str], Optional[str]]:
163
+ """计算 Docstring 的 raw/contract 双哈希。
164
+
165
+ @harbor.scope: internal
166
+ @harbor.l3_strictness: standard
167
+
168
+ Args:
169
+ doc: Docstring 文本或 None。
170
+
171
+ Returns:
172
+ Tuple[str | None, str | None]: (raw_hash, contract_hash)。
173
+ """
174
+ if not doc:
175
+ return None, None
176
+ text = doc.replace("\r\n", "\n").strip()
177
+ raw = hashlib.sha256(text.encode("utf-8")).hexdigest()
178
+ contract_text = self._contract_area(text)
179
+ if not contract_text:
180
+ return raw, raw
181
+ contract = hashlib.sha256(contract_text.encode("utf-8")).hexdigest()
182
+ return raw, contract
183
+
184
+ def _contract_area(self, doc: str) -> str:
185
+ """提取契约区文本(Args/Returns/Raises + @harbor.* tags)。找不到则返回空串。
186
+
187
+ @harbor.scope: internal
188
+ @harbor.l3_strictness: standard
189
+
190
+ Args:
191
+ doc: 完整 Docstring。
192
+
193
+ Returns:
194
+ str: 契约区文本。
195
+ """
196
+ lines = doc.split("\n")
197
+ captured: List[str] = []
198
+ capturing = False
199
+ target_headers = {"Args:", "Returns:", "Raises:"}
200
+ for i, line in enumerate(lines):
201
+ s = line.strip()
202
+ if s.startswith("@harbor."):
203
+ captured.append(s)
204
+ continue
205
+ if s in target_headers:
206
+ capturing = True
207
+ captured.append(s)
208
+ continue
209
+ if capturing:
210
+ if s == "":
211
+ capturing = False
212
+ continue
213
+ if line.startswith(" ") or line.startswith("\t"):
214
+ captured.append(line.rstrip())
215
+ else:
216
+ capturing = False
217
+ return "\n".join([x for x in captured if x.strip()]).strip()
218
+
219
+ def _parse_tags(
220
+ self, doc: str
221
+ ) -> Tuple[Optional[Literal["public", "internal"]], Optional[Literal["strict", "standard", "light"]]]:
222
+ """从 Docstring 提取 @harbor.* 标签。
223
+
224
+ @harbor.scope: internal
225
+ @harbor.l3_strictness: standard
226
+
227
+ Args:
228
+ doc: 完整 Docstring。
229
+
230
+ Returns:
231
+ Tuple[scope, strictness]: 若未找到则返回 (None, None)。
232
+ """
233
+ scope: Optional[Literal["public", "internal"]] = None
234
+ strictness: Optional[Literal["strict", "standard", "light"]] = None
235
+ for line in doc.split("\n"):
236
+ s = line.strip()
237
+ if s.startswith("@harbor.scope:"):
238
+ val = s.split(":", 1)[1].strip()
239
+ if val in ("public", "internal"):
240
+ scope = val # type: ignore
241
+ elif s.startswith("@harbor.l3_strictness:"):
242
+ val = s.split(":", 1)[1].strip()
243
+ if val in ("strict", "standard", "light"):
244
+ strictness = val # type: ignore
245
+ return scope, strictness
246
+
247
+ def _module_qual_from_path(self, p: Path) -> str:
248
+ """根据文件路径生成模块限定名(点分格式)。
249
+
250
+ @harbor.scope: internal
251
+ @harbor.l3_strictness: standard
252
+
253
+ Args:
254
+ p: 源文件路径。
255
+
256
+ Returns:
257
+ str: 点分模块名,如 `harbor.adapters.python.parser`。
258
+ """
259
+ root = Path.cwd().resolve()
260
+ try:
261
+ rel = p.resolve().relative_to(root)
262
+ except Exception:
263
+ rel = p.name if p.is_file() else str(p)
264
+ rel = Path(rel)
265
+ parts = list(rel.parts)
266
+ if parts and parts[-1].endswith(".py"):
267
+ parts[-1] = parts[-1][:-3]
268
+ return ".".join([x for x in parts if x and x not in (".", "..")])
269
+
@@ -0,0 +1,2 @@
1
+ """CLI package."""
2
+