openagent-principle 0.6.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 (42) hide show
  1. openagent_principle-0.6.0/.env.example +47 -0
  2. openagent_principle-0.6.0/CHANGELOG.md +283 -0
  3. openagent_principle-0.6.0/LICENSE +21 -0
  4. openagent_principle-0.6.0/MANIFEST.in +6 -0
  5. openagent_principle-0.6.0/PKG-INFO +611 -0
  6. openagent_principle-0.6.0/README.md +580 -0
  7. openagent_principle-0.6.0/data/principles.seed.json +178 -0
  8. openagent_principle-0.6.0/pyproject.toml +69 -0
  9. openagent_principle-0.6.0/setup.cfg +4 -0
  10. openagent_principle-0.6.0/src/openagent_principle/__init__.py +32 -0
  11. openagent_principle-0.6.0/src/openagent_principle/__main__.py +8 -0
  12. openagent_principle-0.6.0/src/openagent_principle/_http.py +69 -0
  13. openagent_principle-0.6.0/src/openagent_principle/agent.py +508 -0
  14. openagent_principle-0.6.0/src/openagent_principle/api.py +343 -0
  15. openagent_principle-0.6.0/src/openagent_principle/cli.py +887 -0
  16. openagent_principle-0.6.0/src/openagent_principle/config.py +417 -0
  17. openagent_principle-0.6.0/src/openagent_principle/jev.py +383 -0
  18. openagent_principle-0.6.0/src/openagent_principle/judge.py +499 -0
  19. openagent_principle-0.6.0/src/openagent_principle/llm.py +243 -0
  20. openagent_principle-0.6.0/src/openagent_principle/models.py +262 -0
  21. openagent_principle-0.6.0/src/openagent_principle/py.typed +0 -0
  22. openagent_principle-0.6.0/src/openagent_principle/store.py +546 -0
  23. openagent_principle-0.6.0/src/openagent_principle/tools.py +674 -0
  24. openagent_principle-0.6.0/src/openagent_principle.egg-info/PKG-INFO +611 -0
  25. openagent_principle-0.6.0/src/openagent_principle.egg-info/SOURCES.txt +40 -0
  26. openagent_principle-0.6.0/src/openagent_principle.egg-info/dependency_links.txt +1 -0
  27. openagent_principle-0.6.0/src/openagent_principle.egg-info/entry_points.txt +3 -0
  28. openagent_principle-0.6.0/src/openagent_principle.egg-info/requires.txt +6 -0
  29. openagent_principle-0.6.0/src/openagent_principle.egg-info/top_level.txt +1 -0
  30. openagent_principle-0.6.0/tests/conftest.py +90 -0
  31. openagent_principle-0.6.0/tests/test_agent.py +208 -0
  32. openagent_principle-0.6.0/tests/test_api.py +180 -0
  33. openagent_principle-0.6.0/tests/test_cli.py +302 -0
  34. openagent_principle-0.6.0/tests/test_config.py +119 -0
  35. openagent_principle-0.6.0/tests/test_general_tools.py +85 -0
  36. openagent_principle-0.6.0/tests/test_home_resolution.py +183 -0
  37. openagent_principle-0.6.0/tests/test_jev.py +260 -0
  38. openagent_principle-0.6.0/tests/test_judge.py +476 -0
  39. openagent_principle-0.6.0/tests/test_llm.py +114 -0
  40. openagent_principle-0.6.0/tests/test_models.py +77 -0
  41. openagent_principle-0.6.0/tests/test_store.py +134 -0
  42. openagent_principle-0.6.0/tests/test_tools.py +214 -0
