Files

165 lines
13 KiB
Markdown
Raw Permalink Normal View History

# 项目开发 · 任务执行关键步骤(全文版)
> 🔴 **每个会话、每个任务都必须按本顺序执行;跳步=违规。**
> **实体精要已在 `CODEBUDDY.md §1.5`**(那份**每次会话自动加载**,冲突以 `CODEBUDDY.md` 为准);**本文是全文版**(命令、判据、坑)。
> 权威来源:`CODEBUDDY.md`(根规)+ 技能 `dsh-workflow` → `references/00-平台改造六阶段.md`(六阶段原文)。
---
## 0 一句话总览
**开工前三件 → 六阶段(0 需求识别 → 1 调研 → 2 规划 → 3 开发 → 4 验证 → 5 归档清理)→ 收尾四件。**
其中**三道硬门禁**:**抢不到锁 ⇒ 停手**(R9)|**红线命中 ⇒ 先停手**(R1–R11)|**交付门禁**(本机改完 ≠ 交付)。
---
## 1 开工前三件(顺序固定,⛔ 不准换)
### 1.1 跑状态(1 次调用顶十几轮探索)
```bash
"$PY" "$WS/state.py" # --online 加远端基线
```
🔴 **跑完之前不许 Glob/Grep 全库摸底。** 输出里看:`[锁]` / `[git]` / `[入口]`(它会展开本线接续入口的 §2)。
### 1.2 判可锁定范围(开工门禁)
```bash
bash "$DOC\07-scripts\preflight-lock.sh" "<会话名>" <目标文件...>
```
- 【A】可独立锁 ·【B】秒级独占 ·【C】共享(构建产物/依赖树)·【D】**未归类** ·【E】**机制层**
- 🔴 **【D】或【E】非空 ⇒ `rc=1` 拒开工**:D 先归类再动;**E(机制层:`config`·`crypto`·`isolation`·`index`·`scripts`·`CODEBUDDY.md`·锁与钩子本身)必须独占**,且**仅当确认无其他会话在跑**才可开工。
### 1.3 抢锁(是"抢"不是"看")
```bash
bash "$DOC\07-scripts\handoff-guard.sh" --claim-exec "<会话名>" [--domains <域键>]
```
- 域键 = `<锚点段>/<下一段>`,多个用逗号;**⛔ 不带 `--domains` ⇒ 退化为全局独占**(机制层必走)
- 🔍 **必须"校验结果"不能"看输出"**:① 检查**退出码**(⛔ 不接管道,`| grep` 会吃掉退出码)② **复读 `.locks/<会话名>/DOMAINS` 或 `.exec-lock/OWNER` 并断言是自己的**
- ⚠️ `rc=1` 两因分清:**域冲突(停手)** vs `.gate` 占用(重试)
- ⛔ **抢不到锁 = 终点**:只读、报告、结束(**R9**:不删锁、不接管)
- ✅ **锁只约束「写」,不约束「读」**;⚠️ 会改本地状态的命令(`git fetch/checkout/stash/reset/switch`)**算写** ⇒ 要持锁
---
## 2 六阶段
### 阶段 0 · 需求识别(先盘点再动手,勿跳步)
0. ★ **开工前置检查 —— 本流程最重要的一步**(血的教训:不先查"已经有什么"就凭直觉装工具/猜机制,事后才发现文档里早写了)。任何「**装工具 / 写自动化 / 查机制**」之前按序做完三条:
1. **先看可用技能列表**(会话开始就在)⇒ 有对应的**立刻加载技能**,禁止另起炉灶;
2. **先看本机/项目已有资产**:`E:/ProgramData/.workbuddy/skills/`(技能根,改动下一请求生效)、工作区 `MEMORY.md`;
3. **要装任何东西前自问:本机已有的能否满足?** 能 ⇒ 不装;不能 ⇒ **先说清楚再装**。
1. **环境盘点**:本机 / 服务器 / 工具链 / 权限 / DB / 实例状态先行。
2. **需求边界**:区分「**方案请求**」(只输出方案 —— **方案与执行分离**,未经明确授权不改文件)与「**任务明确直接执行**」。
3. **用户确认**:关键分叉用**选项表**收敛(推荐项置首)。
4. **输出格式**:**一句话结论先行** + 表格化细节。
### 阶段 1 · 调研(源码级实证优先,⛔ 禁只靠文档推断)
0. ★ **用户报障第一步:先拿「真实失败请求」,别猜** —— 平台 journal 里有精确 URL + method + status:
```bash
ssh ... 'journalctl -u dshs --since "-30min" --no-pager \
| grep -E "401|403|404|500|502|503|crash-restart|YAMLException|ERR_MODULE" \
| grep -v "level.:30.*200"'
```
判据:`401` 先分辨**平台 401** 还是**实例 401**(改的地方完全不同);`502` = 实例没起来 ⇒ 翻同段 `YAMLException` / `ERR_MODULE_NOT_FOUND` / `crash-loop`。
1. **只读分析官方包**(允许):读 bundle 定位机制(slot 声明、inject 契约)。**绝不写官方主程序**。
2. **服务器实测 > 推断**:区分 fence 层 / 应用层错误。
3. **双端对照**:archive 源 ↔ 实例安装副本 **md5 对账**。
4. **多模型交叉验证**:关键结论不轻信单点推断。
### 阶段 2 · 规划(文档先行,方案确认后动工)
1. **方案对比表**:≥2 选项 + 各自影响/风险 + 建议。
2. 🔴 **红线自查 R1–R11**(逐条过;命中 ⇒ 先停手)。
3. **影响评估**:重启换端口 / 旧连接断连 / 权限影响…;**命中 R5(权限扩大)另附「权限影响评估」+ 改动前后 diff**。
4. **文档占位**:`04-调整方案/` 建编号档案 —— ⚠️ **档案号必须「原子占用」**(`mkdir .lock-$n` 或 `flock`),⛔ 不能"读一眼 ls 再写"(已两次撞号)。
### 阶段 3 · 开发(小步 + 备份 + 逐条验证)
1. `scp` 服务器源码 → 本地 → **读一条 → 改一条 → 验一条**(⛔ 禁批量读全部文件)
2. `scp` 回服务器 `/tmp/` → `cp` 覆盖前**先备份** `bak-<功能>-<YYYYMMDD>/`
3. `npm run build`(零报错)→ `systemctl restart dshs`
4. **本机直连验证**(绕 DNS/代理):`curl -sk --resolve <域名>:443:127.0.0.1 https://<域名>/api/...`
> ⚠️ **全量覆盖 `lib/` 前必须先在 HEAD 上 build**(曾把别人已上线的修复整体回退);**部署完立刻复验「上一次刚验收过的东西」**。
> ⚠️ **「已部署」≠「已提交」**;**不能拿服务器状态当版本事实源**。
**客户端插件(client bundle)另有链路**:**先做基线校验**(拉线上 tgz ↔ 本地源码**忽略行尾**全量 diff,确认"差异只有我要改的")→ 改 → `npm pack` → 铺 tgz(chown 用户 uid)→ kill 实例 → 抓新端口 → 验 `node_modules` 里 markers(版本、关键串计数)。⛔ **反例:先改后验**(顺序错 = 风险窗口白开)。
### 阶段 4 · 验证(全链路 + 浏览器实测 + 清理)
1. **API 链路**:portal enter → url token → 页面 200 → 关键接口 ok。
- 🔴 **用例必须同时覆盖「有请求体」与「无请求体」**(只测 `POST` 会整条漏掉 `GET`/`SSE`)。
- **模拟浏览器语义要测到底**:只带最初那个旧 cookie 再跑一遍,并显式断言 `Set-Cookie` 回写。
2. **浏览器验证栈**:**只用 `browser-harness`**(⛔ `agent-browser`、Playwright 均已禁用)。
- 🔴 **铁律 0:动手前先 `list_tabs()` 确认"你在驱动哪个浏览器"** —— ⛔ 不要假定端口号(端口归属每次都变);**看到的不是你新开的空浏览器 ⇒ 立刻停手**,只做只读检查。收尾必须 `close_tab` 关掉自己开的标签。
3. **静态 vs 后端**:改 `web/*.html` **无需重启**;改 `src/**` 才 build + restart。⛔ 别为前端改动重启服务(会打断所有用户实例)。
4. **安全面复测**:降权 uid 探测敏感目录应 denied;中间目录 711(去 r 留 x)不破坏子进程访问。
5. **清理临时物**(`poc-*` 会话用完即删、测试 tab 关闭)。
6. **截图留证**(每功能验收存 PNG + 展示)。
7. 🔴 **交付前必问一句:这份改动「出厂」了吗** —— 改完文件 ≠ 用户会看到变化。**一秒自检**:`ls -la` 对比「源文件 mtime」与「最新 tgz mtime」,**源更新 ⇒ 还没出厂**。
8. **视觉/UI 必须三层验收**:① 单测(断言 **class 名与结构**,不只文本)② 实装(`md5sum` 对齐本地产物 ↔ 实例 `node_modules` 实链,断言旧标记为 0)③ 端到端(解出真实 bundle URL → `curl` 回来 grep 新/旧标记)。
9. **用户说"参考某现成页面的样式" ⇒ 抄那个页面的源码**(逐条搬实际取值),⛔ 不要抄规范的抽象条目再自行演绎。
### 阶段 5 · 归档清理(文档同步 + 三层沉淀)
0. ★★ **交付门禁:本机改完 ≠ 交付**。收尾前逐层自问三句:**① 这次改的是哪一层?② 这一层的生效链路是什么?③ 最后一步走了吗、在「用户可见面」验了吗?**
| 改动所在层 | 生效链路(缺一步都不算交付) | 用户可见面复验 |
|---|---|---|
| 平台静态页 | `scp` 到服务器对应路径(注意 CDN/CF 缓存) | `curl` 取**线上**页面确认新内容 |
| 平台 TS(`src/**`) | `npm run build` → `systemctl restart dshs` | **线上**端点/页面实测(**不是**本地 build 通过) |
| 自研插件(client bundle / host 面) | 打 tgz → 导入候选池 → 实例「功能管理」启用 → **重启实例** | 取实例页 HTML 里**真实 bundle URL** 逐串验证 |
| 文档库 / 技能 | `docs-sync-check.sh` 对账 → `scp` → **复跑对账** | 对账「一致」计数回升 |
| 配置(env / nginx / nft / 配额) | 改 → reload / restart 对应服务 | 生效值实测 |
⛔ **四条"自我安慰"一条都不算交付**:**本机改完了 / build 通过了 / 本地打包完成 / 已 commit 了**。
⛔ **也别回头问用户"要不要部署"** —— 不打断在线用户的上线属**我的 lane 内执行细节 ⇒ 直接做完**(§3 R7-边界)。
1. **文档落盘**:**源 = 本地 `D:\github\dsh_shenxian\dsh-server-docs`**(目录即 git 工作树)。
**四件套(顺序固定)**:`docs-audit.py` → `docs-index-stats.py --write` → `docs-manifest.py` → `docs-sync-check.sh`。
传服务器用**单个 `tar` 管道**(逐个 `scp` 会因每文件一条 SSH 连接而超时),随后 `chmod`(目录 700 / 文件 600)。
⚠️ 本库**多会话共用** ⇒ 提交前 `git status`,**只 add 自己改的文件**;`docs-manifest.json` 是派生文件,别人有在途改动时**宁可让它 dirty**。
2. **档案更新**:`04-调整方案/<NN>-*.md` 写"需求→改动文件→commit→验证记录";`INDEX.md` 同步(以它为准)。
3. **三层沉淀**:治本(机制/流程固化进 skill 或档案)/失误(**append-only** 教训档)/记忆(`AGENTS.md` 或工作区规则)。
4. **汇总表**:带状态/结果列交付,列明未完成项与副作用。
5. **技能自身归档**(本 skill 有改动时**必做**):本机 → 服务器**单向推**,**md5 双端一致**才算完成;同时更新引用它的 `README` 模块表行 / `INDEX` 场景速查行。
⚠️ **改「跨载体规则」时必做全载体扫描**(`grep -rn` 关键短语,把所有命中处**全部**改掉;只改一处 ⇒ 其余载体自相矛盾,比不改更糟)。
---
## 3 收尾四件(缺一不算完成)
1. **反序释放锁**:先 `--release`,最后 `--release-exec "<会话名>"` —— ⛔ 不带会话名 ⇒ **拒绝释放**
🔓 **释放时机 = 交付闭环走完**(台账 → 四件套 → commit → 推送 + 对账 → 归档),**不是"改完就放"**;**要等用户拍板 ⇒ 先释放再等**
2. **台账 / 档案**(见阶段 5)
3. **提交边界**:未明确要求 ⇒ **不 commit / 不 push / 不同步仓库**;说了才做且**只 add 自己改的文件**;
⛔ **三类禁止入库**:`tmp/` / 中间产物 / 会话交接单。**提交前自查** `git diff --cached --name-only` 命中即 `git reset`
4. **收口清本棒 `tmp/`**;🔴 **结束语必须对锁状态负责**(写明"已释放",或点名锁在谁手上 + 原因 + 下一步)
⛔ **禁"抢到锁、做一半、不解锁就结束回合"**(带锁结束 = 把所有人挡在门外)。⚠️ 护栏额度耗尽时 release 可能 `rc=124` 卡住 ⇒ 用 `mv` 等效释放。
---
## 4 并行纪律(要点)
- 共享文件**只用 `Edit` 精确片段替换**(失败 = 天然冲突检测),**⛔ 禁整文件 `Write` 覆盖**;`settings.json` 的 `hooks` 段与用户级 `MEMORY.md` **只能增删条目,⛔ 禁整段覆盖**
- **并行度由「冲突域」定,不由任务数量定**:只读/调研可自由并行;改码 → 构建 → 重启 → 提交 → 写文档是**单通道,必须串行**
- 🔴 **域键算法 shell 与 hook 两侧必须逐字一致**(`_ANCHOR_SEGS` ⇄ `_DOMAIN_SEGS`),⛔ 改一侧 ⇒ **域锁静默失效(假绿)**
- ⚠️ **钩子 = 会话启动时快照**:对**在跑的会话无效** ⇒ 改完要**完全重启**(关窗 ≠ 退出);**脚本路径失配 = fail-closed**(Write/Edit 全被拒)
---
## 5 收尾自检清单(逐项打勾)
- [ ] 跑过 `state.py`?门禁 `preflight-lock.sh` 过?锁**校验过是自己的**?
- [ ] 阶段 0 的「开工前置检查」做了吗(**先看技能/已有资产**)?
- [ ] **红线 R1–R11 逐条过**了吗?命中 R5 出了权限影响评估吗?
- [ ] 覆盖前**备份**了吗?**部署完复验"上一次刚验收过的东西"**了吗?
- [ ] 用例覆盖**「有/无请求体」**两类了吗?
- [ ] **交付门禁三句**答得上吗?**四条自我安慰**有没有出现?
- [ ] 四件套跑了吗(顺序对)?只 add 自己的文件?
- [ ] **锁释放了吗**(带会话名)?结束语点名锁状态了吗?
- [ ] 本棒 `tmp/` 清了吗?