@xihe-lab/tapd-cli 2.0.0-rc.4 → 2.0.0-rc.6

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.
Files changed (71) hide show
  1. package/LICENSE +16 -4
  2. package/README.md +13 -1
  3. package/package.json +7 -4
  4. package/dist/advisor/domain-axis.test.d.ts +0 -2
  5. package/dist/advisor/domain-axis.test.d.ts.map +0 -1
  6. package/dist/advisor/domain-axis.test.js +0 -198
  7. package/dist/advisor/domain-axis.test.js.map +0 -1
  8. package/dist/flags.test.d.ts +0 -2
  9. package/dist/flags.test.d.ts.map +0 -1
  10. package/dist/flags.test.js +0 -56
  11. package/dist/flags.test.js.map +0 -1
  12. package/dist/output/formatter.test.d.ts +0 -2
  13. package/dist/output/formatter.test.d.ts.map +0 -1
  14. package/dist/output/formatter.test.js +0 -170
  15. package/dist/output/formatter.test.js.map +0 -1
  16. package/dist/pipeline/engine.test.d.ts +0 -2
  17. package/dist/pipeline/engine.test.d.ts.map +0 -1
  18. package/dist/pipeline/engine.test.js +0 -419
  19. package/dist/pipeline/engine.test.js.map +0 -1
  20. package/dist/pipeline/expression.test.d.ts +0 -2
  21. package/dist/pipeline/expression.test.d.ts.map +0 -1
  22. package/dist/pipeline/expression.test.js +0 -111
  23. package/dist/pipeline/expression.test.js.map +0 -1
  24. package/dist/pipeline/record.test.d.ts +0 -2
  25. package/dist/pipeline/record.test.d.ts.map +0 -1
  26. package/dist/pipeline/record.test.js +0 -109
  27. package/dist/pipeline/record.test.js.map +0 -1
  28. package/dist/pipeline/template.test.d.ts +0 -2
  29. package/dist/pipeline/template.test.d.ts.map +0 -1
  30. package/dist/pipeline/template.test.js +0 -94
  31. package/dist/pipeline/template.test.js.map +0 -1
  32. package/dist/pipeline/unwrap.test.d.ts +0 -2
  33. package/dist/pipeline/unwrap.test.d.ts.map +0 -1
  34. package/dist/pipeline/unwrap.test.js +0 -36
  35. package/dist/pipeline/unwrap.test.js.map +0 -1
  36. package/dist/pipeline/validate.test.d.ts +0 -2
  37. package/dist/pipeline/validate.test.d.ts.map +0 -1
  38. package/dist/pipeline/validate.test.js +0 -166
  39. package/dist/pipeline/validate.test.js.map +0 -1
  40. package/dist/pm/discovery.test.d.ts +0 -2
  41. package/dist/pm/discovery.test.d.ts.map +0 -1
  42. package/dist/pm/discovery.test.js +0 -147
  43. package/dist/pm/discovery.test.js.map +0 -1
  44. package/dist/pm/domains.test.d.ts +0 -2
  45. package/dist/pm/domains.test.d.ts.map +0 -1
  46. package/dist/pm/domains.test.js +0 -141
  47. package/dist/pm/domains.test.js.map +0 -1
  48. package/dist/pm/iteration.test.d.ts +0 -2
  49. package/dist/pm/iteration.test.d.ts.map +0 -1
  50. package/dist/pm/iteration.test.js +0 -125
  51. package/dist/pm/iteration.test.js.map +0 -1
  52. package/dist/pm/pm-command.test.d.ts +0 -2
  53. package/dist/pm/pm-command.test.d.ts.map +0 -1
  54. package/dist/pm/pm-command.test.js +0 -321
  55. package/dist/pm/pm-command.test.js.map +0 -1
  56. package/dist/pm/tpl-communication-stakeholder.test.d.ts +0 -2
  57. package/dist/pm/tpl-communication-stakeholder.test.d.ts.map +0 -1
  58. package/dist/pm/tpl-communication-stakeholder.test.js +0 -392
  59. package/dist/pm/tpl-communication-stakeholder.test.js.map +0 -1
  60. package/dist/pm/tpl-integration-scope.test.d.ts +0 -2
  61. package/dist/pm/tpl-integration-scope.test.d.ts.map +0 -1
  62. package/dist/pm/tpl-integration-scope.test.js +0 -387
  63. package/dist/pm/tpl-integration-scope.test.js.map +0 -1
  64. package/dist/pm/tpl-quality-risk.test.d.ts +0 -2
  65. package/dist/pm/tpl-quality-risk.test.d.ts.map +0 -1
  66. package/dist/pm/tpl-quality-risk.test.js +0 -414
  67. package/dist/pm/tpl-quality-risk.test.js.map +0 -1
  68. package/dist/pm/tpl-schedule-cost.test.d.ts +0 -2
  69. package/dist/pm/tpl-schedule-cost.test.d.ts.map +0 -1
  70. package/dist/pm/tpl-schedule-cost.test.js +0 -376
  71. package/dist/pm/tpl-schedule-cost.test.js.map +0 -1
