From 83b7aca84ac4522fe3e3782b2befe7e4636570a3 Mon Sep 17 00:00:00 2001 From: Haoyu Xi Date: Fri, 16 Oct 2026 01:48:33 +0800 Subject: [PATCH] =?UTF-8?q?chore(hygiene):=20=E8=AF=84=E4=BC=B0=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E6=89=B9=E6=AC=A1=201=20=E2=80=94=E2=80=94=20?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=80=81=E4=BA=A7=E7=89=A9=E5=BF=BD=E7=95=A5?= =?UTF-8?q?=E7=BC=BA=E5=8F=A3=20+=20=E5=85=A5=E5=8F=A3=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E4=B8=8E=E6=96=87=E6=A1=A3=E5=8F=A3=E5=BE=84=EF=BC=885=20?= =?UTF-8?q?=E5=A4=84=20+=20=E5=AE=88=E5=8D=AB=E6=B5=8B=E8=AF=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 来源:docs/reviews/2026-10-16-swarm-audit-master.md(P1-2)、2026-10-16-repo-structure-and-docs-audit.md(P2-1/P2-2/P2-4/P2-8)。全部是「已定案、不需决策、无危险」的条目;代码级修复(P0-1/P0-2/P1-1)与需决策项一律未动。 - .gitignore(P1-2):补 /launch.log、/launch.log.*、/lan-address.txt 三条根级规则。桌面壳把这三个产物写在数据目录,而便携模式(DELECTOR_PORTABLE=1)或源码运行时数据目录就是仓库根(data_dir_bootstrap.resolve_data_dir → program_dir())⇒ 与 *.db* 同一威胁模型:一次 git add -A 会把运行态日志(启动堆栈/端口冲突详情)与内网 IP 提交进历史。编排者实测三者由 NOT-IGNORED → IGNORED,且历史从未进过这三个文件。 - .gitignore(P2-4):补 .superpowers/ 根级兜底(原靠自身嵌套 .gitignore 内容 * 自忽略;工具升级重建目录时可能整棵漏进 status)。 - .env.example(P2-8):数据目录注释改正。实测 resolve_data_dir({}) = %LOCALAPPDATA%\DeLector(Linux/macOS: ~/.local/share/DeLector),**不是**仓库根;只有 DELECTOR_PORTABLE=1 才回落程序所在目录。 - CLAUDE.md(P2-1):新增「文档路由(先读这个)」一节指向 AGENTS.md —— 此前只读 CLAUDE.md 的会话完全不知道 architecture/ops 存在(AGENTS.md:3 自称「同 CLAUDE.md 形态」但 CLAUDE.md 没有路由表)。 - .cursorrules + .agent-rules.md(P2-2):沉淀草稿目录 08-Inbox → 99-Inbox(实测 08-Inbox 不存在、99-Inbox 存在;四份入口文件此前两个地址)。 守卫:tests/test_server.py 新增 test_runtime_artifacts_protected_by_gitignore —— 沿用 test_keystore_protected_by_gitignore_and_hook 惯例,另加两层:① git check-ignore 实证(防规则写错/被重新包含);② 与 desktop.py 的 LOG_FILE_NAME/LOG_BACKUP_SUFFIX/LAN_ADDRESS_FILE_NAME 常量对账(防改了常量忘了改规则)。变异自证:删掉三条规则 ⇒ 该测试红。 门禁:守卫 1 passed;ruff check . 全绿;mypy --strict delector 67 files 0;mypy --follow-imports=skip tests/test_server.py 0;前端契约闸过。 全量 pytest 1983 passed + 2 skipped + 2 failed —— 两条失败已用 git stash 在 master 态复现,证实是 tests/conftest.py:16-19 明文记载的「根目录有库 ⇒ test_save_wb_state_cost 迁移闸拒绝运行 ⇒ 本地红/CI 绿」既有分歧,与本 PR 无关;未删用户库文件(属危险操作,留待用户处置)。 --- .agent-rules.md | 2 +- .cursorrules | 2 +- .env.example | 4 +++- .gitignore | 10 ++++++++++ CLAUDE.md | 4 ++++ WORKMEMORY/work.log | 12 ++++++++++++ tests/test_server.py | 28 ++++++++++++++++++++++++++++ 7 files changed, 59 insertions(+), 3 deletions(-) diff --git a/.agent-rules.md b/.agent-rules.md index 263edf18..0f62917e 100644 --- a/.agent-rules.md +++ b/.agent-rules.md @@ -4,4 +4,4 @@ - 核心规范源:d:\Obsidian\Coding\AGENTS.md - 检索避坑规范:python d:\Obsidian\Coding\scripts\search-vault.py <报错/模式关键词> -- 发现新踩坑自动沉淀:写草稿至 d:\Obsidian\Coding\08-Inbox\YYYY-MM-DD-{topic}.md +- 发现新踩坑自动沉淀:写草稿至 d:\Obsidian\Coding\99-Inbox\YYYY-MM-DD-{topic}.md diff --git a/.cursorrules b/.cursorrules index 263edf18..0f62917e 100644 --- a/.cursorrules +++ b/.cursorrules @@ -4,4 +4,4 @@ - 核心规范源:d:\Obsidian\Coding\AGENTS.md - 检索避坑规范:python d:\Obsidian\Coding\scripts\search-vault.py <报错/模式关键词> -- 发现新踩坑自动沉淀:写草稿至 d:\Obsidian\Coding\08-Inbox\YYYY-MM-DD-{topic}.md +- 发现新踩坑自动沉淀:写草稿至 d:\Obsidian\Coding\99-Inbox\YYYY-MM-DD-{topic}.md diff --git a/.env.example b/.env.example index 71d1832d..ccf0e3d7 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,9 @@ # DeepSeek API Key for Goethe CEFR Grammar Analysis DEEPSEEK_API_KEY=your_deepseek_api_key_here -# 数据目录:delector.db / progress.db 的落盘位置。留空(不设)= 仓库根,即桌面端默认。 +# 数据目录:delector.db / progress.db 的落盘位置。留空(不设)= 平台默认目录 +# (Windows: %LOCALAPPDATA%\DeLector;Linux/macOS: ~/.local/share/DeLector), +# **不是**仓库根 —— 只有 DELECTOR_PORTABLE=1(便携模式)才回落到程序所在目录。 # # 一般**不要**设置本项——docker-compose.yml 已自行设成 /app/data。手工改它之前先读 # README「数据目录与旧版迁移」一节:把数据指到新目录、而旧目录里还留着非空的库文件时, diff --git a/.gitignore b/.gitignore index 03346ce7..6b7da638 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,13 @@ credentials.json # 学习记录**,单个可达数 MB。上面几条 `*.db*` 都匹配不到 `.bak-<时间戳>` 后缀, # 故它在仓库根是「未忽略的未跟踪文件」——一次 `git add -A` 就会把用户数据提交进历史。 *.db.bak-* +# 桌面壳运行态产物:launch.log(+ .1 轮转备份)与 lan-address.txt 由 desktop.py 写在 +# 数据目录里;而便携模式(DELECTOR_PORTABLE=1)或源码运行时,数据目录就是仓库根 +# (data_dir_bootstrap.resolve_data_dir → program_dir())。与上面 *.db* 同一威胁模型: +# 一次 `git add -A` 会把运行态日志(启动堆栈/端口冲突详情)与**内网 IP 地址**提交进历史。 +/launch.log +/launch.log.* +/lan-address.txt *.apkg *.apk artifact*.html @@ -31,6 +38,9 @@ artifact*.html # (内部 .gitignore 缺失或工具换版重建目录时,缓存内容会漏进 status)。 .mypy_cache/ .ruff_cache/ +# 与上面同理:.superpowers 目前靠自身嵌套 .gitignore(内容 `*`)自忽略;此处补根级兜底, +# 防止工具升级/重建目录但未写回嵌套规则时,整棵工具缓存漏进 status 被 `git add -A` 收走。 +.superpowers/ build/ dist/ *.spec diff --git a/CLAUDE.md b/CLAUDE.md index fa854603..629bf213 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,9 @@ # Project Guidelines +## 文档路由(先读这个) + +- 本仓 agent 文档入口是 `AGENTS.md`(纯路由表):架构 / 运维 / 发版 / 文档落位规则都在那里。进入会话先读它,再按需下沉到具体文档。 + ## 工程规范与自动化工具路径 (Coding Vault Invariants) - **核心规范源**:`d:\Obsidian\Coding\AGENTS.md` diff --git a/WORKMEMORY/work.log b/WORKMEMORY/work.log index 83cfb580..9df71464 100644 --- a/WORKMEMORY/work.log +++ b/WORKMEMORY/work.log @@ -570,3 +570,15 @@ Caps: filesystem-read, filesystem-write, shell-exec - **纪律**:阈值 pilot(N=5)后固定并写回设计稿;样本集冻结;三臂全量原始输出随报告落盘;**P1 成立亦为正当产出**(届时结论是"当前裁判不足以支撑宣称",表述必须反向收紧)。 - **成本按 token 计、不猜价格**(主实验上限 ≈180 次 chat + 120 次 rater 调用,N=20);harness MUST 有 `--dry-run`(stub chat)以便**无 Key 也能被 CI 测**。 - 后续:本条要动手时走 `/dfs-plan`(harness + 测试 + 种子集三个任务),**不影响**现行 §4.3 口径(无条件「已实现」继续禁用)。 + +### 2026-10-16 02:30 | codebuddy | NOTE +Caps: filesystem-read, filesystem-write, shell-exec +事件:用户去睡觉,自主推进「评估报告里已定案、不需决策、无危险」的一批修正(分支 `chore/audit-fixes-hygiene`)。 +- **P1-2(.gitignore 缺口,swarm/git 管理两席都点到)**:补 `/launch.log`、`/launch.log.*`、`/lan-address.txt` 三条根级规则 + 注释写清威胁模型(便携模式/源码运行时数据目录=仓库根 ⇒ 一次 `git add -A` 会把运行态日志与**内网 IP** 提交进历史)。编排者实测三者由 NOT-IGNORED → IGNORED,且**历史从未进过这三个文件**。 +- **P2-4**:补 `.superpowers/` 根级兜底(与 `.mypy_cache/` 同款理由:原靠嵌套 .gitignore 自忽略)。 +- **P2-8**:`.env.example` 数据目录注释改正 —— 实测 `resolve_data_dir({})` = `%LOCALAPPDATA%\DeLector`(**不是仓库根**),只有 `DELECTOR_PORTABLE=1` 才回落程序目录。 +- **P2-1**:`CLAUDE.md` 加「文档路由(先读这个)」一节指向 `AGENTS.md`(此前只读 CLAUDE.md 的会话完全不知道 architecture/ops 存在)。 +- **P2-2**:`.cursorrules` 与 `.agent-rules.md` 的 `08-Inbox` → `99-Inbox`(实测 08-Inbox 不存在、99-Inbox 存在)。 +- **守卫测试**:`tests/test_server.py` 新增 `test_runtime_artifacts_protected_by_gitignore`(沿用 keystore 那条惯例 + 多一层 `git check-ignore` 实证 + 与 `desktop.py` 常量对账)。**变异自证**:删掉三条规则 ⇒ 该测试红(判别力成立)。 +- **门禁**:守卫 1 passed;`ruff check .` 全绿;`mypy --strict delector` 67 files 0;`--follow-imports=skip tests/test_server.py` 0;契约闸过。全量 `pytest` **1983 passed + 2 skipped + 2 failed** —— 已用 `git stash` 在 master 态复现同样 2 failed,证实是 `tests/conftest.py:16-19` 明文记载的「根目录有库 ⇒ 迁移闸拒绝运行 ⇒ 本地红 / CI 绿」既有分歧,与本 PR 无关(**未删用户库文件**:那属危险操作)。 +- **未做(需决策或有危险)**:P1-1 分支纪律机械闸(CI 改动;`gh` 无 workflow scope ⇒ 合并要走 SSH no-ff)、P2-7 `.gitattributes` CRLF 契约(改跨平台 checkout 行为)、P2-6 renormalize、P2-5 `git gc`、P2-3 design-system 状态定夺,以及 swarm audit 的 P0-1/P0-2/P1-1(密钥进备份)等代码级修复。 diff --git a/tests/test_server.py b/tests/test_server.py index 4316e37e..b2c8a038 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -2527,6 +2527,34 @@ def test_keystore_protected_by_gitignore_and_hook(): assert "base64" in hook and "0x30" in hook, "PKCS12 Base64 检测需经 base64 解码后验文件头" +def test_runtime_artifacts_protected_by_gitignore(): + """桌面壳运行态产物 MUST 被 .gitignore 命中(评审 P1-2:`launch.log`/`lan-address.txt` 曾是缺口)。 + + 威胁模型与 `*.db*` 同族:便携模式(`DELECTOR_PORTABLE=1`)或源码运行时,数据目录 + 就是仓库根(`data_dir_bootstrap.resolve_data_dir` → `program_dir()`)⇒ 一次 + `git add -A` 会把运行态日志(启动堆栈/端口冲突详情)与**内网 IP 地址**提交进历史。 + """ + root = ROOT + import subprocess # 本文件惯例:subprocess 只在使用处局部导入 + + ignore = open(os.path.join(root, ".gitignore"), encoding="utf-8").read() + for pat in ("/launch.log", "/launch.log.*", "/lan-address.txt"): + assert pat in ignore, f".gitignore 缺 {pat}" + # 光有规则字符串不够:必须真的匹配得上(防规则写错、或被后续规则重新包含) + for rel in ("launch.log", "launch.log.1", "lan-address.txt"): + proc = subprocess.run( + ["git", "check-ignore", "-q", rel], cwd=str(root), capture_output=True + ) + assert proc.returncode == 0, ( + f"{rel} 未被 .gitignore 命中(git check-ignore rc={proc.returncode})" + ) + # 产物名 MUST 与桌面壳常量一致(防改了常量却忘了改忽略规则) + desktop = open(os.path.join(root, "desktop.py"), encoding="utf-8").read() + assert 'LOG_FILE_NAME = "launch.log"' in desktop + assert 'LOG_BACKUP_SUFFIX = ".1"' in desktop + assert 'LAN_ADDRESS_FILE_NAME = "lan-address.txt"' in desktop + + def _pkcs12_b64(): import base64