soloforge 1.2.19 → 1.2.20

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 (102) hide show
  1. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  2. package/dist/adapters/claude_code/tools.js +159 -1
  3. package/dist/adapters/claude_code/tools.js.map +1 -1
  4. package/dist/adapters/trae/trae_config.d.ts +1 -1
  5. package/dist/adapters/trae/trae_config.d.ts.map +1 -1
  6. package/dist/adapters/trae/trae_config.js +1 -1
  7. package/dist/adapters/trae/trae_config.js.map +1 -1
  8. package/dist/engine/audit_pool.d.ts.map +1 -1
  9. package/dist/engine/audit_pool.js +1 -0
  10. package/dist/engine/audit_pool.js.map +1 -1
  11. package/dist/engine/contract_registry.d.ts +113 -0
  12. package/dist/engine/contract_registry.d.ts.map +1 -0
  13. package/dist/engine/contract_registry.js +1159 -0
  14. package/dist/engine/contract_registry.js.map +1 -0
  15. package/dist/engine/contract_state_store.d.ts +67 -0
  16. package/dist/engine/contract_state_store.d.ts.map +1 -0
  17. package/dist/engine/contract_state_store.js +167 -0
  18. package/dist/engine/contract_state_store.js.map +1 -0
  19. package/dist/engine/debugger.d.ts.map +1 -1
  20. package/dist/engine/debugger.js +30 -1
  21. package/dist/engine/debugger.js.map +1 -1
  22. package/dist/engine/degradation.d.ts +58 -0
  23. package/dist/engine/degradation.d.ts.map +1 -0
  24. package/dist/engine/degradation.js +74 -0
  25. package/dist/engine/degradation.js.map +1 -0
  26. package/dist/engine/delivery_readiness.d.ts +66 -0
  27. package/dist/engine/delivery_readiness.d.ts.map +1 -0
  28. package/dist/engine/delivery_readiness.js +176 -0
  29. package/dist/engine/delivery_readiness.js.map +1 -0
  30. package/dist/engine/deprecated_contract.d.ts +21 -0
  31. package/dist/engine/deprecated_contract.d.ts.map +1 -0
  32. package/dist/engine/deprecated_contract.js +14 -0
  33. package/dist/engine/deprecated_contract.js.map +1 -0
  34. package/dist/engine/diagnostic_registry.d.ts +64 -0
  35. package/dist/engine/diagnostic_registry.d.ts.map +1 -0
  36. package/dist/engine/diagnostic_registry.js +176 -0
  37. package/dist/engine/diagnostic_registry.js.map +1 -0
  38. package/dist/engine/enforcement_guard.d.ts +84 -0
  39. package/dist/engine/enforcement_guard.d.ts.map +1 -0
  40. package/dist/engine/enforcement_guard.js +305 -0
  41. package/dist/engine/enforcement_guard.js.map +1 -0
  42. package/dist/engine/failure_report.d.ts +74 -0
  43. package/dist/engine/failure_report.d.ts.map +1 -0
  44. package/dist/engine/failure_report.js +143 -0
  45. package/dist/engine/failure_report.js.map +1 -0
  46. package/dist/engine/governance_report.d.ts +9 -1
  47. package/dist/engine/governance_report.d.ts.map +1 -1
  48. package/dist/engine/governance_report.js +16 -2
  49. package/dist/engine/governance_report.js.map +1 -1
  50. package/dist/engine/implementation_roadmap_registry.d.ts +1 -1
  51. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  52. package/dist/engine/implementation_roadmap_registry.js +32 -24
  53. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  54. package/dist/engine/knowledge_lifecycle.d.ts +23 -0
  55. package/dist/engine/knowledge_lifecycle.d.ts.map +1 -0
  56. package/dist/engine/knowledge_lifecycle.js +13 -0
  57. package/dist/engine/knowledge_lifecycle.js.map +1 -0
  58. package/dist/engine/language_policy.d.ts +21 -0
  59. package/dist/engine/language_policy.d.ts.map +1 -0
  60. package/dist/engine/language_policy.js +18 -0
  61. package/dist/engine/language_policy.js.map +1 -0
  62. package/dist/engine/language_policy_contract.d.ts +52 -0
  63. package/dist/engine/language_policy_contract.d.ts.map +1 -0
  64. package/dist/engine/language_policy_contract.js +78 -0
  65. package/dist/engine/language_policy_contract.js.map +1 -0
  66. package/dist/engine/mechanism_family_registry.d.ts +48 -0
  67. package/dist/engine/mechanism_family_registry.d.ts.map +1 -0
  68. package/dist/engine/mechanism_family_registry.js +197 -0
  69. package/dist/engine/mechanism_family_registry.js.map +1 -0
  70. package/dist/engine/policy_drift_detector.d.ts +20 -0
  71. package/dist/engine/policy_drift_detector.d.ts.map +1 -1
  72. package/dist/engine/policy_drift_detector.js +79 -0
  73. package/dist/engine/policy_drift_detector.js.map +1 -1
  74. package/dist/engine/retention_policy.d.ts +46 -0
  75. package/dist/engine/retention_policy.d.ts.map +1 -0
  76. package/dist/engine/retention_policy.js +124 -0
  77. package/dist/engine/retention_policy.js.map +1 -0
  78. package/dist/engine/state_update_bypass.d.ts +19 -0
  79. package/dist/engine/state_update_bypass.d.ts.map +1 -0
  80. package/dist/engine/state_update_bypass.js +17 -0
  81. package/dist/engine/state_update_bypass.js.map +1 -0
  82. package/dist/engine/task_context.d.ts.map +1 -1
  83. package/dist/engine/task_context.js +8 -0
  84. package/dist/engine/task_context.js.map +1 -1
  85. package/dist/engine/test_strategy.d.ts +58 -0
  86. package/dist/engine/test_strategy.d.ts.map +1 -0
  87. package/dist/engine/test_strategy.js +93 -0
  88. package/dist/engine/test_strategy.js.map +1 -0
  89. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  90. package/dist/engine/tool_invocation_contract_registry.js +11 -1
  91. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  92. package/dist/engine/verification_contract.d.ts +132 -0
  93. package/dist/engine/verification_contract.d.ts.map +1 -0
  94. package/dist/engine/verification_contract.js +296 -0
  95. package/dist/engine/verification_contract.js.map +1 -0
  96. package/dist/engine/workspace_lease.d.ts +69 -0
  97. package/dist/engine/workspace_lease.d.ts.map +1 -0
  98. package/dist/engine/workspace_lease.js +153 -0
  99. package/dist/engine/workspace_lease.js.map +1 -0
  100. package/dist/types.d.ts +13 -1
  101. package/dist/types.d.ts.map +1 -1
  102. package/package.json +3 -2
