@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
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* checker.ts 测试
|
|
3
3
|
*
|
|
4
|
-
* ADR-
|
|
5
|
-
* prompt
|
|
6
|
-
* 已退役/被吸收约束的用例随之移除。
|
|
4
|
+
* ADR-0029:只覆盖存活 check 约束的 checker 行为;
|
|
5
|
+
* prompt 面已删除,其短路用例随之移除。
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
import { ConstraintChecker, checkConstraint } from '../core/constraints/checker';
|
|
10
|
-
import { PROMPTS } from '../core/constraints/definitions';
|
|
11
9
|
import type { ConstraintContext } from '../types/constraint';
|
|
12
|
-
import {
|
|
10
|
+
import { rmSync, mkdtempSync } from 'fs';
|
|
13
11
|
import { join } from 'path';
|
|
14
12
|
import { tmpdir } from 'os';
|
|
15
13
|
|
|
@@ -31,42 +29,7 @@ describe('ConstraintChecker', () => {
|
|
|
31
29
|
}
|
|
32
30
|
});
|
|
33
31
|
|
|
34
|
-
describe('
|
|
35
|
-
it('should check no_bypass_checkpoint with skip patterns', async () => {
|
|
36
|
-
// 创建包含 skip 的文件
|
|
37
|
-
const skipFile = join(tempDir, 'skip-test.ts');
|
|
38
|
-
writeFileSync(skipFile, 'test.skip("skipped test", () => {});');
|
|
39
|
-
|
|
40
|
-
const context: ConstraintContext = {
|
|
41
|
-
operation: 'code_implementation',
|
|
42
|
-
changedFiles: [skipFile],
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const result = await checker.check(
|
|
46
|
-
{ id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
47
|
-
context
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
expect(result.satisfied).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should pass no_bypass_checkpoint without skip patterns', async () => {
|
|
54
|
-
const normalFile = join(tempDir, 'normal-test.ts');
|
|
55
|
-
writeFileSync(normalFile, 'test("normal test", () => { expect(true).toBe(true); });');
|
|
56
|
-
|
|
57
|
-
const context: ConstraintContext = {
|
|
58
|
-
operation: 'code_implementation',
|
|
59
|
-
changedFiles: [normalFile],
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const result = await checker.check(
|
|
63
|
-
{ id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
64
|
-
context
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
expect(result.satisfied).toBe(true);
|
|
68
|
-
});
|
|
69
|
-
|
|
32
|
+
describe('error 级约束', () => {
|
|
70
33
|
it('should check no_completion_without_verification', async () => {
|
|
71
34
|
const contextWithEvidence: ConstraintContext = {
|
|
72
35
|
operation: 'code_implementation',
|
|
@@ -79,71 +42,21 @@ describe('ConstraintChecker', () => {
|
|
|
79
42
|
};
|
|
80
43
|
|
|
81
44
|
const resultWithEvidence = await checker.check(
|
|
82
|
-
{ id: 'no_completion_without_verification', kind: 'check',
|
|
45
|
+
{ id: 'no_completion_without_verification', kind: 'check', severity: 'error', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
83
46
|
contextWithEvidence
|
|
84
47
|
);
|
|
85
48
|
|
|
86
49
|
const resultWithoutEvidence = await checker.check(
|
|
87
|
-
{ id: 'no_completion_without_verification', kind: 'check',
|
|
50
|
+
{ id: 'no_completion_without_verification', kind: 'check', severity: 'error', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
88
51
|
contextWithoutEvidence
|
|
89
52
|
);
|
|
90
53
|
|
|
91
54
|
expect(resultWithEvidence.satisfied).toBe(true);
|
|
92
55
|
expect(resultWithoutEvidence.satisfied).toBe(false);
|
|
93
56
|
});
|
|
94
|
-
|
|
95
|
-
it('should check incremental_progress', async () => {
|
|
96
|
-
const contextWithSingleTask: ConstraintContext = {
|
|
97
|
-
operation: 'code_implementation',
|
|
98
|
-
hasSingleTask: true,
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const contextWithMultipleTasks: ConstraintContext = {
|
|
102
|
-
operation: 'code_implementation',
|
|
103
|
-
hasSingleTask: false,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const resultWith = await checker.check(
|
|
107
|
-
{ id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
108
|
-
contextWithSingleTask
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
const resultWithout = await checker.check(
|
|
112
|
-
{ id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
113
|
-
contextWithMultipleTasks
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
expect(resultWith.satisfied).toBe(true);
|
|
117
|
-
expect(resultWithout.satisfied).toBe(false);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should check no_implementation_without_requirement', async () => {
|
|
121
|
-
const contextWithRequirement: ConstraintContext = {
|
|
122
|
-
operation: 'code_implementation',
|
|
123
|
-
hasRequirement: true,
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const contextWithoutRequirement: ConstraintContext = {
|
|
127
|
-
operation: 'code_implementation',
|
|
128
|
-
hasRequirement: false,
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const resultWith = await checker.check(
|
|
132
|
-
{ id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
133
|
-
contextWithRequirement
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
const resultWithout = await checker.check(
|
|
137
|
-
{ id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
|
|
138
|
-
contextWithoutRequirement
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
expect(resultWith.satisfied).toBe(true);
|
|
142
|
-
expect(resultWithout.satisfied).toBe(false);
|
|
143
|
-
});
|
|
144
57
|
});
|
|
145
58
|
|
|
146
|
-
describe('
|
|
59
|
+
describe('warning 级约束', () => {
|
|
147
60
|
it('should check capability_sync without CAPABILITIES.md', async () => {
|
|
148
61
|
// 注意:tempDir 在 harness 仓库内,如果有缓存的变更,会检查到代码变更
|
|
149
62
|
// 所以需要创建一个无代码变更的场景或创建 CAPABILITIES.md
|
|
@@ -159,7 +72,7 @@ describe('ConstraintChecker', () => {
|
|
|
159
72
|
fs.writeFileSync(capabilitiesPath, '# Capabilities\n');
|
|
160
73
|
|
|
161
74
|
const result = await checker.check(
|
|
162
|
-
{ id: 'capability_sync', kind: 'check',
|
|
75
|
+
{ id: 'capability_sync', kind: 'check', severity: 'warning', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
|
|
163
76
|
context
|
|
164
77
|
);
|
|
165
78
|
|
|
@@ -171,24 +84,6 @@ describe('ConstraintChecker', () => {
|
|
|
171
84
|
});
|
|
172
85
|
});
|
|
173
86
|
|
|
174
|
-
describe('Prompt constraints(ADR-0001:不执行 checker,check() 短路 satisfied)', () => {
|
|
175
|
-
it('所有内置 prompt 约束 check() 均短路通过', async () => {
|
|
176
|
-
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
177
|
-
for (const prompt of Object.values(PROMPTS)) {
|
|
178
|
-
const result = await checker.check(prompt, context);
|
|
179
|
-
expect(result.satisfied).toBe(true);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('prompt 短路不产生 requiredAction/message', async () => {
|
|
184
|
-
const context: ConstraintContext = { operation: 'code_implementation' };
|
|
185
|
-
const result = await checker.check(PROMPTS['no_fix_without_root_cause'], context);
|
|
186
|
-
expect(result.satisfied).toBe(true);
|
|
187
|
-
expect(result.message).toBeUndefined();
|
|
188
|
-
expect(result.requiredAction).toBeUndefined();
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
87
|
describe('Helper functions', () => {
|
|
193
88
|
it('should check single constraint via checkConstraint', async () => {
|
|
194
89
|
const context: ConstraintContext = {
|
|
@@ -205,8 +100,8 @@ describe('ConstraintChecker', () => {
|
|
|
205
100
|
operation: 'code_implementation',
|
|
206
101
|
};
|
|
207
102
|
|
|
208
|
-
const result = await checkConstraint('
|
|
209
|
-
expect(result.id).toBe('
|
|
103
|
+
const result = await checkConstraint('no_completion_without_verification', context);
|
|
104
|
+
expect(result.id).toBe('no_completion_without_verification');
|
|
210
105
|
expect(result.satisfied).toBe(true);
|
|
211
106
|
});
|
|
212
107
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 生效约束集(getEffectiveConstraints / lintEffectiveConfig)测试
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 合并矩阵(ADR-0029):preset 裁剪 / config.yml 禁用 / 未知 id 诊断
|
|
5
|
+
* (custom 追加与 scenes 过滤已随文本注入层关停一并退役)
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
@@ -11,25 +12,19 @@ import {
|
|
|
11
12
|
lintEffectiveConfig,
|
|
12
13
|
} from '../core/effective-constraints';
|
|
13
14
|
import { createProjectFixture } from '../test-setup/project-fixture';
|
|
14
|
-
import {
|
|
15
|
+
import { CONSTRAINTS } from '../core/constraints/definitions';
|
|
15
16
|
|
|
16
|
-
const BUILTIN_TOTAL =
|
|
17
|
-
Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length + Object.keys(PROMPTS).length;
|
|
18
|
-
/** 带 appliesTo 标签的内置 prompt(scenes 过滤对象) */
|
|
19
|
-
const SCENE_PROMPTS = Object.values(PROMPTS)
|
|
20
|
-
.filter(c => c.appliesTo && c.appliesTo.length > 0)
|
|
21
|
-
.map(c => c.id);
|
|
17
|
+
const BUILTIN_TOTAL = Object.keys(CONSTRAINTS).length;
|
|
22
18
|
|
|
23
19
|
describe('getEffectiveConstraints / lintEffectiveConfig', () => {
|
|
24
20
|
let tempDir: string;
|
|
25
21
|
let counter = 0;
|
|
26
22
|
|
|
27
|
-
const setupProject = (configYaml?: string
|
|
23
|
+
const setupProject = (configYaml?: string): string =>
|
|
28
24
|
createProjectFixture({
|
|
29
25
|
parentDir: tempDir,
|
|
30
26
|
name: `p${counter++}`,
|
|
31
27
|
config: configYaml,
|
|
32
|
-
files: customYaml === undefined ? undefined : { '.harness/custom-constraints.yml': customYaml },
|
|
33
28
|
});
|
|
34
29
|
|
|
35
30
|
beforeEach(() => {
|
|
@@ -42,65 +37,28 @@ describe('getEffectiveConstraints / lintEffectiveConfig', () => {
|
|
|
42
37
|
});
|
|
43
38
|
|
|
44
39
|
describe('合并矩阵', () => {
|
|
45
|
-
it('
|
|
40
|
+
it('无配置项目:内置全集(全部 kind=check,带 severity)', () => {
|
|
46
41
|
const dir = setupProject();
|
|
47
42
|
const constraints = getEffectiveConstraints(dir);
|
|
48
|
-
const ids = constraints.map(c => c.id);
|
|
49
|
-
|
|
50
|
-
expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length);
|
|
51
|
-
for (const id of SCENE_PROMPTS) {
|
|
52
|
-
expect(ids).not.toContain(id);
|
|
53
|
-
}
|
|
54
|
-
// check + prompt 均带 kind
|
|
55
|
-
expect(constraints.every(c => c.kind === 'check' || c.kind === 'prompt')).toBe(true);
|
|
56
|
-
expect(constraints.filter(c => c.kind === 'check')).toHaveLength(
|
|
57
|
-
Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('scenes 命中:对应场景 prompt 进入生效集,其余场景 prompt 仍排除', () => {
|
|
62
|
-
const dir = setupProject(`scenes:\n - agent-skill\n`);
|
|
63
|
-
const ids = getEffectiveConstraints(dir).map(c => c.id);
|
|
64
43
|
|
|
65
|
-
expect(
|
|
66
|
-
expect(
|
|
44
|
+
expect(constraints.length).toBe(BUILTIN_TOTAL);
|
|
45
|
+
expect(constraints.every(c => c.kind === 'check')).toBe(true);
|
|
67
46
|
});
|
|
68
47
|
|
|
69
|
-
it('config.yml
|
|
48
|
+
it('config.yml 禁用:条目从生效集移除', () => {
|
|
70
49
|
const dir = setupProject(`
|
|
71
50
|
constraints:
|
|
72
|
-
|
|
51
|
+
capability_sync:
|
|
73
52
|
enabled: false
|
|
74
|
-
|
|
53
|
+
docs_freshness:
|
|
75
54
|
enabled: false
|
|
76
55
|
`);
|
|
77
56
|
const constraints = getEffectiveConstraints(dir);
|
|
78
57
|
const ids = constraints.map(c => c.id);
|
|
79
58
|
|
|
80
|
-
expect(ids).not.toContain('
|
|
81
|
-
expect(ids).not.toContain('
|
|
82
|
-
expect(constraints.length).toBe(BUILTIN_TOTAL -
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('config.yml 禁用:custom 约束同样从生效集移除(retire 落 config.yml 的退役路径)', () => {
|
|
86
|
-
const dir = setupProject(
|
|
87
|
-
`
|
|
88
|
-
constraints:
|
|
89
|
-
my_project_rule:
|
|
90
|
-
enabled: false
|
|
91
|
-
`,
|
|
92
|
-
`
|
|
93
|
-
custom_constraints:
|
|
94
|
-
my_project_rule:
|
|
95
|
-
level: iron_law
|
|
96
|
-
rule: MY RULE
|
|
97
|
-
message: 项目自定义
|
|
98
|
-
`
|
|
99
|
-
);
|
|
100
|
-
const constraints = getEffectiveConstraints(dir);
|
|
101
|
-
const ids = constraints.map(c => c.id);
|
|
102
|
-
|
|
103
|
-
expect(ids).not.toContain('my_project_rule');
|
|
59
|
+
expect(ids).not.toContain('capability_sync');
|
|
60
|
+
expect(ids).not.toContain('docs_freshness');
|
|
61
|
+
expect(constraints.length).toBe(BUILTIN_TOTAL - 2);
|
|
104
62
|
});
|
|
105
63
|
|
|
106
64
|
it('preset: relaxed 裁剪生效集', () => {
|
|
@@ -111,33 +69,13 @@ custom_constraints:
|
|
|
111
69
|
expect(ids).toEqual(
|
|
112
70
|
expect.arrayContaining([
|
|
113
71
|
'no_completion_without_verification',
|
|
114
|
-
'incremental_progress',
|
|
115
|
-
'no_implementation_without_requirement',
|
|
116
|
-
'no_bypass_checkpoint',
|
|
117
72
|
'no_hardcoded_credentials',
|
|
118
73
|
])
|
|
119
74
|
);
|
|
120
|
-
expect(constraints).toHaveLength(
|
|
75
|
+
expect(constraints).toHaveLength(2);
|
|
121
76
|
expect(constraints.every(c => c.kind === 'check')).toBe(true);
|
|
122
77
|
});
|
|
123
78
|
|
|
124
|
-
it('custom-constraints.yml 追加自定义约束(kind=prompt)', () => {
|
|
125
|
-
const dir = setupProject(undefined, `
|
|
126
|
-
custom_constraints:
|
|
127
|
-
my_project_rule:
|
|
128
|
-
level: guideline
|
|
129
|
-
rule: MY RULE
|
|
130
|
-
message: 项目自定义
|
|
131
|
-
trigger: code_implementation
|
|
132
|
-
`);
|
|
133
|
-
const constraints = getEffectiveConstraints(dir);
|
|
134
|
-
const custom = constraints.find(c => c.id === 'my_project_rule');
|
|
135
|
-
|
|
136
|
-
expect(custom).toBeDefined();
|
|
137
|
-
expect(custom!.kind).toBe('prompt');
|
|
138
|
-
expect(custom!.level).toBe('guideline');
|
|
139
|
-
});
|
|
140
|
-
|
|
141
79
|
it('禁用未知 id(已移除约束的残留配置):不报错,lint 可诊断', () => {
|
|
142
80
|
const dir = setupProject(`
|
|
143
81
|
constraints:
|
|
@@ -146,19 +84,16 @@ constraints:
|
|
|
146
84
|
`);
|
|
147
85
|
// 生效集不受影响、不抛错
|
|
148
86
|
const constraints = getEffectiveConstraints(dir);
|
|
149
|
-
expect(constraints.length).toBe(BUILTIN_TOTAL
|
|
87
|
+
expect(constraints.length).toBe(BUILTIN_TOTAL);
|
|
150
88
|
|
|
151
89
|
const lint = lintEffectiveConfig(dir);
|
|
152
90
|
expect(lint.unknownIds).toContain('removed_legacy_constraint');
|
|
153
91
|
});
|
|
154
92
|
|
|
155
|
-
it('lintEffectiveConfig
|
|
156
|
-
const dir = setupProject(
|
|
93
|
+
it('lintEffectiveConfig:干净配置 unknownIds 为空', () => {
|
|
94
|
+
const dir = setupProject();
|
|
157
95
|
const lint = lintEffectiveConfig(dir);
|
|
158
96
|
|
|
159
|
-
expect(lint.scenes).toEqual(['llm-app']);
|
|
160
|
-
expect(lint.sceneExcluded).toContain('no_skill_without_test');
|
|
161
|
-
expect(lint.sceneExcluded).not.toContain('no_model_for_deterministic');
|
|
162
97
|
expect(lint.unknownIds).toEqual([]);
|
|
163
98
|
});
|
|
164
99
|
});
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 约束系统测试(ADR-
|
|
2
|
+
* 约束系统测试(ADR-0029:severity 显式模型——三层命名废弃、prompt 面删除、注册表闭环保留)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, it, expect } from '@jest/globals';
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
GUIDELINES,
|
|
9
|
-
PROMPTS,
|
|
7
|
+
CONSTRAINTS,
|
|
10
8
|
getAllConstraints,
|
|
11
9
|
findConstraintsByTrigger,
|
|
12
10
|
getConstraint
|
|
@@ -16,32 +14,28 @@ import { getConstraintCheck, registeredCheckCount } from '../core/constraints/ch
|
|
|
16
14
|
import type { ConstraintContext } from '../types/constraint';
|
|
17
15
|
|
|
18
16
|
describe('Constraint System', () => {
|
|
19
|
-
describe('清单构成(ADR-
|
|
20
|
-
it('getAllConstraints 返回
|
|
17
|
+
describe('清单构成(ADR-0029:16 → 7,全部 kind=check)', () => {
|
|
18
|
+
it('getAllConstraints 返回 7 条 check 约束', () => {
|
|
21
19
|
const all = getAllConstraints();
|
|
22
|
-
expect(all).toHaveLength(
|
|
23
|
-
expect(all.
|
|
24
|
-
expect(all.filter(c => c.kind === 'prompt')).toHaveLength(16);
|
|
20
|
+
expect(all).toHaveLength(7);
|
|
21
|
+
expect(all.every(c => c.kind === 'check')).toBe(true);
|
|
25
22
|
});
|
|
26
23
|
|
|
27
|
-
it('
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
it('severity 分桶 = 3 error + 4 warning', () => {
|
|
25
|
+
const errors = Object.values(CONSTRAINTS).filter(c => c.severity === 'error');
|
|
26
|
+
const warnings = Object.values(CONSTRAINTS).filter(c => c.severity === 'warning');
|
|
27
|
+
expect(errors).toHaveLength(3);
|
|
28
|
+
expect(warnings).toHaveLength(4);
|
|
29
|
+
Object.values(CONSTRAINTS).forEach(c => {
|
|
31
30
|
expect(c.kind).toBe('check');
|
|
32
|
-
expect(c.level).toBe('iron_law');
|
|
33
|
-
});
|
|
34
|
-
Object.values(GUIDELINES).forEach(c => {
|
|
35
|
-
expect(c.kind).toBe('check');
|
|
36
|
-
expect(c.level).toBe('guideline');
|
|
37
31
|
});
|
|
38
32
|
});
|
|
39
33
|
|
|
40
|
-
it('prompt
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expect(c
|
|
44
|
-
expect(c
|
|
34
|
+
it('prompt 面字段已删除(promptInjection / injectPrompt / appliesTo 不存在)', () => {
|
|
35
|
+
Object.values(CONSTRAINTS).forEach(c => {
|
|
36
|
+
expect('promptInjection' in c).toBe(false);
|
|
37
|
+
expect('injectPrompt' in c).toBe(false);
|
|
38
|
+
expect('appliesTo' in c).toBe(false);
|
|
45
39
|
});
|
|
46
40
|
});
|
|
47
41
|
|
|
@@ -78,20 +72,48 @@ describe('Constraint System', () => {
|
|
|
78
72
|
}
|
|
79
73
|
});
|
|
80
74
|
|
|
81
|
-
it('
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
it('harness#174 删除的 10 条不再存在', () => {
|
|
76
|
+
const removed = [
|
|
77
|
+
'incremental_progress',
|
|
78
|
+
'no_implementation_without_requirement',
|
|
79
|
+
'no_bypass_checkpoint',
|
|
80
|
+
'simplest_solution_first',
|
|
81
|
+
'no_simplification_without_approval',
|
|
82
|
+
'follow_conventions',
|
|
83
|
+
'first_principles_first',
|
|
84
|
+
'no_conflict_blending',
|
|
85
|
+
'no_performative_agreement',
|
|
86
|
+
'no_skill_without_test',
|
|
87
|
+
];
|
|
88
|
+
for (const id of removed) {
|
|
89
|
+
expect(getConstraint(id)).toBeUndefined();
|
|
90
|
+
expect(getConstraintCheck(id)).toBeUndefined();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('ADR-0029:prompt 类 9 条随文本注入层关停删除', () => {
|
|
95
|
+
const removed = [
|
|
96
|
+
'no_fuzzy_completion_claim',
|
|
97
|
+
'no_fix_without_root_cause',
|
|
98
|
+
'no_code_without_test',
|
|
99
|
+
'fix_the_problem_not_the_gate',
|
|
100
|
+
'verify_external_capability',
|
|
101
|
+
'no_delete_without_context',
|
|
102
|
+
'design_decision_requires_discussion',
|
|
103
|
+
'surgical_changes_only',
|
|
104
|
+
'no_model_for_deterministic',
|
|
105
|
+
];
|
|
106
|
+
for (const id of removed) {
|
|
107
|
+
expect(getConstraint(id)).toBeUndefined();
|
|
108
|
+
expect(getConstraintCheck(id)).toBeUndefined();
|
|
109
|
+
}
|
|
84
110
|
});
|
|
85
111
|
|
|
86
112
|
it('no_completion_without_verification 不硬编码具体命令示例(#25:口径由项目声明)', () => {
|
|
87
|
-
const law =
|
|
88
|
-
expect(law.promptInjection).not.toMatch(/npm test|npm run build/);
|
|
113
|
+
const law = CONSTRAINTS['no_completion_without_verification'];
|
|
89
114
|
expect(law.description).not.toMatch(/npm test|npm run build/);
|
|
90
|
-
expect(law.promptInjection).not.toContain('完整');
|
|
91
115
|
expect(law.description).not.toContain('完整');
|
|
92
|
-
expect(law.promptInjection).toContain('项目声明的测试');
|
|
93
116
|
expect(law.description).toContain('项目声明的测试');
|
|
94
|
-
expect(law.promptInjection).toContain('不得凭记忆声称完成');
|
|
95
117
|
});
|
|
96
118
|
});
|
|
97
119
|
|
|
@@ -107,12 +129,6 @@ describe('Constraint System', () => {
|
|
|
107
129
|
const checkCount = getAllConstraints().filter(c => c.kind === 'check').length;
|
|
108
130
|
expect(registeredCheckCount()).toBe(checkCount);
|
|
109
131
|
});
|
|
110
|
-
|
|
111
|
-
it('prompt 约束不注册 checker', () => {
|
|
112
|
-
for (const c of Object.values(PROMPTS)) {
|
|
113
|
-
expect(getConstraintCheck(c.id)).toBeUndefined();
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
132
|
});
|
|
117
133
|
|
|
118
134
|
describe('Helper Functions', () => {
|
|
@@ -122,10 +138,10 @@ describe('Constraint System', () => {
|
|
|
122
138
|
});
|
|
123
139
|
|
|
124
140
|
it('should get single constraint by id', () => {
|
|
125
|
-
const constraint = getConstraint('
|
|
141
|
+
const constraint = getConstraint('no_completion_without_verification');
|
|
126
142
|
expect(constraint).toBeDefined();
|
|
127
|
-
expect(constraint?.kind).toBe('
|
|
128
|
-
expect(constraint?.
|
|
143
|
+
expect(constraint?.kind).toBe('check');
|
|
144
|
+
expect(constraint?.severity).toBe('error');
|
|
129
145
|
});
|
|
130
146
|
|
|
131
147
|
it('should return undefined for unknown constraint', () => {
|
|
@@ -147,16 +163,7 @@ describe('Constraint Checker', () => {
|
|
|
147
163
|
};
|
|
148
164
|
|
|
149
165
|
const result = constraintChecker.findApplicableConstraints(context);
|
|
150
|
-
expect(result.
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('prompt 约束 check() 短路 satisfied,不查注册表', async () => {
|
|
154
|
-
const context: ConstraintContext = {
|
|
155
|
-
operation: 'code_implementation',
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const result = await constraintChecker.check(PROMPTS['no_fix_without_root_cause'], context);
|
|
159
|
-
expect(result.satisfied).toBe(true);
|
|
166
|
+
expect(result.errors.length + result.warnings.length).toBeGreaterThan(0);
|
|
160
167
|
});
|
|
161
168
|
|
|
162
169
|
it('kind=check 但未注册 checker 的约束应抛错(不许静默 pass)', async () => {
|
|
@@ -169,7 +176,7 @@ describe('Constraint Checker', () => {
|
|
|
169
176
|
{
|
|
170
177
|
id: 'ghost_check_constraint',
|
|
171
178
|
kind: 'check',
|
|
172
|
-
|
|
179
|
+
severity: 'warning',
|
|
173
180
|
rule: 'GHOST',
|
|
174
181
|
message: 'test',
|
|
175
182
|
trigger: 'code_implementation',
|
|
@@ -189,66 +196,40 @@ describe('Constraint Checker', () => {
|
|
|
189
196
|
};
|
|
190
197
|
|
|
191
198
|
const result = await constraintChecker.checkConstraints(context);
|
|
192
|
-
expect(result.
|
|
199
|
+
expect(result.errors.length + result.warnings.length).toBeGreaterThan(0);
|
|
193
200
|
});
|
|
194
201
|
|
|
195
|
-
it('should skip
|
|
202
|
+
it('should skip no_completion_without_verification when hasVerificationEvidence is undefined(未接线不评估)', async () => {
|
|
196
203
|
const context: ConstraintContext = {
|
|
197
204
|
operation: 'code_implementation',
|
|
198
205
|
};
|
|
199
206
|
|
|
200
|
-
const result = await constraintChecker.check(
|
|
207
|
+
const result = await constraintChecker.check(CONSTRAINTS['no_completion_without_verification'], context);
|
|
201
208
|
expect(result.skipped).toBe(true);
|
|
202
209
|
expect(result.satisfied).toBe(true);
|
|
203
210
|
});
|
|
204
211
|
|
|
205
|
-
it('should pass
|
|
212
|
+
it('should pass no_completion_without_verification when hasVerificationEvidence is true', async () => {
|
|
206
213
|
const context: ConstraintContext = {
|
|
207
214
|
operation: 'code_implementation',
|
|
208
|
-
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const result = await constraintChecker.check(IRON_LAWS['incremental_progress'], context);
|
|
212
|
-
expect(result.satisfied).toBe(true);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should skip no_implementation_without_requirement when hasRequirement is undefined(未接线不评估)', async () => {
|
|
216
|
-
const context: ConstraintContext = {
|
|
217
|
-
operation: 'code_implementation',
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const result = await constraintChecker.check(IRON_LAWS['no_implementation_without_requirement'], context);
|
|
221
|
-
expect(result.skipped).toBe(true);
|
|
222
|
-
expect(result.satisfied).toBe(true);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('should pass no_implementation_without_requirement when hasRequirement is true', async () => {
|
|
226
|
-
const context: ConstraintContext = {
|
|
227
|
-
operation: 'code_implementation',
|
|
228
|
-
hasRequirement: true,
|
|
215
|
+
hasVerificationEvidence: true,
|
|
229
216
|
};
|
|
230
217
|
|
|
231
|
-
const result = await constraintChecker.check(
|
|
218
|
+
const result = await constraintChecker.check(CONSTRAINTS['no_completion_without_verification'], context);
|
|
232
219
|
expect(result.satisfied).toBe(true);
|
|
233
220
|
});
|
|
234
221
|
});
|
|
235
222
|
|
|
236
|
-
describe('Constraint
|
|
237
|
-
it('
|
|
238
|
-
|
|
239
|
-
expect(
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should have correct level for guidelines', () => {
|
|
244
|
-
Object.values(GUIDELINES).forEach(guideline => {
|
|
245
|
-
expect(guideline.level).toBe('guideline');
|
|
223
|
+
describe('Constraint Severity', () => {
|
|
224
|
+
it('error 级约束 severity 均为 error', () => {
|
|
225
|
+
['no_completion_without_verification', 'no_test_simplification', 'docs_freshness'].forEach(id => {
|
|
226
|
+
expect(CONSTRAINTS[id].severity).toBe('error');
|
|
246
227
|
});
|
|
247
228
|
});
|
|
248
229
|
|
|
249
|
-
it('
|
|
250
|
-
|
|
251
|
-
expect(
|
|
230
|
+
it('warning 级约束 severity 均为 warning', () => {
|
|
231
|
+
['no_hardcoded_credentials', 'capability_sync', 'context_doc_sync', 'governance_presence'].forEach(id => {
|
|
232
|
+
expect(CONSTRAINTS[id].severity).toBe('warning');
|
|
252
233
|
});
|
|
253
234
|
});
|
|
254
235
|
});
|
|
@@ -30,7 +30,7 @@ describe('PassesGate.check()', () => {
|
|
|
30
30
|
expect(result.violations).toBeDefined();
|
|
31
31
|
expect(result.violations?.length).toBe(1);
|
|
32
32
|
expect(result.violations?.[0]?.id).toBe('no_self_approval');
|
|
33
|
-
expect(result.violations?.[0]?.
|
|
33
|
+
expect(result.violations?.[0]?.severity).toBe('error');
|
|
34
34
|
expect(result.testResult).toEqual(testResult);
|
|
35
35
|
});
|
|
36
36
|
|
|
@@ -47,7 +47,7 @@ describe('PassesGate.check()', () => {
|
|
|
47
47
|
expect(result.violations).toBeDefined();
|
|
48
48
|
expect(result.violations?.length).toBe(1);
|
|
49
49
|
expect(result.violations?.[0]?.id).toBe('no_completion_without_verification');
|
|
50
|
-
expect(result.violations?.[0]?.
|
|
50
|
+
expect(result.violations?.[0]?.severity).toBe('error');
|
|
51
51
|
expect(result.testResult).toEqual(testResult);
|
|
52
52
|
});
|
|
53
53
|
|