kcode-pi 0.1.14 → 0.1.16

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.
@@ -40,89 +40,94 @@ export function defaultArtifactContent(phase: KdPhase, goal?: string, profile?:
40
40
  switch (phase) {
41
41
  case "discuss":
42
42
  return [
43
- "# Context",
44
- "",
45
- `- Goal: ${goal ?? "unknown"}`,
46
- `- Product: ${profile?.product ?? "unknown"}`,
47
- "- Version: unknown",
48
- `- Tech stack: ${profile?.techStack ?? "unknown"}`,
49
- `- Language: ${profile?.language ?? "unknown"}`,
50
- "- Plugin type: unknown",
51
- "- Target bill/entity/form: unknown",
52
- "- Out of scope: unknown",
53
- "- Open questions:",
54
- " - Confirm Kingdee product/version, tech stack, plugin type, and target object.",
43
+ "# 需求讨论上下文",
44
+ "",
45
+ `- 需求目标:${goal ?? "未知"}`,
46
+ `- 金蝶产品:${profile?.product ?? "未知"}`,
47
+ "- 版本:未知",
48
+ `- 技术栈:${profile?.techStack ?? "未知"}`,
49
+ `- 语言:${profile?.language ?? "未知"}`,
50
+ "- 插件类型:未知",
51
+ "- 目标单据/实体/表单:未知",
52
+ "- 非目标范围:未知",
53
+ "- 待确认问题:",
54
+ " - 确认金蝶产品/版本、技术栈、插件类型和目标对象。",
55
55
  "",
56
56
  ].join("\n");
57
57
  case "spec":
58
58
  return [
59
- "# Spec",
59
+ "# 需求规格",
60
60
  "",
61
- "## Acceptance Criteria",
61
+ "## 验收标准",
62
62
  "",
63
- "## Lifecycle / Extension Point",
63
+ "## 生命周期 / 扩展点",
64
64
  "",
65
- "## Data Objects and Fields",
65
+ "## 数据对象和字段",
66
66
  "",
67
- "## Exceptions and Performance",
67
+ "## 异常行为和性能约束",
68
68
  "",
69
- "## Assumptions",
69
+ "## 假设和风险",
70
70
  "",
71
71
  ].join("\n");
72
72
  case "plan":
73
73
  return [
74
- "# Plan",
74
+ "# 实施计划",
75
75
  "",
76
- "## Project Structure Checked",
76
+ "## 已检查的项目结构",
77
77
  "",
78
- "## Files to Inspect",
78
+ "## 需要查看的文件",
79
79
  "",
80
- "## Target Source Root / Path",
80
+ "## 目标源码根 / 路径",
81
81
  "",
82
- "## Files to Edit",
82
+ "## 允许修改的文件",
83
83
  "",
84
- "## Required Kingdee Lookups",
84
+ "## 必需的金蝶查证项",
85
85
  "",
86
- "## Execution Steps",
86
+ "- Java/C# 代码涉及 SDK 类、方法、构造器、枚举、属性时,必须先用 kd_sdk_signature 或项目构建输出确认真实签名。",
87
+ "- 知识库搜索、随包 Cosmic API 查询只能作为线索,不能作为最终方法签名事实。",
88
+ "- SDK 签名证据:evidence/sdk-signature.md",
87
89
  "",
88
- "- [ ] STEP-001: Inspect the existing target files and confirm exact edit locations.",
89
- "- [ ] STEP-002: Run a failing red check and record red evidence.",
90
- "- [ ] STEP-003: Implement only the approved file changes.",
91
- "- [ ] STEP-004: Run the same check again and record green evidence.",
92
- "- [ ] STEP-005: Record changed files and step evidence.",
90
+ "## 执行步骤",
93
91
  "",
94
- "## TDD / Red-Green Checks",
92
+ "- [ ] STEP-001:检查现有目标文件,确认精确修改位置。",
93
+ "- [ ] STEP-002:运行一个会失败的红灯检查,并记录红灯证据。",
94
+ "- [ ] STEP-003:只实现已批准的文件改动。",
95
+ "- [ ] STEP-004:再次运行同一检查,并记录绿灯证据。",
96
+ "- [ ] STEP-005:记录变更文件和步骤证据。",
95
97
  "",
96
- "- Red evidence: evidence/tdd-red.md",
97
- "- Green evidence: evidence/tdd-green.md",
98
- "- Red/green command or tool: unknown",
99
- "- Allowed checks: official API/base-class/method lookup, metadata lookup, kd_check, build/compile output, existing project test framework, or a minimal external-interface test.",
100
- "- Do not add third-party test jars or frameworks just to satisfy this gate.",
101
- "- If automated tests are impossible, document the product-specific check that can fail before implementation and pass after implementation.",
98
+ "## TDD / 红绿检查",
102
99
  "",
103
- "## Validation Commands",
100
+ "- 红灯证据:evidence/tdd-red.md",
101
+ "- 绿灯证据:evidence/tdd-green.md",
102
+ "- 红绿检查命令或工具:未知",
103
+ "- 允许的检查:本地 SDK 签名查证、官方 API/基类/方法查证、元数据查证、kd_check、构建/编译输出、项目已有测试框架、外部接口最小验证。",
104
+ "- 不要为了满足门禁引入第三方测试 jar 或框架。",
105
+ "- 如果无法自动化测试,记录一个产品相关、实现前应失败且实现后应通过的检查。",
106
+ "- 禁止凭记忆或随包知识库猜 SDK 方法签名;签名事实必须来自当前项目 jar/dll、构建输出或官方元数据。",
104
107
  "",
105
- "## Rollback / Containment",
108
+ "## 验证命令",
109
+ "",
110
+ "## 回滚 / 影响控制",
106
111
  "",
107
112
  ].join("\n");
108
113
  case "execute":
109
114
  return [
110
- "# Execution",
115
+ "# 执行记录",
111
116
  "",
112
- "## Step Results",
117
+ "## 步骤结果",
113
118
  "",
114
- "Record each planned step as:",
119
+ "每个计划步骤按以下格式记录:",
115
120
  "",
116
- "- [x] STEP-001: completed. Evidence: evidence/step-001.md",
121
+ "- [x] STEP-001:已完成。证据:evidence/step-001.md",
117
122
  "",
118
- "## Changed Files",
123
+ "## 变更文件",
119
124
  "",
120
- "## Deviations",
125
+ "## 偏离计划说明",
121
126
  "",
122
127
  ].join("\n");
123
128
  case "verify":
124
- return ["# Verify", "", "## Commands", "", "## Evidence", "", "## Residual Risk", ""].join("\n");
129
+ return ["# 验证记录", "", "## 命令", "", "## 证据", "", "## 残余风险", ""].join("\n");
125
130
  case "ship":
126
- return ["# Ship", "", "## Summary", "", "## Verification Evidence", "", "## Risks", "", "## Follow-ups", ""].join("\n");
131
+ return ["# 交付摘要", "", "## 摘要", "", "## 验证证据", "", "## 风险", "", "## 后续事项", ""].join("\n");
127
132
  }
128
133
  }
