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.
Files changed (156) hide show
  1. package/README.md +229 -28
  2. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  3. package/dist/adapters/claude_code/tools.js +319 -5
  4. package/dist/adapters/claude_code/tools.js.map +1 -1
  5. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  6. package/dist/adapters/shared/workflow_template.js +26 -3
  7. package/dist/adapters/shared/workflow_template.js.map +1 -1
  8. package/dist/bin/soloforge.js +169 -13
  9. package/dist/bin/soloforge.js.map +1 -1
  10. package/dist/engine/audit_pool.d.ts +36 -0
  11. package/dist/engine/audit_pool.d.ts.map +1 -0
  12. package/dist/engine/audit_pool.js +83 -0
  13. package/dist/engine/audit_pool.js.map +1 -0
  14. package/dist/engine/audit_sampler.d.ts +15 -0
  15. package/dist/engine/audit_sampler.d.ts.map +1 -0
  16. package/dist/engine/audit_sampler.js +26 -0
  17. package/dist/engine/audit_sampler.js.map +1 -0
  18. package/dist/engine/capability_action_advisor.d.ts +24 -0
  19. package/dist/engine/capability_action_advisor.d.ts.map +1 -0
  20. package/dist/engine/capability_action_advisor.js +147 -0
  21. package/dist/engine/capability_action_advisor.js.map +1 -0
  22. package/dist/engine/capability_registry.d.ts +23 -1
  23. package/dist/engine/capability_registry.d.ts.map +1 -1
  24. package/dist/engine/capability_registry.js +511 -19
  25. package/dist/engine/capability_registry.js.map +1 -1
  26. package/dist/engine/capability_state_store.d.ts +50 -0
  27. package/dist/engine/capability_state_store.d.ts.map +1 -0
  28. package/dist/engine/capability_state_store.js +123 -0
  29. package/dist/engine/capability_state_store.js.map +1 -0
  30. package/dist/engine/cognitive_anchor.d.ts +59 -0
  31. package/dist/engine/cognitive_anchor.d.ts.map +1 -0
  32. package/dist/engine/cognitive_anchor.js +68 -0
  33. package/dist/engine/cognitive_anchor.js.map +1 -0
  34. package/dist/engine/conflict_gate.d.ts +36 -0
  35. package/dist/engine/conflict_gate.d.ts.map +1 -0
  36. package/dist/engine/conflict_gate.js +73 -0
  37. package/dist/engine/conflict_gate.js.map +1 -0
  38. package/dist/engine/decision_contract.d.ts +29 -0
  39. package/dist/engine/decision_contract.d.ts.map +1 -0
  40. package/dist/engine/decision_contract.js +41 -0
  41. package/dist/engine/decision_contract.js.map +1 -0
  42. package/dist/engine/delivery.d.ts.map +1 -1
  43. package/dist/engine/delivery.js +83 -0
  44. package/dist/engine/delivery.js.map +1 -1
  45. package/dist/engine/developer_sovereignty.d.ts +62 -0
  46. package/dist/engine/developer_sovereignty.d.ts.map +1 -0
  47. package/dist/engine/developer_sovereignty.js +134 -0
  48. package/dist/engine/developer_sovereignty.js.map +1 -0
  49. package/dist/engine/diff_ownership.d.ts +74 -0
  50. package/dist/engine/diff_ownership.d.ts.map +1 -0
  51. package/dist/engine/diff_ownership.js +143 -0
  52. package/dist/engine/diff_ownership.js.map +1 -0
  53. package/dist/engine/diff_ownership_store.d.ts +76 -0
  54. package/dist/engine/diff_ownership_store.d.ts.map +1 -0
  55. package/dist/engine/diff_ownership_store.js +264 -0
  56. package/dist/engine/diff_ownership_store.js.map +1 -0
  57. package/dist/engine/escape_report.d.ts +45 -0
  58. package/dist/engine/escape_report.d.ts.map +1 -0
  59. package/dist/engine/escape_report.js +97 -0
  60. package/dist/engine/escape_report.js.map +1 -0
  61. package/dist/engine/exploration.d.ts +54 -0
  62. package/dist/engine/exploration.d.ts.map +1 -1
  63. package/dist/engine/exploration.js +138 -0
  64. package/dist/engine/exploration.js.map +1 -1
  65. package/dist/engine/governance_report.d.ts +36 -0
  66. package/dist/engine/governance_report.d.ts.map +1 -0
  67. package/dist/engine/governance_report.js +79 -0
  68. package/dist/engine/governance_report.js.map +1 -0
  69. package/dist/engine/java_quality_guard.d.ts +52 -0
  70. package/dist/engine/java_quality_guard.d.ts.map +1 -0
  71. package/dist/engine/java_quality_guard.js +237 -0
  72. package/dist/engine/java_quality_guard.js.map +1 -0
  73. package/dist/engine/job_manager.d.ts +76 -0
  74. package/dist/engine/job_manager.d.ts.map +1 -0
  75. package/dist/engine/job_manager.js +225 -0
  76. package/dist/engine/job_manager.js.map +1 -0
  77. package/dist/engine/knowledge_sovereignty.d.ts +61 -0
  78. package/dist/engine/knowledge_sovereignty.d.ts.map +1 -0
  79. package/dist/engine/knowledge_sovereignty.js +190 -0
  80. package/dist/engine/knowledge_sovereignty.js.map +1 -0
  81. package/dist/engine/mutation_audit.d.ts +43 -0
  82. package/dist/engine/mutation_audit.d.ts.map +1 -0
  83. package/dist/engine/mutation_audit.js +118 -0
  84. package/dist/engine/mutation_audit.js.map +1 -0
  85. package/dist/engine/policy_drift_detector.d.ts +46 -0
  86. package/dist/engine/policy_drift_detector.d.ts.map +1 -0
  87. package/dist/engine/policy_drift_detector.js +181 -0
  88. package/dist/engine/policy_drift_detector.js.map +1 -0
  89. package/dist/engine/regression_matrix.d.ts +102 -0
  90. package/dist/engine/regression_matrix.d.ts.map +1 -0
  91. package/dist/engine/regression_matrix.js +380 -0
  92. package/dist/engine/regression_matrix.js.map +1 -0
  93. package/dist/engine/risk_sampler.d.ts +37 -0
  94. package/dist/engine/risk_sampler.d.ts.map +1 -0
  95. package/dist/engine/risk_sampler.js +69 -0
  96. package/dist/engine/risk_sampler.js.map +1 -0
  97. package/dist/engine/runtime_safety.d.ts +80 -0
  98. package/dist/engine/runtime_safety.d.ts.map +1 -0
  99. package/dist/engine/runtime_safety.js +195 -0
  100. package/dist/engine/runtime_safety.js.map +1 -0
  101. package/dist/engine/scope_lease.d.ts +45 -0
  102. package/dist/engine/scope_lease.d.ts.map +1 -0
  103. package/dist/engine/scope_lease.js +122 -0
  104. package/dist/engine/scope_lease.js.map +1 -0
  105. package/dist/engine/semantic_evidence.d.ts +23 -0
  106. package/dist/engine/semantic_evidence.d.ts.map +1 -0
  107. package/dist/engine/semantic_evidence.js +81 -0
  108. package/dist/engine/semantic_evidence.js.map +1 -0
  109. package/dist/engine/task_context.d.ts +16 -0
  110. package/dist/engine/task_context.d.ts.map +1 -1
  111. package/dist/engine/task_context.js +58 -0
  112. package/dist/engine/task_context.js.map +1 -1
  113. package/dist/engine/verifier.d.ts.map +1 -1
  114. package/dist/engine/verifier.js +22 -1
  115. package/dist/engine/verifier.js.map +1 -1
  116. package/dist/engine/workspace_resumer.d.ts +43 -0
  117. package/dist/engine/workspace_resumer.d.ts.map +1 -1
  118. package/dist/engine/workspace_resumer.js +119 -4
  119. package/dist/engine/workspace_resumer.js.map +1 -1
  120. package/dist/engine/zero_config_init.d.ts +87 -0
  121. package/dist/engine/zero_config_init.d.ts.map +1 -0
  122. package/dist/engine/zero_config_init.js +427 -0
  123. package/dist/engine/zero_config_init.js.map +1 -0
  124. package/dist/knowledge/index_manager.d.ts +19 -0
  125. package/dist/knowledge/index_manager.d.ts.map +1 -1
  126. package/dist/knowledge/index_manager.js +31 -0
  127. package/dist/knowledge/index_manager.js.map +1 -1
  128. package/dist/knowledge/writer.d.ts.map +1 -1
  129. package/dist/knowledge/writer.js +1 -0
  130. package/dist/knowledge/writer.js.map +1 -1
  131. package/dist/types.d.ts +61 -1
  132. package/dist/types.d.ts.map +1 -1
  133. package/package.json +2 -2
  134. package/templates/knowledge/patterns/core/Diff/345/275/222/345/261/236/350/277/275/350/270/252.md +47 -0
  135. package/templates/knowledge/patterns/core/Java/350/264/250/351/207/217/351/227/250/347/246/201.md +46 -0
  136. package/templates/knowledge/patterns/core/LLM/351/242/204/347/256/227/347/275/221/345/205/263.md +46 -0
  137. 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
  138. package/templates/knowledge/patterns/core//344/273/273/345/212/241/347/256/241/347/220/206/345/231/250.md +47 -0
  139. 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
  140. package/templates/knowledge/patterns/core//344/275/234/347/224/250/345/237/237/347/247/237/347/272/246.md +47 -0
  141. package/templates/knowledge/patterns/core//345/206/262/347/252/201/351/227/250/347/246/201.md +47 -0
  142. package/templates/knowledge/patterns/core//345/206/263/347/255/226/347/275/221/345/205/263.md +30 -11
  143. package/templates/knowledge/patterns/core//345/217/230/345/274/202/345/256/241/350/256/241.md +20 -0
  144. package/templates/knowledge/patterns/core//345/233/236/345/275/222/347/237/251/351/230/265.md +46 -0
  145. 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
  146. package/templates/knowledge/patterns/core//345/267/245/344/275/234/345/214/272/345/224/244/351/206/222.md +46 -0
  147. package/templates/knowledge/patterns/core//345/271/266/345/217/221/351/224/201.md +29 -16
  148. package/templates/knowledge/patterns/core//345/274/200/345/217/221/350/200/205/345/256/252/346/263/225.md +20 -0
  149. 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
  150. 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
  151. package/templates/knowledge/patterns/core//346/265/201/345/274/217/345/277/203/350/267/263.md +20 -0
  152. package/templates/knowledge/patterns/core//347/237/245/350/257/206/344/270/273/346/235/203.md +20 -0
  153. package/templates/knowledge/patterns/core//350/257/255/344/271/211/350/257/201/346/215/256.md +47 -0
  154. package/templates/knowledge/patterns/core//350/277/220/350/241/214/345/256/211/345/205/250/345/214/205.md +50 -0
  155. 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
  156. 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,225 @@
