@xihe-lab/tapd-cli 2.0.0-rc.1 → 2.0.0-rc.3

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 (176) hide show
  1. package/README.md +22 -0
  2. package/dist/advisor/domain-axis.d.ts +16 -0
  3. package/dist/advisor/domain-axis.d.ts.map +1 -0
  4. package/dist/advisor/domain-axis.js +43 -0
  5. package/dist/advisor/domain-axis.js.map +1 -0
  6. package/dist/advisor/domain-axis.test.d.ts +2 -0
  7. package/dist/advisor/domain-axis.test.d.ts.map +1 -0
  8. package/dist/advisor/domain-axis.test.js +198 -0
  9. package/dist/advisor/domain-axis.test.js.map +1 -0
  10. package/dist/advisor/index.d.ts +8 -0
  11. package/dist/advisor/index.d.ts.map +1 -0
  12. package/dist/advisor/index.js +6 -0
  13. package/dist/advisor/index.js.map +1 -0
  14. package/dist/advisor/persona.d.ts +12 -0
  15. package/dist/advisor/persona.d.ts.map +1 -0
  16. package/dist/advisor/persona.js +34 -0
  17. package/dist/advisor/persona.js.map +1 -0
  18. package/dist/advisor/recall.d.ts +38 -0
  19. package/dist/advisor/recall.d.ts.map +1 -0
  20. package/dist/advisor/recall.js +96 -0
  21. package/dist/advisor/recall.js.map +1 -0
  22. package/dist/advisor/render.d.ts +8 -0
  23. package/dist/advisor/render.d.ts.map +1 -0
  24. package/dist/advisor/render.js +42 -0
  25. package/dist/advisor/render.js.map +1 -0
  26. package/dist/bin/tapd.js +0 -0
  27. package/dist/commands/advisor.d.ts.map +1 -1
  28. package/dist/commands/advisor.js +31 -13
  29. package/dist/commands/advisor.js.map +1 -1
  30. package/dist/commands/pipeline.d.ts +4 -0
  31. package/dist/commands/pipeline.d.ts.map +1 -0
  32. package/dist/commands/pipeline.js +178 -0
  33. package/dist/commands/pipeline.js.map +1 -0
  34. package/dist/commands/pm.d.ts +4 -0
  35. package/dist/commands/pm.d.ts.map +1 -0
  36. package/dist/commands/pm.js +175 -0
  37. package/dist/commands/pm.js.map +1 -0
  38. package/dist/index.d.ts +2 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +8 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/pipeline/engine.d.ts +38 -0
  43. package/dist/pipeline/engine.d.ts.map +1 -0
  44. package/dist/pipeline/engine.js +326 -0
  45. package/dist/pipeline/engine.js.map +1 -0
  46. package/dist/pipeline/engine.test.d.ts +2 -0
  47. package/dist/pipeline/engine.test.d.ts.map +1 -0
  48. package/dist/pipeline/engine.test.js +419 -0
  49. package/dist/pipeline/engine.test.js.map +1 -0
  50. package/dist/pipeline/expression.d.ts +31 -0
  51. package/dist/pipeline/expression.d.ts.map +1 -0
  52. package/dist/pipeline/expression.js +249 -0
  53. package/dist/pipeline/expression.js.map +1 -0
  54. package/dist/pipeline/expression.test.d.ts +2 -0
  55. package/dist/pipeline/expression.test.d.ts.map +1 -0
  56. package/dist/pipeline/expression.test.js +111 -0
  57. package/dist/pipeline/expression.test.js.map +1 -0
  58. package/dist/pipeline/history.d.ts +13 -0
  59. package/dist/pipeline/history.d.ts.map +1 -0
  60. package/dist/pipeline/history.js +66 -0
  61. package/dist/pipeline/history.js.map +1 -0
  62. package/dist/pipeline/index.d.ts +13 -0
  63. package/dist/pipeline/index.d.ts.map +1 -0
  64. package/dist/pipeline/index.js +9 -0
  65. package/dist/pipeline/index.js.map +1 -0
  66. package/dist/pipeline/record.d.ts +13 -0
  67. package/dist/pipeline/record.d.ts.map +1 -0
  68. package/dist/pipeline/record.js +30 -0
  69. package/dist/pipeline/record.js.map +1 -0
  70. package/dist/pipeline/record.test.d.ts +2 -0
  71. package/dist/pipeline/record.test.d.ts.map +1 -0
  72. package/dist/pipeline/record.test.js +109 -0
  73. package/dist/pipeline/record.test.js.map +1 -0
  74. package/dist/pipeline/template.d.ts +24 -0
  75. package/dist/pipeline/template.d.ts.map +1 -0
  76. package/dist/pipeline/template.js +134 -0
  77. package/dist/pipeline/template.js.map +1 -0
  78. package/dist/pipeline/template.test.d.ts +2 -0
  79. package/dist/pipeline/template.test.d.ts.map +1 -0
  80. package/dist/pipeline/template.test.js +94 -0
  81. package/dist/pipeline/template.test.js.map +1 -0
  82. package/dist/pipeline/types.d.ts +99 -0
  83. package/dist/pipeline/types.d.ts.map +1 -0
  84. package/dist/pipeline/types.js +31 -0
  85. package/dist/pipeline/types.js.map +1 -0
  86. package/dist/pipeline/unwrap.d.ts +3 -0
  87. package/dist/pipeline/unwrap.d.ts.map +1 -0
  88. package/dist/pipeline/unwrap.js +26 -0
  89. package/dist/pipeline/unwrap.js.map +1 -0
  90. package/dist/pipeline/unwrap.test.d.ts +2 -0
  91. package/dist/pipeline/unwrap.test.d.ts.map +1 -0
  92. package/dist/pipeline/unwrap.test.js +36 -0
  93. package/dist/pipeline/unwrap.test.js.map +1 -0
  94. package/dist/pipeline/validate.d.ts +18 -0
  95. package/dist/pipeline/validate.d.ts.map +1 -0
  96. package/dist/pipeline/validate.js +134 -0
  97. package/dist/pipeline/validate.js.map +1 -0
  98. package/dist/pipeline/validate.test.d.ts +2 -0
  99. package/dist/pipeline/validate.test.d.ts.map +1 -0
  100. package/dist/pipeline/validate.test.js +166 -0
  101. package/dist/pipeline/validate.test.js.map +1 -0
  102. package/dist/pm/discovery.d.ts +54 -0
  103. package/dist/pm/discovery.d.ts.map +1 -0
  104. package/dist/pm/discovery.js +198 -0
  105. package/dist/pm/discovery.js.map +1 -0
  106. package/dist/pm/discovery.test.d.ts +2 -0
  107. package/dist/pm/discovery.test.d.ts.map +1 -0
  108. package/dist/pm/discovery.test.js +147 -0
  109. package/dist/pm/discovery.test.js.map +1 -0
  110. package/dist/pm/domains.d.ts +15 -0
  111. package/dist/pm/domains.d.ts.map +1 -0
  112. package/dist/pm/domains.js +27 -0
  113. package/dist/pm/domains.js.map +1 -0
  114. package/dist/pm/domains.test.d.ts +2 -0
  115. package/dist/pm/domains.test.d.ts.map +1 -0
  116. package/dist/pm/domains.test.js +141 -0
  117. package/dist/pm/domains.test.js.map +1 -0
  118. package/dist/pm/index.d.ts +9 -0
  119. package/dist/pm/index.d.ts.map +1 -0
  120. package/dist/pm/index.js +6 -0
  121. package/dist/pm/index.js.map +1 -0
  122. package/dist/pm/iteration.d.ts +26 -0
  123. package/dist/pm/iteration.d.ts.map +1 -0
  124. package/dist/pm/iteration.js +50 -0
  125. package/dist/pm/iteration.js.map +1 -0
  126. package/dist/pm/iteration.test.d.ts +2 -0
  127. package/dist/pm/iteration.test.d.ts.map +1 -0
  128. package/dist/pm/iteration.test.js +125 -0
  129. package/dist/pm/iteration.test.js.map +1 -0
  130. package/dist/pm/pm-command.test.d.ts +2 -0
  131. package/dist/pm/pm-command.test.d.ts.map +1 -0
  132. package/dist/pm/pm-command.test.js +321 -0
  133. package/dist/pm/pm-command.test.js.map +1 -0
  134. package/dist/pm/render.d.ts +17 -0
  135. package/dist/pm/render.d.ts.map +1 -0
  136. package/dist/pm/render.js +82 -0
  137. package/dist/pm/render.js.map +1 -0
  138. package/dist/pm/tpl-communication-stakeholder.test.d.ts +2 -0
  139. package/dist/pm/tpl-communication-stakeholder.test.d.ts.map +1 -0
  140. package/dist/pm/tpl-communication-stakeholder.test.js +392 -0
  141. package/dist/pm/tpl-communication-stakeholder.test.js.map +1 -0
  142. package/dist/pm/tpl-integration-scope.test.d.ts +2 -0
  143. package/dist/pm/tpl-integration-scope.test.d.ts.map +1 -0
  144. package/dist/pm/tpl-integration-scope.test.js +387 -0
  145. package/dist/pm/tpl-integration-scope.test.js.map +1 -0
  146. package/dist/pm/tpl-quality-risk.test.d.ts +2 -0
  147. package/dist/pm/tpl-quality-risk.test.d.ts.map +1 -0
  148. package/dist/pm/tpl-quality-risk.test.js +414 -0
  149. package/dist/pm/tpl-quality-risk.test.js.map +1 -0
  150. package/dist/pm/tpl-schedule-cost.test.d.ts +2 -0
  151. package/dist/pm/tpl-schedule-cost.test.d.ts.map +1 -0
  152. package/dist/pm/tpl-schedule-cost.test.js +376 -0
  153. package/dist/pm/tpl-schedule-cost.test.js.map +1 -0
  154. package/dist/program.d.ts.map +1 -1
  155. package/dist/program.js +6 -0
  156. package/dist/program.js.map +1 -1
  157. package/package.json +17 -11
  158. package/templates/deliver-story.yaml +38 -0
  159. package/templates/iteration-review.yaml +52 -0
  160. package/templates/pm/README.md +57 -0
  161. package/templates/pm/communication-notify.yaml +65 -0
  162. package/templates/pm/communication-weekly.yaml +160 -0
  163. package/templates/pm/cost-report.yaml +74 -0
  164. package/templates/pm/integration-close.yaml +118 -0
  165. package/templates/pm/integration-health.yaml +155 -0
  166. package/templates/pm/integration-kickoff.yaml +94 -0
  167. package/templates/pm/quality-dashboard.yaml +88 -0
  168. package/templates/pm/quality-triage.yaml +42 -0
  169. package/templates/pm/risk-register.yaml +55 -0
  170. package/templates/pm/risk-scan.yaml +87 -0
  171. package/templates/pm/schedule-burndown.yaml +87 -0
  172. package/templates/pm/schedule-standup.yaml +109 -0
  173. package/templates/pm/scope-baseline.yaml +93 -0
  174. package/templates/pm/scope-drift-check.yaml +129 -0
  175. package/templates/pm/stakeholder-map.yaml +121 -0
  176. package/templates/triage-bugs.yaml +49 -0
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,18 @@
1
+ import type { ToolRegistry } from '@xihe-lab/tapd-core';
2
+ import type { PipelineTemplate } from './types.js';
3
+ export interface ValidationIssue {
4
+ level: 'error' | 'warning';
5
+ target: string;
6
+ message: string;
7
+ }
8
+ export interface ValidationResult {
9
+ ok: boolean;
10
+ errors: ValidationIssue[];
11
+ warnings: ValidationIssue[];
12
+ /** 每步骤的写判定(供预览/运行复用) */
13
+ writeSteps: string[];
14
+ }
15
+ export declare function validateTemplate(template: PipelineTemplate, registry: ToolRegistry): ValidationResult;
16
+ export declare function formatIssues(issues: ValidationIssue[]): string;
17
+ export declare function assertTemplateValid(template: PipelineTemplate, registry: ToolRegistry): ValidationResult;
18
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/pipeline/validate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGjE,OAAO,KAAK,EAAgB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAIjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,wBAAwB;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AA4CD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,GAAG,gBAAgB,CAuErG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAE9D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,GAAG,gBAAgB,CAUxG"}
@@ -0,0 +1,134 @@
1
+ // 静态校验(tapd pipeline validate):命令存在性、参数 zod 校验、写步骤标记、表达式语法、引用完整性
2
+ //
3
+ // 校验口径:
4
+ // - 参数校验逐字段进行:值仍为 ${steps.*} 延迟引用时跳过该字段的类型检查(运行期类型未知),
5
+ // 其余字段对 schema 逐个 safeParse,避免整对象 parse 被延迟引用误伤。
6
+ // - 写/只读判定复用 core 的 write-policy(resolveWrite),不另造清单(FSD §4.2.3)。
7
+ import { resolveWrite } from '@xihe-lab/tapd-core';
8
+ import { z } from 'zod';
9
+ import { PipelineError } from './types.js';
10
+ import { checkExprSyntax, extractStepRefs, interpolate, isDeferredWholeRef } from './expression.js';
11
+ function unwrapSchema(field) {
12
+ let cur = field;
13
+ for (;;) {
14
+ if (cur instanceof z.ZodOptional || cur instanceof z.ZodNullable || cur instanceof z.ZodDefault) {
15
+ cur = cur._def.innerType;
16
+ }
17
+ else {
18
+ return cur;
19
+ }
20
+ }
21
+ }
22
+ function validateStepArgs(step, tool, issues) {
23
+ const schema = tool.inputSchema;
24
+ const shape = schema instanceof z.ZodObject ? schema.shape : {};
25
+ const args = step.args ?? {};
26
+ // 必填缺失:schema 声明 required(非 optional/nullable/default)而步骤未提供
27
+ for (const [key, field] of Object.entries(shape)) {
28
+ if (key in args)
29
+ continue;
30
+ if (!field.isOptional()) {
31
+ issues.push({ level: 'error', target: `steps.${step.id}.args.${key}`, message: '必填参数缺失(schema required)' });
32
+ }
33
+ }
34
+ for (const key of Object.keys(args)) {
35
+ const field = shape[key];
36
+ if (!field) {
37
+ issues.push({ level: 'error', target: `steps.${step.id}.args.${key}`, message: `工具 ${tool.name} 的 schema 不包含参数 "${key}"(运行期会被丢弃,疑似拼写错误)` });
38
+ continue;
39
+ }
40
+ // 整串 ${...}(vars/steps 引用)运行期才有真值:静态跳过类型检查,仅查 key 合法性
41
+ if (isDeferredWholeRef(args[key]))
42
+ continue;
43
+ const inner = unwrapSchema(field);
44
+ const probe = inner.safeParse(interpolate(args[key], { vars: {}, steps: {} }));
45
+ if (!probe.success) {
46
+ const detail = probe.error.issues.map(i => i.message).join('; ');
47
+ issues.push({ level: 'error', target: `steps.${step.id}.args.${key}`, message: `参数不符 schema: ${detail}` });
48
+ }
49
+ }
50
+ }
51
+ export function validateTemplate(template, registry) {
52
+ const issues = [];
53
+ const writeSteps = [];
54
+ const stepIds = new Set(template.steps.map(s => s.id));
55
+ for (const step of template.steps) {
56
+ // 1) 依赖与引用完整性(depends_on 指向缺失步骤已由 parseTemplate 拦截,此处查 ${steps.*} 软引用)
57
+ const refs = [
58
+ ...extractStepRefs(step.args ?? {}),
59
+ ...extractStepRefs(step.depends_on ?? []),
60
+ ...(step.where ? extractStepRefs(step.where) : []),
61
+ ...(step.filter ? extractStepRefs(step.filter) : []),
62
+ ];
63
+ for (const ref of refs) {
64
+ if (!stepIds.has(ref)) {
65
+ issues.push({ level: 'error', target: `steps.${step.id}`, message: `引用了不存在的步骤 "${ref}"` });
66
+ }
67
+ }
68
+ // 2) 表达式语法
69
+ try {
70
+ if (step.expr)
71
+ checkExprSyntax(step.expr, true);
72
+ if (step.where)
73
+ checkExprSyntax(step.where, true);
74
+ if (step.filter)
75
+ checkExprSyntax(step.filter, true);
76
+ }
77
+ catch (error) {
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ issues.push({ level: 'error', target: `steps.${step.id}`, message });
80
+ }
81
+ // 3) expr 步骤:本地计算,无命令校验
82
+ if (step.expr && !step.uses)
83
+ continue;
84
+ // 4) 命令存在性(uses 必须命中 toolRegistry)
85
+ const tool = step.uses ? registry.get(step.uses) : undefined;
86
+ if (!tool) {
87
+ issues.push({
88
+ level: 'error',
89
+ target: `steps.${step.id}.uses`,
90
+ message: `未知命令 "${step.uses}"(必须是 toolRegistry 中存在的工具名,可用 tapd advisor 或 schema 导出查询)`,
91
+ });
92
+ continue;
93
+ }
94
+ // 5) 写判定(复用 write-policy)与参数 schema 校验
95
+ if (resolveWrite(tool))
96
+ writeSteps.push(step.id);
97
+ try {
98
+ validateStepArgs(step, tool, issues);
99
+ }
100
+ catch (error) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ issues.push({ level: 'error', target: `steps.${step.id}.args`, message });
103
+ }
104
+ }
105
+ // 6) 写标记一致性:含写步骤必须声明 write: true(闸门依据,防绕过)
106
+ if (writeSteps.length > 0 && template.write !== true) {
107
+ issues.push({
108
+ level: 'error',
109
+ target: 'write',
110
+ message: `模板包含写步骤 [${writeSteps.join(', ')}],必须声明 write: true(运行期将强制写闸门)`,
111
+ });
112
+ }
113
+ else if (writeSteps.length === 0 && template.write === true) {
114
+ issues.push({
115
+ level: 'warning',
116
+ target: 'write',
117
+ message: '模板声明 write: true 但所有步骤均为只读,建议改为 write: false',
118
+ });
119
+ }
120
+ const errors = issues.filter(i => i.level === 'error');
121
+ const warnings = issues.filter(i => i.level === 'warning');
122
+ return { ok: errors.length === 0, errors, warnings, writeSteps };
123
+ }
124
+ export function formatIssues(issues) {
125
+ return issues.map(i => ` ${i.level === 'error' ? '✗' : '!'} ${i.target}: ${i.message}`).join('\n');
126
+ }
127
+ export function assertTemplateValid(template, registry) {
128
+ const result = validateTemplate(template, registry);
129
+ if (!result.ok) {
130
+ throw new PipelineError('TEMPLATE_INVALID', `模板校验未通过(${template.name})`, result.errors.map(e => `${e.target}: ${e.message}`));
131
+ }
132
+ return result;
133
+ }
134
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/pipeline/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../src/pipeline/validate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,166 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../src/pipeline/validate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { type PipelineTemplate } from '../pipeline/types.js';
2
+ export declare const PM_TEMPLATE_EXTS: string[];
3
+ export interface PmTemplateEntry {
4
+ /** 域键(frontmatter domain 优先,否则取文件名首段;无法判定为空串 → help 归「其他」) */
5
+ domain: string;
6
+ /** 场景名(文件名去掉 <domain>- 前缀后的剩余部分) */
7
+ scenario: string;
8
+ /** 模板名(frontmatter name,缺省为文件名 stem) */
9
+ name: string;
10
+ title: string;
11
+ write: boolean;
12
+ /** 模板绝对路径 */
13
+ file: string;
14
+ source: 'builtin' | 'user';
15
+ /** 域键是否命中 PM_DOMAINS 元数据表 */
16
+ domainKnown: boolean;
17
+ }
18
+ export interface PmCatalog {
19
+ /** 已按域序/场景名排序、用户覆盖内置后的生效清单 */
20
+ entries: PmTemplateEntry[];
21
+ /** 发现期跳过的文件及原因(pm 子命令动作时打 stderr,不阻塞其它命令) */
22
+ warnings: string[];
23
+ }
24
+ /** 内置 pm 模板目录:packages/cli/templates/pm */
25
+ export declare function builtinPmTemplatesDir(): string;
26
+ /** 用户模板根目录(默认 ~/.tapd/templates,可用 TAPD_USER_TEMPLATES_DIR 覆盖,测试注入用) */
27
+ export declare function userTemplatesRoot(): string;
28
+ export declare function userPmTemplatesDir(): string;
29
+ /** 别名键:域 + 场景(域可为空串 → 「其他」组) */
30
+ export declare function pmAliasKey(entry: Pick<PmTemplateEntry, 'domain' | 'scenario'>): string;
31
+ /** 文件名 stem → 域/场景:有 frontmatter domain 时剥掉 <domain>- 前缀,否则首个 '-' 前为域 */
32
+ export declare function splitAlias(stem: string, domain?: string): {
33
+ domain: string;
34
+ scenario: string;
35
+ };
36
+ /** 用户同别名覆盖内置;排序:域表序 → 其他域按域键字典序 → 场景名字典序 */
37
+ export declare function mergePmEntries(builtin: PmTemplateEntry[], user: PmTemplateEntry[]): PmTemplateEntry[];
38
+ /** 扫描内置 + 用户目录,产出生效目录(用户同名覆盖内置) */
39
+ export declare function discoverPmTemplates(): PmCatalog;
40
+ /**
41
+ * 别名解析:tapd pm <domain> <scenario> → 模板条目。
42
+ * 未命中时按「域不存在 / 域存在但场景缺失」给可操作的错误信息。
43
+ */
44
+ export declare function resolvePmEntry(catalog: PmCatalog, domain: string, scenario: string): PmTemplateEntry;
45
+ /**
46
+ * 加载并剥离 pm 元数据后交 S1 引擎严格校验:
47
+ * frontmatter 的 domain 字段由 pm 层消费,parseTemplate 是 strict schema,
48
+ * 不剥离会以 TEMPLATE_INVALID 拒绝。
49
+ */
50
+ export declare function loadPmTemplate(entry: PmTemplateEntry): {
51
+ template: PipelineTemplate;
52
+ path: string;
53
+ };
54
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/pm/discovery.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAI5E,eAAO,MAAM,gBAAgB,UAA6B,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,8BAA8B;IAC9B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,UAAU,CAAC,GAAG,MAAM,CAEtF;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAS9F;AAwFD,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAUrG;AAED,mCAAmC;AACnC,wBAAgB,mBAAmB,IAAI,SAAS,CAK/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAkBpG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG;IAAE,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAqBnG"}
@@ -0,0 +1,198 @@
1
+ // pm 模板发现与别名解析(S2 框架本体)
2
+ //
3
+ // 发现口径(设计 §3):
4
+ // 内置 packages/cli/templates/pm/<domain>-<scenario>.yaml(随包发布)
5
+ // 用户 ~/.tapd/templates/pm/(TAPD_USER_TEMPLATES_DIR 可改根目录),同别名覆盖内置
6
+ //
7
+ // pm 模板在 pipeline 模板 schema 之外多一个 frontmatter 字段 domain:(S1 parseTemplate
8
+ // 是 strict schema,不认识它),因此本模块负责:
9
+ // 1. 扫描目录提取元数据(domain/name/title/write),不认识的文件只产 warning 不炸;
10
+ // 2. 执行前剥离 domain 字段再交 S1 parseTemplate 严格校验(loadPmTemplate)。
11
+ // 域名兜底来自文件名约定 <domain>-<scenario>.yaml —— 首个 '-' 前为域键。
12
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
13
+ import { homedir } from 'node:os';
14
+ import path from 'node:path';
15
+ import YAML from 'yaml';
16
+ import { builtinTemplatesDir, parseTemplate } from '../pipeline/template.js';
17
+ import { PipelineError } from '../pipeline/types.js';
18
+ import { CliError } from '../errors.js';
19
+ import { PM_DOMAINS, findDomain } from './domains.js';
20
+ export const PM_TEMPLATE_EXTS = ['.yaml', '.yml', '.json'];
21
+ /** 内置 pm 模板目录:packages/cli/templates/pm */
22
+ export function builtinPmTemplatesDir() {
23
+ return path.join(builtinTemplatesDir(), 'pm');
24
+ }
25
+ /** 用户模板根目录(默认 ~/.tapd/templates,可用 TAPD_USER_TEMPLATES_DIR 覆盖,测试注入用) */
26
+ export function userTemplatesRoot() {
27
+ const env = process.env.TAPD_USER_TEMPLATES_DIR;
28
+ if (env && env.trim() !== '')
29
+ return env;
30
+ return path.join(homedir(), '.tapd', 'templates');
31
+ }
32
+ export function userPmTemplatesDir() {
33
+ return path.join(userTemplatesRoot(), 'pm');
34
+ }
35
+ /** 别名键:域 + 场景(域可为空串 → 「其他」组) */
36
+ export function pmAliasKey(entry) {
37
+ return `${entry.domain}::${entry.scenario}`;
38
+ }
39
+ /** 文件名 stem → 域/场景:有 frontmatter domain 时剥掉 <domain>- 前缀,否则首个 '-' 前为域 */
40
+ export function splitAlias(stem, domain) {
41
+ if (domain) {
42
+ const lower = stem.toLowerCase();
43
+ const prefix = `${domain.toLowerCase()}-`;
44
+ return { domain, scenario: lower.startsWith(prefix) ? stem.slice(domain.length + 1) : stem };
45
+ }
46
+ const idx = stem.indexOf('-');
47
+ if (idx > 0)
48
+ return { domain: stem.slice(0, idx), scenario: stem.slice(idx + 1) };
49
+ return { domain: '', scenario: stem };
50
+ }
51
+ /** 只读元数据:容错解析(YAML.parse 兼容 json),结构不合法直接抛错由调用方降级为 warning */
52
+ function readPmDocMeta(file) {
53
+ const source = readFileSync(file, 'utf8');
54
+ let doc;
55
+ try {
56
+ doc = YAML.parse(source);
57
+ }
58
+ catch (error) {
59
+ const message = error instanceof Error ? error.message.split('\n')[0] : String(error);
60
+ throw new Error(`YAML 解析失败: ${message}`, { cause: error });
61
+ }
62
+ if (!doc || typeof doc !== 'object' || Array.isArray(doc)) {
63
+ throw new Error('顶层必须是 YAML 映射(name/steps/...)');
64
+ }
65
+ const d = doc;
66
+ const domain = typeof d.domain === 'string' && d.domain.trim() !== '' ? d.domain.trim() : undefined;
67
+ if (domain !== undefined && domain !== domain.toLowerCase()) {
68
+ throw new Error(`domain 必须是小写域键(got "${domain}")`);
69
+ }
70
+ return {
71
+ domain,
72
+ name: typeof d.name === 'string' && d.name.trim() !== '' ? d.name.trim() : undefined,
73
+ title: typeof d.title === 'string' ? d.title : '',
74
+ write: d.write === true,
75
+ hasSteps: Array.isArray(d.steps) && d.steps.length > 0,
76
+ };
77
+ }
78
+ function scanPmDir(dir, source, warnings) {
79
+ if (!existsSync(dir))
80
+ return [];
81
+ let files;
82
+ try {
83
+ files = readdirSync(dir)
84
+ .filter(f => PM_TEMPLATE_EXTS.includes(path.extname(f).toLowerCase()))
85
+ .sort();
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ warnings.push(`读取模板目录失败(${dir}): ${message}`);
90
+ return [];
91
+ }
92
+ const out = [];
93
+ for (const f of files) {
94
+ const full = path.join(dir, f);
95
+ try {
96
+ if (!statSync(full).isFile())
97
+ continue;
98
+ const meta = readPmDocMeta(full);
99
+ if (!meta.hasSteps) {
100
+ warnings.push(`跳过 pm 模板(无 steps): ${full}`);
101
+ continue;
102
+ }
103
+ const stem = f.replace(/\.(yaml|yml|json)$/i, '');
104
+ const { domain, scenario } = splitAlias(stem, meta.domain);
105
+ if (!scenario) {
106
+ warnings.push(`跳过 pm 模板(无法解析场景名): ${full}`);
107
+ continue;
108
+ }
109
+ out.push({
110
+ domain,
111
+ scenario,
112
+ name: meta.name ?? stem,
113
+ title: meta.title,
114
+ write: meta.write,
115
+ file: full,
116
+ source,
117
+ domainKnown: findDomain(domain) !== undefined,
118
+ });
119
+ }
120
+ catch (error) {
121
+ const message = error instanceof Error ? error.message : String(error);
122
+ warnings.push(`跳过 pm 模板(${message}): ${full}`);
123
+ }
124
+ }
125
+ return out;
126
+ }
127
+ function domainOrder(domain) {
128
+ const idx = PM_DOMAINS.findIndex(d => d.key === domain);
129
+ return idx >= 0 ? idx : PM_DOMAINS.length;
130
+ }
131
+ /** 用户同别名覆盖内置;排序:域表序 → 其他域按域键字典序 → 场景名字典序 */
132
+ export function mergePmEntries(builtin, user) {
133
+ const byAlias = new Map();
134
+ for (const e of builtin)
135
+ byAlias.set(pmAliasKey(e), e);
136
+ for (const e of user)
137
+ byAlias.set(pmAliasKey(e), e);
138
+ return [...byAlias.values()].sort((a, b) => {
139
+ const d = domainOrder(a.domain) - domainOrder(b.domain);
140
+ if (d !== 0)
141
+ return d;
142
+ if (a.domain !== b.domain)
143
+ return a.domain.localeCompare(b.domain);
144
+ return a.scenario.localeCompare(b.scenario);
145
+ });
146
+ }
147
+ /** 扫描内置 + 用户目录,产出生效目录(用户同名覆盖内置) */
148
+ export function discoverPmTemplates() {
149
+ const warnings = [];
150
+ const builtin = scanPmDir(builtinPmTemplatesDir(), 'builtin', warnings);
151
+ const user = scanPmDir(userPmTemplatesDir(), 'user', warnings);
152
+ return { entries: mergePmEntries(builtin, user), warnings };
153
+ }
154
+ /**
155
+ * 别名解析:tapd pm <domain> <scenario> → 模板条目。
156
+ * 未命中时按「域不存在 / 域存在但场景缺失」给可操作的错误信息。
157
+ */
158
+ export function resolvePmEntry(catalog, domain, scenario) {
159
+ const hit = catalog.entries.find(e => e.domain === domain && e.scenario === scenario) ??
160
+ catalog.entries.find(e => e.name === `${domain}-${scenario}`);
161
+ if (hit)
162
+ return hit;
163
+ if (!findDomain(domain) && !catalog.entries.some(e => e.domain === domain)) {
164
+ throw new CliError('INVALID_ARGS', `未知域 "${domain}",可用域: ${PM_DOMAINS.map(d => d.key).join(', ')}(tapd pm --help 查看域分组)`);
165
+ }
166
+ const peers = catalog.entries.filter(e => e.domain === domain).map(e => e.scenario);
167
+ throw new CliError('INVALID_ARGS', `域 ${domain} 下没有场景 "${scenario}",可用场景: ${peers.length > 0 ? peers.join(', ') : '(暂无,放置 templates/pm/<domain>-<scenario>.yaml 即自动收录)'}`);
168
+ }
169
+ /**
170
+ * 加载并剥离 pm 元数据后交 S1 引擎严格校验:
171
+ * frontmatter 的 domain 字段由 pm 层消费,parseTemplate 是 strict schema,
172
+ * 不剥离会以 TEMPLATE_INVALID 拒绝。
173
+ */
174
+ export function loadPmTemplate(entry) {
175
+ let source;
176
+ try {
177
+ source = readFileSync(entry.file, 'utf8');
178
+ }
179
+ catch (error) {
180
+ const message = error instanceof Error ? error.message : String(error);
181
+ throw new PipelineError('IO', `读取 pm 模板失败(${entry.file}): ${message}`);
182
+ }
183
+ let doc;
184
+ try {
185
+ doc = YAML.parse(source);
186
+ }
187
+ catch (error) {
188
+ const message = error instanceof Error ? error.message.split('\n')[0] : String(error);
189
+ throw new PipelineError('TEMPLATE_INVALID', `pm 模板解析失败(${entry.file}): ${message}`);
190
+ }
191
+ if (doc && typeof doc === 'object' && !Array.isArray(doc) && 'domain' in doc) {
192
+ delete doc.domain;
193
+ }
194
+ // YAML 序列化回灌 parseTemplate(JSON 亦为合法 YAML,这里用 YAML.stringify 保真)
195
+ const template = parseTemplate(YAML.stringify(doc), entry.file);
196
+ return { template, path: entry.file };
197
+ }
198
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/pm/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=discovery.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.test.d.ts","sourceRoot":"","sources":["../../src/pm/discovery.test.ts"],"names":[],"mappings":""}