soloforge 1.2.2 → 1.2.4
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 +229 -28
- package/dist/adapters/claude_code/tools.d.ts.map +1 -1
- package/dist/adapters/claude_code/tools.js +319 -5
- package/dist/adapters/claude_code/tools.js.map +1 -1
- package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
- package/dist/adapters/shared/workflow_template.js +26 -3
- package/dist/adapters/shared/workflow_template.js.map +1 -1
- package/dist/bin/soloforge.js +169 -13
- package/dist/bin/soloforge.js.map +1 -1
- package/dist/engine/audit_pool.d.ts +36 -0
- package/dist/engine/audit_pool.d.ts.map +1 -0
- package/dist/engine/audit_pool.js +83 -0
- package/dist/engine/audit_pool.js.map +1 -0
- package/dist/engine/audit_sampler.d.ts +15 -0
- package/dist/engine/audit_sampler.d.ts.map +1 -0
- package/dist/engine/audit_sampler.js +26 -0
- package/dist/engine/audit_sampler.js.map +1 -0
- package/dist/engine/capability_action_advisor.d.ts +24 -0
- package/dist/engine/capability_action_advisor.d.ts.map +1 -0
- package/dist/engine/capability_action_advisor.js +147 -0
- package/dist/engine/capability_action_advisor.js.map +1 -0
- package/dist/engine/capability_registry.d.ts +23 -1
- package/dist/engine/capability_registry.d.ts.map +1 -1
- package/dist/engine/capability_registry.js +511 -19
- package/dist/engine/capability_registry.js.map +1 -1
- package/dist/engine/capability_state_store.d.ts +50 -0
- package/dist/engine/capability_state_store.d.ts.map +1 -0
- package/dist/engine/capability_state_store.js +123 -0
- package/dist/engine/capability_state_store.js.map +1 -0
- package/dist/engine/cognitive_anchor.d.ts +59 -0
- package/dist/engine/cognitive_anchor.d.ts.map +1 -0
- package/dist/engine/cognitive_anchor.js +68 -0
- package/dist/engine/cognitive_anchor.js.map +1 -0
- package/dist/engine/conflict_gate.d.ts +36 -0
- package/dist/engine/conflict_gate.d.ts.map +1 -0
- package/dist/engine/conflict_gate.js +73 -0
- package/dist/engine/conflict_gate.js.map +1 -0
- package/dist/engine/decision_contract.d.ts +29 -0
- package/dist/engine/decision_contract.d.ts.map +1 -0
- package/dist/engine/decision_contract.js +41 -0
- package/dist/engine/decision_contract.js.map +1 -0
- package/dist/engine/delivery.d.ts.map +1 -1
- package/dist/engine/delivery.js +83 -0
- package/dist/engine/delivery.js.map +1 -1
- package/dist/engine/developer_sovereignty.d.ts +62 -0
- package/dist/engine/developer_sovereignty.d.ts.map +1 -0
- package/dist/engine/developer_sovereignty.js +134 -0
- package/dist/engine/developer_sovereignty.js.map +1 -0
- package/dist/engine/diff_ownership.d.ts +74 -0
- package/dist/engine/diff_ownership.d.ts.map +1 -0
- package/dist/engine/diff_ownership.js +143 -0
- package/dist/engine/diff_ownership.js.map +1 -0
- package/dist/engine/diff_ownership_store.d.ts +76 -0
- package/dist/engine/diff_ownership_store.d.ts.map +1 -0
- package/dist/engine/diff_ownership_store.js +264 -0
- package/dist/engine/diff_ownership_store.js.map +1 -0
- package/dist/engine/escape_report.d.ts +45 -0
- package/dist/engine/escape_report.d.ts.map +1 -0
- package/dist/engine/escape_report.js +97 -0
- package/dist/engine/escape_report.js.map +1 -0
- package/dist/engine/exploration.d.ts +54 -0
- package/dist/engine/exploration.d.ts.map +1 -1
- package/dist/engine/exploration.js +138 -0
- package/dist/engine/exploration.js.map +1 -1
- package/dist/engine/governance_report.d.ts +36 -0
- package/dist/engine/governance_report.d.ts.map +1 -0
- package/dist/engine/governance_report.js +79 -0
- package/dist/engine/governance_report.js.map +1 -0
- package/dist/engine/java_quality_guard.d.ts +52 -0
- package/dist/engine/java_quality_guard.d.ts.map +1 -0
- package/dist/engine/java_quality_guard.js +237 -0
- package/dist/engine/java_quality_guard.js.map +1 -0
- package/dist/engine/job_manager.d.ts +76 -0
- package/dist/engine/job_manager.d.ts.map +1 -0
- package/dist/engine/job_manager.js +225 -0
- package/dist/engine/job_manager.js.map +1 -0
- package/dist/engine/knowledge_sovereignty.d.ts +61 -0
- package/dist/engine/knowledge_sovereignty.d.ts.map +1 -0
- package/dist/engine/knowledge_sovereignty.js +190 -0
- package/dist/engine/knowledge_sovereignty.js.map +1 -0
- package/dist/engine/mutation_audit.d.ts +43 -0
- package/dist/engine/mutation_audit.d.ts.map +1 -0
- package/dist/engine/mutation_audit.js +118 -0
- package/dist/engine/mutation_audit.js.map +1 -0
- package/dist/engine/policy_drift_detector.d.ts +46 -0
- package/dist/engine/policy_drift_detector.d.ts.map +1 -0
- package/dist/engine/policy_drift_detector.js +181 -0
- package/dist/engine/policy_drift_detector.js.map +1 -0
- package/dist/engine/regression_matrix.d.ts +102 -0
- package/dist/engine/regression_matrix.d.ts.map +1 -0
- package/dist/engine/regression_matrix.js +380 -0
- package/dist/engine/regression_matrix.js.map +1 -0
- package/dist/engine/risk_sampler.d.ts +37 -0
- package/dist/engine/risk_sampler.d.ts.map +1 -0
- package/dist/engine/risk_sampler.js +69 -0
- package/dist/engine/risk_sampler.js.map +1 -0
- package/dist/engine/runtime_safety.d.ts +80 -0
- package/dist/engine/runtime_safety.d.ts.map +1 -0
- package/dist/engine/runtime_safety.js +195 -0
- package/dist/engine/runtime_safety.js.map +1 -0
- package/dist/engine/scope_lease.d.ts +45 -0
- package/dist/engine/scope_lease.d.ts.map +1 -0
- package/dist/engine/scope_lease.js +122 -0
- package/dist/engine/scope_lease.js.map +1 -0
- package/dist/engine/semantic_evidence.d.ts +23 -0
- package/dist/engine/semantic_evidence.d.ts.map +1 -0
- package/dist/engine/semantic_evidence.js +81 -0
- package/dist/engine/semantic_evidence.js.map +1 -0
- package/dist/engine/task_context.d.ts +16 -0
- package/dist/engine/task_context.d.ts.map +1 -1
- package/dist/engine/task_context.js +58 -0
- package/dist/engine/task_context.js.map +1 -1
- package/dist/engine/verifier.d.ts.map +1 -1
- package/dist/engine/verifier.js +22 -1
- package/dist/engine/verifier.js.map +1 -1
- package/dist/engine/workspace_resumer.d.ts +43 -0
- package/dist/engine/workspace_resumer.d.ts.map +1 -1
- package/dist/engine/workspace_resumer.js +119 -4
- package/dist/engine/workspace_resumer.js.map +1 -1
- package/dist/engine/zero_config_init.d.ts +87 -0
- package/dist/engine/zero_config_init.d.ts.map +1 -0
- package/dist/engine/zero_config_init.js +427 -0
- package/dist/engine/zero_config_init.js.map +1 -0
- package/dist/knowledge/index_manager.d.ts +19 -0
- package/dist/knowledge/index_manager.d.ts.map +1 -1
- package/dist/knowledge/index_manager.js +31 -0
- package/dist/knowledge/index_manager.js.map +1 -1
- package/dist/knowledge/writer.d.ts.map +1 -1
- package/dist/knowledge/writer.js +1 -0
- package/dist/knowledge/writer.js.map +1 -1
- package/dist/types.d.ts +61 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/templates/knowledge/patterns/core/Diff/345/275/222/345/261/236/350/277/275/350/270/252.md +47 -0
- package/templates/knowledge/patterns/core/Java/350/264/250/351/207/217/351/227/250/347/246/201.md +46 -0
- package/templates/knowledge/patterns/core/LLM/351/242/204/347/256/227/347/275/221/345/205/263.md +46 -0
- package/templates/knowledge/patterns/core//344/273/273/345/212/241/344/270/212/344/270/213/346/226/207/347/224/237/345/221/275/345/221/250/346/234/237.md +47 -0
- package/templates/knowledge/patterns/core//344/273/273/345/212/241/347/256/241/347/220/206/345/231/250.md +47 -0
- package/templates/knowledge/patterns/core//344/275/234/347/224/250/345/237/237/344/270/216/345/257/206/351/222/245/346/213/246/346/210/252.md +46 -0
- package/templates/knowledge/patterns/core//344/275/234/347/224/250/345/237/237/347/247/237/347/272/246.md +47 -0
- package/templates/knowledge/patterns/core//345/206/262/347/252/201/351/227/250/347/246/201.md +47 -0
- package/templates/knowledge/patterns/core//345/206/263/347/255/226/347/275/221/345/205/263.md +30 -11
- package/templates/knowledge/patterns/core//345/217/230/345/274/202/345/256/241/350/256/241.md +20 -0
- package/templates/knowledge/patterns/core//345/233/236/345/275/222/347/237/251/351/230/265.md +46 -0
- package/templates/knowledge/patterns/core//345/267/245/344/275/234/345/214/272/344/272/222/346/226/245/351/224/201.md +44 -0
- package/templates/knowledge/patterns/core//345/267/245/344/275/234/345/214/272/345/224/244/351/206/222.md +46 -0
- package/templates/knowledge/patterns/core//345/271/266/345/217/221/351/224/201.md +29 -16
- package/templates/knowledge/patterns/core//345/274/200/345/217/221/350/200/205/345/256/252/346/263/225.md +20 -0
- package/templates/knowledge/patterns/core//346/225/217/346/204/237/344/277/241/346/201/257/346/211/253/346/217/217.md +45 -0
- package/templates/knowledge/patterns/core//346/262/273/347/220/206/350/277/220/350/241/214/346/227/266/345/276/252/347/216/257.md +48 -0
- package/templates/knowledge/patterns/core//346/265/201/345/274/217/345/277/203/350/267/263.md +20 -0
- package/templates/knowledge/patterns/core//347/237/245/350/257/206/344/270/273/346/235/203.md +20 -0
- package/templates/knowledge/patterns/core//350/257/255/344/271/211/350/257/201/346/215/256.md +47 -0
- package/templates/knowledge/patterns/core//350/277/220/350/241/214/345/256/211/345/205/250/345/214/205.md +50 -0
- package/templates/knowledge/patterns/core//351/233/266/351/205/215/347/275/256/345/210/235/345/247/213/345/214/226.md +47 -0
- package/templates/knowledge/patterns/core//351/252/214/350/257/201/345/221/275/344/273/244/347/224/237/346/210/220.md +46 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 运行安全包 — 证据 hash chain、命令副作用分级、供应链治理、迁移回滚契约。
|
|
3
|
+
* advisory: 不 hard block(除 destructive 命令需人工确认)。
|
|
4
|
+
*/
|
|
5
|
+
import crypto from "node:crypto";
|
|
6
|
+
/**
|
|
7
|
+
* 构建证据链 — 每个步骤产出带 hash 的证据块,与前一个块链式连接。
|
|
8
|
+
*/
|
|
9
|
+
export function buildEvidenceChain(steps) {
|
|
10
|
+
const chain = [];
|
|
11
|
+
let prevHash = null;
|
|
12
|
+
for (const s of steps) {
|
|
13
|
+
const timestamp = s.timestamp ?? new Date().toISOString();
|
|
14
|
+
const dataHash = crypto
|
|
15
|
+
.createHash("sha256")
|
|
16
|
+
.update(s.payload)
|
|
17
|
+
.digest("hex")
|
|
18
|
+
.slice(0, 16);
|
|
19
|
+
const chainInput = `${s.step}:${timestamp}:${dataHash}:${prevHash ?? "genesis"}`;
|
|
20
|
+
const chainHash = crypto
|
|
21
|
+
.createHash("sha256")
|
|
22
|
+
.update(chainInput)
|
|
23
|
+
.digest("hex")
|
|
24
|
+
.slice(0, 16);
|
|
25
|
+
const block = {
|
|
26
|
+
step: s.step,
|
|
27
|
+
timestamp,
|
|
28
|
+
data_hash: dataHash,
|
|
29
|
+
prev_hash: prevHash,
|
|
30
|
+
chain_hash: chainHash,
|
|
31
|
+
payload: s.payload,
|
|
32
|
+
};
|
|
33
|
+
chain.push(block);
|
|
34
|
+
prevHash = chainHash;
|
|
35
|
+
}
|
|
36
|
+
return chain;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 验证证据链完整性 — 检查每个块的 chain_hash 是否与重算结果一致。
|
|
40
|
+
*/
|
|
41
|
+
export function verifyEvidenceChain(chain) {
|
|
42
|
+
if (chain.length === 0) {
|
|
43
|
+
return { valid: true, broken_at: null, advisory: "empty chain" };
|
|
44
|
+
}
|
|
45
|
+
for (let i = 0; i < chain.length; i++) {
|
|
46
|
+
const block = chain[i];
|
|
47
|
+
const expectedPrev = i === 0 ? null : chain[i - 1].chain_hash;
|
|
48
|
+
if (block.prev_hash !== expectedPrev) {
|
|
49
|
+
return {
|
|
50
|
+
valid: false,
|
|
51
|
+
broken_at: i,
|
|
52
|
+
advisory: `chain broken at step ${i}: prev_hash mismatch`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Recompute data_hash from payload to detect tampering
|
|
56
|
+
const expectedDataHash = crypto
|
|
57
|
+
.createHash("sha256")
|
|
58
|
+
.update(block.payload)
|
|
59
|
+
.digest("hex")
|
|
60
|
+
.slice(0, 16);
|
|
61
|
+
if (block.data_hash !== expectedDataHash) {
|
|
62
|
+
return {
|
|
63
|
+
valid: false,
|
|
64
|
+
broken_at: i,
|
|
65
|
+
advisory: `chain broken at step ${i}: data_hash mismatch (payload tampered)`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const chainInput = `${block.step}:${block.timestamp}:${block.data_hash}:${block.prev_hash ?? "genesis"}`;
|
|
69
|
+
const expectedHash = crypto
|
|
70
|
+
.createHash("sha256")
|
|
71
|
+
.update(chainInput)
|
|
72
|
+
.digest("hex")
|
|
73
|
+
.slice(0, 16);
|
|
74
|
+
if (block.chain_hash !== expectedHash) {
|
|
75
|
+
return {
|
|
76
|
+
valid: false,
|
|
77
|
+
broken_at: i,
|
|
78
|
+
advisory: `chain broken at step ${i}: chain_hash mismatch`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
valid: true,
|
|
84
|
+
broken_at: null,
|
|
85
|
+
advisory: `chain intact: ${chain.length} blocks verified`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const DESTRUCTIVE_PATTERNS = [
|
|
89
|
+
{ pattern: /\brm\s+(-[rf]+\s+|--no-preserve-root)/, example: "rm -rf" },
|
|
90
|
+
{ pattern: /\bgit\s+(push\s+--force|reset\s+--hard|clean\s+-fd)/, example: "git push --force" },
|
|
91
|
+
{ pattern: /\bdd\s+if=/, example: "dd" },
|
|
92
|
+
{ pattern: /\b(format|mkfs)\b/, example: "format" },
|
|
93
|
+
{ pattern: /\bdrop\s+(table|database|schema)\b/i, example: "DROP TABLE" },
|
|
94
|
+
{ pattern: /\bTRUNCATE\b/i, example: "TRUNCATE" },
|
|
95
|
+
{ pattern: /\bDELETE\s+FROM\b/i, example: "DELETE FROM" },
|
|
96
|
+
{ pattern: /\b(npm\s+publish|yarn\s+publish|pnpm\s+publish)\b/, example: "npm publish" },
|
|
97
|
+
];
|
|
98
|
+
const MUTATING_PATTERNS = [
|
|
99
|
+
{ pattern: /\bgit\s+(add|commit|push|merge|rebase|checkout)\b/, example: "git commit" },
|
|
100
|
+
{ pattern: /\b(npm\s+install|yarn\s+add|pnpm\s+add)\b/, example: "npm install" },
|
|
101
|
+
{ pattern: /\bmv\s+/, example: "mv" },
|
|
102
|
+
{ pattern: /\bcp\s+/, example: "cp" },
|
|
103
|
+
{ pattern: /\bmkdir\s+/, example: "mkdir" },
|
|
104
|
+
{ pattern: /\bdocker\s+(run|build|push|rmi|rm)\b/, example: "docker run" },
|
|
105
|
+
{ pattern: /\b(INSERT|UPDATE|ALTER|CREATE)\b/i, example: "INSERT" },
|
|
106
|
+
];
|
|
107
|
+
/**
|
|
108
|
+
* 分类命令的副作用级别。
|
|
109
|
+
*/
|
|
110
|
+
export function classifyCommand(command) {
|
|
111
|
+
for (const dp of DESTRUCTIVE_PATTERNS) {
|
|
112
|
+
if (dp.pattern.test(command)) {
|
|
113
|
+
return {
|
|
114
|
+
command,
|
|
115
|
+
risk: "destructive",
|
|
116
|
+
advisory: `destructive command detected: ${dp.example} — requires human confirmation`,
|
|
117
|
+
requires_human_confirm: true,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const mp of MUTATING_PATTERNS) {
|
|
122
|
+
if (mp.pattern.test(command)) {
|
|
123
|
+
return {
|
|
124
|
+
command,
|
|
125
|
+
risk: "mutating",
|
|
126
|
+
advisory: `mutating command: ${mp.example}`,
|
|
127
|
+
requires_human_confirm: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
command,
|
|
133
|
+
risk: "read_only",
|
|
134
|
+
advisory: "read-only command",
|
|
135
|
+
requires_human_confirm: false,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 检查迁移契约 — 确保 schema 变更有回滚路径。
|
|
140
|
+
*/
|
|
141
|
+
export function checkMigrationContract(migration) {
|
|
142
|
+
const forwardClassified = classifyCommand(migration.forward_command);
|
|
143
|
+
const rollbackClassified = classifyCommand(migration.rollback_command);
|
|
144
|
+
if (!migration.rollback_command || migration.rollback_command.trim().length === 0) {
|
|
145
|
+
return {
|
|
146
|
+
migration_id: migration.migration_id,
|
|
147
|
+
has_rollback: false,
|
|
148
|
+
rollback_valid: false,
|
|
149
|
+
advisory: `advisory: migration "${migration.migration_id}" has no rollback command — manual recovery required if it fails`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// Rollback should be the inverse operation
|
|
153
|
+
const rollbackValid = migration.rollback_command.length > 0;
|
|
154
|
+
return {
|
|
155
|
+
migration_id: migration.migration_id,
|
|
156
|
+
has_rollback: true,
|
|
157
|
+
rollback_valid: rollbackValid,
|
|
158
|
+
advisory: `migration "${migration.migration_id}": forward=${forwardClassified.risk}, rollback=${rollbackClassified.risk}`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const LOCKFILE_NAMES = [
|
|
162
|
+
"package-lock.json",
|
|
163
|
+
"pnpm-lock.yaml",
|
|
164
|
+
"yarn.lock",
|
|
165
|
+
"go.sum",
|
|
166
|
+
"Cargo.lock",
|
|
167
|
+
];
|
|
168
|
+
/**
|
|
169
|
+
* 检查供应链安全 — 验证依赖有 lockfile 和完整性 hash。
|
|
170
|
+
* 此为轻量级检查,不读取实际文件内容。
|
|
171
|
+
*/
|
|
172
|
+
export function checkSupplyChain(rootDirFiles, dependencies) {
|
|
173
|
+
const hasLockfile = LOCKFILE_NAMES.some((lf) => rootDirFiles.includes(lf));
|
|
174
|
+
const checks = dependencies.map((dep) => ({
|
|
175
|
+
package_name: dep.name,
|
|
176
|
+
version: dep.version,
|
|
177
|
+
has_lockfile: hasLockfile,
|
|
178
|
+
has_integrity_hash: hasLockfile, // lockfile implies integrity hashes
|
|
179
|
+
advisory: hasLockfile
|
|
180
|
+
? "locked with integrity hash"
|
|
181
|
+
: `advisory: ${dep.name}@${dep.version} not locked — supply chain risk`,
|
|
182
|
+
}));
|
|
183
|
+
const locked = checks.filter((c) => c.has_lockfile).length;
|
|
184
|
+
const unlocked = checks.length - locked;
|
|
185
|
+
return {
|
|
186
|
+
total_dependencies: dependencies.length,
|
|
187
|
+
locked_dependencies: locked,
|
|
188
|
+
unlocked_dependencies: unlocked,
|
|
189
|
+
checks,
|
|
190
|
+
advisory: unlocked > 0
|
|
191
|
+
? `advisory: ${unlocked}/${dependencies.length} dependencies not locked — recommend adding lockfile`
|
|
192
|
+
: `all ${dependencies.length} dependencies locked`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=runtime_safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime_safety.js","sourceRoot":"","sources":["../../src/engine/runtime_safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope Lease — 追踪任务对文件的 advisory 租约。
|
|
3
|
+
*
|
|
4
|
+
* CAP-011 实验性: advisory only, 不 hard block, 不阻止写入。
|
|
5
|
+
* 职责: 记录哪个任务正在操作哪些文件,供其他任务查询冲突。
|
|
6
|
+
*
|
|
7
|
+
* 生命周期:
|
|
8
|
+
* - 任务进入 executing 时 acquire
|
|
9
|
+
* - 任务完成/失败/取消时 release
|
|
10
|
+
* - 其他任务写前可 queryLease 查询 advisory 冲突
|
|
11
|
+
*/
|
|
12
|
+
export interface LeaseEntry {
|
|
13
|
+
task_id: string;
|
|
14
|
+
file_paths: string[];
|
|
15
|
+
acquired_at: string;
|
|
16
|
+
released_at: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface LeaseConflict {
|
|
19
|
+
file_path: string;
|
|
20
|
+
leased_by: string;
|
|
21
|
+
lease_acquired_at: string;
|
|
22
|
+
severity: "advisory";
|
|
23
|
+
message: string;
|
|
24
|
+
}
|
|
25
|
+
export interface LeaseSummary {
|
|
26
|
+
active_leases: number;
|
|
27
|
+
total_files_leased: number;
|
|
28
|
+
leased_by_task: Record<string, string[]>;
|
|
29
|
+
}
|
|
30
|
+
export declare class ScopeLeaseStore {
|
|
31
|
+
private filePath;
|
|
32
|
+
private leases;
|
|
33
|
+
private loaded;
|
|
34
|
+
constructor(stateDir: string);
|
|
35
|
+
private ensureLoaded;
|
|
36
|
+
private persist;
|
|
37
|
+
acquire(taskId: string, filePaths: string[]): LeaseEntry;
|
|
38
|
+
release(taskId: string): LeaseEntry | null;
|
|
39
|
+
queryLease(taskId: string, filePath: string): LeaseConflict | null;
|
|
40
|
+
getActiveLeases(): LeaseEntry[];
|
|
41
|
+
getLeaseForTask(taskId: string): LeaseEntry | null;
|
|
42
|
+
getSummary(): LeaseSummary;
|
|
43
|
+
clear(): void;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=scope_lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope_lease.d.ts","sourceRoot":"","sources":["../../src/engine/scope_lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC1C;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,EAAE,MAAM;IAO5B,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU;IAcxD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAU1C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAoBlE,eAAe,IAAI,UAAU,EAAE;IAK/B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAKlD,UAAU,IAAI,YAAY;IAe1B,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope Lease — 追踪任务对文件的 advisory 租约。
|
|
3
|
+
*
|
|
4
|
+
* CAP-011 实验性: advisory only, 不 hard block, 不阻止写入。
|
|
5
|
+
* 职责: 记录哪个任务正在操作哪些文件,供其他任务查询冲突。
|
|
6
|
+
*
|
|
7
|
+
* 生命周期:
|
|
8
|
+
* - 任务进入 executing 时 acquire
|
|
9
|
+
* - 任务完成/失败/取消时 release
|
|
10
|
+
* - 其他任务写前可 queryLease 查询 advisory 冲突
|
|
11
|
+
*/
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
export class ScopeLeaseStore {
|
|
15
|
+
filePath;
|
|
16
|
+
leases = new Map();
|
|
17
|
+
loaded = false;
|
|
18
|
+
constructor(stateDir) {
|
|
19
|
+
this.filePath = path.join(stateDir, "scope-leases.json");
|
|
20
|
+
if (!fs.existsSync(stateDir)) {
|
|
21
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
ensureLoaded() {
|
|
25
|
+
if (this.loaded)
|
|
26
|
+
return;
|
|
27
|
+
this.loaded = true;
|
|
28
|
+
try {
|
|
29
|
+
const data = fs.readFileSync(this.filePath, "utf-8");
|
|
30
|
+
const entries = JSON.parse(data);
|
|
31
|
+
for (const e of entries) {
|
|
32
|
+
if (e.released_at === null) {
|
|
33
|
+
this.leases.set(e.task_id, e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
this.leases = new Map();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
persist() {
|
|
42
|
+
const entries = [...this.leases.values()];
|
|
43
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
44
|
+
fs.writeFileSync(tmpPath, JSON.stringify(entries, null, 2));
|
|
45
|
+
fs.renameSync(tmpPath, this.filePath);
|
|
46
|
+
}
|
|
47
|
+
acquire(taskId, filePaths) {
|
|
48
|
+
this.ensureLoaded();
|
|
49
|
+
const resolved = filePaths.map(f => path.resolve(f));
|
|
50
|
+
const entry = {
|
|
51
|
+
task_id: taskId,
|
|
52
|
+
file_paths: resolved,
|
|
53
|
+
acquired_at: new Date().toISOString(),
|
|
54
|
+
released_at: null,
|
|
55
|
+
};
|
|
56
|
+
this.leases.set(taskId, entry);
|
|
57
|
+
this.persist();
|
|
58
|
+
return entry;
|
|
59
|
+
}
|
|
60
|
+
release(taskId) {
|
|
61
|
+
this.ensureLoaded();
|
|
62
|
+
const entry = this.leases.get(taskId);
|
|
63
|
+
if (!entry)
|
|
64
|
+
return null;
|
|
65
|
+
entry.released_at = new Date().toISOString();
|
|
66
|
+
this.leases.delete(taskId);
|
|
67
|
+
this.persist();
|
|
68
|
+
return entry;
|
|
69
|
+
}
|
|
70
|
+
queryLease(taskId, filePath) {
|
|
71
|
+
this.ensureLoaded();
|
|
72
|
+
const resolved = path.resolve(filePath);
|
|
73
|
+
for (const [ownerId, entry] of this.leases) {
|
|
74
|
+
if (ownerId === taskId)
|
|
75
|
+
continue;
|
|
76
|
+
for (const leased of entry.file_paths) {
|
|
77
|
+
if (leased === resolved || isParentPath(leased, resolved)) {
|
|
78
|
+
return {
|
|
79
|
+
file_path: resolved,
|
|
80
|
+
leased_by: ownerId,
|
|
81
|
+
lease_acquired_at: entry.acquired_at,
|
|
82
|
+
severity: "advisory",
|
|
83
|
+
message: `advisory: file is in scope of task ${ownerId} (leased since ${entry.acquired_at})`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
getActiveLeases() {
|
|
91
|
+
this.ensureLoaded();
|
|
92
|
+
return [...this.leases.values()];
|
|
93
|
+
}
|
|
94
|
+
getLeaseForTask(taskId) {
|
|
95
|
+
this.ensureLoaded();
|
|
96
|
+
return this.leases.get(taskId) ?? null;
|
|
97
|
+
}
|
|
98
|
+
getSummary() {
|
|
99
|
+
this.ensureLoaded();
|
|
100
|
+
const leasedByTask = {};
|
|
101
|
+
let totalFiles = 0;
|
|
102
|
+
for (const [taskId, entry] of this.leases) {
|
|
103
|
+
leasedByTask[taskId] = [...entry.file_paths];
|
|
104
|
+
totalFiles += entry.file_paths.length;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
active_leases: this.leases.size,
|
|
108
|
+
total_files_leased: totalFiles,
|
|
109
|
+
leased_by_task: leasedByTask,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
clear() {
|
|
113
|
+
this.leases.clear();
|
|
114
|
+
this.loaded = true;
|
|
115
|
+
this.persist();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function isParentPath(parent, child) {
|
|
119
|
+
const rel = path.relative(parent, child);
|
|
120
|
+
return rel.length > 0 && !rel.startsWith("..");
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=scope_lease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope_lease.js","sourceRoot":"","sources":["../../src/engine/scope_lease.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 语义交付证据 — R9 需求→语义 diff→断言→变异证据链。
|
|
3
|
+
* CAP-011 advisory: 不 hard block,只产出 advisory 报告。
|
|
4
|
+
*
|
|
5
|
+
* 职责:
|
|
6
|
+
* - computeSemanticEvidence: 从变更文件 + 需求点计算语义证据
|
|
7
|
+
* - buildDeliveryEvidenceChain: 从任务上下文构建完整交付证据链
|
|
8
|
+
*/
|
|
9
|
+
import type { TaskContext, RequirementPoint, SemanticEvidence, DeliveryEvidenceChain } from "../types.js";
|
|
10
|
+
/**
|
|
11
|
+
* 从任务上下文计算语义证据。
|
|
12
|
+
* 基于变更文件和需求点,推断变更行为和需求覆盖状态。
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeSemanticEvidence(changedFiles: string[], requirementPoints: RequirementPoint[], acceptanceResults?: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
passed: boolean;
|
|
17
|
+
}>): SemanticEvidence;
|
|
18
|
+
/**
|
|
19
|
+
* 从任务上下文构建完整交付证据链。
|
|
20
|
+
* 聚合 expand 的需求点、verify 的语义证据、execution 的变更文件。
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildDeliveryEvidenceChain(taskContext: TaskContext): DeliveryEvidenceChain | null;
|
|
23
|
+
//# sourceMappingURL=semantic_evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic_evidence.d.ts","sourceRoot":"","sources":["../../src/engine/semantic_evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EAAE,EACtB,iBAAiB,EAAE,gBAAgB,EAAE,EACrC,iBAAiB,CAAC,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,GACzD,gBAAgB,CA0ClB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,WAAW,GACvB,qBAAqB,GAAG,IAAI,CA8C9B"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 语义交付证据 — R9 需求→语义 diff→断言→变异证据链。
|
|
3
|
+
* CAP-011 advisory: 不 hard block,只产出 advisory 报告。
|
|
4
|
+
*
|
|
5
|
+
* 职责:
|
|
6
|
+
* - computeSemanticEvidence: 从变更文件 + 需求点计算语义证据
|
|
7
|
+
* - buildDeliveryEvidenceChain: 从任务上下文构建完整交付证据链
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* 从任务上下文计算语义证据。
|
|
11
|
+
* 基于变更文件和需求点,推断变更行为和需求覆盖状态。
|
|
12
|
+
*/
|
|
13
|
+
export function computeSemanticEvidence(changedFiles, requirementPoints, acceptanceResults) {
|
|
14
|
+
const changedBehaviors = changedFiles.map((f) => {
|
|
15
|
+
const matchedReq = requirementPoints.find((rp) => rp.acceptance_test_ids?.some((tid) => f.toLowerCase().includes(tid.toLowerCase().replace(/[^a-z0-9]/g, ""))));
|
|
16
|
+
return {
|
|
17
|
+
file_path: f,
|
|
18
|
+
description: `modified: ${f}`,
|
|
19
|
+
requirement_point_id: matchedReq?.id,
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
const requirementCoverage = requirementPoints.map((rp) => {
|
|
23
|
+
const hasMatchingFile = changedBehaviors.some((cb) => cb.requirement_point_id === rp.id);
|
|
24
|
+
const acceptancePassed = acceptanceResults?.filter((ar) => rp.acceptance_test_ids?.includes(ar.id));
|
|
25
|
+
const allAcceptancePassed = acceptancePassed
|
|
26
|
+
? acceptancePassed.length > 0 && acceptancePassed.every((a) => a.passed)
|
|
27
|
+
: false;
|
|
28
|
+
const covered = hasMatchingFile || allAcceptancePassed;
|
|
29
|
+
return {
|
|
30
|
+
requirement_point_id: rp.id,
|
|
31
|
+
covered,
|
|
32
|
+
evidence: covered
|
|
33
|
+
? hasMatchingFile
|
|
34
|
+
? "file change matched"
|
|
35
|
+
: "acceptance tests passed"
|
|
36
|
+
: "no matching evidence",
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
changed_behaviors: changedBehaviors,
|
|
41
|
+
unchanged_assertions: [],
|
|
42
|
+
requirement_coverage: requirementCoverage,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 从任务上下文构建完整交付证据链。
|
|
47
|
+
* 聚合 expand 的需求点、verify 的语义证据、execution 的变更文件。
|
|
48
|
+
*/
|
|
49
|
+
export function buildDeliveryEvidenceChain(taskContext) {
|
|
50
|
+
const requirementPoints = taskContext.expansion?.requirement_points ?? [];
|
|
51
|
+
const semanticEvidence = taskContext.verification?.semantic_evidence;
|
|
52
|
+
const changedFiles = taskContext.execution?.changed_files ?? [];
|
|
53
|
+
if (requirementPoints.length === 0 && changedFiles.length === 0) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const fileToRequirements = changedFiles.map((f) => ({
|
|
57
|
+
file_path: f,
|
|
58
|
+
requirement_point_ids: requirementPoints
|
|
59
|
+
.filter((rp) => semanticEvidence?.changed_behaviors.some((cb) => cb.file_path === f && cb.requirement_point_id === rp.id))
|
|
60
|
+
.map((rp) => rp.id),
|
|
61
|
+
}));
|
|
62
|
+
const uncoveredPoints = requirementPoints
|
|
63
|
+
.filter((rp) => {
|
|
64
|
+
const coverage = semanticEvidence?.requirement_coverage?.find((rc) => rc.requirement_point_id === rp.id);
|
|
65
|
+
return !coverage?.covered;
|
|
66
|
+
})
|
|
67
|
+
.map((rp) => rp.id);
|
|
68
|
+
return {
|
|
69
|
+
requirement_points: requirementPoints,
|
|
70
|
+
semantic_evidence: semanticEvidence ?? undefined,
|
|
71
|
+
file_to_requirements: fileToRequirements,
|
|
72
|
+
completeness: {
|
|
73
|
+
all_requirements_covered: uncoveredPoints.length === 0,
|
|
74
|
+
uncovered_points: uncoveredPoints,
|
|
75
|
+
advisory: uncoveredPoints.length > 0
|
|
76
|
+
? `advisory: ${uncoveredPoints.length} requirement point(s) not covered by evidence: ${uncoveredPoints.join(", ")}`
|
|
77
|
+
: "all requirement points covered",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=semantic_evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic_evidence.js","sourceRoot":"","sources":["../../src/engine/semantic_evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { TaskContext, ClassifyResult, ExpandResult, VerifyResult, FailureRecord, PlanResult, CodeReviewResult, DeliveryResult } from "../types.js";
|
|
2
|
+
import { AuditPool } from "./audit_pool.js";
|
|
3
|
+
import { DiffOwnershipStore } from "./diff_ownership_store.js";
|
|
4
|
+
import { ScopeLeaseStore } from "./scope_lease.js";
|
|
5
|
+
import { ConflictGate } from "./conflict_gate.js";
|
|
2
6
|
/**
|
|
3
7
|
* 任务上下文管理器 — 负责任务状态的创建、持久化、查询和生命周期管理。
|
|
4
8
|
* 状态文件存储在 stateDir 目录下,每个任务一个 JSON 文件。
|
|
@@ -6,9 +10,21 @@ import type { TaskContext, ClassifyResult, ExpandResult, VerifyResult, FailureRe
|
|
|
6
10
|
*/
|
|
7
11
|
export declare class TaskContextManager {
|
|
8
12
|
private stateDir;
|
|
13
|
+
private auditPool;
|
|
14
|
+
private diffOwnership;
|
|
15
|
+
private scopeLease;
|
|
16
|
+
private conflictGate;
|
|
9
17
|
constructor(stateDir: string);
|
|
10
18
|
/** 获取状态存储目录路径 */
|
|
11
19
|
getStateDir(): string;
|
|
20
|
+
/** 获取审计池实例 */
|
|
21
|
+
getAuditPool(): AuditPool;
|
|
22
|
+
/** 获取 Diff 归属追踪实例 */
|
|
23
|
+
getDiffOwnership(): DiffOwnershipStore;
|
|
24
|
+
/** 获取 Scope Lease 实例 */
|
|
25
|
+
getScopeLease(): ScopeLeaseStore;
|
|
26
|
+
/** 获取冲突合并门实例 */
|
|
27
|
+
getConflictGate(): ConflictGate;
|
|
12
28
|
/**
|
|
13
29
|
* 创建新任务上下文,生成唯一 ID 并持久化到磁盘。
|
|
14
30
|
* @param intent - 用户意图文本
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task_context.d.ts","sourceRoot":"","sources":["../../src/engine/task_context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAkD,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"task_context.d.ts","sourceRoot":"","sources":["../../src/engine/task_context.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,10 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import fss from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
|
+
import { AuditPool } from "./audit_pool.js";
|
|
6
|
+
import { DiffOwnershipStore } from "./diff_ownership_store.js";
|
|
7
|
+
import { ScopeLeaseStore } from "./scope_lease.js";
|
|
8
|
+
import { ConflictGate } from "./conflict_gate.js";
|
|
5
9
|
/**
|
|
6
10
|
* 任务上下文管理器 — 管理任务的完整生命周期状态持久化。
|
|
7
11
|
*
|
|
@@ -37,14 +41,38 @@ const VALID_TRANSITIONS = {
|
|
|
37
41
|
*/
|
|
38
42
|
export class TaskContextManager {
|
|
39
43
|
stateDir;
|
|
44
|
+
auditPool;
|
|
45
|
+
diffOwnership;
|
|
46
|
+
scopeLease;
|
|
47
|
+
conflictGate;
|
|
40
48
|
constructor(stateDir) {
|
|
41
49
|
this.stateDir = stateDir;
|
|
42
50
|
fss.mkdirSync(stateDir, { recursive: true });
|
|
51
|
+
this.auditPool = new AuditPool(stateDir);
|
|
52
|
+
this.diffOwnership = new DiffOwnershipStore(stateDir);
|
|
53
|
+
this.scopeLease = new ScopeLeaseStore(stateDir);
|
|
54
|
+
this.conflictGate = new ConflictGate(this.diffOwnership, this.scopeLease);
|
|
43
55
|
}
|
|
44
56
|
/** 获取状态存储目录路径 */
|
|
45
57
|
getStateDir() {
|
|
46
58
|
return this.stateDir;
|
|
47
59
|
}
|
|
60
|
+
/** 获取审计池实例 */
|
|
61
|
+
getAuditPool() {
|
|
62
|
+
return this.auditPool;
|
|
63
|
+
}
|
|
64
|
+
/** 获取 Diff 归属追踪实例 */
|
|
65
|
+
getDiffOwnership() {
|
|
66
|
+
return this.diffOwnership;
|
|
67
|
+
}
|
|
68
|
+
/** 获取 Scope Lease 实例 */
|
|
69
|
+
getScopeLease() {
|
|
70
|
+
return this.scopeLease;
|
|
71
|
+
}
|
|
72
|
+
/** 获取冲突合并门实例 */
|
|
73
|
+
getConflictGate() {
|
|
74
|
+
return this.conflictGate;
|
|
75
|
+
}
|
|
48
76
|
/**
|
|
49
77
|
* 创建新任务上下文,生成唯一 ID 并持久化到磁盘。
|
|
50
78
|
* @param intent - 用户意图文本
|
|
@@ -106,6 +134,29 @@ export class TaskContextManager {
|
|
|
106
134
|
}
|
|
107
135
|
ctx.status = status;
|
|
108
136
|
await this.save(ctx);
|
|
137
|
+
if (status === "executing") {
|
|
138
|
+
// CAP-011: Auto-capture baseline from expansion scope when entering executing
|
|
139
|
+
const scopePaths = ctx.expansion?.scope?.allowed_paths;
|
|
140
|
+
if (scopePaths && scopePaths.length > 0) {
|
|
141
|
+
this.diffOwnership.captureBaselineFromScope(taskId, scopePaths);
|
|
142
|
+
this.scopeLease.acquire(taskId, scopePaths);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (status === "done" || status === "failed") {
|
|
146
|
+
if (status === "done") {
|
|
147
|
+
this.auditPool.append({
|
|
148
|
+
task_id: ctx.task_id,
|
|
149
|
+
risk: (ctx.classification?.risk ?? "low"),
|
|
150
|
+
changed_files: ctx.execution?.changed_files ?? [],
|
|
151
|
+
evidence: ctx.classification?.strategy ?? "",
|
|
152
|
+
capability_refs: [],
|
|
153
|
+
created_at: new Date().toISOString(),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// CAP-011: Clean up diff ownership + scope lease for terminal states
|
|
157
|
+
this.diffOwnership.clearTask(taskId);
|
|
158
|
+
this.scopeLease.release(taskId);
|
|
159
|
+
}
|
|
109
160
|
return ctx;
|
|
110
161
|
}
|
|
111
162
|
/**
|
|
@@ -163,6 +214,10 @@ export class TaskContextManager {
|
|
|
163
214
|
ctx.execution.attempt_count++;
|
|
164
215
|
ctx.execution.failure_history.push(failure);
|
|
165
216
|
}
|
|
217
|
+
// CAP-011: Record task-owned writes for diff ownership tracking (advisory)
|
|
218
|
+
for (const f of changedFiles) {
|
|
219
|
+
this.diffOwnership.recordWrite(taskId, f);
|
|
220
|
+
}
|
|
166
221
|
await this.save(ctx);
|
|
167
222
|
return ctx;
|
|
168
223
|
}
|
|
@@ -207,6 +262,9 @@ export class TaskContextManager {
|
|
|
207
262
|
return false;
|
|
208
263
|
ctx.status = "failed";
|
|
209
264
|
await this.save(ctx);
|
|
265
|
+
// CAP-011: Clean up diff ownership + scope lease for cancelled task
|
|
266
|
+
this.diffOwnership.clearTask(taskId);
|
|
267
|
+
this.scopeLease.release(taskId);
|
|
210
268
|
return true;
|
|
211
269
|
}
|
|
212
270
|
/**
|