diff --git a/.gitignore b/.gitignore index c3327c75..95177d29 100644 --- a/.gitignore +++ b/.gitignore @@ -33,8 +33,10 @@ benchmarks/jyotish/outputs/ output_report.txt results_extracted.md runtime-smoke-report-*.html -# Local Python runtime for the API server -.venv/ +# Local Python runtime for the API server. +# No trailing slash: `.venv/` ignores only directories, so a symlink of the +# same name stayed tracked and CI overwrote it with a real venv (BUG-974). +.venv # Local Supabase CLI link/cache state supabase/.temp/ # Local review artifacts and unused package-manager state diff --git a/.venv b/.venv deleted file mode 120000 index 3ab1ce63..00000000 --- a/.venv +++ /dev/null @@ -1 +0,0 @@ -/workspace/Jyotisha/.venv \ No newline at end of file diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 47b5958c..514e2175 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -12838,3 +12838,35 @@ - 防复发:保留源/目标、根/嵌套、大小写回归;仓库扫描复用既有标记并检查用户目录前缀,已接入 quick。仅精确许可经过核实的声明/合成样例及无关数值节点,48 项自测通过;历史校正包正常扫描,不豁免整目录。该固定规则集不是通用 PII 检测器。 - 关联记录:BUG-190 / BUG-191 / BUG-192(导入约束历史)、BUG-261 / BUG-278(导入与保护边界)、BUG-972(存量残留)。旧防线覆盖范围有限,未拦截本次路径资料。 - 修复版本:本轮首轮提交 `fe9489e6`;第二轮 P0 修复尚未推送或部署,待远端认证恢复后发布并由验收方复核。 + +## BUG-974 | 跟踪的 `.venv` 符号链接让 staging 隐私扫描 READ_ERROR + +- 状态:resolved +- 首次发现:2026-09-20 +- 最近更新:2026-09-20 +- 影响面:`tests/test_repo_privacy_markers.py`、staging `backend-quality-gate` validate +- 用户现象:门禁 [run 2807](https://git.copse.top/root/Jyotisha/actions/runs/2807) 红。Python 快速门 858 通过、1 失败:`test_tracked_repository_has_no_privacy_markers` 报 `files=1 hits=1` / `READ_ERROR .venv`。`publish` 跳过。线上仍停在上次绿灯 `d6fc4fb8`。 +- 触发条件:staging 推送触发门禁;validate 先 `rm -rf -- .venv` 再 `python3 -m venv --clear .venv`,然后跑仓库跟踪文件隐私扫描。 +- 根因:`9375012f`(文档提交)把名为 `.venv` 的符号链接写入跟踪树。`.gitignore` 写成 `.venv/`,Git 只忽略同名目录、不忽略同名符号链接。CI 用真实虚拟环境目录盖掉该链接后,扫描器对跟踪路径 `.venv` 做 `lstat` 得到目录而非普通文件,记为 `READ_ERROR`。不是又扫到姓名或本机路径。 +- 修复:从跟踪树删除该链接;`.gitignore` 改为 `.venv`(文件、目录、符号链接都忽略)。合同测试锁定:`git ls-files` 不含 `.venv`,`git check-ignore --no-index .venv` 命中。 +- 验证:`pytest tests/test_repo_privacy_markers.py`;前端头像合同见 BUG-975。门禁重跑结果写入进度记录。 +- 防复发:不得把本地运行时目录或指向它的符号链接加入跟踪树;忽略规则不要只写带尾斜杠的目录形式。 +- 相关记录:BUG-972、BUG-973 +- 复发自:无 +- 修复版本:`2bdab58c` + +## BUG-975 | 头像说明文案已改,源码合同仍锁旧句,门禁卡在 npm test + +- 状态:resolved +- 首次发现:2026-09-19 +- 最近更新:2026-09-20 +- 影响面:`frontend/tests/beam-avatar.test.ts`、`frontend/src/components/profile-panel.tsx` +- 用户现象:门禁 [run 2804](https://git.copse.top/root/Jyotisha/actions/runs/2804)、[2805](https://git.copse.top/root/Jyotisha/actions/runs/2805)、[2806](https://git.copse.top/root/Jyotisha/actions/runs/2806) 的 `npm test` 红:`renders the persisted Beam avatar in the sidebar, account menu, and profile editor`。run 2807 先在 Python 步失败,未跑到这一步。 +- 触发条件:设置弹窗改了头像区说明后,任何会跑 `npm test --prefix frontend` 的 staging 门禁。 +- 根因:产品文案已是「Beam 形象会在刷新和换设备后保持一致」,合同仍断言「Beam 形象由随机种子生成」。 +- 修复:合同改为锁定现行文案。不改产品文案。 +- 验证:`frontend/tests/beam-avatar.test.ts` 定向;断言三栏见进度记录。 +- 防复发:改设置弹窗可见文案时同步源码合同,不得只改组件。 +- 相关记录:BUG-970 +- 复发自:无 +- 修复版本:`2bdab58c` diff --git a/docs/tasks/PROGRESS-privacy-venv-20260920.md b/docs/tasks/PROGRESS-privacy-venv-20260920.md new file mode 100644 index 00000000..8e852b0b --- /dev/null +++ b/docs/tasks/PROGRESS-privacy-venv-20260920.md @@ -0,0 +1,43 @@ +# 门禁 `.venv` 符号链接与头像合同 · 执行记录 + +## 基线 + +- 日期:2026-09-20。 +- 模式:直接执行(用户要求修复并重跑门禁)。 +- 基线:`origin/staging` `980c77c3`。 +- 工作树:`.worktrees/privacy-venv-20260920`,分支 `codex/privacy-venv-20260920`。 +- 不改 workflow、不提升 main、不动 DNS。主检出未跟踪文件未纳入本轮。 + +## 事故 + +| 门禁 | SHA | 失败点 | +| --- | --- | --- | +| [2804](https://git.copse.top/root/Jyotisha/actions/runs/2804)–[2806](https://git.copse.top/root/Jyotisha/actions/runs/2806) | `eb8f5147` 起 | `npm test`:Beam 头像合同 | +| [2807](https://git.copse.top/root/Jyotisha/actions/runs/2807) | `8497587e` | Python 快速门:`READ_ERROR .venv`(858 通过 / 1 失败) | + +线上 `/api/health` 仍为上次绿灯 `d6fc4fb8`。 + +## 根因 + +1. **BUG-974**:`9375012f` 把 `.venv` 符号链接写进跟踪树;`.gitignore` 的 `.venv/` 不忽略符号链接。门禁 `rm -rf -- .venv && python3 -m venv --clear .venv` 把链接换成目录,隐私扫描对跟踪路径读目录 → `READ_ERROR`。 +2. **BUG-975**:设置弹窗头像说明已改,源码合同未改。 + +## 改动 + +- `git rm .venv` +- `.gitignore`:`.venv/` → `.venv` +- `tests/test_repo_privacy_markers.py`:锁定 `.venv` 不在 `git ls-files`,且 `check-ignore --no-index .venv` 命中 +- `frontend/tests/beam-avatar.test.ts`:对齐现行文案 + +### 断言三栏(BUG-975) + +| 项 | 原值 | 新值 | 原因 | +| --- | --- | --- | --- | +| `beam-avatar.test.ts` 头像说明 | `/Beam 形象由随机种子生成/` | `/Beam 形象会在刷新和换设备后保持一致/` | 组件文案已改;合同锁旧句导致 2804–2806 红 | + +## 验证 + +- `python -m pytest tests/test_repo_privacy_markers.py`:62 collected / 62 passed(基线 60,本轮 +2:`.venv` 不得跟踪、gitignore 覆盖符号链接名)。 +- `tsx --test tests/beam-avatar.test.ts`:6/6 通过,含原先红的第 6 条。 +- 未跑全量 `npm test` / `run_quality_gate.py --profile quick`(工作树无独立依赖;以门禁为准)。 +- 本轮提交:`2bdab58c`。门禁结论在推送后补。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index a0f2e281..067953cb 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -9,6 +9,7 @@ - [上游私人案例与本机路径清理](PROGRESS-owner-case-purge-20260919.md) — 2026-09-19,执行分支已创建;删除依赖与全仓扫描口径发现任务范围冲突,未交付。 - [侧栏导航注册循环修复与验收](PROGRESS-sidebar-navigation-loop-20260919.md) — 2026-09-19,修复/回归已完成,完整验收与 staging 交付状态见记录。 +- [门禁隐私扫描 `.venv` 与头像合同](PROGRESS-privacy-venv-20260920.md) — 2026-09-20,直接执行:删跟踪的 `.venv` 符号链接、对齐 Beam 文案合同(BUG-974/975)。 ## 状态板 diff --git a/frontend/tests/beam-avatar.test.ts b/frontend/tests/beam-avatar.test.ts index f16cff44..4b374ed1 100644 --- a/frontend/tests/beam-avatar.test.ts +++ b/frontend/tests/beam-avatar.test.ts @@ -94,7 +94,7 @@ test("renders the persisted Beam avatar in the sidebar, account menu, and profil assert.match(sidebar, / None: assert "lines=1" in report and "lines=2" in report +def test_local_python_venv_is_not_tracked() -> None: + paths = tracked_paths(ROOT) + assert ".venv" not in paths + assert not any(path.startswith(".venv/") for path in paths) + + +def test_gitignore_covers_venv_symlink_name() -> None: + assert _git(ROOT, "check-ignore", "--no-index", ".venv").decode("utf8").strip() == ".venv" + + def test_git_enumeration_is_nul_delimited_and_status_first(monkeypatch: pytest.MonkeyPatch) -> None: calls = [] def run(argv, **kwargs):