记录旧 Portal 兼容清理证据(07-16-legacy-portal-navigation-compat-cleanup)

这个提交包含在:
2026-07-16 16:46:56 +08:00
父节点 9a8b7477b6
当前提交 9568168bfc
共修改 6 个文件,包含 296 行新增和 0 行删除
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,56 @@
# 旧 Portal 导航兼容清理设计
## Safety Boundary
本任务只移除已经没有实际调用链的兼容描述和重复报告字段。`Portal` 作为负向英文检测词、`/portal` 路由和内部技术标识继续保留;历史审计文件保持只读。
## Classification Matrix
| 类别 | 例子 | 处理 |
| --- | --- | --- |
| 当前用户导航合同 | `工作台` | 保留并作为唯一允许 label |
| 失效双文案兼容 | 部署规约中的 `工作台 | Portal` | 删除旧 fallback |
| 负向视觉检测 | `ENGLISH_PRIMARY_TERMS` 中的 `Portal` | 保留,用于发现英文旧词回归 |
| 重复报告字段 | `navPortalCopy` | 删除;`englishFound` 已覆盖同一信号 |
| 内部技术标识 | `/portal`、`assertPortalLoaded`、Portal API/组件 | 保留 |
| 历史证据 | 归档 summary、Issue CSV、旧截图 | 保留,不改写 |
| 现行手册术语 | 管理员/员工/部署手册中的 `Portal` | 由用户决定是否另行迁移 |
## Implementation
### 最小方案
1. 把部署规约的当前 label 合同收敛为精确 `工作台`。
2. 移除规约中的旧 mock/fallback 描述和 `.or(...Portal)` 示例。
3. 从只读视觉报告对象中移除 `navPortalCopy` 的采集与输出。
4. 保持 `Portal` 在 `ENGLISH_PRIMARY_TERMS` 中,从而继续生成英文文案 finding。
### 扩展方案
若用户选择现行手册迁移,先由文档状态矩阵筛出 CURRENT 用户/运维事实源,再逐条区分用户文案、历史描述和技术路由,不能全局替换。
## Validation Matrix
| 条件 | 预期 |
| --- | --- |
| 当前导航源和 mock label | 只有 `工作台` |
| 部署规约导航 fallback | 不再允许 `Portal` |
| 视觉英文词检测 | 仍包含 `Portal` |
| 新报告 schema | 无 `navPortalCopy`,保留 `englishFound` |
| 历史归档报告 | 不修改,仍可保留旧字段 |
| TypeScript / Playwright `--list` / build | 通过 |
| Trellis/task/diff 门禁 | 通过 |
## Failure Handling
- 发现现行消费者读取 `navPortalCopy`:停止删除该字段,先迁移消费者并更新合同。
- 发现 fixture 仍输出 `Portal`:先判断是否仍为合法用户体验;不能靠继续放宽 smoke 掩盖文案回归。
- Playwright spec 加载或类型检查失败:恢复相关改动并按最小范围修复,不扩展到内部符号重命名。
## Rollback
从任务提交的父提交恢复部署规约段落和 `navPortalCopy` 两处代码即可;不涉及数据库、路由、配置或生产数据回滚。
## Verification Boundary
本任务的默认验证为本地静态、TypeScript、Playwright spec 加载与 build。未获单独批准时不运行带凭据公网 smoke/视觉审计,不宣称已部署或线上可测。
@@ -0,0 +1 @@
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
@@ -0,0 +1,147 @@
# 清理旧 Portal 导航兼容
## Goal
移除已经失效的 `Portal` 导航双文案兼容和重复报告字段,使公网 smoke、视觉审计与当前产品文案统一以 `工作台` 为准,同时保留 `/portal` 路由、内部技术标识、对用户可见英文 `Portal` 的负向检测以及历史审计材料。
## Scope
- 最小推荐范围:更新部署规约中的 `工作台 | Portal` 双接受合同为仅接受 `工作台`。
- 删除只读视觉报告中与 `englishFound` 重复、无现行消费者的 `navPortalCopy` 字段。
- 保留 `ENGLISH_PRIMARY_TERMS` 中的 `Portal`,继续把用户可见英文旧词视为视觉 finding。
- 现行用户/运维手册中的 `Portal` 术语不在本批迁移范围。
## What I Already Know
- 当前前端导航、后端 workspace 默认导航和所有现行 mock fixture 都使用 `工作台`。
- `client/tests/e2e/helpers/smokeAssertions.ts` 自 2026-05-29 起只接受精确中文 `工作台`,没有运行时代码仍执行双文案兼容。
- `.trellis/spec/hyb-oa/deployment-trialrun.md` 仍声称旧 mock 可输出 `Portal`,并给出 `.or(...Portal)` 示例;该规约已与实际 helper 漂移。
- 当前 mock/fixture 中未发现 `label: "Portal"` 或等价单引号写法。
- `client/tests/e2e/oafront3-pc-readonly-visual.spec.ts` 把 `Portal` 纳入禁止英文主展示词,这是应保留的负向检测。
- 同一视觉报告另行输出 `navPortalCopy: text.includes("Portal")`,但 `englishFound` 已包含相同信号;现行代码没有消费者。
- 归档视觉报告包含旧 `navPortalCopy` 字段,属于历史证据,不改写。
- `/portal` 路由、`assertPortalLoaded`、`PortalHomePage`、Portal API/数据库标识和测试标题是仍在使用的内部技术标识,不等同于用户可见旧导航兼容。
- 多份当前手册和业务规约仍用 `Portal` 指代工作台;一次性迁移会显著扩大审阅范围。
## Confirmed Scope
- 用户于 2026-07-16 选择方案 1,采用最小兼容清理,不把文档术语迁移和内部符号重命名混入同一批。
- 移除重复报告字段不会影响历史报告读取,因为未发现现行聚合器或门禁消费该字段。
- 本任务不改变路由、导航结构、页面视觉、角色权限或部署行为。
## Open Questions
- 无。
## Requirements
- 规约必须准确反映现行 smoke helper:导航仅接受 `工作台`。
- 删除重复的 `navPortalCopy` 新报告字段,但保留 `Portal` 英文负向检测。
- 保留 `/portal` 路由和所有仍有消费者的内部 Portal 技术标识。
- 不改写历史 Issue、归档 task 或归档视觉报告。
- 验证 TypeScript、Playwright spec 加载、前端构建和 Trellis 治理。
- 验证产生的 `client/dist/`、Playwright report 和 test-results 在取证后清理。
## Acceptance Criteria
- [x] 部署规约不再声明或示范 `工作台 | Portal` 导航双接受。
- [x] `smokeAssertions.ts` 继续精确断言 `工作台`,不新增其他旧词 fallback。
- [x] 新生成的只读视觉报告不再包含重复字段 `navPortalCopy`。
- [x] `ENGLISH_PRIMARY_TERMS` 仍包含 `Portal`,用户可见旧英文文案仍产生 finding。
- [x] 当前 mock/fixture 不含 `Portal` 导航 label。
- [x] `/portal` 路由与内部 Portal 标识保持不变。
- [x] TypeScript、Playwright spec `--list`、前端 build、task/governance/diff 门禁通过。
- [x] 最终工作树不包含验证生成物,修改范围与用户选择一致。
## Feasible Approaches
### 方案 1:最小兼容清理(推荐)
- 更新部署规约为中文单一合同。
- 删除重复 `navPortalCopy` 报告字段。
- 保留负向英文检测、内部标识和所有现行/历史文档原状。
- 优点:两处小改、风险最低,直接解决实际兼容漂移。
- 缺点:部分现行手册仍使用 `Portal` 作为工作台术语。
### 方案 2:兼容清理 + 现行手册术语迁移
- 在方案 1 基础上,把 CURRENT 用户/运维文档中面向人的 `Portal` 改为 `工作台`。
- 优点:用户和运维文案更一致。
- 缺点:涉及多份事实源,需要逐条判断历史描述、路由名与当前体验,回归面明显扩大。
### 方案 3:连内部 Portal 标识一起重命名
- 同时重命名路由、组件、API、测试标题或数据库技术标识。
- 不推荐:没有用户价值,会制造跨前后端、数据与历史兼容风险。
## Definition of Done
- 用户选择的范围完成并记录,未顺带重命名内部技术标识。
- 兼容删除有静态引用、历史、报告消费者和回滚证据。
- 前端与治理门禁通过,生成物清理完成。
- 形成中文本地提交计划并另行取得提交确认;不自动 push 或部署。
## Technical Approach
1. 区分用户可见旧词、负向检测、内部标识、现行手册与历史证据。
2. 以现行 helper 和导航源为事实,删除规约中的虚假双接受描述。
3. 删除只读视觉报告中的重复字段,保留 `englishFound` 的 `Portal` 负向信号。
4. 运行静态引用、TypeScript、Playwright 加载、build 和治理门禁。
详细引用矩阵、验证边界与回滚见 `design.md` 和 `research/portal-compat-audit.md`。
## Decision (ADR-lite)
**Context**:运行时已经中文单一化,但部署规约仍保留旧 fallback,视觉报告又重复输出相同旧词信号;同时内部 `/portal` 技术标识和历史证据仍有合法用途。
**Decision**:用户已选择方案 1;只删失效兼容和重复报告字段,不做大范围术语或内部符号迁移。
**Consequences**:当前导航合同与代码重新一致,未来报告更精简;现行手册术语一致性留待独立文档治理批次。
## Test Plan
```bash
cd client && npm run typecheck
cd client && npx playwright test tests/e2e/oafront3-pc-readonly-visual.spec.ts --list
cd client && npx playwright test tests/e2e/visual-shell.spec.ts --list
cd client && npm run build
python3 ./.trellis/scripts/task.py validate 07-16-legacy-portal-navigation-compat-cleanup
node scripts/qa/check-trellis-governance.mjs
git diff --check
```
- 不运行带凭据公网视觉审计或 live smoke;若需要真实公网复核,必须另行批准并提供前置条件。
- 不执行部署、生产配置修改、数据库写入或企业微信写入。
## Verification Results
- `smokeAssertions.ts` 仍有两处精确 `工作台` 导航断言;当前前后端及 fixture 搜索未发现 `Portal` 导航 label。
- 活跃测试、规约、脚本和部署范围中 `navPortalCopy` 引用为 0;受保护归档报告仍保留旧字段。
- `ENGLISH_PRIMARY_TERMS` 继续包含 `Portal`,`englishFound` 仍是用户可见英文旧词的单一 finding 信号。
- `cd client && npm run typecheck` 退出码为 0。
- 两个相关 Playwright spec 使用 `--list` 成功加载,共列出 2 个文件、6 个测试;未启动浏览器或访问公网。
- `cd client && npm run build` 退出码为 0:Vite 转换 2381 个模块,PWA 生成 102 个预缓存条目;仅有既有 Browserslist 数据陈旧提示。
- task validate、Trellis governance 和 `git diff --check` 严格模式通过;治理无 warning/error。
- `client/dist`、`client/playwright-report` 和 `client/test-results` 已清理。
- 独立只读复核无阻断:确认精确中文导航合同、`englishFound` 检测能力、内部标识与历史证据边界均保持完整,工作树未超出方案 1。
- 未执行 live smoke、带凭据视觉审计、部署、push 或任何数据写入。
## Out of Scope
- 未经选择的现行手册术语批量迁移。
- `/portal` 路由、Portal API、数据库字段、组件名和内部 helper 名重命名。
- 改写历史 Issue CSV、归档 task、归档视觉报告或旧截图。
- 页面布局、视觉、交互、权限、导航分组或业务能力调整。
- push、部署、公网检查或真实数据写入。
## Technical Notes
- 当前中文导航源:`client/src/components/navigation/NavLinks.tsx`、`client/src/features/navigation/schema.ts`、`server/src/services/workspaceSettings.js`。
- 当前 smoke helper:`client/tests/e2e/helpers/smokeAssertions.ts`。
- 待清理规约:`.trellis/spec/hyb-oa/deployment-trialrun.md`。
- 待精简报告:`client/tests/e2e/oafront3-pc-readonly-visual.spec.ts`。
- 上一批候选:`.trellis/tasks/archive/2026-07/07-15-production-trust-closeout-cleanup/research/cleanup-candidate-inventory.md`。
## Research References
- `research/portal-compat-audit.md`:导航源、fixture、规约、视觉报告、历史证据和内部标识分类结果。
@@ -0,0 +1,59 @@
# 旧 Portal 导航兼容审计
## Summary
当前运行时已经不存在 `Portal` 导航双接受:前端、后端、fixture 和 smoke helper 均以 `工作台` 为唯一用户导航 label。剩余可清理项是部署规约的过时 fallback 描述,以及视觉报告中与 `englishFound` 重复的 `navPortalCopy` 字段。
## Current Navigation Sources
- 前端默认导航:`NavLinks.tsx` 使用 `工作台`。
- 前端路由元数据:navigation schema 使用 `工作台`。
- 后端 workspace 导航:workspace settings 使用 `工作台`。
- 当前 E2E fixture 搜索未发现 `label: "Portal"`。
- `smokeAssertions.ts` 对工作台链接使用精确中文断言。
## History
- Git blame 显示 smoke helper 在 2026-05-29 已从旧英文 label 迁移到 `工作台`。
- 部署规约仍描述旧 fixture 和 `.or(...Portal)` fallback,已经落后于代码事实。
- 归档只读视觉报告保留 `navPortalCopy: false`,属于当时的审计 schema,不应改写。
## Visual Audit Field
- `ENGLISH_PRIMARY_TERMS` 包含 `Portal`,页面出现该用户可见英文词时会进入 `englishFound` 并产生 finding。
- `readMetrics` 另行计算 `navPortalCopy: text.includes("Portal")`,报告对象再次输出该布尔值。
- 当前仓库除该测试文件和受保护归档报告外,没有现行消费者读取 `navPortalCopy`。
- 因此删除未来报告的 `navPortalCopy` 不会降低检测能力,也不会破坏现行门禁;`englishFound` 是保留的单一信号。
## Protected Internal Identifiers
- `/portal` 是现行路由和 Enterprise WeChat return target。
- Portal API、feature flag、数据库实体、组件和 helper 名仍有大量消费者。
- 测试标题中的 Portal 多为内部场景名,不是导航 fallback。
- Radix UI 的 `DialogPrimitive.Portal` / `DropdownMenuPrimitive.Portal` 是第三方渲染概念,与产品文案无关。
## Current Documentation
- 多份 CURRENT 用户、管理员、业务和部署手册仍用 `Portal` 指代工作台。
- 这些文档混合了当前操作说明、历史结论、路由术语和内部模块名;若迁移必须按状态矩阵逐份审核。
- 不建议把文档迁移与两处兼容清理自动捆绑,也不能全局替换。
## Recommended Scope
采用最小方案:更新部署规约,删除重复报告字段,保留英文负向检测、内部标识、现行手册和历史证据。后续若用户希望统一手册术语,另建文档治理批次。
## Validation
- 精确搜索当前 mock label 和 `navPortalCopy` 消费者。
- 前端 TypeScript 检查。
- 两个相关 Playwright spec 使用 `--list` 加载。
- 前端 production build。
- Trellis governance、task validate 和 `git diff --check`。
## 2026-07-16 Execution Result
- 用户选择最小方案;部署规约已收敛为精确中文导航合同。
- 新视觉报告已移除重复 `navPortalCopy` 字段,`Portal` 英文负向检测保持不变。
- 当前 fixture 的旧导航 label 和活跃重复字段消费者均为 0。
- TypeScript、两个 Playwright spec 的 `--list`、production build 和 Trellis 治理通过。
- 验证生成物已清理;未运行公网或带凭据检查。
@@ -0,0 +1,32 @@
{
"id": "legacy-portal-navigation-compat-cleanup",
"name": "legacy-portal-navigation-compat-cleanup",
"title": "清理旧 Portal 导航兼容",
"description": "移除已经失效的 Portal 导航双文案兼容和重复视觉报告字段,同时保留中文负向检测、内部路由标识与历史证据。",
"status": "in_progress",
"dev_type": null,
"scope": "deployment navigation spec, focused Playwright visual report compatibility, and current Trellis evidence",
"package": null,
"priority": "P2",
"creator": "shunli",
"assignee": "shunli",
"createdAt": "2026-07-16",
"completedAt": null,
"branch": null,
"base_branch": "main",
"worktree_path": null,
"commit": null,
"pr_url": null,
"subtasks": [],
"children": [],
"parent": null,
"relatedFiles": [
".trellis/spec/hyb-oa/deployment-trialrun.md",
"client/tests/e2e/helpers/smokeAssertions.ts",
"client/tests/e2e/oafront3-pc-readonly-visual.spec.ts",
"client/src/components/navigation/NavLinks.tsx",
"server/src/services/workspaceSettings.js"
],
"notes": "用户于 2026-07-16 选择方案 1;过时导航 fallback 和重复视觉报告字段已清理,本地门禁通过,现行手册与内部 Portal 标识保持不变。",
"meta": {}
}