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