@@ -0,0 +1,47 @@
1
+ # openagent-principle 的全部配置都来自环境变量。
2
+ # 复制一份成 .env 并填自己的值,或直接 export。
3
+ # 判断需要模型:JEV 与 LLM 都没配时 judge 会明确报错,不会给出结论。
4
+
5
+ # ---------- 存储 ----------
6
+ # 原则库 / 案例 / 反馈的落盘目录。
7
+ # 默认是**项目级**:<项目根>/.openagent-principle(见 `principles home`)。
8
+ # 设了就覆盖项目级发现,优先级最高。
9
+ # PRINCIPLE_HOME=~/.openagent-principle
10
+
11
+ # ---------- 判断后端 ----------
12
+ # auto(默认)| jev | llm
13
+ # jev = 打 JEV 端点(结构化判断,主路径)
14
+ # llm = 用 OpenAI 兼容的 chat/completions 按**同一套题型**判断
15
+ # auto = 配了 JEV 就用 jev,失败降级 llm;两者都没配则报错
16
+ # 注意:`rules` 后端已移除。旧配置里若还写着 rules,启动时会直接报错并提示改法 ——
17
+ # 不会静默退回 auto(那会在有 LLM key 时把材料发给外部模型)。请显式改成 jev 或 llm。
18
+ # PRINCIPLE_JUDGE_BACKEND=auto
19
+
20
+ # ---------- JEV(主判断后端,可选) ----------
21
+ # JEV 端点:填你自己的网关地址(需要暴露 /systemone 路由)。
22
+ # JEV_BASE_URL=https://your-jev-gateway.example.com
23
+ # JEV_PATH=/systemone/v1/systemone
24
+ # JEV_MODEL=jev-1.13.0
25
+ # JEV_API_KEY= # 缺省回落到 PRINCIPLE_API_KEY / OPENAI_API_KEY
26
+ # JEV_TIMEOUT=120
27
+
28
+ # ---------- LLM(agent 与 llm 判断后端共用) ----------
29
+ # 缺省按 DEEPSEEK_API_KEY / OPENAI_API_KEY 的顺序找 key。
30
+ # PRINCIPLE_API_KEY=
31
+ # PRINCIPLE_BASE_URL=https://api.deepseek.com
32
+ # PRINCIPLE_MODEL=deepseek-flash
33
+ # PRINCIPLE_CONTEXT_SIZE=1048576
34
+ # PRINCIPLE_TEMPERATURE=0.3
35
+ # PRINCIPLE_MAX_TOKENS=4096
36
+ # PRINCIPLE_MAX_ITERS=200
37
+
38
+ # ---------- 预算 ----------
39
+ # 单次判断最多带多少条原则(JEV 按调用计费,一次装够才划算)
40
+ # PRINCIPLE_MAX_PRINCIPLES_PER_JUDGE=12
41
+ # 单次判断送进模型的材料字符上限
42
+ # PRINCIPLE_MAX_MATERIAL_CHARS=12000
43
+ # agent 每轮允许的 judge / 读文件次数(护栏,代码强制;0 = 不限,默认不限)
44
+ # PRINCIPLE_MAX_JUDGE_CALLS=0
45
+ # PRINCIPLE_MAX_READ_CALLS=0
46
+ # 兼容字段:fetch_url 已移除,设了也不会有工具命中
47
+ # PRINCIPLE_MAX_FETCH_CALLS=0
@@ -0,0 +1,283 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.6.0 — 2026-11-06
4
+
5
+ ### 移除规则层(破坏性变更)
6
+
7
+ **判断完全交给模型。** 确定性规则引擎(短语表 / 正则 / 长度阈值)整个移除 ——
8
+ 它和设计哲学冲突:不认识否定(「不用备份」含「备份」)、替模型做判断、
9
+ 用字面命中冒充语义结论。
10
+
11
+ - **删除 `rules.py`**(`RuleHit` / `RuleReport` / `evaluate` / `rule_report` / `rule_verdict`)。
12
+ - **`models.py`**:删 `Rule`、`RULE_KINDS`、`parse_rules`、`MAX_REGEX_LEN`;
13
+ `Principle` 删 `rules` 与 `scope_keywords` 字段、删 `applies_to()`。
14
+ - **`judge.merge` 重写**:签名从 `merge(principle, rule_report, model_verdict)` 改为
15
+ `merge(principle, model_verdict)`。只保留两条规则 —— 模型有结论就采纳;
16
+ 模型自相矛盾(所选选项概率 < 0.6)降为存疑。
17
+ - **`choose_backend` 不再降级到 `rules`**:JEV 与 LLM 都没配时抛 `JudgeError`
18
+ (「没有可用的判断后端」)。判断需要模型,不提供假装在判的降级。
19
+ - **`jev.build_questions` / `principle_instruction`** 去掉 `rule_reports` 参数,
20
+ 不再把规则报告写进 instructions。
21
+ - **CLI**:删 `--rule` 参数与 `--backend rules`;`add` / `update` 不再接受规则。
22
+ - **API / tools**:`save_principle` 去掉 `rules` 参数。
23
+ - **`config.JUDGE_BACKENDS`**:`("auto", "jev", "llm", "rules")` → `("auto", "jev", "llm")`。
24
+ - **种子原则**:8 条全部去掉 `rules` / `scope_keywords`,只保留 `criteria` / `examples`;
25
+ `data/principles.seed.json` 已重新生成。
26
+ - **`agent.describe` / `cli check`**:没配后端时显示「不可用」,不再抛异常。
27
+ - **测试**:删 `test_rules.py`;`test_judge.py` 的合并用例重写为「模型结论 + 矛盾检测」;
28
+ 判断链路用例改用假 JEV transport。
29
+
30
+ ### JEV 重试
31
+
32
+ - **200 但响应不可用也重试**:不是 JSON(网关吐 HTML 错误页)、没有 `answers`、
33
+ `answers` 里一道题都解析不出来 —— 这三种以前直接抛 `JevError` 降级,现在按可重试处理。
34
+ 重打一次往往就好了,直接降级反而丢掉语义判断。
35
+ - **默认重试次数 2 → 3**(`jev.DEFAULT_RETRIES`),退避 `(1, 2)` → `(1, 2, 4)` 秒。
36
+ 最坏情况 4 次请求、多等 7 秒。
37
+ - 不可重试的仍是:401/403/404 等非 `RETRYABLE_STATUS` 状态码、缺 key、材料为空、题型不合法。
38
+ - 新增测试:非 JSON 重试后成功、空 answers / 解析不出答案重试后成功、重试耗尽(4 次请求)。
39
+
40
+ ## 0.5.0 — 2026-11-05
41
+
42
+ **判断架构重构:最终语义判断统一由 JEV 裁决;CLI 支持单轮提示词;移除 `fetch_url`。**
43
+
44
+ ### 判断架构(破坏性变更)
45
+
46
+ - **规则层不再判违规,只产出报告**(`rules.rule_report` → `RuleReport`)
47
+ - 只做三件事:适用范围检查、确定性匹配、原文取证。
48
+ - `RuleHit.passed=False` 的语义从「违反」改为「这条规则的字面条件没满足」。
49
+ - 新增 `Principle.scope_keywords`:结构化的适用范围。材料不命中就不判 ——
50
+ 修掉「仅复盘」的原则对天气报告判「缺少改进」的误报。
51
+ - **规则结果作为结构化输入交给 JEV**(`RuleReport.as_prompt()`)
52
+ - 写进每条原则的 instructions,明确告诉 JEV:「未通过 ≠ 违反,请自行判断」。
53
+ - JEV 可以采纳,也可以基于语义推翻。
54
+ - **`judge.merge` 重写**:JEV 有结论就以 JEV 为准,规则命中只作为证据附上。
55
+ - 规则与 JEV 冲突时(规则未通过但 JEV 判 pass,或反之),在 reasoning 里留痕,
56
+ 不改判。
57
+ - 模型自相矛盾(所选选项概率 < 0.6)一律降为存疑,`violation` 与 `pass` 对称处理。
58
+ - **JEV 没给答案时**:显式 `--backend rules` 才允许规则定论;其他情况标存疑并写明
59
+ 「语义判断缺席」。
60
+ - **整体结论以 JEV 的全局答案为准**(`judge._resolve_overall`)
61
+ - 逐条与整体冲突时写进 `notes` 供复核,不改判。
62
+ - JEV 没给全局答案时才由逐条推导,并注明原因。
63
+ - **`Judge` 只负责协议校验、矛盾检测、存疑处理、审计留痕**,不再自行改判或重算整体结论。
64
+
65
+ ### CLI
66
+
67
+ - **新增单轮模式**:`principles "一段自然语言提示词"`
68
+ - 首个参数不是已知子命令时,建 agent、执行一次、输出、退出,不进多轮交互。
69
+ - `principles`(无参数)仍是交互模式;所有已有子命令行为不变。
70
+ - 子命令表从 parser 动态读取(`_known_subcommands`),加子命令时自动同步。
71
+
72
+ ### 移除
73
+
74
+ - **`fetch_url` 工具**:agent 有 `Bash` / `PowerShell`,`curl` / `Invoke-WebRequest`
75
+ 就是抓取能力。衍生能力不该占域工具位,也少一个 SSRF 面。
76
+ - `DOMAIN_TOOLS` 从 11 个减到 10 个;`READ_ONLY_DOMAIN` 同步。
77
+ - `PRINCIPLE_MAX_FETCH_CALLS` 保留为兼容字段(设了也不会有工具命中)。
78
+
79
+ ### 修复(来自两轮复审)
80
+
81
+ - `judge --source` 参数失效(读错了 `args.source`,应为 `source_label`)。
82
+ - 纯规则后端硬编码 `probability=0.95`,导致 `score` 无依据。
83
+ - `add --id` 撞号时静默覆盖并清空字段 → 现在拒绝,改字段用 `update`,整条覆盖需 `--force`。
84
+ - 安全配置拼写错误回退 `full` → 改为回退 `readonly`(失败方向必须更严)。
85
+ - `readonly` / `domain` 仍装写工具 → 只装 `READ_ONLY_DOMAIN`。
86
+ - 程序化 `Settings` 不传给域工具 → 用 `contextvars` 绑定(`tools.bind_settings`)。
87
+ - 原则 ID 撞上保留字 `overall` / `severity` → 保留字先占位。
88
+ - 畸形 JEV 响应(`probabilities` 是列表)抛 `AttributeError` 绕过降级 → 类型校验。
89
+ - 存储并发丢更新 → 加跨进程写锁(`store._write_lock`)。
90
+ - ReDoS → 正则执行加超时(子进程隔离,超时 `terminate`)。
91
+ - `search_files` 的 `glob` 用 `Path.match` 只匹配当前层 → 改用 `fnmatch` 匹配文件名。
92
+
93
+ ### OCR 复审(open-code-review v1.13.5)
94
+
95
+ 对 `judge.py` / `cli.py` / `agent.py` / `tools.py` 跑了 `ocr scan`,共 18 条发现,
96
+ 全部逐条验证后修复:
97
+
98
+ **judge.py(4 条)**
99
+ - `pass` 无 probabilities 时 fallback 写成 `0.0`,被 `merge` 的「< 0.6 即矛盾」
100
+ 检查误降为存疑 → 改为 `1.0`(`probability` 是「所选选项的概率」,不是违反概率)。
101
+ - 范围检查只在 `model_verdict is None` 分支做,模型对范围外原则给答案时会被采纳
102
+ → 补上范围外短路,模型结论一律忽略。
103
+ - 降级备注写「存疑(规则层不裁决)」,实际代码让规则层定论 → 改文案。
104
+ - 模块 docstring 仍说「规则命中不可推翻」,与实现相反 → 重写。
105
+
106
+ **cli.py(5 条)**
107
+ - `seed` 去重区分大小写,用户已有 `p-001` 时会被 `P-001` 覆盖 → 统一小写比较。
108
+ - `_read_material` 把参数错误和 I/O 失败都抛 `OSError`,退出码都是 2
109
+ → 拆出 `_MaterialArgError`(2)与 `OSError`(3)。
110
+ - `ModelError` 被当成执行失败(3),但它是参数错误 → 改为 2。
111
+ - 旧库损坏会拖垮 `home` → 包 try/except,只提示「读不了」。
112
+ - 帮助文本残留英文 `only` → 改「只」。
113
+
114
+ **agent.py(4 条)**
115
+ - **我引入的回归**:`read_only_only=toolset != "full"` 把 `domain` 也砍成 5 个
116
+ 只读工具,`judge_material` / `save_principle` 消失 → 改为 `== "readonly"`。
117
+ - `PRINCIPLE_PERMISSION` 拼错回退 `BYPASS`(最宽松)→ 改为 `DEFAULT`。
118
+ - `ToolBudget.take()` 的「检查 + 自增」无锁,并行调用会超限 → 加 `threading.Lock`。
119
+ - system prompt 无条件列出所有工具,只读/domain 模式下模型会反复撞不存在的工具
120
+ → 加「先看实际装了哪些」的说明。
121
+
122
+ **tools.py(5 条)**
123
+ - **最严重**:`hard="false"` 是真值,会把「归档」变成「不可恢复的真删」
124
+ → 新增 `_to_bool` 严格解析。
125
+ - `save_principle` 收到 `null` 时 `.strip()` 抛 `AttributeError` 逃逸
126
+ → 新增 `_as_text` 归一 + catch-all。
127
+ - 多处 `int(...)` 在 guard 外,模型传非数字会抛异常 → 新增 `_to_int`。
128
+ - `search_files` 的 `context > 0` 时把上下文行算进命中数 → 单独计数。
129
+ - `_iter_files` 跟随软链目录,成环时无限遍历 → 跳过软链目录。
130
+
131
+ ### 测试
132
+
133
+ - 244 passed。新增覆盖:规则与 JEV 冲突(双向)、逐条与整体冲突、后端降级
134
+ (jev→llm、jev→rules)、单轮模式识别、`fetch_url` 已移除、ReDoS 超时、
135
+ OCR 复审的 18 条修复(含 `hard="false"` 不真删、seed 大小写去重、
136
+ 退出码区分参数错误与执行失败、domain 模式工具数、`context` 命中计数)。
137
+
138
+ ## 0.4.0 — 2026-11-05
139
+
140
+ **判断题型从二态改三态;补上「被其他 agent 调用」的接口。**
141
+
142
+ ### 变更
143
+
144
+ - **每条原则的题型 `noul` → `choice`**(`jev.build_questions`)
145
+ - `noul` 只输出一个 0~1 的概率,**没有「不确定」这个出口** —— 模型想说的
146
+ 「证据不够」无处表达,只能被压成一个概率,再由调用方用 0.35/0.6 两个阈值切成三态。
147
+ - 实测(真 JEV,5 份材料 × 2 种写法):信息不足的材料在 `noul` 下只能拿到
148
+ 0.62~0.91 的「倾向违反」;换成 `choice` 后同一批材料的 `uncertain` 拿到 0.17~0.37。
149
+ - 三态由 `PRINCIPLE_CRITERIA`(pass / violation / uncertain)直接承载。
150
+ - **`noul` 从判断层彻底移除**:解析层不再认它,收到就按「无法判断」处理。
151
+ 留着兼容只会让「不知道」继续被伪装成「没事」。
152
+ - **去掉 `principle_instruction` 里的两条负面约束**
153
+ - 原文:「只有材料确实触犯了这条原则时,才回答「是」」「信息不足以下判断时,回答「否」」。
154
+ - 第二条会把「不知道」往「没事」拉,与项目自己的「存疑就说存疑」冲突。
155
+ - 换成「材料只是提到相关话题、并不构成违反时,选 pass;证据不足以判断时,选 uncertain」。
156
+ - **`judge.merge` 新增自相矛盾降级**:模型选了 `violation` 但自报概率 < 0.6 时降成存疑。
157
+ 实测见过两次:明确通过的材料被判 `violation` 0.49 / confidence 0.24,另一次 0.51 / 0.26。
158
+ 0.6 是「够不够格当结论」的线,不是「倾向哪边」的线。
159
+ - **删掉 `VIOLATION_THRESHOLD` / `CLEAR_THRESHOLD`**:三态由模型直接给,不再需要阈值。
160
+ - **新增 `api.py`:结构化 API**(给程序 / 其他 agent 用)
161
+ - 返回 `Principle` / `Judgement` / `Verdict` 对象,错误是异常
162
+ (`NotFoundError` / `InvalidInputError` / `BackendError` / `ApiError`)。
163
+ - `tools.py` 改为薄壳:调 `api` + 把结果/异常翻译成给模型读的中文。
164
+ - 两层分开的理由:模型要读得懂的话,程序要能 `except` 的对象。
165
+ - **CLI 全链路 `--json`**:`add` / `update` / `rm` / `seed` / `feedback` 补齐
166
+ (`list` / `show` / `judge` / `cases` / `case` / `stats` / `home` 原本就有)。
167
+ 除 `chat` / `check` 外每个子命令都能输出结构化 JSON,配合退出码给其他 agent 调用。
168
+ - **`PRINCIPLE_MAX_ITERS` 默认 50 → 200**:多步任务(看 → 改 → 跑 → 验)步数不够。
169
+ - **`JEV_BASE_URL` 不再有默认值**:网关是部署方自己的,写死一个只会把别人的内网地址
170
+ 带进仓库。不配就 `jev_configured=False`,自动降级到 llm / rules。
171
+ 同时清掉文档与注释里的内网域名、本机路径、服务端快照名。
172
+ - **README**:新增「被其他 agent 调用:两条路」(CLI + Python 库);
173
+ 更新题型说明、合并策略、目录结构;修正 `PRINCIPLE_MAX_TOKENS` 注释里的旧默认值。
174
+
175
+ ### 验证
176
+
177
+ - `pytest`:**206 passed**(新增 `tests/test_api.py` 22 例;`test_jev.py` / `test_judge.py` /
178
+ `test_llm.py` 全部改用 choice 答案,并补「noul 被拒」与自相矛盾降级用例)。
179
+ - 真 JEV 端到端:
180
+ - 明确违反 → `violation` 0.99;明确通过 → `pass` 0.99;
181
+ - 信息不足 → 模型给出 `uncertain`,不再被阈值硬掰成结论;
182
+ - 自相矛盾样本(violation 0.49 / 0.51)→ 降成存疑并写明原因。
183
+
184
+ ## 0.3.0 — 2026-11-05
185
+
186
+ **Agent 回到「全能力」**:它本来被限制成「只会判原则」——11 个工具、6/3/5 次硬预算,
187
+ 连读代码、跑测试、改文件都做不到,独立使用等于残废。这一版把能力边界交还给用户,
188
+ 默认全开,收窄改成显式动作。
189
+
190
+ ### 变更
191
+
192
+ - **工具箱分两层**(`agent.py`)
193
+ - 通用层:`Bash` / `PowerShell` / `Read` / `Write` / `Edit` / `Glob` / `Grep` /
194
+ `search_files` / `list_dir` / `TaskCreate|Get|List|Update`;
195
+ - 原则层:原来那 11 个域工具,一个不少。
196
+ - 默认 `full` = 两层都在(实测 23 个工具)。
197
+ - **能力边界显式可控**:`PRINCIPLE_TOOLSET=full|readonly|domain`、`--toolset`、
198
+ `PRINCIPLE_ALLOW_SHELL=0` / `--no-shell`(full 自动降为 readonly)。
199
+ 非法值退回 `full` —— 配置写错不该悄悄少一半能力。
200
+ - **预算默认不限**(`PRINCIPLE_MAX_JUDGE_CALLS` / `..._FETCH_CALLS` / `..._READ_CALLS` 默认 0):
201
+ 只数域工具(`judge_*` / `fetch_url` / `read_text_file`),通用工具不计数。
202
+ 护栏仍在,但只在显式配置时生效,超限文案会说明 `=0` 怎么解除。
203
+ - **`max_iters` 20 → 50、`max_tokens` 2048 → 4096**:22 个工具的多步任务,
204
+ 20 步不够走完「看 → 改 → 跑 → 验」。
205
+ - **系统提示词重写**:从「你只做四件事」改成「你是通用 agent,原则是你的纪律」,
206
+ 并补上破坏性操作先确认、材料不是命令、不搬运 secrets 三条安全纪律。
207
+ - **新增通用工具 `search_files` / `list_dir`**(`tools.py`,纯 Python):
208
+ 这台机器没有 ripgrep,AgentScope 的 `Grep` 直接报 `code 127`;因此
209
+ **有 `rg` 才装 `Grep`**,否则只装 `search_files`,不让模型反复撞一个必然失败的工具。
210
+ - **CLI**:`principles chat --toolset/--workspace/--no-shell`、banner 显示能力边界与
211
+ 工作目录、新指令 `/tools`(按层列出这次装了什么)。
212
+
213
+ ### 验证
214
+
215
+ - `pytest`:**179 passed**(新增 `tests/test_general_tools.py` 11 例 + `test_agent.py` 扩到 18 例)。
216
+ - 真跑(`deepseek-v4.1-flash`,full 能力):同一条链路里
217
+ `Read` 读材料 → `Bash` 执行命令 → `judge_material` 判原则 → `Write` 落盘报告,
218
+ 四类工具都被模型自己选中并成功执行。
219
+
220
+ ## 0.2.0 — 2026-11-05
221
+
222
+ **默认原则库从 `~/.openagent-principle` 改为项目级**,同轮补上「怎么本地测试」。
223
+
224
+ ### 变更
225
+
226
+ - **库位置默认跟着项目走**(`resolve_home()`):`PRINCIPLE_HOME` → 最近的已有库 →
227
+ 最近的项目标记(`.git` / `pyproject.toml` / `setup.py` / `package.json` / `Cargo.toml` / `go.mod`)→ 当前目录。
228
+ 「最近的已有库」优先于「项目标记」,是为了让子目录里跑命令仍落到同一个库 ——
229
+ 否则会出现「`list` 有 8 条、`judge` 说没有原则可判」这种没有线索的自相矛盾。
230
+ - **`Settings.home` 改为实例化时求值**(`field(default_factory=...)`):旧实现把默认值在
231
+ import 时算一次,`cd` 到别的项目后仍然写回旧库 —— 项目级默认最容易踩的正是这个坑,已加回归测试。
232
+ - **库目录自动生成 `.gitignore`**:忽略 `cases.jsonl` / `feedback.jsonl`(含材料原文),
233
+ 保留 `principles.json`(原则是资产,该进版本库);已存在则**绝不覆盖**。
234
+ - **新命令 `principles home`**:路径 + 来源 + 条数 + 旧库提示,`--json` 可脚本化;
235
+ `principles check` 也报来源。
236
+ - **README 新增「十一、本地测试」**:离线三分钟 / pytest / 真端点 / agent 迭代 / 已知坑。
237
+
238
+ ### 验证
239
+
240
+ - `pytest`:**156 passed**(新增 `tests/test_home_resolution.py` 14 例:发现规则、`PRINCIPLE_HOME` 覆盖、
241
+ 实例化时机、`.gitignore` 三条纪律、CLI 文本与 JSON 输出)。
242
+ - 端到端真跑(临时项目 `%TEMP%\principles-demo`,含 `.git` 标记):
243
+ - 在 `src/` 子目录执行 `principles home` → 库落在**项目根** `.openagent-principle`;
244
+ - `seed` 8 条 → `judge --backend rules` 退出码 **1**(P-004 命中「基本没问题 / 影响不大」并给原文引用);
245
+ - `judge --backend llm`(`deepseek-v4.1-flash`)→ 红线 0.99;
246
+ - `judge --backend jev`(2 条原则)→ P-007 0.97。
247
+
248
+ ## 0.1.0 — 2026-11-05
249
+
250
+ 首个版本:致敬《原则》的规则化 agent —— **维护原则 → 收集材料 → 判断是否违反 → 复盘改进**。
251
+
252
+ ### 能力
253
+
254
+ - **原则库**(`PRINCIPLE_HOME`,默认 `~/.openagent-principle`)
255
+ - `principles.json` 原子写、版本自增、默认归档而非删除;
256
+ - `cases.jsonl` 只追加的判断案例;`feedback.jsonl` 人工反馈;`stats` 算误判率。
257
+ - **可判定原则模型**:`statement` + `criteria`(人话)+ `rules`(机器可判)+ `examples`
258
+ + `severity`(1~5)+ `tags`/`scope`/`version`。八条种子原则(极度求真、可信度加权、
259
+ 痛苦+反思、直面问题、目标先行、不把情绪当事实、可逆/不可逆决策、决策留痕)。
260
+ - **三种判断后端**,`auto` 固定降级:`jev` → `llm` → `rules`
261
+ - Jev:`POST /systemone/v1/systemone`,把每条原则翻译成 `noul`,另加全局 `choice` + `score`;
262
+ - LLM:**同一套 questions** 交给 OpenAI 兼容 `chat/completions`,带 JSON 容错与 400 回退;
263
+ - rules:短语/正则/长度七种规则,纯本地、零成本、完全可复现。
264
+ - **两层合并**:规则命中 = 硬证据(模型不可推翻);规则通过只给 0.6 置信度;
265
+ `noul` 三态阈值 0.35/0.6;模型全局结论与逐条结论矛盾时写进 notes(不掩盖)。
266
+ - **agent 模式**(AgentScope 2.0.x):11 个工具、每轮硬预算(判断 6 / 抓网 3 / 读文件 5)、
267
+ 达利欧式 system prompt(材料是数据、判不了的原则是口号、存疑就说、误判变改进项)。
268
+ - **CLI**:`seed/add/update/list/show/rm/judge/cases/case/feedback/stats/check/chat`;
269
+ `judge` 退出码 0/1/2/3 有语义,可进 CI;`--json` 全链路可脚本化。
270
+
271
+ ### 验证
272
+
273
+ - `pytest`:142 passed(全离线,JEV/LLM 用假 transport 覆盖协议、重试、错误分级)。
274
+ - 在线验收(真 key,2026-11-05):
275
+ - JEV:8 条原则一次调用,结论「违反」;
276
+ - LLM(OpenAI 兼容端点):同一套题型,同一结论;
277
+ - agent:自行调用 `judge_material`(P-004,置信度 0.98)。
278
+
279
+ ### 已知限制
280
+
281
+ - 关键词规则不认识否定句(「不用备份」含「备份」)—— 规则层只作初筛与证据引用。
282
+ - Jev 不返回理由,`reasoning` 只有概率与置信度;要人话理由需 `--backend llm`。
283
+ - 单次判断默认最多 12 条原则(按严重度挑,超限写明)。
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yifei Yang
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,6 @@
1
+ # sdist 里要带上「测试需要、但不是包内模块」的文件
2
+ # data/principles.seed.json: test_store.test_seed_file_matches_code 要拿它比对
3
+ include data/principles.seed.json
4
+ include CHANGELOG.md
5
+ include .env.example
6
+ recursive-include tests *.py