@@ -7,25 +7,25 @@ import { formatProductProfile } from "../product/profile.ts";
7
7
 
8
8
  export function formatStatus(cwd: string, run: ActiveRun | undefined): string {
9
9
  if (!run) {
10
- return ["No active Kingdee harness run.", "", "Start one with:", "/kd-start <goal>"].join("\n");
10
+ return ["当前没有 active Kingdee Harness run", "", "创建方式:", "/kd-start <需求>"].join("\n");
11
11
  }
12
12
 
13
13
  const refreshed = refreshGate(cwd, run);
14
14
  const next = nextPhase(refreshed.phase) ?? "done";
15
15
 
16
16
  return [
17
- `Run: ${refreshed.id}`,
18
- refreshed.goal ? `Goal: ${refreshed.goal}` : undefined,
19
- `Status: ${refreshed.status ?? "active"}`,
20
- `Phase: ${refreshed.phase}`,
21
- `Next: ${next}`,
22
- `Product: ${formatProductProfile(refreshed.profile)}`,
23
- `Version: ${refreshed.version ?? "unselected"}`,
24
- `Risk: ${refreshed.risk ?? "unknown"}`,
25
- `Gate: ${refreshed.gate.passed ? "pass" : "blocked"}`,
26
- refreshed.gate.reason ? `Reason: ${refreshed.gate.reason}` : undefined,
17
+ `Run:${refreshed.id}`,
18
+ refreshed.goal ? `需求:${refreshed.goal}` : undefined,
19
+ `状态:${refreshed.status ?? "active"}`,
20
+ `阶段:${refreshed.phase}`,
21
+ `下一阶段:${next}`,
22
+ `产品:${formatProductProfile(refreshed.profile)}`,
23
+ `版本:${refreshed.version ?? "未选择"}`,
24
+ `风险:${refreshed.risk ?? "未知"}`,
25
+ `门禁:${refreshed.gate.passed ? "通过" : "阻塞"}`,
26
+ refreshed.gate.reason ? `原因:${refreshed.gate.reason}` : undefined,
27
27
  "",
28
- `Run directory: ${join(runsDir(cwd), refreshed.id)}`,
28
+ `Run 目录:${join(runsDir(cwd), refreshed.id)}`,
29
29
  ]
30
30
  .filter(Boolean)
31
31
  .join("\n");
@@ -1,3 +1,5 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
1
3
  import type { ActiveRun, GateResult, KdPhase } from "./types.ts";
2
4
  import { PHASE_ARTIFACTS, PHASE_ORDER } from "./types.ts";
3
5
  import { artifactExists, readArtifact } from "./artifacts.ts";
@@ -5,11 +7,13 @@ import { isKnownProduct } from "../product/profile.ts";
5
7
  import { flagshipPlanBlockReason } from "./path-policy.ts";
6
8
  import { executionStepsBlockReason, planStepsBlockReason } from "./plan-steps.ts";
7
9
  import { tddPlanBlockReason, tddVerifyBlockReason } from "./tdd-policy.ts";
10
+ import { SDK_SIGNATURE_EVIDENCE, hasValidSdkSignatureEvidence, requiresSdkSignatureEvidence } from "./sdk-policy.ts";
11
+ import { runRoot } from "./paths.ts";
8
12
 
9
13
  const REQUIRED_MARKERS: Partial<Record<KdPhase, string[]>> = {
10
- plan: ["## Validation Commands"],
11
- verify: ["## Evidence"],
12
- ship: ["## Verification Evidence"],
14
+ plan: ["## 验证命令"],
15
+ verify: ["## 证据"],
16
+ ship: ["## 验证证据"],
13
17
  };
14
18
 
15
19
  const COSMIC_CONFIG_EVIDENCE = "evidence/cosmic-config.txt";
@@ -129,7 +133,7 @@ function inspectMarkers(cwd: string, run: ActiveRun, phase: KdPhase): string | u
129
133
  function inspectEvidence(cwd: string, run: ActiveRun, phase: KdPhase): string | undefined {
130
134
  const missing = missingEvidenceForPhase(cwd, run, phase);
131
135
  if (missing.length === 0) return undefined;
132
- return `缺少必需的官方证据:${missing.join(", ")}`;
136
+ return `缺少必需证据:${missing.join(", ")}`;
133
137
  }
134
138
 
135
139
  function isCosmicRun(run: ActiveRun): boolean {
@@ -137,22 +141,23 @@ function isCosmicRun(run: ActiveRun): boolean {
137
141
  }
138
142
 
139
143
  function missingEvidenceForPhase(cwd: string, run: ActiveRun, phase: KdPhase): string[] {
140
- return requiredEvidenceForPhase(cwd, run, phase).filter((artifact) => !artifactExists(cwd, run, artifact));
144
+ return requiredEvidenceForPhase(cwd, run, phase).filter((artifact) => !evidenceArtifactSatisfied(cwd, run, artifact));
141
145
  }
142
146
 
143
147
  function requiredEvidenceForPhase(cwd: string, run: ActiveRun, phase: KdPhase): string[] {
144
- if (!isCosmicRun(run)) return [];
145
-
146
148
  const required = new Set<string>();
147
149
  const phaseIndex = PHASE_ORDER.indexOf(phase);
148
150
 
149
151
  if (phaseIndex >= PHASE_ORDER.indexOf("execute")) {
150
- required.add(COSMIC_CONFIG_EVIDENCE);
151
- if (planHasMetadataRequirement(cwd, run)) required.add(COSMIC_METADATA_EVIDENCE);
152
- if (planHasApiRequirement(cwd, run)) required.add(COSMIC_API_EVIDENCE);
152
+ if (requiresSdkSignatureEvidence(run)) required.add(SDK_SIGNATURE_EVIDENCE);
153
+ if (isCosmicRun(run)) {
154
+ required.add(COSMIC_CONFIG_EVIDENCE);
155
+ if (planHasMetadataRequirement(cwd, run)) required.add(COSMIC_METADATA_EVIDENCE);
156
+ if (planHasApiRequirement(cwd, run)) required.add(COSMIC_API_EVIDENCE);
157
+ }
153
158
  }
154
159
 
155
- if (phaseIndex >= PHASE_ORDER.indexOf("ship") && runHasKsqlDelivery(cwd, run)) {
160
+ if (isCosmicRun(run) && phaseIndex >= PHASE_ORDER.indexOf("ship") && runHasKsqlDelivery(cwd, run)) {
156
161
  required.add(COSMIC_METADATA_EVIDENCE);
157
162
  required.add(KSQL_LINT_EVIDENCE);
158
163
  }
@@ -160,14 +165,19 @@ function requiredEvidenceForPhase(cwd: string, run: ActiveRun, phase: KdPhase):
160
165
  return [...required];
161
166
  }
162
167
 
168
+ function evidenceArtifactSatisfied(cwd: string, run: ActiveRun, artifact: string): boolean {
169
+ if (artifact === SDK_SIGNATURE_EVIDENCE) return hasValidSdkSignatureEvidence(cwd, run);
170
+ return existsSync(join(runRoot(cwd, run), artifact));
171
+ }
172
+
163
173
  function planHasMetadataRequirement(cwd: string, run: ActiveRun): boolean {
164
174
  const plan = readArtifact(cwd, run, "plan") ?? "";
165
- return /kd_cosmic_metadata|cosmic-metadata|metadata evidence|元数据|字段验证|字段确认|字段元数据/i.test(plan);
175
+ return /kd_cosmic_metadata|cosmic-metadata|cosmic-metadata\.json|metadata evidence|字段元数据证据|元数据证据/i.test(plan);
166
176
  }
167
177
 
168
178
  function planHasApiRequirement(cwd: string, run: ActiveRun): boolean {
169
179
  const plan = readArtifact(cwd, run, "plan") ?? "";
170
- return /kd_sdk_signature|kd_cosmic_api|cosmic-api|api signature|method signature|sdk.*签名|方法签名|接口签名/i.test(plan);
180
+ return /kd_cosmic_api|cosmic-api|cosmic-api\.txt/i.test(plan);
171
181
  }
172
182
 
173
183
  function runHasKsqlDelivery(cwd: string, run: ActiveRun): boolean {
@@ -20,13 +20,13 @@ export function parsePlanSteps(plan: string): PlanStep[] {
20
20
  }
21
21
 
22
22
  export function planStepsBlockReason(plan: string): string | undefined {
23
- if (!/##\s*Execution Steps/i.test(plan)) {
24
- return "PLAN.md 缺少 ## Execution Steps。必须把计划拆成 STEP-001 这种可跟踪步骤。";
23
+ if (!/##\s*执行步骤/i.test(plan)) {
24
+ return "PLAN.md 缺少 ## 执行步骤。必须把计划拆成 STEP-001 这种可跟踪步骤。";
25
25
  }
26
26
 
27
27
  const steps = parsePlanSteps(plan);
28
28
  if (steps.length === 0) {
29
- return "PLAN.md 没有可执行步骤。请使用 `- [ ] STEP-001: ...` 列出步骤。";
29
+ return "PLAN.md 没有可执行步骤。请使用 `- [ ] STEP-001:...` 列出步骤。";
30
30
  }
31
31
 
32
32
  const duplicate = firstDuplicate(steps.map((step) => step.id));
@@ -0,0 +1,37 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { isAbsolute, join, relative } from "node:path";
3
+ import type { ActiveRun } from "./types.ts";
4
+ import { runRoot } from "./paths.ts";
5
+ import { isSourceLikePath } from "./path-policy.ts";
6
+
7
+ export const SDK_SIGNATURE_EVIDENCE = "evidence/sdk-signature.md";
8
+
9
+ export function requiresSdkSignatureEvidence(run: ActiveRun): boolean {
10
+ const language = run.profile?.language;
11
+ return language === "java" || language === "csharp";
12
+ }
13
+
14
+ export function hasValidSdkSignatureEvidence(cwd: string, run: ActiveRun): boolean {
15
+ if (!requiresSdkSignatureEvidence(run)) return true;
16
+ const path = join(runRoot(cwd, run), SDK_SIGNATURE_EVIDENCE);
17
+ if (!existsSync(path)) return false;
18
+
19
+ const content = readFileSync(path, "utf8");
20
+ return /(退出码|Exit)\s*[::]\s*0/i.test(content) && /(来源|Sources?)\s*[::]/i.test(content);
21
+ }
22
+
23
+ export function sdkSignatureProductionWriteBlockReason(cwd: string, run: ActiveRun | undefined, path: string | undefined): string | undefined {
24
+ if (!run || run.phase !== "execute") return undefined;
25
+ if (!requiresSdkSignatureEvidence(run)) return undefined;
26
+ if (!path || !isSourceLikePath(path)) return undefined;
27
+
28
+ const normalized = normalizeRelativePath(cwd && isAbsolute(path) ? relative(cwd, path) : path);
29
+ if (normalized.startsWith(".pi/")) return undefined;
30
+ if (hasValidSdkSignatureEvidence(cwd, run)) return undefined;
31
+
32
+ return `不能写生产源码 ${normalized}:缺少本地 SDK 签名证据 ${SDK_SIGNATURE_EVIDENCE}。请先用 kd_sdk_signature 从当前项目真实 jar/dll 查证类、方法、构造器或属性签名;禁止凭记忆猜 SDK API。`;
33
+ }
34
+
35
+ function normalizeRelativePath(path: string): string {
36
+ return path.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/+/, "");
37
+ }
@@ -84,7 +84,7 @@ export function createActiveRun(cwd: string, goal: string, productInput?: string
84
84
  questions: [],
85
85
  gate: {
86
86
  passed: false,
87
- reason: "CONTEXT.md and product profile are required before moving to spec",
87
+ reason: "进入 spec 前必须先完成 CONTEXT.md 并确认产品画像",
88
88
  checkedAt: new Date().toISOString(),
89
89
  },
90
90
  };
@@ -161,21 +161,21 @@ export function updatePhaseArtifact(cwd: string, run: ActiveRun, phase: KdPhase,
161
161
  export function advanceRun(cwd: string, run: ActiveRun, requestedPhase?: KdPhase): { run: ActiveRun; message: string } {
162
162
  const target = requestedPhase ?? nextPhase(run.phase);
163
163
  if (!target) {
164
- return { run, message: `Run is already at final phase: ${run.phase}` };
164
+ return { run, message: `Run 已处于最终阶段:${run.phase}` };
165
165
  }
166
166
 
167
167
  const gate = canEnterPhase(cwd, run, target);
168
168
  if (!gate.passed) {
169
169
  run.gate = gate;
170
170
  writeActiveRun(cwd, run);
171
- return { run, message: gate.reason ?? `Cannot enter ${target}` };
171
+ return { run, message: gate.reason ?? `不能进入 ${target}` };
172
172
  }
173
173
 
174
174
  run.phase = target;
175
175
  ensurePhaseArtifact(cwd, run, target);
176
176
  run.gate = inspectGate(cwd, run);
177
177
  writeActiveRun(cwd, run);
178
- return { run, message: `Advanced Kingdee run to phase: ${target}` };
178
+ return { run, message: `已推进 Kingdee run 到阶段:${target}` };
179
179
  }
180
180
 
181
181
  export function refreshGate(cwd: string, run: ActiveRun): ActiveRun {
@@ -8,8 +8,8 @@ export const TDD_RED_EVIDENCE = "evidence/tdd-red.md";
8
8
  export const TDD_GREEN_EVIDENCE = "evidence/tdd-green.md";
9
9
 
10
10
  export function tddPlanBlockReason(plan: string): string | undefined {
11
- if (/##\s*TDD\s*\/\s*Red-Green Checks/i.test(plan)) return undefined;
12
- return "PLAN.md 缺少 ## TDD / Red-Green Checks。必须声明红灯验证、绿灯验证和无法自动化时的产品验证替代方案。";
11
+ if (/##\s*TDD\s*\/\s*红绿检查/i.test(plan)) return undefined;
12
+ return "PLAN.md 缺少 ## TDD / 红绿检查。必须声明红灯验证、绿灯验证和无法自动化时的产品验证替代方案。";
13
13
  }
14
14
 
15
15
  export function tddProductionWriteBlockReason(cwd: string, run: ActiveRun | undefined, path: string | undefined): string | undefined {
@@ -3,15 +3,15 @@ import type { SearchResult, TableSchema } from "./types.ts";
3
3
 
4
4
  export function formatSearchResults(query: string, results: SearchResult[], basePath: string): string {
5
5
  if (results.length === 0) {
6
- return `No Kingdee knowledge results found for "${query}".`;
6
+ return `未找到与 "${query}" 相关的金蝶知识库结果。`;
7
7
  }
8
8
 
9
- const lines = [`Kingdee knowledge results for "${query}":`, ""];
9
+ const lines = [`"${query}" 的金蝶知识库结果:`, ""];
10
10
  for (let i = 0; i < results.length; i++) {
11
11
  const result = results[i];
12
12
  lines.push(`[${i + 1}] ${result.section.heading}`);
13
- lines.push(`Source: ${relative(basePath, result.file.path)}:${result.section.lineStart + 1}`);
14
- lines.push(`Score: ${result.score.toFixed(2)}`);
13
+ lines.push(`来源:${relative(basePath, result.file.path)}:${result.section.lineStart + 1}`);
14
+ lines.push(`相关度:${result.score.toFixed(2)}`);
15
15
  lines.push(result.highlights[0] || result.section.content.trim().split("\n").slice(0, 5).join("\n"));
16
16
  lines.push("");
17
17
  }
@@ -20,24 +20,24 @@ export function formatSearchResults(query: string, results: SearchResult[], base
20
20
 
21
21
  export function formatTableSchema(tableName: string, schema: TableSchema | undefined): string {
22
22
  if (!schema) {
23
- return `No table schema found for "${tableName}".`;
23
+ return `未找到 "${tableName}" 的表结构。`;
24
24
  }
25
25
 
26
26
  const lines = [
27
- `Table: ${schema.name} (${tableName.toUpperCase()})`,
28
- `Module: ${schema.module || "unknown"}`,
29
- `Description: ${schema.description || "none"}`,
27
+ `表:${schema.name} (${tableName.toUpperCase()})`,
28
+ `模块:${schema.module || "未知"}`,
29
+ `说明:${schema.description || ""}`,
30
30
  "",
31
- "Fields:",
31
+ "字段:",
32
32
  ];
33
33
 
34
34
  for (const field of schema.fields) {
35
- const nullable = field.nullable ? "nullable" : "required";
35
+ const nullable = field.nullable ? "可空" : "必填";
36
36
  lines.push(`- ${field.name} ${field.type} ${nullable} - ${field.description}`);
37
37
  }
38
38
 
39
39
  if (schema.relatedTables.length > 0) {
40
- lines.push("", "Related tables:");
40
+ lines.push("", "相关表:");
41
41
  for (const related of schema.relatedTables) {
42
42
  lines.push(`- ${related.table}: ${related.relation} - ${related.description}`);
43
43
  }
@@ -45,4 +45,3 @@ export function formatTableSchema(tableName: string, schema: TableSchema | undef
45
45
 
46
46
  return lines.join("\n");
47
47
  }
48
-
@@ -24,61 +24,61 @@ const PROFILES: Record<KdProduct, ProductProfile> = {
24
24
  language: "unknown",
25
25
  knowledgeScope: "common",
26
26
  requiresMetadataVerification: true,
27
- notes: ["Product is not selected; do not assume Java, C#, BOS, Cosmic, or KSQL rules."],
27
+ notes: ["尚未选择产品;不要假设 JavaC#、BOSCosmic KSQL 规则。"],
28
28
  },
29
29
  flagship: {
30
30
  product: "flagship",
31
- displayName: "Kingdee Xingkong Flagship",
31
+ displayName: "金蝶星空旗舰版",
32
32
  platform: "cosmic",
33
33
  techStack: "java-cosmic",
34
34
  language: "java",
35
35
  knowledgeScope: "flagship",
36
36
  requiresMetadataVerification: true,
37
37
  notes: [
38
- "Xingkong Flagship is Cosmic-family. Use Cosmic metadata, plugin lifecycle, SDK, and post-check constraints.",
39
- "Place product code under the workspace code/ directory when that directory exists.",
40
- "Before creating or editing code, inspect the existing project structure under code/ and follow its actual layout, whether it is organized by cloud, app, or no module split.",
38
+ "星空旗舰版属于 Cosmic 家族。使用 Cosmic 元数据、插件生命周期、SDK 和后置检查约束。",
39
+ "如果当前工作区存在 code/ 目录,产品代码应放在 code/ 下。",
40
+ "创建或编辑代码前,必须检查 code/ 下真实项目结构,并跟随其实际布局;可能按云、按应用组织,也可能不分模块。",
41
41
  ],
42
42
  },
43
43
  cosmic: {
44
44
  product: "cosmic",
45
- displayName: "Kingdee Cosmic Platform",
45
+ displayName: "金蝶 Cosmic 平台",
46
46
  platform: "cosmic",
47
47
  techStack: "java-cosmic",
48
48
  language: "java",
49
49
  knowledgeScope: "cosmic",
50
50
  requiresMetadataVerification: true,
51
- notes: ["Cosmic is the shared platform base for Cangqiong, Xinghan, and Xingkong Flagship."],
51
+ notes: ["Cosmic 是苍穹、星瀚和星空旗舰版的共享平台基础。"],
52
52
  },
53
53
  xinghan: {
54
54
  product: "xinghan",
55
- displayName: "Kingdee Xinghan",
55
+ displayName: "金蝶星瀚",
56
56
  platform: "cosmic",
57
57
  techStack: "java-cosmic",
58
58
  language: "java",
59
59
  knowledgeScope: "xinghan",
60
60
  requiresMetadataVerification: true,
61
- notes: ["Treat as Cosmic-family Java unless a Xinghan-specific rule overrides it."],
61
+ notes: ["除非存在星瀚特有规则,否则按 Cosmic 家族 Java 处理。"],
62
62
  },
63
63
  cangqiong: {
64
64
  product: "cangqiong",
65
- displayName: "Kingdee Cangqiong",
65
+ displayName: "金蝶苍穹",
66
66
  platform: "cosmic",
67
67
  techStack: "java-cosmic",
68
68
  language: "java",
69
69
  knowledgeScope: "cangqiong",
70
70
  requiresMetadataVerification: true,
71
- notes: ["Use Cangqiong/Cosmic plugin, SDK, metadata, KSQL, and lifecycle rules."],
71
+ notes: ["使用苍穹/Cosmic 插件、SDK、元数据、KSQL 和生命周期规则。"],
72
72
  },
73
73
  enterprise: {
74
74
  product: "enterprise",
75
- displayName: "Kingdee Enterprise",
75
+ displayName: "金蝶企业版",
76
76
  platform: "enterprise-csharp",
77
77
  techStack: "csharp-bos",
78
78
  language: "csharp",
79
79
  knowledgeScope: "enterprise",
80
80
  requiresMetadataVerification: true,
81
- notes: ["Use enterprise C# stack. Java plugin rules and Cosmic APIs are not applicable."],
81
+ notes: ["使用企业版 C# 技术栈。Java 插件规则和 Cosmic API 不适用。"],
82
82
  },
83
83
  };
84
84
 
@@ -101,9 +101,9 @@ function enterprisePythonProfile(): ProductProfile {
101
101
  language: "python",
102
102
  knowledgeScope: "enterprise-python",
103
103
  notes: [
104
- "Use Kingdee Cloud Enterprise / BOS IronPython plugin patterns only when the user explicitly asks for Python plugin or IronPython script.",
105
- "Default Enterprise plugin work remains C# unless Python plugin is explicitly requested.",
106
- "Python plugins run in BOS through IronPython and call Kingdee.BOS .NET assemblies; verify plugin type, event, FormId, field keys, and registration steps before coding.",
104
+ "只有用户明确要求 Python 插件或 IronPython 脚本时,才使用金蝶云企业版 / BOS IronPython 插件模式。",
105
+ "企业版默认插件开发仍按 C# 处理,除非用户明确要求 Python 插件。",
106
+ "Python 插件通过 BOS 中的 IronPython 运行,并调用 Kingdee.BOS .NET 程序集;编码前必须确认插件类型、事件、FormId、字段标识和注册步骤。",
107
107
  ],
108
108
  };
109
109
  }