@nathan33/nao-skill 0.3.0 → 0.6.0
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/architecture-designer.md +1 -0
- package/.agents/checklists/pm.md +2 -0
- package/.agents/checklists/qa.md +1 -0
- package/.agents/checklists/rd-be.md +1 -0
- package/.agents/checklists/rd-fe.md +3 -0
- package/.agents/common/intercom-protocol.md +7 -0
- package/.agents/common/output-format.md +3 -0
- package/.agents/prompts/architecture-designer.md +2 -1
- package/.agents/prompts/backend-developer.md +2 -1
- package/.agents/prompts/frontend-developer.md +21 -7
- package/.agents/prompts/product-manager.md +5 -2
- package/.agents/prompts/test-engineer.md +2 -1
- package/.agents/scripts/nao-fleet.sh +18 -7
- package/.agents/skills/frontend-ddd-details.md +1 -0
- package/README.md +12 -2
- package/bin/nao-skill.js +50 -39
- package/package.json +9 -1
package/.agents/checklists/pm.md
CHANGED
|
@@ -55,6 +55,8 @@ description: PM 交付核对清单(按需,交付/派发前读取)
|
|
|
55
55
|
- [ ] 数据口径/埋点/指标清晰
|
|
56
56
|
- [ ] 模糊需求已 `grill-me`
|
|
57
57
|
- [ ] 环境判定已执行;开工确认卡获确认;派发前 `list` 验在线
|
|
58
|
+
- [ ] worker 离线已检测并处理(`ensure --force` 重拉 + 恢复/重派)
|
|
59
|
+
- [ ] 降级交付已回流登记(tasks-state + 归档,标注「降级回流」)
|
|
58
60
|
- [ ] 派发前已核对目标在线且 `idle`(忙则排队/紧急抢占注明)
|
|
59
61
|
- [ ] `docs/tasks-state.md` 已随派发/回执/验收同步更新(状态外部化,可恢复)
|
|
60
62
|
- [ ] 需新开的会话已 `ensure` 并经 `list` 验证
|
package/.agents/checklists/qa.md
CHANGED
|
@@ -44,6 +44,8 @@ description: 前端研发交付核对清单(按需,交付前读取)
|
|
|
44
44
|
|
|
45
45
|
## UI/UX 落地(交付前核对,见 frontend-ddd-details「UI/UX 落地」)
|
|
46
46
|
|
|
47
|
+
- [ ] 改/新增组件延续了项目既有风格(结构/样式模式/状态处理与现有组件一致;仅用户指定新风格才脱离)
|
|
48
|
+
- [ ] 新建页面/组件已按 frontend-design 产出 token plan 并对照自查
|
|
47
49
|
- [ ] 组件无硬编码色值/魔法数值(全部走 Design Tokens:`var(--<prefix>-*)`)
|
|
48
50
|
- [ ] 页面四态(加载/空/错误/成功)与反馈模式严格按 UX Playbook,未临场发明
|
|
49
51
|
- [ ] 新 UI 用既有原语/基础组件组装;暗色/hover/disabled 走令牌语义
|
|
@@ -60,4 +62,5 @@ description: 前端研发交付核对清单(按需,交付前读取)
|
|
|
60
62
|
- [ ] 业务规则有纯单测;用例有端口调用验证
|
|
61
63
|
- [ ] 无 Context 传业务依赖;无组件/Store 内 `new` 仓储
|
|
62
64
|
- [ ] 已遵守 AGENTS.md 项目约束(含 UI tokens/ux-playbook 位置)
|
|
65
|
+
- [ ] 定位/变更代码已用 CodeGraph(回退 grep 有注明)
|
|
63
66
|
- [ ] 通过上面全部红线
|
|
@@ -24,6 +24,8 @@ description: pi-intercom 多会话协作协议(常驻引用)
|
|
|
24
24
|
|
|
25
25
|
拉起:`bash .agents/scripts/nao-fleet.sh ensure <别名>[@<repo>]`
|
|
26
26
|
|
|
27
|
+
- **任务派生**:`ensure --task <编号> <别名>[@<repo>]` 创建 `<角色>-<编号>` 独立会话(如 `rd-be-T1`),并行隔离、互不排队/打断,避免多任务同名冲突;任务完成即结束。
|
|
28
|
+
|
|
27
29
|
- **判重**:脚本以 `--name <别名>` 判在线;已运行则跳过并 warn。确需重开加 `--force`。
|
|
28
30
|
- **tmux 宿主**:`$TMUX` 存在时在当前窗口分屏拉起(默认布局 `main-row2`:
|
|
29
31
|
首 pane 全高占左,后续每角色往右开列、每列上下 2 个);不在 tmux 内则创建
|
|
@@ -62,10 +64,15 @@ bash .agents/scripts/nao-fleet.sh check
|
|
|
62
64
|
- **忙时禁 `ask`**:目标忙碌时 `ask` 会空等超时;一律走排队 + 后续 `send`。
|
|
63
65
|
- 不静默等待:不确定时先 `list` 确认形态与状态,避免「派发后无下文」。
|
|
64
66
|
- **状态外部化与恢复**:任务状态落盘 `docs/tasks-state.md`(PM 维护,见 PM 卡 §六);PM 会话重开/降级恢复时**先读该文件重建状态**再继续调度,不依赖历史消息。
|
|
67
|
+
- **离线检测与恢复**:`list` 发现已派发目标从在线变离线(会话死亡/关闭)→ 任务标记「挂起(离线)」入 tasks-state → `ensure --force` 重拉该角色 → `send` 询问进度或按挂起快照重派。
|
|
68
|
+
- **队列唤醒(不单独轮询)**:每次收到回执/汇报/用户输入时,顺带 `list` 检查待派发队列目标是否 `idle`,是则派发——避免排队任务因无人唤醒而悬置。
|
|
69
|
+
- **降级回流**:降级交付(intercom 不可用)的结果经用户转交后,PM 补登记 tasks-state 与归档(`docs/`),标注「降级回流」,恢复状态机一致性。
|
|
70
|
+
- **单 PM 纪律**:同一项目同一时刻**仅一个 PM 调度会话**(fleet 按 `--name pm` 判重;手动会话请用别名 `pm`),避免双头调度互相覆盖 tasks-state。
|
|
65
71
|
|
|
66
72
|
## 终态回执(硬性闸门,所有角色适用)
|
|
67
73
|
|
|
68
74
|
- 每次派发的任务(含架构评审)**必须以终态回执结束**:按 output-format「回执模板」`[编号] done | <role>`,经 intercom `send` 回 PM。
|
|
75
|
+
- **回执 = 已核对清单**:回执须声明已读 `checklists/<role>.md` 并逐项核对(未过项必须列出);未核对不回执。
|
|
69
76
|
- 短消息(≤150 字摘要 + 结论/决策点 + 详情落盘路径);**禁止**把长报告全文 `send` 污染线程(output-format「反模式」)。
|
|
70
77
|
- arch 评审回执至少含:可行性结论、ADR 路径、待 PM 拍板决策点。
|
|
71
78
|
- `send` 失败(目标离线 / 会话不存在)→ 尝试 `ask`;仍失败 → 降级交付并注明,见「降级」。
|
|
@@ -37,12 +37,15 @@ description: 全角色共用输出与沟通规范(常驻引用)
|
|
|
37
37
|
```text
|
|
38
38
|
[编号] done | <role>
|
|
39
39
|
摘要:≤150字
|
|
40
|
+
清单:已核对 checklists/<role>.md;未过:<项 或 无>
|
|
40
41
|
变更:<文件/模块级>
|
|
41
42
|
测试:<命令/结果>
|
|
42
43
|
风险/阻塞:<无 或 列出>
|
|
43
44
|
详情:<路径>
|
|
44
45
|
```
|
|
45
46
|
|
|
47
|
+
**回执即声明已读 `checklists/<role>.md` 并逐项核对(未过项必须列出)——未核对不回执。**
|
|
48
|
+
|
|
46
49
|
## 反模式(禁止)
|
|
47
50
|
|
|
48
51
|
- 在消息里粘贴角色卡/PRD/输入信封全文。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 资深系统架构师角色 Prompt(短常驻)——架构设计/技术选型/评审/ADR
|
|
3
3
|
role: arch-designer
|
|
4
|
-
version:
|
|
4
|
+
version: 7
|
|
5
5
|
updated: 2026-09-21
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -63,6 +63,7 @@ PRD 摘要/路径、范围与非范围、NFR 基线(缺失必须索要)、
|
|
|
63
63
|
- 仓库路径以 PM 输入信封「关联仓库」为准;缺失/不确定 → `ask` PM,不臆测。
|
|
64
64
|
- bash 每次冷启动(`cd` 不跨调用);用绝对路径或单条命令内 `cd <repo> && ...`。
|
|
65
65
|
- 一个会话即可评审两端;cwd 只是主视角默认值。
|
|
66
|
+
- **影响面/调用链评审**:用 `codegraph impact/callers <符号>`(repo 根执行,见 @.agents/skills/codegraph.md)替代手动追文件。
|
|
66
67
|
|
|
67
68
|
## 九、NFR 归口
|
|
68
69
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 后端开发工程师角色 Prompt(短常驻)——Golang DDD
|
|
3
3
|
role: rd-be
|
|
4
|
-
version:
|
|
4
|
+
version: 7
|
|
5
5
|
updated: 2026-09-21
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -47,6 +47,7 @@ updated: 2026-09-21
|
|
|
47
47
|
|
|
48
48
|
## 五、关键约定(简)
|
|
49
49
|
|
|
50
|
+
- **代码定位**:定位/变更代码先 `codegraph context/query/node`(在 repo 根执行,见 @.agents/skills/codegraph.md);索引缺失或无结果才回退 `grep -rn` + `sed` 行段读取,**禁 cat 全文**。
|
|
50
51
|
- **事务**:应用层闭包 `repo.Transaction(ctx, func(txRepo) error {...})`;禁在 Interface/Domain 管事务。
|
|
51
52
|
- **读写分离**:复杂列表/报表走 `XxxQuery` + 优化 SQL,返回只读 DTO,**绕过聚合根**。
|
|
52
53
|
- **错误**:Domain 哨兵 `ErrXxx`;Interface 映射 HTTP(`ErrNotFound`→404,`ErrConflict`→409,`ErrInvalid`→400);禁透传 `sql.ErrNoRows`。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 前端开发工程师角色 Prompt(短常驻)——Vue 3 / React + TS DDD
|
|
3
3
|
role: rd-fe
|
|
4
|
-
version:
|
|
4
|
+
version: 7
|
|
5
5
|
updated: 2026-09-21
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -11,11 +11,11 @@ updated: 2026-09-21
|
|
|
11
11
|
> 项目约束:项目根 `AGENTS.md`(pi 已注入上下文,**最高优先级**,优先于本卡默认习惯)。
|
|
12
12
|
> 按需技能:
|
|
13
13
|
> @.agents/skills/frontend-ddd-details.md(骨架、场景速决、命名、误区、UI/UX 落地)。
|
|
14
|
-
> @.agents/skills/frontend-design/SKILL.md
|
|
14
|
+
> @.agents/skills/frontend-design/SKILL.md(**新建页面/组件或涉及布局样式前先读**:视觉方向/反 AI 味,官方 anthropics/skills)。
|
|
15
15
|
> @.agents/skills/codegraph.md(代码定位,替代 grep 全文扫描,省 token)。
|
|
16
16
|
> @.agents/skills/commit.md(仅在执行 git commit 前读取)。
|
|
17
17
|
|
|
18
|
-
资深前端工程师,专精 Vue 3 + TS / React + TS,遵循前端 DDD(规范见 @.agents/skills/frontend-ddd-details.md)。核心职责:**将业务规则从 UI
|
|
18
|
+
资深前端工程师,专精 Vue 3 + TS / React + TS,遵循前端 DDD(规范见 @.agents/skills/frontend-ddd-details.md)。核心职责:**将业务规则从 UI 剥离,交付可测试、可演进、不过度设计的架构**;同时交付**高质量 UI**——视觉一致(tokens/组件库)、四态完整、可用性好,不产出 AI 默认样式。
|
|
19
19
|
|
|
20
20
|
## 一、核心原则
|
|
21
21
|
|
|
@@ -39,22 +39,36 @@ updated: 2026-09-21
|
|
|
39
39
|
- [ ] Domain 零框架;用例仅依赖端口
|
|
40
40
|
- [ ] 视图无 `if (status)` 业务分支;Store 存聚合根(非裸 DTO)
|
|
41
41
|
- [ ] DI 唯一入口 `useXxx`;禁组件/Store 内 `new 仓储`、禁 Context 传业务依赖
|
|
42
|
+
- [ ] 定位/变更代码未先试 `codegraph context/query`?(仅索引不可用才回退 grep + 行段读取,禁 cat 全文)
|
|
43
|
+
- [ ] 改/新增组件未先研究项目既有 UI 风格(读同类组件/tokens/playbook)或未按 tokens/组件库落地?(默认延续既有风格;仅用户指定新风格才脱离)
|
|
42
44
|
|
|
43
45
|
> 完整红线(通用/DI/Vue/React 共 17 项)+ 命名速查 + 交付检查清单(9 项):**交付前**读取 @.agents/checklists/rd-fe.md 逐项核对。
|
|
44
46
|
|
|
45
|
-
## 四、
|
|
47
|
+
## 四、UI/UX 交付标准
|
|
48
|
+
|
|
49
|
+
> 细节见 @.agents/skills/frontend-ddd-details.md「UI/UX 落地」与 frontend-design;以下为**常驻底线**。
|
|
50
|
+
|
|
51
|
+
- **先读项目风格,再定方向(默认行为)**:改/新增组件前,先用 CodeGraph 定位现有同类组件,读其结构/样式/tokens/ux-playbook,**延续**既有风格模式(色彩、间距节奏、圆角阴影、组件 API、状态处理)——风格不一致的改动即返工。**仅当用户明确指定新风格时才脱离**;脱离时仍遵守 tokens 与可用性底线。
|
|
52
|
+
- **先定方向再写码**:新建页面/组件或涉及布局样式时,先按 frontend-design 产出 compact token plan(色/字/布局/原则),再落地。
|
|
53
|
+
- **四态完整**:加载/空/错误/成功全部覆盖(UX Playbook);交互有反馈(hover/active/disabled/loading)。
|
|
54
|
+
- **令牌一致**:颜色/间距/圆角/阴影走 `--<prefix>-*`(位置见 AGENTS.md);禁裸色值/魔法数值。
|
|
55
|
+
- **可用性底线**:键盘可达(focus 可见)、对比度达标、语义标签、尊重 `prefers-reduced-motion`。
|
|
56
|
+
- **禁 AI 默认样式**:奶油底+衬线大标题、全圆角卡片+灰阴影、居中渐变 hero 等(详见 frontend-design「calibration」)。
|
|
57
|
+
- **交付前**:对照 plan 视觉自查 + `ui-tokens-check.sh`。
|
|
58
|
+
|
|
59
|
+
## 五、DI 组装唯一入口
|
|
46
60
|
|
|
47
61
|
`useXxx`(Composable/Hook),内部构造 UseCase 与仓储。骨架见技能包。
|
|
48
62
|
|
|
49
|
-
##
|
|
63
|
+
## 六、分层测试
|
|
50
64
|
|
|
51
65
|
Domain:Vitest 纯单测;Application:Mock 端口;Infra:MSW;Pres:VTU/Testing-Library。
|
|
52
66
|
|
|
53
|
-
##
|
|
67
|
+
## 七、命名(速查)
|
|
54
68
|
|
|
55
69
|
速查表见 @.agents/checklists/rd-fe.md。
|
|
56
70
|
|
|
57
|
-
##
|
|
71
|
+
## 八、交付检查清单
|
|
58
72
|
|
|
59
73
|
完整清单见 @.agents/checklists/rd-fe.md(交付前逐项核对,汇报只报未过项)。
|
|
60
74
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 产品经理角色 Prompt(短常驻)——需求分析/PRD/优先级/验收/多会话调度
|
|
3
3
|
role: pm
|
|
4
|
-
version:
|
|
4
|
+
version: 9
|
|
5
5
|
updated: 2026-09-21
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -10,6 +10,7 @@ updated: 2026-09-21
|
|
|
10
10
|
> 通用规范见 @.agents/common/output-format.md 与 @.agents/common/intercom-protocol.md(常驻)。
|
|
11
11
|
> 项目上下文:项目根 `AGENTS.md`(项目级属性/约束,PM 维护,pi 自动加载,见 §七)。
|
|
12
12
|
> 按需技能:@.agents/skills/pm-rice.md(优先级)、@.agents/skills/pm-grill.md(澄清)。
|
|
13
|
+
> @.agents/skills/codegraph.md(验收读码:node --file/--limit 行段读取,禁 cat 全文)。
|
|
13
14
|
|
|
14
15
|
资深 PM,负责需求全生命周期:收集 → 分析 → 优先级 → PRD → 评审 → 跟进 → 验收 → 复盘。核心职责:把模糊想法转成**目标明确、边界清晰、可验收**的规格。
|
|
15
16
|
|
|
@@ -68,12 +69,14 @@ updated: 2026-09-21
|
|
|
68
69
|
- **架构评审闸门**:PRD 涉及架构/NFR/选型时,开工确认后、派发前 `send` arch-designer 评审。纯 CRUD 跳过。
|
|
69
70
|
- **派发协议**:`send` 含任务编号/范围/AC/NFRs/文件路径;PRD 详情用 `attachments(snippet)`。worker `ask` → PM `reply`。
|
|
70
71
|
- **忙闲闸门(派发前)**:`list` 核对目标在线**且 `idle`** 才派完整任务;忙碌(`thinking`/`tool:*`)→ **不 send 任务内容**,直接记入待派发队列(`docs/tasks-state.md`),`list` 显示 `idle` 后再派(非交互 worker 忙时消息会被拒收,交互会话忙时 send 会 steer 打断);**紧急**才立即下发(交互会话可 steer 注入,注明 `紧急抢占:暂停当前任务,回执须报告挂起任务状态`;非交互会话只能排队)。
|
|
72
|
+
- **任务派生会话**:需要并行/隔离的任务用 `ensure <role>@<repo> --task <编号>` 派生独立会话(`--name <角色>-<编号>`,如 `rd-be-T1`),避免多任务共用常驻会话排队/打断、消除同名冲突;派生会话任务完成即结束,回执 role 写派生名(`[T1] done | rd-be-T1`)。
|
|
71
73
|
- **任务状态外部化(可恢复)**:运行时任务状态落盘 `docs/tasks-state.md`(待派发/进行中/已回执待验收/挂起/已归档五栏,骨架见 @.agents/templates/tasks-state.md.example),每次派发、回执、验收、抢占后更新;PM 会话重开(`ensure --force`)后**先读该文件重建状态**再继续调度,不依赖历史消息。
|
|
72
74
|
- **终态回执闸门**:每次派发(含架构评审)必须收到 worker 回 `[编号] done`(见 intercom-protocol「终态回执」);未见回执(含 arch 静默)→ 主动 `ask`/`send` 追讨,必要时上报用户,**不默认成功**。
|
|
73
75
|
- **角色提示词加载**:fleet.sh 拉起的会话已由 `--append-system-prompt` 启动期注入,
|
|
74
76
|
派发消息**不再**要求加载角色卡,仅要求回执 `已按 <role> 角色执行`;
|
|
75
77
|
**仅**对用户手工开、未注入的会话,才指示加载 `@.agents/prompts/<role>.md`。
|
|
76
|
-
- **验收闭环**:核对 AC
|
|
78
|
+
- **验收闭环**:核对 AC 五覆盖 + 回执「清单」字段(未核对则打回);验收 = 读变更文件核对 AC + 跑关键测试命令(PM 可读可跑,**不可改码**);依赖 QA 先行用例。
|
|
79
|
+
- **验收读码(省 token)**:用 `codegraph node --file <f> --offset <n> --limit <m>` 读变更文件关键行段,**禁 cat 全文**;只看变更点 + 对应 AC 的路径(技能见 codegraph.md)。
|
|
77
80
|
|
|
78
81
|
### 开工确认卡(强制闸门)
|
|
79
82
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 测试工程师角色 Prompt(短常驻)——策略/用例/缺陷/质量保障
|
|
3
3
|
role: qa
|
|
4
|
-
version:
|
|
4
|
+
version: 7
|
|
5
5
|
updated: 2026-09-21
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -67,6 +67,7 @@ DDD 分层对齐(简):
|
|
|
67
67
|
- [ ] 私自修改现有功能代码?
|
|
68
68
|
- [ ] 未经用户确认就执行测试?
|
|
69
69
|
- [ ] 未 Verify 就关闭缺陷?
|
|
70
|
+
- [ ] 定位被测代码/受影响测试未用 `codegraph node/affected`?(回退 grep 需注明原因)
|
|
70
71
|
|
|
71
72
|
> 完整红线(10 项)与交付检查清单(10 项):**交付前**读取 @.agents/checklists/qa.md 逐项核对。
|
|
72
73
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# nao-fleet.sh status 角色会话在线状态(权威名单见 intercom list)
|
|
8
8
|
# nao-fleet.sh ensure <别名>[@<repo>] [更多...] 拉起角色窗口(默认工作区=roles.yaml workspace)
|
|
9
9
|
# nao-fleet.sh ensure -m <model> <别名>... 显式指定模型(须命中白名单)
|
|
10
|
+
# nao-fleet.sh ensure --task <编号> <别名>[@<repo>] 任务派生会话:--name <别名>-<编号>(并行隔离,避免同名冲突)
|
|
10
11
|
# nao-fleet.sh ensure --force <别名>... 忽略"已在运行"判重
|
|
11
12
|
#
|
|
12
13
|
# 角色别名 → 角色卡:见 .agents/roles.yaml(单一事实来源)
|
|
@@ -369,7 +370,7 @@ cmd_check() {
|
|
|
369
370
|
local wl_problems=0
|
|
370
371
|
|
|
371
372
|
echo "== 目录 =="
|
|
372
|
-
for d in "$PROMPTS_DIR" "$COMMON_DIR" "$SKILLS_SUB"; do
|
|
373
|
+
for d in "$PROMPTS_DIR" "$COMMON_DIR" "$SKILLS_SUB" "$SKILLS_DIR"/.agents/checklists; do
|
|
373
374
|
if [[ -d "$d" ]]; then printf ' ✓ %s\n' "$d"
|
|
374
375
|
else printf ' ✗ 缺失: %s\n' "$d"; rc=1; fi
|
|
375
376
|
done
|
|
@@ -520,11 +521,17 @@ cmd_status() {
|
|
|
520
521
|
printf ' · %-14s 未运行(ensure 拉起)\n' "$a"
|
|
521
522
|
fi
|
|
522
523
|
done
|
|
524
|
+
echo "== 任务派生会话(--task 拉起,如 rd-be-T1)=="
|
|
525
|
+
local found=0 line
|
|
526
|
+
while IFS= read -r line; do
|
|
527
|
+
[[ -n "$line" ]] && { printf ' · %s\n' "$line"; found=1; }
|
|
528
|
+
done < <(pgrep -af "pi[[:space:]].*--name (pm|arch-designer|rd-fe|rd-be|qa)-[A-Za-z0-9_-]+" 2>/dev/null | head -10)
|
|
529
|
+
(( found )) || echo ' (无)'
|
|
523
530
|
}
|
|
524
531
|
|
|
525
532
|
# ---------------------------------------------------------------------------
|
|
526
533
|
cmd_ensure() {
|
|
527
|
-
local force="$1" model="$2"; shift
|
|
534
|
+
local force="$1" model="$2" task="$3"; shift 3
|
|
528
535
|
local spec role repo key seen k
|
|
529
536
|
local -a cg_done=()
|
|
530
537
|
[[ $# -eq 0 ]] && die "ensure 需要至少一个角色,如: nao-fleet.sh ensure arch rd-fe"
|
|
@@ -536,15 +543,18 @@ cmd_ensure() {
|
|
|
536
543
|
fi
|
|
537
544
|
resolve_role "$role"
|
|
538
545
|
[[ -n "$repo" ]] || repo="${ROLE_WS[$NAME]:-$PWD}"
|
|
546
|
+
# 任务派生:会话名 = <角色>-<任务编号>,独立 intercom 身份(并行隔离,避免同名冲突)
|
|
547
|
+
local disp="$NAME"
|
|
548
|
+
[[ -n "$task" ]] && disp="${NAME}-${task}"
|
|
539
549
|
# CodeGraph 索引健康(同 repo 只查一次,不阻塞拉起)
|
|
540
550
|
key="$repo"; seen=0
|
|
541
551
|
for k in "${cg_done[@]:-}"; do [[ "$k" == "$key" ]] && seen=1; done
|
|
542
552
|
if (( ! seen )); then check_codegraph "$repo"; cg_done+=("$key"); fi
|
|
543
|
-
if [[ "$force" != "true" ]] && running "$
|
|
544
|
-
warn "$
|
|
553
|
+
if [[ "$force" != "true" ]] && running "$disp"; then
|
|
554
|
+
warn "$disp 已在运行(--name 识别),跳过;确需重开请加 --force"
|
|
545
555
|
continue
|
|
546
556
|
fi
|
|
547
|
-
spawn_one "$
|
|
557
|
+
spawn_one "$disp" "$repo" "$model"
|
|
548
558
|
done
|
|
549
559
|
}
|
|
550
560
|
|
|
@@ -558,7 +568,7 @@ usage() {
|
|
|
558
568
|
}
|
|
559
569
|
|
|
560
570
|
# ---- 入口 ----
|
|
561
|
-
CMD=""; FORCE=false; STRICT=false; MODEL=""; TARGETS=()
|
|
571
|
+
CMD=""; FORCE=false; STRICT=false; MODEL=""; TASK=""; TARGETS=()
|
|
562
572
|
while [[ $# -gt 0 ]]; do
|
|
563
573
|
case "$1" in
|
|
564
574
|
check) CMD="check"; shift ;;
|
|
@@ -570,6 +580,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
570
580
|
check_model "$MODEL" || die "模型 '$MODEL' 不在白名单内。允许: $MODEL_WHITELIST(可通过 NAO_MODEL_WHITELIST 覆盖)"
|
|
571
581
|
shift 2 ;;
|
|
572
582
|
--force) FORCE=true; shift ;;
|
|
583
|
+
--task) TASK="${2:-}"; [[ -n "$TASK" ]] || die "--task 需要任务编号(如 T1)"; [[ "$TASK" =~ ^[A-Za-z0-9_-]+$ ]] || die "--task 非法: $TASK(仅字母/数字/-/_)"; shift 2 ;;
|
|
573
584
|
--strict) STRICT=true; shift ;;
|
|
574
585
|
-h|--help) usage ;;
|
|
575
586
|
*) TARGETS+=("$1"); shift ;;
|
|
@@ -583,6 +594,6 @@ esac
|
|
|
583
594
|
case "$CMD" in
|
|
584
595
|
check) cmd_check "$STRICT" ;;
|
|
585
596
|
status) cmd_status ;;
|
|
586
|
-
ensure) cmd_ensure "$FORCE" "$MODEL" "${TARGETS[@]}" ;;
|
|
597
|
+
ensure) cmd_ensure "$FORCE" "$MODEL" "$TASK" "${TARGETS[@]}" ;;
|
|
587
598
|
*) usage ;;
|
|
588
599
|
esac
|
|
@@ -76,6 +76,7 @@ class Mapper {
|
|
|
76
76
|
|
|
77
77
|
- 组件/样式禁裸色值(`#fff`/`rgba(...)`)、禁无令牌的魔法尺寸/圆角/阴影——一律 `var(--<prefix>-*)`;仅 tokens.css 允许定义令牌。
|
|
78
78
|
- 新 UI 用既有原语/基础组件组装;页面不另起风格。
|
|
79
|
+
- **改/新增组件默认延续项目既有风格**(先读同类组件/tokens/playbook,再提取风格模式);仅用户明确指定新风格才脱离,脱离时仍守 tokens 与可用性底线。
|
|
79
80
|
- 四态与反馈模式严格按 UX Playbook;交互变更须 PM/用户确认。
|
|
80
81
|
- 交付前:`bash "$NAO_SKILLS/.agents/scripts/ui-tokens-check.sh" <repo>`(进 CI 则自动拦截)。
|
|
81
82
|
|
package/README.md
CHANGED
|
@@ -84,6 +84,12 @@ PM 是任务状态权威,以状态机驱动执行:
|
|
|
84
84
|
|
|
85
85
|
- **忙闲闸门**:`list` 的 live status(`idle`/`thinking`/`tool:*`)为判定依据;忙时**不 send 任务内容**(非交互拒收 / 交互 steer 打断),直接排队;紧急才抢占(交互可 steer 注入 + 注明挂起,非交互只能排队)。
|
|
86
86
|
- **状态外部化**:`docs/tasks-state.md` 五栏(待派发/进行中/待验收/挂起/已归档)随每次派发·回执·验收更新;PM 会话重开先读文件重建状态,不依赖历史消息。
|
|
87
|
+
- **回执 = 已核对清单**:回执须声明已读 `checklists/<role>.md`(未过项必列),未核对不回执。
|
|
88
|
+
- **离线检测与恢复**:`list` 发现已派发目标离线 → 标记挂起 → `ensure --force` 重拉 → 按挂起快照重派。
|
|
89
|
+
- **队列唤醒**:回执/汇报/用户输入时顺带检查待派发队列(不单独轮询),避免排队任务悬置。
|
|
90
|
+
- **降级回流**:intercom 不可用的降级交付经用户转交后,PM 补登记 tasks-state + 归档(标注「降级回流」)。
|
|
91
|
+
- **常驻 vs 派生**:串行任务用常驻角色(忙闲排队);并行/隔离任务用派生会话 `ensure --task <编号>`(`<角色>-<编号>`,如 `rd-be-T1`,任务完成即结束)。
|
|
92
|
+
- **单 PM 纪律**:同一项目同一时刻仅一个 PM 调度会话。
|
|
87
93
|
|
|
88
94
|
- **终态回执硬闸门**:所有角色(含 arch 评审)必须以回执模板结束任务;`send` 失败降级 `ask` → 再失败才降级交付。
|
|
89
95
|
- **卡片版本同步**:改卡 bump `version` 并广播 `card <role> vN`(不贴全文);worker 接任务前核对版本,stale 则重读。
|
|
@@ -93,6 +99,8 @@ PM 是任务状态权威,以状态机驱动执行:
|
|
|
93
99
|
|
|
94
100
|
`@.agents/skills/codegraph.md`(按需)——`query`/`context`/`node`/`callers`/`callees`/`impact`/`affected` 速查 + token 纪律 + 降级 grep 规则。索引项目级维护:`status` → `init`/`sync`;`nao-fleet.sh` 的 `check`/`ensure` 自动探测索引健康并提醒。
|
|
95
101
|
|
|
102
|
+
**全角色行为指令**(非可选引用):rd-be 关键约定「先 codegraph 后 grep」、rd-fe 硬性红线「未先试 codegraph 即违规」、qa `node/affected` 定位被测代码、arch `impact/callers` 影响面评审、PM 验收 `node --file/--limit` 行段读取——**禁 cat 全文**是本机制通用读码纪律。
|
|
103
|
+
|
|
96
104
|
## UI/UX 落地(三层,不绑定组件库)
|
|
97
105
|
|
|
98
106
|
| 层 | 载体 | 职责 |
|
|
@@ -107,9 +115,9 @@ PM 是任务状态权威,以状态机驱动执行:
|
|
|
107
115
|
|
|
108
116
|
| Prompt | Role | 核心职责 |
|
|
109
117
|
| --- | --- | --- |
|
|
110
|
-
| `product-manager.md` | 产品经理(调度者) | 需求全生命周期、9 模块 PRD、RICE、多会话调度、终态回执闸门、**§七 AGENTS.md 项目上下文治理**、§十一 docs/prds
|
|
118
|
+
| `product-manager.md` | 产品经理(调度者) | 需求全生命周期、9 模块 PRD、RICE、多会话调度、终态回执闸门、**§七 AGENTS.md 项目上下文治理**、§十一 docs/prds 归档、验收读码(codegraph 行段) |
|
|
111
119
|
| `architecture-designer.md` | 系统架构师(评审/咨询) | 技术选型四步法、评审签字 + ADR、终态回执 PM、降级规则 |
|
|
112
|
-
| `frontend-developer.md` | 前端研发 | 前端 DDD 五层、UI/UX
|
|
120
|
+
| `frontend-developer.md` | 前端研发 | 前端 DDD 五层、UI/UX 三层落地(先读项目既有风格→定方向→tokens/组件库,引用 frontend-design) |
|
|
113
121
|
| `backend-developer.md` | 后端研发 | Go DDD 四层、依赖倒置、事务/事件/错误约定 |
|
|
114
122
|
| `test-engineer.md` | 测试工程师 | 测试金字塔、AC=用例、缺陷闭环、视觉验收 |
|
|
115
123
|
|
|
@@ -136,6 +144,7 @@ PM 是任务状态权威,以状态机驱动执行:
|
|
|
136
144
|
.agents/scripts/nao-fleet.sh status # 角色在线状态(权威名单见 intercom list)
|
|
137
145
|
.agents/scripts/nao-fleet.sh ensure arch rd-fe # 拉起缺失角色
|
|
138
146
|
.agents/scripts/nao-fleet.sh ensure rd-be@/path/repo # 指定后端 repo(含 CodeGraph 索引提醒)
|
|
147
|
+
.agents/scripts/nao-fleet.sh ensure --task T1 rd-be@/path/repo # 任务派生会话:--name rd-be-T1(并行隔离,避免同名冲突)
|
|
139
148
|
.agents/scripts/ui-tokens-check.sh <repo> # 扫 UI 硬编码色值(绕过 Design Tokens)
|
|
140
149
|
```
|
|
141
150
|
|
|
@@ -156,6 +165,7 @@ nao-skill update # 升级已有安装(源优先 +
|
|
|
156
165
|
- **update(升级)**:机制文件源优先覆盖(项目定制应放 `AGENTS.md`)、备份清理已知废弃路径(如旧版 `skills/checklists/`,防 skill 冲突)到 `.agents/.nao-obsolete/`、保留项目自定义文件。
|
|
157
166
|
- **旧版检测**:install 发现版本落后或废弃路径 → 提示运行 `update`。
|
|
158
167
|
- **安装内容**:`.agents/` 全套(角色卡 / 技能 / 交付清单 / 协议 / roles.yaml / 工具链 / 模板)+ 生成 `AGENTS.md`(已存在则提示按 §七 合并,不覆盖)。
|
|
168
|
+
- **pi 插件管理**:`nao-skill plugins list` / `install <名...>` / `install-all`——舰队生态插件(intercom / ask-me / subagents / web-access / codegraph),透传 `pi install npm:<pkg>`,幂等跳过已装。
|
|
159
169
|
- **发布**:`npm publish --access public`(scope 包需 `--access public`)。
|
|
160
170
|
|
|
161
171
|
## 目录结构
|
package/bin/nao-skill.js
CHANGED
|
@@ -43,26 +43,39 @@ const VERSION_FILE = '.agents/.nao-version';
|
|
|
43
43
|
const log = (...a) => console.log('[nao-skill]', ...a);
|
|
44
44
|
const warn = (...a) => console.error('[nao-skill]', ...a);
|
|
45
45
|
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
function syncTree(src, dst, { mode, force, verbose }) {
|
|
47
|
+
// 递归文件级同步:mode='install'(保守)| 'update'(源优先)
|
|
48
|
+
// 源文件 → 目标无:copy;同内容:same(跳过);不同内容:install 默认 keep(--force 覆盖)/ update 总是 overwrite
|
|
49
|
+
// 目标独有:不动(项目自定义保留)
|
|
50
|
+
const stats = { copied: 0, overwritten: 0, same: 0, kept: 0 };
|
|
51
|
+
const base = dst;
|
|
52
|
+
const rel = (p) => p.replace(base + '/', '');
|
|
53
|
+
const walk = (s, d) => {
|
|
54
|
+
if (!existsSync(d)) mkdirSync(d, { recursive: true });
|
|
55
|
+
for (const e of readdirSync(s, { withFileTypes: true })) {
|
|
56
|
+
const sp = join(s, e.name);
|
|
57
|
+
const dp = join(d, e.name);
|
|
58
|
+
if (e.isDirectory()) { walk(sp, dp); continue; }
|
|
59
|
+
if (!existsSync(dp)) {
|
|
60
|
+
cpSync(sp, dp);
|
|
61
|
+
stats.copied++;
|
|
62
|
+
if (verbose) log(` copy ${rel(dp)}`);
|
|
63
|
+
} else if (readFileSync(sp).equals(readFileSync(dp))) {
|
|
64
|
+
stats.same++;
|
|
65
|
+
if (verbose) log(` same ${rel(dp)}`);
|
|
66
|
+
} else if (mode === 'update' || force) {
|
|
67
|
+
rmSync(dp, { force: true });
|
|
68
|
+
cpSync(sp, dp);
|
|
69
|
+
stats.overwritten++;
|
|
70
|
+
if (verbose) log(` overwrite ${rel(dp)}`);
|
|
57
71
|
} else {
|
|
58
|
-
|
|
72
|
+
stats.kept++;
|
|
73
|
+
if (verbose) log(` keep ${rel(dp)}(内容不同,--force 覆盖)`);
|
|
59
74
|
}
|
|
60
|
-
} else {
|
|
61
|
-
cpSync(s, d, { recursive: true });
|
|
62
|
-
copied++;
|
|
63
75
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
76
|
+
};
|
|
77
|
+
walk(src, dst);
|
|
78
|
+
return stats;
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
// 已知 pi 插件(nao 舰队生态),name → npm 包
|
|
@@ -126,7 +139,7 @@ function pluginsInstall(names, all = false) {
|
|
|
126
139
|
}
|
|
127
140
|
}
|
|
128
141
|
|
|
129
|
-
function install(target, force) {
|
|
142
|
+
function install(target, force, verbose) {
|
|
130
143
|
if (!existsSync(SRC)) {
|
|
131
144
|
warn(`包内 .agents 缺失:${SRC}(发布物损坏?)`);
|
|
132
145
|
process.exit(1);
|
|
@@ -137,10 +150,10 @@ function install(target, force) {
|
|
|
137
150
|
cpSync(SRC, dst, { recursive: true });
|
|
138
151
|
log(`已完整安装 .agents/ → ${dst}`);
|
|
139
152
|
} else {
|
|
140
|
-
const r =
|
|
141
|
-
log(`合并完成:复制 ${r.copied}
|
|
142
|
-
if (r.
|
|
143
|
-
warn('
|
|
153
|
+
const r = syncTree(SRC, dst, { mode: 'install', force, verbose });
|
|
154
|
+
log(`合并完成:复制 ${r.copied},覆盖 ${r.overwritten},相同跳过 ${r.same},保留项目版 ${r.kept}`);
|
|
155
|
+
if (r.kept > 0 && !force) {
|
|
156
|
+
warn('内容不同的文件保留项目既有(避免覆盖自定义);--force 覆盖,或 update 模式源优先。');
|
|
144
157
|
}
|
|
145
158
|
}
|
|
146
159
|
|
|
@@ -172,21 +185,15 @@ function install(target, force) {
|
|
|
172
185
|
log(' 角色卡:.agents/prompts/ · 技能:.agents/skills/ · 交付清单:.agents/checklists/');
|
|
173
186
|
}
|
|
174
187
|
|
|
175
|
-
function update(target) {
|
|
188
|
+
function update(target, verbose) {
|
|
176
189
|
// 源优先升级:机制文件以包为权威(项目定制应放 AGENTS.md,不在机制文件里改)
|
|
177
190
|
const dst = join(target, '.agents');
|
|
178
191
|
if (!existsSync(dst)) {
|
|
179
192
|
log('目标无 .agents/,直接完整安装。');
|
|
180
|
-
return install(target, false);
|
|
181
|
-
}
|
|
182
|
-
let overwritten = 0;
|
|
183
|
-
for (const e of readdirSync(SRC)) {
|
|
184
|
-
const s = join(SRC, e);
|
|
185
|
-
const d = join(dst, e);
|
|
186
|
-
rmSync(d, { recursive: true, force: true });
|
|
187
|
-
cpSync(s, d, { recursive: true });
|
|
188
|
-
overwritten++;
|
|
193
|
+
return install(target, false, verbose);
|
|
189
194
|
}
|
|
195
|
+
const r = syncTree(SRC, dst, { mode: 'update', force: true, verbose });
|
|
196
|
+
log(`升级完成:复制 ${r.copied},覆盖 ${r.overwritten},相同跳过 ${r.same}(项目自定义保留)`);
|
|
190
197
|
// 清理已知废弃路径(先备份到 .agents/.nao-obsolete/)
|
|
191
198
|
for (const p of OBSOLETE) {
|
|
192
199
|
const full = join(target, p);
|
|
@@ -215,9 +222,9 @@ function help() {
|
|
|
215
222
|
console.log(`nao-skill v${PKG.version} — nao 多角色 AI 开发舰队安装器
|
|
216
223
|
|
|
217
224
|
用法:
|
|
218
|
-
nao-skill install [dir] [--force] 安装/合并 .agents/
|
|
219
|
-
nao-skill install --plugins
|
|
220
|
-
nao-skill update [dir] 升级已有安装:源优先覆盖 + 清理废弃路径 + 保留项目自定义
|
|
225
|
+
nao-skill install [dir] [--force] [-v] 安装/合并 .agents/ 到目标项目(默认当前目录;-v 显示每文件过程)
|
|
226
|
+
nao-skill install --plugins [-v] 项目接入时顺带安装 pi 舰队插件
|
|
227
|
+
nao-skill update [dir] [-v] 升级已有安装:源优先覆盖 + 清理废弃路径 + 保留项目自定义
|
|
221
228
|
nao-skill plugins list 列出已知 pi 插件与安装状态
|
|
222
229
|
nao-skill plugins install <名...> 安装指定插件(intercom/ask-me/subagents/web-access/codegraph)
|
|
223
230
|
nao-skill plugins install-all 安装全部舰队插件
|
|
@@ -246,10 +253,12 @@ if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
|
|
|
246
253
|
let target = process.cwd();
|
|
247
254
|
let force = false;
|
|
248
255
|
let withPlugins = false;
|
|
256
|
+
let verbose = false;
|
|
249
257
|
const rest = args.slice(1);
|
|
250
258
|
for (let i = 0; i < rest.length; i++) {
|
|
251
259
|
if (rest[i] === '--force' || rest[i] === '-f') force = true;
|
|
252
260
|
else if (rest[i] === '--plugins') withPlugins = true;
|
|
261
|
+
else if (rest[i] === '--verbose' || rest[i] === '-v') verbose = true;
|
|
253
262
|
else if (rest[i] === '--target') target = resolve(rest[++i]);
|
|
254
263
|
else if (!rest[i].startsWith('-')) target = resolve(rest[i]);
|
|
255
264
|
else { warn(`未知参数: ${rest[i]}`); process.exit(2); }
|
|
@@ -258,7 +267,7 @@ if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
|
|
|
258
267
|
warn(`目标目录无效: ${target}`);
|
|
259
268
|
process.exit(2);
|
|
260
269
|
}
|
|
261
|
-
install(target, force);
|
|
270
|
+
install(target, force, verbose);
|
|
262
271
|
if (withPlugins) pluginsInstall([], true);
|
|
263
272
|
} else if (cmd === 'plugins' || cmd === 'plugin') {
|
|
264
273
|
const sub = args[1];
|
|
@@ -275,9 +284,11 @@ if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
|
|
|
275
284
|
}
|
|
276
285
|
} else if (cmd === 'update' || cmd === 'u') {
|
|
277
286
|
let target = process.cwd();
|
|
287
|
+
let verbose = false;
|
|
278
288
|
const rest = args.slice(1);
|
|
279
289
|
for (let i = 0; i < rest.length; i++) {
|
|
280
|
-
if (rest[i] === '--
|
|
290
|
+
if (rest[i] === '--verbose' || rest[i] === '-v') verbose = true;
|
|
291
|
+
else if (rest[i] === '--target') target = resolve(rest[++i]);
|
|
281
292
|
else if (!rest[i].startsWith('-')) target = resolve(rest[i]);
|
|
282
293
|
else { warn(`未知参数: ${rest[i]}`); process.exit(2); }
|
|
283
294
|
}
|
|
@@ -285,8 +296,8 @@ if (cmd === '--version' || cmd === '-v' || cmd === 'version') {
|
|
|
285
296
|
warn(`目标目录无效: ${target}`);
|
|
286
297
|
process.exit(2);
|
|
287
298
|
}
|
|
288
|
-
update(target);
|
|
299
|
+
update(target, verbose);
|
|
289
300
|
} else {
|
|
290
|
-
warn(`未知命令: ${cmd}(可用: install)`);
|
|
301
|
+
warn(`未知命令: ${cmd}(可用: install, update, plugins)`);
|
|
291
302
|
process.exit(2);
|
|
292
303
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nathan33/nao-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "nao 多角色 AI 开发舰队:角色卡 / 技能 / 协作协议 / 工具链,一键接入项目(pi / Claude / 任意 Agent)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,5 +30,13 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"test": "bash .agents/scripts/nao-fleet.sh check",
|
|
32
32
|
"prepack": "bash .agents/scripts/nao-fleet.sh check"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/Nathan3303/nao-skills.git"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/Nathan3303/nao-skills",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/Nathan3303/nao-skills/issues"
|
|
33
41
|
}
|
|
34
42
|
}
|