@dommaker/harness 0.13.3 → 0.16.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.
- package/CHANGELOG.md +35 -0
- package/bin/harness-knowledge-check.js +38 -23
- package/bin/harness-knowledge-track.js +30 -4
- package/bin/harness.js +24 -1
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +4 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +21 -0
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +160 -9
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +43 -6
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/core/constraints/checker.js +1 -1
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/definitions.d.ts.map +1 -1
- package/dist/core/constraints/definitions.js +34 -26
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/knowledge/audit.d.ts +76 -0
- package/dist/knowledge/audit.d.ts.map +1 -0
- package/dist/knowledge/audit.js +566 -0
- package/dist/knowledge/audit.js.map +1 -0
- package/dist/knowledge/doctor.d.ts +1 -1
- package/dist/knowledge/doctor.d.ts.map +1 -1
- package/dist/knowledge/import.d.ts +1 -1
- package/dist/knowledge/import.d.ts.map +1 -1
- package/dist/knowledge/import.js +3 -0
- package/dist/knowledge/import.js.map +1 -1
- package/dist/knowledge/index.d.ts +7 -2
- package/dist/knowledge/index.d.ts.map +1 -1
- package/dist/knowledge/index.js +7 -2
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge/ingest.d.ts +28 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +150 -5
- package/dist/knowledge/ingest.js.map +1 -1
- package/dist/knowledge/lifecycle-hooks.d.ts +1 -1
- package/dist/knowledge/lifecycle-hooks.d.ts.map +1 -1
- package/dist/knowledge/lifecycle-hooks.js +3 -0
- package/dist/knowledge/lifecycle-hooks.js.map +1 -1
- package/dist/knowledge/lifecycle.d.ts +60 -8
- package/dist/knowledge/lifecycle.d.ts.map +1 -1
- package/dist/knowledge/lifecycle.js +213 -52
- package/dist/knowledge/lifecycle.js.map +1 -1
- package/dist/knowledge/lint.d.ts +1 -1
- package/dist/knowledge/lint.d.ts.map +1 -1
- package/dist/knowledge/lint.js +44 -3
- package/dist/knowledge/lint.js.map +1 -1
- package/dist/knowledge/migration.d.ts +25 -0
- package/dist/knowledge/migration.d.ts.map +1 -0
- package/dist/knowledge/migration.js +96 -0
- package/dist/knowledge/migration.js.map +1 -0
- package/dist/knowledge/query.d.ts +30 -2
- package/dist/knowledge/query.d.ts.map +1 -1
- package/dist/knowledge/query.js +58 -0
- package/dist/knowledge/query.js.map +1 -1
- package/dist/knowledge/reference-tracker.d.ts +1 -1
- package/dist/knowledge/reference-tracker.d.ts.map +1 -1
- package/dist/knowledge/store.d.ts +50 -3
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +111 -9
- package/dist/knowledge/store.js.map +1 -1
- package/dist/knowledge/types.d.ts +43 -1
- package/dist/knowledge/types.d.ts.map +1 -1
- package/dist/knowledge/types.js +1 -0
- package/dist/knowledge/types.js.map +1 -1
- package/dist/monitoring/knowledge-evolver.d.ts +1 -1
- package/dist/monitoring/knowledge-evolver.d.ts.map +1 -1
- package/dist/types/constraint.d.ts +1 -1
- package/dist/types/constraint.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/checker.test.ts +4 -4
- package/src/cli/commands/__tests__/knowledge.test.ts +167 -0
- package/src/cli/commands/index.ts +1 -1
- package/src/cli/commands/knowledge.ts +176 -5
- package/src/cli/commands/release.ts +44 -6
- package/src/context/__tests__/knowledge-injector.test.ts +4 -1
- package/src/core/constraints/checker.ts +1 -1
- package/src/core/constraints/definitions.ts +35 -27
- package/src/dashboard/__tests__/data.test.ts +3 -0
- package/src/dashboard/__tests__/stats.test.ts +3 -0
- package/src/index.ts +3 -1
- package/src/knowledge/CONTEXT.md +29 -7
- package/src/knowledge/__tests__/audit.test.ts +598 -0
- package/src/knowledge/__tests__/doctor.test.ts +28 -1
- package/src/knowledge/__tests__/import.test.ts +1 -1
- package/src/knowledge/__tests__/ingest.test.ts +320 -1
- package/src/knowledge/__tests__/lifecycle-hooks.test.ts +4 -1
- package/src/knowledge/__tests__/lifecycle.test.ts +656 -3
- package/src/knowledge/__tests__/lint.test.ts +52 -1
- package/src/knowledge/__tests__/migration.test.ts +115 -0
- package/src/knowledge/__tests__/query.test.ts +87 -1
- package/src/knowledge/__tests__/reference-tracker.test.ts +4 -1
- package/src/knowledge/__tests__/store.test.ts +208 -1
- package/src/knowledge/audit.ts +641 -0
- package/src/knowledge/doctor.ts +1 -1
- package/src/knowledge/import.ts +4 -1
- package/src/knowledge/index.ts +7 -2
- package/src/knowledge/ingest.ts +170 -6
- package/src/knowledge/lifecycle-hooks.ts +4 -1
- package/src/knowledge/lifecycle.ts +219 -50
- package/src/knowledge/lint.ts +45 -4
- package/src/knowledge/migration.ts +73 -0
- package/src/knowledge/query.ts +72 -1
- package/src/knowledge/reference-tracker.ts +1 -1
- package/src/knowledge/store.ts +125 -8
- package/src/knowledge/types.ts +50 -1
- package/src/monitoring/__tests__/knowledge-doctor.test.ts +3 -0
- package/src/monitoring/__tests__/knowledge-evolver.test.ts +3 -0
- package/src/monitoring/knowledge-evolver.ts +1 -1
- package/src/types/constraint.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,41 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [0.16.0] - 2026-06-10
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- **prefer_worktree demoted to guideline**: `prefer_worktree` moved from iron_law to guideline severity — worktree usage is now recommended, not enforced
|
|
11
|
+
- **KnowledgeStore interface extracted**: `FileKnowledgeStore` implements `KnowledgeStore` interface, enabling mock/testing and future alternative implementations
|
|
12
|
+
|
|
13
|
+
## [0.15.0] - 2026-06-07
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Internal release (constraint tier adjustment prep)
|
|
17
|
+
|
|
18
|
+
## [0.14.0] - 2026-06-04
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **ConsumptionMode + KnowledgeOrigin types** (AS-021 P1): `rule | context | signal | reference` 消费模式,`system | agent | human | external` 知识来源
|
|
22
|
+
- **Per-mode lifecycle** (AS-021 P2): rule/context/signal 三条独立生命周期路径
|
|
23
|
+
- **queryByMode + consume()** (AS-021 P3): 按 consumptionMode 查询 + 消费时 recordReference
|
|
24
|
+
- **External content sanitization** (AS-021 P4): `ingestExternal()` 剥离 prompt injection 模式 + 长度限制
|
|
25
|
+
- **Migration script + CLI** (AS-021 P5): `harness knowledge migrate` 旧条目自动标记 consumptionMode
|
|
26
|
+
- **6-dimension quality audit engine**: `harness knowledge audit [--fix] [--dry-run]`,健康分 + 自动修复
|
|
27
|
+
- **KR4 snapshot mechanism**: 每日 index.json 快照 + 30 天存活率统计
|
|
28
|
+
- **GAP-11 promotion content quality gate**: draft→verified 要求 content ≥ 50 字符
|
|
29
|
+
- **Semantic dedup + test ID interception**: KnowledgeIngest 去重增强
|
|
30
|
+
- **Execution success rate tracking**: Path C 自动晋升依据
|
|
31
|
+
- **Human/auto contributor classification**: 晋升来源区分
|
|
32
|
+
- **D6 flywheel stats**: `harness knowledge stats` 展示飞轮指标
|
|
33
|
+
- **hooks → Agent Event Protocol API** (B9-016): 通用 hook 管线暴露为 API
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **飞轮质量审计 5 项根因修复**: 噪音治理 + 资源优化
|
|
37
|
+
- **B12 噪音治理**: 低质量条目过滤 + 资源优化
|
|
38
|
+
- **E3 findFile 碰撞修复**: 文件查找哈希碰撞
|
|
39
|
+
- **`no_delete_without_context` 增强**: 零引用 ≠ 无价值
|
|
40
|
+
- **undefined tags/applicablePhases guard**: matchesFilter 空值保护
|
|
41
|
+
|
|
7
42
|
## [0.13.0] - 2026-05-26
|
|
8
43
|
|
|
9
44
|
### Breaking
|
|
@@ -14,7 +14,6 @@ const path = require('path');
|
|
|
14
14
|
const os = require('os');
|
|
15
15
|
const STATE_FILE = '/tmp/claude-knowledge-capture-state.json';
|
|
16
16
|
const LOG_FILE = '/tmp/claude-knowledge-hooks.log';
|
|
17
|
-
const EVENTS_FILE = path.join(os.homedir(), 'events', 'studio.jsonl');
|
|
18
17
|
const UNIQUE_DIR_THRESHOLD = 10;
|
|
19
18
|
|
|
20
19
|
function log(level, message, data) {
|
|
@@ -79,30 +78,46 @@ try {
|
|
|
79
78
|
|
|
80
79
|
console.log(JSON.stringify({ systemMessage: message }));
|
|
81
80
|
}
|
|
82
|
-
//
|
|
81
|
+
// B9-016: POST agent events to Studio API
|
|
83
82
|
try {
|
|
83
|
+
const events = state.events || [];
|
|
84
|
+
const sessionId = state.sessionId || ('cc-' + Date.now());
|
|
84
85
|
const now = Date.now();
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
86
|
+
|
|
87
|
+
// Append session:end event
|
|
88
|
+
events.push({
|
|
89
|
+
sessionId,
|
|
90
|
+
agentId: 'claude-code',
|
|
91
|
+
timestamp: now,
|
|
92
|
+
type: 'session:end',
|
|
93
|
+
payload: {
|
|
94
|
+
success: true,
|
|
95
|
+
durationMs: state.startTime ? now - state.startTime : 0,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Read Studio API URL from env or default
|
|
100
|
+
const studioUrl = process.env.STUDIO_API_URL || 'http://127.0.0.1:13101';
|
|
101
|
+
const token = process.env.STUDIO_API_TOKEN || '';
|
|
102
|
+
|
|
103
|
+
if (events.length > 0 && token) {
|
|
104
|
+
const { execSync } = require('child_process');
|
|
105
|
+
const body = JSON.stringify(events);
|
|
106
|
+
try {
|
|
107
|
+
execSync(
|
|
108
|
+
`curl -s -X POST "${studioUrl}/api/v1/events/agent-events" ` +
|
|
109
|
+
`-H "Content-Type: application/json" ` +
|
|
110
|
+
`-H "Authorization: Bearer ${token}" ` +
|
|
111
|
+
`-d '${body.replace(/'/g, "'\\''")}'`,
|
|
112
|
+
{ timeout: 10000, stdio: 'pipe' }
|
|
113
|
+
);
|
|
114
|
+
log('info', 'agent-events-posted', { count: events.length, sessionId });
|
|
115
|
+
} catch (e) {
|
|
116
|
+
log('warn', 'agent-events-post-failed', { error: (e.message || String(e)).slice(0, 200) });
|
|
117
|
+
}
|
|
118
|
+
} else if (events.length > 0 && !token) {
|
|
119
|
+
log('info', 'agent-events-skipped-no-token', { count: events.length });
|
|
120
|
+
}
|
|
106
121
|
} catch {}
|
|
107
122
|
|
|
108
123
|
// Auto-ingest: scan memory files with ingest:true → call local-rag API
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* PostToolUse hook — track deep analysis signals
|
|
3
|
+
* PostToolUse hook — track deep analysis signals + collect AgentEvents
|
|
4
4
|
*
|
|
5
5
|
* Updates state file with:
|
|
6
6
|
* - planned: EnterPlanMode was called
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* - readDirs: Set of unique directories Read was called on
|
|
9
9
|
* - captured: Write to .harness/knowledge-docs/ or .harness/knowledge/
|
|
10
10
|
* - turnCount: session turn counter
|
|
11
|
+
* - events: AgentEvent[] (B9-016) — buffered for batch POST on session:end
|
|
11
12
|
*
|
|
12
|
-
* Usage: PostToolUse hook with matcher "EnterPlanMode|Agent|Read|Write|
|
|
13
|
+
* Usage: PostToolUse hook with matcher "EnterPlanMode|Agent|Read|Write|Edit|Bash"
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
const fs = require('fs');
|
|
@@ -47,7 +48,9 @@ function loadState() {
|
|
|
47
48
|
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
|
|
48
49
|
}
|
|
49
50
|
} catch {}
|
|
50
|
-
|
|
51
|
+
// B9-016: generate sessionId for this Claude Code session
|
|
52
|
+
const sessionId = 'cc-' + Date.now() + '-' + Math.random().toString(36).slice(2, 8);
|
|
53
|
+
return { planned: false, explored: false, readDirs: [], captured: false, sessionId, events: [], startTime: Date.now() };
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
function updateState(state, event) {
|
|
@@ -75,13 +78,36 @@ function updateState(state, event) {
|
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
if (toolName === 'Write') {
|
|
81
|
+
if (toolName === 'Write' || toolName === 'Edit') {
|
|
79
82
|
const input = event.tool_input || {};
|
|
80
83
|
const filePath = input.file_path || '';
|
|
81
84
|
if (filePath.includes('.harness/knowledge-docs/') || filePath.includes('.harness/knowledge/')) {
|
|
82
85
|
state.captured = true;
|
|
83
86
|
log('info', 'captured', { file: filePath });
|
|
84
87
|
}
|
|
88
|
+
// B9-016: collect file:change event
|
|
89
|
+
if (filePath && !filePath.includes('.harness/')) {
|
|
90
|
+
state.events.push({
|
|
91
|
+
sessionId: state.sessionId,
|
|
92
|
+
agentId: 'claude-code',
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
type: 'file:change',
|
|
95
|
+
payload: { path: filePath, action: toolName === 'Write' ? 'create' : 'modify' },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (toolName === 'Bash') {
|
|
101
|
+
const input = event.tool_input || {};
|
|
102
|
+
const command = input.command || '';
|
|
103
|
+
// B9-016: collect tool:call event
|
|
104
|
+
state.events.push({
|
|
105
|
+
sessionId: state.sessionId,
|
|
106
|
+
agentId: 'claude-code',
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
type: 'tool:call',
|
|
109
|
+
payload: { tool: 'Bash', command: command.slice(0, 200) },
|
|
110
|
+
});
|
|
85
111
|
}
|
|
86
112
|
}
|
|
87
113
|
|
package/bin/harness.js
CHANGED
|
@@ -39,6 +39,9 @@ const {
|
|
|
39
39
|
knowledgeUpsert,
|
|
40
40
|
knowledgeSyncStatus,
|
|
41
41
|
knowledgeSyncRag,
|
|
42
|
+
knowledgeAudit,
|
|
43
|
+
knowledgeSnapshot,
|
|
44
|
+
knowledgeMigrate,
|
|
42
45
|
failureList,
|
|
43
46
|
failureStats,
|
|
44
47
|
failureClear,
|
|
@@ -351,7 +354,7 @@ program
|
|
|
351
354
|
// ========================================
|
|
352
355
|
program
|
|
353
356
|
.command('knowledge [subcommand] [arg]')
|
|
354
|
-
.description('知识库管理(list/search/import/decay/stats)')
|
|
357
|
+
.description('知识库管理(list/search/import/decay/stats/audit)')
|
|
355
358
|
.alias('kb')
|
|
356
359
|
.option('-p, --project-path <path>', '项目路径')
|
|
357
360
|
.option('--type <types>', '按类型过滤(逗号分隔)')
|
|
@@ -365,6 +368,10 @@ program
|
|
|
365
368
|
.option('--content <content>', '知识内容 Markdown(用于 upsert)')
|
|
366
369
|
.option('--file <path>', '从文件读取内容(用于 upsert)')
|
|
367
370
|
.option('--source <source>', '知识来源 (analyst/cli/design)', 'cli')
|
|
371
|
+
.option('--fix', '自动修复(用于 audit)', false)
|
|
372
|
+
.option('--dry-run', '只输出报告不修改(用于 audit)', false)
|
|
373
|
+
.option('--threshold <n>', '短内容阈值(字符数,用于 audit)', '50')
|
|
374
|
+
.option('--dir <path>', '知识库目录(覆盖默认路径)')
|
|
368
375
|
.option('--json', 'JSON 格式输出', false)
|
|
369
376
|
.action(async (subcommand, arg, options) => {
|
|
370
377
|
const opts = { projectPath: options.projectPath, json: options.json };
|
|
@@ -408,6 +415,22 @@ program
|
|
|
408
415
|
source: options.source || 'cli',
|
|
409
416
|
});
|
|
410
417
|
break;
|
|
418
|
+
case 'audit':
|
|
419
|
+
case 'a':
|
|
420
|
+
await knowledgeAudit({
|
|
421
|
+
...opts,
|
|
422
|
+
fix: options.fix,
|
|
423
|
+
dryRun: options.dryRun,
|
|
424
|
+
threshold: options.threshold,
|
|
425
|
+
dir: options.dir,
|
|
426
|
+
});
|
|
427
|
+
break;
|
|
428
|
+
case 'snapshot':
|
|
429
|
+
knowledgeSnapshot({ ...opts, dir: options.dir });
|
|
430
|
+
break;
|
|
431
|
+
case 'migrate':
|
|
432
|
+
knowledgeMigrate({ ...opts, dir: options.dir });
|
|
433
|
+
break;
|
|
411
434
|
default:
|
|
412
435
|
// 无子命令时显示帮助
|
|
413
436
|
if (!subcommand) {
|
|
@@ -16,7 +16,7 @@ export { contract, validateSchema, type ContractOptions } from './contract';
|
|
|
16
16
|
export { review, reviewStatus, type ReviewOptions } from './review';
|
|
17
17
|
export { executeCommand, type CommandCheckOptions } from './command';
|
|
18
18
|
export { syncDocs, type SyncDocsOptions } from './sync-docs';
|
|
19
|
-
export { knowledgeList, knowledgeSearch, knowledgeImport, knowledgeDecay, knowledgeStats, knowledgeUpsert, knowledgeSyncStatus, knowledgeSyncRag, type KnowledgeOptions, type KnowledgeUpsertOptions } from './knowledge';
|
|
19
|
+
export { knowledgeList, knowledgeSearch, knowledgeImport, knowledgeDecay, knowledgeStats, knowledgeUpsert, knowledgeSyncStatus, knowledgeSyncRag, knowledgeAudit, knowledgeSnapshot, knowledgeMigrate, type KnowledgeOptions, type KnowledgeUpsertOptions } from './knowledge';
|
|
20
20
|
export { failureList, failureStats, failureClear, type FailureOptions } from './failure';
|
|
21
21
|
export { postevalPlan, type PostEvalPlanOptions } from './posteval-plan';
|
|
22
22
|
export { release, type ReleaseOptions } from './release';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC/Q,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* CLI 命令导出
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getConstraintsMeta = exports.constraints = exports.updateUserModel = exports.analyzeSessions = exports.release = exports.postevalPlan = exports.failureClear = exports.failureStats = exports.failureList = exports.knowledgeSyncRag = exports.knowledgeSyncStatus = exports.knowledgeUpsert = exports.knowledgeStats = exports.knowledgeDecay = exports.knowledgeImport = exports.knowledgeSearch = exports.knowledgeList = exports.syncDocs = exports.executeCommand = exports.reviewStatus = exports.review = exports.validateSchema = exports.contract = exports.auditDetails = exports.security = exports.performance = exports.listAcceptanceCriteria = exports.acceptance = exports.listSpecTypes = exports.specValidate = exports.flow = exports.status = exports.report = exports.init = exports.checkCoverage = exports.runPassesGate = exports.DEFAULT_CHECKPOINTS = exports.createExampleCheckpoint = exports.validate = exports.listLaws = exports.check = void 0;
|
|
6
|
+
exports.getConstraintsMeta = exports.constraints = exports.updateUserModel = exports.analyzeSessions = exports.release = exports.postevalPlan = exports.failureClear = exports.failureStats = exports.failureList = exports.knowledgeMigrate = exports.knowledgeSnapshot = exports.knowledgeAudit = exports.knowledgeSyncRag = exports.knowledgeSyncStatus = exports.knowledgeUpsert = exports.knowledgeStats = exports.knowledgeDecay = exports.knowledgeImport = exports.knowledgeSearch = exports.knowledgeList = exports.syncDocs = exports.executeCommand = exports.reviewStatus = exports.review = exports.validateSchema = exports.contract = exports.auditDetails = exports.security = exports.performance = exports.listAcceptanceCriteria = exports.acceptance = exports.listSpecTypes = exports.specValidate = exports.flow = exports.status = exports.report = exports.init = exports.checkCoverage = exports.runPassesGate = exports.DEFAULT_CHECKPOINTS = exports.createExampleCheckpoint = exports.validate = exports.listLaws = exports.check = void 0;
|
|
7
7
|
var check_1 = require("./check");
|
|
8
8
|
Object.defineProperty(exports, "check", { enumerable: true, get: function () { return check_1.check; } });
|
|
9
9
|
Object.defineProperty(exports, "listLaws", { enumerable: true, get: function () { return check_1.listLaws; } });
|
|
@@ -52,6 +52,9 @@ Object.defineProperty(exports, "knowledgeStats", { enumerable: true, get: functi
|
|
|
52
52
|
Object.defineProperty(exports, "knowledgeUpsert", { enumerable: true, get: function () { return knowledge_1.knowledgeUpsert; } });
|
|
53
53
|
Object.defineProperty(exports, "knowledgeSyncStatus", { enumerable: true, get: function () { return knowledge_1.knowledgeSyncStatus; } });
|
|
54
54
|
Object.defineProperty(exports, "knowledgeSyncRag", { enumerable: true, get: function () { return knowledge_1.knowledgeSyncRag; } });
|
|
55
|
+
Object.defineProperty(exports, "knowledgeAudit", { enumerable: true, get: function () { return knowledge_1.knowledgeAudit; } });
|
|
56
|
+
Object.defineProperty(exports, "knowledgeSnapshot", { enumerable: true, get: function () { return knowledge_1.knowledgeSnapshot; } });
|
|
57
|
+
Object.defineProperty(exports, "knowledgeMigrate", { enumerable: true, get: function () { return knowledge_1.knowledgeMigrate; } });
|
|
55
58
|
var failure_1 = require("./failure");
|
|
56
59
|
Object.defineProperty(exports, "failureList", { enumerable: true, get: function () { return failure_1.failureList; } });
|
|
57
60
|
Object.defineProperty(exports, "failureStats", { enumerable: true, get: function () { return failure_1.failureStats; } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,iCAA6D;AAApD,8FAAA,KAAK,OAAA;AAAE,iGAAA,QAAQ,OAAA;AACxB,uCAA0G;AAAjG,oGAAA,QAAQ,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAAE,+GAAA,mBAAmB,OAAA;AAC/D,6CAAqF;AAA5E,4GAAA,aAAa,OAAA;AAAE,4GAAA,aAAa,OAAA;AACrC,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,+BAA+E;AAAtE,oGAAA,YAAY,OAAA;AAAE,qGAAA,aAAa,OAAA;AACpC,2CAA0F;AAAjF,wGAAA,UAAU,OAAA;AAAE,oHAAA,sBAAsB,OAAA;AAC3C,6CAAqE;AAA5D,0GAAA,WAAW,OAAA;AACpB,uCAA0E;AAAjE,oGAAA,QAAQ,OAAA;AAAE,wGAAA,YAAY,OAAA;AAC/B,uCAA4E;AAAnE,oGAAA,QAAQ,OAAA;AAAE,0GAAA,cAAc,OAAA;AACjC,mCAAoE;AAA3D,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAC7B,qCAAqE;AAA5D,yGAAA,cAAc,OAAA;AACvB,yCAA6D;AAApD,qGAAA,QAAQ,OAAA;AACjB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,iCAA6D;AAApD,8FAAA,KAAK,OAAA;AAAE,iGAAA,QAAQ,OAAA;AACxB,uCAA0G;AAAjG,oGAAA,QAAQ,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAAE,+GAAA,mBAAmB,OAAA;AAC/D,6CAAqF;AAA5E,4GAAA,aAAa,OAAA;AAAE,4GAAA,aAAa,OAAA;AACrC,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,+BAA+E;AAAtE,oGAAA,YAAY,OAAA;AAAE,qGAAA,aAAa,OAAA;AACpC,2CAA0F;AAAjF,wGAAA,UAAU,OAAA;AAAE,oHAAA,sBAAsB,OAAA;AAC3C,6CAAqE;AAA5D,0GAAA,WAAW,OAAA;AACpB,uCAA0E;AAAjE,oGAAA,QAAQ,OAAA;AAAE,wGAAA,YAAY,OAAA;AAC/B,uCAA4E;AAAnE,oGAAA,QAAQ,OAAA;AAAE,0GAAA,cAAc,OAAA;AACjC,mCAAoE;AAA3D,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAC7B,qCAAqE;AAA5D,yGAAA,cAAc,OAAA;AACvB,yCAA6D;AAApD,qGAAA,QAAQ,OAAA;AACjB,yCAA+Q;AAAtQ,0GAAA,aAAa,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,gHAAA,mBAAmB,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AACrM,qCAAyF;AAAhF,sGAAA,WAAW,OAAA;AAAE,uGAAA,YAAY,OAAA;AAAE,uGAAA,YAAY,OAAA;AAChD,iDAAyE;AAAhE,6GAAA,YAAY,OAAA;AACrB,qCAAyD;AAAhD,kGAAA,OAAO,OAAA;AAChB,uDAAkF;AAAzE,mHAAA,eAAe,OAAA;AACxB,yDAAmF;AAA1E,oHAAA,eAAe,OAAA;AACxB,6CAAsF;AAA7E,0GAAA,WAAW,OAAA;AAAE,iHAAA,kBAAkB,OAAA"}
|
|
@@ -61,4 +61,25 @@ export declare function knowledgeSyncRag(options: KnowledgeOptions): Promise<voi
|
|
|
61
61
|
* 知识同步状态:检测所有 tracked scope 的新鲜度
|
|
62
62
|
*/
|
|
63
63
|
export declare function knowledgeSyncStatus(options: KnowledgeOptions): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* 知识库质量审计
|
|
66
|
+
*/
|
|
67
|
+
export declare function knowledgeAudit(options: KnowledgeOptions & {
|
|
68
|
+
fix?: boolean;
|
|
69
|
+
dryRun?: boolean;
|
|
70
|
+
threshold?: number;
|
|
71
|
+
dir?: string;
|
|
72
|
+
}): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* 知识库快照(KR4 存活率追踪)
|
|
75
|
+
*/
|
|
76
|
+
export declare function knowledgeSnapshot(options: KnowledgeOptions & {
|
|
77
|
+
dir?: string;
|
|
78
|
+
}): void;
|
|
79
|
+
/**
|
|
80
|
+
* 知识库迁移 — 为现有条目添加 AS-021 新字段
|
|
81
|
+
*/
|
|
82
|
+
export declare function knowledgeMigrate(options: KnowledgeOptions & {
|
|
83
|
+
dir?: string;
|
|
84
|
+
}): void;
|
|
64
85
|
//# sourceMappingURL=knowledge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/knowledge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"knowledge.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/knowledge.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,MAAM,WAAW,gBAAgB;IAC/B,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAsChB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB7E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D7E;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDpF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B/E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ClF;AAQD;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAC/D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAUpF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4BnF"}
|
|
@@ -49,17 +49,24 @@ exports.knowledgeStats = knowledgeStats;
|
|
|
49
49
|
exports.knowledgeUpsert = knowledgeUpsert;
|
|
50
50
|
exports.knowledgeSyncRag = knowledgeSyncRag;
|
|
51
51
|
exports.knowledgeSyncStatus = knowledgeSyncStatus;
|
|
52
|
+
exports.knowledgeAudit = knowledgeAudit;
|
|
53
|
+
exports.knowledgeSnapshot = knowledgeSnapshot;
|
|
54
|
+
exports.knowledgeMigrate = knowledgeMigrate;
|
|
52
55
|
const chalk_1 = __importDefault(require("chalk"));
|
|
53
56
|
const fs = __importStar(require("fs"));
|
|
57
|
+
const os = __importStar(require("os"));
|
|
58
|
+
const path = __importStar(require("path"));
|
|
54
59
|
const store_1 = require("../../knowledge/store");
|
|
55
60
|
const query_1 = require("../../knowledge/query");
|
|
56
61
|
const lifecycle_1 = require("../../knowledge/lifecycle");
|
|
57
62
|
const import_1 = require("../../knowledge/import");
|
|
63
|
+
const audit_1 = require("../../knowledge/audit");
|
|
64
|
+
const migration_1 = require("../../knowledge/migration");
|
|
58
65
|
/**
|
|
59
66
|
* 知识库列表
|
|
60
67
|
*/
|
|
61
68
|
async function knowledgeList(options) {
|
|
62
|
-
const store = new store_1.
|
|
69
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
63
70
|
const filter = { excludeArchived: false };
|
|
64
71
|
if (options.type) {
|
|
65
72
|
filter.types = options.type.split(',');
|
|
@@ -96,7 +103,7 @@ async function knowledgeList(options) {
|
|
|
96
103
|
* 知识库搜索
|
|
97
104
|
*/
|
|
98
105
|
async function knowledgeSearch(query, options) {
|
|
99
|
-
const store = new store_1.
|
|
106
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
100
107
|
const queryEngine = new query_1.KnowledgeQuery(store);
|
|
101
108
|
const budget = {
|
|
102
109
|
phase: 'cli',
|
|
@@ -130,7 +137,7 @@ async function knowledgeSearch(query, options) {
|
|
|
130
137
|
*/
|
|
131
138
|
async function knowledgeImport(options) {
|
|
132
139
|
const projectPath = options.projectPath || process.cwd();
|
|
133
|
-
const store = new store_1.
|
|
140
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
134
141
|
const sources = options.sources
|
|
135
142
|
? options.sources.split(',')
|
|
136
143
|
: ['code', 'git', 'docs'];
|
|
@@ -171,7 +178,7 @@ async function knowledgeImport(options) {
|
|
|
171
178
|
* 知识库衰减周期
|
|
172
179
|
*/
|
|
173
180
|
async function knowledgeDecay(options) {
|
|
174
|
-
const store = new store_1.
|
|
181
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
175
182
|
const lifecycle = new lifecycle_1.KnowledgeLifecycle(store);
|
|
176
183
|
if (!options.json) {
|
|
177
184
|
console.log(chalk_1.default.blue('🔄 运行衰减周期...'));
|
|
@@ -195,8 +202,9 @@ async function knowledgeDecay(options) {
|
|
|
195
202
|
* 知识库统计
|
|
196
203
|
*/
|
|
197
204
|
async function knowledgeStats(options) {
|
|
198
|
-
const store = new store_1.
|
|
205
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: getKnowledgeDir(options.projectPath) });
|
|
199
206
|
const entries = store.list({ excludeArchived: false });
|
|
207
|
+
const active = entries.filter(e => e.maturity !== 'archived');
|
|
200
208
|
const byType = {};
|
|
201
209
|
const byMaturity = {};
|
|
202
210
|
const byLayer = {};
|
|
@@ -205,12 +213,29 @@ async function knowledgeStats(options) {
|
|
|
205
213
|
byMaturity[entry.maturity] = (byMaturity[entry.maturity] || 0) + 1;
|
|
206
214
|
byLayer[entry.layer] = (byLayer[entry.layer] || 0) + 1;
|
|
207
215
|
}
|
|
216
|
+
// D6 flywheel metrics
|
|
217
|
+
const withRefs = active.filter(e => e.referencedBy.length > 0).length;
|
|
218
|
+
const refCoverage = active.length > 0 ? Math.round(withRefs / active.length * 100) : 0;
|
|
219
|
+
const avgRefs = active.length > 0
|
|
220
|
+
? Math.round(active.reduce((sum, e) => sum + e.referencedBy.length, 0) / active.length * 10) / 10
|
|
221
|
+
: 0;
|
|
222
|
+
let consumptionHitRate = 0;
|
|
223
|
+
try {
|
|
224
|
+
const statsPath = path.join(store.getBaseDir(), '.consumption-stats.json');
|
|
225
|
+
if (fs.existsSync(statsPath)) {
|
|
226
|
+
const stats = JSON.parse(fs.readFileSync(statsPath, 'utf-8'));
|
|
227
|
+
const dailyEvents = stats.dailyEvents || 0;
|
|
228
|
+
consumptionHitRate = active.length > 0 ? Math.min(Math.round(dailyEvents / active.length * 100), 100) : 0;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch { /* best-effort */ }
|
|
232
|
+
const flywheel = { refCoverage, avgRefs, consumptionHitRate };
|
|
208
233
|
if (options.json) {
|
|
209
|
-
console.log(JSON.stringify({ total: entries.length, byType, byMaturity, byLayer }, null, 2));
|
|
234
|
+
console.log(JSON.stringify({ total: entries.length, byType, byMaturity, byLayer, flywheel }, null, 2));
|
|
210
235
|
return;
|
|
211
236
|
}
|
|
212
237
|
console.log(chalk_1.default.blue(`📊 知识库统计\n`));
|
|
213
|
-
console.log(chalk_1.default.bold(` 总计: ${entries.length}
|
|
238
|
+
console.log(chalk_1.default.bold(` 总计: ${entries.length} 条 (活跃: ${active.length})\n`));
|
|
214
239
|
console.log(chalk_1.default.bold(' 按类型:'));
|
|
215
240
|
for (const [type, count] of Object.entries(byType)) {
|
|
216
241
|
console.log(` ${type}: ${count}`);
|
|
@@ -224,6 +249,10 @@ async function knowledgeStats(options) {
|
|
|
224
249
|
for (const [layer, count] of Object.entries(byLayer)) {
|
|
225
250
|
console.log(` ${layer}: ${count}`);
|
|
226
251
|
}
|
|
252
|
+
console.log(chalk_1.default.bold('\n 飞轮指标:'));
|
|
253
|
+
console.log(` 引用覆盖: ${refCoverage}%`);
|
|
254
|
+
console.log(` 平均引用: ${avgRefs}`);
|
|
255
|
+
console.log(` 消费命中率: ${consumptionHitRate}%`);
|
|
227
256
|
}
|
|
228
257
|
/**
|
|
229
258
|
* 设计时知识沉淀:写入 KnowledgeStore + 同步 Prisma Document(Studio UI 可见)
|
|
@@ -353,7 +382,129 @@ async function knowledgeSyncStatus(options) {
|
|
|
353
382
|
}
|
|
354
383
|
}
|
|
355
384
|
function getKnowledgeDir(projectPath) {
|
|
356
|
-
|
|
357
|
-
|
|
385
|
+
if (projectPath)
|
|
386
|
+
return `${projectPath}/.harness/knowledge`;
|
|
387
|
+
if (process.env.KNOWLEDGE_BASE_DIR)
|
|
388
|
+
return process.env.KNOWLEDGE_BASE_DIR;
|
|
389
|
+
return path.join(os.homedir(), '.studio', 'knowledge');
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* 知识库质量审计
|
|
393
|
+
*/
|
|
394
|
+
async function knowledgeAudit(options) {
|
|
395
|
+
const audit = new audit_1.KnowledgeAudit({
|
|
396
|
+
baseDir: options.dir || getKnowledgeDir(options.projectPath),
|
|
397
|
+
shortContentThreshold: options.threshold ? parseInt(options.threshold, 10) : undefined,
|
|
398
|
+
});
|
|
399
|
+
const isDryRun = options.dryRun && !options.fix;
|
|
400
|
+
if (!options.json && !isDryRun) {
|
|
401
|
+
console.log(chalk_1.default.blue('🔍 知识库质量审计...\n'));
|
|
402
|
+
}
|
|
403
|
+
const report = audit.run({ autoFix: options.fix && !isDryRun });
|
|
404
|
+
if (options.json) {
|
|
405
|
+
console.log(JSON.stringify(report, null, 2));
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
// Summary
|
|
409
|
+
console.log(chalk_1.default.bold(` 总条目: ${report.totalEntries}`));
|
|
410
|
+
console.log(chalk_1.default.bold(` 健康分: ${report.healthScore.before}/100`));
|
|
411
|
+
if (report.autoFixed > 0) {
|
|
412
|
+
console.log(chalk_1.default.green(` 自动修复: ${report.autoFixed} 条`));
|
|
413
|
+
console.log(chalk_1.default.bold(` 修复后: ${report.healthScore.after}/100`));
|
|
414
|
+
}
|
|
415
|
+
console.log();
|
|
416
|
+
// Dimension scores
|
|
417
|
+
const dimLabels = {
|
|
418
|
+
structure: 'D1 结构完整性',
|
|
419
|
+
content: 'D2 内容质量',
|
|
420
|
+
dedup: 'D3 去重有效性',
|
|
421
|
+
maturity: 'D4 成熟度健康',
|
|
422
|
+
freshness: 'D5 新鲜度',
|
|
423
|
+
flywheel: 'D6 飞轮验证',
|
|
424
|
+
};
|
|
425
|
+
console.log(chalk_1.default.bold(' 维度评分:'));
|
|
426
|
+
for (const [key, dim] of Object.entries(report.dimensions)) {
|
|
427
|
+
const label = dimLabels[key] || key;
|
|
428
|
+
const scoreColor = dim.score >= 80 ? chalk_1.default.green : dim.score >= 60 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
429
|
+
console.log(` ${label}: ${scoreColor(`${dim.score}/100`)} (${dim.issues} 问题)`);
|
|
430
|
+
}
|
|
431
|
+
console.log();
|
|
432
|
+
// Issues by rule
|
|
433
|
+
const ruleLabels = {
|
|
434
|
+
'frontmatter-missing': 'frontmatter 缺失',
|
|
435
|
+
'test-data-pollution': '测试数据污染',
|
|
436
|
+
'daily-audit-noise': '每日审计噪音',
|
|
437
|
+
'zero-content-proven': '零内容 proven',
|
|
438
|
+
'short-content': '短内容',
|
|
439
|
+
'maturity-inflation': '成熟度虚高',
|
|
440
|
+
'title-duplicate': '标题重复',
|
|
441
|
+
'source-refs-bloat': 'sourceReferences 膨胀',
|
|
442
|
+
'promotion-blocked': 'promotion 受阻',
|
|
443
|
+
'orphan-draft': '孤儿 draft',
|
|
444
|
+
'stale-entry': '过期条目',
|
|
445
|
+
};
|
|
446
|
+
for (const [rule, count] of Object.entries(report.summary)) {
|
|
447
|
+
if (count === 0)
|
|
448
|
+
continue;
|
|
449
|
+
const label = ruleLabels[rule] || rule;
|
|
450
|
+
console.log(` ${chalk_1.default.red(`${label}: ${count}`)}`);
|
|
451
|
+
}
|
|
452
|
+
// Detail (first 20)
|
|
453
|
+
if (report.issues.length > 0) {
|
|
454
|
+
console.log(chalk_1.default.bold(`\n 问题详情 (前 20 条):\n`));
|
|
455
|
+
for (const issue of report.issues.slice(0, 20)) {
|
|
456
|
+
const severityColor = issue.severity === 'critical' ? chalk_1.default.red
|
|
457
|
+
: issue.severity === 'high' ? chalk_1.default.yellow
|
|
458
|
+
: chalk_1.default.gray;
|
|
459
|
+
console.log(` ${severityColor(`[${issue.severity}]`)} ${issue.entryId}: ${issue.title}`);
|
|
460
|
+
console.log(` ${chalk_1.default.gray(issue.detail)} → ${issue.action}`);
|
|
461
|
+
}
|
|
462
|
+
if (report.issues.length > 20) {
|
|
463
|
+
console.log(chalk_1.default.gray(`\n ... 还有 ${report.issues.length - 20} 条`));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (!options.fix && report.issues.length > 0) {
|
|
467
|
+
console.log(chalk_1.default.yellow(`\n 使用 --fix 自动修复`));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* 知识库快照(KR4 存活率追踪)
|
|
472
|
+
*/
|
|
473
|
+
function knowledgeSnapshot(options) {
|
|
474
|
+
const store = new store_1.FileKnowledgeStore({ baseDir: options.dir || getKnowledgeDir(options.projectPath) });
|
|
475
|
+
const snapPath = store.snapshot();
|
|
476
|
+
if (options.json) {
|
|
477
|
+
console.log(JSON.stringify({ snapshotPath: snapPath }));
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
console.log(chalk_1.default.green(`✅ 快照已保存: ${snapPath}`));
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* 知识库迁移 — 为现有条目添加 AS-021 新字段
|
|
484
|
+
*/
|
|
485
|
+
function knowledgeMigrate(options) {
|
|
486
|
+
const baseDir = options.dir || getKnowledgeDir(options.projectPath);
|
|
487
|
+
if (options.json) {
|
|
488
|
+
const result = (0, migration_1.migrateKnowledgeEntries)(baseDir);
|
|
489
|
+
console.log(JSON.stringify(result, null, 2));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
console.log(chalk_1.default.blue('🔄 迁移知识条目(添加 consumptionMode/origin 字段)\n'));
|
|
493
|
+
const result = (0, migration_1.migrateKnowledgeEntries)(baseDir);
|
|
494
|
+
console.log(chalk_1.default.green(` 总计: ${result.total} 条`));
|
|
495
|
+
console.log(chalk_1.default.green(` 已迁移: ${result.migrated} 条`));
|
|
496
|
+
console.log(chalk_1.default.gray(` 已跳过: ${result.skipped} 条`));
|
|
497
|
+
if (result.errors.length > 0) {
|
|
498
|
+
console.log(chalk_1.default.red(`\n 错误: ${result.errors.length} 条`));
|
|
499
|
+
for (const err of result.errors.slice(0, 5)) {
|
|
500
|
+
console.log(chalk_1.default.red(` ${err}`));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (result.migrated === 0 && result.errors.length === 0) {
|
|
504
|
+
console.log(chalk_1.default.green('\n✅ 所有条目已是最新,无需迁移'));
|
|
505
|
+
}
|
|
506
|
+
else if (result.migrated > 0) {
|
|
507
|
+
console.log(chalk_1.default.green(`\n✅ 迁移完成`));
|
|
508
|
+
}
|
|
358
509
|
}
|
|
359
510
|
//# sourceMappingURL=knowledge.js.map
|