@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.
Files changed (117) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/bin/harness-knowledge-check.js +38 -23
  3. package/bin/harness-knowledge-track.js +30 -4
  4. package/bin/harness.js +24 -1
  5. package/dist/cli/commands/index.d.ts +1 -1
  6. package/dist/cli/commands/index.d.ts.map +1 -1
  7. package/dist/cli/commands/index.js +4 -1
  8. package/dist/cli/commands/index.js.map +1 -1
  9. package/dist/cli/commands/knowledge.d.ts +21 -0
  10. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  11. package/dist/cli/commands/knowledge.js +160 -9
  12. package/dist/cli/commands/knowledge.js.map +1 -1
  13. package/dist/cli/commands/release.d.ts.map +1 -1
  14. package/dist/cli/commands/release.js +43 -6
  15. package/dist/cli/commands/release.js.map +1 -1
  16. package/dist/core/constraints/checker.js +1 -1
  17. package/dist/core/constraints/checker.js.map +1 -1
  18. package/dist/core/constraints/definitions.d.ts.map +1 -1
  19. package/dist/core/constraints/definitions.js +34 -26
  20. package/dist/core/constraints/definitions.js.map +1 -1
  21. package/dist/index.d.ts +3 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +6 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/knowledge/audit.d.ts +76 -0
  26. package/dist/knowledge/audit.d.ts.map +1 -0
  27. package/dist/knowledge/audit.js +566 -0
  28. package/dist/knowledge/audit.js.map +1 -0
  29. package/dist/knowledge/doctor.d.ts +1 -1
  30. package/dist/knowledge/doctor.d.ts.map +1 -1
  31. package/dist/knowledge/import.d.ts +1 -1
  32. package/dist/knowledge/import.d.ts.map +1 -1
  33. package/dist/knowledge/import.js +3 -0
  34. package/dist/knowledge/import.js.map +1 -1
  35. package/dist/knowledge/index.d.ts +7 -2
  36. package/dist/knowledge/index.d.ts.map +1 -1
  37. package/dist/knowledge/index.js +7 -2
  38. package/dist/knowledge/index.js.map +1 -1
  39. package/dist/knowledge/ingest.d.ts +28 -1
  40. package/dist/knowledge/ingest.d.ts.map +1 -1
  41. package/dist/knowledge/ingest.js +150 -5
  42. package/dist/knowledge/ingest.js.map +1 -1
  43. package/dist/knowledge/lifecycle-hooks.d.ts +1 -1
  44. package/dist/knowledge/lifecycle-hooks.d.ts.map +1 -1
  45. package/dist/knowledge/lifecycle-hooks.js +3 -0
  46. package/dist/knowledge/lifecycle-hooks.js.map +1 -1
  47. package/dist/knowledge/lifecycle.d.ts +60 -8
  48. package/dist/knowledge/lifecycle.d.ts.map +1 -1
  49. package/dist/knowledge/lifecycle.js +213 -52
  50. package/dist/knowledge/lifecycle.js.map +1 -1
  51. package/dist/knowledge/lint.d.ts +1 -1
  52. package/dist/knowledge/lint.d.ts.map +1 -1
  53. package/dist/knowledge/lint.js +44 -3
  54. package/dist/knowledge/lint.js.map +1 -1
  55. package/dist/knowledge/migration.d.ts +25 -0
  56. package/dist/knowledge/migration.d.ts.map +1 -0
  57. package/dist/knowledge/migration.js +96 -0
  58. package/dist/knowledge/migration.js.map +1 -0
  59. package/dist/knowledge/query.d.ts +30 -2
  60. package/dist/knowledge/query.d.ts.map +1 -1
  61. package/dist/knowledge/query.js +58 -0
  62. package/dist/knowledge/query.js.map +1 -1
  63. package/dist/knowledge/reference-tracker.d.ts +1 -1
  64. package/dist/knowledge/reference-tracker.d.ts.map +1 -1
  65. package/dist/knowledge/store.d.ts +50 -3
  66. package/dist/knowledge/store.d.ts.map +1 -1
  67. package/dist/knowledge/store.js +111 -9
  68. package/dist/knowledge/store.js.map +1 -1
  69. package/dist/knowledge/types.d.ts +43 -1
  70. package/dist/knowledge/types.d.ts.map +1 -1
  71. package/dist/knowledge/types.js +1 -0
  72. package/dist/knowledge/types.js.map +1 -1
  73. package/dist/monitoring/knowledge-evolver.d.ts +1 -1
  74. package/dist/monitoring/knowledge-evolver.d.ts.map +1 -1
  75. package/dist/types/constraint.d.ts +1 -1
  76. package/dist/types/constraint.d.ts.map +1 -1
  77. package/package.json +1 -1
  78. package/src/__tests__/checker.test.ts +4 -4
  79. package/src/cli/commands/__tests__/knowledge.test.ts +167 -0
  80. package/src/cli/commands/index.ts +1 -1
  81. package/src/cli/commands/knowledge.ts +176 -5
  82. package/src/cli/commands/release.ts +44 -6
  83. package/src/context/__tests__/knowledge-injector.test.ts +4 -1
  84. package/src/core/constraints/checker.ts +1 -1
  85. package/src/core/constraints/definitions.ts +35 -27
  86. package/src/dashboard/__tests__/data.test.ts +3 -0
  87. package/src/dashboard/__tests__/stats.test.ts +3 -0
  88. package/src/index.ts +3 -1
  89. package/src/knowledge/CONTEXT.md +29 -7
  90. package/src/knowledge/__tests__/audit.test.ts +598 -0
  91. package/src/knowledge/__tests__/doctor.test.ts +28 -1
  92. package/src/knowledge/__tests__/import.test.ts +1 -1
  93. package/src/knowledge/__tests__/ingest.test.ts +320 -1
  94. package/src/knowledge/__tests__/lifecycle-hooks.test.ts +4 -1
  95. package/src/knowledge/__tests__/lifecycle.test.ts +656 -3
  96. package/src/knowledge/__tests__/lint.test.ts +52 -1
  97. package/src/knowledge/__tests__/migration.test.ts +115 -0
  98. package/src/knowledge/__tests__/query.test.ts +87 -1
  99. package/src/knowledge/__tests__/reference-tracker.test.ts +4 -1
  100. package/src/knowledge/__tests__/store.test.ts +208 -1
  101. package/src/knowledge/audit.ts +641 -0
  102. package/src/knowledge/doctor.ts +1 -1
  103. package/src/knowledge/import.ts +4 -1
  104. package/src/knowledge/index.ts +7 -2
  105. package/src/knowledge/ingest.ts +170 -6
  106. package/src/knowledge/lifecycle-hooks.ts +4 -1
  107. package/src/knowledge/lifecycle.ts +219 -50
  108. package/src/knowledge/lint.ts +45 -4
  109. package/src/knowledge/migration.ts +73 -0
  110. package/src/knowledge/query.ts +72 -1
  111. package/src/knowledge/reference-tracker.ts +1 -1
  112. package/src/knowledge/store.ts +125 -8
  113. package/src/knowledge/types.ts +50 -1
  114. package/src/monitoring/__tests__/knowledge-doctor.test.ts +3 -0
  115. package/src/monitoring/__tests__/knowledge-evolver.test.ts +3 -0
  116. package/src/monitoring/knowledge-evolver.ts +1 -1
  117. package/src/types/constraint.ts +1 -1