@@ -1,109 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import path from 'node:path';
5
- import { allTools, ToolRegistry, resolveWrite } from '@xihe-lab/tapd-core';
6
- import YAML from 'yaml';
7
- import { historyPath, readHistory, recordCommandHistory } from './history.js';
8
- import { buildTemplateFromHistory, renderTemplateYaml } from './record.js';
9
- import { parseTemplate, resolveTemplatePath } from './template.js';
10
- import { validateTemplate } from './validate.js';
11
- const sandboxDir = mkdtempSync(path.join(tmpdir(), 'tapd-history-test-'));
12
- const sandboxFile = path.join(sandboxDir, 'history.jsonl');
13
- const originalPath = process.env.TAPD_HISTORY_PATH;
14
- process.env.TAPD_HISTORY_PATH = sandboxFile;
15
- const registry = new ToolRegistry();
16
- registry.register(allTools);
17
- const audit = (tool, ok = true) => ({
18
- ts: new Date().toISOString(),
19
- entry: 'cli',
20
- tool,
21
- args: { id: '1001' },
22
- ok,
23
- durationMs: 5,
24
- });
25
- const checks = [
26
- ['recordCommandHistory: 成功命令追加 JSONL,失败命令不记录', () => {
27
- recordCommandHistory(audit('tapd_get_stories'));
28
- recordCommandHistory(audit('tapd_update_story'));
29
- recordCommandHistory(audit('tapd_get_bugs', false));
30
- const entries = readHistory(10);
31
- assert.deepEqual(entries.map(e => e.tool), ['tapd_get_stories', 'tapd_update_story']);
32
- assert.equal(entries[0].args.id, '1001');
33
- assert.ok(historyPath().startsWith(sandboxDir));
34
- }],
35
- ['readHistory: --last 截取最近 N 条', () => {
36
- const entries = readHistory(1);
37
- assert.equal(entries.length, 1);
38
- assert.equal(entries[0].tool, 'tapd_update_story');
39
- }],
40
- ['readHistory: 损坏行被跳过', () => {
41
- writeFileSync(sandboxFile, readHistory(10).map(e => JSON.stringify(e)).concat('{broken').join('\n') + '\n');
42
- assert.equal(readHistory(10).length, 2);
43
- }],
44
- ['buildTemplateFromHistory: 写命令经 write-policy 判定 → 模板自动 write: true', () => {
45
- const entries = readHistory(10);
46
- const isWrite = (tool) => {
47
- const def = registry.get(tool);
48
- return def ? resolveWrite(def) : false;
49
- };
50
- const template = buildTemplateFromHistory(entries, { name: 'recorded', title: '录制' }, isWrite);
51
- assert.equal(template.write, true, 'tapd_update_story 命中写策略');
52
- assert.equal(template.name, 'recorded');
53
- assert.equal(template.steps.length, 2);
54
- assert.equal(template.steps[1].uses, 'tapd_update_story');
55
- }],
56
- ['buildTemplateFromHistory: 全只读历史 → 模板不带 write 标记', () => {
57
- const isWrite = (tool) => {
58
- const def = registry.get(tool);
59
- return def ? resolveWrite(def) : false;
60
- };
61
- const template = buildTemplateFromHistory([{ ts: 't', tool: 'tapd_get_bugs', args: {}, durationMs: 1 }], { name: 'read-only-rec' }, isWrite);
62
- assert.equal(template.write, undefined);
63
- }],
64
- ['录制产物闭环: record → yaml → parse → validate 全绿', () => {
65
- const isWrite = (tool) => {
66
- const def = registry.get(tool);
67
- return def ? resolveWrite(def) : false;
68
- };
69
- const template = buildTemplateFromHistory(readHistory(10), { name: 'recorded-roundtrip' }, isWrite);
70
- const yaml = renderTemplateYaml(template);
71
- const reparsed = parseTemplate(yaml, 'roundtrip');
72
- assert.equal(reparsed.name, 'recorded-roundtrip');
73
- const result = validateTemplate(reparsed, registry);
74
- assert.equal(result.ok, true, JSON.stringify(result.errors));
75
- const roundtrip = YAML.parse(yaml);
76
- assert.equal(roundtrip.steps[0].args.id, '1001');
77
- }],
78
- ['resolveTemplatePath: 录制产物写入内置目录后可用裸名解析(临时目录模拟)', () => {
79
- // 不真的写入包目录(避免污染仓库),只验证解析逻辑对扩展名回退的行为
80
- assert.throws(() => resolveTemplatePath('definitely-not-a-template'), Error);
81
- }],
82
- ];
83
- let failed = 0;
84
- try {
85
- for (const [name, fn] of checks) {
86
- try {
87
- await fn();
88
- console.log(`ok - ${name}`);
89
- }
90
- catch (error) {
91
- failed++;
92
- console.error(`FAIL - ${name}`);
93
- console.error(error);
94
- }
95
- }
96
- }
97
- finally {
98
- if (originalPath === undefined)
99
- delete process.env.TAPD_HISTORY_PATH;
100
- else
101
- process.env.TAPD_HISTORY_PATH = originalPath;
102
- rmSync(sandboxDir, { recursive: true, force: true });
103
- }
104
- if (failed > 0) {
105
- console.error(`\n${failed}/${checks.length} failed`);
106
- process.exit(1);
107
- }
108
- console.log(`\n${checks.length}/${checks.length} passed`);
109
- //# sourceMappingURL=record.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"record.test.js","sourceRoot":"","sources":["../../src/pipeline/record.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=template.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"template.test.d.ts","sourceRoot":"","sources":["../../src/pipeline/template.test.ts"],"names":[],"mappings":""}
@@ -1,94 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { listBuiltinTemplates, parseTemplate, resolveTemplatePath } from './template.js';
3
- import { PipelineError } from './types.js';
4
- const checks = [
5
- ['parseTemplate: 合法模板完整解析(name/title/write/vars/steps/report)', () => {
6
- const tpl = parseTemplate(`
7
- name: demo
8
- title: 演示模板
9
- write: true
10
- vars:
11
- iteration_id: "1001"
12
- steps:
13
- - id: a
14
- uses: tapd_get_stories
15
- args: { iteration_id: "${'$'}{vars.iteration_id}" }
16
- filter: "!item.name.startsWith('zzz')"
17
- - id: b
18
- uses: tapd_update_story
19
- args: { id: "1", status: developing }
20
- depends_on: [a]
21
- report:
22
- format: markdown
23
- template: |
24
- # 报告 ${'$'}{steps.a.data | length}
25
- `, 'inline');
26
- assert.equal(tpl.name, 'demo');
27
- assert.equal(tpl.write, true);
28
- assert.equal(tpl.vars?.iteration_id, '1001');
29
- assert.equal(tpl.steps.length, 2);
30
- assert.equal(tpl.steps[1].depends_on?.[0], 'a');
31
- assert.equal(tpl.report?.format, 'markdown');
32
- }],
33
- ['parseTemplate: json 源同样可解析(YAML 是 JSON 超集)', () => {
34
- const tpl = parseTemplate(JSON.stringify({ name: 'j', steps: [{ id: 's', uses: 'tapd_get_bugs' }] }), 'inline');
35
- assert.equal(tpl.name, 'j');
36
- assert.equal(tpl.steps[0].uses, 'tapd_get_bugs');
37
- }],
38
- ['parseTemplate: yaml 语法错误 → TEMPLATE_INVALID', () => {
39
- assert.throws(() => parseTemplate('name: [unclosed', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
40
- }],
41
- ['parseTemplate: 缺 name / 空 steps → TEMPLATE_INVALID', () => {
42
- assert.throws(() => parseTemplate('steps: [{ id: a, uses: x }]', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
43
- assert.throws(() => parseTemplate('name: demo, steps: []'.replace(',', '\n'), 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
44
- }],
45
- ['parseTemplate: 步骤缺 uses/expr 或两者同存 → TEMPLATE_INVALID', () => {
46
- assert.throws(() => parseTemplate('name: d\nsteps:\n - id: a\n args: {}', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
47
- assert.throws(() => parseTemplate('name: d\nsteps:\n - id: a\n uses: tapd_get_bugs\n expr: "1+1"', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
48
- }],
49
- ['parseTemplate: 步骤 id 重复 → TEMPLATE_INVALID', () => {
50
- assert.throws(() => parseTemplate('name: d\nsteps:\n - id: a\n uses: tapd_get_bugs\n - id: a\n uses: tapd_get_bugs', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
51
- }],
52
- ['parseTemplate: depends_on 指向缺失步骤 → TEMPLATE_INVALID', () => {
53
- assert.throws(() => parseTemplate('name: d\nsteps:\n - id: a\n uses: tapd_get_bugs\n depends_on: [ghost]', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
54
- }],
55
- ['parseTemplate: 未知顶层字段 → TEMPLATE_INVALID(strict)', () => {
56
- assert.throws(() => parseTemplate('name: d\nsteps:\n - id: a\n uses: tapd_get_bugs\nbogus: 1', 'inline'), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
57
- }],
58
- ['resolveTemplatePath: 内置模板裸名与 templates/ 相对名都可解析', () => {
59
- const bare = resolveTemplatePath('iteration-review');
60
- const rel = resolveTemplatePath('templates/iteration-review.yaml');
61
- assert.ok(bare.endsWith('templates/iteration-review.yaml'), bare);
62
- assert.equal(bare, rel);
63
- }],
64
- ['resolveTemplatePath: 找不到 → IO 错误并列出尝试路径', () => {
65
- assert.throws(() => resolveTemplatePath('no-such-template'), (error) => error instanceof PipelineError && error.code === 'IO' && error.message.includes('no-such-template'));
66
- }],
67
- ['listBuiltinTemplates: 三个内置模板齐全且声明正确的 write 标记', () => {
68
- const list = listBuiltinTemplates();
69
- const byName = Object.fromEntries(list.map(t => [t.name, t]));
70
- assert.deepEqual(Object.keys(byName).sort(), ['deliver-story', 'iteration-review', 'triage-bugs']);
71
- assert.equal(byName['iteration-review'].write, false);
72
- assert.equal(byName['deliver-story'].write, true);
73
- assert.equal(byName['triage-bugs'].write, true);
74
- assert.ok(byName['iteration-review'].title.length > 0);
75
- }],
76
- ];
77
- let failed = 0;
78
- for (const [name, fn] of checks) {
79
- try {
80
- await fn();
81
- console.log(`ok - ${name}`);
82
- }
83
- catch (error) {
84
- failed++;
85
- console.error(`FAIL - ${name}`);
86
- console.error(error);
87
- }
88
- }
89
- if (failed > 0) {
90
- console.error(`\n${failed}/${checks.length} failed`);
91
- process.exit(1);
92
- }
93
- console.log(`\n${checks.length}/${checks.length} passed`);
94
- //# sourceMappingURL=template.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"template.test.js","sourceRoot":"","sources":["../../src/pipeline/template.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=unwrap.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unwrap.test.d.ts","sourceRoot":"","sources":["../../src/pipeline/unwrap.test.ts"],"names":[],"mappings":""}
@@ -1,36 +0,0 @@
1
- // unwrapEntities 单元测试:TAPD 包裹形态拍平(真机 L2 冒烟暴露的形态差异,2026-09-11)
2
- import { test } from 'node:test';
3
- import assert from 'node:assert/strict';
4
- import { unwrapEntities } from './unwrap.js';
5
- void test('数组逐项解包并附 __entity', () => {
6
- const data = [
7
- { Story: { id: '1', name: 'a' } },
8
- { Story: { id: '2', name: 'b' } },
9
- ];
10
- assert.deepEqual(unwrapEntities(data), [
11
- { id: '1', name: 'a', __entity: 'Story' },
12
- { id: '2', name: 'b', __entity: 'Story' },
13
- ]);
14
- });
15
- void test('单对象解包(按 id 查询返回)', () => {
16
- assert.deepEqual(unwrapEntities({ Iteration: { id: '9', name: 'it' } }), { id: '9', name: 'it', __entity: 'Iteration' });
17
- });
18
- void test('小写单键对象不动(count 等非实体形态)', () => {
19
- assert.deepEqual(unwrapEntities({ count: 3 }), { count: 3 });
20
- assert.equal(unwrapEntities(42), 42);
21
- assert.equal(unwrapEntities('x'), 'x');
22
- assert.equal(unwrapEntities(null), null);
23
- });
24
- void test('多键对象不动(已扁平/混合形态)', () => {
25
- const flat = { id: '1', name: 'a', status: 'planning' };
26
- assert.deepEqual(unwrapEntities(flat), flat);
27
- });
28
- void test('包裹值为标量不动(单键值为原始类型的陷阱形态)', () => {
29
- assert.deepEqual(unwrapEntities({ Code: 'x' }), { Code: 'x' });
30
- });
31
- void test('混合数组:能解的解,不能解的保原样', () => {
32
- const out = unwrapEntities([{ Bug: { id: '1' } }, { note: 'plain' }]);
33
- assert.deepEqual(out[0], { id: '1', __entity: 'Bug' });
34
- assert.deepEqual(out[1], { note: 'plain' });
35
- });
36
- //# sourceMappingURL=unwrap.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unwrap.test.js","sourceRoot":"","sources":["../../src/pipeline/unwrap.test.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,KAAK,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAClC,MAAM,IAAI,GAAG;QACX,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACjC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;KAClC,CAAC;IACF,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE;QACrC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE;QACzC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE;KAC1C,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,KAAK,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE;IACjC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;AAC3H,CAAC,CAAC,CAAC;AAEH,KAAK,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACvC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,KAAK,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE;IACjC,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACxD,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEH,KAAK,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACxC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,KAAK,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAClC,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAA8B,CAAC;IACnG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=validate.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../src/pipeline/validate.test.ts"],"names":[],"mappings":""}
@@ -1,166 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import { readFileSync } from 'node:fs';
3
- import { allTools, ToolRegistry } from '@xihe-lab/tapd-core';
4
- import { validateTemplate } from './validate.js';
5
- import { parseTemplate } from './template.js';
6
- const registry = new ToolRegistry();
7
- registry.register(allTools);
8
- function validate(yaml) {
9
- return validateTemplate(parseTemplate(yaml, 'inline'), registry);
10
- }
11
- const checks = [
12
- ['validate: 合法只读模板通过且 writeSteps 为空', () => {
13
- const result = validate(`
14
- name: ok-read
15
- write: false
16
- steps:
17
- - id: stories
18
- uses: tapd_get_stories
19
- args: { iteration_id: "1001", limit: 5 }
20
- `);
21
- assert.equal(result.ok, true, JSON.stringify(result.errors));
22
- assert.deepEqual(result.writeSteps, []);
23
- }],
24
- ['validate: 未知命令 → error 且 target 指向 uses', () => {
25
- const result = validate(`
26
- name: bad-tool
27
- write: false
28
- steps:
29
- - id: a
30
- uses: tapd_totally_missing
31
- `);
32
- assert.equal(result.ok, false);
33
- assert.ok(result.errors.some(e => e.target === 'steps.a.uses' && e.message.includes('tapd_totally_missing')));
34
- }],
35
- ['validate: 参数不符 zod schema → error(limit 传字符串)', () => {
36
- const result = validate(`
37
- name: bad-args
38
- write: false
39
- steps:
40
- - id: a
41
- uses: tapd_get_stories
42
- args: { limit: "not-a-number" }
43
- `);
44
- assert.equal(result.ok, false);
45
- const issue = result.errors.find(e => e.target === 'steps.a.args.limit');
46
- assert.ok(issue, JSON.stringify(result.errors));
47
- assert.ok(issue.message.includes('参数不符 schema'));
48
- }],
49
- ['validate: 未知参数名 → error(schema 不包含该字段)', () => {
50
- const result = validate(`
51
- name: unknown-key
52
- write: false
53
- steps:
54
- - id: a
55
- uses: tapd_get_stories
56
- args: { bogus_param: 1 }
57
- `);
58
- assert.equal(result.ok, false);
59
- assert.ok(result.errors.some(e => e.target === 'steps.a.args.bogus_param'));
60
- }],
61
- ['validate: 必填参数缺失 → error(tapd_update_story 缺 id)', () => {
62
- const result = validate(`
63
- name: missing-required
64
- write: true
65
- steps:
66
- - id: a
67
- uses: tapd_update_story
68
- args: { status: developing }
69
- `);
70
- assert.equal(result.ok, false);
71
- const issue = result.errors.find(e => e.target === 'steps.a.args.id');
72
- assert.ok(issue, JSON.stringify(result.errors));
73
- }],
74
- ['validate: 必填参数为步骤间延迟引用 → 跳过静态检查不误报', () => {
75
- const result = validate(`
76
- name: deferred-ok
77
- write: true
78
- steps:
79
- - id: fetch
80
- uses: tapd_get_stories
81
- args: { iteration_id: "1" }
82
- - id: patch
83
- uses: tapd_update_story
84
- args: { id: "${'$'}{steps.fetch.data.0.id}", status: developing }
85
- depends_on: [fetch]
86
- `);
87
- assert.deepEqual(result.writeSteps, ['patch']);
88
- assert.equal(result.ok, true, JSON.stringify(result.errors));
89
- }],
90
- ['validate: 含写步骤未声明 write: true → WRITE_MARKER_MISSING 语义错误', () => {
91
- const result = validate(`
92
- name: unmarked-write
93
- steps:
94
- - id: a
95
- uses: tapd_update_story
96
- args: { id: "1", status: developing }
97
- `);
98
- assert.equal(result.ok, false);
99
- const issue = result.errors.find(e => e.target === 'write');
100
- assert.ok(issue, JSON.stringify(result.errors));
101
- assert.ok(issue.message.includes('write: true') && issue.message.includes('a'));
102
- }],
103
- ['validate: 声明 write: true 但全只读 → warning 不阻塞', () => {
104
- const result = validate(`
105
- name: overmarked
106
- write: true
107
- steps:
108
- - id: a
109
- uses: tapd_get_stories
110
- args: { iteration_id: "1" }
111
- `);
112
- assert.equal(result.ok, true);
113
- assert.ok(result.warnings.some(w => w.target === 'write'));
114
- }],
115
- ['validate: 三个内置模板全部通过(写模板正确声明 write)', () => {
116
- for (const name of ['deliver-story', 'triage-bugs', 'iteration-review']) {
117
- // 经文件系统加载,覆盖 builtinTemplatesDir 相对路径推导(src/pipeline → ../../templates)
118
- const source = readFileSync(new URL(`../../templates/${name}.yaml`, import.meta.url), 'utf8');
119
- const template = parseTemplate(source, name);
120
- const result = validateTemplate(template, registry);
121
- assert.equal(result.ok, true, `${name}: ${JSON.stringify(result.errors)}`);
122
- }
123
- }],
124
- ['validate: 引用不存在的步骤 → REF_UNKNOWN 语义错误', () => {
125
- const result = validate(`
126
- name: bad-ref
127
- write: false
128
- steps:
129
- - id: a
130
- uses: tapd_get_stories
131
- args: { id: "${'$'}{steps.ghost.data.0.id}" }
132
- `);
133
- assert.equal(result.ok, false);
134
- assert.ok(result.errors.some(e => e.message.includes('ghost')));
135
- }],
136
- ['validate: where 表达式语法错误 → EXPR_ERROR 语义错误', () => {
137
- const result = validate(`
138
- name: bad-expr
139
- write: false
140
- steps:
141
- - id: a
142
- uses: tapd_get_stories
143
- where: "steps.a.data.length >"
144
- `);
145
- assert.equal(result.ok, false);
146
- assert.ok(result.errors.some(e => e.message.includes('表达式语法错误')));
147
- }],
148
- ];
149
- let failed = 0;
150
- for (const [name, fn] of checks) {
151
- try {
152
- await fn();
153
- console.log(`ok - ${name}`);
154
- }
155
- catch (error) {
156
- failed++;
157
- console.error(`FAIL - ${name}`);
158
- console.error(error);
159
- }
160
- }
161
- if (failed > 0) {
162
- console.error(`\n${failed}/${checks.length} failed`);
163
- process.exit(1);
164
- }
165
- console.log(`\n${checks.length}/${checks.length} passed`);
166
- //# sourceMappingURL=validate.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../src/pipeline/validate.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=discovery.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"discovery.test.d.ts","sourceRoot":"","sources":["../../src/pm/discovery.test.ts"],"names":[],"mappings":""}
@@ -1,147 +0,0 @@
1
- // pm 模板发现 / 用户覆盖 / 别名解析 / 元数据剥离测试(S2)
2
- // fixture 模板写在测试临时目录(TAPD_USER_TEMPLATES_DIR 注入),不污染 templates/pm/。
3
- import assert from 'node:assert/strict';
4
- import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
5
- import { tmpdir } from 'node:os';
6
- import path from 'node:path';
7
- import { PipelineError } from '../pipeline/types.js';
8
- import { CliError } from '../errors.js';
9
- import { discoverPmTemplates, loadPmTemplate, mergePmEntries, resolvePmEntry, userPmTemplatesDir, } from './discovery.js';
10
- import { builtinPmTemplatesDir } from './discovery.js';
11
- const RISK_SCAN = `# 多源风险扫描(fixture)
12
- name: risk-scan
13
- domain: risk
14
- title: 风险扫描(fixture)
15
- write: false
16
- vars:
17
- iteration_id: ""
18
- steps:
19
- - id: iterations
20
- uses: tapd_get_iterations
21
- args: { status: open, fields: "id,name,startdate" }
22
- filter: "!item.name.startsWith('zzz-delete-me')"
23
- - id: overdue
24
- uses: tapd_get_stories
25
- args: { iteration_id: "${'$'}{vars.iteration_id}" }
26
- `;
27
- const prevEnv = process.env.TAPD_USER_TEMPLATES_DIR;
28
- function makeEntry(partial) {
29
- return {
30
- domain: 'risk',
31
- scenario: 'scan',
32
- name: 'risk-scan',
33
- title: '',
34
- write: false,
35
- file: '/tmp/x.yaml',
36
- source: 'builtin',
37
- domainKnown: true,
38
- ...partial,
39
- };
40
- }
41
- const checks = [
42
- ['内置目录 = builtinTemplatesDir()/pm,用户目录默认 ~/.tapd/templates/pm', () => {
43
- assert.ok(builtinPmTemplatesDir().endsWith(path.join('templates', 'pm')));
44
- assert.ok(userPmTemplatesDir().endsWith(path.join('pm')));
45
- }],
46
- ['发现:扫描用户目录,frontmatter domain 命中域表;坏文件降级为 warning 不炸', () => {
47
- process.env.TAPD_USER_TEMPLATES_DIR = root;
48
- try {
49
- const catalog = discoverPmTemplates();
50
- const scan = catalog.entries.find(e => e.scenario === 'scan');
51
- assert.ok(scan, 'risk-scan 应被收录');
52
- assert.equal(scan.domain, 'risk');
53
- assert.equal(scan.domainKnown, true);
54
- assert.equal(scan.source, 'user');
55
- assert.equal(scan.write, false);
56
- assert.equal(scan.name, 'risk-scan');
57
- assert.equal(scan.title, '风险扫描(fixture)');
58
- // broken.yaml(非法 yaml)与 no-steps.yaml(缺 steps)只产 warning
59
- assert.equal(catalog.warnings.length, 2);
60
- assert.ok(catalog.warnings.some(w => w.includes('broken.yaml')));
61
- assert.ok(catalog.warnings.some(w => w.includes('no-steps.yaml')));
62
- // 自定义域 procurement:domainKnown=false,仍被收录(可执行,help 归「其他」)
63
- const audit = catalog.entries.find(e => e.scenario === 'audit');
64
- assert.ok(audit);
65
- assert.equal(audit.domain, 'procurement');
66
- assert.equal(audit.domainKnown, false);
67
- }
68
- finally {
69
- if (prevEnv === undefined)
70
- delete process.env.TAPD_USER_TEMPLATES_DIR;
71
- else
72
- process.env.TAPD_USER_TEMPLATES_DIR = prevEnv;
73
- }
74
- }],
75
- ['用户同名覆盖内置(mergePmEntries 同别名 user 胜出)', () => {
76
- const builtin = [
77
- makeEntry({ source: 'builtin', file: '/builtin/risk-scan.yaml' }),
78
- makeEntry({ domain: 'scope', scenario: 'drift-check', name: 'scope-drift-check', file: '/builtin/scope-drift-check.yaml' }),
79
- ];
80
- const user = [makeEntry({ source: 'user', file: '/user/risk-scan.yaml', title: '用户版' })];
81
- const merged = mergePmEntries(builtin, user);
82
- assert.equal(merged.length, 2, '同别名只保留一份');
83
- const scan = merged.find(e => e.scenario === 'scan');
84
- assert.equal(scan.source, 'user');
85
- assert.equal(scan.title, '用户版');
86
- assert.equal(merged.find(e => e.scenario === 'drift-check').source, 'builtin');
87
- // 排序:域表序在前
88
- assert.ok(merged.findIndex(e => e.domain === 'scope') < merged.findIndex(e => e.domain === 'risk'));
89
- }],
90
- ['别名解析:命中 / 未知域 / 已知域缺场景(错误信息给可操作指引)', () => {
91
- const catalog = {
92
- entries: [
93
- makeEntry({ domain: 'risk', scenario: 'scan' }),
94
- makeEntry({ domain: 'risk', scenario: 'register', name: 'risk-register', write: true }),
95
- ],
96
- warnings: [],
97
- };
98
- const hit = resolvePmEntry(catalog, 'risk', 'scan');
99
- assert.equal(hit.file, '/tmp/x.yaml');
100
- // name 兜底匹配 <domain>-<scenario>
101
- assert.equal(resolvePmEntry(catalog, 'risk', 'register').write, true);
102
- assert.throws(() => resolvePmEntry(catalog, 'procurement', 'audit'), (error) => error instanceof CliError && error.code === 'INVALID_ARGS' && error.message.includes('未知域 "procurement"') && error.message.includes('integration, scope'));
103
- assert.throws(() => resolvePmEntry(catalog, 'risk', 'nope'), (error) => error instanceof CliError && error.message.includes('域 risk 下没有场景 "nope"') && error.message.includes('scan, register'));
104
- // 空目录的已知域:指引放模板即收录
105
- assert.throws(() => resolvePmEntry({ entries: [], warnings: [] }, 'risk', 'scan'), (error) => error instanceof CliError && error.message.includes('放置 templates/pm'));
106
- }],
107
- ['loadPmTemplate:剥离 frontmatter domain 后交 S1 严格校验;坏结构抛 TEMPLATE_INVALID', () => {
108
- const ok = loadPmTemplate({ ...makeEntry({}), file: path.join(root, 'pm', 'risk-scan.yaml') });
109
- assert.equal(ok.template.name, 'risk-scan');
110
- assert.equal(ok.template.write, false);
111
- assert.equal(ok.template.steps.length, 2);
112
- assert.equal(ok.template.domain, undefined, 'domain 字段必须被剥离');
113
- assert.equal(ok.path, path.join(root, 'pm', 'risk-scan.yaml'));
114
- assert.throws(() => loadPmTemplate({ ...makeEntry({}), file: path.join(root, 'pm', 'broken.yaml') }), (error) => error instanceof PipelineError && error.code === 'TEMPLATE_INVALID');
115
- assert.throws(() => loadPmTemplate({ ...makeEntry({}), file: '/nonexistent/nope.yaml' }), (error) => error instanceof PipelineError && error.code === 'IO');
116
- }],
117
- ];
118
- // ---- fixture 准备 ----
119
- const root = mkdtempSync(path.join(tmpdir(), 'tapd-pm-discovery-'));
120
- mkdirSync(path.join(root, 'pm'), { recursive: true });
121
- writeFileSync(path.join(root, 'pm', 'risk-scan.yaml'), RISK_SCAN);
122
- writeFileSync(path.join(root, 'pm', 'procurement-audit.yaml'), 'name: procurement-audit\ndomain: procurement\ntitle: 外部依赖台账\nsteps:\n - id: a\n uses: tapd_get_stories\n');
123
- writeFileSync(path.join(root, 'pm', 'broken.yaml'), 'name: [broken\n steps: {{{');
124
- writeFileSync(path.join(root, 'pm', 'no-steps.yaml'), 'name: no-steps\ntitle: 没有 steps\n');
125
- let failed = 0;
126
- try {
127
- for (const [name, fn] of checks) {
128
- try {
129
- await fn();
130
- console.log(`ok - ${name}`);
131
- }
132
- catch (error) {
133
- failed++;
134
- console.error(`FAIL - ${name}`);
135
- console.error(error);
136
- }
137
- }
138
- }
139
- finally {
140
- rmSync(root, { recursive: true, force: true });
141
- }
142
- if (failed > 0) {
143
- console.error(`\n${failed}/${checks.length} failed`);
144
- process.exit(1);
145
- }
146
- console.log(`\n${checks.length}/${checks.length} passed`);
147
- //# sourceMappingURL=discovery.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"discovery.test.js","sourceRoot":"","sources":["../../src/pm/discovery.test.ts"],"names":[],"mappings":"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"}