phasegate 0.191.0 → 0.222.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 +15 -0
- package/README.ja.md +52 -15
- package/README.md +39 -11
- package/docs/ADR/030-injection-threat-model-and-trust-root.md +145 -0
- package/docs/guide/hooks-integration.md +101 -1
- package/docs/guide/installation.md +1 -1
- package/docs/guide/quick-vs-full-mode.md +1 -1
- package/docs/guide/skills-overview.md +7 -8
- package/package.json +1 -1
- package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +131 -63
- package/scripts/harness/agent-integration/presentation/session-start-hook.ts +31 -4
- package/scripts/harness/agent-integration/presentation/spotlight.ts +65 -0
- package/scripts/harness/biome-ast-engine/application/mappers/build-harness-error-payload-output-mapper.ts +3 -3
- package/scripts/harness/biome-ast-engine/infrastructure/mappers/rule-violation-code-mapper.ts +3 -3
- package/scripts/harness/biome-ast-engine/presentation/cli/harness-lint-command-handler.ts +6 -4
- package/scripts/harness/ci-governance/application/dto/pin-integrity-input.ts +8 -0
- package/scripts/harness/ci-governance/application/dto/pin-integrity-output.ts +9 -0
- package/scripts/harness/ci-governance/application/dto/verify-integrity-input.ts +7 -0
- package/scripts/harness/ci-governance/application/dto/verify-integrity-output.ts +10 -0
- package/scripts/harness/ci-governance/application/usecases/pin-integrity-usecase.ts +60 -0
- package/scripts/harness/ci-governance/application/usecases/verify-integrity-usecase.ts +46 -0
- package/scripts/harness/ci-governance/composition-root.ts +67 -64
- package/scripts/harness/ci-governance/domain/ports/integrity-manifest-repository-port.ts +14 -0
- package/scripts/harness/ci-governance/domain/ports/sha256-hasher-port.ts +10 -0
- package/scripts/harness/ci-governance/domain/services/integrity-checker.ts +42 -0
- package/scripts/harness/ci-governance/domain/value-objects/integrity-drift.ts +16 -0
- package/scripts/harness/ci-governance/domain/value-objects/integrity-manifest.ts +49 -0
- package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +40 -0
- package/scripts/harness/ci-governance/infrastructure/adapters/file-system-sha256-hasher-adapter.ts +17 -0
- package/scripts/harness/ci-governance/infrastructure/adapters/harness-api-command-existence-adapter.ts +7 -73
- package/scripts/harness/ci-governance/infrastructure/adapters/integrity-manifest-json-repository-adapter.ts +83 -0
- package/scripts/harness/ci-governance/presentation/handlers/integrity-handler.ts +76 -0
- package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +60 -28
- package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +33 -8
- package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +90 -0
- package/scripts/harness/harness-error/infrastructure/registry/l1-error-definitions.ts +9 -9
- package/scripts/harness/installation/application/bundled-skill-selection.ts +2 -5
- package/scripts/harness/installation/application/usecases/run-reconcile.ts +69 -1
- package/scripts/harness/main.ts +257 -105
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +65 -3
- package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +44 -40
- package/scripts/harness/setup/skill-deployer.ts +2 -4
- package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +82 -49
- package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +133 -53
- package/scripts/harness/validator-system/composition-root.ts +153 -99
- package/scripts/harness/validator-system/domain/ports/coverage-attestation-gating-policy-port.ts +14 -0
- package/scripts/harness/validator-system/domain/ports/coverage-attestation-verification-policy-port.ts +30 -0
- package/scripts/harness/validator-system/domain/ports/injection-scan-policy-port.ts +14 -0
- package/scripts/harness/validator-system/domain/services/coverage-attestation-gating-service.ts +56 -0
- package/scripts/harness/validator-system/domain/services/coverage-attestation-verification-service.ts +45 -0
- package/scripts/harness/validator-system/domain/services/injection-pattern-scan-service.ts +118 -0
- package/scripts/harness/validator-system/domain/value-objects/attestation-verification-report.ts +59 -0
- package/scripts/harness/validator-system/domain/value-objects/coverage-gating-report.ts +67 -0
- package/scripts/harness/validator-system/domain/value-objects/injection-scan-report.ts +55 -0
- package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +37 -31
- package/scripts/harness/validator-system/infrastructure/adapters/adr-foundation-reference-adapter.ts +13 -7
- package/scripts/harness/validator-system/infrastructure/adapters/file-system-coverage-attestation-gating-adapter.ts +87 -0
- package/scripts/harness/validator-system/infrastructure/adapters/file-system-coverage-attestation-verification-adapter.ts +165 -0
- package/scripts/harness/validator-system/infrastructure/adapters/file-system-injection-scan-adapter.ts +82 -0
- package/skills/README.md +1 -1
- package/skills/codebase-mapper/SKILL.md +1 -1
- package/skills/consistency-checker/references//343/203/201/343/202/247/343/203/203/343/202/257/343/203/252/343/202/271/343/203/210.md +1 -1
- package/skills/doc-health-checker/SKILL.md +148 -0
- package/skills/release-publisher/SKILL.md +101 -0
- package/skills/skill-creator/SKILL.md +74 -332
- package/skills/story-implementor/SKILL.md +52 -0
- package/skills/story-mapper/SKILL.md +4 -0
- package/skills/story-writer/SKILL.md +9 -0
- package/skills/uiux-designer/references/uiux-design-template.md +4 -4
- package/skills/unit-designer/SKILL.md +3 -1
- package/templates/.claude/scripts/deny-check.sh +260 -0
- package/skills/doc-freshness-checker/SKILL.md +0 -140
- package/skills/implementation-planner/SKILL.md +0 -169
- package/skills/implementation-planner/references/document-structure.md +0 -116
- package/skills/implementation-planner/references/plan-template.md +0 -177
- package/skills/implementation-planner/references/workflow.md +0 -164
- package/skills/pointer-validator/SKILL.md +0 -105
|
@@ -5,24 +5,33 @@
|
|
|
5
5
|
*
|
|
6
6
|
* RunL3ValidatorsUseCase — H08-02: L3バリデータ実行
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import type {
|
|
14
|
-
import type {
|
|
15
|
-
import type {
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
|
|
9
|
+
import type { AcBoundCoveragePolicyPort } from "../../domain/ports/ac-bound-coverage-policy-port.js";
|
|
10
|
+
import type { AcCoveragePolicyPort } from "../../domain/ports/ac-coverage-policy-port.js";
|
|
11
|
+
import type { CoverageAttestationVerificationPolicyPort } from "../../domain/ports/coverage-attestation-verification-policy-port.js";
|
|
12
|
+
import type { InjectionScanPolicyPort } from "../../domain/ports/injection-scan-policy-port.js";
|
|
13
|
+
import type { PerformanceScannerPort } from "../../domain/ports/performance-scanner-port.js";
|
|
14
|
+
import type { SecurityPatternScannerPort } from "../../domain/ports/security-pattern-scanner-port.js";
|
|
15
|
+
import type { ValidatorConfigPort } from "../../domain/ports/validator-config-port.js";
|
|
16
|
+
import { CoverageAttestationVerificationService } from "../../domain/services/coverage-attestation-verification-service.js";
|
|
17
|
+
import { InjectionPatternScanService } from "../../domain/services/injection-pattern-scan-service.js";
|
|
18
|
+
import {
|
|
19
|
+
ValidatorExecutionError,
|
|
20
|
+
type ValidatorExecutionService,
|
|
21
|
+
} from "../../domain/services/validator-execution-service.js";
|
|
22
|
+
import { ValidatorLanguageCapabilityService } from "../../domain/services/validator-language-capability-service.js";
|
|
23
|
+
import type { ValidatorRegistry } from "../../domain/services/validator-registry.js";
|
|
24
|
+
import type { HarnessErrorLike } from "../../domain/value-objects/validation-result.js";
|
|
25
|
+
import { ValidationResult } from "../../domain/value-objects/validation-result.js";
|
|
26
|
+
import { ValidatorId } from "../../domain/value-objects/validator-id.js";
|
|
27
|
+
import type { RunL3ValidatorsInput } from "../dto/run-l3-validators-input.js";
|
|
28
|
+
import type { ValidationResultContract } from "../dto/validation-result-contract.js";
|
|
29
|
+
import type { ValidationResultContractMapper } from "../mappers/validation-result-contract-mapper.js";
|
|
21
30
|
|
|
22
31
|
export class CoverageReportNotFoundError extends Error {
|
|
23
32
|
constructor(path: string) {
|
|
24
33
|
super(`Coverage report not found: ${path}`);
|
|
25
|
-
this.name =
|
|
34
|
+
this.name = "CoverageReportNotFoundError";
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
|
|
@@ -33,9 +42,18 @@ export interface RunL3ValidatorsUseCaseDeps {
|
|
|
33
42
|
contractMapper: ValidationResultContractMapper;
|
|
34
43
|
acCoveragePolicyPort?: AcCoveragePolicyPort;
|
|
35
44
|
acBoundCoveragePolicyPort?: AcBoundCoveragePolicyPort;
|
|
36
|
-
coverageReportPort?: {
|
|
45
|
+
coverageReportPort?: {
|
|
46
|
+
getCoverage(): Promise<{
|
|
47
|
+
overallCoverage: number;
|
|
48
|
+
perFileCoverage: readonly { filePath: string; coverage: number }[];
|
|
49
|
+
}>;
|
|
50
|
+
};
|
|
37
51
|
securityScannerPort?: SecurityPatternScannerPort;
|
|
38
52
|
performanceScannerPort?: PerformanceScannerPort;
|
|
53
|
+
/** WI-259 / ADR-030 §Decision.3.④: L3-006 (injection-scan, advisory) 用ポート。 */
|
|
54
|
+
injectionScanPolicyPort?: InjectionScanPolicyPort;
|
|
55
|
+
/** WI-268 / ADR-030 §Decision.1・§Decision.3.② 第2段: L3-007 (coverage-attestation-verification, fail-closed) 用ポート。 */
|
|
56
|
+
coverageAttestationVerificationPolicyPort?: CoverageAttestationVerificationPolicyPort;
|
|
39
57
|
/** L3-005 のスコープ対象 story-id(config layers.L3.acBoundStories 由来。既定 [])。 */
|
|
40
58
|
acBoundStories?: readonly string[];
|
|
41
59
|
}
|
|
@@ -47,11 +65,15 @@ export class RunL3ValidatorsUseCase {
|
|
|
47
65
|
private readonly mapper: ValidationResultContractMapper;
|
|
48
66
|
private readonly acCoveragePolicyPort?: AcCoveragePolicyPort;
|
|
49
67
|
private readonly acBoundCoveragePolicyPort?: AcBoundCoveragePolicyPort;
|
|
50
|
-
private readonly coverageReportPort?: RunL3ValidatorsUseCaseDeps[
|
|
68
|
+
private readonly coverageReportPort?: RunL3ValidatorsUseCaseDeps["coverageReportPort"];
|
|
51
69
|
private readonly securityScannerPort?: SecurityPatternScannerPort;
|
|
52
70
|
private readonly performanceScannerPort?: PerformanceScannerPort;
|
|
71
|
+
private readonly injectionScanPolicyPort?: InjectionScanPolicyPort;
|
|
72
|
+
private readonly coverageAttestationVerificationPolicyPort?: CoverageAttestationVerificationPolicyPort;
|
|
53
73
|
private readonly acBoundStories: readonly string[];
|
|
54
74
|
private readonly languageCapabilityService = new ValidatorLanguageCapabilityService();
|
|
75
|
+
private readonly injectionScanService = new InjectionPatternScanService();
|
|
76
|
+
private readonly coverageAttestationVerificationService = new CoverageAttestationVerificationService();
|
|
55
77
|
|
|
56
78
|
constructor(deps: RunL3ValidatorsUseCaseDeps) {
|
|
57
79
|
this.registry = deps.validatorRegistry;
|
|
@@ -63,6 +85,8 @@ export class RunL3ValidatorsUseCase {
|
|
|
63
85
|
this.coverageReportPort = deps.coverageReportPort;
|
|
64
86
|
this.securityScannerPort = deps.securityScannerPort;
|
|
65
87
|
this.performanceScannerPort = deps.performanceScannerPort;
|
|
88
|
+
this.injectionScanPolicyPort = deps.injectionScanPolicyPort;
|
|
89
|
+
this.coverageAttestationVerificationPolicyPort = deps.coverageAttestationVerificationPolicyPort;
|
|
66
90
|
this.acBoundStories = deps.acBoundStories ?? [];
|
|
67
91
|
}
|
|
68
92
|
|
|
@@ -71,16 +95,19 @@ export class RunL3ValidatorsUseCase {
|
|
|
71
95
|
if (input.validatorIds && input.validatorIds.length > 0) {
|
|
72
96
|
validatorIds = input.validatorIds.map((id) => ValidatorId.create(id));
|
|
73
97
|
} else {
|
|
74
|
-
validatorIds = this.registry.listByLayer(
|
|
98
|
+
validatorIds = this.registry.listByLayer("L3").map((d) => d.validatorId);
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
const definitions = this.registry.select(validatorIds);
|
|
78
102
|
|
|
79
|
-
let layerConfig
|
|
103
|
+
let layerConfig: Awaited<ReturnType<ValidatorConfigPort["getLayerConfig"]>>;
|
|
80
104
|
try {
|
|
81
|
-
layerConfig = await this.configPort.getLayerConfig(
|
|
105
|
+
layerConfig = await this.configPort.getLayerConfig("L3");
|
|
82
106
|
} catch (err) {
|
|
83
|
-
throw new ValidatorExecutionError(
|
|
107
|
+
throw new ValidatorExecutionError(
|
|
108
|
+
`Failed to get L3 LayerConfig: ${err instanceof Error ? err.message : String(err)}`,
|
|
109
|
+
err,
|
|
110
|
+
);
|
|
84
111
|
}
|
|
85
112
|
|
|
86
113
|
// LayerConfig.enabled === false の場合は空を返す
|
|
@@ -105,18 +132,17 @@ export class RunL3ValidatorsUseCase {
|
|
|
105
132
|
// このブロックは例外を送出せず、L3-003 の per-validator 結果のみを差し替える。
|
|
106
133
|
// これにより兄弟バリデータ(L3-001/002/004 および L2/L4 バッチ)は常に通常実行される。
|
|
107
134
|
const l3003InScope =
|
|
108
|
-
!unsupportedValidatorIds.has(
|
|
109
|
-
definitions.some((d) => d.validatorId.value === 'L3-003');
|
|
135
|
+
!unsupportedValidatorIds.has("L3-003") && definitions.some((d) => d.validatorId.value === "L3-003");
|
|
110
136
|
if (this.coverageReportPort && l3003InScope) {
|
|
111
|
-
const l3003Id = ValidatorId.create(
|
|
112
|
-
const threshold = layerConfig.getThreshold(
|
|
137
|
+
const l3003Id = ValidatorId.create("L3-003");
|
|
138
|
+
const threshold = layerConfig.getThreshold("coverageThreshold");
|
|
113
139
|
|
|
114
140
|
if (threshold === null) {
|
|
115
141
|
overrideMap.set(
|
|
116
|
-
|
|
142
|
+
"L3-003",
|
|
117
143
|
ValidationResult.skipWithReason(
|
|
118
144
|
l3003Id,
|
|
119
|
-
|
|
145
|
+
"coverageThreshold が未設定のためカバレッジ判定をスキップ(カバレッジゲートはオプトイン)",
|
|
120
146
|
),
|
|
121
147
|
);
|
|
122
148
|
} else {
|
|
@@ -124,13 +150,13 @@ export class RunL3ValidatorsUseCase {
|
|
|
124
150
|
const coverageData = await this.coverageReportPort.getCoverage();
|
|
125
151
|
if (coverageData.overallCoverage < threshold) {
|
|
126
152
|
overrideMap.set(
|
|
127
|
-
|
|
153
|
+
"L3-003",
|
|
128
154
|
ValidationResult.fail(
|
|
129
155
|
l3003Id,
|
|
130
156
|
[
|
|
131
157
|
{
|
|
132
|
-
code:
|
|
133
|
-
severity:
|
|
158
|
+
code: "L3-003",
|
|
159
|
+
severity: "error",
|
|
134
160
|
message: `カバレッジ不足: 現在値 ${coverageData.overallCoverage}%、不足 ${threshold - coverageData.overallCoverage}%`,
|
|
135
161
|
suggestion: `テストカバレッジを ${threshold}% 以上に引き上げてください`,
|
|
136
162
|
},
|
|
@@ -139,20 +165,20 @@ export class RunL3ValidatorsUseCase {
|
|
|
139
165
|
),
|
|
140
166
|
);
|
|
141
167
|
} else {
|
|
142
|
-
overrideMap.set(
|
|
168
|
+
overrideMap.set("L3-003", ValidationResult.pass(l3003Id, 0));
|
|
143
169
|
}
|
|
144
170
|
} catch {
|
|
145
171
|
// レポート不在などで取得失敗 → FAIL-CLOSED(例外は握りつぶし per-validator FAIL に変換)
|
|
146
172
|
overrideMap.set(
|
|
147
|
-
|
|
173
|
+
"L3-003",
|
|
148
174
|
ValidationResult.fail(
|
|
149
175
|
l3003Id,
|
|
150
176
|
[
|
|
151
177
|
{
|
|
152
|
-
code:
|
|
153
|
-
severity:
|
|
178
|
+
code: "L3-003",
|
|
179
|
+
severity: "error",
|
|
154
180
|
message: `coverageThreshold=${threshold}% が設定されていますがカバレッジレポートが見つかりません(テストをカバレッジ付きで実行してください)`,
|
|
155
|
-
suggestion:
|
|
181
|
+
suggestion: "vitest --coverage 等でカバレッジレポートを生成してから再実行してください",
|
|
156
182
|
},
|
|
157
183
|
],
|
|
158
184
|
0,
|
|
@@ -163,42 +189,35 @@ export class RunL3ValidatorsUseCase {
|
|
|
163
189
|
}
|
|
164
190
|
|
|
165
191
|
if (this.securityScannerPort) {
|
|
166
|
-
const l3001Result = overrideMap.get(
|
|
192
|
+
const l3001Result = overrideMap.get("L3-001");
|
|
167
193
|
if (l3001Result && !l3001Result.skipped) {
|
|
168
194
|
const scanResult = await this.securityScannerPort.scan(input.targetPaths);
|
|
169
195
|
if (!scanResult.passed) {
|
|
170
|
-
overrideMap.set(
|
|
196
|
+
overrideMap.set("L3-001", ValidationResult.fail(ValidatorId.create("L3-001"), [...scanResult.findings], 0));
|
|
171
197
|
}
|
|
172
198
|
}
|
|
173
199
|
}
|
|
174
200
|
|
|
175
201
|
if (this.performanceScannerPort) {
|
|
176
|
-
const l3002Result = overrideMap.get(
|
|
202
|
+
const l3002Result = overrideMap.get("L3-002");
|
|
177
203
|
if (l3002Result && !l3002Result.skipped) {
|
|
178
|
-
const bundleSizeLimit = layerConfig.getThreshold(
|
|
204
|
+
const bundleSizeLimit = layerConfig.getThreshold("bundleSizeLimit");
|
|
179
205
|
const thresholds: Record<string, number> = bundleSizeLimit !== null ? { bundleSizeLimit } : {};
|
|
180
206
|
const scanResult = await this.performanceScannerPort.scan(input.targetPaths, thresholds);
|
|
181
207
|
if (!scanResult.passed) {
|
|
182
|
-
overrideMap.set(
|
|
208
|
+
overrideMap.set("L3-002", ValidationResult.fail(ValidatorId.create("L3-002"), [...scanResult.findings], 0));
|
|
183
209
|
}
|
|
184
210
|
}
|
|
185
211
|
}
|
|
186
212
|
|
|
187
213
|
if (this.acCoveragePolicyPort) {
|
|
188
|
-
const l3004Result = overrideMap.get(
|
|
214
|
+
const l3004Result = overrideMap.get("L3-004");
|
|
189
215
|
if (l3004Result && !l3004Result.skipped) {
|
|
190
216
|
const policyResult = await this.acCoveragePolicyPort.checkCoverage({
|
|
191
217
|
matrixFilePath: input.requirementMatrixPath,
|
|
192
218
|
});
|
|
193
219
|
if (!policyResult.passed) {
|
|
194
|
-
overrideMap.set(
|
|
195
|
-
'L3-004',
|
|
196
|
-
ValidationResult.fail(
|
|
197
|
-
ValidatorId.create('L3-004'),
|
|
198
|
-
[...policyResult.errors],
|
|
199
|
-
0,
|
|
200
|
-
),
|
|
201
|
-
);
|
|
220
|
+
overrideMap.set("L3-004", ValidationResult.fail(ValidatorId.create("L3-004"), [...policyResult.errors], 0));
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
223
|
}
|
|
@@ -206,21 +225,82 @@ export class RunL3ValidatorsUseCase {
|
|
|
206
225
|
// L3-005: AC-bound coverage(fail-closed, default-OFF)。
|
|
207
226
|
// override map に unskipped な L3-005 がある場合のみ policy を呼ぶ(L3-004 と同じ方式)。
|
|
208
227
|
if (this.acBoundCoveragePolicyPort) {
|
|
209
|
-
const l3005Result = overrideMap.get(
|
|
228
|
+
const l3005Result = overrideMap.get("L3-005");
|
|
210
229
|
if (l3005Result && !l3005Result.skipped) {
|
|
211
230
|
const policyResult = await this.acBoundCoveragePolicyPort.checkAcBoundCoverage({
|
|
212
231
|
matrixFilePath: input.requirementMatrixPath,
|
|
213
232
|
acBoundStories: input.acBoundStories ?? this.acBoundStories,
|
|
214
233
|
});
|
|
215
234
|
if (!policyResult.passed) {
|
|
235
|
+
overrideMap.set("L3-005", ValidationResult.fail(ValidatorId.create("L3-005"), [...policyResult.errors], 0));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// WI-259 / ADR-030 §Decision.3.④: L3-006 advisory インジェクションスキャナ。
|
|
241
|
+
// 指示搭載ファイルの既知インジェクションパターンを検出し warning-only の finding として報告する。
|
|
242
|
+
// finding は必ず severity=warning のため ADR-017 集約規則(failOnWarning=false 既定)で overall PASS。
|
|
243
|
+
// blocking にしない(§4.(b): 「すり抜け=安全」の誤信頼を避ける)。default-OFF/skip 時は override しない。
|
|
244
|
+
if (this.injectionScanPolicyPort) {
|
|
245
|
+
const l3006Result = overrideMap.get("L3-006");
|
|
246
|
+
if (l3006Result && !l3006Result.skipped) {
|
|
247
|
+
const targets = await this.injectionScanPolicyPort.collect();
|
|
248
|
+
const report = this.injectionScanService.scan(targets);
|
|
249
|
+
if (report.hasFindings()) {
|
|
250
|
+
const errors: HarnessErrorLike[] = report.findings.map((finding) => ({
|
|
251
|
+
code: { value: "L3-006", toString: () => "L3-006" },
|
|
252
|
+
severity: { value: "warning", toString: () => "warning" },
|
|
253
|
+
message: `${finding.sourcePath}:${finding.lineNumber} [${finding.kind}] ${finding.message}`,
|
|
254
|
+
suggestion: finding.suggestion,
|
|
255
|
+
sourcePath: finding.sourcePath,
|
|
256
|
+
}));
|
|
257
|
+
overrideMap.set("L3-006", ValidationResult.fail(ValidatorId.create("L3-006"), errors, 0));
|
|
258
|
+
} else {
|
|
259
|
+
overrideMap.set("L3-006", ValidationResult.pass(ValidatorId.create("L3-006"), 0));
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// WI-268 / ADR-030 §Decision.1・§Decision.3.② 第2段: L3-007 coverage-attestation-verification。
|
|
265
|
+
// coverage_report の @attestation 参照を requirement-test-matrix に突合し、解決不能な参照
|
|
266
|
+
// (空手形の attestation)を fail-closed の error として遮断する(L2-016 の authoritative 相棒)。
|
|
267
|
+
// 参照ありで matrix を読めなければ fail-closed で FAIL。default-OFF/skip 時は override しない。
|
|
268
|
+
if (this.coverageAttestationVerificationPolicyPort) {
|
|
269
|
+
const l3007Result = overrideMap.get("L3-007");
|
|
270
|
+
if (l3007Result && !l3007Result.skipped) {
|
|
271
|
+
const l3007Id = ValidatorId.create("L3-007");
|
|
272
|
+
const collected = await this.coverageAttestationVerificationPolicyPort.collect();
|
|
273
|
+
if (collected.matrixError !== null) {
|
|
216
274
|
overrideMap.set(
|
|
217
|
-
|
|
275
|
+
"L3-007",
|
|
218
276
|
ValidationResult.fail(
|
|
219
|
-
|
|
220
|
-
[
|
|
277
|
+
l3007Id,
|
|
278
|
+
[
|
|
279
|
+
{
|
|
280
|
+
code: { value: "L3-007", toString: () => "L3-007" },
|
|
281
|
+
severity: { value: "error", toString: () => "error" },
|
|
282
|
+
message: collected.matrixError,
|
|
283
|
+
suggestion:
|
|
284
|
+
".harness/requirement-test-matrix.json を生成してください(phasegate:generate-matrix)。パスは config の layers.L3.requirementMatrixPath で変更できます。",
|
|
285
|
+
},
|
|
286
|
+
],
|
|
221
287
|
0,
|
|
222
288
|
),
|
|
223
289
|
);
|
|
290
|
+
} else {
|
|
291
|
+
const report = this.coverageAttestationVerificationService.verify(collected.references, collected.evidence);
|
|
292
|
+
if (report.hasFindings()) {
|
|
293
|
+
const errors: HarnessErrorLike[] = report.findings.map((finding) => ({
|
|
294
|
+
code: { value: "L3-007", toString: () => "L3-007" },
|
|
295
|
+
severity: { value: "error", toString: () => "error" },
|
|
296
|
+
message: finding.message,
|
|
297
|
+
suggestion: finding.suggestion,
|
|
298
|
+
sourcePath: finding.sourcePath,
|
|
299
|
+
}));
|
|
300
|
+
overrideMap.set("L3-007", ValidationResult.fail(l3007Id, errors, 0));
|
|
301
|
+
} else {
|
|
302
|
+
overrideMap.set("L3-007", ValidationResult.pass(l3007Id, 0));
|
|
303
|
+
}
|
|
224
304
|
}
|
|
225
305
|
}
|
|
226
306
|
}
|
|
@@ -232,6 +312,6 @@ export class RunL3ValidatorsUseCase {
|
|
|
232
312
|
}
|
|
233
313
|
|
|
234
314
|
private async getProjectLanguages(): Promise<readonly string[]> {
|
|
235
|
-
return this.configPort.getProjectLanguages ? await this.configPort.getProjectLanguages() : [
|
|
315
|
+
return this.configPort.getProjectLanguages ? await this.configPort.getProjectLanguages() : ["typescript"];
|
|
236
316
|
}
|
|
237
317
|
}
|