@@ -0,0 +1,296 @@
1
+ /**
2
+ * 验证契约 — 问题十二 (Verification Contract)。
3
+ *
4
+ * 核心规则:
5
+ * - VerificationPlan 只是计划,不是结果
6
+ * - VerificationResult 必须来自真实执行或明确 not_executed
7
+ * - 未验证不得 delivered
8
+ * - delivery_readiness 不得触发 delivery_execution
9
+ */
10
+ /**
11
+ * 创建验证计划(不执行)。
12
+ */
13
+ export function createVerificationPlan(taskId, commands, acceptanceCriteria) {
14
+ return {
15
+ plan_id: `vp-${taskId}-${Date.now()}`,
16
+ task_id: taskId,
17
+ commands,
18
+ acceptance_criteria: acceptanceCriteria,
19
+ created_at: new Date().toISOString(),
20
+ status: "plan_only",
21
+ };
22
+ }
23
+ /**
24
+ * 检查是否为 plan_only(无真实执行)。
25
+ * VerificationPlan.status === "plan_only" 时不得视为 VerificationResult。
26
+ */
27
+ export function isPlanOnly(plan) {
28
+ return plan.status === "plan_only";
29
+ }
30
+ /**
31
+ * 创建验证结果(内部使用,provenance = "direct")。
32
+ * delivery_readiness 必须拒绝 provenance="direct" 的 passed 结果。
33
+ * 唯一合法 passed 入口是 recordVerificationExecution。
34
+ */
35
+ export function createVerificationResult(taskId, planId, evidenceIds, commandResults) {
36
+ // 不允许空 evidenceIds + 空 commandResults 时返回 passed
37
+ const hasEvidence = evidenceIds.length > 0;
38
+ const hasCommands = commandResults.length > 0;
39
+ // 无 evidence 或无 commands → 强制 failed
40
+ if (!hasEvidence || !hasCommands) {
41
+ return {
42
+ result_id: `vr-${taskId}-${Date.now()}`,
43
+ task_id: taskId,
44
+ plan_id: planId,
45
+ status: "failed",
46
+ total_commands: commandResults.length,
47
+ passed_commands: 0,
48
+ failed_commands: 0,
49
+ evidence_ids: evidenceIds,
50
+ findings: [{
51
+ rule: "evidence_required",
52
+ severity: "hard_fail",
53
+ message_zh: `验证结果缺少${!hasEvidence ? " evidence" : ""}${!hasEvidence && !hasCommands ? " 和" : ""}${!hasCommands ? " commands" : ""},不得 passed`,
54
+ diagnostic_code: "SF-VERIFY-0003",
55
+ }],
56
+ completed_at: new Date().toISOString(),
57
+ provenance: "direct",
58
+ };
59
+ }
60
+ const passedCount = commandResults.filter((r) => r.passed).length;
61
+ const failedCount = commandResults.filter((r) => !r.passed).length;
62
+ const findings = commandResults
63
+ .filter((r) => !r.passed && r.diagnostic_code)
64
+ .map((r) => ({
65
+ rule: "command_failed",
66
+ severity: "hard_fail",
67
+ message_zh: `验证命令失败: ${r.diagnostic_code}`,
68
+ diagnostic_code: r.diagnostic_code,
69
+ }));
70
+ return {
71
+ result_id: `vr-${taskId}-${Date.now()}`,
72
+ task_id: taskId,
73
+ plan_id: planId,
74
+ status: failedCount === 0 ? "passed" : "failed",
75
+ total_commands: commandResults.length,
76
+ passed_commands: passedCount,
77
+ failed_commands: failedCount,
78
+ evidence_ids: evidenceIds,
79
+ findings,
80
+ completed_at: new Date().toISOString(),
81
+ provenance: "direct",
82
+ };
83
+ }
84
+ /**
85
+ * 创建未执行的验证结果。
86
+ */
87
+ export function createNotExecutedResult(taskId, planId, reason) {
88
+ return {
89
+ result_id: `vr-${taskId}-${Date.now()}`,
90
+ task_id: taskId,
91
+ plan_id: planId,
92
+ status: "not_executed",
93
+ total_commands: 0,
94
+ passed_commands: 0,
95
+ failed_commands: 0,
96
+ evidence_ids: [],
97
+ findings: [{
98
+ rule: "not_executed",
99
+ severity: "warning",
100
+ message_zh: `验证未执行: ${reason}`,
101
+ diagnostic_code: "SF-VERIFY-0001",
102
+ }],
103
+ completed_at: new Date().toISOString(),
104
+ provenance: "direct",
105
+ };
106
+ }
107
+ /** SHA256 hex 格式 */
108
+ const SHA256_RE = /^[a-f0-9]{64}$/i;
109
+ /** ISO 8601 日期格式 */
110
+ const ISO8601_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
111
+ /**
112
+ * 校验执行记录: 证据格式、命令合法性、evidence_id 唯一性、时间合法性。
113
+ * 返回校验失败的记录索引及对应的 diagnostic_code。
114
+ */
115
+ export function validateExecutionRecords(plan, records) {
116
+ const errors = [];
117
+ const seenEvidenceIds = new Set();
118
+ const planCommands = new Set(plan.commands);
119
+ for (let i = 0; i < records.length; i++) {
120
+ const r = records[i];
121
+ if (!r.command) {
122
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5001", message_zh: `记录 ${i}: command 为空` });
123
+ continue;
124
+ }
125
+ if (!planCommands.has(r.command)) {
126
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5006", message_zh: `记录 ${i}: 命令 "${r.command}" 不在 plan.commands 中` });
127
+ }
128
+ if (!r.stdout_hash || !SHA256_RE.test(r.stdout_hash)) {
129
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5007", message_zh: `记录 ${i}: stdout_hash 为空或格式非法` });
130
+ }
131
+ if (!r.stderr_hash || !SHA256_RE.test(r.stderr_hash)) {
132
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5008", message_zh: `记录 ${i}: stderr_hash 为空或格式非法` });
133
+ }
134
+ if (!r.evidence_id) {
135
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5009", message_zh: `记录 ${i}: evidence_id 为空` });
136
+ }
137
+ else if (seenEvidenceIds.has(r.evidence_id)) {
138
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5010", message_zh: `记录 ${i}: evidence_id "${r.evidence_id}" 重复` });
139
+ }
140
+ else {
141
+ seenEvidenceIds.add(r.evidence_id);
142
+ }
143
+ if (!r.started_at || !ISO8601_RE.test(r.started_at)) {
144
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5011", message_zh: `记录 ${i}: started_at 格式非法` });
145
+ }
146
+ if (!r.finished_at || !ISO8601_RE.test(r.finished_at)) {
147
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5012", message_zh: `记录 ${i}: finished_at 格式非法` });
148
+ }
149
+ if (r.started_at && r.finished_at && ISO8601_RE.test(r.started_at) && ISO8601_RE.test(r.finished_at)) {
150
+ if (new Date(r.finished_at).getTime() < new Date(r.started_at).getTime()) {
151
+ errors.push({ index: i, diagnostic_code: "SF-VERIFY-5013", message_zh: `记录 ${i}: finished_at 早于 started_at` });
152
+ }
153
+ }
154
+ }
155
+ return errors;
156
+ }
157
+ /**
158
+ * 计算命令覆盖率: plan.commands 中被 records 覆盖的比例。
159
+ */
160
+ export function computeCommandCoverage(plan, records) {
161
+ const covered = new Set(records.map((r) => r.command));
162
+ const coveredCommands = [];
163
+ const missingCommands = [];
164
+ for (const cmd of plan.commands) {
165
+ if (covered.has(cmd)) {
166
+ coveredCommands.push(cmd);
167
+ }
168
+ else {
169
+ missingCommands.push(cmd);
170
+ }
171
+ }
172
+ return { covered_commands: coveredCommands, missing_commands: missingCommands };
173
+ }
174
+ /** 构造带 diagnostic_code 的 failed 结果 */
175
+ function createFailedResult(taskId, planId, diagnosticCode, message) {
176
+ return {
177
+ result_id: `vr-${taskId}-${Date.now()}`,
178
+ task_id: taskId,
179
+ plan_id: planId,
180
+ status: "failed",
181
+ total_commands: 0,
182
+ passed_commands: 0,
183
+ failed_commands: 0,
184
+ evidence_ids: [],
185
+ findings: [{
186
+ rule: "plan_binding_required",
187
+ severity: "hard_fail",
188
+ message_zh: message,
189
+ diagnostic_code: diagnosticCode,
190
+ }],
191
+ completed_at: new Date().toISOString(),
192
+ provenance: "direct",
193
+ covered_commands: [],
194
+ missing_commands: [],
195
+ evidence_integrity_passed: false,
196
+ };
197
+ }
198
+ /**
199
+ * 录入真实执行结果 — VerificationResult.status = "passed" 的唯一合法入口。
200
+ *
201
+ * 规则:
202
+ * - plan 为 null → hard fail (SF-VERIFY-5002)
203
+ * - records 为空 → not_executed
204
+ * - 非计划命令 → 该条 failed (SF-VERIFY-5006)
205
+ * - stdout/stderr hash 格式非法 → 该条 failed
206
+ * - evidence_id 重复 → 该条 failed
207
+ * - 时间倒挂 → 该条 failed
208
+ * - plan.commands 未全覆盖 → failed (SF-VERIFY-5003)
209
+ * - 所有 exit_code === 0 且全覆盖且无格式错误 → passed
210
+ */
211
+ export function recordVerificationExecution(taskId, planId, records, plan) {
212
+ if (!plan) {
213
+ return createFailedResult(taskId, planId, "SF-VERIFY-5002", "无关联 VerificationPlan,不得录入执行结果");
214
+ }
215
+ if (planId !== plan.plan_id) {
216
+ return createFailedResult(taskId, planId, "SF-VERIFY-5014", `plan_id 不匹配: 传入 "${planId}",plan 中 "${plan.plan_id}"`);
217
+ }
218
+ if (taskId !== plan.task_id) {
219
+ return createFailedResult(taskId, planId, "SF-VERIFY-5015", `task_id 不匹配: 传入 "${taskId}",plan 中 "${plan.task_id}"`);
220
+ }
221
+ if (records.length === 0) {
222
+ return createNotExecutedResult(taskId, planId, "无执行记录");
223
+ }
224
+ // 校验证据格式和命令合法性
225
+ const validationErrors = validateExecutionRecords(plan, records);
226
+ const errorIndices = new Set(validationErrors.map((e) => e.index));
227
+ // 校验命令覆盖
228
+ const { covered_commands, missing_commands } = computeCommandCoverage(plan, records);
229
+ const hasMissing = missing_commands.length > 0;
230
+ // 逐条判定: 合法记录按 exit_code 判,非法记录直接 failed
231
+ const commandResults = records.map((r, i) => {
232
+ if (errorIndices.has(i)) {
233
+ return { passed: false, diagnostic_code: "SF-VERIFY-5001" };
234
+ }
235
+ return {
236
+ passed: r.exit_code === 0,
237
+ diagnostic_code: r.exit_code !== 0 ? "SF-VERIFY-0004" : undefined,
238
+ };
239
+ });
240
+ // 所有校验错误转为 findings(每条记录可能有多个错误)
241
+ const validationFindings = validationErrors.map((e) => ({
242
+ rule: "evidence_validation",
243
+ severity: "hard_fail",
244
+ message_zh: e.message_zh,
245
+ diagnostic_code: e.diagnostic_code,
246
+ }));
247
+ const evidenceIds = records.map((r) => r.evidence_id);
248
+ const base = createVerificationResult(taskId, planId, evidenceIds, commandResults);
249
+ // 合并所有 findings
250
+ const allFindings = [...base.findings, ...validationFindings];
251
+ // 命令未全覆盖 → 强制 failed 并追加 finding
252
+ if (hasMissing) {
253
+ return {
254
+ ...base,
255
+ status: "failed",
256
+ provenance: "record_verification_execution",
257
+ findings: [...allFindings, {
258
+ rule: "plan_coverage_incomplete",
259
+ severity: "hard_fail",
260
+ message_zh: `plan 命令未全覆盖,缺少: ${missing_commands.join(", ")}`,
261
+ diagnostic_code: "SF-VERIFY-5003",
262
+ }],
263
+ covered_commands,
264
+ missing_commands,
265
+ evidence_integrity_passed: errorIndices.size === 0,
266
+ };
267
+ }
268
+ return {
269
+ ...base,
270
+ provenance: "record_verification_execution",
271
+ findings: allFindings,
272
+ covered_commands,
273
+ missing_commands,
274
+ evidence_integrity_passed: errorIndices.size === 0,
275
+ };
276
+ }
277
+ /**
278
+ * 验证: VerificationPlan 不得当作 VerificationEvidence。
279
+ */
280
+ export function validateVerificationSeparation(plan, result) {
281
+ const errors = [];
282
+ if (!result) {
283
+ errors.push({
284
+ error: `验证计划 ${plan.plan_id} 存在但无 VerificationResult`,
285
+ severity: "hard_fail",
286
+ });
287
+ }
288
+ else if (result.status === "not_executed") {
289
+ errors.push({
290
+ error: `验证结果状态为 not_executed,不得视为通过`,
291
+ severity: "hard_fail",
292
+ });
293
+ }
294
+ return errors;
295
+ }
296
+ //# sourceMappingURL=verification_contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification_contract.js","sourceRoot":"","sources":["../../src/engine/verification_contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * 工作区隔离 — 问题二十八 (Workspace Isolation / Concurrency Contract)。
3
+ *
4
+ * 核心规则:
5
+ * - 同 scope code_write 冲突必须 blocked 或 require_human
6
+ * - delivery 必须互斥
7
+ * - lease active/conflicted 不得交付
8
+ * - out-of-scope write 必须 blocked
9
+ */
10
+ import { type DiagnosticEvent } from "./diagnostic_registry.js";
11
+ export type LeaseType = "code_write" | "delivery" | "output_artifact";
12
+ export type LeaseStatus = "active" | "released" | "expired" | "conflicted";
13
+ export interface WorkspaceLease {
14
+ lease_id: string;
15
+ task_id: string;
16
+ lease_type: LeaseType;
17
+ scope_paths: string[];
18
+ status: LeaseStatus;
19
+ acquired_at: string;
20
+ expires_at?: string;
21
+ diagnostic_event: DiagnosticEvent | null;
22
+ }
23
+ export interface WorkspaceIsolationReport {
24
+ report_id: string;
25
+ task_id: string;
26
+ active_leases: WorkspaceLease[];
27
+ conflicts: LeaseConflict[];
28
+ out_of_scope_writes: Array<{
29
+ path: string;
30
+ allowed_paths: string[];
31
+ }>;
32
+ delivery_blocked: boolean;
33
+ evaluated_at: string;
34
+ }
35
+ export interface LeaseConflict {
36
+ lease_a_id: string;
37
+ lease_b_id: string;
38
+ conflict_path: string;
39
+ conflict_type: "scope_overlap" | "delivery_overlap";
40
+ resolved: boolean;
41
+ }
42
+ /** 获取 lease */
43
+ export declare function getLease(leaseId: string): WorkspaceLease | undefined;
44
+ /** 列出所有活跃 lease */
45
+ export declare function listActiveLeases(): WorkspaceLease[];
46
+ /**
47
+ * 尝试获取 lease。
48
+ * 如果同 scope 有冲突,返回冲突信息。
49
+ */
50
+ export declare function acquireLease(taskId: string, leaseType: LeaseType, scopePaths: string[]): {
51
+ lease: WorkspaceLease | null;
52
+ conflicts: LeaseConflict[];
53
+ };
54
+ /** 释放 lease */
55
+ export declare function releaseLease(leaseId: string): boolean;
56
+ /**
57
+ * 检查是否超出 scope 写入。
58
+ */
59
+ export declare function checkOutOfScopeWrite(taskId: string, targetPath: string, allowedPaths: string[]): {
60
+ allowed: boolean;
61
+ reason?: string;
62
+ };
63
+ /**
64
+ * 生成工作区隔离报告。
65
+ */
66
+ export declare function generateIsolationReport(taskId: string): WorkspaceIsolationReport;
67
+ /** 重置 lease 存储(测试用) */
68
+ export declare function resetLeaseStore(): void;
69
+ //# sourceMappingURL=workspace_lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace_lease.d.ts","sourceRoot":"","sources":["../../src/engine/workspace_lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEvF,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,iBAAiB,CAAC;AACtE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,SAAS,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,eAAe,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,cAAc,EAAE,CAAC;IAChC,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,mBAAmB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACtE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,eAAe,GAAG,kBAAkB,CAAC;IACpD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD,eAAe;AACf,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEpE;AAED,mBAAmB;AACnB,wBAAgB,gBAAgB,IAAI,cAAc,EAAE,CAEnD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM,EAAE,GACnB;IAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,aAAa,EAAE,CAAA;CAAE,CAqE9D;AAED,eAAe;AACf,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CASrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EAAE,GACrB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CASvC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,wBAAwB,CAyChF;AAED,uBAAuB;AACvB,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * 工作区隔离 — 问题二十八 (Workspace Isolation / Concurrency Contract)。
3
+ *
4
+ * 核心规则:
5
+ * - 同 scope code_write 冲突必须 blocked 或 require_human
6
+ * - delivery 必须互斥
7
+ * - lease active/conflicted 不得交付
8
+ * - out-of-scope write 必须 blocked
9
+ */
10
+ import { createDiagnosticEvent } from "./diagnostic_registry.js";
11
+ /** 内存存储 */
12
+ const leaseStore = new Map();
13
+ /** 获取 lease */
14
+ export function getLease(leaseId) {
15
+ return leaseStore.get(leaseId);
16
+ }
17
+ /** 列出所有活跃 lease */
18
+ export function listActiveLeases() {
19
+ return [...leaseStore.values()].filter((l) => l.status === "active");
20
+ }
21
+ /**
22
+ * 尝试获取 lease。
23
+ * 如果同 scope 有冲突,返回冲突信息。
24
+ */
25
+ export function acquireLease(taskId, leaseType, scopePaths) {
26
+ const conflicts = [];
27
+ const leaseId = `wl-${taskId}-${Date.now()}`;
28
+ // 检查冲突
29
+ const activeLeases = listActiveLeases();
30
+ for (const existing of activeLeases) {
31
+ if (existing.task_id === taskId)
32
+ continue;
33
+ // 同 scope 重叠检查
34
+ const overlap = existing.scope_paths.some((p) => scopePaths.some((sp) => p === sp || p.startsWith(sp + "/") || sp.startsWith(p + "/")));
35
+ if (overlap) {
36
+ if (leaseType === "delivery" || existing.lease_type === "delivery") {
37
+ // delivery 必须互斥
38
+ conflicts.push({
39
+ lease_a_id: existing.lease_id,
40
+ lease_b_id: leaseId,
41
+ conflict_path: existing.scope_paths.find((p) => scopePaths.some((sp) => p === sp || p.startsWith(sp + "/"))) ?? "unknown",
42
+ conflict_type: "delivery_overlap",
43
+ resolved: false,
44
+ });
45
+ }
46
+ else if (leaseType === "code_write" && existing.lease_type === "code_write") {
47
+ // code_write 同文件冲突
48
+ conflicts.push({
49
+ lease_a_id: existing.lease_id,
50
+ lease_b_id: leaseId,
51
+ conflict_path: existing.scope_paths.find((p) => scopePaths.some((sp) => p === sp)) ?? "unknown",
52
+ conflict_type: "scope_overlap",
53
+ resolved: false,
54
+ });
55
+ }
56
+ }
57
+ }
58
+ if (conflicts.length > 0) {
59
+ // 创建冲突 lease
60
+ const diagEvent = createDiagnosticEvent("SF-WORKSPACE-0001", { taskId, leaseType });
61
+ const lease = {
62
+ lease_id: leaseId,
63
+ task_id: taskId,
64
+ lease_type: leaseType,
65
+ scope_paths: scopePaths,
66
+ status: "conflicted",
67
+ acquired_at: new Date().toISOString(),
68
+ diagnostic_event: diagEvent,
69
+ };
70
+ leaseStore.set(leaseId, lease);
71
+ return { lease, conflicts };
72
+ }
73
+ // 无冲突,创建活跃 lease
74
+ const lease = {
75
+ lease_id: leaseId,
76
+ task_id: taskId,
77
+ lease_type: leaseType,
78
+ scope_paths: scopePaths,
79
+ status: "active",
80
+ acquired_at: new Date().toISOString(),
81
+ diagnostic_event: null,
82
+ };
83
+ leaseStore.set(leaseId, lease);
84
+ return { lease, conflicts: [] };
85
+ }
86
+ /** 释放 lease */
87
+ export function releaseLease(leaseId) {
88
+ const lease = leaseStore.get(leaseId);
89
+ if (!lease)
90
+ return false;
91
+ if (lease.status === "conflicted") {
92
+ // conflicted lease 不得标记 released
93
+ return false;
94
+ }
95
+ lease.status = "released";
96
+ return true;
97
+ }
98
+ /**
99
+ * 检查是否超出 scope 写入。
100
+ */
101
+ export function checkOutOfScopeWrite(taskId, targetPath, allowedPaths) {
102
+ const inScope = allowedPaths.some((p) => targetPath === p || targetPath.startsWith(p + "/"));
103
+ if (!inScope) {
104
+ return {
105
+ allowed: false,
106
+ reason: `写入 ${targetPath} 超出允许范围`,
107
+ };
108
+ }
109
+ return { allowed: true };
110
+ }
111
+ /**
112
+ * 生成工作区隔离报告。
113
+ */
114
+ export function generateIsolationReport(taskId) {
115
+ const activeLeases = listActiveLeases();
116
+ const conflicts = [];
117
+ // 检测冲突
118
+ for (let i = 0; i < activeLeases.length; i++) {
119
+ for (let j = i + 1; j < activeLeases.length; j++) {
120
+ const a = activeLeases[i];
121
+ const b = activeLeases[j];
122
+ if (a.task_id === b.task_id)
123
+ continue;
124
+ const overlap = a.scope_paths.some((p) => b.scope_paths.some((bp) => p === bp || p.startsWith(bp + "/") || bp.startsWith(p + "/")));
125
+ if (overlap) {
126
+ conflicts.push({
127
+ lease_a_id: a.lease_id,
128
+ lease_b_id: b.lease_id,
129
+ conflict_path: a.scope_paths[0],
130
+ conflict_type: "scope_overlap",
131
+ resolved: false,
132
+ });
133
+ }
134
+ }
135
+ }
136
+ const taskLeases = activeLeases.filter((l) => l.task_id === taskId);
137
+ const hasDeliveryLease = taskLeases.some((l) => l.lease_type === "delivery" && l.status === "active");
138
+ const hasConflict = conflicts.some((c) => taskLeases.some((l) => l.lease_id === c.lease_a_id || l.lease_id === c.lease_b_id));
139
+ return {
140
+ report_id: `wir-${taskId}-${Date.now()}`,
141
+ task_id: taskId,
142
+ active_leases: taskLeases,
143
+ conflicts,
144
+ out_of_scope_writes: [],
145
+ delivery_blocked: hasConflict || !hasDeliveryLease,
146
+ evaluated_at: new Date().toISOString(),
147
+ };
148
+ }
149
+ /** 重置 lease 存储(测试用) */
150
+ export function resetLeaseStore() {
151
+ leaseStore.clear();
152
+ }
153
+ //# sourceMappingURL=workspace_lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace_lease.js","sourceRoot":"","sources":["../../src/engine/workspace_lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,qBAAqB,EAAwB,MAAM,0BAA0B,CAAC;AAkCvF,WAAW;AACX,MAAM,UAAU,GAAG,IAAI,GAAG,EAA0B,CAAC;AAErD,eAAe;AACf,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,mBAAmB;AACnB,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,SAAoB,EACpB,UAAoB;IAEpB,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAE7C,OAAO;IACP,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;IACxC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;QACpC,IAAI,QAAQ,CAAC,OAAO,KAAK,MAAM;YAAE,SAAS;QAE1C,eAAe;QACf,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CACtF,CAAC;QAEF,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,SAAS,KAAK,UAAU,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACnE,gBAAgB;gBAChB,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,QAAQ,CAAC,QAAQ;oBAC7B,UAAU,EAAE,OAAO;oBACnB,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAC5D,IAAI,SAAS;oBACd,aAAa,EAAE,kBAAkB;oBACjC,QAAQ,EAAE,KAAK;iBAChB,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,SAAS,KAAK,YAAY,IAAI,QAAQ,CAAC,UAAU,KAAK,YAAY,EAAE,CAAC;gBAC9E,mBAAmB;gBACnB,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,QAAQ,CAAC,QAAQ;oBAC7B,UAAU,EAAE,OAAO;oBACnB,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC7C,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAClC,IAAI,SAAS;oBACd,aAAa,EAAE,eAAe;oBAC9B,QAAQ,EAAE,KAAK;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,aAAa;QACb,MAAM,SAAS,GAAG,qBAAqB,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACpF,MAAM,KAAK,GAAmB;YAC5B,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,SAAS;YACrB,WAAW,EAAE,UAAU;YACvB,MAAM,EAAE,YAAY;YACpB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACrC,gBAAgB,EAAE,SAAS;SAC5B,CAAC;QACF,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IAED,iBAAiB;IACjB,MAAM,KAAK,GAAmB;QAC5B,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,gBAAgB,EAAE,IAAI;KACvB,CAAC;IACF,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAClC,CAAC;AAED,eAAe;AACf,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,iCAAiC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,UAAkB,EAClB,YAAsB;IAEtB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,KAAK,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC7F,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,MAAM,UAAU,SAAS;SAClC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAoB,EAAE,CAAC;IAEtC,OAAO;IACP,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO;gBAAE,SAAS;YAEtC,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CACzF,CAAC;YACF,IAAI,OAAO,EAAE,CAAC;gBACZ,SAAS,CAAC,IAAI,CAAC;oBACb,UAAU,EAAE,CAAC,CAAC,QAAQ;oBACtB,UAAU,EAAE,CAAC,CAAC,QAAQ;oBACtB,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;oBAC/B,aAAa,EAAE,eAAe;oBAC9B,QAAQ,EAAE,KAAK;iBAChB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IACtG,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,UAAU,CAAC,CAC1F,CAAC;IAEF,OAAO;QACL,SAAS,EAAE,OAAO,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;QACxC,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,UAAU;QACzB,SAAS;QACT,mBAAmB,EAAE,EAAE;QACvB,gBAAgB,EAAE,WAAW,IAAI,CAAC,gBAAgB;QAClD,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACvC,CAAC;AACJ,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,eAAe;IAC7B,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -260,6 +260,16 @@ export interface TaskContext {
260
260
  sensitivity_labels?: import("./engine/privacy_secret_contract.js").DataSensitivityLabel[];
