@dommaker/harness 0.14.0 → 0.16.1
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 +11 -0
- package/bin/harness.js +71 -0
- package/dist/cli/commands/doc-freshness-check.d.ts +53 -0
- package/dist/cli/commands/doc-freshness-check.d.ts.map +1 -0
- package/dist/cli/commands/doc-freshness-check.js +366 -0
- package/dist/cli/commands/doc-freshness-check.js.map +1 -0
- package/dist/cli/commands/index.d.ts +4 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +13 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +12 -0
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +140 -6
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/release.d.ts +11 -0
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +80 -12
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/sdd.d.ts +8 -0
- package/dist/cli/commands/sdd.d.ts.map +1 -0
- package/dist/cli/commands/sdd.js +68 -0
- package/dist/cli/commands/sdd.js.map +1 -0
- package/dist/cli/commands/spec-baseline-check.d.ts +30 -0
- package/dist/cli/commands/spec-baseline-check.d.ts.map +1 -0
- package/dist/cli/commands/spec-baseline-check.js +366 -0
- package/dist/cli/commands/spec-baseline-check.js.map +1 -0
- 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 +30 -24
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/knowledge/audit.d.ts +1 -1
- package/dist/knowledge/audit.d.ts.map +1 -1
- package/dist/knowledge/audit.js +60 -8
- package/dist/knowledge/audit.js.map +1 -1
- 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/index-generator.d.ts +36 -0
- package/dist/knowledge/index-generator.d.ts.map +1 -0
- package/dist/knowledge/index-generator.js +241 -0
- package/dist/knowledge/index-generator.js.map +1 -0
- package/dist/knowledge/index.d.ts +4 -1
- package/dist/knowledge/index.d.ts.map +1 -1
- package/dist/knowledge/index.js +4 -2
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge/ingest.d.ts +1 -1
- package/dist/knowledge/ingest.d.ts.map +1 -1
- package/dist/knowledge/ingest.js +2 -2
- 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.d.ts +16 -1
- package/dist/knowledge/lifecycle.d.ts.map +1 -1
- package/dist/knowledge/lifecycle.js +70 -0
- 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 +4 -4
- package/dist/knowledge/lint.js.map +1 -1
- package/dist/knowledge/primitives/code-structure.d.ts +37 -0
- package/dist/knowledge/primitives/code-structure.d.ts.map +1 -0
- package/dist/knowledge/primitives/code-structure.js +168 -0
- package/dist/knowledge/primitives/code-structure.js.map +1 -0
- package/dist/knowledge/query.d.ts +1 -1
- package/dist/knowledge/query.d.ts.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 +29 -2
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +10 -5
- package/dist/knowledge/store.js.map +1 -1
- package/dist/knowledge/types.d.ts +17 -1
- package/dist/knowledge/types.d.ts.map +1 -1
- 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/sdd/index-generator.d.ts +22 -0
- package/dist/sdd/index-generator.d.ts.map +1 -0
- package/dist/sdd/index-generator.js +118 -0
- package/dist/sdd/index-generator.js.map +1 -0
- 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__/doc-freshness-check.test.ts +168 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +70 -2
- package/src/cli/commands/__tests__/spec-baseline-check.test.ts +235 -0
- package/src/cli/commands/doc-freshness-check.ts +397 -0
- package/src/cli/commands/index.ts +4 -1
- package/src/cli/commands/knowledge.ts +151 -1
- package/src/cli/commands/release.ts +86 -12
- package/src/cli/commands/sdd.ts +44 -0
- package/src/cli/commands/spec-baseline-check.ts +384 -0
- package/src/context/__tests__/knowledge-injector.test.ts +1 -1
- package/src/core/constraints/checker.ts +1 -1
- package/src/core/constraints/definitions.ts +31 -25
- package/src/knowledge/__tests__/audit.test.ts +57 -1
- package/src/knowledge/__tests__/doctor.test.ts +1 -1
- package/src/knowledge/__tests__/import.test.ts +1 -1
- package/src/knowledge/__tests__/index-generator.test.ts +335 -0
- package/src/knowledge/__tests__/ingest.test.ts +1 -1
- package/src/knowledge/__tests__/lifecycle-hooks.test.ts +1 -1
- package/src/knowledge/__tests__/lifecycle.test.ts +1 -1
- package/src/knowledge/__tests__/lint.test.ts +1 -1
- package/src/knowledge/__tests__/query.test.ts +1 -1
- package/src/knowledge/__tests__/reference-tracker.test.ts +1 -1
- package/src/knowledge/__tests__/store.test.ts +1 -1
- package/src/knowledge/audit.ts +67 -10
- package/src/knowledge/doctor.ts +1 -1
- package/src/knowledge/import.ts +1 -1
- package/src/knowledge/index-generator.ts +233 -0
- package/src/knowledge/index.ts +4 -1
- package/src/knowledge/ingest.ts +3 -3
- package/src/knowledge/lifecycle-hooks.ts +1 -1
- package/src/knowledge/lifecycle.ts +72 -1
- package/src/knowledge/lint.ts +5 -5
- package/src/knowledge/primitives/__tests__/code-structure.test.ts +120 -0
- package/src/knowledge/primitives/code-structure.ts +161 -0
- package/src/knowledge/query.ts +1 -1
- package/src/knowledge/reference-tracker.ts +1 -1
- package/src/knowledge/store.ts +27 -4
- package/src/knowledge/types.ts +21 -1
- package/src/monitoring/knowledge-evolver.ts +1 -1
- package/src/sdd/__tests__/index-generator.test.ts +150 -0
- package/src/sdd/index-generator.ts +109 -0
- package/src/types/constraint.ts +1 -1
- package/dist/cli/commands/diagnose.d.ts +0 -16
- package/dist/cli/commands/diagnose.d.ts.map +0 -1
- package/dist/cli/commands/diagnose.js +0 -195
- package/dist/cli/commands/diagnose.js.map +0 -1
- package/dist/cli/commands/propose.d.ts +0 -18
- package/dist/cli/commands/propose.d.ts.map +0 -1
- package/dist/cli/commands/propose.js +0 -331
- package/dist/cli/commands/propose.js.map +0 -1
- package/dist/cli/commands/traces.d.ts +0 -15
- package/dist/cli/commands/traces.d.ts.map +0 -1
- package/dist/cli/commands/traces.js +0 -167
- package/dist/cli/commands/traces.js.map +0 -1
- package/dist/constraints/definitions.d.ts +0 -39
- package/dist/constraints/definitions.d.ts.map +0 -1
- package/dist/constraints/definitions.js +0 -71
- package/dist/constraints/definitions.js.map +0 -1
- package/dist/constraints/quality.d.ts +0 -11
- package/dist/constraints/quality.d.ts.map +0 -1
- package/dist/constraints/quality.js +0 -257
- package/dist/constraints/quality.js.map +0 -1
- package/dist/constraints/safety.d.ts +0 -13
- package/dist/constraints/safety.d.ts.map +0 -1
- package/dist/constraints/safety.js +0 -103
- package/dist/constraints/safety.js.map +0 -1
- package/dist/extensions/long-running/constraints.d.ts +0 -38
- package/dist/extensions/long-running/constraints.d.ts.map +0 -1
- package/dist/extensions/long-running/constraints.js +0 -153
- package/dist/extensions/long-running/constraints.js.map +0 -1
- package/dist/extensions/long-running/index.d.ts +0 -30
- package/dist/extensions/long-running/index.d.ts.map +0 -1
- package/dist/extensions/long-running/index.js +0 -50
- package/dist/extensions/long-running/index.js.map +0 -1
- package/dist/extensions/long-running/types.d.ts +0 -154
- package/dist/extensions/long-running/types.d.ts.map +0 -1
- package/dist/extensions/long-running/types.js +0 -9
- package/dist/extensions/long-running/types.js.map +0 -1
- package/dist/presets/long-running.d.ts +0 -33
- package/dist/presets/long-running.d.ts.map +0 -1
- package/dist/presets/long-running.js +0 -52
- package/dist/presets/long-running.js.map +0 -1
package/src/knowledge/query.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
QueryFilter,
|
|
17
17
|
IndexEntry,
|
|
18
18
|
} from './types';
|
|
19
|
-
import { KnowledgeStore } from './store';
|
|
19
|
+
import type { KnowledgeStore } from './store';
|
|
20
20
|
import { KnowledgeLifecycle } from './lifecycle';
|
|
21
21
|
|
|
22
22
|
// ── Constants ──────────────────────────────────────────────
|
package/src/knowledge/store.ts
CHANGED
|
@@ -22,7 +22,30 @@ const DEFAULT_CONFIG: StoreConfig = {
|
|
|
22
22
|
baseDir: DEFAULT_DIR,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* KnowledgeStore interface — abstract contract for knowledge storage.
|
|
27
|
+
*/
|
|
28
|
+
export interface KnowledgeStore {
|
|
29
|
+
getBaseDir(): string;
|
|
30
|
+
get(id: string): KnowledgeEntry | undefined;
|
|
31
|
+
list(filter?: QueryFilter): KnowledgeEntry[];
|
|
32
|
+
save(entry: KnowledgeEntry): void;
|
|
33
|
+
delete(id: string): boolean;
|
|
34
|
+
update(id: string, partial: Partial<KnowledgeEntry>): KnowledgeEntry | undefined;
|
|
35
|
+
rebuildIndex(): void;
|
|
36
|
+
readIndex(): IndexEntry[];
|
|
37
|
+
readEntriesFromDisk(): KnowledgeEntry[];
|
|
38
|
+
snapshot(): string;
|
|
39
|
+
getSnapshot(date: string): IndexEntry[] | undefined;
|
|
40
|
+
getSurvivalRate(daysAgo: number): { rate: number; survived: number; total: number; snapshotDate: string } | undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* FileKnowledgeStore — file-based implementation of KnowledgeStore.
|
|
45
|
+
* Each entry is a markdown file with YAML frontmatter.
|
|
46
|
+
* An index.json provides fast listing without reading all files.
|
|
47
|
+
*/
|
|
48
|
+
export class FileKnowledgeStore implements KnowledgeStore {
|
|
26
49
|
private baseDir: string;
|
|
27
50
|
|
|
28
51
|
constructor(config?: Partial<StoreConfig>) {
|
|
@@ -269,7 +292,7 @@ export class KnowledgeStore {
|
|
|
269
292
|
* 保存当日 index.json 快照
|
|
270
293
|
*/
|
|
271
294
|
snapshot(): string {
|
|
272
|
-
const snapDir = path.join(this.baseDir,
|
|
295
|
+
const snapDir = path.join(this.baseDir, FileKnowledgeStore.SNAPSHOTS_DIR);
|
|
273
296
|
if (!fs.existsSync(snapDir)) {
|
|
274
297
|
fs.mkdirSync(snapDir, { recursive: true });
|
|
275
298
|
}
|
|
@@ -286,7 +309,7 @@ export class KnowledgeStore {
|
|
|
286
309
|
* 读取指定日期的快照
|
|
287
310
|
*/
|
|
288
311
|
getSnapshot(date: string): IndexEntry[] | undefined {
|
|
289
|
-
const snapPath = path.join(this.baseDir,
|
|
312
|
+
const snapPath = path.join(this.baseDir, FileKnowledgeStore.SNAPSHOTS_DIR, `index-${date}.json`);
|
|
290
313
|
if (!fs.existsSync(snapPath)) return undefined;
|
|
291
314
|
try {
|
|
292
315
|
return JSON.parse(fs.readFileSync(snapPath, 'utf-8')) as IndexEntry[];
|
|
@@ -323,7 +346,7 @@ export class KnowledgeStore {
|
|
|
323
346
|
|
|
324
347
|
// ── Index I/O ────────────────────────────────────────────
|
|
325
348
|
|
|
326
|
-
|
|
349
|
+
readIndex(): IndexEntry[] {
|
|
327
350
|
const indexPath = path.join(this.baseDir, INDEX_FILE);
|
|
328
351
|
if (!fs.existsSync(indexPath)) return [];
|
|
329
352
|
try {
|
package/src/knowledge/types.ts
CHANGED
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
// ── Dimensions ──────────────────────────────────────────────
|
|
11
11
|
|
|
12
|
-
export type
|
|
12
|
+
export type KnowledgeSubsystem = 'model' | 'decision' | 'guideline' | 'pitfall' | 'process' | 'architecture';
|
|
13
|
+
|
|
14
|
+
/** @deprecated Use KnowledgeSubsystem */
|
|
15
|
+
export type KnowledgeType = KnowledgeSubsystem;
|
|
13
16
|
|
|
14
17
|
export type MaturityLevel = 'draft' | 'verified' | 'proven' | 'archived' | 'active' | 'deprecated';
|
|
15
18
|
|
|
@@ -146,6 +149,23 @@ export const DEFAULT_DECAY_CONFIG: DecayConfig = {
|
|
|
146
149
|
autoPromoteSources: [],
|
|
147
150
|
};
|
|
148
151
|
|
|
152
|
+
// ── Decision ────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
export interface DecisionRecord {
|
|
155
|
+
topic: string;
|
|
156
|
+
category: 'architecture' | 'tooling' | 'process' | 'design';
|
|
157
|
+
context: string;
|
|
158
|
+
decision: string;
|
|
159
|
+
alternatives: string[];
|
|
160
|
+
rationale: string;
|
|
161
|
+
consequences: string;
|
|
162
|
+
participants: string[];
|
|
163
|
+
sourceType: string;
|
|
164
|
+
sourceId?: string;
|
|
165
|
+
revisable: boolean;
|
|
166
|
+
revisitCondition?: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
149
169
|
// ── Reference ───────────────────────────────────────────────
|
|
150
170
|
|
|
151
171
|
export interface ReferenceRecord {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import type { KnowledgeEntry, MaturityLevel } from '../knowledge/types';
|
|
11
11
|
import type { KnowledgeDiagnosis } from './knowledge-doctor';
|
|
12
|
-
import { KnowledgeStore } from '../knowledge/store';
|
|
12
|
+
import type { KnowledgeStore } from '../knowledge/store';
|
|
13
13
|
|
|
14
14
|
// ── 进化提案 ─────────────────────────────────────────────
|
|
15
15
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// SDD Index Generator Tests (AC-9)
|
|
2
|
+
// Tests: scan docs/sdd/ subdirs with requirement.md → generate _index.md
|
|
3
|
+
// Format: slug|pmoNumber|status|title|tags
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
|
|
8
|
+
// Import will fail until implementation exists — this is intentional RED
|
|
9
|
+
import { SDDIndexGenerator } from '../index-generator';
|
|
10
|
+
|
|
11
|
+
describe('SDDIndexGenerator', () => {
|
|
12
|
+
let tmpDir: string;
|
|
13
|
+
let sddDir: string;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sdd-index-test-'));
|
|
17
|
+
sddDir = path.join(tmpDir, 'docs', 'sdd');
|
|
18
|
+
fs.mkdirSync(sddDir, { recursive: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function createSDD(slug: string, frontmatter: Record<string, unknown>): void {
|
|
26
|
+
const dir = path.join(sddDir, slug);
|
|
27
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
28
|
+
const lines = ['---'];
|
|
29
|
+
for (const [key, value] of Object.entries(frontmatter)) {
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
lines.push(`${key}: [${value.map(v => `"${v}"`).join(', ')}]`);
|
|
32
|
+
} else {
|
|
33
|
+
lines.push(`${key}: "${value}"`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lines.push('---');
|
|
37
|
+
lines.push('');
|
|
38
|
+
lines.push(`# ${frontmatter.title || slug}`);
|
|
39
|
+
fs.writeFileSync(path.join(dir, 'requirement.md'), lines.join('\n'));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
it('generates index from SDD directories with requirement.md', () => {
|
|
43
|
+
createSDD('jwt-auth', {
|
|
44
|
+
slug: 'jwt-auth',
|
|
45
|
+
status: 'done',
|
|
46
|
+
title: 'JWT 认证系统',
|
|
47
|
+
tags: ['auth', 'security'],
|
|
48
|
+
pmoNumber: 'PM-001',
|
|
49
|
+
});
|
|
50
|
+
createSDD('user-management', {
|
|
51
|
+
slug: 'user-management',
|
|
52
|
+
status: 'confirmed',
|
|
53
|
+
title: '用户管理',
|
|
54
|
+
tags: ['user'],
|
|
55
|
+
pmoNumber: 'PM-002',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
59
|
+
const result = generator.regenerate();
|
|
60
|
+
|
|
61
|
+
expect(result.count).toBe(2);
|
|
62
|
+
expect(result.entries).toHaveLength(2);
|
|
63
|
+
|
|
64
|
+
// Verify _index.md was written
|
|
65
|
+
const indexPath = path.join(sddDir, '_index.md');
|
|
66
|
+
expect(fs.existsSync(indexPath)).toBe(true);
|
|
67
|
+
|
|
68
|
+
const content = fs.readFileSync(indexPath, 'utf-8');
|
|
69
|
+
expect(content).toContain('jwt-auth|PM-001|done|JWT 认证系统|auth,security');
|
|
70
|
+
expect(content).toContain('user-management|PM-002|confirmed|用户管理|user');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('skips directories without requirement.md', () => {
|
|
74
|
+
createSDD('has-req', { slug: 'has-req', status: 'done', title: 'Has Req' });
|
|
75
|
+
// Create directory without requirement.md
|
|
76
|
+
fs.mkdirSync(path.join(sddDir, 'no-req'), { recursive: true });
|
|
77
|
+
|
|
78
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
79
|
+
const result = generator.regenerate();
|
|
80
|
+
|
|
81
|
+
expect(result.count).toBe(1);
|
|
82
|
+
expect(result.entries[0].slug).toBe('has-req');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('skips status: stale SDDs', () => {
|
|
86
|
+
createSDD('active-one', { slug: 'active-one', status: 'done', title: 'Active' });
|
|
87
|
+
createSDD('stale-one', { slug: 'stale-one', status: 'stale', title: 'Stale' });
|
|
88
|
+
|
|
89
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
90
|
+
const result = generator.regenerate();
|
|
91
|
+
|
|
92
|
+
expect(result.count).toBe(1);
|
|
93
|
+
expect(result.entries[0].slug).toBe('active-one');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('handles missing pmoNumber (empty column)', () => {
|
|
97
|
+
createSDD('no-pmo', { slug: 'no-pmo', status: 'done', title: 'No PMO' });
|
|
98
|
+
|
|
99
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
100
|
+
const result = generator.regenerate();
|
|
101
|
+
|
|
102
|
+
expect(result.count).toBe(1);
|
|
103
|
+
// pmoNumber column should be empty: slug||status|title|tags
|
|
104
|
+
expect(result.entries[0].pmoNumber).toBe('');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('handles missing tags (empty column)', () => {
|
|
108
|
+
createSDD('no-tags', { slug: 'no-tags', status: 'done', title: 'No Tags' });
|
|
109
|
+
|
|
110
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
111
|
+
const result = generator.regenerate();
|
|
112
|
+
|
|
113
|
+
expect(result.count).toBe(1);
|
|
114
|
+
expect(result.entries[0].tags).toBe('');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('throws when SDD directory does not exist', () => {
|
|
118
|
+
const emptyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sdd-empty-'));
|
|
119
|
+
|
|
120
|
+
expect(() => new SDDIndexGenerator(emptyDir).regenerate()).toThrow(/not found/);
|
|
121
|
+
|
|
122
|
+
fs.rmSync(emptyDir, { recursive: true, force: true });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('generates header with correct format', () => {
|
|
126
|
+
createSDD('test', { slug: 'test', status: 'done', title: 'Test' });
|
|
127
|
+
|
|
128
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
129
|
+
generator.regenerate();
|
|
130
|
+
|
|
131
|
+
const indexPath = path.join(sddDir, '_index.md');
|
|
132
|
+
const content = fs.readFileSync(indexPath, 'utf-8');
|
|
133
|
+
|
|
134
|
+
expect(content).toContain('# SDD Index');
|
|
135
|
+
expect(content).toContain('Auto-generated');
|
|
136
|
+
expect(content).toContain('Total: 1 entries');
|
|
137
|
+
expect(content).toContain('slug|pmoNumber|status|title|tags');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('sorts entries by slug', () => {
|
|
141
|
+
createSDD('zebra', { slug: 'zebra', status: 'done', title: 'Zebra' });
|
|
142
|
+
createSDD('alpha', { slug: 'alpha', status: 'done', title: 'Alpha' });
|
|
143
|
+
|
|
144
|
+
const generator = new SDDIndexGenerator(tmpDir);
|
|
145
|
+
const result = generator.regenerate();
|
|
146
|
+
|
|
147
|
+
expect(result.entries[0].slug).toBe('alpha');
|
|
148
|
+
expect(result.entries[1].slug).toBe('zebra');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// SDD Index Generator
|
|
2
|
+
// Scans docs/sdd/*/requirement.md, generates docs/sdd/_index.md
|
|
3
|
+
// Format: slug|pmoNumber|status|title|tags
|
|
4
|
+
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as yaml from 'js-yaml';
|
|
8
|
+
|
|
9
|
+
const INDEX_FILENAME = '_index.md';
|
|
10
|
+
|
|
11
|
+
interface SDDIndexEntry {
|
|
12
|
+
slug: string;
|
|
13
|
+
pmoNumber: string;
|
|
14
|
+
status: string;
|
|
15
|
+
title: string;
|
|
16
|
+
tags: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SDDIndexResult {
|
|
20
|
+
count: number;
|
|
21
|
+
entries: SDDIndexEntry[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class SDDIndexGenerator {
|
|
25
|
+
private sddDir: string;
|
|
26
|
+
|
|
27
|
+
constructor(baseDir: string) {
|
|
28
|
+
this.sddDir = path.join(baseDir, 'docs', 'sdd');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
regenerate(): SDDIndexResult {
|
|
32
|
+
if (!fs.existsSync(this.sddDir)) {
|
|
33
|
+
throw new Error(`SDD directory not found: ${this.sddDir}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const entries = this.scanEntries();
|
|
37
|
+
entries.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
38
|
+
|
|
39
|
+
const content = this.buildContent(entries);
|
|
40
|
+
const indexPath = path.join(this.sddDir, INDEX_FILENAME);
|
|
41
|
+
fs.writeFileSync(indexPath, content, 'utf-8');
|
|
42
|
+
|
|
43
|
+
return { count: entries.length, entries };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private scanEntries(): SDDIndexEntry[] {
|
|
47
|
+
const entries: SDDIndexEntry[] = [];
|
|
48
|
+
const dirs = fs.readdirSync(this.sddDir, { withFileTypes: true })
|
|
49
|
+
.filter(d => d.isDirectory())
|
|
50
|
+
.map(d => d.name);
|
|
51
|
+
|
|
52
|
+
for (const dir of dirs) {
|
|
53
|
+
const reqPath = path.join(this.sddDir, dir, 'requirement.md');
|
|
54
|
+
if (!fs.existsSync(reqPath)) continue;
|
|
55
|
+
|
|
56
|
+
const content = fs.readFileSync(reqPath, 'utf-8');
|
|
57
|
+
const fm = this.parseFrontmatter(content);
|
|
58
|
+
if (!fm) continue;
|
|
59
|
+
|
|
60
|
+
// Skip stale SDDs
|
|
61
|
+
const status = String(fm.status || 'unknown');
|
|
62
|
+
if (status === 'stale') continue;
|
|
63
|
+
|
|
64
|
+
entries.push({
|
|
65
|
+
slug: String(fm.slug || dir),
|
|
66
|
+
pmoNumber: String(fm.pmoNumber || ''),
|
|
67
|
+
status,
|
|
68
|
+
title: this.sanitize(String(fm.title || dir)),
|
|
69
|
+
tags: Array.isArray(fm.tags) ? fm.tags.join(',') : '',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return entries;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private parseFrontmatter(content: string): Record<string, unknown> | null {
|
|
77
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
78
|
+
if (!match) return null;
|
|
79
|
+
try {
|
|
80
|
+
return yaml.load(match[1]) as Record<string, unknown> || null;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private sanitize(s: string): string {
|
|
87
|
+
return s.replace(/\n/g, ' ').replace(/\|/g, '/').replace(/\s+/g, ' ').trim();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private buildContent(entries: SDDIndexEntry[]): string {
|
|
91
|
+
const header = [
|
|
92
|
+
'# SDD Index',
|
|
93
|
+
'# Auto-generated — run `harness sdd index` to rebuild',
|
|
94
|
+
`# Total: ${entries.length} entries`,
|
|
95
|
+
'#',
|
|
96
|
+
'# Usage:',
|
|
97
|
+
'# grep "<pmoNumber>" docs/sdd/_index.md',
|
|
98
|
+
'# Then Read the matching SDD directory for full content.',
|
|
99
|
+
'#',
|
|
100
|
+
'# slug|pmoNumber|status|title|tags',
|
|
101
|
+
].join('\n');
|
|
102
|
+
|
|
103
|
+
const lines = entries.map(e =>
|
|
104
|
+
`${e.slug}|${e.pmoNumber}|${e.status}|${e.title}|${e.tags}`
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return header + '\n' + lines.join('\n') + '\n';
|
|
108
|
+
}
|
|
109
|
+
}
|
package/src/types/constraint.ts
CHANGED
|
@@ -220,7 +220,7 @@ export interface ConstraintContext {
|
|
|
220
220
|
/** 是否有需求文档(用于 no_implementation_without_requirement) */
|
|
221
221
|
hasRequirement?: boolean;
|
|
222
222
|
|
|
223
|
-
/** 是否在 worktree 中执行(用于
|
|
223
|
+
/** 是否在 worktree 中执行(用于 prefer_worktree) */
|
|
224
224
|
hasWorktree?: boolean;
|
|
225
225
|
|
|
226
226
|
/** worktree 路径(用于 worktree 相关检查) */
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Diagnose CLI 命令
|
|
3
|
-
*
|
|
4
|
-
* 运行诊断分析异常
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* diagnose 命令
|
|
8
|
-
*/
|
|
9
|
-
export declare function diagnoseCommand(subcommand: string, options: {
|
|
10
|
-
hours?: number;
|
|
11
|
-
constraintId?: string;
|
|
12
|
-
anomalyId?: string;
|
|
13
|
-
format?: 'json' | 'text';
|
|
14
|
-
save?: boolean;
|
|
15
|
-
}): Promise<void>;
|
|
16
|
-
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/diagnose.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CA6Bf"}
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Diagnose CLI 命令
|
|
4
|
-
*
|
|
5
|
-
* 运行诊断分析异常
|
|
6
|
-
*/
|
|
7
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
-
}
|
|
13
|
-
Object.defineProperty(o, k2, desc);
|
|
14
|
-
}) : (function(o, m, k, k2) {
|
|
15
|
-
if (k2 === undefined) k2 = k;
|
|
16
|
-
o[k2] = m[k];
|
|
17
|
-
}));
|
|
18
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
-
}) : function(o, v) {
|
|
21
|
-
o["default"] = v;
|
|
22
|
-
});
|
|
23
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
-
var ownKeys = function(o) {
|
|
25
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
-
var ar = [];
|
|
27
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
-
return ar;
|
|
29
|
-
};
|
|
30
|
-
return ownKeys(o);
|
|
31
|
-
};
|
|
32
|
-
return function (mod) {
|
|
33
|
-
if (mod && mod.__esModule) return mod;
|
|
34
|
-
var result = {};
|
|
35
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
-
__setModuleDefault(result, mod);
|
|
37
|
-
return result;
|
|
38
|
-
};
|
|
39
|
-
})();
|
|
40
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.diagnoseCommand = diagnoseCommand;
|
|
42
|
-
const fs = __importStar(require("fs"));
|
|
43
|
-
const path = __importStar(require("path"));
|
|
44
|
-
const traces_1 = require("../../monitoring/traces");
|
|
45
|
-
const trace_analyzer_1 = require("../../monitoring/trace-analyzer");
|
|
46
|
-
const constraint_doctor_1 = require("../../monitoring/constraint-doctor");
|
|
47
|
-
/**
|
|
48
|
-
* diagnose 命令
|
|
49
|
-
*/
|
|
50
|
-
async function diagnoseCommand(subcommand, options) {
|
|
51
|
-
switch (subcommand) {
|
|
52
|
-
case 'run':
|
|
53
|
-
await runDiagnose(options);
|
|
54
|
-
break;
|
|
55
|
-
case 'show':
|
|
56
|
-
await showDiagnose(options);
|
|
57
|
-
break;
|
|
58
|
-
case 'list':
|
|
59
|
-
await listDiagnoses(options);
|
|
60
|
-
break;
|
|
61
|
-
default:
|
|
62
|
-
console.log('Usage: harness diagnose <subcommand>');
|
|
63
|
-
console.log('');
|
|
64
|
-
console.log('Subcommands:');
|
|
65
|
-
console.log(' run Run diagnosis on detected anomalies');
|
|
66
|
-
console.log(' show Show a specific diagnosis result');
|
|
67
|
-
console.log(' list List all diagnosis results');
|
|
68
|
-
console.log('');
|
|
69
|
-
console.log('Options:');
|
|
70
|
-
console.log(' --hours <n> Analyze last N hours (default: 24)');
|
|
71
|
-
console.log(' --constraint <id> Filter by constraint ID');
|
|
72
|
-
console.log(' --anomaly <id> Show specific anomaly diagnosis');
|
|
73
|
-
console.log(' --format <format> Output format: json or text (default: text)');
|
|
74
|
-
console.log(' --save Save diagnosis to file');
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* 运行诊断
|
|
79
|
-
*/
|
|
80
|
-
async function runDiagnose(options) {
|
|
81
|
-
const hours = options.hours || 24;
|
|
82
|
-
const analyzer = (0, trace_analyzer_1.createAnalyzer)();
|
|
83
|
-
const doctor = (0, constraint_doctor_1.createDoctor)();
|
|
84
|
-
// 1. 检测异常
|
|
85
|
-
const anomalies = analyzer.runDailyAnomalyCheck();
|
|
86
|
-
// 过滤特定约束
|
|
87
|
-
let filteredAnomalies = anomalies;
|
|
88
|
-
if (options.constraintId) {
|
|
89
|
-
filteredAnomalies = anomalies.filter(a => a.constraintId === options.constraintId);
|
|
90
|
-
}
|
|
91
|
-
if (filteredAnomalies.length === 0) {
|
|
92
|
-
console.log('✅ No anomalies detected. No diagnosis needed.');
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
console.log(`🔍 Detected ${filteredAnomalies.length} anomalies, running diagnosis...`);
|
|
96
|
-
console.log('');
|
|
97
|
-
// 2. 获取 traces
|
|
98
|
-
const collector = (0, traces_1.getTraceCollector)();
|
|
99
|
-
const traces = collector.readRecent(hours);
|
|
100
|
-
// 3. 运行诊断
|
|
101
|
-
const diagnoses = [];
|
|
102
|
-
for (const anomaly of filteredAnomalies) {
|
|
103
|
-
doctor.setData(traces.filter(t => t.constraintId === anomaly.constraintId));
|
|
104
|
-
const diagnosis = await doctor.diagnose(anomaly);
|
|
105
|
-
diagnoses.push(diagnosis);
|
|
106
|
-
// 保存诊断
|
|
107
|
-
if (options.save) {
|
|
108
|
-
const outputPath = `.harness/diagnoses/${diagnosis.anomalyId}.json`;
|
|
109
|
-
doctor.saveDiagnosis(diagnosis, outputPath);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// 4. 输出结果
|
|
113
|
-
if (options.format === 'json') {
|
|
114
|
-
console.log(JSON.stringify(diagnoses, null, 2));
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
for (const diagnosis of diagnoses) {
|
|
118
|
-
console.log(doctor.generateReport(diagnosis));
|
|
119
|
-
console.log('---');
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// 5. 统计
|
|
123
|
-
const needsChange = diagnoses.filter(d => d.needsChange).length;
|
|
124
|
-
console.log('');
|
|
125
|
-
console.log(`📊 Summary: ${needsChange} diagnoses need constraint changes`);
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* 显示特定诊断
|
|
129
|
-
*/
|
|
130
|
-
async function showDiagnose(options) {
|
|
131
|
-
if (!options.anomalyId) {
|
|
132
|
-
console.log('❌ Please specify --anomaly <id>');
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
const doctor = (0, constraint_doctor_1.createDoctor)();
|
|
136
|
-
const diagnosisPath = `.harness/diagnoses/${options.anomalyId}.json`;
|
|
137
|
-
if (!fs.existsSync(diagnosisPath)) {
|
|
138
|
-
console.log(`❌ Diagnosis not found: ${options.anomalyId}`);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const diagnosis = doctor.loadDiagnosis(diagnosisPath);
|
|
142
|
-
if (options.format === 'json') {
|
|
143
|
-
console.log(JSON.stringify(diagnosis, null, 2));
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
console.log(doctor.generateReport(diagnosis));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* 列出所有诊断
|
|
151
|
-
*/
|
|
152
|
-
async function listDiagnoses(options) {
|
|
153
|
-
const diagnosesDir = '.harness/diagnoses';
|
|
154
|
-
if (!fs.existsSync(diagnosesDir)) {
|
|
155
|
-
console.log('❌ No diagnoses found. Run `harness diagnose run` first.');
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const files = fs.readdirSync(diagnosesDir)
|
|
159
|
-
.filter(f => f.endsWith('.json'));
|
|
160
|
-
if (files.length === 0) {
|
|
161
|
-
console.log('❌ No diagnoses found.');
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const doctor = (0, constraint_doctor_1.createDoctor)();
|
|
165
|
-
const diagnoses = files.map(f => {
|
|
166
|
-
const content = fs.readFileSync(path.join(diagnosesDir, f), 'utf-8');
|
|
167
|
-
return JSON.parse(content);
|
|
168
|
-
});
|
|
169
|
-
if (options.format === 'json') {
|
|
170
|
-
console.log(JSON.stringify(diagnoses.map(d => ({
|
|
171
|
-
anomalyId: d.anomalyId,
|
|
172
|
-
constraintId: d.constraintId,
|
|
173
|
-
needsChange: d.needsChange,
|
|
174
|
-
urgency: d.urgency,
|
|
175
|
-
})), null, 2));
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
console.log('📋 Diagnosis List');
|
|
179
|
-
console.log('');
|
|
180
|
-
for (const diagnosis of diagnoses) {
|
|
181
|
-
const urgencyEmoji = {
|
|
182
|
-
low: '🟢',
|
|
183
|
-
medium: '🟡',
|
|
184
|
-
high: '🔴',
|
|
185
|
-
}[diagnosis.urgency] || '⚪';
|
|
186
|
-
console.log(`${urgencyEmoji} ${diagnosis.anomalyId}`);
|
|
187
|
-
console.log(` Constraint: ${diagnosis.constraintId}`);
|
|
188
|
-
console.log(` Needs Change: ${diagnosis.needsChange ? 'Yes' : 'No'}`);
|
|
189
|
-
console.log(` Urgency: ${diagnosis.urgency}`);
|
|
190
|
-
console.log('');
|
|
191
|
-
}
|
|
192
|
-
console.log(`Total: ${diagnoses.length} diagnoses`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
//# sourceMappingURL=diagnose.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../../src/cli/commands/diagnose.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Propose CLI 命令
|
|
3
|
-
*
|
|
4
|
-
* 根据诊断生成约束提案
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* propose 命令
|
|
8
|
-
*/
|
|
9
|
-
export declare function proposeCommand(subcommand: string, options: {
|
|
10
|
-
diagnosisId?: string;
|
|
11
|
-
format?: 'json' | 'text';
|
|
12
|
-
save?: boolean;
|
|
13
|
-
status?: 'proposed' | 'accepted' | 'rejected';
|
|
14
|
-
accept?: boolean;
|
|
15
|
-
reject?: boolean;
|
|
16
|
-
comment?: string;
|
|
17
|
-
}): Promise<void>;
|
|
18
|
-
//# sourceMappingURL=propose.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"propose.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/propose.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,OAAO,CAAC,IAAI,CAAC,CAyCf"}
|