speccore 6.3.1 → 6.5.0

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.
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /**
3
+ * decay-detector — 知识衰减检测
4
+ *
5
+ * 对比上次完整性快照(integrity.json)与当前文件状态,
6
+ * 检测哪些文件已变更但其关联索引/下游引用未更新
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.detectDecay = detectDecay;
43
+ exports.formatDecayReport = formatDecayReport;
44
+ const fs_extra_1 = require("fs-extra");
45
+ const path_1 = require("path");
46
+ const crypto_1 = require("crypto");
47
+ // ═══════════════════════════════════════════════
48
+ // 核心检测
49
+ // ═══════════════════════════════════════════════
50
+ /** 加载上次完整性快照 */
51
+ async function loadIntegritySnapshot(cwd) {
52
+ const filePath = (0, path_1.join)(cwd, '.speccore', 'cache', 'integrity.json');
53
+ if (!(await (0, fs_extra_1.pathExists)(filePath)))
54
+ return null;
55
+ try {
56
+ const content = await (0, fs_extra_1.readFile)(filePath, 'utf-8');
57
+ return JSON.parse(content);
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /** 计算当前文件 hash */
64
+ async function currentFileHash(filePath) {
65
+ try {
66
+ const { readFile: read } = await Promise.resolve().then(() => __importStar(require('fs-extra')));
67
+ const content = await read(filePath, 'utf-8');
68
+ return (0, crypto_1.createHash)('md5').update(content).digest('hex').slice(0, 8);
69
+ }
70
+ catch {
71
+ return '';
72
+ }
73
+ }
74
+ /**
75
+ * 检测知识衰减
76
+ *
77
+ * 检测规则:
78
+ * 1. content_changed: 文件 hash 与上次快照不同 → 内容已变更
79
+ * 2. downstream_stale: 上游需求变更了,但关联的 spec/task 未同步更新
80
+ * 3. orphaned: 图谱中有引用但文件已不存在
81
+ */
82
+ async function detectDecay(cwd, graph) {
83
+ const snapshot = await loadIntegritySnapshot(cwd);
84
+ const report = {
85
+ generated: new Date().toISOString(),
86
+ iteration: graph.iteration,
87
+ decayedFiles: [],
88
+ summary: { total: 0, decayed: 0, healthy: 0 },
89
+ };
90
+ const entities = Object.values(graph.entities);
91
+ report.summary.total = entities.length;
92
+ // 检测 1: content_changed — 文件内容与上次快照不一致
93
+ for (const entity of entities) {
94
+ if (!entity.file || !entity.hash)
95
+ continue;
96
+ if (snapshot && snapshot.files[entity.file]) {
97
+ const oldHash = snapshot.files[entity.file].hash;
98
+ if (oldHash !== entity.hash) {
99
+ report.decayedFiles.push({
100
+ entityId: entity.id,
101
+ title: entity.title,
102
+ file: entity.file,
103
+ type: 'content_changed',
104
+ severity: 'warning',
105
+ detail: `内容自上次索引后已变更(hash: ${oldHash} → ${entity.hash})`,
106
+ });
107
+ }
108
+ }
109
+ }
110
+ // 检测 2: downstream_stale — 上游需求变更,下游 spec/task 未更新
111
+ // 找出所有变更的需求
112
+ const changedReqs = new Set(report.decayedFiles
113
+ .filter(d => d.type === 'content_changed')
114
+ .map(d => d.entityId));
115
+ for (const reqId of changedReqs) {
116
+ // 找实现该需求的任务
117
+ const implRelations = graph.relations.filter(r => r.to === reqId && r.type === 'implements');
118
+ for (const rel of implRelations) {
119
+ const task = graph.entities[rel.from];
120
+ if (!task)
121
+ continue;
122
+ // 检查任务文件是否也变更了
123
+ const taskDecayed = report.decayedFiles.some(d => d.entityId === task.id);
124
+ if (!taskDecayed) {
125
+ report.decayedFiles.push({
126
+ entityId: task.id,
127
+ title: task.title,
128
+ file: task.file,
129
+ type: 'downstream_stale',
130
+ severity: 'critical',
131
+ detail: `上游需求 ${reqId} 已变更,但此任务未同步更新`,
132
+ affectedDownstream: [reqId],
133
+ });
134
+ }
135
+ }
136
+ }
137
+ // 检测 3: orphaned — 图谱中有实体但文件可能不存在(hash 为空)
138
+ for (const entity of entities) {
139
+ if (entity.hash === '' && entity.file && entity.type !== 'user-file') {
140
+ report.decayedFiles.push({
141
+ entityId: entity.id,
142
+ title: entity.title,
143
+ file: entity.file,
144
+ type: 'orphaned',
145
+ severity: 'warning',
146
+ detail: '文件不存在或无法读取',
147
+ });
148
+ }
149
+ }
150
+ report.summary.decayed = report.decayedFiles.length;
151
+ report.summary.healthy = report.summary.total - report.summary.decayed;
152
+ return report;
153
+ }
154
+ /** 格式化衰减报告为 Markdown */
155
+ function formatDecayReport(report) {
156
+ const lines = [];
157
+ lines.push('## 知识衰减检测');
158
+ lines.push('');
159
+ if (report.decayedFiles.length === 0) {
160
+ lines.push('> ✅ 所有知识均为最新状态,无衰减');
161
+ return lines.join('\n');
162
+ }
163
+ const critical = report.decayedFiles.filter(d => d.severity === 'critical');
164
+ const warning = report.decayedFiles.filter(d => d.severity === 'warning');
165
+ if (critical.length > 0) {
166
+ lines.push('### ❌ 严重(上下游不一致)');
167
+ lines.push('');
168
+ for (const item of critical) {
169
+ lines.push(`| \`${item.entityId}\` | ${item.title} | ${item.detail} |`);
170
+ }
171
+ lines.push('');
172
+ }
173
+ if (warning.length > 0) {
174
+ lines.push('### ⚠️ 警告(内容已变更)');
175
+ lines.push('');
176
+ for (const item of warning) {
177
+ lines.push(`| \`${item.entityId}\` | ${item.title} | ${item.detail} |`);
178
+ }
179
+ lines.push('');
180
+ }
181
+ lines.push(`> 共 ${report.summary.total} 个实体,${report.summary.decayed} 个需关注`);
182
+ return lines.join('\n');
183
+ }
184
+ //# sourceMappingURL=decay-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decay-detector.js","sourceRoot":"","sources":["../../src/core/decay-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * knowledge-graph — 知识图谱构建引擎
3
+ *
4
+ * 从文件系统扫描需求/规格/任务/子任务,提取实体和关联关系
5
+ * 输出 knowledge-graph.json(机器读)+ CONTEXT.md(AI 读)
6
+ */
7
+ export interface KnowledgeGraph {
8
+ version: string;
9
+ generated: string;
10
+ iteration: string;
11
+ entities: Record<string, GraphEntity>;
12
+ relations: GraphRelation[];
13
+ stats: GraphStats;
14
+ }
15
+ export interface GraphEntity {
16
+ id: string;
17
+ type: 'requirement' | 'spec' | 'task' | 'subtask' | 'user-file';
18
+ title: string;
19
+ file: string;
20
+ hash: string;
21
+ mtime: string;
22
+ status?: string;
23
+ platform?: string;
24
+ parentTaskId?: string;
25
+ tags?: string[];
26
+ }
27
+ export interface GraphRelation {
28
+ from: string;
29
+ to: string;
30
+ type: 'implements' | 'specifies' | 'subtask_of' | 'depends_on' | 'references';
31
+ }
32
+ export interface GraphStats {
33
+ requirements: number;
34
+ specs: number;
35
+ tasks: number;
36
+ subtasks: number;
37
+ userFiles: number;
38
+ relations: number;
39
+ }
40
+ export declare function buildKnowledgeGraph(cwd: string, iteration?: string): Promise<KnowledgeGraph>;
41
+ /** 保存知识图谱到 cache 目录 */
42
+ export declare function saveKnowledgeGraph(cwd: string, graph: KnowledgeGraph): Promise<string>;
43
+ /** 加载已存在的知识图谱 */
44
+ export declare function loadKnowledgeGraph(cwd: string): Promise<KnowledgeGraph | null>;
45
+ /** 获取指定任务的关联链(上游需求 + 关联子任务) */
46
+ export declare function getTaskContext(graph: KnowledgeGraph, taskId: string): {
47
+ requirement: GraphEntity | null;
48
+ siblingSubtasks: GraphEntity[];
49
+ parentTask: GraphEntity | null;
50
+ };
51
+ //# sourceMappingURL=knowledge-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge-graph.d.ts","sourceRoot":"","sources":["../../src/core/knowledge-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACtC,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,KAAK,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,CAAC;CAC/E;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAiVD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAoDzB;AAED,uBAAuB;AACvB,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5F;AAED,iBAAiB;AACjB,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CASpF;AAED,+BAA+B;AAC/B,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG;IACrE,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;CAChC,CA+BA"}