261
261
  /** 脱敏记录列表( 隐私) */
262
262
  redaction_records?: import("./engine/privacy_secret_contract.js").RedactionRecord[];
263
+ /** Batch2 验证计划(plan_only,非执行结果) */
264
+ batch2_verification_plan?: import("./engine/verification_contract.js").VerificationPlan;
265
+ /** Batch2 验证结果(真实执行产出) */
266
+ batch2_verification_result?: import("./engine/verification_contract.js").VerificationResult;
267
+ /** Batch2 失败报告(脱敏,非 raw error_output) */
268
+ batch2_failure_report?: import("./engine/failure_report.js").FailureReport;
269
+ /** Batch2 降级事件 */
270
+ batch2_degradation_event?: import("./engine/degradation.js").DegradationEvent;
271
+ /** Batch2 交付就绪报告 */
272
+ batch2_delivery_readiness?: import("./engine/delivery_readiness.js").DeliveryReadinessReport;
263
273
  }
264
274
  /** 失败记录 */
265
275
  export interface FailureRecord {
@@ -1218,8 +1228,10 @@ export interface TestSuggestion {
1218
1228
  export interface DebugSession {
1219
1229
  /** 任务 ID */
1220
1230
  task_id: string;
1221
- /** 原始错误输出 */
1231
+ /** 脱敏后的错误输出摘要(Batch2: 不保留 raw 原文) */
1222
1232
  error_output: string;
1233
+ /** 原始输出稳定哈希(Batch2: 用于追溯,不存原文) */
1234
+ error_output_hash?: string;
1223
1235
  /** 解析后的错误 */
1224
1236
  parsed_error: ParsedError;
1225
1237
  /** 调用链 */