phasegate 0.133.0 → 0.134.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 +9 -0
- package/README.ja.md +1 -4
- package/README.md +1 -5
- package/docs/guide/configuration.md +0 -1
- package/docs/guide/layer-model.md +7 -7
- package/package.json +1 -1
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +0 -16
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +0 -16
- package/scripts/harness/main.ts +3 -3
- package/scripts/harness/validator-system/composition-root.ts +1 -14
- package/scripts/harness/validator-system/domain/ports/validator-config-port.ts +1 -1
- package/scripts/harness/validator-system/domain/services/validator-execution-service.ts +2 -2
- package/scripts/harness/validator-system/domain/services/validator-registry.ts +2 -2
- package/scripts/harness/validator-system/domain/value-objects/layer-config.ts +2 -2
- package/scripts/harness/validator-system/domain/value-objects/validator-definition.ts +5 -6
- package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +0 -2
- package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +1 -3
- package/scripts/harness/validator-system/presentation/handlers/run-validators-handler.ts +6 -35
- package/scripts/harness/validator-system/application/dto/run-l0-validators-input.ts +0 -9
- package/scripts/harness/validator-system/application/use-cases/run-l0-validators-usecase.ts +0 -60
package/CHANGELOG.md
CHANGED
|
@@ -7,15 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.134.0] - 2026-05-08
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **WI-034: L0 legacy validator (`L0-001` / `L0-002`) の撤去** — `validator-system` から FUSE 時代の未実装 validator 定義と `RunL0ValidatorsUseCase` を削除し、config schema / `phasegate.config.json` から `layers.L0` を撤去。`list-errors --layer L0` は空のままになり、`validate --layer L0` は runtime L0 が agent-integration hooks と Husky hooks で提供される旨の案内を表示して exit 0 で終了する。
|
|
15
|
+
- **Migration guide**: CI で `phasegate validate --layer L0` を実行していた場合、そのジョブは削除してください。L0 相当の防御は `.claude/settings.json` / `.codex/hooks.json` の runtime hook と `.husky/pre-commit` / `.husky/commit-msg` で有効化し、CI 側は `phasegate validate --layer L2` / `--layer L3` / `--layer L4` または `--layer all` に移行します。
|
|
16
|
+
|
|
10
17
|
## [0.133.0] - 2026-05-08
|
|
11
18
|
|
|
12
19
|
### Added
|
|
13
20
|
|
|
14
21
|
- **WI-095 — L4-001 drift-detect の design pointers 対応** — 設計見出し直下の `<!-- pointers: ... -->` / `<pointers>` block で実装ファイルpathを明示できるようにし、設計名とcode export名が異なる移行中ケースのfalse positiveを抑制。ADR-018でsyntaxとORセマンティクスを定義。
|
|
22
|
+
- **post-publish dogfood**: `/private/tmp/phasegate-dogfood-0.133.0` で `npx phasegate@0.133.0 phasegate:detect-drift --json` を実行。設計見出し `UserProfile` に `<!-- pointers: scripts/harness/sample-unit/domain/user-profile.ts -->` を付け、コード側は `export class UserProfileV2 {}` とした状態で `drifts: [] / totalCount: 0` を確認。
|
|
15
23
|
|
|
16
24
|
### Fixed
|
|
17
25
|
|
|
18
26
|
- **WI-096 — `phasegate:status` が `layers.L?.enabled` user override を表示に反映しない問題を修正** — status表示用のenabledLayersをpreset値と明示overrideから合成し、`strict + L4.enabled:false` / `minimal + L4.enabled:true` の双方に対応。
|
|
27
|
+
- **post-publish dogfood**: `npx phasegate@0.133.0 phasegate:status --json` で `project.preset: "minimal" + layers.L4.enabled: true` の L4 `enabled: true`、および `project.preset: "strict" + layers.L4.enabled: false` の L4 `enabled: false` を確認。
|
|
19
28
|
|
|
20
29
|
## [0.132.0] - 2026-05-08
|
|
21
30
|
|
package/README.ja.md
CHANGED
|
@@ -161,8 +161,6 @@ npx phasegate update-skills # スキルを最新版に再デプロイ
|
|
|
161
161
|
|
|
162
162
|
エラーは `HarnessError` 形式(理由 / ADR 参照 / 修正例)で返されるため、AI agent が自己修正できます。
|
|
163
163
|
|
|
164
|
-
> `--layer L0` の `L0-001` / `L0-002` は legacy validator で `enabled: false`。実体の L0 は agent-integration の hook と Husky です。
|
|
165
|
-
|
|
166
164
|
詳細: [5-Layer Defense Model](docs/guide/layer-model.md)
|
|
167
165
|
|
|
168
166
|
---
|
|
@@ -238,7 +236,7 @@ L2-STORY-REFLECTION バリデータがこのアノテーションを検出し、
|
|
|
238
236
|
"project": { "name": "my-project", "preset": "standard" },
|
|
239
237
|
"architecture": { "preset": "clean" },
|
|
240
238
|
"layers": {
|
|
241
|
-
"
|
|
239
|
+
"L1": { "enabled": true },
|
|
242
240
|
"L2": { "enabled": true }, "L3": { "enabled": true },
|
|
243
241
|
"L4": { "enabled": false }
|
|
244
242
|
},
|
|
@@ -456,7 +454,6 @@ reports/
|
|
|
456
454
|
| **[WI-031](docs/inception/_cross/WI-031/description.md)** | CI template の二系統統一 + `phasegate init --with-ci` |
|
|
457
455
|
| **[WI-032](docs/inception/_cross/WI-032/description.md)** | AGENTS.md / CLAUDE.md auto-refresh パイプライン |
|
|
458
456
|
| **[WI-033](docs/inception/_cross/WI-033/description.md)** | `doc-freshness` / `pointer-validation` を L4 validator に昇格 |
|
|
459
|
-
| **[WI-034](docs/inception/_cross/WI-034/description.md)** | L0 legacy validator (`L0-001` / `L0-002`) の撤去 |
|
|
460
457
|
|
|
461
458
|
L3 Nyquist Validation の `requirement-test-matrix.json` 自動生成はまだ未自動化です。現時点では手動セットアップで利用できます。
|
|
462
459
|
|
package/README.md
CHANGED
|
@@ -157,8 +157,6 @@ npx phasegate update-skills
|
|
|
157
157
|
| L3 | CI/CD pipeline | Security, performance, coverage (90%/95%), requirements traceability |
|
|
158
158
|
| L4 | Scheduled (weekly). Currently `layers.L4.enabled: false` by default — opt-in per project | Design-code drift, cross-document consistency, dead code, doc freshness, pointer validation |
|
|
159
159
|
|
|
160
|
-
> The `L0-001` / `L0-002` validators that appear in `list-errors --layer L0` output are legacy definitions from an earlier design and are disabled by default (`layers.L0.enabled: false`). The runtime L0 enforcement happens via the agent-integration hook scripts and Husky git hooks listed above, not via those validators.
|
|
161
|
-
|
|
162
160
|
---
|
|
163
161
|
|
|
164
162
|
## 28 Skills
|
|
@@ -339,7 +337,6 @@ For selection guidance and config examples see [Preset Selection Guide](docs/gui
|
|
|
339
337
|
{
|
|
340
338
|
"project": { "name": "my-project", "preset": "standard" },
|
|
341
339
|
"layers": {
|
|
342
|
-
"L0": { "enabled": false },
|
|
343
340
|
"L1": { "enabled": true },
|
|
344
341
|
"L2": { "enabled": true },
|
|
345
342
|
"L3": { "enabled": true },
|
|
@@ -468,7 +465,7 @@ npx phasegate <command> [options]
|
|
|
468
465
|
|---|---|
|
|
469
466
|
| `init --name <name>` | Initialize project, deploy skills, generate config |
|
|
470
467
|
| `lint` | Run L1 Biome AST checks |
|
|
471
|
-
| `validate --layer <
|
|
468
|
+
| `validate --layer <L2-L4\|all>` | Run validators for specified layer (`--layer L0` prints runtime hook guidance) |
|
|
472
469
|
| `ci-check` | Full CI check (L2-L4) |
|
|
473
470
|
| `update-skills` | Update skills to latest version |
|
|
474
471
|
| `phasegate:status` | Display overall harness health summary |
|
|
@@ -518,7 +515,6 @@ The main path is ready for project use, but a few documented behaviors still req
|
|
|
518
515
|
| **[WI-031](docs/inception/_cross/WI-031/description.md)** | CI template unification + `phasegate init --with-ci` | Today the bundled YAML and the `ci:generate-template` output diverge (different cron schedule, only the bundled one creates GitHub Issues). `phasegate init` does not deploy the workflow, so L4 only runs after the user manually copies the file. WI-031 unifies the two paths and adds an opt-in deploy flag. |
|
|
519
516
|
| **[WI-032](docs/inception/_cross/WI-032/description.md)** | AGENTS.md / CLAUDE.md auto-refresh pipeline | `ci:migrate-agents-md` exists as a one-shot CLI but there is no scheduled job, and CLAUDE.md is fully hand-maintained. WI-032 adds an `auto-refresh-agent-context` workflow plus a template-driven CLAUDE.md regenerator that preserves user-owned sections. |
|
|
520
517
|
| **[WI-033](docs/inception/_cross/WI-033/description.md)** | Promote `doc-freshness` / `pointer-validation` to L4 validators | Both capabilities exist as `p2:check-freshness` / `p2:validate-pointers` CLI commands but are not registered as L4 validators, so `validate --layer L4` skips them. WI-033 plumbs them through `validator-system` so they run via the standard L4 path and presets. |
|
|
521
|
-
| **[WI-034](docs/inception/_cross/WI-034/description.md)** | Retire legacy L0 validators (`L0-001` / `L0-002`) | The `fuse-hook-config` / `fuse-mount-status` validator IDs are leftovers from an earlier FUSE-based design. They are disabled by default and have no actual implementation behind them. WI-034 removes them and lets the agent-integration runtime hooks be the sole L0 surface. |
|
|
522
518
|
|
|
523
519
|
`requirement-test-matrix.json` auto-generation for L3 Nyquist Validation is not automated yet; see the L3 guide for the current manual setup.
|
|
524
520
|
|
|
@@ -15,7 +15,6 @@ This file is the **Single Source of Truth** for all quality configuration in a P
|
|
|
15
15
|
"preset": "standard" // "minimal" | "standard" | "strict"
|
|
16
16
|
},
|
|
17
17
|
"layers": {
|
|
18
|
-
"L0": { "enabled": false },
|
|
19
18
|
"L1": { "enabled": true },
|
|
20
19
|
"L2": { "enabled": true },
|
|
21
20
|
"L3": { "enabled": true },
|
|
@@ -52,13 +52,13 @@ Deployed by `phasegate init --with-husky` into `.husky/`.
|
|
|
52
52
|
| **.husky/pre-commit** | `npx phasegate pre-commit` | Runs L2 validators (phase-gate / metadata / story-reflection / test-quality) on staged files. Fails the commit on violation. |
|
|
53
53
|
| **.husky/commit-msg** | `npx phasegate commit-msg $1` | Enforces the `Work-Item: WI-XXX` trailer when WI directories or their contents are staged. Ensures every commit is traceable to a work item. |
|
|
54
54
|
|
|
55
|
-
### About
|
|
55
|
+
### About `validate --layer L0`
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
58
|
npx phasegate validate --layer L0
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
`
|
|
61
|
+
`validate --layer L0` is kept as a compatibility alias that prints guidance and exits successfully. Runtime L0 enforcement happens via the agent-runtime hooks and Husky git hooks above. `list-errors --layer L0` returns no validator definitions.
|
|
62
62
|
|
|
63
63
|
---
|
|
64
64
|
|
|
@@ -227,14 +227,14 @@ History: prior to v0.131.0, the aggregator's `failOnWarning` flag was effectivel
|
|
|
227
227
|
|
|
228
228
|
Presets control which layers are active. Choose based on project maturity and team discipline.
|
|
229
229
|
|
|
230
|
-
| Preset | L0
|
|
230
|
+
| Preset | L0 hooks | L1 | L2 | L3 | L4 |
|
|
231
231
|
|------------|-----|-----|-----|-----|-----|
|
|
232
|
-
| `minimal` |
|
|
233
|
-
| `standard` |
|
|
234
|
-
| `strict` |
|
|
232
|
+
| `minimal` | installed separately | on | on | off | off |
|
|
233
|
+
| `standard` | installed separately | on | on | on | off |
|
|
234
|
+
| `strict` | installed separately | on | on | on | on |
|
|
235
235
|
|
|
236
236
|
- **minimal** — Suitable for early prototyping. Editor-time rules and pre-commit checks only.
|
|
237
237
|
- **standard** — Recommended for active development. Adds CI/CD validators for security, performance, coverage, and traceability.
|
|
238
|
-
- **strict** — Full defense. Enables
|
|
238
|
+
- **strict** — Full defense. Enables scheduled drift detection (L4). Runtime L0 hooks are configured through the agent and Husky hook files, not through validator presets.
|
|
239
239
|
|
|
240
240
|
Presets are configured in `phasegate.config.json`, the single source of truth for all quality settings.
|
package/package.json
CHANGED
package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json
CHANGED
|
@@ -68,22 +68,6 @@
|
|
|
68
68
|
"type": "object",
|
|
69
69
|
"additionalProperties": false,
|
|
70
70
|
"properties": {
|
|
71
|
-
"L0": {
|
|
72
|
-
"type": "object",
|
|
73
|
-
"additionalProperties": false,
|
|
74
|
-
"properties": {
|
|
75
|
-
"enabled": {
|
|
76
|
-
"type": "boolean"
|
|
77
|
-
},
|
|
78
|
-
"validators": {
|
|
79
|
-
"type": "array",
|
|
80
|
-
"items": {
|
|
81
|
-
"type": "string"
|
|
82
|
-
},
|
|
83
|
-
"uniqueItems": true
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
71
|
"L1": {
|
|
88
72
|
"type": "object",
|
|
89
73
|
"additionalProperties": false,
|
package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json
CHANGED
|
@@ -68,22 +68,6 @@
|
|
|
68
68
|
"type": "object",
|
|
69
69
|
"additionalProperties": false,
|
|
70
70
|
"properties": {
|
|
71
|
-
"L0": {
|
|
72
|
-
"type": "object",
|
|
73
|
-
"additionalProperties": false,
|
|
74
|
-
"properties": {
|
|
75
|
-
"enabled": {
|
|
76
|
-
"type": "boolean"
|
|
77
|
-
},
|
|
78
|
-
"validators": {
|
|
79
|
-
"type": "array",
|
|
80
|
-
"items": {
|
|
81
|
-
"type": "string"
|
|
82
|
-
},
|
|
83
|
-
"uniqueItems": true
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
71
|
"L1": {
|
|
88
72
|
"type": "object",
|
|
89
73
|
"additionalProperties": false,
|
package/scripts/harness/main.ts
CHANGED
|
@@ -110,7 +110,7 @@ Commands:
|
|
|
110
110
|
|
|
111
111
|
lint Run lint checks (--json, --target <path>)
|
|
112
112
|
|
|
113
|
-
validate Run validators (--layer
|
|
113
|
+
validate Run validators (--layer L2|L3|L4|all; L0 prints runtime hook info, --unit, --format human|agent|ci)
|
|
114
114
|
ci-check CI check (--quick for quick mode, --fail-on-reject, --dry-run, --files)
|
|
115
115
|
|
|
116
116
|
phasegate:check-ready Check ready status (--json)
|
|
@@ -263,10 +263,10 @@ Options:
|
|
|
263
263
|
--help, -h Show this help`,
|
|
264
264
|
validate: `Usage: phasegate validate [options]
|
|
265
265
|
|
|
266
|
-
Run validators against the project. Without --layer, runs all enabled layers (
|
|
266
|
+
Run validators against the project. Without --layer, runs all enabled validator layers (L2/L3/L4).
|
|
267
267
|
|
|
268
268
|
Options:
|
|
269
|
-
--layer <L0|L2|L3|L4> Run only the specified layer
|
|
269
|
+
--layer <L0|L2|L3|L4> Run only the specified validator layer; L0 prints runtime hook info
|
|
270
270
|
--json Output machine-readable JSON
|
|
271
271
|
--help, -h Show this help`,
|
|
272
272
|
lint: `Usage: phasegate lint [options]
|
|
@@ -10,7 +10,6 @@ import { ValidationRule } from './domain/value-objects/validation-rule.js';
|
|
|
10
10
|
import { ValidatorRegistry } from './domain/services/validator-registry.js';
|
|
11
11
|
import { ValidatorExecutionService } from './domain/services/validator-execution-service.js';
|
|
12
12
|
import { ValidationResultContractMapper } from './application/mappers/validation-result-contract-mapper.js';
|
|
13
|
-
import { RunL0ValidatorsUseCase } from './application/use-cases/run-l0-validators-usecase.js';
|
|
14
13
|
import { RunL2ValidatorsUseCase } from './application/use-cases/run-l2-validators-usecase.js';
|
|
15
14
|
import { RunL3ValidatorsUseCase } from './application/use-cases/run-l3-validators-usecase.js';
|
|
16
15
|
import { RunL4ValidatorsUseCase } from './application/use-cases/run-l4-validators-usecase.js';
|
|
@@ -45,7 +44,6 @@ import { join } from 'node:path';
|
|
|
45
44
|
const DEFAULT_CONFIG = {
|
|
46
45
|
preset: 'standard' as const,
|
|
47
46
|
layers: {
|
|
48
|
-
L0: { enabled: true, validators: ['L0-001', 'L0-002'] },
|
|
49
47
|
L2: { enabled: true, validators: ['L2-001', 'L2-002', 'L2-003'] },
|
|
50
48
|
L3: { enabled: true, validators: ['L3-001', 'L3-002', 'L3-003', 'L3-004'], coverageThreshold: 90, bundleSizeLimit: 512000 },
|
|
51
49
|
L4: { enabled: true, validators: ['L4-001', 'L4-002', 'L4-003'] },
|
|
@@ -61,7 +59,7 @@ function buildDefaultRegistry(): ValidatorRegistry {
|
|
|
61
59
|
fixExample: null,
|
|
62
60
|
});
|
|
63
61
|
|
|
64
|
-
const createDef = (id: string, layer: '
|
|
62
|
+
const createDef = (id: string, layer: 'L2' | 'L3' | 'L4', enabledCondition: 'always' | 'strictOnly' = 'always', externalPolicyRef: string | null = null) =>
|
|
65
63
|
ValidatorDefinition.create({
|
|
66
64
|
validatorId: ValidatorId.create(id),
|
|
67
65
|
layer,
|
|
@@ -75,7 +73,6 @@ function buildDefaultRegistry(): ValidatorRegistry {
|
|
|
75
73
|
});
|
|
76
74
|
|
|
77
75
|
const definitions = [
|
|
78
|
-
createDef('L0-001', 'L0', 'always'),
|
|
79
76
|
createDef('L2-001', 'L2', 'always', 'PhaseGatePolicyPort'),
|
|
80
77
|
createDef('L2-002', 'L2', 'always', 'MetadataPolicyPort'),
|
|
81
78
|
createDef('L2-003', 'L2', 'always'),
|
|
@@ -93,7 +90,6 @@ function buildDefaultRegistry(): ValidatorRegistry {
|
|
|
93
90
|
|
|
94
91
|
export interface ValidatorSystemModule {
|
|
95
92
|
registry: ValidatorRegistry;
|
|
96
|
-
runL0ValidatorsUseCase: RunL0ValidatorsUseCase;
|
|
97
93
|
runL1ValidatorsUseCase: RunL1ValidatorsUseCase;
|
|
98
94
|
runL2ValidatorsUseCase: RunL2ValidatorsUseCase;
|
|
99
95
|
runL3ValidatorsUseCase: RunL3ValidatorsUseCase;
|
|
@@ -124,13 +120,6 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
|
|
|
124
120
|
const securityScannerPort = new FileSystemSecurityPatternScannerAdapter();
|
|
125
121
|
const performanceScannerPort = new AstPerformanceScannerAdapter();
|
|
126
122
|
|
|
127
|
-
const runL0ValidatorsUseCase = new RunL0ValidatorsUseCase({
|
|
128
|
-
validatorRegistry: registry,
|
|
129
|
-
validatorExecutionService: executionService,
|
|
130
|
-
validatorConfigPort: configPort,
|
|
131
|
-
contractMapper,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
123
|
const runL2ValidatorsUseCase = new RunL2ValidatorsUseCase({
|
|
135
124
|
validatorRegistry: registry,
|
|
136
125
|
validatorExecutionService: executionService,
|
|
@@ -220,7 +209,6 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
|
|
|
220
209
|
const handlers = {
|
|
221
210
|
runValidators: new RunValidatorsHandler({
|
|
222
211
|
runFullValidationUseCase,
|
|
223
|
-
runL0ValidatorsUseCase,
|
|
224
212
|
runL1ValidatorsUseCase,
|
|
225
213
|
defaultFailOnWarning,
|
|
226
214
|
}),
|
|
@@ -230,7 +218,6 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
|
|
|
230
218
|
|
|
231
219
|
return {
|
|
232
220
|
registry,
|
|
233
|
-
runL0ValidatorsUseCase,
|
|
234
221
|
runL1ValidatorsUseCase,
|
|
235
222
|
runL2ValidatorsUseCase,
|
|
236
223
|
runL3ValidatorsUseCase,
|
|
@@ -19,7 +19,7 @@ export class ValidatorExecutionError extends Error {
|
|
|
19
19
|
|
|
20
20
|
export interface ValidatorExecutionServiceDeps {
|
|
21
21
|
configPort?: {
|
|
22
|
-
getLayerConfig(layer: '
|
|
22
|
+
getLayerConfig(layer: 'L2' | 'L3' | 'L4'): LayerConfig | Promise<LayerConfig>;
|
|
23
23
|
};
|
|
24
24
|
policyPort?: PhaseGatePolicyPort | { check: (...args: unknown[]) => unknown };
|
|
25
25
|
[key: string]: unknown;
|
|
@@ -132,7 +132,7 @@ export class ValidatorExecutionService {
|
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
private _getLayerConfigSync(layer: '
|
|
135
|
+
private _getLayerConfigSync(layer: 'L2' | 'L3' | 'L4'): LayerConfig | undefined {
|
|
136
136
|
const port = this.deps.configPort;
|
|
137
137
|
if (!port) return undefined;
|
|
138
138
|
const result = port.getLayerConfig(layer);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @unit validator-system
|
|
4
4
|
*
|
|
5
5
|
* ValidatorRegistry ドメインサービス
|
|
6
|
-
*
|
|
6
|
+
* L2-L4バリデータ定義のカタログ管理と選択実行インターフェース
|
|
7
7
|
*/
|
|
8
8
|
import { ValidatorId } from '../value-objects/validator-id.js';
|
|
9
9
|
import { ValidatorDefinition } from '../value-objects/validator-definition.js';
|
|
@@ -48,7 +48,7 @@ export class ValidatorRegistry {
|
|
|
48
48
|
return this.definitionList;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
listByLayer(layer: '
|
|
51
|
+
listByLayer(layer: 'L2' | 'L3' | 'L4'): readonly ValidatorDefinition[] {
|
|
52
52
|
return this.definitionList.filter((def) => def.layer === layer);
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { ValidatorId } from './validator-id.js';
|
|
9
9
|
|
|
10
10
|
export interface LayerConfigProps {
|
|
11
|
-
readonly layer: '
|
|
11
|
+
readonly layer: 'L2' | 'L3' | 'L4';
|
|
12
12
|
readonly enabled: boolean;
|
|
13
13
|
readonly validatorIds: readonly string[];
|
|
14
14
|
readonly thresholds: Record<string, number>;
|
|
@@ -17,7 +17,7 @@ export interface LayerConfigProps {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export class LayerConfig {
|
|
20
|
-
readonly layer: '
|
|
20
|
+
readonly layer: 'L2' | 'L3' | 'L4';
|
|
21
21
|
readonly enabled: boolean;
|
|
22
22
|
readonly validatorIds: readonly string[];
|
|
23
23
|
readonly thresholds: Readonly<Record<string, number>>;
|
|
@@ -10,17 +10,16 @@ import { ValidationRule } from './validation-rule.js';
|
|
|
10
10
|
|
|
11
11
|
export interface ValidatorDefinitionProps {
|
|
12
12
|
readonly validatorId: ValidatorId;
|
|
13
|
-
readonly layer: '
|
|
13
|
+
readonly layer: 'L2' | 'L3' | 'L4';
|
|
14
14
|
readonly name?: string;
|
|
15
15
|
readonly description?: string;
|
|
16
16
|
readonly rules: readonly ValidationRule[];
|
|
17
17
|
readonly enabledCondition: 'always' | 'layerEnabled' | 'strictOnly';
|
|
18
18
|
readonly externalPolicyRef: string | null;
|
|
19
|
-
readonly executionPhase?: '
|
|
19
|
+
readonly executionPhase?: 'pre-commit' | 'ci' | 'scheduled';
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const LAYER_TO_PHASE: Record<'
|
|
23
|
-
L0: 'fuse-hook',
|
|
22
|
+
const LAYER_TO_PHASE: Record<'L2' | 'L3' | 'L4', 'pre-commit' | 'ci' | 'scheduled'> = {
|
|
24
23
|
L2: 'pre-commit',
|
|
25
24
|
L3: 'ci',
|
|
26
25
|
L4: 'scheduled',
|
|
@@ -28,13 +27,13 @@ const LAYER_TO_PHASE: Record<'L0' | 'L2' | 'L3' | 'L4', 'fuse-hook' | 'fuse-hook
|
|
|
28
27
|
|
|
29
28
|
export class ValidatorDefinition {
|
|
30
29
|
readonly validatorId: ValidatorId;
|
|
31
|
-
readonly layer: '
|
|
30
|
+
readonly layer: 'L2' | 'L3' | 'L4';
|
|
32
31
|
readonly name: string;
|
|
33
32
|
readonly description: string;
|
|
34
33
|
readonly rules: readonly ValidationRule[];
|
|
35
34
|
readonly enabledCondition: 'always' | 'layerEnabled' | 'strictOnly';
|
|
36
35
|
readonly externalPolicyRef: string | null;
|
|
37
|
-
readonly executionPhase: '
|
|
36
|
+
readonly executionPhase: 'pre-commit' | 'ci' | 'scheduled';
|
|
38
37
|
|
|
39
38
|
private constructor(props: ValidatorDefinitionProps) {
|
|
40
39
|
this.validatorId = props.validatorId;
|
|
@@ -20,8 +20,6 @@ const VALIDATOR_ID_PATTERN = /^L[0-4]-\d{3}$/;
|
|
|
20
20
|
|
|
21
21
|
/** バリデータID -> バリデータ名のマップ */
|
|
22
22
|
const VALIDATOR_NAME_MAP: Record<string, string> = {
|
|
23
|
-
'L0-001': 'fuse-hook-config',
|
|
24
|
-
'L0-002': 'fuse-mount-status',
|
|
25
23
|
'L1-017': 'it-test-mock-detection',
|
|
26
24
|
'L1-018': 'stub-comment-detection',
|
|
27
25
|
'L2-001': 'phase-gate',
|
|
@@ -9,7 +9,6 @@ import { LayerConfig } from '../../domain/value-objects/layer-config.js';
|
|
|
9
9
|
import type { ValidatorConfigPort } from '../../domain/ports/validator-config-port.js';
|
|
10
10
|
|
|
11
11
|
export interface HarnessConfigLayers {
|
|
12
|
-
L0?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string };
|
|
13
12
|
L2?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string };
|
|
14
13
|
L3?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string; coverageThreshold?: number; bundleSizeLimit?: number };
|
|
15
14
|
L4?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string; deadCodeGC?: boolean };
|
|
@@ -32,13 +31,12 @@ export class HarnessConfigValidatorConfigAdapter implements ValidatorConfigPort
|
|
|
32
31
|
this.config = config;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
async getLayerConfig(layer: '
|
|
34
|
+
async getLayerConfig(layer: 'L2' | 'L3' | 'L4'): Promise<LayerConfig> {
|
|
36
35
|
const preset = (this.config.project?.preset ?? this.config.preset ?? 'standard') as 'minimal' | 'standard' | 'strict';
|
|
37
36
|
const strictOnly = preset === 'strict';
|
|
38
37
|
const layerData = this.config.layers?.[layer] ?? {};
|
|
39
38
|
|
|
40
39
|
const defaultValidators: Record<string, string[]> = {
|
|
41
|
-
L0: ['L0-001', 'L0-002'],
|
|
42
40
|
L2: ['L2-001', 'L2-002', 'L2-003'],
|
|
43
41
|
L3: ['L3-001', 'L3-002', 'L3-003', 'L3-004'],
|
|
44
42
|
L4: ['L4-001', 'L4-002', 'L4-003'],
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* RunValidatorsHandler — バリデータ実行 CLIハンドラー
|
|
6
6
|
*/
|
|
7
7
|
import type { RunFullValidationUseCase } from '../../application/use-cases/run-full-validation-usecase.js';
|
|
8
|
-
import type { RunL0ValidatorsUseCase } from '../../application/use-cases/run-l0-validators-usecase.js';
|
|
9
8
|
import type { RunL1ValidatorsUseCase } from '../../application/use-cases/run-l1-validators-usecase.js';
|
|
10
9
|
import type { AggregatedValidationReport } from '../../application/dto/aggregated-validation-report.js';
|
|
11
10
|
import { HumanValidationResultFormatter } from '../formatters/human-validation-result-formatter.js';
|
|
@@ -25,7 +24,6 @@ export interface RunValidatorsHandlerArgs {
|
|
|
25
24
|
|
|
26
25
|
export interface RunValidatorsHandlerDeps {
|
|
27
26
|
runFullValidationUseCase: RunFullValidationUseCase;
|
|
28
|
-
runL0ValidatorsUseCase?: RunL0ValidatorsUseCase;
|
|
29
27
|
runL1ValidatorsUseCase?: RunL1ValidatorsUseCase;
|
|
30
28
|
/** WI-094 / ADR-017: config 由来の failOnWarning デフォルト。args.failOnWarning が undefined の場合に適用 */
|
|
31
29
|
defaultFailOnWarning?: boolean;
|
|
@@ -33,13 +31,11 @@ export interface RunValidatorsHandlerDeps {
|
|
|
33
31
|
|
|
34
32
|
export class RunValidatorsHandler {
|
|
35
33
|
private readonly useCase: RunFullValidationUseCase;
|
|
36
|
-
private readonly l0UseCase: RunL0ValidatorsUseCase | undefined;
|
|
37
34
|
private readonly l1UseCase: RunL1ValidatorsUseCase | undefined;
|
|
38
35
|
private readonly defaultFailOnWarning: boolean;
|
|
39
36
|
|
|
40
37
|
constructor(deps: RunValidatorsHandlerDeps) {
|
|
41
38
|
this.useCase = deps.runFullValidationUseCase;
|
|
42
|
-
this.l0UseCase = deps.runL0ValidatorsUseCase;
|
|
43
39
|
this.l1UseCase = deps.runL1ValidatorsUseCase;
|
|
44
40
|
this.defaultFailOnWarning = deps.defaultFailOnWarning ?? false;
|
|
45
41
|
}
|
|
@@ -47,37 +43,12 @@ export class RunValidatorsHandler {
|
|
|
47
43
|
async execute(args: RunValidatorsHandlerArgs): Promise<{ output: string; exitCode: number }> {
|
|
48
44
|
try {
|
|
49
45
|
if (args.layer === 'L0') {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
const l0Report: AggregatedValidationReport = {
|
|
58
|
-
overallPassed: l0Results.every((r) => r.passed || r.skipped),
|
|
59
|
-
totalValidators: l0Results.length,
|
|
60
|
-
passedValidators: l0Results.filter((r) => r.passed).length,
|
|
61
|
-
failedValidators: l0Results.filter((r) => !r.passed && !r.skipped).length,
|
|
62
|
-
skippedValidators: l0Results.filter((r) => r.skipped).length,
|
|
63
|
-
allErrors: l0Results.flatMap((r) => r.errors),
|
|
64
|
-
summary: {
|
|
65
|
-
totalErrors: l0Results.flatMap((r) => r.errors).filter((e) => e.severity === 'error').length,
|
|
66
|
-
totalWarnings: l0Results.flatMap((r) => r.errors).filter((e) => e.severity === 'warning').length,
|
|
67
|
-
errorsByLayer: { L2: 0, L3: 0, L4: 0 },
|
|
68
|
-
},
|
|
69
|
-
results: l0Results,
|
|
70
|
-
};
|
|
71
|
-
const format = args.format ?? 'human';
|
|
72
|
-
let output: string;
|
|
73
|
-
if (format === 'agent') {
|
|
74
|
-
output = new AgentValidationResultFormatter().format(l0Report);
|
|
75
|
-
} else if (format === 'ci') {
|
|
76
|
-
output = new CiValidationResultFormatter().format(l0Report);
|
|
77
|
-
} else {
|
|
78
|
-
output = new HumanValidationResultFormatter().format(l0Report);
|
|
79
|
-
}
|
|
80
|
-
return { output, exitCode: l0Report.overallPassed ? 0 : 1 };
|
|
46
|
+
const output = [
|
|
47
|
+
'L0 validator execution has been retired.',
|
|
48
|
+
'Runtime L0 enforcement is provided by agent-integration hooks and Husky git hooks.',
|
|
49
|
+
'Use the configured PreToolUse/PostToolUse/Stop/SessionStart/UserPromptSubmit hooks and .husky/pre-commit / .husky/commit-msg instead of validate --layer L0.',
|
|
50
|
+
].join('\n');
|
|
51
|
+
return { output, exitCode: 0 };
|
|
81
52
|
}
|
|
82
53
|
|
|
83
54
|
if (args.layer === 'L1') {
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @layer application
|
|
3
|
-
* @unit validator-system
|
|
4
|
-
*
|
|
5
|
-
* RunL0ValidatorsUseCase — L0 バリデータ実行
|
|
6
|
-
*/
|
|
7
|
-
import { ValidatorId } from '../../domain/value-objects/validator-id.js';
|
|
8
|
-
import { ValidationResult } from '../../domain/value-objects/validation-result.js';
|
|
9
|
-
import { ValidatorRegistry } from '../../domain/services/validator-registry.js';
|
|
10
|
-
import { ValidatorExecutionService } from '../../domain/services/validator-execution-service.js';
|
|
11
|
-
import { ValidationResultContractMapper } from '../mappers/validation-result-contract-mapper.js';
|
|
12
|
-
import type { ValidationResultContract } from '../dto/validation-result-contract.js';
|
|
13
|
-
import type { RunL0ValidatorsInput } from '../dto/run-l0-validators-input.js';
|
|
14
|
-
import type { ValidatorConfigPort } from '../../domain/ports/validator-config-port.js';
|
|
15
|
-
|
|
16
|
-
export interface RunL0ValidatorsUseCaseDeps {
|
|
17
|
-
validatorRegistry: ValidatorRegistry;
|
|
18
|
-
validatorExecutionService: ValidatorExecutionService;
|
|
19
|
-
validatorConfigPort: ValidatorConfigPort;
|
|
20
|
-
contractMapper: ValidationResultContractMapper;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class RunL0ValidatorsUseCase {
|
|
24
|
-
private readonly registry: ValidatorRegistry;
|
|
25
|
-
private readonly executionService: ValidatorExecutionService;
|
|
26
|
-
private readonly configPort: ValidatorConfigPort;
|
|
27
|
-
private readonly mapper: ValidationResultContractMapper;
|
|
28
|
-
|
|
29
|
-
constructor(deps: RunL0ValidatorsUseCaseDeps) {
|
|
30
|
-
this.registry = deps.validatorRegistry;
|
|
31
|
-
this.executionService = deps.validatorExecutionService;
|
|
32
|
-
this.configPort = deps.validatorConfigPort;
|
|
33
|
-
this.mapper = deps.contractMapper;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async execute(input: RunL0ValidatorsInput): Promise<readonly ValidationResultContract[]> {
|
|
37
|
-
let validatorIds: readonly ValidatorId[];
|
|
38
|
-
if (input.validatorIds && input.validatorIds.length > 0) {
|
|
39
|
-
validatorIds = input.validatorIds.map((id) => ValidatorId.create(id));
|
|
40
|
-
} else {
|
|
41
|
-
validatorIds = this.registry.listByLayer('L0').map((d) => d.validatorId);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const definitions = this.registry.select(validatorIds);
|
|
45
|
-
|
|
46
|
-
const layerConfig = await this.configPort.getLayerConfig('L0');
|
|
47
|
-
if (!layerConfig.enabled) {
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const results = this.executionService.execute(definitions, [layerConfig]);
|
|
52
|
-
const finalResults = definitions.map(
|
|
53
|
-
(definition) => {
|
|
54
|
-
const result = results.find((r) => r.validatorId.value === definition.validatorId.value);
|
|
55
|
-
return result ?? ValidationResult.skip(definition.validatorId);
|
|
56
|
-
},
|
|
57
|
-
);
|
|
58
|
-
return this.mapper.toContracts(finalResults);
|
|
59
|
-
}
|
|
60
|
-
}
|