kcode-pi 0.1.34 → 0.1.35
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 +10 -10
- package/dist/cli/kcode.js +3 -3
- package/dist/context/project-context.js +3 -3
- package/docs/CHANGELOG.md +28 -2
- package/docs/COMMAND_REFERENCE.md +10 -10
- package/docs/DEVELOPMENT.md +3 -3
- package/docs/EVIDENCE_AND_GATES.md +8 -8
- package/docs/HARNESS_WORKFLOW.md +12 -12
- package/docs/KCODE_DISTRIBUTION.md +7 -7
- package/docs/PRODUCT_PROFILE.md +9 -9
- package/docs/TROUBLESHOOTING.md +8 -8
- package/docs/USER_GUIDE.md +10 -10
- package/extensions/kingdee-harness.ts +52 -49
- package/extensions/kingdee-header.ts +1 -1
- package/extensions/kingdee-subagents.ts +1 -1
- package/extensions/kingdee-tools.ts +44 -44
- package/package.json +1 -1
- package/src/cli/kcode.ts +3 -3
- package/src/context/project-context.ts +3 -3
- package/src/harness/artifacts.ts +6 -7
- package/src/harness/data-source-policy.ts +302 -0
- package/src/harness/delegation.ts +23 -23
- package/src/harness/gates.ts +16 -1
- package/src/harness/messages.ts +65 -11
- package/src/harness/path-policy.ts +1 -0
- package/src/harness/plan-steps.ts +3 -3
- package/src/harness/prompt-policy.ts +196 -0
- package/src/harness/prompt.ts +8 -16
- package/src/harness/repair.ts +2 -2
- package/src/harness/state.ts +1 -1
- package/src/official/kingdee-skills.ts +4 -4
- package/src/product/profile.ts +2 -2
- package/src/rules/checker.ts +27 -27
- package/src/tools/build-debug.ts +5 -5
- package/src/tools/sdk-signature.ts +4 -4
|
@@ -21,29 +21,29 @@ export interface ParsedDelegationArgs extends DelegationRequest {
|
|
|
21
21
|
const ROLE_GUIDANCE: Record<DelegationRole, string[]> = {
|
|
22
22
|
research: [
|
|
23
23
|
"只读调研项目、文档、SDK 线索和现有实现。",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
24
|
+
"输出压缩结论、证据文件/代码位置、风险和下一步指令。",
|
|
25
|
+
"禁止修改文件;禁止推进 Harness 状态。",
|
|
26
26
|
],
|
|
27
27
|
doc: [
|
|
28
28
|
"只写当前任务明确要求的文档或阶段产物。",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
29
|
+
"修改阶段文档时,内容必须匹配当前 Harness 阶段。",
|
|
30
|
+
"禁止修改产品源码;禁止推进 Harness 状态。",
|
|
31
31
|
],
|
|
32
32
|
code: [
|
|
33
33
|
"只有当前 run 处于 execute 阶段时才允许修改产品代码。",
|
|
34
|
-
"只修改 PLAN.md
|
|
35
|
-
"
|
|
34
|
+
"只修改 PLAN.md 批准的文件;发现新文件需求时停止并说明必须回到 plan。",
|
|
35
|
+
"完成后列出变更文件、执行步骤证据和主 agent 必须执行的验证命令。",
|
|
36
36
|
],
|
|
37
37
|
review: [
|
|
38
38
|
"只读交叉自查,不修改文件。",
|
|
39
|
-
"
|
|
39
|
+
"审查重点:bug、状态机漏洞、门禁绕过、证据缺口和测试缺口。",
|
|
40
40
|
"输出 findings,按严重程度排序并带文件/函数引用;明确是否阻止发布。",
|
|
41
41
|
],
|
|
42
42
|
verify: [
|
|
43
43
|
"只读分析计划中的验证命令、失败证据和风险。",
|
|
44
|
-
"
|
|
44
|
+
"实际运行验证由主 agent 执行;子 agent 输出命令和原因。",
|
|
45
45
|
"验证结果由主 agent 通过 kd_verify_result 记录。",
|
|
46
|
-
"
|
|
46
|
+
"禁止绕过 Harness 的 VERIFY/evidence 记录闭环。",
|
|
47
47
|
],
|
|
48
48
|
};
|
|
49
49
|
|
|
@@ -55,12 +55,12 @@ const ROLE_ALLOWED_WRITES: Record<DelegationRole, string> = {
|
|
|
55
55
|
verify: "evidence-through-kd_verify_result",
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
export const DEFAULT_REVIEW_TASK = "审查当前 run
|
|
58
|
+
export const DEFAULT_REVIEW_TASK = "审查当前 run 和最近变更,重点找状态机漏洞、门禁绕过、证据缺口、工程指令分散和测试缺口。";
|
|
59
59
|
export const CHILD_AGENT_USER_TASK = "执行 KCode 子 agent 委派任务。";
|
|
60
60
|
export const KD_SUBAGENT_TOOL_DESCRIPTION =
|
|
61
61
|
"将调研、文档、代码、验证或交叉审查任务委派给隔离 Pi 子进程。主 Harness 仍负责阶段推进、证据和门禁。";
|
|
62
62
|
export const KD_DELEGATE_USAGE = "用法:/kd-delegate <research|doc|code|review|verify> <任务> [--dry-run]";
|
|
63
|
-
export const KD_SUBAGENT_INVALID_PARAMS = "kd_subagent
|
|
63
|
+
export const KD_SUBAGENT_INVALID_PARAMS = "kd_subagent 参数要求:role=research|doc|code|review|verify 且 task 非空,或提供 tasks/chain。";
|
|
64
64
|
export const KD_SUBAGENT_PARALLEL_ROLE_ERROR = "kd_subagent 并行模式只允许 research、review、verify 这类只读角色。doc/code 必须串行执行。";
|
|
65
65
|
export const KD_REVIEW_COMMAND_DESCRIPTION = "启动只读交叉自查子 agent:/kd-review [审查重点]";
|
|
66
66
|
export const KD_DELEGATE_COMMAND_DESCRIPTION = "委派任务给隔离子 agent:/kd-delegate <research|doc|code|review|verify> <任务> [--dry-run]";
|
|
@@ -97,10 +97,10 @@ export function parseDelegationArgs(args: string): ParsedDelegationArgs | undefi
|
|
|
97
97
|
|
|
98
98
|
export function delegationBlockReason(role: DelegationRole, run: ActiveRun | undefined): string | undefined {
|
|
99
99
|
if (role === "code") {
|
|
100
|
-
if (!run) return "code 子 agent
|
|
100
|
+
if (!run) return "code 子 agent 要求 active Harness run,且必须处于 execute 阶段。";
|
|
101
101
|
if (run.phase !== "execute") return `code 子 agent 只能在 execute 阶段运行;当前阶段:${run.phase}。`;
|
|
102
102
|
}
|
|
103
|
-
if (role === "verify" && !run) return "verify 子 agent
|
|
103
|
+
if (role === "verify" && !run) return "verify 子 agent 要求 active Harness run。";
|
|
104
104
|
return undefined;
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -142,7 +142,7 @@ export function subagentToolCallBlockReason(input: {
|
|
|
142
142
|
sourceWriteBlockReason?: string;
|
|
143
143
|
}): string | undefined {
|
|
144
144
|
if (SHELL_TOOL_NAMES.has(input.toolName)) {
|
|
145
|
-
return "子 agent
|
|
145
|
+
return "子 agent 禁止调用 shell 类工具;运行命令由主 agent 执行,子 agent 只输出命令和原因。";
|
|
146
146
|
}
|
|
147
147
|
if (!WRITE_TOOL_NAMES.has(input.toolName)) return undefined;
|
|
148
148
|
|
|
@@ -164,19 +164,19 @@ export function subagentToolCallBlockReason(input: {
|
|
|
164
164
|
|
|
165
165
|
export function buildDelegationCommandPrompt(request: DelegationRequest, dryRun: boolean): string {
|
|
166
166
|
return [
|
|
167
|
-
"
|
|
167
|
+
"执行 kd_subagent 委派任务。",
|
|
168
168
|
`role: ${request.role}`,
|
|
169
169
|
`dryRun: ${dryRun ? "true" : "false"}`,
|
|
170
170
|
"task:",
|
|
171
171
|
request.task,
|
|
172
172
|
"",
|
|
173
|
-
"子 agent
|
|
173
|
+
"子 agent 返回后,主 agent 负责采纳结论、修改文件、记录 evidence 或推进 Harness。",
|
|
174
174
|
].join("\n");
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
export function delegationGuidanceForWorkflow(): string {
|
|
178
178
|
return [
|
|
179
|
-
"-
|
|
179
|
+
"- 任务包含大量调研、独立交叉审查、长上下文复盘或可并行拆分内容时,使用 kd_subagent。",
|
|
180
180
|
"- 自动委派只做旁路工作;主 agent 仍负责采纳结论、修改文件、记录 evidence 和推进阶段。",
|
|
181
181
|
"- code 委派只能在 execute 阶段且限于 PLAN.md 批准文件;review/research 默认只读。",
|
|
182
182
|
].join("\n");
|
|
@@ -192,7 +192,7 @@ export function buildChainedDelegationRequest(request: DelegationRequest, previo
|
|
|
192
192
|
"上一子 agent 输出:",
|
|
193
193
|
trimForPrompt(previousOutput, 6000),
|
|
194
194
|
"",
|
|
195
|
-
"
|
|
195
|
+
"基于上一输出继续当前步骤;仅交付本步骤结论。",
|
|
196
196
|
].join("\n"),
|
|
197
197
|
};
|
|
198
198
|
}
|
|
@@ -217,8 +217,8 @@ export function buildDelegationPrompt(cwd: string, run: ActiveRun | undefined, r
|
|
|
217
217
|
"",
|
|
218
218
|
"角色规则:",
|
|
219
219
|
...roleGuidance.map((item) => `- ${item}`),
|
|
220
|
-
"-
|
|
221
|
-
"-
|
|
220
|
+
"- 子 agent 不是主状态机;禁止调用 /kd-advance、/kd-finish 或改变 run 生命周期。",
|
|
221
|
+
"- 禁止创建子 agent;输出结果交回主 agent 统一决策。",
|
|
222
222
|
"",
|
|
223
223
|
"Harness 状态:",
|
|
224
224
|
status,
|
|
@@ -227,13 +227,13 @@ export function buildDelegationPrompt(cwd: string, run: ActiveRun | undefined, r
|
|
|
227
227
|
phaseContext,
|
|
228
228
|
"",
|
|
229
229
|
"项目上下文:",
|
|
230
|
-
projectContext ? trimForPrompt(projectContext, 1200) : "
|
|
230
|
+
projectContext ? trimForPrompt(projectContext, 1200) : "未生成。项目结构缺失时读取本地文件;无法读取时要求主 agent 运行 `kcode context --refresh`。",
|
|
231
231
|
"",
|
|
232
232
|
"输出格式:",
|
|
233
233
|
"- 结论",
|
|
234
234
|
"- 证据/引用",
|
|
235
235
|
"- 风险",
|
|
236
|
-
"-
|
|
236
|
+
"- 主 agent 下一步指令",
|
|
237
237
|
].join("\n");
|
|
238
238
|
}
|
|
239
239
|
|
|
@@ -268,7 +268,7 @@ function artifactSection(cwd: string, run: ActiveRun, phase: KdPhase): string |
|
|
|
268
268
|
|
|
269
269
|
function trimForPrompt(content: string, maxLength: number): string {
|
|
270
270
|
if (content.length <= maxLength) return content;
|
|
271
|
-
return `${content.slice(0, maxLength)}\n\n[
|
|
271
|
+
return `${content.slice(0, maxLength)}\n\n[...已截断;完整内容读取本地文件...]`;
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
function isDocWritablePath(cwd: string, run: ActiveRun | undefined, path: string | undefined): boolean {
|
package/src/harness/gates.ts
CHANGED
|
@@ -8,6 +8,13 @@ import { flagshipPlanBlockReason } from "./path-policy.ts";
|
|
|
8
8
|
import { executionStepsBlockReason, planStepsBlockReason } from "./plan-steps.ts";
|
|
9
9
|
import { tddPlanBlockReason, tddVerifyBlockReason } from "./tdd-policy.ts";
|
|
10
10
|
import { SDK_SIGNATURE_EVIDENCE, hasValidSdkSignatureEvidence, requiresSdkSignatureEvidence } from "./sdk-policy.ts";
|
|
11
|
+
import {
|
|
12
|
+
COSMIC_METADATA_EVIDENCE,
|
|
13
|
+
dataSourceContextBlockReason,
|
|
14
|
+
dataSourceEvidenceForRun,
|
|
15
|
+
hasValidDataSourceEvidence,
|
|
16
|
+
requiresDataSourceEvidence,
|
|
17
|
+
} from "./data-source-policy.ts";
|
|
11
18
|
import { runRoot } from "./paths.ts";
|
|
12
19
|
import { EVIDENCE_INDEX, readEvidenceIndex } from "./evidence.ts";
|
|
13
20
|
import {
|
|
@@ -28,7 +35,6 @@ const REQUIRED_MARKERS: Partial<Record<KdPhase, string[]>> = {
|
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
const COSMIC_CONFIG_EVIDENCE = "evidence/cosmic-config.txt";
|
|
31
|
-
const COSMIC_METADATA_EVIDENCE = "evidence/cosmic-metadata.json";
|
|
32
38
|
const COSMIC_API_EVIDENCE = "evidence/cosmic-api.txt";
|
|
33
39
|
const KSQL_LINT_EVIDENCE = "evidence/ksql-lint.txt";
|
|
34
40
|
|
|
@@ -69,6 +75,7 @@ function collectGateProblems(cwd: string, run: ActiveRun, phase: KdPhase, mode:
|
|
|
69
75
|
|
|
70
76
|
const markerProblem = mode === "inspect" ? inspectMarkers(cwd, run, phase) : undefined;
|
|
71
77
|
const flagshipPathProblem = mode === "enter" && phase === "execute" ? flagshipPlanBlockReason(cwd, run, readArtifact(cwd, run, "plan") ?? "") : undefined;
|
|
78
|
+
const dataSourceContextProblem = phaseIndex >= PHASE_ORDER.indexOf("execute") ? dataSourceContextBlockReason(cwd, run) : undefined;
|
|
72
79
|
const stepProblem = inspectStepState(cwd, run, phase);
|
|
73
80
|
const evidenceProblem = mode === "inspect" ? inspectEvidence(cwd, run, phase) : undefined;
|
|
74
81
|
const questionProblem = inspectOpenQuestions(run);
|
|
@@ -77,6 +84,9 @@ function collectGateProblems(cwd: string, run: ActiveRun, phase: KdPhase, mode:
|
|
|
77
84
|
if (flagshipPathProblem) {
|
|
78
85
|
reasonParts.push(flagshipPathProblem);
|
|
79
86
|
}
|
|
87
|
+
if (dataSourceContextProblem) {
|
|
88
|
+
reasonParts.push(dataSourceContextProblem);
|
|
89
|
+
}
|
|
80
90
|
if (markerProblem) {
|
|
81
91
|
reasonParts.push(markerProblem);
|
|
82
92
|
}
|
|
@@ -204,6 +214,10 @@ function requiredEvidenceForPhase(cwd: string, run: ActiveRun, phase: KdPhase):
|
|
|
204
214
|
|
|
205
215
|
if (phaseIndex >= PHASE_ORDER.indexOf("execute")) {
|
|
206
216
|
if (requiresSdkSignatureEvidence(run)) required.add(SDK_SIGNATURE_EVIDENCE);
|
|
217
|
+
if (requiresDataSourceEvidence(cwd, run)) {
|
|
218
|
+
const evidence = dataSourceEvidenceForRun(run);
|
|
219
|
+
if (evidence) required.add(evidence);
|
|
220
|
+
}
|
|
207
221
|
if (isCosmicRun(run)) {
|
|
208
222
|
required.add(COSMIC_CONFIG_EVIDENCE);
|
|
209
223
|
if (planHasMetadataRequirement(cwd, run)) required.add(COSMIC_METADATA_EVIDENCE);
|
|
@@ -221,6 +235,7 @@ function requiredEvidenceForPhase(cwd: string, run: ActiveRun, phase: KdPhase):
|
|
|
221
235
|
|
|
222
236
|
function evidenceArtifactSatisfied(cwd: string, run: ActiveRun, artifact: string): boolean {
|
|
223
237
|
if (artifact === SDK_SIGNATURE_EVIDENCE) return hasValidSdkSignatureEvidence(cwd, run);
|
|
238
|
+
if (artifact === dataSourceEvidenceForRun(run)) return hasValidDataSourceEvidence(cwd, run);
|
|
224
239
|
if (artifact === EVIDENCE_INDEX) return existsSync(join(runRoot(cwd, run), artifact));
|
|
225
240
|
return existsSync(join(runRoot(cwd, run), artifact)) && hasSuccessfulEvidenceEntry(cwd, run, artifact);
|
|
226
241
|
}
|
package/src/harness/messages.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { KdPhase } from "./types.ts";
|
|
2
2
|
import { PHASE_ARTIFACTS } from "./types.ts";
|
|
3
|
+
import {
|
|
4
|
+
DATA_SOURCE_CONTEXT_FIELDS,
|
|
5
|
+
IMPLEMENTATION_CONTRACT_FIELDS,
|
|
6
|
+
INTEGRATION_CONTEXT_FIELDS,
|
|
7
|
+
fieldLabels,
|
|
8
|
+
questionForMissingLabel,
|
|
9
|
+
} from "./prompt-policy.ts";
|
|
3
10
|
|
|
4
11
|
export function unknownProductReason(declaration: boolean | undefined): string {
|
|
5
12
|
if (declaration === undefined) {
|
|
6
|
-
return "不能进入 execute:产品画像未知,且 PLAN.md 未明确声明是否涉及产品实现、构建、元数据或 SDK
|
|
13
|
+
return "不能进入 execute:产品画像未知,且 PLAN.md 未明确声明是否涉及产品实现、构建、元数据或 SDK 查证。下一步:根据当前需求和项目计划判断范围;涉及产品实现时执行 /kd-product <flagship|xinghan|cangqiong|enterprise>;不涉及时在 PLAN.md 的“产品实现范围”写明“不涉及”及依据。";
|
|
7
14
|
}
|
|
8
|
-
return "不能进入 execute:PLAN.md 声明涉及产品实现、构建、元数据或 SDK 查证,但产品画像未知。下一步:根据需求、计划或用户回答确认产品,然后执行 /kd-product <flagship|xinghan|cangqiong|enterprise
|
|
15
|
+
return "不能进入 execute:PLAN.md 声明涉及产品实现、构建、元数据或 SDK 查证,但产品画像未知。下一步:根据需求、计划或用户回答确认产品,然后执行 /kd-product <flagship|xinghan|cangqiong|enterprise>;无法判断时使用 kd_question 登记一个最阻塞的产品确认问题。";
|
|
9
16
|
}
|
|
10
17
|
|
|
11
18
|
export function unknownRiskReason(): string {
|
|
@@ -15,7 +22,7 @@ export function unknownRiskReason(): string {
|
|
|
15
22
|
export function openQuestionsReason(questions: Array<{ id: string; question: string }>): string {
|
|
16
23
|
return [
|
|
17
24
|
`存在未回答的阻断问题:${questions.map((question) => `${question.id} ${question.question}`).join(";")}`,
|
|
18
|
-
"
|
|
25
|
+
"下一步:获取用户答案,然后用 kd_question action=answer id=<问题编号> answer=<用户答案> 记录。",
|
|
19
26
|
].join("。");
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -24,6 +31,33 @@ export function repairBlockedReason(attempts: number, maxAttempts: number, evide
|
|
|
24
31
|
return `自动修复已停止:验证失败 ${attempts}/${maxAttempts}${evidenceText}。下一步:回到 plan 调整范围,或重新创建/回答修复问题选择“继续修复”。`;
|
|
25
32
|
}
|
|
26
33
|
|
|
34
|
+
export function dataSourcePlanBlockedReason(missing: string[]): string {
|
|
35
|
+
return [
|
|
36
|
+
`不能进入 execute:业务数据源上下文不完整,缺少 ${missing.join("、")}。`,
|
|
37
|
+
`下一步:停止编码,使用 kd_question 逐项确认 ${fieldLabels(DATA_SOURCE_CONTEXT_FIELDS).join("、")}。`,
|
|
38
|
+
nextQuestionInstruction(missing),
|
|
39
|
+
"API 文档只能作为调用线索,不能替代这些业务事实。",
|
|
40
|
+
].filter(Boolean).join("");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function integrationPlanBlockedReason(missing: string[]): string {
|
|
44
|
+
return [
|
|
45
|
+
`不能进入 execute:第三方对接上下文不完整,缺少 ${missing.join("、")}。`,
|
|
46
|
+
`下一步:停止编码,使用 kd_question 逐项确认 ${fieldLabels(INTEGRATION_CONTEXT_FIELDS).join("、")}。`,
|
|
47
|
+
nextQuestionInstruction(missing),
|
|
48
|
+
"缺少这些信息时禁止生成模板代码。",
|
|
49
|
+
].filter(Boolean).join("");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function implementationPlanBlockedReason(missing: string[]): string {
|
|
53
|
+
return [
|
|
54
|
+
`不能进入 execute:实现就绪信息不完整,缺少 ${missing.join("、")}。`,
|
|
55
|
+
`下一步:禁止生成模板代码;使用 kd_question 按最阻塞项逐个确认 ${fieldLabels(IMPLEMENTATION_CONTRACT_FIELDS).join("、")}。`,
|
|
56
|
+
nextQuestionInstruction(missing),
|
|
57
|
+
"这些字段是所有插件、服务和集成实现的通用输入,不依赖具体业务场景枚举。",
|
|
58
|
+
].filter(Boolean).join("");
|
|
59
|
+
}
|
|
60
|
+
|
|
27
61
|
export function missingMarkerReason(phase: KdPhase, missing: string[]): string {
|
|
28
62
|
return `${PHASE_ARTIFACTS[phase]} 缺少必需章节:${missing.join(", ")}。下一步:更新 ${PHASE_ARTIFACTS[phase]},补齐这些章节并写入真实内容。`;
|
|
29
63
|
}
|
|
@@ -40,7 +74,7 @@ export function missingForTargetReason(target: KdPhase, artifacts: string[]): st
|
|
|
40
74
|
const documents = artifacts.filter((artifact) => !artifact.startsWith("evidence/"));
|
|
41
75
|
const actions: string[] = [];
|
|
42
76
|
if (documents.length > 0) {
|
|
43
|
-
actions.push(
|
|
77
|
+
actions.push(`补齐阶段文档 ${documents.join(", ")};可使用 /kd-artifact 创建模板后填入真实分析、计划或验证内容`);
|
|
44
78
|
}
|
|
45
79
|
if (evidence.length > 0) {
|
|
46
80
|
actions.push(evidenceAction(evidence));
|
|
@@ -61,9 +95,11 @@ export function evidenceArtifactAction(artifact: string): string {
|
|
|
61
95
|
case "evidence/sdk-signature.md":
|
|
62
96
|
return "运行 kd_sdk_signature,从当前项目真实 SDK jar/dll 查证类、方法、构造器或属性签名,成功后自动写入 evidence/sdk-signature.md";
|
|
63
97
|
case "evidence/cosmic-config.txt":
|
|
64
|
-
return "运行 kd_cosmic_config 生成 evidence/cosmic-config.txt
|
|
98
|
+
return "运行 kd_cosmic_config 生成 evidence/cosmic-config.txt;项目没有 ok-cosmic.json 时使用 KCode 默认配置";
|
|
65
99
|
case "evidence/cosmic-metadata.json":
|
|
66
100
|
return "运行 kd_cosmic_metadata 查询目标表单/单据/字段元数据并生成 evidence/cosmic-metadata.json";
|
|
101
|
+
case "evidence/data-source.md":
|
|
102
|
+
return "写入真实数据源证据 evidence/data-source.md,至少包含目标 FormId/单据或表单、字段/实体标识、表或数据来源、验证来源和测试数据;禁止只引用 API 文档";
|
|
67
103
|
case "evidence/cosmic-api.txt":
|
|
68
104
|
return "运行 kd_cosmic_api 查询相关 Cosmic API 线索并生成 evidence/cosmic-api.txt,再用 kd_sdk_signature 或构建输出确认签名";
|
|
69
105
|
case "evidence/ksql-lint.txt":
|
|
@@ -74,7 +110,7 @@ export function evidenceArtifactAction(artifact: string): string {
|
|
|
74
110
|
}
|
|
75
111
|
|
|
76
112
|
export function flagshipWriteBlockedReason(path: string): string {
|
|
77
|
-
return `星空旗舰版代码必须跟随当前项目结构写入 code/ 下,不能写到 ${path}
|
|
113
|
+
return `星空旗舰版代码必须跟随当前项目结构写入 code/ 下,不能写到 ${path}。下一步:读取当前项目 code/ 下的真实模块结构,在 PLAN.md 记录目标源码路径,再把写入路径改为 code/... 下的项目相对路径。`;
|
|
78
114
|
}
|
|
79
115
|
|
|
80
116
|
export function planWriteBlockedReason(path: string): string {
|
|
@@ -82,11 +118,11 @@ export function planWriteBlockedReason(path: string): string {
|
|
|
82
118
|
}
|
|
83
119
|
|
|
84
120
|
export function flagshipPlanNeedsCodePathReason(): string {
|
|
85
|
-
return "不能进入 execute:星空旗舰版 PLAN.md
|
|
121
|
+
return "不能进入 execute:星空旗舰版 PLAN.md 必须记录当前项目 code/ 下的实际目标路径。下一步:列出 code/ 下模块,识别当前项目是按云、按应用还是不分模块组织,在 PLAN.md 写明真实目标文件。";
|
|
86
122
|
}
|
|
87
123
|
|
|
88
124
|
export function flagshipPlanNeedsSourcePathReason(): string {
|
|
89
|
-
return "不能进入 execute:PLAN.md
|
|
125
|
+
return "不能进入 execute:PLAN.md 必须记录已检查当前项目结构,并写明实际源码根或目标文件路径。下一步:读取构建文件和 src/lib/bin 等目录,确认源码根后写入 PLAN.md 的 ## 已检查的项目结构、## 目标源码根 / 路径 和 ## 允许修改的文件。";
|
|
90
126
|
}
|
|
91
127
|
|
|
92
128
|
export function tddPlanMissingReason(): string {
|
|
@@ -94,7 +130,7 @@ export function tddPlanMissingReason(): string {
|
|
|
94
130
|
}
|
|
95
131
|
|
|
96
132
|
export function tddProductionMissingRedReason(path: string, evidenceName: string): string {
|
|
97
|
-
return `不能写生产源码 ${path}:缺少红灯证据 ${evidenceName}
|
|
133
|
+
return `不能写生产源码 ${path}:缺少红灯证据 ${evidenceName}。下一步:运行一个实现前应失败的检查,例如 kd_sdk_signature 方法不存在检查、元数据/API 检查、编译检查、kd_check、项目已有测试或外部接口最小验证;把命令、非 0 Exit 或失败输出写入 evidence/tdd-red.md 后再写生产源码。`;
|
|
98
134
|
}
|
|
99
135
|
|
|
100
136
|
export function tddVerifyBlockedReason(reasons: string[]): string {
|
|
@@ -106,13 +142,31 @@ export function tddVerifyBlockedReason(reasons: string[]): string {
|
|
|
106
142
|
}
|
|
107
143
|
|
|
108
144
|
export function redEvidenceInvalidReason(evidenceName: string): string {
|
|
109
|
-
return `${evidenceName}
|
|
145
|
+
return `${evidenceName} 内容无效:必须包含真实失败输出或非 0 退出码`;
|
|
110
146
|
}
|
|
111
147
|
|
|
112
148
|
export function greenEvidenceInvalidReason(evidenceName: string): string {
|
|
113
|
-
return `${evidenceName}
|
|
149
|
+
return `${evidenceName} 内容无效:绿灯证据必须同时包含成功结论和 Exit: 0/退出码:0`;
|
|
114
150
|
}
|
|
115
151
|
|
|
116
152
|
export function sdkSignatureWriteBlockedReason(path: string, evidenceName: string): string {
|
|
117
153
|
return `不能写生产源码 ${path}:缺少本地 SDK 签名证据 ${evidenceName}。下一步:运行 kd_sdk_signature,从当前项目真实 jar/dll 查证即将使用的 SDK 类、方法、构造器或属性签名;成功生成 evidence/sdk-signature.md 后再写代码。禁止凭记忆或随包知识库猜 SDK API。`;
|
|
118
154
|
}
|
|
155
|
+
|
|
156
|
+
export function dataSourceWriteBlockedReason(path: string, evidenceName: string): string {
|
|
157
|
+
return `不能写生产源码 ${path}:缺少真实数据源/元数据证据 ${evidenceName}。下一步:确认目标 FormId、单据/表单、字段/实体、表或数据来源和测试数据;API 文档只能证明调用方式,不能证明当前业务数据源存在。`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function integrationWriteBlockedReason(path: string, missing: string[]): string {
|
|
161
|
+
return `不能写生产源码 ${path}:第三方对接上下文不完整,缺少 ${missing.join("、")}。下一步:补齐 ${fieldLabels(INTEGRATION_CONTEXT_FIELDS).join("、")}。`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function implementationWriteBlockedReason(path: string, missing: string[]): string {
|
|
165
|
+
return `不能写生产源码 ${path}:实现就绪信息不完整,缺少 ${missing.join("、")}。下一步:确认 ${fieldLabels(IMPLEMENTATION_CONTRACT_FIELDS).join("、")};信息不足时继续提问,禁止生成模板代码。`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function nextQuestionInstruction(missing: string[]): string | undefined {
|
|
169
|
+
const question = questionForMissingLabel(missing[0]);
|
|
170
|
+
if (!question) return undefined;
|
|
171
|
+
return `阻断问题命令:kd_question action=ask question="${question}" reason="${missing[0]} 缺失会阻塞实现。"。`;
|
|
172
|
+
}
|
|
@@ -22,12 +22,12 @@ export function parsePlanSteps(plan: string): PlanStep[] {
|
|
|
22
22
|
|
|
23
23
|
export function planStepsBlockReason(plan: string): string | undefined {
|
|
24
24
|
if (!/##\s*执行步骤/i.test(plan)) {
|
|
25
|
-
return "PLAN.md 缺少 ## 执行步骤。下一步:回到 plan,补充 `##
|
|
25
|
+
return "PLAN.md 缺少 ## 执行步骤。下一步:回到 plan,补充 `## 执行步骤`;使用 `- [ ] STEP-001:...` 拆分可跟踪步骤;每一步必须产生代码变更或 evidence。";
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const steps = parsePlanSteps(plan);
|
|
29
29
|
if (steps.length === 0) {
|
|
30
|
-
return "PLAN.md 没有可执行步骤。下一步:在 `## 执行步骤` 下使用 `- [ ] STEP-001:...`
|
|
30
|
+
return "PLAN.md 没有可执行步骤。下一步:在 `## 执行步骤` 下使用 `- [ ] STEP-001:...` 列出步骤;禁止用普通段落代替可勾选步骤。";
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const duplicate = firstDuplicate(steps.map((step) => step.id));
|
|
@@ -56,7 +56,7 @@ export function executionStepsBlockReason(cwd: string, run: ActiveRun, plan: str
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (missing.length > 0) {
|
|
59
|
-
return `不能进入 verify:EXECUTION.md 未完成计划步骤 ${missing.join(", ")}
|
|
59
|
+
return `不能进入 verify:EXECUTION.md 未完成计划步骤 ${missing.join(", ")}。下一步:执行缺失步骤;完成后在 EXECUTION.md 的 ## 步骤结果 中使用 \`- [x] STEP-###:已完成。证据:evidence/step-###.md\` 记录;未执行完成时禁止勾选。`;
|
|
60
60
|
}
|
|
61
61
|
if (missingEvidence.length > 0) {
|
|
62
62
|
return `不能进入 verify:步骤 ${missingEvidence.join(", ")} 缺少已落地的 evidence 文件。下一步:为每个步骤创建真实 evidence 文件,写入检查命令、结果、改动文件或验证输出,然后在 EXECUTION.md 对应步骤行引用该 evidence 路径。`;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { KdPhase } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
export interface ContractField {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
aliases: string[];
|
|
7
|
+
question: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const IMPLEMENTATION_CONTRACT_FIELDS: ContractField[] = [
|
|
11
|
+
{
|
|
12
|
+
id: "trigger",
|
|
13
|
+
label: "触发入口或执行时机",
|
|
14
|
+
aliases: ["触发入口", "执行时机", "触发时机", "插件类型和事件", "入口事件"],
|
|
15
|
+
question: "该实现由哪个入口触发,执行时机是什么?",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "source",
|
|
19
|
+
label: "源对象/输入数据",
|
|
20
|
+
aliases: ["源对象", "源单", "输入数据", "数据来源", "取数来源"],
|
|
21
|
+
question: "实现读取的源对象或输入数据是什么?",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "target",
|
|
25
|
+
label: "目标对象/输出结果",
|
|
26
|
+
aliases: ["目标对象", "目标单据", "目标表单", "输出结果", "生成结果"],
|
|
27
|
+
question: "实现写入、生成或影响的目标对象是什么?",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "data-change",
|
|
31
|
+
label: "数据变化或字段映射",
|
|
32
|
+
aliases: ["数据变化", "字段映射", "字段对应", "字段改写", "赋值规则"],
|
|
33
|
+
question: "列出新增、修改、映射或保持不变的字段。",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "rules",
|
|
37
|
+
label: "业务规则和适用条件",
|
|
38
|
+
aliases: ["业务规则", "适用条件", "执行条件", "过滤条件", "前置条件"],
|
|
39
|
+
question: "该实现在哪些条件下执行,业务规则是什么?",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "failure",
|
|
43
|
+
label: "失败处理、回滚或人工处理方式",
|
|
44
|
+
aliases: ["失败处理", "异常处理", "错误处理", "回滚", "补偿", "人工处理"],
|
|
45
|
+
question: "失败、异常或重复执行时如何处理?",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "acceptance",
|
|
49
|
+
label: "验收样例或测试数据",
|
|
50
|
+
aliases: ["验收样例", "测试数据", "请求样例", "响应样例", "示例数据"],
|
|
51
|
+
question: "用于验收的样例数据和预期结果是什么?",
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
export const DATA_SOURCE_CONTEXT_FIELDS: ContractField[] = [
|
|
56
|
+
{
|
|
57
|
+
id: "target-form",
|
|
58
|
+
label: "目标 FormId/单据或表单标识",
|
|
59
|
+
aliases: ["目标 FormId", "FormId", "表单标识", "单据标识", "目标单据", "目标表单"],
|
|
60
|
+
question: "目标 FormId、单据或表单标识是什么?",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "plugin-hook",
|
|
64
|
+
label: "插件类型和触发事件",
|
|
65
|
+
aliases: ["插件类型", "触发事件", "生命周期", "挂载点", "插件类型和事件"],
|
|
66
|
+
question: "插件类型和触发事件是什么?",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "field-entity",
|
|
70
|
+
label: "字段/实体/分录标识",
|
|
71
|
+
aliases: ["字段标识", "实体标识", "分录标识", "单据体标识", "字段/实体标识"],
|
|
72
|
+
question: "涉及哪些字段、实体或分录标识?",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "data-access",
|
|
76
|
+
label: "数据读取写入方式",
|
|
77
|
+
aliases: ["数据读取写入方式", "读取方式", "写入方式", "数据访问", "取数方式"],
|
|
78
|
+
question: "数据通过表单模型、服务、SQL/KSQL 还是接口读取和写入?",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "sql-identifiers",
|
|
82
|
+
label: "SQL/KSQL 表名和数据库字段名",
|
|
83
|
+
aliases: ["SQL 表名", "KSQL 表名", "表名", "数据库字段名", "字段名"],
|
|
84
|
+
question: "SQL/KSQL 场景的表名和数据库字段名是什么?",
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
export const INTEGRATION_CONTEXT_FIELDS: ContractField[] = [
|
|
89
|
+
{
|
|
90
|
+
id: "interface-doc",
|
|
91
|
+
label: "接口文档来源/版本",
|
|
92
|
+
aliases: ["接口文档", "API 文档", "文档来源", "协议文档", "OpenAPI", "Swagger"],
|
|
93
|
+
question: "第三方接口文档来源和版本是什么?",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: "direction",
|
|
97
|
+
label: "对接方向和触发时机",
|
|
98
|
+
aliases: ["对接方向", "触发时机", "同步方向", "数据流向"],
|
|
99
|
+
question: "对接方向、调用方和触发时机是什么?",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "endpoint-auth",
|
|
103
|
+
label: "接口地址、认证和密钥配置方式",
|
|
104
|
+
aliases: ["接口地址", "认证", "鉴权", "密钥", "Token", "OAuth"],
|
|
105
|
+
question: "接口地址、认证方式和密钥配置方式是什么?",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "field-mapping",
|
|
109
|
+
label: "第三方字段到金蝶字段的映射",
|
|
110
|
+
aliases: ["字段映射", "映射关系", "字段对应", "字段对照"],
|
|
111
|
+
question: "第三方字段与金蝶字段如何对应?",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "concurrency",
|
|
115
|
+
label: "并发/幂等策略",
|
|
116
|
+
aliases: ["并发", "幂等", "去重", "唯一键", "重复提交"],
|
|
117
|
+
question: "并发、重复提交和幂等如何处理?",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "retry",
|
|
121
|
+
label: "超时、重试和限流策略",
|
|
122
|
+
aliases: ["超时", "重试", "限流", "频率", "熔断"],
|
|
123
|
+
question: "超时、重试和限流策略是什么?",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: "error",
|
|
127
|
+
label: "错误处理和失败补偿",
|
|
128
|
+
aliases: ["错误处理", "异常处理", "失败处理", "失败补偿", "告警"],
|
|
129
|
+
question: "接口失败、异常响应和补偿流程如何处理?",
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: "logging",
|
|
133
|
+
label: "日志、审计和敏感信息脱敏策略",
|
|
134
|
+
aliases: ["日志", "审计", "留痕", "脱敏", "敏感信息"],
|
|
135
|
+
question: "列出日志字段、审计留痕和敏感信息脱敏规则。",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "samples",
|
|
139
|
+
label: "请求/响应样例和验收数据",
|
|
140
|
+
aliases: ["请求样例", "响应样例", "报文样例", "验收数据", "payload"],
|
|
141
|
+
question: "请求样例、响应样例和验收数据是什么?",
|
|
142
|
+
},
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
export const PROMPT_STYLE_RULES = [
|
|
146
|
+
"使用正式、可执行的工程指令;禁止口语化、闲聊式、鼓励式表达。",
|
|
147
|
+
"事实不足时生成阻断问题;禁止输出模板代码、占位实现或基于猜测的业务标识。",
|
|
148
|
+
"每次只提出一个最阻塞问题;问题必须指向可验证事实、数据标识或验收证据。",
|
|
149
|
+
"引用顺序:当前项目文件、PLAN/SPEC、元数据 evidence、SDK 签名、验证输出。",
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
export const CORE_WORKFLOW_CONSTRAINTS = [
|
|
153
|
+
"产品代码只在 execute 阶段写入,并限于 PLAN.md 批准的文件。",
|
|
154
|
+
"写代码前必须具备通用实现契约:触发入口、源对象/输入数据、目标对象/输出结果、数据变化或字段映射、业务规则、失败处理和验收样例。",
|
|
155
|
+
"业务数据源未知时禁止编码;确认目标 FormId/单据或表单、插件类型和事件、字段/实体/分录标识、数据读取写入方式后再编码;SQL/KSQL 同步确认表名和数据库字段名。",
|
|
156
|
+
"第三方对接确认接口文档、对接方向、触发时机、认证配置、字段映射、并发/幂等、重试超时限流、错误补偿、日志脱敏和验收样例后再编码。",
|
|
157
|
+
"事实缺失时使用 kd_question 登记一个最阻塞问题;禁止用 API 文档、SDK 知识库或推测替代业务事实。",
|
|
158
|
+
"Java/C# SDK 签名以当前项目 jar/dll、构建输出或官方元数据为准。",
|
|
159
|
+
"Java/Cosmic 使用当前项目 Gradle;C#/企业版使用 dotnet build。",
|
|
160
|
+
"evidence 必须记录命令、Exit 和关键输出;命令无法运行时记录阻塞原因。",
|
|
161
|
+
"外部系统操作、BOS 注册、人工功能测试和生产环境验证不能由 LLM 代办;必须要求用户提供验证结果或可核验证据,并记录证据来源。",
|
|
162
|
+
"Windows 路径规则:项目相对路径为默认;绝对路径使用 D:\\... 形式。",
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
export const PHASE_GUIDANCE: Record<KdPhase, string> = {
|
|
166
|
+
discuss: "梳理需求来源、范围、已知事实;如缺通用实现契约、数据源或第三方接口关键事实,使用 kd_question 登记一个最阻塞问题。",
|
|
167
|
+
spec: "将需求转成验收标准、实现契约、数据对象、接口契约、异常行为、依赖和风险;数据对象和字段映射必须落到可核验标识。",
|
|
168
|
+
plan: "检查项目结构,写明目标路径、允许修改文件、通用实现契约、数据源/元数据查证项、第三方接口契约、插件挂载点、验证命令和回滚说明。",
|
|
169
|
+
execute: "按 PLAN.md 实现,记录步骤结果、变更文件和 evidence。",
|
|
170
|
+
verify: "运行计划中的验证命令,并用 kd_verify_result 记录结果;失败会回到 execute 修复,成功后更新 VERIFY.md、证据和残余风险。",
|
|
171
|
+
ship: "整理 SHIP.md,包括摘要、验证证据、风险和后续事项。",
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const PLAN_REQUIRED_CHECK_LINES = [
|
|
175
|
+
"涉及表单、单据、字段、实体、SQL/KSQL、数据读取写入或插件事件时,确认真实数据源/元数据后再编码;禁止只根据 API 文档编码。",
|
|
176
|
+
"Cosmic 家族数据源证据:evidence/cosmic-metadata.json;企业版/BOS 数据源证据:evidence/data-source.md。",
|
|
177
|
+
`所有产品代码实现必须写明通用实现契约后再编码:${IMPLEMENTATION_CONTRACT_FIELDS.map((field) => field.label).join("、")}。`,
|
|
178
|
+
`进入 execute 前必须写明:${DATA_SOURCE_CONTEXT_FIELDS.map((field) => field.label).join("、")}。`,
|
|
179
|
+
`第三方对接必须写明:${INTEGRATION_CONTEXT_FIELDS.map((field) => field.label).join("、")}。`,
|
|
180
|
+
"Java/C# 代码涉及 SDK 类、方法、构造器、枚举、属性时,使用 kd_sdk_signature 或项目构建输出确认真实签名后再编码。",
|
|
181
|
+
"知识库搜索、随包 Cosmic API 查询只能作为线索,不能作为最终方法签名事实。",
|
|
182
|
+
"SDK 签名证据:evidence/sdk-signature.md",
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
export function formatPromptLines(lines: string[]): string[] {
|
|
186
|
+
return lines.map((line) => `- ${line}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function fieldLabels(fields: ContractField[]): string[] {
|
|
190
|
+
return fields.map((field) => field.label);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function questionForMissingLabel(label: string): string | undefined {
|
|
194
|
+
const fields = [...IMPLEMENTATION_CONTRACT_FIELDS, ...DATA_SOURCE_CONTEXT_FIELDS, ...INTEGRATION_CONTEXT_FIELDS];
|
|
195
|
+
return fields.find((field) => field.label === label)?.question;
|
|
196
|
+
}
|
package/src/harness/prompt.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { delegationGuidanceForWorkflow, shouldInjectDelegationGuidance } from ".
|
|
|
4
4
|
import { formatStatus } from "./format.ts";
|
|
5
5
|
import type { ActiveRun, KdPhase } from "./types.ts";
|
|
6
6
|
import { PHASE_ORDER } from "./types.ts";
|
|
7
|
+
import { CORE_WORKFLOW_CONSTRAINTS, PHASE_GUIDANCE, PROMPT_STYLE_RULES, formatPromptLines } from "./prompt-policy.ts";
|
|
7
8
|
|
|
8
9
|
export function workflowPromptForRun(cwd: string, run: ActiveRun, userText: string): string {
|
|
9
10
|
const status = formatStatus(cwd, run);
|
|
@@ -23,17 +24,16 @@ export function workflowPromptForRun(cwd: string, run: ActiveRun, userText: stri
|
|
|
23
24
|
memory,
|
|
24
25
|
"",
|
|
25
26
|
"项目上下文:",
|
|
26
|
-
projectContext ? trimForPrompt(projectContext, 1200) : "
|
|
27
|
+
projectContext ? trimForPrompt(projectContext, 1200) : "未生成。项目结构缺失时运行 `kcode context --refresh`。",
|
|
27
28
|
"",
|
|
28
29
|
"当前阶段任务:",
|
|
29
30
|
phaseGuidance,
|
|
30
31
|
"",
|
|
32
|
+
"工程指令风格:",
|
|
33
|
+
...formatPromptLines(PROMPT_STYLE_RULES),
|
|
34
|
+
"",
|
|
31
35
|
"核心约束:",
|
|
32
|
-
|
|
33
|
-
"- Java/C# SDK 签名以当前项目 jar/dll、构建输出或官方元数据为准。",
|
|
34
|
-
"- Java/Cosmic 用当前项目 Gradle;C#/企业版用 dotnet build。",
|
|
35
|
-
"- evidence 记录命令、Exit 和关键输出;命令无法运行时记录阻塞原因。",
|
|
36
|
-
"- Windows 下优先使用项目相对路径;绝对路径使用 D:\\... 形式。",
|
|
36
|
+
...formatPromptLines(CORE_WORKFLOW_CONSTRAINTS),
|
|
37
37
|
...delegationGuidance,
|
|
38
38
|
].join("\n");
|
|
39
39
|
}
|
|
@@ -48,15 +48,7 @@ export function repairPromptForRun(run: ActiveRun): string {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
function phaseGuidanceForRun(phase: KdPhase): string {
|
|
51
|
-
|
|
52
|
-
discuss: "梳理需求来源、范围、已知事实和一个最阻塞的待确认问题。",
|
|
53
|
-
spec: "把需求转成验收标准、数据对象、异常行为、依赖和风险。",
|
|
54
|
-
plan: "检查项目结构,写明目标路径、允许修改文件、查证项、验证命令和回滚说明。",
|
|
55
|
-
execute: "按 PLAN.md 实现,记录步骤结果、变更文件和 evidence。",
|
|
56
|
-
verify: "运行计划中的验证命令,并用 kd_verify_result 记录结果;失败会回到 execute 修复,成功后更新 VERIFY.md、证据和残余风险。",
|
|
57
|
-
ship: "整理 SHIP.md,包括摘要、验证证据、风险和后续事项。",
|
|
58
|
-
};
|
|
59
|
-
return guidance[phase];
|
|
51
|
+
return PHASE_GUIDANCE[phase];
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
function workflowMemoryForRun(cwd: string, run: ActiveRun): string {
|
|
@@ -76,5 +68,5 @@ function workflowMemoryForRun(cwd: string, run: ActiveRun): string {
|
|
|
76
68
|
|
|
77
69
|
function trimForPrompt(content: string, maxLength: number): string {
|
|
78
70
|
if (content.length <= maxLength) return content;
|
|
79
|
-
return `${content.slice(0, maxLength)}\n\n[
|
|
71
|
+
return `${content.slice(0, maxLength)}\n\n[...已截断;完整内容读取本地文件...]`;
|
|
80
72
|
}
|