@dommaker/harness 1.9.0 → 1.11.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 +17 -0
- package/README.md +9 -12
- package/dist/cli/commands/check.d.ts +3 -3
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +41 -78
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/constraints-report.d.ts +2 -10
- package/dist/cli/commands/constraints-report.d.ts.map +1 -1
- package/dist/cli/commands/constraints-report.js +4 -57
- package/dist/cli/commands/constraints-report.js.map +1 -1
- package/dist/cli/commands/constraints-retire.d.ts +9 -23
- package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
- package/dist/cli/commands/constraints-retire.js +39 -121
- package/dist/cli/commands/constraints-retire.js.map +1 -1
- package/dist/cli/commands/constraints.d.ts +3 -8
- package/dist/cli/commands/constraints.d.ts.map +1 -1
- package/dist/cli/commands/constraints.js +8 -23
- package/dist/cli/commands/constraints.js.map +1 -1
- package/dist/cli/commands/definitions.d.ts.map +1 -1
- package/dist/cli/commands/definitions.js +7 -12
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/init.d.ts +0 -32
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +7 -149
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +14 -17
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/scaffold-templates.d.ts +1 -3
- package/dist/cli/commands/scaffold-templates.d.ts.map +1 -1
- package/dist/cli/commands/scaffold-templates.js +2 -53
- package/dist/cli/commands/scaffold-templates.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +0 -2
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +0 -10
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/commands/status.js +10 -10
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts +0 -2
- package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.js +4 -23
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
- package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
- package/dist/core/constraints/capabilities-parser.js +16 -4
- package/dist/core/constraints/capabilities-parser.js.map +1 -1
- package/dist/core/constraints/checker.d.ts +15 -24
- package/dist/core/constraints/checker.d.ts.map +1 -1
- package/dist/core/constraints/checker.js +33 -72
- package/dist/core/constraints/checker.js.map +1 -1
- package/dist/core/constraints/checkers/docs-freshness.js +1 -1
- package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts +2 -1
- package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
- package/dist/core/constraints/checkers/governance-presence.js +4 -3
- package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
- package/dist/core/constraints/checkers/index.d.ts +1 -1
- package/dist/core/constraints/checkers/index.d.ts.map +1 -1
- package/dist/core/constraints/checkers/index.js +4 -8
- package/dist/core/constraints/checkers/index.js.map +1 -1
- package/dist/core/constraints/checkers/iron-flags.d.ts +3 -4
- package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
- package/dist/core/constraints/checkers/iron-flags.js +4 -5
- package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.js +1 -1
- package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
- package/dist/core/constraints/checkers/types.d.ts +1 -1
- package/dist/core/constraints/checkers/types.js +1 -1
- package/dist/core/constraints/definitions/guidelines.d.ts +4 -4
- package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
- package/dist/core/constraints/definitions/guidelines.js +9 -25
- package/dist/core/constraints/definitions/guidelines.js.map +1 -1
- package/dist/core/constraints/definitions/iron-laws.d.ts +4 -4
- package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
- package/dist/core/constraints/definitions/iron-laws.js +10 -81
- package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
- package/dist/core/constraints/definitions.d.ts +7 -9
- package/dist/core/constraints/definitions.d.ts.map +1 -1
- package/dist/core/constraints/definitions.js +13 -16
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/core/constraints/index.d.ts +2 -5
- package/dist/core/constraints/index.d.ts.map +1 -1
- package/dist/core/constraints/index.js +3 -13
- package/dist/core/constraints/index.js.map +1 -1
- package/dist/core/constraints/injection-writer.d.ts +10 -38
- package/dist/core/constraints/injection-writer.d.ts.map +1 -1
- package/dist/core/constraints/injection-writer.js +17 -54
- package/dist/core/constraints/injection-writer.js.map +1 -1
- package/dist/core/constraints/run-env.d.ts +1 -10
- package/dist/core/constraints/run-env.d.ts.map +1 -1
- package/dist/core/constraints/run-env.js +1 -22
- package/dist/core/constraints/run-env.js.map +1 -1
- package/dist/core/constraints/usage-report.d.ts +6 -8
- package/dist/core/constraints/usage-report.d.ts.map +1 -1
- package/dist/core/constraints/usage-report.js +6 -11
- package/dist/core/constraints/usage-report.js.map +1 -1
- package/dist/core/effective-constraints.d.ts +12 -22
- package/dist/core/effective-constraints.d.ts.map +1 -1
- package/dist/core/effective-constraints.js +13 -30
- package/dist/core/effective-constraints.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -9
- package/dist/core/index.js.map +1 -1
- package/dist/core/project-config-loader.d.ts +4 -42
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +16 -125
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/validators/passes-gate.d.ts +2 -2
- package/dist/core/validators/passes-gate.js +6 -6
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/index.d.ts +9 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -18
- package/dist/index.js.map +1 -1
- package/dist/knowledge/lint.d.ts +17 -0
- package/dist/knowledge/lint.d.ts.map +1 -1
- package/dist/knowledge/lint.js +52 -0
- package/dist/knowledge/lint.js.map +1 -1
- package/dist/knowledge/store.d.ts +7 -0
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +48 -13
- package/dist/knowledge/store.js.map +1 -1
- package/dist/knowledge/types.d.ts +5 -1
- package/dist/knowledge/types.d.ts.map +1 -1
- package/dist/knowledge/types.js +5 -1
- package/dist/knowledge/types.js.map +1 -1
- package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
- package/dist/monitoring/trace-analyzer.js +11 -12
- package/dist/monitoring/trace-analyzer.js.map +1 -1
- package/dist/monitoring/traces.d.ts +4 -4
- package/dist/monitoring/traces.d.ts.map +1 -1
- package/dist/monitoring/traces.js +8 -8
- package/dist/monitoring/traces.js.map +1 -1
- package/dist/presets/standard.d.ts +8 -10
- package/dist/presets/standard.d.ts.map +1 -1
- package/dist/presets/standard.js +10 -16
- package/dist/presets/standard.js.map +1 -1
- package/dist/types/constraint.d.ts +24 -35
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js +8 -7
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/passes-gate.d.ts +5 -5
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +8 -66
- package/dist/types/project-config.d.ts.map +1 -1
- package/dist/types/project-config.js +3 -2
- package/dist/types/project-config.js.map +1 -1
- package/dist/types/trace.d.ts +8 -10
- package/dist/types/trace.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/CONTEXT.md +2 -2
- package/src/__tests__/checker-extra.test.ts +37 -61
- package/src/__tests__/checker.test.ts +10 -115
- package/src/__tests__/effective-constraints.test.ts +18 -83
- package/src/__tests__/iron-laws.test.ts +71 -90
- package/src/__tests__/passes-gate-check.test.ts +2 -2
- package/src/__tests__/project-config-loader-extra.test.ts +22 -123
- package/src/__tests__/project-config-loader.test.ts +5 -33
- package/src/__tests__/public-exports.test.ts +8 -7
- package/src/__tests__/public-type-surface.test.ts +7 -5
- package/src/__tests__/public-value-surface.test.ts +1 -7
- package/src/__tests__/skip-semantics.test.ts +21 -37
- package/src/__tests__/trace-analyzer-extra.test.ts +14 -14
- package/src/__tests__/trace-analyzer.test.ts +21 -21
- package/src/__tests__/trace-collector.test.ts +22 -22
- package/src/__tests__/traces.test.ts +27 -28
- package/src/__tests__/usage-report-public-export.test.ts +21 -0
- package/src/cli/commands/CONTEXT.md +12 -12
- package/src/cli/commands/__tests__/check-read-count.test.ts +4 -15
- package/src/cli/commands/__tests__/check-skip-output.test.ts +14 -14
- package/src/cli/commands/__tests__/check.test.ts +14 -31
- package/src/cli/commands/__tests__/constraints-report-json-flag.test.ts +101 -0
- package/src/cli/commands/__tests__/constraints-report.test.ts +12 -80
- package/src/cli/commands/__tests__/constraints-retire.test.ts +42 -231
- package/src/cli/commands/__tests__/init-governance-io.test.ts +12 -58
- package/src/cli/commands/__tests__/init-ondisk.test.ts +13 -21
- package/src/cli/commands/__tests__/init.test.ts +1 -16
- package/src/cli/commands/__tests__/numeric-flag-assembly.test.ts +1 -1
- package/src/cli/commands/__tests__/passes-gate-dead-options.test.ts +1 -1
- package/src/cli/commands/__tests__/project-path-anchoring.test.ts +2 -2
- package/src/cli/commands/__tests__/registry.test.ts +1 -1
- package/src/cli/commands/__tests__/report-extra.test.ts +4 -4
- package/src/cli/commands/__tests__/report.test.ts +1 -1
- package/src/cli/commands/__tests__/scaffold.test.ts +4 -14
- package/src/cli/commands/__tests__/status-analysis-wiring.test.ts +3 -3
- package/src/cli/commands/__tests__/status-extra.test.ts +14 -14
- package/src/cli/commands/__tests__/status.test.ts +12 -12
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +1 -1
- package/src/cli/commands/check.ts +43 -82
- package/src/cli/commands/constraints-report.ts +4 -59
- package/src/cli/commands/constraints-retire.ts +49 -154
- package/src/cli/commands/constraints.ts +11 -26
- package/src/cli/commands/definitions.ts +7 -12
- package/src/cli/commands/init.ts +8 -179
- package/src/cli/commands/report.ts +19 -23
- package/src/cli/commands/scaffold-templates.ts +1 -53
- package/src/cli/commands/scaffold.ts +0 -11
- package/src/cli/commands/status.ts +10 -10
- package/src/cli/commands/sync-docs/agents-syncer.ts +4 -25
- package/src/core/CONTEXT.md +9 -9
- package/src/core/constraints/__tests__/capability-counts.test.ts +5 -5
- package/src/core/constraints/__tests__/collect-constraints.test.ts +13 -8
- package/src/core/constraints/__tests__/git-evidence.test.ts +4 -7
- package/src/core/constraints/__tests__/injection-writer.test.ts +8 -61
- package/src/core/constraints/__tests__/run-env.test.ts +5 -34
- package/src/core/constraints/__tests__/trace-injection.test.ts +1 -1
- package/src/core/constraints/capabilities-parser.ts +17 -5
- package/src/core/constraints/checker.ts +39 -88
- package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +5 -8
- package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +1 -53
- package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +5 -25
- package/src/core/constraints/checkers/docs-freshness.ts +1 -1
- package/src/core/constraints/checkers/governance-presence.ts +4 -3
- package/src/core/constraints/checkers/index.ts +4 -10
- package/src/core/constraints/checkers/iron-flags.ts +3 -12
- package/src/core/constraints/checkers/no-test-simplification.ts +1 -1
- package/src/core/constraints/checkers/types.ts +1 -1
- package/src/core/constraints/definitions/guidelines.ts +8 -25
- package/src/core/constraints/definitions/iron-laws.ts +9 -82
- package/src/core/constraints/definitions.ts +14 -15
- package/src/core/constraints/index.ts +4 -19
- package/src/core/constraints/injection-writer.ts +16 -61
- package/src/core/constraints/run-env.ts +1 -33
- package/src/core/constraints/usage-report.ts +9 -16
- package/src/core/effective-constraints.ts +14 -45
- package/src/core/index.ts +3 -10
- package/src/core/project-config-loader.ts +20 -145
- package/src/core/validators/passes-gate.ts +6 -6
- package/src/failure/CONTEXT.md +1 -1
- package/src/hooks/__tests__/bootstrap.test.ts +3 -5
- package/src/index.ts +28 -18
- package/src/knowledge/CONTEXT.md +4 -3
- package/src/knowledge/__tests__/lint.test.ts +84 -0
- package/src/knowledge/__tests__/store.test.ts +70 -0
- package/src/knowledge/lint.ts +60 -1
- package/src/knowledge/store.ts +48 -11
- package/src/knowledge/types.ts +7 -1
- package/src/monitoring/CONTEXT.md +1 -1
- package/src/monitoring/__tests__/trace-file-anchoring.test.ts +1 -1
- package/src/monitoring/__tests__/traces.test.ts +22 -22
- package/src/monitoring/trace-analyzer.ts +12 -13
- package/src/monitoring/traces.ts +8 -8
- package/src/presets/__tests__/standard.test.ts +12 -16
- package/src/presets/standard.ts +14 -23
- package/src/types/__tests__/types.test.ts +3 -3
- package/src/types/constraint.ts +26 -40
- package/src/types/passes-gate.ts +5 -5
- package/src/types/project-config.ts +8 -77
- package/src/types/trace.ts +8 -11
- package/dist/cli/commands/posteval-plan.d.ts +0 -15
- package/dist/cli/commands/posteval-plan.d.ts.map +0 -1
- package/dist/cli/commands/posteval-plan.js +0 -86
- package/dist/cli/commands/posteval-plan.js.map +0 -1
- package/dist/core/constraints/agent-prompt-renderer.d.ts +0 -32
- package/dist/core/constraints/agent-prompt-renderer.d.ts.map +0 -1
- package/dist/core/constraints/agent-prompt-renderer.js +0 -55
- package/dist/core/constraints/agent-prompt-renderer.js.map +0 -1
- package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +0 -6
- package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +0 -1
- package/dist/core/constraints/checkers/no-bypass-checkpoint.js +0 -40
- package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +0 -1
- package/dist/core/constraints/definitions/prompts.d.ts +0 -12
- package/dist/core/constraints/definitions/prompts.d.ts.map +0 -1
- package/dist/core/constraints/definitions/prompts.js +0 -400
- package/dist/core/constraints/definitions/prompts.js.map +0 -1
- package/dist/core/constraints/injection-drift.d.ts +0 -61
- package/dist/core/constraints/injection-drift.d.ts.map +0 -1
- package/dist/core/constraints/injection-drift.js +0 -131
- package/dist/core/constraints/injection-drift.js.map +0 -1
- package/dist/core/constraints/injection-renderer.d.ts +0 -23
- package/dist/core/constraints/injection-renderer.d.ts.map +0 -1
- package/dist/core/constraints/injection-renderer.js +0 -44
- package/dist/core/constraints/injection-renderer.js.map +0 -1
- package/src/cli/commands/__tests__/check-drift.test.ts +0 -158
- package/src/cli/commands/__tests__/init-injection.test.ts +0 -466
- package/src/cli/commands/__tests__/posteval-plan.test.ts +0 -204
- package/src/cli/commands/posteval-plan.ts +0 -98
- package/src/core/constraints/__tests__/agent-prompt-renderer.test.ts +0 -129
- package/src/core/constraints/__tests__/injection-drift.test.ts +0 -247
- package/src/core/constraints/agent-prompt-renderer.ts +0 -67
- package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +0 -76
- package/src/core/constraints/checkers/no-bypass-checkpoint.ts +0 -40
- package/src/core/constraints/definitions/prompts.ts +0 -414
- package/src/core/constraints/injection-drift.ts +0 -142
- package/src/core/constraints/injection-renderer.ts +0 -44
|
@@ -23,7 +23,7 @@ import type { MergedConstraintsConfig } from '../../../../types/project-config';
|
|
|
23
23
|
const CAPABILITY_SYNC: Constraint = {
|
|
24
24
|
id: 'capability_sync',
|
|
25
25
|
kind: 'check',
|
|
26
|
-
|
|
26
|
+
severity: 'warning',
|
|
27
27
|
rule: 'CODE CHANGES MUST UPDATE CAPABILITIES.MD',
|
|
28
28
|
message: '核心模块变更必须同步功能清单',
|
|
29
29
|
trigger: ['module_modification'],
|
|
@@ -62,11 +62,8 @@ describe('normalizeCheckOutcome — 三态 + 证据归一', () => {
|
|
|
62
62
|
/** 只含 capability_sync 的生效集:一次 run 一条 trace,不牵动其他约束 */
|
|
63
63
|
function onlyCapabilitySync(): MergedConstraintsConfig {
|
|
64
64
|
return {
|
|
65
|
-
|
|
66
|
-
guidelines: { capability_sync: CAPABILITY_SYNC },
|
|
67
|
-
prompts: {},
|
|
65
|
+
constraints: { capability_sync: CAPABILITY_SYNC },
|
|
68
66
|
disabled: [],
|
|
69
|
-
custom: [],
|
|
70
67
|
};
|
|
71
68
|
}
|
|
72
69
|
|
|
@@ -81,7 +78,7 @@ async function runGuideline(dir: string): Promise<{
|
|
|
81
78
|
{ operation: 'module_modification', projectPath: dir },
|
|
82
79
|
onlyCapabilitySync()
|
|
83
80
|
);
|
|
84
|
-
const result = run.
|
|
81
|
+
const result = run.warnings.find(r => r.id === 'capability_sync')!;
|
|
85
82
|
const trace = traces.find(t => t.constraintId === 'capability_sync')!;
|
|
86
83
|
return { result, trace };
|
|
87
84
|
}
|
|
@@ -151,7 +148,7 @@ describe('证据随铁律异常外溢(CLI catch 分支只打印 error.message
|
|
|
151
148
|
it('ConstraintViolationError 文案带出证据行', () => {
|
|
152
149
|
const error = new ConstraintViolationError({
|
|
153
150
|
id: 'docs_freshness',
|
|
154
|
-
|
|
151
|
+
severity: 'error',
|
|
155
152
|
satisfied: false,
|
|
156
153
|
message: '文档新鲜度检查未通过',
|
|
157
154
|
evidence: ['CAPABILITIES.md 登记的条目不存在:', 'src/gone.ts'],
|
|
@@ -165,7 +162,7 @@ describe('证据随铁律异常外溢(CLI catch 分支只打印 error.message
|
|
|
165
162
|
it('无证据时文案保持原样(旧消费方断言不受影响)', () => {
|
|
166
163
|
const error = new ConstraintViolationError({
|
|
167
164
|
id: 'no_test_simplification',
|
|
168
|
-
|
|
165
|
+
severity: 'error',
|
|
169
166
|
satisfied: false,
|
|
170
167
|
message: '禁止简化测试绕过困难',
|
|
171
168
|
checkedAt: new Date(),
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
hasGovernancePreserveBlock,
|
|
17
17
|
hasClaudeGovernance,
|
|
18
18
|
} from '../governance-presence';
|
|
19
|
-
import { detectInjectionDrift } from '../../injection-drift';
|
|
20
19
|
import { createProjectFixture, writeProjectConfig } from '../../../../test-setup/project-fixture';
|
|
21
20
|
import { normalizeCheckOutcome, type CheckEnv } from '../types';
|
|
22
21
|
import { createRunEnv } from '../../run-env';
|
|
@@ -99,7 +98,7 @@ describe('governance_presence checker', () => {
|
|
|
99
98
|
const outcome = await outcomeOf(tempDir);
|
|
100
99
|
expect(outcome.satisfied).toBe(false);
|
|
101
100
|
expect(outcome.evidence.join('\n')).toContain('治理契约');
|
|
102
|
-
expect(outcome.evidence.join('\n')).toContain('
|
|
101
|
+
expect(outcome.evidence.join('\n')).toContain('PRESERVE:governance');
|
|
103
102
|
// ADR-0016:证据只有一个出口。侧信道留着会让 CLI 结构化输出与 trace 两头口径不一致
|
|
104
103
|
expect(errorSpy).not.toHaveBeenCalled();
|
|
105
104
|
});
|
|
@@ -159,54 +158,3 @@ describe('hasGovernancePreserveBlock / hasClaudeGovernance 判定函数', () =>
|
|
|
159
158
|
expect(hasGovernancePreserveBlock(p)).toBe(false);
|
|
160
159
|
});
|
|
161
160
|
});
|
|
162
|
-
|
|
163
|
-
describe('governance_presence × detectInjectionDrift 同 fixture 一致性(#83)', () => {
|
|
164
|
-
let tempDir: string;
|
|
165
|
-
|
|
166
|
-
const writeConfig = () => writeProjectConfig(tempDir, 'preset: standard\n');
|
|
167
|
-
|
|
168
|
-
beforeEach(() => {
|
|
169
|
-
tempDir = createProjectFixture({
|
|
170
|
-
name: 'temp-test-gov-consistency',
|
|
171
|
-
parentDir: process.cwd(),
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
afterEach(() => {
|
|
176
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('双空格标题:presence 认在场(pass),drift 严格计数 0 不报重复——两层不再互相矛盾', async () => {
|
|
180
|
-
writeConfig();
|
|
181
|
-
fs.writeFileSync(path.join(tempDir, 'CLAUDE.md'), '# CLAUDE.md\n\n## Governance Rules\n\n条款\n');
|
|
182
|
-
|
|
183
|
-
expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(true);
|
|
184
|
-
const drift = detectInjectionDrift(tempDir);
|
|
185
|
-
expect(drift.notInjected).toBe(true);
|
|
186
|
-
expect(drift.duplicateHeading).toBe(false);
|
|
187
|
-
expect(drift.hasDrift).toBe(false);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('精确拼写单标题:presence pass,drift 不报重复', async () => {
|
|
191
|
-
writeConfig();
|
|
192
|
-
fs.writeFileSync(path.join(tempDir, 'CLAUDE.md'), '# CLAUDE.md\n\n## Governance Rules\n\n条款\n');
|
|
193
|
-
|
|
194
|
-
expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(true);
|
|
195
|
-
const drift = detectInjectionDrift(tempDir);
|
|
196
|
-
expect(drift.notInjected).toBe(true);
|
|
197
|
-
expect(drift.duplicateHeading).toBe(false);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('精确拼写双标题:presence 认在场,drift 报重复章节(计数是 drift 的独立职责)', async () => {
|
|
201
|
-
writeConfig();
|
|
202
|
-
fs.writeFileSync(
|
|
203
|
-
path.join(tempDir, 'CLAUDE.md'),
|
|
204
|
-
'# CLAUDE.md\n\n## Governance Rules\n\n甲\n\n## Governance Rules\n\n乙\n'
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
expect(await governancePresence.evaluate(makeEnv(tempDir))).toBe(true);
|
|
208
|
-
const drift = detectInjectionDrift(tempDir);
|
|
209
|
-
expect(drift.notInjected).toBe(true);
|
|
210
|
-
expect(drift.duplicateHeading).toBe(true);
|
|
211
|
-
});
|
|
212
|
-
});
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 铁律层 flag 检查旁测(架构评审候选4,ADR-0009 同模式)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 唯一存活的 flag 铁律为 contextEvidenceFlag 构造,真实 bug 面 = 读错上下文字段
|
|
5
5
|
* 与三态语义(undefined→skip / false→fail / true→pass)。直接喂不同字段组合
|
|
6
6
|
* 钉死映射,不再经 engine facade(旧测在 skip-semantics/checker.test 间接打)。
|
|
7
|
+
*
|
|
8
|
+
* harness#174 删除 incremental_progress / no_implementation_without_requirement,
|
|
9
|
+
* 对应用例一并移除。
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
12
|
import { describe, it, expect } from '@jest/globals';
|
|
10
|
-
import {
|
|
11
|
-
noCompletionWithoutVerification,
|
|
12
|
-
incrementalProgress,
|
|
13
|
-
noImplementationWithoutRequirement,
|
|
14
|
-
} from '../iron-flags';
|
|
13
|
+
import { noCompletionWithoutVerification } from '../iron-flags';
|
|
15
14
|
import { buildCheckEnv } from '../types';
|
|
16
15
|
import type { ConstraintContext } from '../../../../types/constraint';
|
|
17
16
|
|
|
@@ -28,23 +27,4 @@ describe('iron flags — 三态与字段映射', () => {
|
|
|
28
27
|
// 相邻字段不串台:hasTest 不能顶替
|
|
29
28
|
expect(await evaluate(noCompletionWithoutVerification, { hasTest: true })).toBe('skip');
|
|
30
29
|
});
|
|
31
|
-
|
|
32
|
-
it('incremental_progress → 读 hasSingleTask', async () => {
|
|
33
|
-
expect(await evaluate(incrementalProgress, {})).toBe('skip');
|
|
34
|
-
expect(await evaluate(incrementalProgress, { hasSingleTask: false })).toBe(false);
|
|
35
|
-
expect(await evaluate(incrementalProgress, { hasSingleTask: true })).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('no_implementation_without_requirement → 读 hasRequirement', async () => {
|
|
39
|
-
expect(await evaluate(noImplementationWithoutRequirement, {})).toBe('skip');
|
|
40
|
-
expect(await evaluate(noImplementationWithoutRequirement, { hasRequirement: false })).toBe(false);
|
|
41
|
-
expect(await evaluate(noImplementationWithoutRequirement, { hasRequirement: true })).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('三 flag 各自独立判定(组合上下文互不影响)', async () => {
|
|
45
|
-
const ctx: Partial<ConstraintContext> = { hasVerificationEvidence: true, hasSingleTask: false };
|
|
46
|
-
expect(await evaluate(noCompletionWithoutVerification, ctx)).toBe(true);
|
|
47
|
-
expect(await evaluate(incrementalProgress, ctx)).toBe(false);
|
|
48
|
-
expect(await evaluate(noImplementationWithoutRequirement, ctx)).toBe('skip');
|
|
49
|
-
});
|
|
50
30
|
});
|
|
@@ -90,7 +90,7 @@ export const docsFreshness: ConstraintCheck = {
|
|
|
90
90
|
if (deadEntries.length > 0) {
|
|
91
91
|
// 证据通道点名条目(harness#119):此前是 console.error 侧信道(2026-08-08 studio
|
|
92
92
|
// CI 4 连红时的临时办法),CLI 结构化输出与 trace 两头都拿不到,
|
|
93
|
-
//
|
|
93
|
+
// error 级拦截时用户只看到一句通用提示,basename 碰撞下无从定位
|
|
94
94
|
return {
|
|
95
95
|
pass: false,
|
|
96
96
|
evidence: formatEvidence('CAPABILITIES.md 登记的条目不存在', deadEntries),
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* governance_presence:治理契约在场守护(studio #302,ADR 2026-08-21 落点模型)
|
|
3
3
|
*
|
|
4
4
|
* 治理契约正本 = AGENTS.md 手写 `PRESERVE:governance` 段(旧模型仓 = CLAUDE.md
|
|
5
|
-
* Governance Rules / HARNESS_CONSTRAINTS
|
|
5
|
+
* Governance Rules 块 / 历史 HARNESS_CONSTRAINTS 注入段,ADR-0029 后注入段不再
|
|
6
|
+
* 生成,残留段仅作历史兼容判据)。PRESERVE 只保「存在」不保「在场」:
|
|
6
7
|
* 段被删除/掏空后 sync-docs 重新生成会静默丢失,此处补「在场」校验。
|
|
7
8
|
*
|
|
8
9
|
* ADR-0001 存在性探测:项目未采用 harness 治理(无 .harness/config.yml)→ skip。
|
|
@@ -48,12 +49,12 @@ export const governancePresence: ConstraintCheck = {
|
|
|
48
49
|
if (hasClaudeGovernance(join(projectPath, 'CLAUDE.md'))) return true;
|
|
49
50
|
|
|
50
51
|
// 证据随判定一并返回(ADR-0016 补迁):此前这里是 console.error 侧信道——
|
|
51
|
-
// 只进本地 stderr,进不了 CLI 结论块与 trace
|
|
52
|
+
// 只进本地 stderr,进不了 CLI 结论块与 trace,error 级拦截时用户看不到该恢复哪个正本
|
|
52
53
|
return {
|
|
53
54
|
pass: false,
|
|
54
55
|
evidence: [
|
|
55
56
|
'治理契约缺失:AGENTS.md 无非空 PRESERVE:governance 段,CLAUDE.md 也无 Governance Rules 块(正本静默丢失)',
|
|
56
|
-
'修复:
|
|
57
|
+
'修复: 恢复其一——AGENTS.md 补回手写 PRESERVE:governance 段,或 CLAUDE.md 补回 Governance Rules 块',
|
|
57
58
|
],
|
|
58
59
|
};
|
|
59
60
|
},
|
|
@@ -13,10 +13,7 @@ import { getAllConstraints } from '../definitions';
|
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
noCompletionWithoutVerification,
|
|
16
|
-
incrementalProgress,
|
|
17
|
-
noImplementationWithoutRequirement,
|
|
18
16
|
} from './iron-flags';
|
|
19
|
-
import { noBypassCheckpoint } from './no-bypass-checkpoint';
|
|
20
17
|
import { noTestSimplification } from './no-test-simplification';
|
|
21
18
|
import { capabilitySync } from './capability-sync';
|
|
22
19
|
import { contextDocSync } from './context-doc-sync';
|
|
@@ -25,15 +22,12 @@ import { noHardcodedCredentials } from './no-hardcoded-credentials';
|
|
|
25
22
|
import { governancePresence } from './governance-presence';
|
|
26
23
|
|
|
27
24
|
const CHECKS: ConstraintCheck[] = [
|
|
28
|
-
//
|
|
25
|
+
// severity='error'
|
|
29
26
|
noCompletionWithoutVerification,
|
|
30
|
-
incrementalProgress,
|
|
31
|
-
noImplementationWithoutRequirement,
|
|
32
27
|
noTestSimplification,
|
|
33
28
|
docsFreshness,
|
|
34
|
-
//
|
|
29
|
+
// severity='warning'
|
|
35
30
|
noHardcodedCredentials,
|
|
36
|
-
noBypassCheckpoint,
|
|
37
31
|
capabilitySync,
|
|
38
32
|
contextDocSync,
|
|
39
33
|
governancePresence,
|
|
@@ -51,7 +45,7 @@ for (const c of checkConstraints) {
|
|
|
51
45
|
if (!registry.has(c.id)) {
|
|
52
46
|
throw new Error(
|
|
53
47
|
`[harness] 约束注册表闭环校验失败:kind='check' 的约束 "${c.id}" 未注册 checker。` +
|
|
54
|
-
`请在 checkers/
|
|
48
|
+
`请在 checkers/ 中实现并注册(纯文本提示层已随 ADR-0029 关停)。`
|
|
55
49
|
);
|
|
56
50
|
}
|
|
57
51
|
}
|
|
@@ -67,7 +61,7 @@ for (const id of registry.keys()) {
|
|
|
67
61
|
|
|
68
62
|
/**
|
|
69
63
|
* 按约束 ID 查找检查实现;未注册返回 undefined
|
|
70
|
-
* (编排层对 kind='check'
|
|
64
|
+
* (编排层对 kind='check' 未注册的情况抛错)
|
|
71
65
|
*/
|
|
72
66
|
export function getConstraintCheck(id: string): ConstraintCheck | undefined {
|
|
73
67
|
return registry.get(id);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* error 级轻量检查(工单 21):纯上下文证据标志判定,无 I/O
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* harness#174 后仅存活的 flag:hasVerificationEvidence
|
|
5
|
+
*(incremental_progress / no_implementation_without_requirement 已随定义一并删除)
|
|
5
6
|
*
|
|
6
7
|
* 三态语义(ADR-0001 防爆措施):
|
|
7
8
|
* - undefined = flag 未接线 → skip(不评估,CLI pre-commit 等路径不误报违规)
|
|
@@ -14,13 +15,3 @@ export const noCompletionWithoutVerification = contextEvidenceFlag(
|
|
|
14
15
|
'no_completion_without_verification',
|
|
15
16
|
ctx => ctx.hasVerificationEvidence
|
|
16
17
|
);
|
|
17
|
-
|
|
18
|
-
export const incrementalProgress = contextEvidenceFlag(
|
|
19
|
-
'incremental_progress',
|
|
20
|
-
ctx => ctx.hasSingleTask
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
export const noImplementationWithoutRequirement = contextEvidenceFlag(
|
|
24
|
-
'no_implementation_without_requirement',
|
|
25
|
-
ctx => ctx.hasRequirement
|
|
26
|
-
);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type { ConstraintCheck } from './types';
|
|
6
6
|
|
|
7
|
-
// m 标志必需:真实 diff 首行恒为 `diff --git`,缺 m 则 ^
|
|
7
|
+
// m 标志必需:真实 diff 首行恒为 `diff --git`,缺 m 则 ^ 永不命中删除行(checker 静默失效)
|
|
8
8
|
const DELETED_TEST_PATTERNS = [
|
|
9
9
|
/^-\s*(test|it|describe)\s*\(/m, // 删除 test/it/describe
|
|
10
10
|
/^-\s*expect\s*\(/m, // 删除 expect
|
|
@@ -113,7 +113,7 @@ export const MAX_EVIDENCE_ITEMS = 10;
|
|
|
113
113
|
/**
|
|
114
114
|
* 组装证据行:一行说明 + 逐条依据(超限截断)
|
|
115
115
|
*
|
|
116
|
-
* 每行自描述且不带缩进——缩进由消费端(CLI / gate 理由 /
|
|
116
|
+
* 每行自描述且不带缩进——缩进由消费端(CLI / gate 理由 / error 级异常文案)决定,trace 原样存。
|
|
117
117
|
* 修复入口不写在这里:那是各约束自己的事,写进各自的 summary 行(docs_freshness 的
|
|
118
118
|
* 幽灵条目与 sync-docs 无关,共用一个指针会误导)。
|
|
119
119
|
*/
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* check
|
|
2
|
+
* check 约束定义(severity='warning' 组,ADR-0029)
|
|
3
3
|
*
|
|
4
|
-
* 只保留带真实 checker
|
|
4
|
+
* 只保留带真实 checker 的约束。每条必须:
|
|
5
5
|
* - kind: 'check'
|
|
6
|
-
* -
|
|
6
|
+
* - severity: 'warning'(违规告警不阻断)
|
|
7
7
|
* - 在 checkers/ 注册表中有对应实现(注册表闭环,缺失即加载期抛错)
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Constraint } from '../../../types/constraint';
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const WARNING_CONSTRAINTS: Record<string, Constraint> = {
|
|
13
13
|
/**
|
|
14
14
|
* 禁止硬编码凭证
|
|
15
15
|
* 原因:密码/token/密钥泄露是最严重的安全漏洞,一旦提交到版本控制即不可逆
|
|
@@ -19,27 +19,10 @@ export const GUIDELINES: Record<string, Constraint> = {
|
|
|
19
19
|
kind: 'check',
|
|
20
20
|
rule: 'NO HARDCODED PASSWORDS, TOKENS, SECRETS, OR CREDENTIALS IN ANY SOURCE FILE',
|
|
21
21
|
message: '禁止在代码/文档/配置文件中硬编码密码、token、密钥、API key',
|
|
22
|
-
|
|
22
|
+
severity: 'warning',
|
|
23
23
|
trigger: ['code_implementation', 'doc_update', 'config_change', 'commit'],
|
|
24
24
|
enforcement: 'credential-scan',
|
|
25
25
|
description: `凭证(密码/token/密钥/API key)必须从环境变量或加密配置读取,严禁以明文形式出现在任何源代码文件中。包括但不限于:源码、Markdown 文档、YAML/JSON 配置、脚本文件。模板文件(.example/.sample/.template)允许占位符但不得包含真实值。建议配合 pre-commit hook 做自动扫描。`,
|
|
26
|
-
promptInjection: '禁止在代码中硬编码密码、API 密钥、Token 等凭证。使用环境变量或安全的凭证管理方案存储敏感信息。',
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* 禁止跳过检查点验证
|
|
31
|
-
* 原因:安全底线,检查点是质量门控
|
|
32
|
-
*/
|
|
33
|
-
no_bypass_checkpoint: {
|
|
34
|
-
id: 'no_bypass_checkpoint',
|
|
35
|
-
kind: 'check',
|
|
36
|
-
rule: 'NO BYPASSING CHECKPOINTS',
|
|
37
|
-
message: '禁止跳过检查点验证',
|
|
38
|
-
level: 'guideline',
|
|
39
|
-
trigger: 'code_implementation',
|
|
40
|
-
enforcement: 'checkpoint-required',
|
|
41
|
-
description: '所有检查点必须通过,不能跳过验证步骤。检查点是质量的最后一道防线。',
|
|
42
|
-
promptInjection: '每个关键步骤后有 checkpoint 验证点,必须通过才能继续。通过标准:测试通过、类型检查无错误、lint 无新增警告。未通过时回退修复,不得跳过。',
|
|
43
26
|
},
|
|
44
27
|
|
|
45
28
|
/**
|
|
@@ -51,7 +34,7 @@ export const GUIDELINES: Record<string, Constraint> = {
|
|
|
51
34
|
kind: 'check',
|
|
52
35
|
rule: 'CODE CHANGES MUST UPDATE CAPABILITIES.MD',
|
|
53
36
|
message: '核心模块变更必须同步功能清单(支持模块级目录条目登记)',
|
|
54
|
-
|
|
37
|
+
severity: 'warning',
|
|
55
38
|
trigger: ['module_creation', 'module_modification', 'module_deletion', 'module_extension'],
|
|
56
39
|
enforcement: 'update-capabilities',
|
|
57
40
|
description: `在创建/修改/删除/扩展核心模块时,必须同步更新 CAPABILITIES.md:
|
|
@@ -79,7 +62,7 @@ export const GUIDELINES: Record<string, Constraint> = {
|
|
|
79
62
|
kind: 'check',
|
|
80
63
|
rule: 'KEY DIRECTORIES SHOULD HAVE CONTEXT.MD',
|
|
81
64
|
message: '关键目录缺少 CONTEXT.md,运行 harness sync-docs 创建模板后填写实际内容',
|
|
82
|
-
|
|
65
|
+
severity: 'warning',
|
|
83
66
|
trigger: 'module_modification',
|
|
84
67
|
enforcement: 'context-check',
|
|
85
68
|
description: `项目的关键目录应包含 CONTEXT.md 文件,描述目录职责和上下文。
|
|
@@ -108,7 +91,7 @@ export const GUIDELINES: Record<string, Constraint> = {
|
|
|
108
91
|
kind: 'check',
|
|
109
92
|
rule: 'GOVERNANCE CONTRACT MUST BE PRESENT (AGENTS.MD PRESERVE:GOVERNANCE BLOCK OR CLAUDE.MD GOVERNANCE RULES)',
|
|
110
93
|
message: '治理契约缺失:AGENTS.md 缺少非空 PRESERVE:governance 段,且 CLAUDE.md 无 Governance Rules 块',
|
|
111
|
-
|
|
94
|
+
severity: 'warning',
|
|
112
95
|
trigger: ['file_modification', 'module_creation', 'module_modification', 'doc_update', 'config_change', 'commit'],
|
|
113
96
|
enforcement: 'governance-presence-check',
|
|
114
97
|
description: `治理契约(约束清单正本)必须在场,两处居其一:
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* check
|
|
2
|
+
* check 约束定义(severity='error' 组,ADR-0029)
|
|
3
3
|
*
|
|
4
|
-
* 只保留带真实 checker
|
|
4
|
+
* 只保留带真实 checker 的约束。每条必须:
|
|
5
5
|
* - kind: 'check'
|
|
6
|
-
* -
|
|
6
|
+
* - severity: 'error'(违规即阻断)
|
|
7
7
|
* - 在 checkers/ 注册表中有对应实现(注册表闭环,缺失即加载期抛错)
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Constraint } from '../../../types/constraint';
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const ERROR_CONSTRAINTS: Record<string, Constraint> = {
|
|
13
13
|
/**
|
|
14
14
|
* 禁止无验证声明完成
|
|
15
15
|
* 原因:质量底线,必须有验证命令
|
|
@@ -19,95 +19,23 @@ export const IRON_LAWS: Record<string, Constraint> = {
|
|
|
19
19
|
kind: 'check',
|
|
20
20
|
rule: 'NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE',
|
|
21
21
|
message: '禁止无验证声明完成,必须运行验证命令',
|
|
22
|
-
|
|
22
|
+
severity: 'error',
|
|
23
23
|
trigger: 'code_implementation',
|
|
24
24
|
enforcement: 'verify-completion',
|
|
25
25
|
description: '在声明任何任务完成之前,必须运行新鲜的验证命令(项目声明的测试 + type check),以新鲜输出作为完成证据。验证命令集由项目自行声明,全量验证留给 CI 流程。',
|
|
26
|
-
promptInjection: '在声明任务完成前,必须重新运行新鲜的验证命令(项目声明的测试 + type check),使用新鲜的输出作为完成证据,不得复用旧结果,不得凭记忆声称完成。',
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* 禁止一次做多个任务(one-shotting)
|
|
31
|
-
* 来源:Anthropic AI Harness - Effective Harnesses for Long-running Agents
|
|
32
|
-
* 原因:避免中途耗尽 context,保持专注和可控
|
|
33
|
-
*/
|
|
34
|
-
incremental_progress: {
|
|
35
|
-
id: 'incremental_progress',
|
|
36
|
-
kind: 'check',
|
|
37
|
-
rule: 'ONE TASK PER SESSION',
|
|
38
|
-
message: '禁止一次做多个任务,每次只做一件事',
|
|
39
|
-
level: 'iron_law',
|
|
40
|
-
trigger: 'code_implementation',
|
|
41
|
-
enforcement: 'single-task-check',
|
|
42
|
-
description: `一个 session 只处理一个任务,避免 one-shotting。
|
|
43
|
-
|
|
44
|
-
【禁止】
|
|
45
|
-
- 一次做多个任务 → 中途耗尽 context
|
|
46
|
-
- 大改动一次性完成 → 失控
|
|
47
|
-
- 没有拆分的复杂任务 → 无法回滚
|
|
48
|
-
|
|
49
|
-
【必须】
|
|
50
|
-
- 一个 session 一个任务 → 保持专注
|
|
51
|
-
- 大任务拆分为小步骤 → 分步执行
|
|
52
|
-
- 每步都有 checkpoint → 可回滚
|
|
53
|
-
|
|
54
|
-
【判断标准】
|
|
55
|
-
- 改动涉及多个模块 → 需拆分
|
|
56
|
-
- 改动超过 100 行 → 需拆分
|
|
57
|
-
- 改动影响多个文件 → 需拆分
|
|
58
|
-
|
|
59
|
-
【参考】
|
|
60
|
-
Anthropic AI: "Effective Harnesses for Long-running Agents"
|
|
61
|
-
https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents`,
|
|
62
|
-
promptInjection: '一次只处理一个任务。改动涉及多个模块、超过 100 行、或影响多个文件时,必须拆分为小步骤分步执行,每步有独立 checkpoint 可回滚。不要试图一次性完成所有改动。',
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 禁止无需求就开始实现(吸收 no_implementation_without_requirement_review)
|
|
67
|
-
* 原因:没有需求就没有验收标准,实现方向不可控;
|
|
68
|
-
* 实现完成后必须逐条对照 AC 验证,避免偏离需求
|
|
69
|
-
*/
|
|
70
|
-
no_implementation_without_requirement: {
|
|
71
|
-
id: 'no_implementation_without_requirement',
|
|
72
|
-
kind: 'check',
|
|
73
|
-
rule: 'NO IMPLEMENTATION WITHOUT REQUIREMENTS, AND REVIEW AGAINST AC AFTER IMPLEMENTATION',
|
|
74
|
-
message: '禁止无需求就开始实现,实现后必须逐条对照 AC 验证',
|
|
75
|
-
level: 'iron_law',
|
|
76
|
-
trigger: ['code_implementation', 'design_request'],
|
|
77
|
-
enforcement: 'requirement-exists',
|
|
78
|
-
description: `在开始实现之前,必须有明确的需求定义;实现完成后,必须逐条对照验收标准(AC)验证。
|
|
79
|
-
|
|
80
|
-
【实现前必须执行】
|
|
81
|
-
1. 确认需求来源(Spec/Issue/Roadmap/用户指令)
|
|
82
|
-
2. 确认验收标准(AC)已定义
|
|
83
|
-
3. 确认边界情况已明确
|
|
84
|
-
|
|
85
|
-
【实现后必须执行】(吸收自 no_implementation_without_requirement_review)
|
|
86
|
-
1. 回顾需求文档(Spec/Roadmap/Issue)
|
|
87
|
-
2. 逐条检查实现是否符合每条 AC
|
|
88
|
-
3. 确认边界情况已覆盖
|
|
89
|
-
4. 输出验证清单(AC × 实现 × 状态)
|
|
90
|
-
|
|
91
|
-
【禁止】
|
|
92
|
-
- 没有需求就开始写代码、凭假设开始实现
|
|
93
|
-
- 实现后不对比需求直接提交,只测"功能能跑"不验证 AC
|
|
94
|
-
- 跳过边界情况验证,假设"差不多就行"
|
|
95
|
-
|
|
96
|
-
【正确流程】
|
|
97
|
-
需求确认 → AC 定义 → 实现 → 逐条对照 AC 验证`,
|
|
98
|
-
promptInjection: '开始编写代码前,必须确认:需求来源明确(Spec/Issue/Roadmap/用户指令)、验收标准(AC)已定义、边界情况已明确。不要凭假设或猜测开始实现。实现完成后,必须逐条对比原始需求文档中的验收标准(AC),确认每条 AC 已实现且边界情况已覆盖,输出验证清单。不得仅凭"功能能跑"就认为完成。',
|
|
99
26
|
},
|
|
100
27
|
|
|
101
28
|
/**
|
|
102
29
|
* 禁止简化测试
|
|
103
30
|
* 原因:质量底线,测试困难必须解决
|
|
31
|
+
* (harness#174:checker 承载执行)
|
|
104
32
|
*/
|
|
105
33
|
no_test_simplification: {
|
|
106
34
|
id: 'no_test_simplification',
|
|
107
35
|
kind: 'check',
|
|
108
36
|
rule: 'NO SIMPLIFYING TESTS TO AVOID DIFFICULTY',
|
|
109
37
|
message: '禁止简化测试绕过困难',
|
|
110
|
-
|
|
38
|
+
severity: 'error',
|
|
111
39
|
trigger: 'test_creation',
|
|
112
40
|
enforcement: 'full-test-coverage',
|
|
113
41
|
description: `在编写测试时,不能因为遇到困难而简化或跳过测试。
|
|
@@ -121,19 +49,18 @@ https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agent
|
|
|
121
49
|
- 为了绕过 mock 困难而删除测试用例
|
|
122
50
|
- 为了绕过异步问题而跳过断言
|
|
123
51
|
- 降低测试覆盖率要求`,
|
|
124
|
-
promptInjection: '编写测试时遇到困难(mock、异步、环境),不得删除用例或跳过断言。正确做法:分析问题 → 查阅文档 → 尝试解决 → 仍不行则向用户说明困难请求指示。不得降低覆盖率要求。',
|
|
125
52
|
},
|
|
126
53
|
|
|
127
54
|
/**
|
|
128
55
|
* 文档新鲜度
|
|
129
|
-
*
|
|
56
|
+
* 原因:只警告不阻断会导致文档持续腐烂。
|
|
130
57
|
*/
|
|
131
58
|
docs_freshness: {
|
|
132
59
|
id: 'docs_freshness',
|
|
133
60
|
kind: 'check',
|
|
134
61
|
rule: 'CAPABILITIES.MD MUST BE IN SYNC WITH CODE',
|
|
135
62
|
message: 'CAPABILITIES.md 与源码不同步,运行 harness sync-docs 更新后重新提交',
|
|
136
|
-
|
|
63
|
+
severity: 'error',
|
|
137
64
|
trigger: ['file_modification', 'module_creation', 'module_modification'],
|
|
138
65
|
enforcement: 'docs-sync-check',
|
|
139
66
|
description: `CAPABILITIES.md 中列出的文件必须在 src/ 中实际存在。删除源文件时须从 CAPABILITIES.md 同步移除。运行 harness sync-docs 自动修复过期引用。
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 约束定义(薄聚合层)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* severity 显式模型(ADR-0029,取代 ADR-0001 三层命名):
|
|
5
|
+
* 全部内置约束 kind='check',severity 写死在定义上(error / warning),
|
|
6
|
+
* 纯文本提示层(prompts.ts)已随文本注入层关停整体删除。
|
|
7
7
|
*
|
|
8
|
-
* 工单 20
|
|
8
|
+
* 工单 20:字面量定义按 severity 分组放 ./definitions/{iron-laws,guidelines}.ts;
|
|
9
9
|
* 本文件保持原路径做薄聚合(studio rule-scanner 按此路径解析,P0 #8)。
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { Constraint, ConstraintTrigger } from '../../types/constraint';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { PROMPTS } from './definitions/prompts';
|
|
13
|
+
import { ERROR_CONSTRAINTS } from './definitions/iron-laws';
|
|
14
|
+
import { WARNING_CONSTRAINTS } from './definitions/guidelines';
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
/** 全部内置约束(check 层全量,severity 在条目上) */
|
|
17
|
+
export const CONSTRAINTS: Record<string, Constraint> = {
|
|
18
|
+
...ERROR_CONSTRAINTS,
|
|
19
|
+
...WARNING_CONSTRAINTS,
|
|
20
|
+
};
|
|
18
21
|
|
|
19
22
|
// ========================================
|
|
20
23
|
// 辅助函数
|
|
21
24
|
// ========================================
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
|
-
* 获取所有约束(check
|
|
27
|
+
* 获取所有约束(check 全量,带 kind/severity)
|
|
25
28
|
*/
|
|
26
29
|
export function getAllConstraints(): Constraint[] {
|
|
27
|
-
return
|
|
28
|
-
...Object.values(IRON_LAWS),
|
|
29
|
-
...Object.values(GUIDELINES),
|
|
30
|
-
...Object.values(PROMPTS),
|
|
31
|
-
];
|
|
30
|
+
return Object.values(CONSTRAINTS);
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
/**
|
|
@@ -45,5 +44,5 @@ export function findConstraintsByTrigger(trigger: ConstraintTrigger): Constraint
|
|
|
45
44
|
* 根据 ID 获取约束
|
|
46
45
|
*/
|
|
47
46
|
export function getConstraint(id: string): Constraint | undefined {
|
|
48
|
-
return
|
|
47
|
+
return CONSTRAINTS[id];
|
|
49
48
|
}
|
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
* 约束模块入口
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
// 约束定义(
|
|
5
|
+
// 约束定义(check 全量,severity 在条目上)
|
|
6
6
|
export {
|
|
7
|
-
|
|
8
|
-
GUIDELINES,
|
|
9
|
-
PROMPTS,
|
|
7
|
+
CONSTRAINTS,
|
|
10
8
|
getAllConstraints,
|
|
11
9
|
findConstraintsByTrigger,
|
|
12
10
|
getConstraint,
|
|
@@ -22,28 +20,15 @@ export {
|
|
|
22
20
|
} from './checker';
|
|
23
21
|
export type { CheckConstraintsOptions, TraceRecorder } from './checker';
|
|
24
22
|
|
|
25
|
-
// CLAUDE.md 约束注入段渲染(纯函数,init 注入与漂移校验共用)
|
|
26
|
-
export {
|
|
27
|
-
CONSTRAINTS_START_MARKER,
|
|
28
|
-
CONSTRAINTS_END_MARKER,
|
|
29
|
-
renderConstraintsSection,
|
|
30
|
-
} from './injection-renderer';
|
|
31
|
-
|
|
32
23
|
// 约束检查缓存(H6/G5:TTL 缓存 + 计数采样,公开导出)
|
|
33
24
|
export { CheckCache } from './check-cache';
|
|
34
25
|
export type { CheckCacheConfig, CheckSamplingConfig } from './check-cache';
|
|
35
26
|
|
|
36
|
-
// Agent prompt 约束段渲染(H6/G6:trigger 参数化分组渲染,role 路由留 studio)
|
|
37
|
-
export {
|
|
38
|
-
renderConstraintsByTrigger,
|
|
39
|
-
} from './agent-prompt-renderer';
|
|
40
|
-
export type { RenderConstraintsByTriggerOptions } from './agent-prompt-renderer';
|
|
41
|
-
|
|
42
27
|
// 类型导出
|
|
43
28
|
export type {
|
|
44
29
|
ConstraintId,
|
|
45
30
|
ConstraintKind,
|
|
46
|
-
|
|
31
|
+
ConstraintSeverity,
|
|
47
32
|
ConstraintTrigger,
|
|
48
33
|
Constraint,
|
|
49
34
|
ConstraintResult,
|
|
@@ -52,4 +37,4 @@ export type {
|
|
|
52
37
|
IronLawContext,
|
|
53
38
|
} from '../../types/constraint';
|
|
54
39
|
|
|
55
|
-
export { ConstraintViolationError } from '../../types/constraint';
|
|
40
|
+
export { ConstraintViolationError } from '../../types/constraint';
|