@nathan33/nao-skill 0.20.0 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.agents/checklists/pm.md
CHANGED
|
@@ -25,7 +25,7 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
25
25
|
|
|
26
26
|
> 写作要求(首屏 TL;DR、每格 ≤3 句、不适用项写法、长度上限 150 行):@.agents/checklists/deliverable-docs.md §三(写 PRD 前读)。
|
|
27
27
|
|
|
28
|
-
## 硬性红线(完整
|
|
28
|
+
## 硬性红线(完整 34 项)
|
|
29
29
|
|
|
30
30
|
- [ ] 无目标指标/假设就进开发?
|
|
31
31
|
- [ ] 边界不清晰(未写不做什么)?
|
|
@@ -54,6 +54,7 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
54
54
|
- [ ] PM 亲自合并 PR / `push` main?(合并由 RD 执行,PM 只验收授权)
|
|
55
55
|
- [ ] PM 改了**源码/测试/构建配置**,或手改冲突内容?(应转 worker;PM 只做仓库治理与发布)
|
|
56
56
|
- [ ] main 上出现多条本需求提交,或出现 `wip()` 提交(未 squash)?
|
|
57
|
+
- [ ] 为文档 / 台账**单开 PR**,或任务期文档作为**独立提交直落 main**?(应随任务 PR;唯一例外 = BR3 立项摘要,降级批次无例外;见 `github-flow.md`)
|
|
57
58
|
- [ ] PR 标题 / 提交信息不可读(纯编号/类名/函数名/文件路径)?
|
|
58
59
|
- [ ] Issue 与 `docs/` 双源(正文抄进 Issue,或状态只留平台)?
|
|
59
60
|
- [ ] 未过验收 / 门禁未绿就打 tag 或 release,或 tag 指向非 main 合并提交?(见 `github-flow.md`)
|
|
@@ -62,7 +63,7 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
62
63
|
- [ ] 输出里有 `warn`/`error`/`pending approval`/`N vulnerabilities` 却判完成,或遗留项未走三出口(「先放着」不算出口)?(见 @.agents/skills/task-completion.md)
|
|
63
64
|
- [ ] 降级(无 `gh` / 无远端)未在 `tasks-state` 与回执中标注?
|
|
64
65
|
|
|
65
|
-
## 交付检查清单(完整
|
|
66
|
+
## 交付检查清单(完整 43 项)
|
|
66
67
|
|
|
67
68
|
- [ ] 目标/边界/验收三件事齐备
|
|
68
69
|
- [ ] 证据 + 5 Whys 已产出
|
|
@@ -97,9 +98,11 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
97
98
|
- [ ] 业界调研(若有)已落盘 `docs/research/`,每条含「适用条件 + 本项目差异(采纳/改造/不采纳)」;引用带访问日期,查不到已写「未检索到」
|
|
98
99
|
- [ ] 派发消息已给出**需求分支** `feat/<issue-id>-<slug>`(或降级 `nao/<批次-slug>`)、PR owner、Reviewer
|
|
99
100
|
- [ ] 工作期无 WIP 提交落在 main;暂存为路径级(无 `git add -A` 卷走他人改动)
|
|
101
|
+
- [ ] **文档随任务 PR**:本任务文档与台账(PRD 定稿 / 报告 / ADR / `docs/tasks-state.md` / 索引 / release notes)已在本需求分支提交并随同一 PR 进 main;main 上无 `docs(<编号>):` 独立提交、无文档-only PR(立项摘要例外仅 1 条且单一文件)
|
|
100
102
|
- [ ] Issue 已建(或降级已标注):body 为摘要 + 指针,正文在 `docs/prds/`;同步仅 5 个节点
|
|
101
103
|
- [ ] 验收在 PR 上完成:AC 逐条评论核对 + QA 门禁数字;**UI 呈现类已交用户验收清单并获回填**(QA 产出 → PM 审 → 用户执行);**验收通过后才授权合并**
|
|
102
104
|
- [ ] 合并由 RD 执行(`--squash`);main 上本需求恰好 1 条提交且无 `wip()`;需求分支已删除
|
|
105
|
+
- [ ] 合并前已核「分支无未推送提交」(适用:在分支上提交过的**任何角色**,含 PM 落的文档/台账):`git rev-list --count origin/<branch>..HEAD` = 0 · `git status --porcelain` 为空 · `HEAD == @{u}`;任一不满足 ⇒ 不得贴验收评论 / 授权合并(T533 孤儿提交教训:`docs/reports/2026-10-30-T533-retro.md`)
|
|
103
106
|
- [ ] 发布(若有):版本号符合 SemVer/项目约定;tag 指向 main 合并提交;release notes 用户可读且落盘 `docs/releases/`(核 @.agents/common/release-notes.md)
|
|
104
107
|
- [ ] `gh` 可用则已用 `gh`,降级已注明;发布后 `tasks-state` 版本/Tag 行已更新
|
|
105
108
|
- [ ] 任务 DoD 四类已随**开工确认卡**逐任务实例化(产物路径 / 可执行验证判据 / 遗留项 / 交接),验收按同一份核
|
|
@@ -109,6 +112,7 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
109
112
|
## 会话回收 / 收窗核对(验收通过后 / 手工关窗前)
|
|
110
113
|
|
|
111
114
|
- [ ] 派生会话:`tasks-state` 已把任务推进到「已验收 / 已归档」→ `nao-fleet.sh close --task <编号> <别名>`(否则会被状态闸门拦下)
|
|
115
|
+
- [ ] `status` 残留节按**仓归属**读:本仓行才可 `close`;他仓 / 归属不可判定行的处置见 @.agents/skills/pm-operations.md「残留自检」(单源,本清单不重复文案)
|
|
112
116
|
- [ ] 常驻会话**不回收**(保留复用);上下文变长时 `ensure --force` 重开
|
|
113
117
|
- [ ] 手工关窗(tmux `kill-pane`)前:该会话已回**终态回执**(**未回执不得关**)+ `tmux capture-pane -p -t <pane>` 末 5 行无 `Working`/spinner + 产物已落盘(`git log` 有提交且**落在需求分支**、工作区干净、无 WIP 提交泄漏到 main、dev server/探针已停)
|
|
114
|
-
- [ ] 残留已核对:`nao-fleet.sh status`
|
|
118
|
+
- [ ] 残留已核对:`nao-fleet.sh status` **本仓**无 `! 残留` 提示(有则 `close --task` 或补登 tasks-state);`~`(他仓)/ `?`(归属不可判定)行按上一条指针处置,**不得**在本仓 `close`
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 产品经理角色 Prompt(短常驻)——需求分析/PRD/优先级/验收/多会话调度
|
|
3
3
|
role: pm
|
|
4
|
-
version:
|
|
5
|
-
updated: 2026-10-
|
|
4
|
+
version: 30
|
|
5
|
+
updated: 2026-10-31
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# 产品经理(PM)
|
|
@@ -62,7 +62,8 @@ updated: 2026-10-28
|
|
|
62
62
|
- **终态回执闸门**:每次派发(含架构评审)必须收到 `[编号] done` 回执(两级:默认 `done(lite)`;有阻塞/风险/需决策 `done(full)`,模板见 @.agents/checklists/comm-templates.md);未见回执(含 arch 静默)→ **主动追讨**,必要时上报用户,**不默认成功**。
|
|
63
63
|
- **任务完成闸门(交付 + 维护通用)**:任务单元分**交付型**(Issue 号/批次号)与**维护型**(`M<YYYYMMDD>-<slug>`,外部命令/依赖/环境动作);DoD 四类(产物/验证/遗留项/交接)在**开工确认卡**上逐任务实例化,验收按同一份核;收尾时遗留项必须走**三出口**(关闭 / 接受含到期日 / 转办),零遗留显式写「无」;命中**返工 ≥1 / 漏闸 / 事故 / 同类第二次 / 用户投诉** → L1 完整复盘。协议与判据见 @.agents/skills/task-completion.md。
|
|
64
64
|
- **验收闭环(省 token)**:核对 AC 五覆盖 + 回执「清单」字段(未核对则打回);验收 = 核对回执**全量门禁精确数字** + 读变更文件核对 AC + **异常才复跑/抽查**(**不可改码**、**不重复跑 worker 已跑的门禁**);读码走三段阶梯(原生入口 `codegraph_explore`(需插件 + CLI + 索引齐备)→ CLI → `grep -rn` + 行段;详情见 `@.agents/skills/codegraph.md`;行段读取如 `codegraph node --file <f> --offset <n> --limit <m>`),**禁 cat 全文**;**UI 呈现类验收 = 用户验收清单**(QA 产出 → PM 审 → 用户执行回填 → QA 据回填关闭/重开缺陷;清单落 `docs/reports/<编号>-user-acceptance.md`,见 qa 卡)。
|
|
65
|
-
- **合并闸门(PM 控制合并时间点)**:工作期 RD 只在需求分支 `feat/<issue-id>-<slug>`(降级 `nao/<批次-slug>`)提交(`wip(<编号>):` 检查点、路径级暂存、禁 `-A`)。**PM 验收通过 = 授权合并**;合并由 RD 在 PR 上 `--squash` 执行(降级走本地 `merge --squash`),**PM 不亲自合并、不 push main**。验收核对:PR 标题/信息**用户可读** + main 上本需求**恰好 1 条提交且无 `wip()`** +
|
|
65
|
+
- **合并闸门(PM 控制合并时间点)**:工作期 RD 只在需求分支 `feat/<issue-id>-<slug>`(降级 `nao/<批次-slug>`)提交(`wip(<编号>):` 检查点、路径级暂存、禁 `-A`)。**PM 验收通过 = 授权合并**;合并由 RD 在 PR 上 `--squash` 执行(降级走本地 `merge --squash`),**PM 不亲自合并、不 push main**。验收核对:PR 标题/信息**用户可读** + main 上本需求**恰好 1 条提交且无 `wip()`** + 工作区干净。**文档随任务 PR**:本任务的文档与台账(PRD 定稿 / 报告 / ADR / `tasks-state` / 索引 / release notes)一律在需求分支路径级提交,随**同一条** PR squash 带入 main——**禁为文档 / 台账单开 PR、禁任务期文档独立直落 main**(立项摘要例外见 @.agents/skills/github-flow.md「文档与台账载体」)。特例白名单与流水线见 @.agents/skills/github-flow.md。
|
|
66
|
+
- **合并前 push 核对(指针,单源在清单)**:在分支上提交过的**任何角色**(含 PM 落的文档/台账)在贴验收评论 / 授权合并前,必须核「分支无未推送提交」——三条命令与判据单写在 @.agents/checklists/pm.md「交付检查清单」合并项,本卡不复制(BR5 单源)。
|
|
66
67
|
- **会话生命周期(PM 专属)**:按批次边界重开(归档完成 / 用户换需求 / `/session` contextTokens 超窗口 40%)+ 落盘接续 + 重开后**回读确认**;细则见 @.agents/skills/pm-operations.md §三。
|
|
67
68
|
- **状态外部化**:任务状态落 `docs/tasks-state.md`(含接续快照),每次派发/回执/验收后更新;重开先读它。
|
|
68
69
|
- **回收与残留**:派生会话验收通过即 `close --task <编号> <别名>`;常驻会话不回收,需重开时 `ensure --force`;`status` 残留即核对回收。
|
|
@@ -98,13 +99,14 @@ updated: 2026-10-28
|
|
|
98
99
|
- [ ] PM 亲自合并 PR / `push` main?(合并由 RD 执行,PM 只验收授权;§十三)
|
|
99
100
|
- [ ] 未过验收 / 门禁未绿就打 tag 或 release,或 tag 指向非 main 合并提交?(§十三)
|
|
100
101
|
- [ ] main 上出现多条本需求提交或 `wip()` 提交(未 squash)?提交 / PR 标题不可读(纯编号/类名/路径)?
|
|
102
|
+
- [ ] 为文档 / 台账单开 PR,或任务期文档作为独立提交直落 main?(应随任务 PR;例外仅 BR3 立项摘要,见 @.agents/skills/github-flow.md)
|
|
101
103
|
- [ ] Issue 与 `docs/` 双源(正文抄进 Issue / 状态只留平台)?(§十三)
|
|
102
104
|
- [ ] `git push --force` 到 main/共享分支(未经用户明确授权并指明分支)?
|
|
103
105
|
- [ ] release notes 不可读(纯编号/类名/路径),或未落盘 `docs/releases/`?
|
|
104
106
|
- [ ] 输出里有 `warn`/`error`/`pending approval`/`N vulnerabilities` 却判完成?(`exit 0` ≠ 完成,见 @.agents/skills/task-completion.md §三)
|
|
105
107
|
- [ ] 降级(无 `gh` / 无远端)未在 `tasks-state` 与回执中标注?
|
|
106
108
|
|
|
107
|
-
> 完整红线(
|
|
109
|
+
> 完整红线(34 项)与交付检查清单(43 项):**交付/派发前**读取 @.agents/checklists/pm.md 逐项核对。
|
|
108
110
|
|
|
109
111
|
## 十一、交付检查清单
|
|
110
112
|
|
|
@@ -120,7 +122,7 @@ PRD 完成且交付闭环后**当日**落 `docs/prds/YYYY-MM-DD-<主题>.md`(
|
|
|
120
122
|
PM 负责 **Issue 立项与同步、PR 验收与评论、Tag Release、仓库治理文件**;**合并由 RD 在 PR 上执行,PM 不亲自合并、不 push main**。
|
|
121
123
|
|
|
122
124
|
- **Issue(入口 + 摘要)**:**PRD 定稿后、开工确认卡前**建 Issue(TL;DR / AC 编号 / 优先级 / `docs/prds` 指针)——分支名需要 issue-id;**正文留 `docs/`**,Issue 不抄正文(避免双源)。同步时机仅 **5 个节点**:立项 / 派发 / 验收通过 / 合并 / 发布。
|
|
123
|
-
- **PR**:PM 在 PR 评论核 AC;**验收通过 = 授权合并**;不点合并按钮。Reviewer 与 PR owner
|
|
125
|
+
- **PR**:PM 在 PR 评论核 AC;**验收通过 = 授权合并**;不点合并按钮。Reviewer 与 PR owner 在开工确认卡指定。**文档随任务 PR**:台账(`docs/tasks-state.md`)/ PRD 定稿 / 报告 / ADR / release notes 均在本任务 PR 内路径级提交,**不为文档单开 PR、不把任务期文档独立提交到 main**(立项摘要例外仅限 BR3 三条件,降级批次无此例外)。
|
|
124
126
|
- **发布(优先 `gh`)**:`gh auth status` 按 **exit code** 判定(`keyring` 警告但 exit 0 仍可用)→ `gh release create <tag> --title "vX.Y.Z" --notes-file docs/releases/<version>.md`(**标题口径(强约束):@.agents/common/release-notes.md** —— 标题仅裸版本号,描述进正文首段);不可用降级 `git tag -a` + `git push origin <tag>`。**不自动 `gh auth login`**。
|
|
125
127
|
- **版本号**:SemVer(feat→MINOR / fix→PATCH / 破坏性→MAJOR);tag 必须指向 **main 的合并提交**。
|
|
126
128
|
- **仓库治理**:分支策略、`.github/` 模板(含 PR 模板)、README、`.gitignore` 属 PM;**不改源码/测试/构建配置**;冲突需改源码 → 转 worker。
|
|
@@ -1324,6 +1324,101 @@ cmd_check() {
|
|
|
1324
1324
|
return $rc
|
|
1325
1325
|
}
|
|
1326
1326
|
|
|
1327
|
+
# ---------------------------------------------------------------------------
|
|
1328
|
+
# T534(A · ADR 2026-10-31-fleet-status-repo-attribution):派生会话归属加「仓」维度
|
|
1329
|
+
# 北极星 = 本仓 status 的残留提示**永不**指向他仓会话(BR2「提示即可执行」);
|
|
1330
|
+
# close / ensure **零改动**(BR3),本批只收紧 status 的判定与提示。
|
|
1331
|
+
# 物理归一:pwd -P → readlink -f → 原串(目录已删/不可读时不猜,交给组件级前缀判否)
|
|
1332
|
+
nao_phys_path() {
|
|
1333
|
+
local p="$1" out=""
|
|
1334
|
+
[[ -n "$p" ]] || return 0
|
|
1335
|
+
out="$(cd "$p" 2>/dev/null && pwd -P)" || out=""
|
|
1336
|
+
[[ -n "$out" ]] || out="$(readlink -f -- "$p" 2>/dev/null || true)"
|
|
1337
|
+
[[ -n "$out" ]] || out="$p"
|
|
1338
|
+
printf '%s\n' "$out"
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
# 单行谓词(AC7⑤,同时是 AC2 的单行变异点):cwd 是否落在 root 子树内。
|
|
1342
|
+
# 组件级前缀:`/a/b` **不**命中 `/a/bc`(裸字符串前缀的经典陷阱 ⇒ AC7②)。
|
|
1343
|
+
repo_contains_path() { [[ -n "$1" && -n "$2" && ( "$2" == "$1" || "$2" == "${1%/}"/* ) ]]; }
|
|
1344
|
+
|
|
1345
|
+
# 本仓锚集(每 run 一次):主锚 pwd -P;git toplevel 是 cwd **严格祖先**时并入
|
|
1346
|
+
# (覆盖在 `.agents/` 等子目录跑 status ⇒ AC7③)。不用 roles.yaml workspace(常为 `.`/子目录,且 ensure 支持 @repo)。
|
|
1347
|
+
repo_anchor_roots() {
|
|
1348
|
+
local cwd top
|
|
1349
|
+
cwd="$(nao_phys_path "$PWD")"
|
|
1350
|
+
[[ -n "$cwd" ]] && printf '%s\n' "$cwd"
|
|
1351
|
+
command -v git >/dev/null 2>&1 || return 0
|
|
1352
|
+
top="$(git -C "$PWD" rev-parse --show-toplevel 2>/dev/null || true)"
|
|
1353
|
+
[[ -n "$top" ]] || return 0
|
|
1354
|
+
top="$(nao_phys_path "$top")"
|
|
1355
|
+
[[ -n "$top" && "$top" != "$cwd" ]] || return 0
|
|
1356
|
+
repo_contains_path "$top" "$cwd" || return 0
|
|
1357
|
+
printf '%s\n' "$top"
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
# pane cwd 一次快照(**禁**逐名 find_pane_for:O(N) 次 tmux 调用违 NFR「不引入额外 I/O 循环」)
|
|
1361
|
+
# 输出:name<TAB>pane_id<TAB>pane_current_path;标题契约 `π - <会话名> - <任意>`(会话名字符集同 visible_session_names)
|
|
1362
|
+
pane_cwd_snapshot() {
|
|
1363
|
+
command -v tmux >/dev/null 2>&1 || return 0
|
|
1364
|
+
tmux list-panes -a -F "#{pane_id}"$'\t'"#{pane_title}"$'\t'"#{pane_current_path}" 2>/dev/null \
|
|
1365
|
+
| awk -F'\t' -v p="$PI_TITLE" '
|
|
1366
|
+
{ pre = p " - "
|
|
1367
|
+
if (index($2, pre) != 1) next
|
|
1368
|
+
rest = substr($2, length(pre) + 1)
|
|
1369
|
+
i = index(rest, " - ")
|
|
1370
|
+
if (i <= 1) next
|
|
1371
|
+
name = substr(rest, 1, i - 1)
|
|
1372
|
+
if (name !~ /^[A-Za-z0-9_-]+$/) next
|
|
1373
|
+
print name "\t" $1 "\t" $3
|
|
1374
|
+
}' || true
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
# 归属三态:local(本仓)/ other(他仓)/ unknown(不可判定 ⇒ fail-closed,只标注不给命令)
|
|
1378
|
+
# $1=本仓锚集(换行分隔)· $2=pane cwd 集(换行分隔;空 = 无 pane)· $3=名册 cwd(可空)
|
|
1379
|
+
# 优先级 pane > 名册;同名多 pane:本仓 ≥1 ⇒ local · 本仓 0 且他仓 ≥1 ⇒ other · 两侧皆无 ⇒ unknown
|
|
1380
|
+
# 输出:`<verdict><TAB><他仓仓名 basename>`
|
|
1381
|
+
session_repo_verdict() {
|
|
1382
|
+
local roots="$1" cwds="$2" rcwd="$3"
|
|
1383
|
+
local c r hit local_n=0 other_n=0 obase="" verdict=""
|
|
1384
|
+
if [[ -n "$cwds" ]]; then
|
|
1385
|
+
while IFS= read -r c; do
|
|
1386
|
+
[[ -n "$c" ]] || continue
|
|
1387
|
+
c="$(nao_phys_path "$c")"
|
|
1388
|
+
hit=0
|
|
1389
|
+
while IFS= read -r r; do
|
|
1390
|
+
[[ -n "$r" ]] || continue
|
|
1391
|
+
if repo_contains_path "$r" "$c"; then hit=1; break; fi
|
|
1392
|
+
done <<< "$roots"
|
|
1393
|
+
if (( hit )); then
|
|
1394
|
+
local_n=$((local_n + 1))
|
|
1395
|
+
else
|
|
1396
|
+
other_n=$((other_n + 1))
|
|
1397
|
+
if [[ -z "$obase" ]]; then obase="${c%/}"; obase="${obase##*/}"; fi
|
|
1398
|
+
fi
|
|
1399
|
+
done <<< "$cwds"
|
|
1400
|
+
if (( local_n > 0 )); then verdict=local
|
|
1401
|
+
elif (( other_n > 0 )); then verdict=other
|
|
1402
|
+
fi
|
|
1403
|
+
fi
|
|
1404
|
+
if [[ -z "$verdict" && -n "$rcwd" ]]; then
|
|
1405
|
+
c="$(nao_phys_path "$rcwd")"
|
|
1406
|
+
hit=0
|
|
1407
|
+
while IFS= read -r r; do
|
|
1408
|
+
[[ -n "$r" ]] || continue
|
|
1409
|
+
if repo_contains_path "$r" "$c"; then hit=1; break; fi
|
|
1410
|
+
done <<< "$roots"
|
|
1411
|
+
if (( hit )); then
|
|
1412
|
+
verdict=local
|
|
1413
|
+
else
|
|
1414
|
+
verdict=other
|
|
1415
|
+
obase="${c%/}"; obase="${obase##*/}"
|
|
1416
|
+
fi
|
|
1417
|
+
fi
|
|
1418
|
+
[[ -n "$verdict" ]] || verdict=unknown
|
|
1419
|
+
printf '%s\t%s\n' "$verdict" "$obase"
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1327
1422
|
# ---------------------------------------------------------------------------
|
|
1328
1423
|
cmd_status() {
|
|
1329
1424
|
local a
|
|
@@ -1337,12 +1432,35 @@ cmd_status() {
|
|
|
1337
1432
|
fi
|
|
1338
1433
|
done
|
|
1339
1434
|
echo "== 任务派生会话(--task 拉起,如 rd-be-T1 / rd-infra-T1)=="
|
|
1340
|
-
|
|
1435
|
+
# T534:先建归属快照(本仓锚 / pane cwd / 名册 cwd),再逐会话**先定归属、后判本仓台账**
|
|
1436
|
+
# (他仓不查本仓 tasks-state,杜绝误读;本仓行 cls tag 逐字不变)
|
|
1437
|
+
local roots_blob="" rl
|
|
1438
|
+
while IFS= read -r rl; do [[ -n "$rl" ]] && roots_blob+="$rl"$'\n'; done < <(repo_anchor_roots)
|
|
1439
|
+
local -A pane_cwds=() roster_cwds=()
|
|
1440
|
+
local pn pname pcwd rn rcwd prev
|
|
1441
|
+
while IFS=$'\t' read -r pn pname pcwd; do
|
|
1442
|
+
[[ -n "$pname" ]] || continue
|
|
1443
|
+
prev="${pane_cwds[$pname]:-}"
|
|
1444
|
+
pane_cwds["$pname"]="$prev$pcwd"$'\n'
|
|
1445
|
+
done < <(pane_cwd_snapshot)
|
|
1446
|
+
while IFS=$'\t' read -r rn rcwd; do
|
|
1447
|
+
[[ -n "$rn" ]] || continue
|
|
1448
|
+
[[ -n "${roster_cwds[$rn]:-}" ]] || roster_cwds["$rn"]="$rcwd"
|
|
1449
|
+
done < <(intercom_roster 2>/dev/null || true)
|
|
1450
|
+
|
|
1451
|
+
local found=0 dname role id cls tag verdict obase
|
|
1341
1452
|
while IFS= read -r dname; do
|
|
1342
1453
|
[[ -n "$dname" ]] || continue
|
|
1343
1454
|
id=""
|
|
1344
1455
|
for role in "${ROLE_ORDER[@]}"; do [[ "$dname" == "$role-"* ]] && { id="${dname#"$role"-}"; break; }; done
|
|
1345
1456
|
[[ -n "$id" ]] || continue
|
|
1457
|
+
IFS=$'\t' read -r verdict obase <<< "$(session_repo_verdict "$roots_blob" "${pane_cwds[$dname]:-}" "${roster_cwds[$dname]:-}")"
|
|
1458
|
+
case "$verdict" in
|
|
1459
|
+
# D5:他仓会话**列出并标注**(不静默隐藏),整行不含任何可执行 close 命令(BR2)
|
|
1460
|
+
other) printf ' ~ %s(他仓 @ %s)他仓会话,勿在本仓回收\n' "$dname" "${obase:-?}"; found=1; continue ;;
|
|
1461
|
+
# fail-closed(T530 对偶):不可判定时不得声称「是本仓残留」,只标注不给命令
|
|
1462
|
+
unknown) printf ' ? %s(归属不可判定)→ 人工核对(勿在本仓回收)\n' "$dname"; found=1; continue ;;
|
|
1463
|
+
esac
|
|
1346
1464
|
cls="$(task_state_class "$id")"
|
|
1347
1465
|
tag=""
|
|
1348
1466
|
case "$cls" in
|
|
@@ -14,19 +14,33 @@ PM 在**立项 / 终签 / 发布**时读取;RD 在**起分支 / 开 PR / 合
|
|
|
14
14
|
- **短生命周期分支**:一个需求一条分支,存活 ≤ 一个批次;跨天过长就拆需求。
|
|
15
15
|
- **边界对齐**:一个批次 ≡ 一个需求 ≡ 一个父 Issue ≡ 一条分支 ≡ 一个 PR(前后端分离则每仓库一条)。
|
|
16
16
|
- **合并权在 RD,闸门在 PM**:PM **验收通过前不得合并**;合并由 RD 在 PR 上执行,**PM 不亲自合并**。
|
|
17
|
+
- **一个任务 PR = 全量改动**:实现 / 测试 / 文档(PRD 定稿 · 验收报告 · ADR · `tasks-state` 台账 · 报告 · 索引 · release notes)同属**一条** PR;**文档不单开 PR、不独立落 main**(唯一例外 = 立项摘要,细则见「文档与台账载体(一任务一 PR)」)。
|
|
17
18
|
|
|
18
19
|
## 八阶段
|
|
19
20
|
|
|
20
21
|
| # | 阶段 | 主责 | 动作 | 产出 |
|
|
21
22
|
| :--- | :--- | :--- | :--- | :--- |
|
|
22
|
-
| 1 | 立项 | PM | 建 Issue(用户故事 / AC / 优先级 / 里程碑)+ PRD 正文落 `docs/prds` | 可追踪 Issue |
|
|
23
|
-
| 2 | 拆分排期 | PM | 拆任务、定 PR owner / Reviewer / 分支名 | 开工确认卡 |
|
|
24
|
-
| 3 | 起分支 | RD | 从 main 拉 `feat/<issue-id>-<slug>`,开 **Draft PR** | Draft PR + CI |
|
|
25
|
-
| 4 | 开发提交 | RD | 小步 `wip(<编号>):` 提交,push 触发 CI | 增量代码 + CI 结果 |
|
|
26
|
-
| 5 | 评审测试 | RD / QA / Reviewer | 填 PR 模板、QA 跑全量门禁、预览环境验证 | Review 通过 |
|
|
27
|
-
| 6 | 验收合并 | PM → RD | PM 逐条核 AC 并在 PR 评论;**通过后由 RD squash 合并、删分支** | main 上 1
|
|
28
|
-
| 7 | 发布 | PM | 版本号 + tag + Release notes(优先 `gh`) | Release 记录 |
|
|
29
|
-
| 8 | 复盘 | PM | 监控指标、关 Issue、归档 PRD | 复盘 +
|
|
23
|
+
| 1 | 立项 | PM | 建 Issue(用户故事 / AC / 优先级 / 里程碑)+ PRD 正文落 `docs/prds` | 可追踪 Issue + **PRD 定稿(随本 PR)** |
|
|
24
|
+
| 2 | 拆分排期 | PM | 拆任务、定 PR owner / Reviewer / 分支名 | 开工确认卡 + **`docs/tasks-state.md` 登记(随本 PR)** |
|
|
25
|
+
| 3 | 起分支 | RD | 从 main 拉 `feat/<issue-id>-<slug>`,开 **Draft PR** | Draft PR + CI(+ 立项摘要,唯一例外) |
|
|
26
|
+
| 4 | 开发提交 | RD | 小步 `wip(<编号>):` 提交,push 触发 CI | 增量代码 + CI 结果 + 阶段文档(ADR / 报告,**随本 PR**) |
|
|
27
|
+
| 5 | 评审测试 | RD / QA / Reviewer | 填 PR 模板、QA 跑全量门禁、预览环境验证 | Review 通过 + QA 报告 / 用户验收清单(`docs/reports/`,**随本 PR**) |
|
|
28
|
+
| 6 | 验收合并 | PM → RD | PM 逐条核 AC 并在 PR 评论;**通过后由 RD squash 合并、删分支** | main 上 1 条提交(**含该任务全部文档改动**) |
|
|
29
|
+
| 7 | 发布 | PM | 版本号 + tag + Release notes(优先 `gh`) | Release 记录 + notes 落 `docs/releases/`,批间收尾事实随发布提交带走 |
|
|
30
|
+
| 8 | 复盘 | PM | 监控指标、关 Issue、归档 PRD | 复盘 + 归档(随发布提交或**下一任务 PR**) |
|
|
31
|
+
|
|
32
|
+
## 文档与台账载体(一任务一 PR)
|
|
33
|
+
|
|
34
|
+
**一个任务 PR = 该任务全量改动**(BR1):文档与台账不另立载体,`docs/` 改动一律随该任务的 PR 进 main。
|
|
35
|
+
|
|
36
|
+
- **BR1 全量(一 PR 含全部改动)**:任务 PR 必须包含该任务**全部文件改动** —— 实现 / 测试 / PRD 定稿 / 验收报告 / ADR / `docs/tasks-state.md` / `docs/reports/*-followups.md` / `docs/prds/README.md` 索引 / `docs/releases/<v>.md`。验收读 PR diff 即见文档变化;回滚 `git revert` 单条即整需求。
|
|
37
|
+
- **BR2 禁令**:① 禁止为文档 / 台账**单开 PR**;② 禁止任务期文档作为**独立提交直落 main**(唯一例外见 BR3)。发布提交(阶段 7)承载批间收尾事实,不计入本禁令。
|
|
38
|
+
- **BR3 立项例外(三条件同时满足才可用)**:① **仅用于**建 Issue / 定分支名所需的最小摘要;② 内容上限 = **最小摘要三要素**(TL;DR + AC 编号 + PRD 路径指针),正文仍留 `docs/`,**禁抄正文**;③ **单条** `docs(<编号>):` 提交、只含该摘要文件、**不与其它改动混提**。**降级批次(无 Issue)无此例外**。
|
|
39
|
+
- **BR4 谁提交**:PM 在需求分支做**路径级**提交(`git add <具体路径>`,`docs(<编号>):` 前缀,**禁 `-A`**、禁 push main);RD 最终 squash 时一并带入。同 worktree 并行时,提交方**只暂存自己的路径**。
|
|
40
|
+
- **BR5 批间收尾**:合并后产生的事实(npm 核验结果 / Release 标题核验 / 角色卡广播登记 / 会话交接快照)随**发布提交一次带走**;发布提交之后才产生的事实,登记进**下一个任务 PR** 或下一次发布提交,**不得单独提交 main**。
|
|
41
|
+
- **BR6 可读性不变**:PR 标题与 `gh pr merge --squash --subject` 仍须用户可读(禁纯编号 / 类名 / 路径);文档改动不降低该要求。
|
|
42
|
+
- **自查三条(可执行)**:main 上本任务提交数(`git log --oneline main | grep -c '(<编号>)'`)· 本 PR diff 是否含 `docs/` 路径(`git diff --name-only main...HEAD | grep '^docs/'`)· 工作区干净(`git status --porcelain` 为空)。
|
|
43
|
+
- **验证接缝**:文本口径由一次性只读探针核(如 `docs/reports/<日期>-*-probe.sh`),不进 `tests/`。
|
|
30
44
|
|
|
31
45
|
## 分支与提交
|
|
32
46
|
|
|
@@ -69,6 +83,7 @@ PM 在**立项 / 终签 / 发布**时读取;RD 在**起分支 / 开 PR / 合
|
|
|
69
83
|
| 分支 | `feat/<issue-id>-<slug>` | `nao/<批次-slug>` |
|
|
70
84
|
| 评审 | PR + CI + 预览环境 | 本地全量门禁 + PM 读 diff |
|
|
71
85
|
| 合并 | PR squash merge | PM 验收通过后,RD 本地 `git merge --squash feat/… && git commit` + 删分支 |
|
|
86
|
+
| 文档载体 | 随任务 PR(PR diff 含 `docs/`) | 同样在本地分支提交并由 `merge --squash` 带入 main,**不另开文档提交** |
|
|
72
87
|
| 发布 | `gh release create` | `git tag -a` + notes 落 `docs/releases/` |
|
|
73
88
|
|
|
74
89
|
降级须在 `tasks-state` 与回执中标注「降级」。
|
|
@@ -77,6 +92,7 @@ PM 在**立项 / 终签 / 发布**时读取;RD 在**起分支 / 开 PR / 合
|
|
|
77
92
|
|
|
78
93
|
- [ ] 未过 PM 验收就合并 PR,或直推 main?
|
|
79
94
|
- [ ] main 上出现多条本需求提交,或出现 `wip()` 提交(未 squash)?
|
|
95
|
+
- [ ] 为文档 / 台账**单开 PR**,或任务期文档作为**独立提交直落 main**(立项摘要例外见 BR3)?
|
|
80
96
|
- [ ] PM 亲自执行合并 / `push` main?
|
|
81
97
|
- [ ] Issue 与 `docs/` 双源(正文抄进 Issue,或状态只留平台)?
|
|
82
98
|
- [ ] 未过验收 / 门禁未绿就打 tag,或 tag 指向非 main 提交?
|
|
@@ -19,7 +19,7 @@ description: 按需技能——PM 运行手册(调度细则 / 开工确认卡
|
|
|
19
19
|
- **任务派生会话(并行隔离)**:`ensure <role>@<repo> --task <编号>` → `--name <角色>-<编号>`(如 `rd-be-T1`);**验收通过后回收**:`nao-fleet.sh close --task <编号> <别名>`(工具内置「在跑 turn / tasks-state 未推进」双闸门,后者防验收未过就回收丢返工上下文);回执 role 写派生名。
|
|
20
20
|
- **状态外部化 + 接续快照(可恢复)**:任务状态落盘 `docs/tasks-state.md`(五栏 + 顶部「PM 接续快照」;骨架见 @.agents/templates/tasks-state.md.example),每次派发/回执/验收/抢占后更新;重开后**先读该文件重建状态**,不依赖历史消息。
|
|
21
21
|
- **终态回执闸门**:每次派发(含架构评审)必须收到 `[编号] done` 回执(两级:默认 `done(lite)`;有阻塞/风险/需决策 `done(full)`,模板见 @.agents/checklists/comm-templates.md);未见回执(含 arch 静默)→ 主动追讨,必要时上报用户,**不默认成功**。
|
|
22
|
-
- **残留自检**:`nao-fleet.sh status` 标出派生会话残留(tasks-state 已归档 / 无记录);发现即核对状态并 `close --task <编号> <别名>`
|
|
22
|
+
- **残留自检**:`nao-fleet.sh status` 标出派生会话残留(tasks-state 已归档 / 无记录);发现即核对状态并 `close --task <编号> <别名>` 回收。判据按 pane 实际工作目录定归属 ⇒ **他仓会话单列、勿在本仓回收**(`~ <名>(他仓 @ <仓名>)` 行不含可执行命令;归属不可判定 ⇒ 人工核对)。
|
|
23
23
|
- **会话回收与收窗**:派生会话验收通过即 `close`;**常驻会话不回收**(保留复用,上下文变长时 `ensure --force` 重开);手工关窗前按 checklists/pm.md「会话回收 / 收窗核对」逐项核对(工具不替代回执与产物核对)。
|
|
24
24
|
- **角色提示词加载**:fleet 拉起的会话已启动期注入,派发只要求回执 `已按 <role> 角色执行`;仅对用户手工开、未注入的会话才指示加载 `@.agents/prompts/<role>.md`。
|
|
25
25
|
- **验收闭环(省 token)**:核对 AC 五覆盖 + 回执「清单」字段(未核对则打回);验收 = 核对回执**全量门禁精确数字** + 读变更文件核对 AC + **异常才复跑/抽查**(**不可改码**、**不重复跑 worker 已跑的门禁**);读码走三段阶梯(原生入口 `codegraph_explore`(需插件 + CLI + 索引齐备)→ CLI → `grep -rn` + 行段;行段读取如 `codegraph node --file <f> --offset <n> --limit <m>`),**禁 cat 全文**;依赖 QA 先行用例。
|