1
+ /**
2
+ * 长任务 Job 管理 — checkpoint、heartbeat、resume/cancel、认知锚点。
3
+ * advisory: 不 hard block,提供恢复和监控能力。
4
+ *
5
+ * 职责:
6
+ * - 创建/更新/查询 job checkpoint
7
+ * - heartbeat 检测活跃状态
8
+ * - 从 checkpoint 恢复任务
9
+ * - 认知锚点(上下文摘要)
10
+ */
11
+ import fs from "node:fs/promises";
12
+ import fss from "node:fs";
13
+ import path from "node:path";
14
+ import crypto from "node:crypto";
15
+ export class JobManager {
16
+ stateDir;
17
+ constructor(stateDir) {
18
+ this.stateDir = stateDir;
19
+ fss.mkdirSync(stateDir, { recursive: true });
20
+ }
21
+ /**
22
+ * 创建新 job,分配 job_id 并写入初始 checkpoint。
23
+ */
24
+ async createJob(taskId, phase, initialSummary) {
25
+ const jobId = `job-${crypto.randomUUID().slice(0, 8)}`;
26
+ const now = new Date().toISOString();
27
+ const checkpoint = {
28
+ job_id: jobId,
29
+ task_id: taskId,
30
+ phase,
31
+ heartbeat_at: now,
32
+ checkpoint_number: 1,
33
+ cognitive_anchor: {
34
+ phase,
35
+ summary: initialSummary,
36
+ key_decisions: [],
37
+ pending_actions: [],
38
+ created_at: now,
39
+ },
40
+ state_snapshot: {},
41
+ };
42
+ await this.writeCheckpoint(checkpoint);
43
+ return checkpoint;
44
+ }
45
+ /**
46
+ * 更新 checkpoint — 记录心跳和阶段进展。
47
+ */
48
+ async updateCheckpoint(jobId, taskId, phase, anchor, stateSnapshot) {
49
+ const existing = await this.loadLatestCheckpoint(jobId, taskId);
50
+ if (!existing)
51
+ return null;
52
+ const now = new Date().toISOString();
53
+ const checkpoint = {
54
+ job_id: jobId,
55
+ task_id: taskId,
56
+ phase,
57
+ heartbeat_at: now,
58
+ checkpoint_number: existing.checkpoint_number + 1,
59
+ cognitive_anchor: {
60
+ phase,
61
+ summary: anchor.summary ?? existing.cognitive_anchor.summary,
62
+ key_decisions: anchor.key_decisions ?? existing.cognitive_anchor.key_decisions,
63
+ pending_actions: anchor.pending_actions ?? existing.cognitive_anchor.pending_actions,
64
+ created_at: now,
65
+ },
66
+ state_snapshot: stateSnapshot ?? existing.state_snapshot,
67
+ };
68
+ await this.writeCheckpoint(checkpoint);
69
+ return checkpoint;
70
+ }
71
+ /**
72
+ * 心跳 — 只更新 heartbeat_at 时间戳。
73
+ */
74
+ async heartbeat(jobId, taskId) {
75
+ const existing = await this.loadLatestCheckpoint(jobId, taskId);
76
+ if (!existing)
77
+ return false;
78
+ existing.heartbeat_at = new Date().toISOString();
79
+ await this.writeCheckpoint(existing);
80
+ return true;
81
+ }
82
+ /**
83
+ * 查询 job 状态 — 包括是否活跃、距上次心跳时间。
84
+ */
85
+ async getJobStatus(jobId, taskId, maxAgeMs = 5 * 60 * 1000) {
86
+ const checkpoint = await this.loadLatestCheckpoint(jobId, taskId);
87
+ if (!checkpoint)
88
+ return null;
89
+ const lastHeartbeat = new Date(checkpoint.heartbeat_at).getTime();
90
+ const elapsed = Date.now() - lastHeartbeat;
91
+ return {
92
+ job_id: jobId,
93
+ task_id: taskId,
94
+ is_alive: elapsed < maxAgeMs,
95
+ last_heartbeat_ms_ago: elapsed,
96
+ current_phase: checkpoint.phase,
97
+ checkpoint_count: checkpoint.checkpoint_number,
98
+ latest_anchor: checkpoint.cognitive_anchor,
99
+ };
100
+ }
101
+ /**
102
+ * 从最新 checkpoint 恢复 — 返回 checkpoint 数据供调用方恢复状态。
103
+ */
104
+ async resumeFromCheckpoint(jobId, taskId) {
105
+ return this.loadLatestCheckpoint(jobId, taskId);
106
+ }
107
+ /**
108
+ * 取消 job — 删除所有 checkpoint 文件。
109
+ */
110
+ async cancelJob(jobId, taskId) {
111
+ const pattern = `${jobId}`;
112
+ const dir = path.join(this.stateDir, "jobs");
113
+ if (!fss.existsSync(dir))
114
+ return false;
115
+ const files = await fs.readdir(dir);
116
+ let removed = false;
117
+ for (const f of files) {
118
+ if (f.includes(pattern) && f.endsWith(".json")) {
119
+ await fs.unlink(path.join(dir, f));
120
+ removed = true;
121
+ }
122
+ }
123
+ return removed;
124
+ }
125
+ /**
126
+ * 列出所有活跃 job。
127
+ */
128
+ async listActiveJobs(maxAgeMs = 5 * 60 * 1000) {
129
+ const dir = path.join(this.stateDir, "jobs");
130
+ if (!fss.existsSync(dir))
131
+ return [];
132
+ const files = await fs.readdir(dir);
133
+ const checkpoints = [];
134
+ for (const f of files.filter((f) => f.endsWith(".json"))) {
135
+ try {
136
+ const data = await fs.readFile(path.join(dir, f), "utf-8");
137
+ checkpoints.push(JSON.parse(data));
138
+ }
139
+ catch {
140
+ // skip corrupt files
141
+ }
142
+ }
143
+ // Group by job_id, take latest per job
144
+ const latest = new Map();
145
+ for (const cp of checkpoints) {
146
+ const existing = latest.get(cp.job_id);
147
+ if (!existing || cp.checkpoint_number > existing.checkpoint_number) {
148
+ latest.set(cp.job_id, cp);
149
+ }
150
+ }
151
+ const statuses = [];
152
+ for (const cp of latest.values()) {
153
+ const elapsed = Date.now() - new Date(cp.heartbeat_at).getTime();
154
+ if (elapsed >= maxAgeMs)
155
+ continue;
156
+ statuses.push({
157
+ job_id: cp.job_id,
158
+ task_id: cp.task_id,
159
+ is_alive: true,
160
+ last_heartbeat_ms_ago: elapsed,
161
+ current_phase: cp.phase,
162
+ checkpoint_count: cp.checkpoint_number,
163
+ latest_anchor: cp.cognitive_anchor,
164
+ });
165
+ }
166
+ return statuses;
167
+ }
168
+ /**
169
+ * 仅凭 job_id 反查 task_id — 扫描 checkpoint 文件,返回最新一条的 task_id。
170
+ * 用于 sf_status 在不传 task_id 时自动推导。
171
+ */
172
+ async resolveTaskId(jobId) {
173
+ const dir = this.getJobsDir();
174
+ const files = await fs.readdir(dir);
175
+ const matching = files
176
+ .filter((f) => f.startsWith(jobId) && f.endsWith(".json"))
177
+ .sort()
178
+ .reverse();
179
+ for (const f of matching) {
180
+ try {
181
+ const data = JSON.parse(await fs.readFile(path.join(dir, f), "utf-8"));
182
+ return data.task_id;
183
+ }
184
+ catch {
185
+ // skip corrupt
186
+ }
187
+ }
188
+ return null;
189
+ }
190
+ // ── Internal ──
191
+ getJobsDir() {
192
+ const dir = path.join(this.stateDir, "jobs");
193
+ fss.mkdirSync(dir, { recursive: true });
194
+ return dir;
195
+ }
196
+ async writeCheckpoint(checkpoint) {
197
+ const dir = this.getJobsDir();
198
+ const filename = `${checkpoint.job_id}-${checkpoint.checkpoint_number.toString().padStart(4, "0")}.json`;
199
+ const filePath = path.join(dir, filename);
200
+ const tmpPath = `${filePath}.tmp`;
201
+ await fs.writeFile(tmpPath, JSON.stringify(checkpoint, null, 2));
202
+ await fs.rename(tmpPath, filePath);
203
+ }
204
+ async loadLatestCheckpoint(jobId, taskId) {
205
+ const dir = this.getJobsDir();
206
+ const files = await fs.readdir(dir);
207
+ const matching = files
208
+ .filter((f) => f.startsWith(jobId) && f.endsWith(".json"))
209
+ .sort()
210
+ .reverse();
211
+ for (const f of matching) {
212
+ try {
213
+ const data = await fs.readFile(path.join(dir, f), "utf-8");
214
+ const cp = JSON.parse(data);
215
+ if (cp.task_id === taskId)
216
+ return cp;
217
+ }
218
+ catch {
219
+ // skip corrupt
220
+ }
221
+ }
222
+ return null;
223
+ }
224
+ }
225
+ //# sourceMappingURL=job_manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job_manager.js","sourceRoot":"","sources":["../../src/engine/job_manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Knowledge Sovereignty — 知识主权: drafts/quarantine/core 三级生命周期。
3
+ * R10 advisory: 不 hard block,只产出 advisory 报告。
4
+ *
5
+ * 职责:
6
+ * - quarantineGate: 检查知识条目是否在 quarantine 期
7
+ * - promoteToQuarantine: 从 drafts 晋升到 quarantine(自动)
8
+ * - promoteToCore: 从 quarantine 晋级到 core(需人工确认)
9
+ * - 查询 quarantine 状态
10
+ */
11
+ export declare const DEFAULT_QUARANTINE_DAYS = 7;
12
+ export type KnowledgeTier = "draft" | "quarantine" | "core";
13
+ export interface KnowledgeSovereigntyEntry {
14
+ name: string;
15
+ file_path: string;
16
+ tier: KnowledgeTier;
17
+ quarantined_at: string | null;
18
+ quarantine_expires_at: string | null;
19
+ can_reference: boolean;
20
+ advisory: string;
21
+ }
22
+ export interface SovereigntyReport {
23
+ total_entries: number;
24
+ by_tier: Record<KnowledgeTier, number>;
25
+ quarantine_entries: KnowledgeSovereigntyEntry[];
26
+ can_promote_to_core: Array<{
27
+ name: string;
28
+ file_path: string;
29
+ }>;
30
+ summary: string;
31
+ }
32
+ /**
33
+ * 检查条目是否在 quarantine 期 — advisory only, 不 hard block。
34
+ * quarantine 期间条目可被引用,但标记为 advisory。
35
+ */
36
+ export declare function quarantineGate(entry: KnowledgeSovereigntyEntry): {
37
+ allowed: boolean;
38
+ advisory: string;
39
+ };
40
+ /**
41
+ * 将 drafts 中的条目晋升到 quarantine — 自动,不需要人工确认。
42
+ */
43
+ export declare function promoteToQuarantine(draftPath: string, knowledgeDir: string, quarantineDays?: number): Promise<KnowledgeSovereigntyEntry | null>;
44
+ /**
45
+ * 将 quarantine 中的条目晋级到 core — 需要人工确认。
46
+ * confirm=false 时只返回预览,不执行晋级。
47
+ */
48
+ export declare function promoteToCore(quarantinePath: string, knowledgeDir: string, confirm: {
49
+ confirmed: boolean;
50
+ confirmed_by: string;
51
+ reason: string;
52
+ }): Promise<{
53
+ success: boolean;
54
+ target_path: string;
55
+ advisory: string;
56
+ }>;
57
+ /**
58
+ * 扫描 knowledge 目录,生成主权报告。
59
+ */
60
+ export declare function generateSovereigntyReport(knowledgeDir: string): Promise<SovereigntyReport>;
61
+ //# sourceMappingURL=knowledge_sovereignty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge_sovereignty.d.ts","sourceRoot":"","sources":["../../src/engine/knowledge_sovereignty.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,EAAE,yBAAyB,EAAE,CAAC;IAChD,mBAAmB,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,yBAAyB,GAC/B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAgCxC;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,cAAc,SAA0B,GACvC,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAmC3C;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IACP,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA0DtE;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAyD5B"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Knowledge Sovereignty — 知识主权: drafts/quarantine/core 三级生命周期。
3
+ * R10 advisory: 不 hard block,只产出 advisory 报告。
4
+ *
5
+ * 职责:
6
+ * - quarantineGate: 检查知识条目是否在 quarantine 期
7
+ * - promoteToQuarantine: 从 drafts 晋升到 quarantine(自动)
8
+ * - promoteToCore: 从 quarantine 晋级到 core(需人工确认)
9
+ * - 查询 quarantine 状态
10
+ */
11
+ import fs from "node:fs/promises";
12
+ import fss from "node:fs";
13
+ import path from "node:path";
14
+ import matter from "gray-matter";
15
+ export const DEFAULT_QUARANTINE_DAYS = 7;
16
+ /**
17
+ * 检查条目是否在 quarantine 期 — advisory only, 不 hard block。
18
+ * quarantine 期间条目可被引用,但标记为 advisory。
19
+ */
20
+ export function quarantineGate(entry) {
21
+ if (entry.tier === "core") {
22
+ return { allowed: true, advisory: "core tier, unrestricted" };
23
+ }
24
+ if (entry.tier === "draft") {
25
+ return {
26
+ allowed: true,
27
+ advisory: "advisory: draft tier, not yet quarantined — reference with caution",
28
+ };
29
+ }
30
+ if (entry.tier === "quarantine") {
31
+ if (!entry.quarantine_expires_at) {
32
+ return { allowed: true, advisory: "advisory: quarantine, no expiry set" };
33
+ }
34
+ const now = Date.now();
35
+ const expires = new Date(entry.quarantine_expires_at).getTime();
36
+ if (now < expires) {
37
+ const daysLeft = Math.ceil((expires - now) / (24 * 60 * 60 * 1000));
38
+ return {
39
+ allowed: true,
40
+ advisory: `advisory: quarantine tier, ${daysLeft} day(s) remaining — reference with caution`,
41
+ };
42
+ }
43
+ return {
44
+ allowed: true,
45
+ advisory: "quarantine expired, eligible for core promotion",
46
+ };
47
+ }
48
+ return { allowed: true, advisory: "unknown tier" };
49
+ }
50
+ /**
51
+ * 将 drafts 中的条目晋升到 quarantine — 自动,不需要人工确认。
52
+ */
53
+ export async function promoteToQuarantine(draftPath, knowledgeDir, quarantineDays = DEFAULT_QUARANTINE_DAYS) {
54
+ if (!fss.existsSync(draftPath))
55
+ return null;
56
+ const raw = await fs.readFile(draftPath, "utf-8");
57
+ const { data: frontmatter, content: body } = matter(raw);
58
+ const quarantineDir = path.join(knowledgeDir, "quarantine");
59
+ fss.mkdirSync(quarantineDir, { recursive: true });
60
+ const now = new Date();
61
+ const expires = new Date(now.getTime() + quarantineDays * 24 * 60 * 60 * 1000);
62
+ frontmatter.tier = "quarantine";
63
+ frontmatter.quarantined_at = now.toISOString();
64
+ frontmatter.quarantine_expires_at = expires.toISOString();
65
+ const filename = path.basename(draftPath);
66
+ const targetPath = path.join(quarantineDir, filename);
67
+ const updated = matter.stringify(body, frontmatter);
68
+ const tmpPath = `${targetPath}.tmp`;
69
+ await fs.writeFile(tmpPath, updated, "utf-8");
70
+ await fs.rename(tmpPath, targetPath);
71
+ await fs.unlink(draftPath).catch(() => { });
72
+ return {
73
+ name: frontmatter.name ?? filename,
74
+ file_path: targetPath,
75
+ tier: "quarantine",
76
+ quarantined_at: now.toISOString(),
77
+ quarantine_expires_at: expires.toISOString(),
78
+ can_reference: true,
79
+ advisory: "newly quarantined, reference with caution",
80
+ };
81
+ }
82
+ /**
83
+ * 将 quarantine 中的条目晋级到 core — 需要人工确认。
84
+ * confirm=false 时只返回预览,不执行晋级。
85
+ */
86
+ export async function promoteToCore(quarantinePath, knowledgeDir, confirm) {
87
+ if (!fss.existsSync(quarantinePath)) {
88
+ return {
89
+ success: false,
90
+ target_path: "",
91
+ advisory: `file not found: ${quarantinePath}`,
92
+ };
93
+ }
94
+ if (!confirm.confirmed || !confirm.confirmed_by) {
95
+ return {
96
+ success: false,
97
+ target_path: quarantinePath,
98
+ advisory: "core promotion requires human confirmation (confirmed=true, confirmed_by non-empty)",
99
+ };
100
+ }
101
+ const raw = await fs.readFile(quarantinePath, "utf-8");
102
+ const { data: frontmatter, content: body } = matter(raw);
103
+ // Check quarantine has expired
104
+ if (frontmatter.quarantine_expires_at) {
105
+ const now = Date.now();
106
+ const expires = new Date(frontmatter.quarantine_expires_at).getTime();
107
+ if (now < expires) {
108
+ return {
109
+ success: false,
110
+ target_path: quarantinePath,
111
+ advisory: "quarantine period not yet expired, cannot promote to core",
112
+ };
113
+ }
114
+ }
115
+ const coreDir = path.join(knowledgeDir, "patterns", "core");
116
+ fss.mkdirSync(coreDir, { recursive: true });
117
+ frontmatter.tier = "core";
118
+ frontmatter.promoted_at = new Date().toISOString();
119
+ frontmatter.promoted_by = confirm.confirmed_by;
120
+ frontmatter.promotion_reason = confirm.reason;
121
+ delete frontmatter.quarantine_expires_at;
122
+ delete frontmatter.quarantined_at;
123
+ const filename = path.basename(quarantinePath);
124
+ const targetPath = path.join(coreDir, filename);
125
+ const updated = matter.stringify(body, frontmatter);
126
+ const tmpPath = `${targetPath}.tmp`;
127
+ await fs.writeFile(tmpPath, updated, "utf-8");
128
+ await fs.rename(tmpPath, targetPath);
129
+ await fs.unlink(quarantinePath).catch(() => { });
130
+ return {
131
+ success: true,
132
+ target_path: targetPath,
133
+ advisory: `promoted to core by ${confirm.confirmed_by}: ${confirm.reason}`,
134
+ };
135
+ }
136
+ /**
137
+ * 扫描 knowledge 目录,生成主权报告。
138
+ */
139
+ export async function generateSovereigntyReport(knowledgeDir) {
140
+ const entries = [];
141
+ const tiers = ["draft", "quarantine", "core"];
142
+ const tierDirs = {
143
+ draft: path.join(knowledgeDir, "drafts"),
144
+ quarantine: path.join(knowledgeDir, "quarantine"),
145
+ core: path.join(knowledgeDir, "patterns", "core"),
146
+ };
147
+ const tierCounts = { draft: 0, quarantine: 0, core: 0 };
148
+ const canPromoteToCore = [];
149
+ for (const tier of tiers) {
150
+ const dir = tierDirs[tier];
151
+ if (!fss.existsSync(dir))
152
+ continue;
153
+ const files = await fs.readdir(dir);
154
+ for (const f of files.filter((f) => f.endsWith(".md"))) {
155
+ const filePath = path.join(dir, f);
156
+ try {
157
+ const raw = await fs.readFile(filePath, "utf-8");
158
+ const { data } = matter(raw);
159
+ const entry = {
160
+ name: data.name ?? f,
161
+ file_path: filePath,
162
+ tier,
163
+ quarantined_at: data.quarantined_at ?? null,
164
+ quarantine_expires_at: data.quarantine_expires_at ?? null,
165
+ can_reference: true,
166
+ advisory: "",
167
+ };
168
+ tierCounts[tier]++;
169
+ if (tier === "quarantine" && data.quarantine_expires_at) {
170
+ const expires = new Date(data.quarantine_expires_at).getTime();
171
+ if (Date.now() >= expires) {
172
+ canPromoteToCore.push({ name: entry.name, file_path: filePath });
173
+ }
174
+ }
175
+ entries.push(entry);
176
+ }
177
+ catch {
178
+ // skip unparseable files
179
+ }
180
+ }
181
+ }
182
+ return {
183
+ total_entries: entries.length,
184
+ by_tier: tierCounts,
185
+ quarantine_entries: entries.filter((e) => e.tier === "quarantine"),
186
+ can_promote_to_core: canPromoteToCore,
187
+ summary: `${entries.length} entries (${tierCounts.draft} drafts, ${tierCounts.quarantine} quarantine, ${tierCounts.core} core)`,
188
+ };
189
+ }
190
+ //# sourceMappingURL=knowledge_sovereignty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge_sovereignty.js","sourceRoot":"","sources":["../../src/engine/knowledge_sovereignty.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 变异审计真实化 — 需求绑定变异点 + mutant killed 证据。
3
+ * R9 advisory: 不 hard block,只产出 advisory 报告。
4
+ *
5
+ * 职责:
6
+ * - computeMutationAudit: 从变更文件 + 需求点 + 源码计算变异证据
7
+ * - 产出 MutationAuditEvidence: mutant_killed_count / mutant_total_count / per-requirement 绑定
8
+ */
9
+ import type { RequirementPoint } from "../types.js";
10
+ export interface MutationPoint {
11
+ file_path: string;
12
+ line_number: number;
13
+ original_line: string;
14
+ requirement_point_id?: string;
15
+ }
16
+ export interface MutationAuditEntry {
17
+ requirement_point_id: string;
18
+ mutation_points: number;
19
+ mutants_killed: number;
20
+ mutants_total: number;
21
+ advisory: string;
22
+ }
23
+ export interface MutationAuditEvidence {
24
+ mutant_killed_count: number;
25
+ mutant_total_count: number;
26
+ kill_ratio: number;
27
+ per_requirement: MutationAuditEntry[];
28
+ uncovered_requirements: string[];
29
+ summary: string;
30
+ }
31
+ /**
32
+ * 从源码中提取变异候选点,并尝试关联到需求点。
33
+ * 关联策略: 文件路径与需求点描述关键词匹配。
34
+ */
35
+ export declare function extractMutationPoints(sourceFiles: Array<{
36
+ file_path: string;
37
+ content: string;
38
+ }>, requirementPoints: RequirementPoint[]): MutationPoint[];
39
+ /**
40
+ * 计算变异审计证据 — 每个需求点的变异覆盖状态。
41
+ */
42
+ export declare function computeMutationAudit(mutationPoints: MutationPoint[], requirementPoints: RequirementPoint[], killedCount: number, totalCount: number): MutationAuditEvidence;
43
+ //# sourceMappingURL=mutation_audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation_audit.d.ts","sourceRoot":"","sources":["../../src/engine/mutation_audit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,kBAAkB,EAAE,CAAC;IACtC,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB;AA6BD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1D,iBAAiB,EAAE,gBAAgB,EAAE,GACpC,aAAa,EAAE,CAuBjB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,aAAa,EAAE,EAC/B,iBAAiB,EAAE,gBAAgB,EAAE,EACrC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,qBAAqB,CAmEvB"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * 变异审计真实化 — 需求绑定变异点 + mutant killed 证据。
3
+ * R9 advisory: 不 hard block,只产出 advisory 报告。
4
+ *
5
+ * 职责:
6
+ * - computeMutationAudit: 从变更文件 + 需求点 + 源码计算变异证据
7
+ * - 产出 MutationAuditEvidence: mutant_killed_count / mutant_total_count / per-requirement 绑定
8
+ */
9
+ const CANDIDATE_PATTERNS = [
10
+ /\b(if|else|switch|case)\b/.source,
11
+ /(===|!==|==|!=|>=|<=|>|<)/.source,
12
+ /(&&|\|\|)/.source,
13
+ /\breturn\b/.source,
14
+ ];
15
+ const CANDIDATE_RE = new RegExp(CANDIDATE_PATTERNS.join("|"));
16
+ const EXCLUDE_PATTERNS = [
17
+ /^\s*\/\//,
18
+ /^\s*\*/,
19
+ /^\s*\/\*/,
20
+ /^\s*import /,
21
+ /^\s*export /,
22
+ /^\s*console\./,
23
+ /^\s*(interface|type|enum|declare) /,
24
+ /^\s*debugger/,
25
+ ];
26
+ function isCandidateLine(line) {
27
+ const trimmed = line.trim();
28
+ if (!trimmed)
29
+ return false;
30
+ if (EXCLUDE_PATTERNS.some((p) => p.test(trimmed)))
31
+ return false;
32
+ return CANDIDATE_RE.test(trimmed);
33
+ }
34
+ /**
35
+ * 从源码中提取变异候选点,并尝试关联到需求点。
36
+ * 关联策略: 文件路径与需求点描述关键词匹配。
37
+ */
38
+ export function extractMutationPoints(sourceFiles, requirementPoints) {
39
+ const points = [];
40
+ for (const file of sourceFiles) {
41
+ const lines = file.content.split("\n");
42
+ for (let i = 0; i < lines.length; i++) {
43
+ if (!isCandidateLine(lines[i]))
44
+ continue;
45
+ const matchedRp = requirementPoints.find((rp) => {
46
+ const keywords = rp.description.toLowerCase().split(/\s+/);
47
+ return keywords.some((kw) => kw.length > 2 && file.file_path.toLowerCase().includes(kw));
48
+ });
49
+ points.push({
50
+ file_path: file.file_path,
51
+ line_number: i + 1,
52
+ original_line: lines[i].trim(),
53
+ requirement_point_id: matchedRp?.id,
54
+ });
55
+ }
56
+ }
57
+ return points;
58
+ }
59
+ /**
60
+ * 计算变异审计证据 — 每个需求点的变异覆盖状态。
61
+ */
62
+ export function computeMutationAudit(mutationPoints, requirementPoints, killedCount, totalCount) {
63
+ const perRequirement = [];
64
+ const coveredRpIds = new Set();
65
+ for (const rp of requirementPoints) {
66
+ const rpPoints = mutationPoints.filter((mp) => mp.requirement_point_id === rp.id);
67
+ const rpTotal = rpPoints.length;
68
+ if (rpTotal > 0) {
69
+ coveredRpIds.add(rp.id);
70
+ // Distribute killed proportionally
71
+ const rpKilled = Math.min(Math.round((rpTotal / Math.max(totalCount, 1)) * killedCount), rpTotal);
72
+ perRequirement.push({
73
+ requirement_point_id: rp.id,
74
+ mutation_points: rpTotal,
75
+ mutants_killed: rpKilled,
76
+ mutants_total: rpTotal,
77
+ advisory: rpKilled === rpTotal
78
+ ? "all mutants killed"
79
+ : `advisory: ${rpTotal - rpKilled}/${rpTotal} mutants not killed for ${rp.id}`,
80
+ });
81
+ }
82
+ else {
83
+ perRequirement.push({
84
+ requirement_point_id: rp.id,
85
+ mutation_points: 0,
86
+ mutants_killed: 0,
87
+ mutants_total: 0,
88
+ advisory: `advisory: no mutation points found for requirement ${rp.id}`,
89
+ });
90
+ }
91
+ }
92
+ // Also include mutation points not bound to any requirement
93
+ const unboundPoints = mutationPoints.filter((mp) => !mp.requirement_point_id);
94
+ if (unboundPoints.length > 0) {
95
+ perRequirement.push({
96
+ requirement_point_id: "_unbound",
97
+ mutation_points: unboundPoints.length,
98
+ mutants_killed: 0,
99
+ mutants_total: unboundPoints.length,
100
+ advisory: `advisory: ${unboundPoints.length} mutation points not bound to any requirement`,
101
+ });
102
+ }
103
+ const uncoveredRequirements = requirementPoints
104
+ .filter((rp) => !coveredRpIds.has(rp.id))
105
+ .map((rp) => rp.id);
106
+ const killRatio = totalCount > 0 ? killedCount / totalCount : 1;
107
+ return {
108
+ mutant_killed_count: killedCount,
109
+ mutant_total_count: totalCount,
110
+ kill_ratio: killRatio,
111
+ per_requirement: perRequirement,
112
+ uncovered_requirements: uncoveredRequirements,
113
+ summary: uncoveredRequirements.length > 0
114
+ ? `advisory: ${uncoveredRequirements.length} requirement(s) have no killed mutants: ${uncoveredRequirements.join(", ")}`
115
+ : `mutation audit: ${killedCount}/${totalCount} killed (ratio: ${(killRatio * 100).toFixed(0)}%)`,
116
+ };
117
+ }
118
+ //# sourceMappingURL=mutation_audit.js.map