@xihe-lab/tapd-cli 2.0.0-rc.1 → 2.0.0-rc.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/README.md +22 -0
- package/dist/advisor/domain-axis.d.ts +16 -0
- package/dist/advisor/domain-axis.d.ts.map +1 -0
- package/dist/advisor/domain-axis.js +43 -0
- package/dist/advisor/domain-axis.js.map +1 -0
- package/dist/advisor/domain-axis.test.d.ts +2 -0
- package/dist/advisor/domain-axis.test.d.ts.map +1 -0
- package/dist/advisor/domain-axis.test.js +198 -0
- package/dist/advisor/domain-axis.test.js.map +1 -0
- package/dist/advisor/index.d.ts +8 -0
- package/dist/advisor/index.d.ts.map +1 -0
- package/dist/advisor/index.js +6 -0
- package/dist/advisor/index.js.map +1 -0
- package/dist/advisor/persona.d.ts +12 -0
- package/dist/advisor/persona.d.ts.map +1 -0
- package/dist/advisor/persona.js +34 -0
- package/dist/advisor/persona.js.map +1 -0
- package/dist/advisor/recall.d.ts +38 -0
- package/dist/advisor/recall.d.ts.map +1 -0
- package/dist/advisor/recall.js +96 -0
- package/dist/advisor/recall.js.map +1 -0
- package/dist/advisor/render.d.ts +8 -0
- package/dist/advisor/render.d.ts.map +1 -0
- package/dist/advisor/render.js +42 -0
- package/dist/advisor/render.js.map +1 -0
- package/dist/commands/advisor.d.ts.map +1 -1
- package/dist/commands/advisor.js +31 -13
- package/dist/commands/advisor.js.map +1 -1
- package/dist/commands/pipeline.d.ts +4 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +178 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/pm.d.ts +4 -0
- package/dist/commands/pm.d.ts.map +1 -0
- package/dist/commands/pm.js +175 -0
- package/dist/commands/pm.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/engine.d.ts +38 -0
- package/dist/pipeline/engine.d.ts.map +1 -0
- package/dist/pipeline/engine.js +326 -0
- package/dist/pipeline/engine.js.map +1 -0
- package/dist/pipeline/engine.test.d.ts +2 -0
- package/dist/pipeline/engine.test.d.ts.map +1 -0
- package/dist/pipeline/engine.test.js +419 -0
- package/dist/pipeline/engine.test.js.map +1 -0
- package/dist/pipeline/expression.d.ts +31 -0
- package/dist/pipeline/expression.d.ts.map +1 -0
- package/dist/pipeline/expression.js +249 -0
- package/dist/pipeline/expression.js.map +1 -0
- package/dist/pipeline/expression.test.d.ts +2 -0
- package/dist/pipeline/expression.test.d.ts.map +1 -0
- package/dist/pipeline/expression.test.js +111 -0
- package/dist/pipeline/expression.test.js.map +1 -0
- package/dist/pipeline/history.d.ts +13 -0
- package/dist/pipeline/history.d.ts.map +1 -0
- package/dist/pipeline/history.js +66 -0
- package/dist/pipeline/history.js.map +1 -0
- package/dist/pipeline/index.d.ts +13 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +9 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/record.d.ts +13 -0
- package/dist/pipeline/record.d.ts.map +1 -0
- package/dist/pipeline/record.js +30 -0
- package/dist/pipeline/record.js.map +1 -0
- package/dist/pipeline/record.test.d.ts +2 -0
- package/dist/pipeline/record.test.d.ts.map +1 -0
- package/dist/pipeline/record.test.js +109 -0
- package/dist/pipeline/record.test.js.map +1 -0
- package/dist/pipeline/template.d.ts +24 -0
- package/dist/pipeline/template.d.ts.map +1 -0
- package/dist/pipeline/template.js +134 -0
- package/dist/pipeline/template.js.map +1 -0
- package/dist/pipeline/template.test.d.ts +2 -0
- package/dist/pipeline/template.test.d.ts.map +1 -0
- package/dist/pipeline/template.test.js +94 -0
- package/dist/pipeline/template.test.js.map +1 -0
- package/dist/pipeline/types.d.ts +99 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +31 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/unwrap.d.ts +3 -0
- package/dist/pipeline/unwrap.d.ts.map +1 -0
- package/dist/pipeline/unwrap.js +26 -0
- package/dist/pipeline/unwrap.js.map +1 -0
- package/dist/pipeline/unwrap.test.d.ts +2 -0
- package/dist/pipeline/unwrap.test.d.ts.map +1 -0
- package/dist/pipeline/unwrap.test.js +36 -0
- package/dist/pipeline/unwrap.test.js.map +1 -0
- package/dist/pipeline/validate.d.ts +18 -0
- package/dist/pipeline/validate.d.ts.map +1 -0
- package/dist/pipeline/validate.js +134 -0
- package/dist/pipeline/validate.js.map +1 -0
- package/dist/pipeline/validate.test.d.ts +2 -0
- package/dist/pipeline/validate.test.d.ts.map +1 -0
- package/dist/pipeline/validate.test.js +166 -0
- package/dist/pipeline/validate.test.js.map +1 -0
- package/dist/pm/discovery.d.ts +54 -0
- package/dist/pm/discovery.d.ts.map +1 -0
- package/dist/pm/discovery.js +198 -0
- package/dist/pm/discovery.js.map +1 -0
- package/dist/pm/discovery.test.d.ts +2 -0
- package/dist/pm/discovery.test.d.ts.map +1 -0
- package/dist/pm/discovery.test.js +147 -0
- package/dist/pm/discovery.test.js.map +1 -0
- package/dist/pm/domains.d.ts +15 -0
- package/dist/pm/domains.d.ts.map +1 -0
- package/dist/pm/domains.js +27 -0
- package/dist/pm/domains.js.map +1 -0
- package/dist/pm/domains.test.d.ts +2 -0
- package/dist/pm/domains.test.d.ts.map +1 -0
- package/dist/pm/domains.test.js +141 -0
- package/dist/pm/domains.test.js.map +1 -0
- package/dist/pm/index.d.ts +9 -0
- package/dist/pm/index.d.ts.map +1 -0
- package/dist/pm/index.js +6 -0
- package/dist/pm/index.js.map +1 -0
- package/dist/pm/iteration.d.ts +26 -0
- package/dist/pm/iteration.d.ts.map +1 -0
- package/dist/pm/iteration.js +50 -0
- package/dist/pm/iteration.js.map +1 -0
- package/dist/pm/iteration.test.d.ts +2 -0
- package/dist/pm/iteration.test.d.ts.map +1 -0
- package/dist/pm/iteration.test.js +125 -0
- package/dist/pm/iteration.test.js.map +1 -0
- package/dist/pm/pm-command.test.d.ts +2 -0
- package/dist/pm/pm-command.test.d.ts.map +1 -0
- package/dist/pm/pm-command.test.js +321 -0
- package/dist/pm/pm-command.test.js.map +1 -0
- package/dist/pm/render.d.ts +17 -0
- package/dist/pm/render.d.ts.map +1 -0
- package/dist/pm/render.js +82 -0
- package/dist/pm/render.js.map +1 -0
- package/dist/pm/tpl-communication-stakeholder.test.d.ts +2 -0
- package/dist/pm/tpl-communication-stakeholder.test.d.ts.map +1 -0
- package/dist/pm/tpl-communication-stakeholder.test.js +392 -0
- package/dist/pm/tpl-communication-stakeholder.test.js.map +1 -0
- package/dist/pm/tpl-integration-scope.test.d.ts +2 -0
- package/dist/pm/tpl-integration-scope.test.d.ts.map +1 -0
- package/dist/pm/tpl-integration-scope.test.js +387 -0
- package/dist/pm/tpl-integration-scope.test.js.map +1 -0
- package/dist/pm/tpl-quality-risk.test.d.ts +2 -0
- package/dist/pm/tpl-quality-risk.test.d.ts.map +1 -0
- package/dist/pm/tpl-quality-risk.test.js +414 -0
- package/dist/pm/tpl-quality-risk.test.js.map +1 -0
- package/dist/pm/tpl-schedule-cost.test.d.ts +2 -0
- package/dist/pm/tpl-schedule-cost.test.d.ts.map +1 -0
- package/dist/pm/tpl-schedule-cost.test.js +376 -0
- package/dist/pm/tpl-schedule-cost.test.js.map +1 -0
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +6 -0
- package/dist/program.js.map +1 -1
- package/package.json +11 -6
- package/templates/deliver-story.yaml +38 -0
- package/templates/iteration-review.yaml +52 -0
- package/templates/pm/README.md +57 -0
- package/templates/pm/communication-notify.yaml +65 -0
- package/templates/pm/communication-weekly.yaml +160 -0
- package/templates/pm/cost-report.yaml +74 -0
- package/templates/pm/integration-close.yaml +118 -0
- package/templates/pm/integration-health.yaml +155 -0
- package/templates/pm/integration-kickoff.yaml +94 -0
- package/templates/pm/quality-dashboard.yaml +88 -0
- package/templates/pm/quality-triage.yaml +42 -0
- package/templates/pm/risk-register.yaml +55 -0
- package/templates/pm/risk-scan.yaml +87 -0
- package/templates/pm/schedule-burndown.yaml +87 -0
- package/templates/pm/schedule-standup.yaml +109 -0
- package/templates/pm/scope-baseline.yaml +93 -0
- package/templates/pm/scope-drift-check.yaml +129 -0
- package/templates/pm/stakeholder-map.yaml +121 -0
- package/templates/triage-bugs.yaml +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @xihe-lab/tapd-cli
|
|
2
|
+
|
|
3
|
+
TAPD 研发协作命令行,与 `@xihe-lab/tapd-mcp-server` 共享同一内核 `@xihe-lab/tapd-core`。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @xihe-lab/tapd-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 命令体系
|
|
12
|
+
|
|
13
|
+
- **资源命令**:`tapd story` / `tapd bug` / `tapd task` / `tapd iteration` / `tapd wiki`(别名 `s` / `b` / `t` / `i` / `w`),由内核工具注册表动态生成,覆盖 TAPD 需求/缺陷/任务/迭代等读写操作
|
|
14
|
+
- `tapd auth` — 配置认证
|
|
15
|
+
- `tapd config` — 配置读写
|
|
16
|
+
- `tapd advisor` — 命令推荐
|
|
17
|
+
- `tapd pipeline` — 管道执行(模板/表达式/校验/引擎/录制)
|
|
18
|
+
- `tapd pm` — 研发项目管理操作(整合/范围/进度/成本/质量/资源/沟通/风险等场景)
|
|
19
|
+
|
|
20
|
+
## License
|
|
21
|
+
|
|
22
|
+
Apache-2.0
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface DomainKeywordEntry {
|
|
2
|
+
/** 域键:tapd pm <key> <scenario> 的 <key> */
|
|
3
|
+
domain: string;
|
|
4
|
+
/** 域中文名(与 PM_DOMAINS.zh 同源口径) */
|
|
5
|
+
zh: string;
|
|
6
|
+
/** 中英文同义词;英文按词边界匹配,中文按子串匹配 */
|
|
7
|
+
keywords: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const DOMAIN_KEYWORDS: readonly DomainKeywordEntry[];
|
|
10
|
+
/** 文本命中的域键(按域表序去重);用于原子候选的 domain 特征标注 */
|
|
11
|
+
export declare function domainsInText(text: string): string[];
|
|
12
|
+
/** 查询命中域(召回入口):空数组 = 未命中任何域轴关键词,退化为纯原子召回 */
|
|
13
|
+
export declare function matchQueryDomains(query: string): string[];
|
|
14
|
+
/** 原子候选的域特征文本:command + description(工具名段已折叠进 command,不重复扫) */
|
|
15
|
+
export declare function candidateFeatureText(command: string, description: string): string;
|
|
16
|
+
//# sourceMappingURL=domain-axis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-axis.d.ts","sourceRoot":"","sources":["../../src/advisor/domain-axis.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,kBAAkB,EAWxD,CAAC;AAYF,0CAA0C;AAC1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGpD;AAED,4CAA4C;AAC5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEjF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// advisor 域轴(S7,TAPD 需求 1139814312001001545)
|
|
2
|
+
//
|
|
3
|
+
// 软考高项第4版八知识域 × 中英文同义词关键词表(tapd-2.0.0-pm-layer-design.md §4)。
|
|
4
|
+
// 一张表同时服务两类候选:
|
|
5
|
+
// - pm 场景模板候选:frontmatter domain 直接给域;本表负责「查询 → 域」的召回判定;
|
|
6
|
+
// - 原子命令候选:对 command + description 文本扫关键词,产出的域集合作为候选的
|
|
7
|
+
// domain 特征字段(F9 LLM 排序的预置特征,也用于域命中时原子块的稳定前移)。
|
|
8
|
+
//
|
|
9
|
+
// 域键口径与 pm/domains.ts 的 PM_DOMAINS 完全一致(八域;采购/绩效不单设域)。
|
|
10
|
+
export const DOMAIN_KEYWORDS = [
|
|
11
|
+
// rc.2 富媒体协作(1139814312001001546/1548):附件/图片上传下载归整合域(工具/资源整合视角)
|
|
12
|
+
{ domain: 'integration', zh: '整合管理', keywords: ['integration', '整合', '健康', '结项', '启动', '看板', 'attachment', '附件', 'upload', '上传', 'download', '下载', 'image', '图片', '截图'] },
|
|
13
|
+
{ domain: 'scope', zh: '范围管理', keywords: ['scope', 'wbs', '基线', '蔓延', '范围', '需求冻结'] },
|
|
14
|
+
{ domain: 'schedule', zh: '进度管理', keywords: ['schedule', '进度', '排期', '站会', '燃尽', '逾期'] },
|
|
15
|
+
{ domain: 'cost', zh: '成本管理', keywords: ['cost', '成本', '工时', '预算', '超支', 'evm'] },
|
|
16
|
+
{ domain: 'quality', zh: '质量管理', keywords: ['quality', '质量', '缺陷', '测试', '用例', '分诊'] },
|
|
17
|
+
// @/提及 是沟通动作(评论 at-who 提及触达),归沟通域;'@' 为子串匹配,查询含 @ 即召回沟通域
|
|
18
|
+
{ domain: 'communication', zh: '沟通管理', keywords: ['communication', '沟通', '周报', '通知', '评论', 'mention', '提及', '@'] },
|
|
19
|
+
{ domain: 'risk', zh: '风险管理', keywords: ['risk', '风险', '预警', '登记册', '暴露'] },
|
|
20
|
+
{ domain: 'stakeholder', zh: '干系人管理', keywords: ['stakeholder', '干系人', '参与', '相关方'] },
|
|
21
|
+
];
|
|
22
|
+
const ASCII_KEYWORD = /^[a-z0-9]+$/;
|
|
23
|
+
function textContainsKeyword(lowerText, keyword) {
|
|
24
|
+
if (ASCII_KEYWORD.test(keyword)) {
|
|
25
|
+
// 词边界匹配:cost 不误吃 process、evm 不误吃 evms
|
|
26
|
+
return new RegExp(`\\b${keyword}\\b`).test(lowerText);
|
|
27
|
+
}
|
|
28
|
+
return lowerText.includes(keyword);
|
|
29
|
+
}
|
|
30
|
+
/** 文本命中的域键(按域表序去重);用于原子候选的 domain 特征标注 */
|
|
31
|
+
export function domainsInText(text) {
|
|
32
|
+
const lower = text.toLowerCase();
|
|
33
|
+
return DOMAIN_KEYWORDS.filter(entry => entry.keywords.some(k => textContainsKeyword(lower, k))).map(e => e.domain);
|
|
34
|
+
}
|
|
35
|
+
/** 查询命中域(召回入口):空数组 = 未命中任何域轴关键词,退化为纯原子召回 */
|
|
36
|
+
export function matchQueryDomains(query) {
|
|
37
|
+
return domainsInText(query);
|
|
38
|
+
}
|
|
39
|
+
/** 原子候选的域特征文本:command + description(工具名段已折叠进 command,不重复扫) */
|
|
40
|
+
export function candidateFeatureText(command, description) {
|
|
41
|
+
return `${command} ${description}`;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=domain-axis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-axis.js","sourceRoot":"","sources":["../../src/advisor/domain-axis.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,8DAA8D;AAC9D,eAAe;AACf,2DAA2D;AAC3D,wDAAwD;AACxD,mDAAmD;AACnD,EAAE;AACF,uDAAuD;AAWvD,MAAM,CAAC,MAAM,eAAe,GAAkC;IAC5D,gEAAgE;IAChE,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;IACzK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;IACrF,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;IACxF,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE;IACjF,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;IACtF,yDAAyD;IACzD,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE;IAClH,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE;IAC3E,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE;CACtF,CAAC;AAEF,MAAM,aAAa,GAAG,aAAa,CAAC;AAEpC,SAAS,mBAAmB,CAAC,SAAiB,EAAE,OAAe;IAC7D,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,sCAAsC;QACtC,OAAO,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACrH,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,WAAmB;IACvE,OAAO,GAAG,OAAO,IAAI,WAAW,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-axis.test.d.ts","sourceRoot":"","sources":["../../src/advisor/domain-axis.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// advisor 域轴 + 角色轴测试(S7,TAPD 需求 1139814312001001545)
|
|
2
|
+
// fixture 模板写在测试临时目录(TAPD_USER_TEMPLATES_DIR 注入),不污染 templates/pm/;
|
|
3
|
+
// 原子召回用真实 allTools registry(纯内存索引,不触 API)。
|
|
4
|
+
import assert from 'node:assert/strict';
|
|
5
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { tmpdir } from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { allTools, buildAdvisorIndex, recommend, ToolRegistry } from '@xihe-lab/tapd-core';
|
|
9
|
+
import { buildProgram } from '../program.js';
|
|
10
|
+
import { CliError } from '../errors.js';
|
|
11
|
+
import { DOMAIN_KEYWORDS, domainsInText, matchQueryDomains } from './domain-axis.js';
|
|
12
|
+
import { PERSONA_LABELS, parsePersona } from './persona.js';
|
|
13
|
+
import { advise } from './recall.js';
|
|
14
|
+
import { advisorJson, advisorNotes, renderAdvisorTable } from './render.js';
|
|
15
|
+
import { PM_DOMAINS } from '../pm/index.js';
|
|
16
|
+
// ---- fixture 模板(用户目录:当前 templates/pm/ 尚无域模板,S3-S6 并行开发中) ----
|
|
17
|
+
const RISK_SCAN = `name: risk-scan
|
|
18
|
+
domain: risk
|
|
19
|
+
title: 多源风险扫描(fixture)
|
|
20
|
+
write: false
|
|
21
|
+
steps:
|
|
22
|
+
- id: iterations
|
|
23
|
+
uses: tapd_get_iterations
|
|
24
|
+
args: { status: open }
|
|
25
|
+
`;
|
|
26
|
+
const RISK_REGISTER = `name: risk-register
|
|
27
|
+
domain: risk
|
|
28
|
+
title: 风险登记册维护(fixture 写场景)
|
|
29
|
+
write: true
|
|
30
|
+
steps:
|
|
31
|
+
- id: stories
|
|
32
|
+
uses: tapd_get_stories
|
|
33
|
+
args: { fields: "id,name" }
|
|
34
|
+
`;
|
|
35
|
+
const QUALITY_DASHBOARD = `name: quality-dashboard
|
|
36
|
+
domain: quality
|
|
37
|
+
title: 质量度量盘(fixture)
|
|
38
|
+
write: false
|
|
39
|
+
steps:
|
|
40
|
+
- id: bugs
|
|
41
|
+
uses: tapd_get_bugs
|
|
42
|
+
args: { fields: "id,status" }
|
|
43
|
+
`;
|
|
44
|
+
const root = mkdtempSync(path.join(tmpdir(), 'tapd-advisor-domain-'));
|
|
45
|
+
mkdirSync(path.join(root, 'pm'), { recursive: true });
|
|
46
|
+
writeFileSync(path.join(root, 'pm', 'risk-scan.yaml'), RISK_SCAN);
|
|
47
|
+
writeFileSync(path.join(root, 'pm', 'risk-register.yaml'), RISK_REGISTER);
|
|
48
|
+
writeFileSync(path.join(root, 'pm', 'quality-dashboard.yaml'), QUALITY_DASHBOARD);
|
|
49
|
+
const prevEnv = process.env.TAPD_USER_TEMPLATES_DIR;
|
|
50
|
+
process.env.TAPD_USER_TEMPLATES_DIR = root;
|
|
51
|
+
const registry = new ToolRegistry();
|
|
52
|
+
registry.register(allTools);
|
|
53
|
+
const index = buildAdvisorIndex(registry);
|
|
54
|
+
function commands(hits) {
|
|
55
|
+
return hits.map(h => h.command);
|
|
56
|
+
}
|
|
57
|
+
const checks = [
|
|
58
|
+
['关键词表:八域齐备且与 PM_DOMAINS 同口径,每域中英文关键词都有', () => {
|
|
59
|
+
assert.equal(DOMAIN_KEYWORDS.length, 8);
|
|
60
|
+
assert.deepEqual(DOMAIN_KEYWORDS.map(e => e.domain), PM_DOMAINS.map(d => d.key), '域键顺序/集合必须与 pm 域表一致');
|
|
61
|
+
for (const entry of DOMAIN_KEYWORDS) {
|
|
62
|
+
assert.ok(entry.keywords.length >= 4, `${entry.domain} 关键词过少`);
|
|
63
|
+
assert.ok(entry.keywords.some(k => /^[a-z0-9]+$/.test(k)), `${entry.domain} 缺英文关键词`);
|
|
64
|
+
assert.ok(entry.keywords.some(k => !/^[a-z0-9]+$/.test(k)), `${entry.domain} 缺中文关键词`);
|
|
65
|
+
assert.ok(entry.zh.length > 0);
|
|
66
|
+
}
|
|
67
|
+
}],
|
|
68
|
+
['域匹配:中文子串命中、英文词边界命中(cost 不吃 process)', () => {
|
|
69
|
+
assert.deepEqual(matchQueryDomains('帮我扫一遍风险预警'), ['risk']);
|
|
70
|
+
assert.deepEqual(domainsInText('范围基线冻结与需求冻结'), ['scope']);
|
|
71
|
+
assert.deepEqual(domainsInText('use evm metrics to watch cost'), ['cost']);
|
|
72
|
+
assert.ok(!domainsInText('this is a process review').includes('cost'), 'cost 不得子串误命中 process');
|
|
73
|
+
assert.ok(domainsInText('工时预算超支了').includes('cost'));
|
|
74
|
+
assert.deepEqual(matchQueryDomains('列表'), [], '无域关键词的查询不得误触发域轴');
|
|
75
|
+
}],
|
|
76
|
+
['域命中 → pm 场景候选置顶,写标识随模板透传', () => {
|
|
77
|
+
const result = advise('看看迭代的风险', index);
|
|
78
|
+
assert.deepEqual(result.matchedDomains, ['risk']);
|
|
79
|
+
assert.equal(result.hits[0].kind, 'pm');
|
|
80
|
+
assert.equal(result.hits[0].command, 'pm risk register');
|
|
81
|
+
assert.equal(result.hits[0].write, true, 'write:true 的 pm 场景必须保留写标识');
|
|
82
|
+
assert.equal(result.hits[1].command, 'pm risk scan');
|
|
83
|
+
assert.equal(result.hits[1].write, false);
|
|
84
|
+
assert.equal(result.hits[2].kind, 'atomic', 'pm 场景之后才是原子命令候选');
|
|
85
|
+
assert.ok(result.hits.every(h => h.kind !== 'pm' || h.domains.includes('risk')));
|
|
86
|
+
// usage 提示随写场景附 --yes
|
|
87
|
+
assert.equal(result.hits[0].usage, 'tapd pm risk register [--iteration <id>] [--dry-run] [--yes]');
|
|
88
|
+
}],
|
|
89
|
+
['多域命中:按域表序排 pm 场景(quality 在 risk 前),原子块稳定跟随', () => {
|
|
90
|
+
const result = advise('风险和用例分诊一起看', index);
|
|
91
|
+
assert.deepEqual(result.matchedDomains, ['quality', 'risk']);
|
|
92
|
+
// 集成后内置模板随域动态扩展(fixture + builtin 叠加),断言排序性质而非精确清单:
|
|
93
|
+
// quality 与 risk 场景都出现,且所有 quality 场景先于所有 risk 场景,pm 块整体在原子块之前。
|
|
94
|
+
const pm = commands(result.hits.filter(h => h.kind === 'pm'));
|
|
95
|
+
const domOf = (c) => (c.startsWith('pm quality ') ? 'quality' : c.startsWith('pm risk ') ? 'risk' : 'other');
|
|
96
|
+
const seq = pm.map(domOf);
|
|
97
|
+
assert.ok(seq.includes('quality') && seq.includes('risk'), 'quality 与 risk 的 pm 场景都必须出现');
|
|
98
|
+
const firstRisk = seq.indexOf('risk');
|
|
99
|
+
assert.ok(seq.every((d, i) => d !== 'quality' || i < firstRisk), '域表序:quality 场景必须全部排在 risk 场景之前');
|
|
100
|
+
const firstAtomic = result.hits.findIndex(h => h.kind === 'atomic');
|
|
101
|
+
const lastPm = result.hits.map(h => h.kind === 'pm').lastIndexOf(true);
|
|
102
|
+
assert.ok(firstAtomic < 0 || lastPm < firstAtomic, 'pm 场景块必须在原子块之前');
|
|
103
|
+
}],
|
|
104
|
+
['未收录域:无模板自动跳过 pm 候选,退化为原子召回(给集成者的行为保证)', () => {
|
|
105
|
+
// 八域现已全部收录内置模板,改用注入空目录直接验证降级语义(不再依赖「某域恰好无模板」)
|
|
106
|
+
const result = advise('冻结范围基线', index, { limit: 10, catalog: { entries: [], warnings: [] } });
|
|
107
|
+
assert.deepEqual(result.matchedDomains, ['scope']);
|
|
108
|
+
assert.ok(result.hits.every(h => h.kind !== 'pm'), '目录为空时不得出现 pm 候选');
|
|
109
|
+
assert.ok(result.hits.length > 0, '域命中但无模板时仍应返回原子候选');
|
|
110
|
+
}],
|
|
111
|
+
['无 persona 且无域命中:与 core recommend 顺序逐位一致(现有行为零变化)', () => {
|
|
112
|
+
const result = advise('列表', index);
|
|
113
|
+
assert.deepEqual(result.matchedDomains, []);
|
|
114
|
+
const baseline = recommend('列表', index, 10).map(h => h.command);
|
|
115
|
+
assert.deepEqual(commands(result.hits), baseline);
|
|
116
|
+
assert.ok(result.hits.every(h => h.kind === 'atomic'));
|
|
117
|
+
assert.equal(result.persona, undefined);
|
|
118
|
+
}],
|
|
119
|
+
['--persona 三档对同一查询顺序可区分:dev 偏 task/story,qa 偏 bug,pm 偏 pm 场景+iteration/release', () => {
|
|
120
|
+
// limit 放大到 20:确保 dev/qa/pm 三方关心的代表命令都留在窗口内可比
|
|
121
|
+
const base = advise('列表', index, { limit: 20 });
|
|
122
|
+
const dev = advise('列表', index, { persona: 'dev', limit: 20 });
|
|
123
|
+
const qa = advise('列表', index, { persona: 'qa', limit: 20 });
|
|
124
|
+
const pm = advise('列表', index, { persona: 'pm', limit: 20 });
|
|
125
|
+
const idx = (hits, cmd) => commands(hits).indexOf(cmd);
|
|
126
|
+
const orderOf = (hits) => commands(hits).join(', ');
|
|
127
|
+
assert.ok(idx(dev.hits, 'task list') < idx(dev.hits, 'bug list'), `dev: task list 应在 bug list 前: ${orderOf(dev.hits)}`);
|
|
128
|
+
assert.ok(idx(dev.hits, 'story list') < idx(dev.hits, 'bug list'), `dev: story list 应在 bug list 前: ${orderOf(dev.hits)}`);
|
|
129
|
+
assert.ok(idx(qa.hits, 'bug list') < idx(qa.hits, 'task list'), `qa: bug list 应在 task list 前: ${orderOf(qa.hits)}`);
|
|
130
|
+
assert.ok(idx(qa.hits, 'bug list') < idx(qa.hits, 'story list'), `qa: bug list 应在 story list 前: ${orderOf(qa.hits)}`);
|
|
131
|
+
assert.equal(pm.hits[0].kind, 'pm', 'pm persona 未命中域轴时也应注入 pm 场景候选');
|
|
132
|
+
assert.ok(pm.hits.slice(0, 3).every(h => h.kind === 'pm'));
|
|
133
|
+
const firstAtomic = pm.hits.find(h => h.kind === 'atomic').command;
|
|
134
|
+
assert.match(firstAtomic, /^(iteration|release|report)\b/, `pm: 首个原子候选应为 iteration/release/report 类: ${firstAtomic}`);
|
|
135
|
+
const orders = [commands(base.hits), commands(dev.hits), commands(qa.hits), commands(pm.hits)];
|
|
136
|
+
for (let i = 0; i < orders.length; i++) {
|
|
137
|
+
for (let j = i + 1; j < orders.length; j++) {
|
|
138
|
+
assert.notDeepEqual(orders[i], orders[j], `第 ${i} 与 ${j} 档顺序必须可区分`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}],
|
|
142
|
+
['输出扩展:DOMAIN 列、说明行、JSON 扩展字段(tool/kind/domains/usage)', () => {
|
|
143
|
+
const result = advise('看看迭代的风险', index, { persona: 'qa' });
|
|
144
|
+
const table = renderAdvisorTable(result.hits);
|
|
145
|
+
for (const fragment of ['COMMAND', 'WRITE', 'DOMAIN', 'DESCRIPTION', 'pm risk register', '✓']) {
|
|
146
|
+
assert.ok(table.includes(fragment), `表格缺片段: ${fragment}`);
|
|
147
|
+
}
|
|
148
|
+
const notes = advisorNotes(result);
|
|
149
|
+
assert.ok(notes.some(n => n.startsWith('domain: 命中知识域 risk')), `缺域命中说明: ${notes.join(' | ')}`);
|
|
150
|
+
assert.ok(notes.some(n => n === `persona: qa —— ${PERSONA_LABELS.qa}`), `缺 persona 说明行: ${notes.join(' | ')}`);
|
|
151
|
+
const parsed = JSON.parse(advisorJson(result.hits));
|
|
152
|
+
const pmHit = parsed.find(h => h.kind === 'pm');
|
|
153
|
+
assert.equal(pmHit.command, 'pm risk register');
|
|
154
|
+
assert.equal(pmHit.write, true);
|
|
155
|
+
assert.deepEqual(pmHit.domains, ['risk']);
|
|
156
|
+
assert.equal(typeof pmHit.usage, 'string');
|
|
157
|
+
assert.equal(pmHit.tool, undefined, 'pm 候选无底层工具名');
|
|
158
|
+
const atomicHit = parsed.find(h => h.kind === 'atomic');
|
|
159
|
+
assert.equal(typeof atomicHit.tool, 'string');
|
|
160
|
+
assert.ok(Array.isArray(atomicHit.domains));
|
|
161
|
+
}],
|
|
162
|
+
['未知 persona:parsePersona 报 INVALID_ARGS(exit 2),CLI 入口同样拒绝', async () => {
|
|
163
|
+
assert.throws(() => parsePersona('boss'), (error) => error instanceof CliError && error.code === 'INVALID_ARGS' && error.exitCode === 2
|
|
164
|
+
&& error.message.includes('dev') && error.message.includes('qa') && error.message.includes('pm'));
|
|
165
|
+
assert.equal(parsePersona(undefined), undefined);
|
|
166
|
+
assert.equal(parsePersona('PM'), 'pm', '大小写不敏感');
|
|
167
|
+
// 端到端:命令入口在发现模板/构建索引之前先校验 persona
|
|
168
|
+
const program = buildProgram(registry, {});
|
|
169
|
+
await assert.rejects(() => program.parseAsync(['node', 'tapd', 'advisor', '风险', '--persona', 'boss']), (error) => error instanceof CliError && error.code === 'INVALID_ARGS');
|
|
170
|
+
}],
|
|
171
|
+
];
|
|
172
|
+
let failed = 0;
|
|
173
|
+
try {
|
|
174
|
+
for (const [name, fn] of checks) {
|
|
175
|
+
try {
|
|
176
|
+
await fn();
|
|
177
|
+
console.log(`ok - ${name}`);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
failed++;
|
|
181
|
+
console.error(`FAIL - ${name}`);
|
|
182
|
+
console.error(error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
if (prevEnv === undefined)
|
|
188
|
+
delete process.env.TAPD_USER_TEMPLATES_DIR;
|
|
189
|
+
else
|
|
190
|
+
process.env.TAPD_USER_TEMPLATES_DIR = prevEnv;
|
|
191
|
+
rmSync(root, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
if (failed > 0) {
|
|
194
|
+
console.error(`\n${failed}/${checks.length} failed`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
console.log(`\n${checks.length}/${checks.length} passed`);
|
|
198
|
+
//# sourceMappingURL=domain-axis.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-axis.test.js","sourceRoot":"","sources":["../../src/advisor/domain-axis.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DOMAIN_KEYWORDS, domainsInText, matchQueryDomains, candidateFeatureText } from './domain-axis.js';
|
|
2
|
+
export type { DomainKeywordEntry } from './domain-axis.js';
|
|
3
|
+
export { PERSONAS, PERSONA_LABELS, parsePersona, personaBoost } from './persona.js';
|
|
4
|
+
export type { Persona } from './persona.js';
|
|
5
|
+
export { advise } from './recall.js';
|
|
6
|
+
export type { AdvisorCandidate, AdviseOptions, AdviseResult } from './recall.js';
|
|
7
|
+
export { renderAdvisorTable, advisorNotes, advisorJson } from './render.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/advisor/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC3G,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpF,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// advisor 域轴/角色轴公共出口(S7):commands/advisor.ts 只从这里取接口
|
|
2
|
+
export { DOMAIN_KEYWORDS, domainsInText, matchQueryDomains, candidateFeatureText } from './domain-axis.js';
|
|
3
|
+
export { PERSONAS, PERSONA_LABELS, parsePersona, personaBoost } from './persona.js';
|
|
4
|
+
export { advise } from './recall.js';
|
|
5
|
+
export { renderAdvisorTable, advisorNotes, advisorJson } from './render.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/advisor/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAErD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE3G,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEpF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type Persona = 'dev' | 'qa' | 'pm';
|
|
2
|
+
export declare const PERSONAS: readonly Persona[];
|
|
3
|
+
/** 输出里的一行角色影响说明(中文,说明偏移方向而非实现细节) */
|
|
4
|
+
export declare const PERSONA_LABELS: Record<Persona, string>;
|
|
5
|
+
/** 候选是否命中角色偏好(参与重排的 +2 权重判定) */
|
|
6
|
+
export declare function personaBoost(candidate: {
|
|
7
|
+
kind: 'pm' | 'atomic';
|
|
8
|
+
command: string;
|
|
9
|
+
}, persona: Persona): boolean;
|
|
10
|
+
/** 解析 --persona:未给返回 undefined;未知值报 INVALID_ARGS(exit 2) */
|
|
11
|
+
export declare function parsePersona(raw: string | undefined): Persona | undefined;
|
|
12
|
+
//# sourceMappingURL=persona.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona.d.ts","sourceRoot":"","sources":["../../src/advisor/persona.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,eAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,EAAwB,CAAC;AAEhE,oCAAoC;AACpC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAIlD,CAAC;AAQF,gCAAgC;AAChC,wBAAgB,YAAY,CAAC,SAAS,EAAE;IAAE,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAK7G;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAKzE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// advisor 角色轴 --persona(S7 / 设计 §2.2 persona 通道)
|
|
2
|
+
//
|
|
3
|
+
// 四层分工里的「意图路由按角色分」:角色进排序特征,不进命名空间——同一查询在
|
|
4
|
+
// dev/qa/pm 三档下重排候选;未给 --persona 时维持现有排序(行为零变化)。
|
|
5
|
+
import { CliError } from '../errors.js';
|
|
6
|
+
export const PERSONAS = ['dev', 'qa', 'pm'];
|
|
7
|
+
/** 输出里的一行角色影响说明(中文,说明偏移方向而非实现细节) */
|
|
8
|
+
export const PERSONA_LABELS = {
|
|
9
|
+
dev: '开发视角:task/story/branch 类命令优先',
|
|
10
|
+
qa: '测试视角:bug/test-case/test-plan 类命令优先',
|
|
11
|
+
pm: 'PM 视角:pm 场景与 iteration/release/report 类命令优先',
|
|
12
|
+
};
|
|
13
|
+
// pm 角色对 pm 场景候选全量加权(kind 判定),对原子候选按资源词匹配
|
|
14
|
+
const PERSONA_ATOMIC_PATTERNS = {
|
|
15
|
+
dev: /\b(task|story|branch)\b/,
|
|
16
|
+
qa: /\b(bug|test-case|test-plan|test)\b/,
|
|
17
|
+
};
|
|
18
|
+
/** 候选是否命中角色偏好(参与重排的 +2 权重判定) */
|
|
19
|
+
export function personaBoost(candidate, persona) {
|
|
20
|
+
if (persona === 'pm') {
|
|
21
|
+
return candidate.kind === 'pm' || /\b(iteration|release|report)\b/.test(candidate.command);
|
|
22
|
+
}
|
|
23
|
+
return PERSONA_ATOMIC_PATTERNS[persona].test(candidate.command);
|
|
24
|
+
}
|
|
25
|
+
/** 解析 --persona:未给返回 undefined;未知值报 INVALID_ARGS(exit 2) */
|
|
26
|
+
export function parsePersona(raw) {
|
|
27
|
+
if (raw === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
const value = raw.trim().toLowerCase();
|
|
30
|
+
if (PERSONAS.includes(value))
|
|
31
|
+
return value;
|
|
32
|
+
throw new CliError('INVALID_ARGS', `未知 persona "${raw}",可选: ${PERSONAS.join('|')}(角色进排序特征,不进命名空间)`);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=persona.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona.js","sourceRoot":"","sources":["../../src/advisor/persona.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,yCAAyC;AACzC,iDAAiD;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,CAAC,MAAM,QAAQ,GAAuB,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEhE,oCAAoC;AACpC,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,GAAG,EAAE,8BAA8B;IACnC,EAAE,EAAE,oCAAoC;IACxC,EAAE,EAAE,6CAA6C;CAClD,CAAC;AAEF,0CAA0C;AAC1C,MAAM,uBAAuB,GAA2C;IACtE,GAAG,EAAE,yBAAyB;IAC9B,EAAE,EAAE,oCAAoC;CACzC,CAAC;AAEF,gCAAgC;AAChC,MAAM,UAAU,YAAY,CAAC,SAAqD,EAAE,OAAgB;IAClG,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC,IAAI,KAAK,IAAI,IAAI,gCAAgC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,uBAAuB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAClE,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,YAAY,CAAC,GAAuB;IAClD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvC,IAAK,QAA8B,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAgB,CAAC;IAC7E,MAAM,IAAI,QAAQ,CAAC,cAAc,EAAE,eAAe,GAAG,SAAS,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AACtG,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AdvisorEntry } from '@xihe-lab/tapd-core';
|
|
2
|
+
import { type PmCatalog } from '../pm/index.js';
|
|
3
|
+
import { type Persona } from './persona.js';
|
|
4
|
+
export interface AdvisorCandidate {
|
|
5
|
+
/** 原子命令 '<resource> <action>';pm 场景为 'pm <domain> <scenario>' */
|
|
6
|
+
command: string;
|
|
7
|
+
description: string;
|
|
8
|
+
write: boolean;
|
|
9
|
+
/** core 召回分(仅原子候选有含义;pm 场景候选为规则置顶,固定 0) */
|
|
10
|
+
score: number;
|
|
11
|
+
/** 域特征:pm 场景为 [frontmatter domain];原子候选来自关键词扫描,可多域;无命中为 [] */
|
|
12
|
+
domains: string[];
|
|
13
|
+
kind: 'pm' | 'atomic';
|
|
14
|
+
/** 原子候选对应的底层工具名(pm 场景无) */
|
|
15
|
+
tool?: string;
|
|
16
|
+
/** pm 场景候选附执行方式提示 */
|
|
17
|
+
usage?: string;
|
|
18
|
+
/** pm 模板来源(builtin/用户覆盖) */
|
|
19
|
+
source?: 'builtin' | 'user';
|
|
20
|
+
}
|
|
21
|
+
export interface AdviseOptions {
|
|
22
|
+
persona?: Persona;
|
|
23
|
+
limit?: number;
|
|
24
|
+
/** 注入 pm 目录(测试/复用);缺省 discoverPmTemplates() 动态发现 */
|
|
25
|
+
catalog?: PmCatalog;
|
|
26
|
+
}
|
|
27
|
+
export interface AdviseResult {
|
|
28
|
+
hits: AdvisorCandidate[];
|
|
29
|
+
/** 查询命中的域键(按域表序);空 = 未命中域轴 */
|
|
30
|
+
matchedDomains: string[];
|
|
31
|
+
persona?: Persona;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 域轴召回 + persona 重排。
|
|
35
|
+
* 返回截断到 limit 的候选;matchedDomains 供输出层说明域命中情况。
|
|
36
|
+
*/
|
|
37
|
+
export declare function advise(query: string, index: AdvisorEntry[], options?: AdviseOptions): AdviseResult;
|
|
38
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/advisor/recall.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,qBAAqB,CAAC;AAGpE,OAAO,EAAuB,KAAK,SAAS,EAAwB,MAAM,gBAAgB,CAAC;AAE3F,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAO1D,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC;IACtB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,EAAE,CAAC;IACzB,8BAA8B;IAC9B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA2BD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,YAAY,CAgDtG"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// advisor 域轴召回 + 角色重排(S7 本体)
|
|
2
|
+
//
|
|
3
|
+
// 召回优先级(设计 §4 / 验收 5):
|
|
4
|
+
// 1. 查询命中域关键词 → 该域的 `tapd pm <domain> <scenario>` 候选置顶
|
|
5
|
+
// (场景清单从 pm/discovery 动态取,模板未收录的域自动跳过,不报错);
|
|
6
|
+
// 2. 原子命令候选沿用 core advisor 召回逻辑(recommend),每条附 domain 特征;
|
|
7
|
+
// 域命中的原子候选在原子块内稳定前移(domain 作为排序特征的预演,F9 完整版再深化)。
|
|
8
|
+
// 3. --persona 在上述基础上按角色加权重排;无 persona 时维持现有排序。
|
|
9
|
+
//
|
|
10
|
+
// 权重合成:boost = 域命中(pm 场景 +2 / 原子 +1) + persona 命中(+2),同为稳定键,
|
|
11
|
+
// boost 同分按池内序(pm 池在前、原子池按 recommend 顺序)——保证确定性输出。
|
|
12
|
+
import { recommend } from '@xihe-lab/tapd-core';
|
|
13
|
+
import { domainLabel } from '../pm/index.js';
|
|
14
|
+
import { discoverPmTemplates } from '../pm/index.js';
|
|
15
|
+
import { candidateFeatureText, domainsInText, matchQueryDomains } from './domain-axis.js';
|
|
16
|
+
import { personaBoost } from './persona.js';
|
|
17
|
+
const DEFAULT_LIMIT = 10;
|
|
18
|
+
/** 原子召回池放大系数:给 persona/域重排留出上浮空间,最终仍截断到 limit */
|
|
19
|
+
const POOL_FACTOR = 4;
|
|
20
|
+
const MIN_POOL = 40;
|
|
21
|
+
function pmCandidate(entry) {
|
|
22
|
+
return {
|
|
23
|
+
command: `pm ${entry.domain} ${entry.scenario}`,
|
|
24
|
+
description: entry.title || `${domainLabel(entry.domain)}场景`,
|
|
25
|
+
write: entry.write,
|
|
26
|
+
score: 0,
|
|
27
|
+
domains: [entry.domain],
|
|
28
|
+
kind: 'pm',
|
|
29
|
+
usage: `tapd pm ${entry.domain} ${entry.scenario} [--iteration <id>] [--dry-run]${entry.write ? ' [--yes]' : ''}`,
|
|
30
|
+
source: entry.source,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function atomicCandidate(hit) {
|
|
34
|
+
return {
|
|
35
|
+
command: hit.command,
|
|
36
|
+
description: hit.description,
|
|
37
|
+
write: hit.write,
|
|
38
|
+
score: hit.score,
|
|
39
|
+
domains: domainsInText(candidateFeatureText(hit.command, hit.description)),
|
|
40
|
+
kind: 'atomic',
|
|
41
|
+
tool: hit.tool,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 域轴召回 + persona 重排。
|
|
46
|
+
* 返回截断到 limit 的候选;matchedDomains 供输出层说明域命中情况。
|
|
47
|
+
*/
|
|
48
|
+
export function advise(query, index, options = {}) {
|
|
49
|
+
const persona = options.persona;
|
|
50
|
+
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
51
|
+
const matchedDomains = matchQueryDomains(query);
|
|
52
|
+
// ---- pm 场景池:域命中取命中域;未命中域时仅 pm 角色注入全量场景(否则不入池) ----
|
|
53
|
+
const catalog = options.catalog ?? discoverPmTemplates();
|
|
54
|
+
let pmEntries;
|
|
55
|
+
if (matchedDomains.length > 0) {
|
|
56
|
+
const orderOf = new Map(matchedDomains.map((d, i) => [d, i]));
|
|
57
|
+
pmEntries = catalog.entries
|
|
58
|
+
.filter(e => orderOf.has(e.domain))
|
|
59
|
+
.sort((a, b) => (orderOf.get(a.domain) - orderOf.get(b.domain)) || a.scenario.localeCompare(b.scenario));
|
|
60
|
+
}
|
|
61
|
+
else if (persona === 'pm') {
|
|
62
|
+
pmEntries = catalog.entries;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
pmEntries = [];
|
|
66
|
+
}
|
|
67
|
+
// ---- 原子池:现有 recommend 召回逻辑,池放大后参与统一重排 ----
|
|
68
|
+
const poolLimit = Math.max(limit * POOL_FACTOR, MIN_POOL);
|
|
69
|
+
const atomicHits = recommend(query, index, poolLimit);
|
|
70
|
+
const pmCandidates = pmEntries.map(pmCandidate);
|
|
71
|
+
const atomicCandidates = atomicHits.map(atomicCandidate);
|
|
72
|
+
const pmCount = pmCandidates.length;
|
|
73
|
+
const scored = [
|
|
74
|
+
...pmCandidates.map((candidate, i) => ({ candidate, base: i })),
|
|
75
|
+
...atomicCandidates.map((candidate, j) => ({ candidate, base: pmCount + j })),
|
|
76
|
+
].map(({ candidate, base }) => {
|
|
77
|
+
let boost = 0;
|
|
78
|
+
if (candidate.kind === 'pm') {
|
|
79
|
+
if (matchedDomains.includes(candidate.domains[0] ?? ''))
|
|
80
|
+
boost += 2;
|
|
81
|
+
}
|
|
82
|
+
else if (candidate.domains.some(d => matchedDomains.includes(d))) {
|
|
83
|
+
boost += 1;
|
|
84
|
+
}
|
|
85
|
+
if (persona && personaBoost(candidate, persona))
|
|
86
|
+
boost += 2;
|
|
87
|
+
return { candidate, base, boost };
|
|
88
|
+
});
|
|
89
|
+
scored.sort((a, b) => b.boost - a.boost || a.base - b.base);
|
|
90
|
+
return {
|
|
91
|
+
hits: scored.slice(0, limit).map(({ candidate }) => candidate),
|
|
92
|
+
matchedDomains,
|
|
93
|
+
...(persona ? { persona } : {}),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.js","sourceRoot":"","sources":["../../src/advisor/recall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AdvisorCandidate, AdviseResult } from './recall.js';
|
|
2
|
+
/** 与旧版一致的 COMMAND/WRITE/DESCRIPTION 三列,新增 DOMAIN 特征列 */
|
|
3
|
+
export declare function renderAdvisorTable(hits: AdvisorCandidate[]): string;
|
|
4
|
+
/** 补充说明行:域命中情况、persona 影响一句话、pm 场景执行方式 */
|
|
5
|
+
export declare function advisorNotes(result: AdviseResult): string[];
|
|
6
|
+
/** JSON 口径:沿用旧版裸数组(command/description/write/score/tool),扩展 kind/domains/usage */
|
|
7
|
+
export declare function advisorJson(hits: AdvisorCandidate[]): string;
|
|
8
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/advisor/render.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAElE,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAQnE;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,CAc3D;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAgB5D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// advisor 输出渲染(S7):沿用现有 advisor 表格口径并扩展域/persona 说明行
|
|
2
|
+
import { renderTable } from '../output/table.js';
|
|
3
|
+
import { PERSONA_LABELS } from './persona.js';
|
|
4
|
+
/** 与旧版一致的 COMMAND/WRITE/DESCRIPTION 三列,新增 DOMAIN 特征列 */
|
|
5
|
+
export function renderAdvisorTable(hits) {
|
|
6
|
+
const rows = hits.map(hit => ({
|
|
7
|
+
COMMAND: hit.command,
|
|
8
|
+
WRITE: hit.write ? '✓' : '',
|
|
9
|
+
DOMAIN: hit.domains.join('/'),
|
|
10
|
+
DESCRIPTION: hit.description,
|
|
11
|
+
}));
|
|
12
|
+
return renderTable(rows, ['COMMAND', 'WRITE', 'DOMAIN', 'DESCRIPTION']);
|
|
13
|
+
}
|
|
14
|
+
/** 补充说明行:域命中情况、persona 影响一句话、pm 场景执行方式 */
|
|
15
|
+
export function advisorNotes(result) {
|
|
16
|
+
const notes = [];
|
|
17
|
+
if (result.matchedDomains.length > 0) {
|
|
18
|
+
notes.push(`domain: 命中知识域 ${result.matchedDomains.join(' / ')} —— pm 场景候选置顶(未收录模板的域自动跳过)`);
|
|
19
|
+
}
|
|
20
|
+
if (result.persona) {
|
|
21
|
+
notes.push(`persona: ${result.persona} —— ${PERSONA_LABELS[result.persona]}`);
|
|
22
|
+
}
|
|
23
|
+
if (result.hits.some(hit => hit.kind === 'pm')) {
|
|
24
|
+
notes.push('pm 场景执行: tapd pm <domain> <scenario> [--iteration <id>] [--dry-run] [--yes]');
|
|
25
|
+
}
|
|
26
|
+
return notes;
|
|
27
|
+
}
|
|
28
|
+
/** JSON 口径:沿用旧版裸数组(command/description/write/score/tool),扩展 kind/domains/usage */
|
|
29
|
+
export function advisorJson(hits) {
|
|
30
|
+
return JSON.stringify(hits.map(hit => ({
|
|
31
|
+
...(hit.tool !== undefined ? { tool: hit.tool } : {}),
|
|
32
|
+
command: hit.command,
|
|
33
|
+
description: hit.description,
|
|
34
|
+
write: hit.write,
|
|
35
|
+
score: hit.score,
|
|
36
|
+
kind: hit.kind,
|
|
37
|
+
domains: hit.domains,
|
|
38
|
+
...(hit.usage !== undefined ? { usage: hit.usage } : {}),
|
|
39
|
+
...(hit.source !== undefined ? { source: hit.source } : {}),
|
|
40
|
+
})), null, 2) + '\n';
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=render.js.map
|