@@ -44,7 +44,26 @@ export async function release(options: ReleaseOptions): Promise<void> {
44
44
  console.log(chalk.cyan(`📦 ${pkgName}@${oldVersion}`));
45
45
  console.log(chalk.cyan(` bump: ${bumpType}${dryRun ? ' (dry-run)' : ''}`));
46
46
 
47
- // ── 2. Check clean working tree ──
47
+ // ── 2. Check branch (must be on master/main) ──
48
+ const branchResult = await run('git rev-parse --abbrev-ref HEAD', pkgPath);
49
+ const currentBranch = branchResult.stdout.trim();
50
+ if (currentBranch !== 'master' && currentBranch !== 'main') {
51
+ console.error(chalk.red(`❌ Must be on master or main branch to release. Currently on: ${currentBranch}`));
52
+ console.error(chalk.gray(' Run: git checkout master && git merge ' + currentBranch));
53
+ process.exit(1);
54
+ }
55
+ console.log(chalk.green(`✅ git: on ${currentBranch}`));
56
+
57
+ // ── 2b. Check remote sync ──
58
+ await run('git fetch origin', pkgPath, 15_000);
59
+ const behind = await run(`git rev-list --count HEAD..origin/${currentBranch}`, pkgPath);
60
+ if (behind.stdout.trim() !== '0') {
61
+ console.error(chalk.red(`❌ Local ${currentBranch} is ${behind.stdout.trim()} commits behind origin/${currentBranch}. Pull first.`));
62
+ process.exit(1);
63
+ }
64
+ console.log(chalk.green('✅ git: synced with remote'));
65
+
66
+ // ── 2c. Check clean working tree ──
48
67
  const stat = await run('git status --porcelain -uno', pkgPath);
49
68
  if (stat.stdout.length > 0) {
50
69
  console.error(chalk.red('❌ Uncommitted changes. Commit or stash before releasing.'));
@@ -98,6 +117,18 @@ export async function release(options: ReleaseOptions): Promise<void> {
98
117
  // ── 5. Bump version (npm version creates git commit + tag atomically,
99
118
  // including package-lock.json — no desync possible) ──
100
119
  console.log(chalk.cyan('🔢 Bumping version...'));
120
+ const [major, minor, patch] = oldVersion.split('.').map(Number);
121
+ let expectedNew: string;
122
+ if (bumpType === 'major') expectedNew = `${major + 1}.0.0`;
123
+ else if (bumpType === 'minor') expectedNew = `${major}.${minor + 1}.0`;
124
+ else expectedNew = `${major}.${minor}.${patch + 1}`;
125
+ const expectedTag = `v${expectedNew}`;
126
+ const tagExists = await run(`git tag -l "${expectedTag}"`, pkgPath);
127
+ if (tagExists.stdout.trim() === expectedTag) {
128
+ console.error(chalk.red(`❌ Tag ${expectedTag} already exists. Version may have been released already.`));
129
+ process.exit(1);
130
+ }
131
+
101
132
  const bump = await run(`npm version ${bumpType} -m "release: %s"`, pkgPath);
102
133
  if (bump.stderr && !bump.stdout) {
103
134
  console.error(chalk.red('❌ npm version failed:'), bump.stderr);
@@ -107,10 +138,9 @@ export async function release(options: ReleaseOptions): Promise<void> {
107
138
  const tag = `v${newVersion}`;
108
139
  console.log(chalk.green(`✅ version: ${oldVersion} → ${newVersion} (committed + tagged)`));
109
140
 
110
- // ── 7. Push ──
141
+ // ── 6. Push ──
111
142
  console.log(chalk.cyan('⬆️ Pushing...'));
112
- const branch = await run('git rev-parse --abbrev-ref HEAD', pkgPath);
113
- const push = await run(`git push origin ${branch.stdout}`, pkgPath, 30_000);
143
+ const push = await run(`git push origin ${currentBranch}`, pkgPath, 30_000);
114
144
  if (push.stderr && push.stderr.includes('error')) {
115
145
  console.error(chalk.red('❌ git push failed:'), push.stderr.slice(0, 500));
116
146
  process.exit(1);
@@ -118,7 +148,15 @@ export async function release(options: ReleaseOptions): Promise<void> {
118
148
  await run(`git push origin ${tag}`, pkgPath, 30_000);
119
149
  console.log(chalk.green('✅ git: pushed'));
120
150
 
121
- // ── 8. npm publish ──
151
+ // ── 8. Check private flag ──
152
+ if (pkgJson.private) {
153
+ console.error(chalk.red('❌ package.json has "private": true. Remove it before publishing.'));
154
+ console.error(chalk.gray(' The release tool will NOT auto-remove private flag.'));
155
+ process.exit(1);
156
+ }
157
+ console.log(chalk.green('✅ package: not private'));
158
+
159
+ // ── 7. npm publish ──
122
160
  // Switch to npmjs.org for publishing (npmmirror is read-only mirror)
123
161
  const origRegistry = await run('npm config get registry', pkgPath);
124
162
  await run('npm config set registry https://registry.npmjs.org/', pkgPath);
@@ -136,7 +174,7 @@ export async function release(options: ReleaseOptions): Promise<void> {
136
174
  process.exit(1);
137
175
  }
138
176
 
139
- // ── 9. GitHub Release ──
177
+ // ── 8. GitHub Release ──
140
178
  console.log(chalk.cyan('🐙 Creating GitHub Release...'));
141
179
  const gh = await run(`gh release create ${tag} --generate-notes`, pkgPath, 30_000);
142
180
  if (gh.stderr && gh.stderr.includes('already exists')) {
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { KnowledgeInjector } from '../knowledge-injector';
6
6
  import { KnowledgeQuery } from '../../knowledge/query';
7
- import { KnowledgeStore } from '../../knowledge/store';
7
+ import { FileKnowledgeStore as KnowledgeStore } from '../../knowledge/store';
8
8
  import * as fs from 'fs';
9
9
  import * as path from 'path';
10
10
  import * as os from 'os';
@@ -42,6 +42,9 @@ describe('KnowledgeInjector', () => {
42
42
  applicablePhases: [],
43
43
  sourceReferences: [],
44
44
  referencedBy: [],
45
+ executionResults: [],
46
+ consumptionMode: 'reference',
47
+ origin: 'agent',
45
48
  ...overrides,
46
49
  });
47
50
  }
@@ -256,7 +256,7 @@ export class ConstraintChecker {
256
256
  // 检查是否有需求文档
257
257
  return context.hasRequirement === true;
258
258
 
259
- case 'must_use_worktree':
259
+ case 'prefer_worktree':
260
260
  // 检查是否在 worktree 中执行
261
261
  return context.hasWorktree === true;
262
262
 
@@ -238,31 +238,6 @@ https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agent
238
238
  promptInjection: '开始编写代码前,必须确认:需求来源明确(Spec/Issue/Roadmap/用户指令)、验收标准(AC)已定义、边界情况已明确。不要凭假设或猜测开始实现。',
239
239
  },
240
240
 
241
- /**
242
- * 必须在 worktree 中开发
243
- * 原因:隔离工作区,安全回滚,并行开发
244
- * 来源:Superpowers must_use_worktree
245
- */
246
- must_use_worktree: {
247
- id: 'must_use_worktree',
248
- rule: 'CODE CHANGES MUST BE ISOLATED IN A WORKTREE',
249
- message: '代码开发必须在隔离的 worktree 中进行',
250
- level: 'iron_law',
251
- trigger: ['code_implementation'],
252
- enforcement: 'check-worktree',
253
- description: `所有代码修改必须在隔离的 worktree 中进行,不要在原始仓库目录直接编辑。
254
-
255
- 【原因】
256
- - 隔离风险:worktree 中的改动不会影响主工作区
257
- - 安全回滚:删除 worktree 即可放弃改动
258
- - 并行开发:多个任务可同时在不同 worktree 中进行
259
-
260
- 【禁止】
261
- - 在原始仓库目录直接编辑文件
262
- - 跳过 worktree 创建直接执行 Agent`,
263
- promptInjection: '所有代码修改必须在隔离的 worktree 中进行。不要在原始仓库目录直接编辑文件。worktree 提供了安全回滚和并行开发能力。如果你发现不在 worktree 中,立即停止并要求创建 worktree。',
264
- },
265
-
266
241
  /**
267
242
  * 禁止模糊完成声明
268
243
  * 原因:质量底线,必须有可量化证据
@@ -371,6 +346,37 @@ https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agent
371
346
  // ========================================
372
347
 
373
348
  export const GUIDELINES: Record<string, Constraint> = {
349
+ /**
350
+ * 高风险改动优先使用 worktree
351
+ * 原因:隔离工作区,安全回滚,并行开发
352
+ * 来源:Superpowers prefer_worktree
353
+ */
354
+ prefer_worktree: {
355
+ id: 'prefer_worktree',
356
+ rule: 'USE WORKTREE FOR HIGH-RISK CHANGES',
357
+ message: '高风险改动应在 worktree 中进行',
358
+ level: 'guideline',
359
+ trigger: ['code_implementation'],
360
+ enforcement: 'check-worktree',
361
+ description: `高风险改动应在隔离的 worktree 中进行。
362
+
363
+ 【何时需要 worktree】
364
+ - 新功能开发(新增模块/API)
365
+ - 跨模块改动(>3 文件)
366
+ - 基础设施变更(CI/CD、依赖)
367
+
368
+ 【何时不需要】
369
+ - 配置文件修改
370
+ - 单文件 bug fix
371
+ - 外科手术式修复(typo、missing import)
372
+
373
+ 【原因】
374
+ - 隔离风险:worktree 中的改动不会影响主工作区
375
+ - 安全回滚:删除 worktree 即可放弃改动
376
+ - 并行开发:多个任务可同时在不同 worktree 中进行`,
377
+ promptInjection: '高风险改动(新功能、跨模块、基础设施)应在 worktree 中进行。配置修改、单文件 fix 可直接编辑。',
378
+ },
379
+
374
380
  /**
375
381
  * 禁止无调查修复 bug
376
382
  * 例外:简单 typo、配置错误
@@ -813,8 +819,10 @@ export const GUIDELINES: Record<string, Constraint> = {
813
819
  description: `删除任何代码(包/模块/文件)前,必须:
814
820
  1. 查设计文档(CLAUDE.md / roadmap / specs)
815
821
  2. 分析是否有可吸收的功能
816
- 3. 记录分析结论(有/无吸收价值,原因)`,
817
- promptInjection: '删除任何代码包或模块前,必须先查 CLAUDE.md 和相关设计文档,分析是否有可吸收的功能,并记录分析结论。',
822
+ 3. 查替代函数是否丢失了关键设计模式(零引用≠无价值)
823
+ 4. 分类:未接线(应接线)/ 被替代但有可吸收设计 / 真正无用
824
+ 5. 记录分析结论(有/无吸收价值,原因)`,
825
+ promptInjection: '删除任何代码前,先查设计意图(JSDoc/commit/spec),分析被替代的函数是否有丢失的关键模式。零引用≠无价值。分类:未接线→接线,被替代→吸收模式,真正无用→才删。',
818
826
  },
819
827
 
820
828
  /**
@@ -22,6 +22,9 @@ function makeEntry(overrides: Partial<KnowledgeEntry> = {}): KnowledgeEntry {
22
22
  applicablePhases: [],
23
23
  sourceReferences: [],
24
24
  referencedBy: [],
25
+ executionResults: [],
26
+ consumptionMode: 'reference',
27
+ origin: 'agent',
25
28
  ...overrides,
26
29
  };
27
30
  }
@@ -21,6 +21,9 @@ function makeEntry(overrides: Partial<KnowledgeEntry> = {}): KnowledgeEntry {
21
21
  applicablePhases: [],
22
22
  sourceReferences: [],
23
23
  referencedBy: [],
24
+ executionResults: [],
25
+ consumptionMode: 'reference',
26
+ origin: 'agent',
24
27
  ...overrides,
25
28
  };
26
29
  }
package/src/index.ts CHANGED
@@ -76,7 +76,9 @@ export * from './verification';
76
76
  // ========================================
77
77
  // 约束分层导出
78
78
  // ========================================
79
- export * from './constraints';
79
+ export * from './constraints/types';
80
+ export { ConstraintRegistry } from './constraints/registry';
81
+ export { ConstraintLifecycleRunner } from './constraints/lifecycle-runner';
80
82
 
81
83
  // ========================================
82
84
  // Dashboard 数据导出
@@ -1,29 +1,51 @@
1
1
  # knowledge/
2
2
 
3
3
  ## 职责
4
- 知识引擎:知识存储(CRUD)、语义查询、引用追踪、质量检查(Linter)、生命周期管理、冷启动导入、健康评分。
4
+ 知识引擎:知识存储(CRUD)、语义查询、引用追踪、质量审计(Audit)、质量检查(Linter)、生命周期管理、冷启动导入、健康评分、外部内容摄入。
5
+
6
+ ## 三维分类体系 (AS-021)
7
+ 知识由三个正交维度定义:
8
+ - **Topic** — 开放集,用 `tags: string[]` 描述
9
+ - **ConsumptionMode** — 闭集 (rule/reference/context/signal),驱动注入策略和生命周期
10
+ - **Origin** — 闭集 (human/agent/external/system),影响信任度和 maturity 起点
11
+
12
+ ## 生命周期按模式分化
13
+ - `rule`: draft → active → deprecated (1 次成功激活, 失败率>=50% 降级)
14
+ - `reference`: draft → verified → proven → archived (现有逻辑)
15
+ - `context`: draft → active → archived (1 次引用激活, 3 个月未引用归档)
16
+ - `signal`: active → archived (消费饱和: ref>=3 + 有更新同标签条目)
17
+ - 所有模式支持 `decayAt` 硬过期
5
18
 
6
19
  ## 核心导出
7
20
  - `KnowledgeStore` — 知识条目 CRUD + 结构化存储
8
- - `KnowledgeQuery` — 语义搜索 + 类型/标签过滤
9
- - `KnowledgeLifecycle` — 知识生命周期: draft → candidate → validated → canonical → archived
10
- - `KnowledgeIngest` — 知识摄取引擎
21
+ - `KnowledgeQuery` — 语义搜索 + 类型/标签过滤 + `queryByMode()` + `consume(taskContext)`
22
+ - `KnowledgeLifecycle` — per-mode 生命周期管理
23
+ - `KnowledgeIngest` — 知识摄取引擎(含 ingest gate 质量门)+ `ingestExternal()` 外部内容摄入
24
+ - `sanitizeExternalContent` — 外部内容安全清洗(过滤注入模式 + 长度限制)
25
+ - `migrateKnowledgeEntries` — AS-021 迁移工具(为现有条目添加 consumptionMode/origin)
26
+ - `KnowledgeAudit` — 6 维度质量审计引擎
11
27
  - `ReferenceTracker` — 知识引用关系图谱
12
28
  - `KnowledgeLinter` — 知识质量检查(完整性/一致性/时效性)
13
29
  - `ColdStartImporter` — 冷启动知识导入
14
- - `KnowledgeHealthScorer` — 知识健康评分
30
+ - `KnowledgeHealthScorer` — 知识健康评分(doctor.ts)
15
31
  - `KnowledgeLifecycleHooks` — 生命周期 hook
16
32
 
17
33
  ## 依赖关系
18
34
  - 依赖 `src/types/` 知识相关类型
19
35
  - 依赖 `src/monitoring/` KnowledgeDoctor / KnowledgeEvolver
20
- - 被 `src/cli/commands/knowledge.ts` CLI 消费
36
+ - 被 `src/cli/commands/knowledge.ts` CLI 消费(含 `migrate` 子命令)
21
37
 
22
38
  ## 约定
23
- - 知识条目有明确的生命周期状态
39
+ - 知识条目有明确的生命周期状态(按 consumptionMode 分化)
24
40
  - 约束退化时自动写入 KnowledgeStore
25
41
  - Linter 检查完整性/一致性/时效性三个维度
42
+ - Audit 6 维度评分:D1结构 D2内容 D3去重 D4成熟度 D5新鲜度 D6飞轮
43
+ - Ingest gate: ingestEntry() 先经 audit.validate() 检查,reject 不入库
44
+ - 外部内容三层防御:ingest sanitization + retrieval marking + prompt constraint
45
+ - 消费饱和度替代固定 TTL 用于 signal 过期判断
26
46
 
27
47
  ## 注意事项
28
48
  - Phase 1+4 实现的知识引擎核心
29
49
  - 约束"退化不删除"——降级时保留规则原文 + 退化原因 + 历史数据
50
+ - `MaturityLevel` 包含 6 个值: draft/verified/proven/archived/active/deprecated
51
+ - `excludeArchived` 同时排除 archived 和 deprecated