phasegate 0.191.0 → 0.212.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.ja.md +52 -15
  3. package/README.md +39 -11
  4. package/docs/ADR/030-injection-threat-model-and-trust-root.md +145 -0
  5. package/docs/guide/hooks-integration.md +50 -1
  6. package/docs/guide/installation.md +1 -1
  7. package/docs/guide/quick-vs-full-mode.md +1 -1
  8. package/docs/guide/skills-overview.md +7 -8
  9. package/package.json +1 -1
  10. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +131 -63
  11. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +31 -4
  12. package/scripts/harness/agent-integration/presentation/spotlight.ts +65 -0
  13. package/scripts/harness/ci-governance/application/dto/pin-integrity-input.ts +8 -0
  14. package/scripts/harness/ci-governance/application/dto/pin-integrity-output.ts +9 -0
  15. package/scripts/harness/ci-governance/application/dto/verify-integrity-input.ts +7 -0
  16. package/scripts/harness/ci-governance/application/dto/verify-integrity-output.ts +10 -0
  17. package/scripts/harness/ci-governance/application/usecases/pin-integrity-usecase.ts +60 -0
  18. package/scripts/harness/ci-governance/application/usecases/verify-integrity-usecase.ts +46 -0
  19. package/scripts/harness/ci-governance/composition-root.ts +67 -64
  20. package/scripts/harness/ci-governance/domain/ports/integrity-manifest-repository-port.ts +14 -0
  21. package/scripts/harness/ci-governance/domain/ports/sha256-hasher-port.ts +10 -0
  22. package/scripts/harness/ci-governance/domain/services/integrity-checker.ts +42 -0
  23. package/scripts/harness/ci-governance/domain/value-objects/integrity-drift.ts +16 -0
  24. package/scripts/harness/ci-governance/domain/value-objects/integrity-manifest.ts +49 -0
  25. package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +40 -0
  26. package/scripts/harness/ci-governance/infrastructure/adapters/file-system-sha256-hasher-adapter.ts +17 -0
  27. package/scripts/harness/ci-governance/infrastructure/adapters/harness-api-command-existence-adapter.ts +7 -73
  28. package/scripts/harness/ci-governance/infrastructure/adapters/integrity-manifest-json-repository-adapter.ts +83 -0
  29. package/scripts/harness/ci-governance/presentation/handlers/integrity-handler.ts +76 -0
  30. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +53 -28
  31. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +33 -8
  32. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +90 -0
  33. package/scripts/harness/installation/application/bundled-skill-selection.ts +2 -5
  34. package/scripts/harness/main.ts +257 -105
  35. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +65 -3
  36. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +44 -40
  37. package/scripts/harness/setup/skill-deployer.ts +2 -4
  38. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +82 -49
  39. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +87 -58
  40. package/scripts/harness/validator-system/composition-root.ts +141 -99
  41. package/scripts/harness/validator-system/domain/ports/coverage-attestation-gating-policy-port.ts +14 -0
  42. package/scripts/harness/validator-system/domain/ports/injection-scan-policy-port.ts +14 -0
  43. package/scripts/harness/validator-system/domain/services/coverage-attestation-gating-service.ts +56 -0
  44. package/scripts/harness/validator-system/domain/services/injection-pattern-scan-service.ts +118 -0
  45. package/scripts/harness/validator-system/domain/value-objects/coverage-gating-report.ts +67 -0
  46. package/scripts/harness/validator-system/domain/value-objects/injection-scan-report.ts +55 -0
  47. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +35 -31
  48. package/scripts/harness/validator-system/infrastructure/adapters/adr-foundation-reference-adapter.ts +13 -7
  49. package/scripts/harness/validator-system/infrastructure/adapters/file-system-coverage-attestation-gating-adapter.ts +87 -0
  50. package/scripts/harness/validator-system/infrastructure/adapters/file-system-injection-scan-adapter.ts +82 -0
  51. package/skills/README.md +1 -1
  52. package/skills/codebase-mapper/SKILL.md +1 -1
  53. 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
  54. package/skills/doc-health-checker/SKILL.md +148 -0
  55. package/skills/release-publisher/SKILL.md +101 -0
  56. package/skills/skill-creator/SKILL.md +74 -332
  57. package/skills/story-implementor/SKILL.md +52 -0
  58. package/skills/story-mapper/SKILL.md +4 -0
  59. package/skills/story-writer/SKILL.md +9 -0
  60. package/skills/uiux-designer/references/uiux-design-template.md +4 -4
  61. package/skills/unit-designer/SKILL.md +3 -1
  62. package/skills/doc-freshness-checker/SKILL.md +0 -140
  63. package/skills/implementation-planner/SKILL.md +0 -169
  64. package/skills/implementation-planner/references/document-structure.md +0 -116
  65. package/skills/implementation-planner/references/plan-template.md +0 -177
  66. package/skills/implementation-planner/references/workflow.md +0 -164
  67. package/skills/pointer-validator/SKILL.md +0 -105
@@ -6,77 +6,92 @@
6
6
  * @work-item-id WI-110 / WI-111 / WI-132 / WI-133 / WI-136 / WI-137 / WI-138 / WI-156
7
7
  * @work-item-id WI-217
8
8
  */
9
- import { ValidatorId } from './domain/value-objects/validator-id.js';
10
- import { ValidatorDefinition } from './domain/value-objects/validator-definition.js';
11
- import { ValidationRule } from './domain/value-objects/validation-rule.js';
12
- import { ValidatorRegistry } from './domain/services/validator-registry.js';
13
- import { ValidatorExecutionService } from './domain/services/validator-execution-service.js';
14
- import { ValidationResultContractMapper } from './application/mappers/validation-result-contract-mapper.js';
15
- import { RunL2ValidatorsUseCase } from './application/use-cases/run-l2-validators-usecase.js';
16
- import { RunL3ValidatorsUseCase } from './application/use-cases/run-l3-validators-usecase.js';
17
- import { RunL4ValidatorsUseCase } from './application/use-cases/run-l4-validators-usecase.js';
18
- import { RunL1ValidatorsUseCase } from './application/use-cases/run-l1-validators-usecase.js';
19
- import { RunQuickModeUseCase } from './application/use-cases/run-quick-mode-usecase.js';
20
- import { AggregateValidationResultsUseCase } from './application/use-cases/aggregate-validation-results-usecase.js';
21
- import { RunFullValidationUseCase } from './application/use-cases/run-full-validation-usecase.js';
22
- import { HarnessConfigValidatorConfigAdapter } from './infrastructure/adapters/harness-config-validator-config-adapter.js';
23
- import { ItTestFileAnalyzerAdapter } from './infrastructure/adapters/it-test-file-analyzer-adapter.js';
24
- import { SourceFileTextScannerAdapter } from './infrastructure/adapters/source-file-text-scanner-adapter.js';
25
- import { E2eTestFileRegistryAdapter } from './infrastructure/adapters/e2e-test-file-registry-adapter.js';
26
- import { CliCommandRegistryAdapter } from './infrastructure/adapters/cli-command-registry-adapter.js';
27
- import { TraceabilityWorkItemStatusPolicyAdapter } from './infrastructure/adapters/traceability-work-item-status-policy-adapter.js';
28
- import { FileSystemContractTraceabilityPolicyAdapter } from './infrastructure/adapters/file-system-contract-traceability-policy-adapter.js';
29
- import { PhaseDependencyPhaseGatePolicyAdapter } from './infrastructure/adapters/phase-dependency-phase-gate-policy-adapter.js';
30
- import { TraceabilityMetadataPolicyAdapter } from './infrastructure/adapters/traceability-metadata-policy-adapter.js';
31
- import { NyquistAcCoveragePolicyAdapter } from './infrastructure/adapters/nyquist-ac-coverage-policy-adapter.js';
32
- import { NyquistAcBoundCoveragePolicyAdapter } from './infrastructure/adapters/nyquist-ac-bound-coverage-policy-adapter.js';
33
- import { JsonCoverageReportAdapter } from './infrastructure/adapters/json-coverage-report-adapter.js';
34
- import { BiomeAstTestQualityAnalyzerAdapter } from './infrastructure/adapters/biome-ast-test-quality-analyzer-adapter.js';
35
- import { FileSystemSecurityPatternScannerAdapter } from './infrastructure/adapters/file-system-security-pattern-scanner-adapter.js';
36
- import { AstPerformanceScannerAdapter } from './infrastructure/adapters/ast-performance-scanner-adapter.js';
37
- import { MarkdownDesignDocumentAdapter } from './infrastructure/adapters/markdown-design-document-adapter.js';
38
- import { BiomeAstSourceCodeAnalyzerAdapter } from './infrastructure/adapters/biome-ast-source-code-analyzer-adapter.js';
39
- import { AdrFoundationReferenceAdapter } from './infrastructure/adapters/adr-foundation-reference-adapter.js';
40
- import { ImportGraphSourceAnalysisAdapter } from './infrastructure/adapters/import-graph-source-analysis-adapter.js';
41
- import { FileSystemArchitectureSemanticSourceAdapter } from './infrastructure/adapters/file-system-architecture-semantic-source-adapter.js';
42
- import { FileSystemSkillCatalogDriftAdapter } from './infrastructure/adapters/file-system-skill-catalog-drift-adapter.js';
43
- import { NyquistAcLevelTraceabilityAdapter } from './infrastructure/adapters/nyquist-ac-level-traceability-adapter.js';
44
- import { FileSystemWorkItemReflectionAdapter } from './infrastructure/adapters/file-system-work-item-reflection-adapter.js';
45
- import { DriftDetectionService } from './domain/services/l4/drift-detection-service.js';
46
- import { ConsistencyCheckService } from './domain/services/l4/consistency-check-service.js';
47
- import { DeadCodeDetectionService } from './domain/services/l4/dead-code-detection-service.js';
48
- import { ArchitectureSemanticAnalysisService, type ArchitectureSemanticPolicy } from './domain/services/l4/architecture-semantic-analysis-service.js';
49
- import { buildPhase2Extensions } from '../phase2-extensions/composition-root.js';
50
- import { RunValidatorsHandler } from './presentation/handlers/run-validators-handler.js';
51
- import { RunQuickModeHandler } from './presentation/handlers/run-quick-mode-handler.js';
52
- import { ReportValidationResultsHandler } from './presentation/handlers/report-validation-results-handler.js';
53
- import { join } from 'node:path';
9
+
10
+ import { join } from "node:path";
11
+ import { buildPhase2Extensions } from "../phase2-extensions/composition-root.js";
12
+ import { ValidationResultContractMapper } from "./application/mappers/validation-result-contract-mapper.js";
13
+ import { AggregateValidationResultsUseCase } from "./application/use-cases/aggregate-validation-results-usecase.js";
14
+ import { RunFullValidationUseCase } from "./application/use-cases/run-full-validation-usecase.js";
15
+ import { RunL1ValidatorsUseCase } from "./application/use-cases/run-l1-validators-usecase.js";
16
+ import { RunL2ValidatorsUseCase } from "./application/use-cases/run-l2-validators-usecase.js";
17
+ import { RunL3ValidatorsUseCase } from "./application/use-cases/run-l3-validators-usecase.js";
18
+ import { RunL4ValidatorsUseCase } from "./application/use-cases/run-l4-validators-usecase.js";
19
+ import { RunQuickModeUseCase } from "./application/use-cases/run-quick-mode-usecase.js";
20
+ import {
21
+ ArchitectureSemanticAnalysisService,
22
+ type ArchitectureSemanticPolicy,
23
+ } from "./domain/services/l4/architecture-semantic-analysis-service.js";
24
+ import { ConsistencyCheckService } from "./domain/services/l4/consistency-check-service.js";
25
+ import { DeadCodeDetectionService } from "./domain/services/l4/dead-code-detection-service.js";
26
+ import { DriftDetectionService } from "./domain/services/l4/drift-detection-service.js";
27
+ import { ValidatorExecutionService } from "./domain/services/validator-execution-service.js";
28
+ import { ValidatorRegistry } from "./domain/services/validator-registry.js";
29
+ import { ValidationRule } from "./domain/value-objects/validation-rule.js";
30
+ import { ValidatorDefinition } from "./domain/value-objects/validator-definition.js";
31
+ import { ValidatorId } from "./domain/value-objects/validator-id.js";
32
+ import { AdrFoundationReferenceAdapter } from "./infrastructure/adapters/adr-foundation-reference-adapter.js";
33
+ import { AstPerformanceScannerAdapter } from "./infrastructure/adapters/ast-performance-scanner-adapter.js";
34
+ import { BiomeAstSourceCodeAnalyzerAdapter } from "./infrastructure/adapters/biome-ast-source-code-analyzer-adapter.js";
35
+ import { BiomeAstTestQualityAnalyzerAdapter } from "./infrastructure/adapters/biome-ast-test-quality-analyzer-adapter.js";
36
+ import { CliCommandRegistryAdapter } from "./infrastructure/adapters/cli-command-registry-adapter.js";
37
+ import { E2eTestFileRegistryAdapter } from "./infrastructure/adapters/e2e-test-file-registry-adapter.js";
38
+ import { FileSystemArchitectureSemanticSourceAdapter } from "./infrastructure/adapters/file-system-architecture-semantic-source-adapter.js";
39
+ import { FileSystemContractTraceabilityPolicyAdapter } from "./infrastructure/adapters/file-system-contract-traceability-policy-adapter.js";
40
+ import { FileSystemCoverageAttestationGatingAdapter } from "./infrastructure/adapters/file-system-coverage-attestation-gating-adapter.js";
41
+ import { FileSystemInjectionScanAdapter } from "./infrastructure/adapters/file-system-injection-scan-adapter.js";
42
+ import { FileSystemSecurityPatternScannerAdapter } from "./infrastructure/adapters/file-system-security-pattern-scanner-adapter.js";
43
+ import { FileSystemSkillCatalogDriftAdapter } from "./infrastructure/adapters/file-system-skill-catalog-drift-adapter.js";
44
+ import { FileSystemWorkItemReflectionAdapter } from "./infrastructure/adapters/file-system-work-item-reflection-adapter.js";
45
+ import { HarnessConfigValidatorConfigAdapter } from "./infrastructure/adapters/harness-config-validator-config-adapter.js";
46
+ import { ImportGraphSourceAnalysisAdapter } from "./infrastructure/adapters/import-graph-source-analysis-adapter.js";
47
+ import { ItTestFileAnalyzerAdapter } from "./infrastructure/adapters/it-test-file-analyzer-adapter.js";
48
+ import { JsonCoverageReportAdapter } from "./infrastructure/adapters/json-coverage-report-adapter.js";
49
+ import { MarkdownDesignDocumentAdapter } from "./infrastructure/adapters/markdown-design-document-adapter.js";
50
+ import { NyquistAcBoundCoveragePolicyAdapter } from "./infrastructure/adapters/nyquist-ac-bound-coverage-policy-adapter.js";
51
+ import { NyquistAcCoveragePolicyAdapter } from "./infrastructure/adapters/nyquist-ac-coverage-policy-adapter.js";
52
+ import { NyquistAcLevelTraceabilityAdapter } from "./infrastructure/adapters/nyquist-ac-level-traceability-adapter.js";
53
+ import { PhaseDependencyPhaseGatePolicyAdapter } from "./infrastructure/adapters/phase-dependency-phase-gate-policy-adapter.js";
54
+ import { SourceFileTextScannerAdapter } from "./infrastructure/adapters/source-file-text-scanner-adapter.js";
55
+ import { TraceabilityMetadataPolicyAdapter } from "./infrastructure/adapters/traceability-metadata-policy-adapter.js";
56
+ import { TraceabilityWorkItemStatusPolicyAdapter } from "./infrastructure/adapters/traceability-work-item-status-policy-adapter.js";
57
+ import { ReportValidationResultsHandler } from "./presentation/handlers/report-validation-results-handler.js";
58
+ import { RunQuickModeHandler } from "./presentation/handlers/run-quick-mode-handler.js";
59
+ import { RunValidatorsHandler } from "./presentation/handlers/run-validators-handler.js";
54
60
 
55
61
  /** デフォルト設定(ハードコード fallback) */
56
62
  const DEFAULT_CONFIG = {
57
- preset: 'standard' as const,
63
+ preset: "standard" as const,
58
64
  layers: {
59
- L2: { enabled: true, validators: ['L2-001', 'L2-002', 'L2-003', 'L2-013', 'L2-014', 'L2-015'] },
60
- L3: { enabled: true, validators: ['L3-001', 'L3-002', 'L3-003', 'L3-004'], coverageThreshold: 90, bundleSizeLimit: 512000, requirementMatrixPath: '.harness/requirement-test-matrix.json' },
61
- L4: { enabled: true, validators: ['L4-001', 'L4-002', 'L4-003', 'L4-004', 'L4-005', 'L4-006'] },
65
+ L2: { enabled: true, validators: ["L2-001", "L2-002", "L2-003", "L2-013", "L2-014", "L2-015", "L2-016"] },
66
+ L3: {
67
+ enabled: true,
68
+ validators: ["L3-001", "L3-002", "L3-003", "L3-004", "L3-006"],
69
+ coverageThreshold: 90,
70
+ bundleSizeLimit: 512000,
71
+ requirementMatrixPath: ".harness/requirement-test-matrix.json",
72
+ },
73
+ L4: { enabled: true, validators: ["L4-001", "L4-002", "L4-003", "L4-004", "L4-005", "L4-006"] },
62
74
  },
63
75
  paths: {
64
- designDocs: 'docs/product/construction',
65
- inceptionDocs: 'docs/inception',
76
+ designDocs: "docs/product/construction",
77
+ inceptionDocs: "docs/inception",
66
78
  },
67
79
  validate: { failOnWarning: false },
68
80
  architecture: {
69
81
  capabilityPolicies: {
70
- domain: { allowed: [], denied: ['filesystem', 'network', 'database', 'process-env', 'subprocess', 'user-io'] },
71
- application: { allowed: ['time', 'random'], denied: ['filesystem', 'network', 'database', 'subprocess'] },
72
- infrastructure: { allowed: ['filesystem', 'network', 'database', 'process-env', 'time', 'random', 'subprocess', 'user-io'], denied: [] },
73
- presentation: { allowed: ['user-io', 'time'], denied: ['database', 'subprocess'] },
82
+ domain: { allowed: [], denied: ["filesystem", "network", "database", "process-env", "subprocess", "user-io"] },
83
+ application: { allowed: ["time", "random"], denied: ["filesystem", "network", "database", "subprocess"] },
84
+ infrastructure: {
85
+ allowed: ["filesystem", "network", "database", "process-env", "time", "random", "subprocess", "user-io"],
86
+ denied: [],
87
+ },
88
+ presentation: { allowed: ["user-io", "time"], denied: ["database", "subprocess"] },
74
89
  },
75
90
  decisionPolicies: {
76
- domain: { expected: ['business-rule-branch', 'validation-rule', 'state-transition'], advisoryOnly: true },
77
- application: { expected: ['policy-selection', 'error-construction'], advisoryOnly: true },
78
- infrastructure: { expected: ['error-construction'], advisoryOnly: true },
79
- presentation: { expected: ['validation-rule', 'error-construction'], advisoryOnly: true },
91
+ domain: { expected: ["business-rule-branch", "validation-rule", "state-transition"], advisoryOnly: true },
92
+ application: { expected: ["policy-selection", "error-construction"], advisoryOnly: true },
93
+ infrastructure: { expected: ["error-construction"], advisoryOnly: true },
94
+ presentation: { expected: ["validation-rule", "error-construction"], advisoryOnly: true },
80
95
  },
81
96
  },
82
97
  };
@@ -84,47 +99,58 @@ const DEFAULT_CONFIG = {
84
99
  /** バリデータ定義カタログ */
85
100
  export function buildDefaultRegistry(): ValidatorRegistry {
86
101
  const defaultRule = ValidationRule.create({
87
- ruleName: 'default-rule',
88
- errorTemplate: { code: 'L2-001', severity: 'error', messageTemplate: '{{message}}' },
102
+ ruleName: "default-rule",
103
+ errorTemplate: { code: "L2-001", severity: "error", messageTemplate: "{{message}}" },
89
104
  fixExample: null,
90
105
  });
91
106
 
92
- const createDef = (id: string, layer: 'L2' | 'L3' | 'L4', enabledCondition: 'always' | 'strictOnly' = 'always', externalPolicyRef: string | null = null) =>
107
+ const createDef = (
108
+ id: string,
109
+ layer: "L2" | "L3" | "L4",
110
+ enabledCondition: "always" | "strictOnly" = "always",
111
+ externalPolicyRef: string | null = null,
112
+ ) =>
93
113
  ValidatorDefinition.create({
94
114
  validatorId: ValidatorId.create(id),
95
115
  layer,
96
- rules: [ValidationRule.create({
97
- ruleName: `${id}-rule`,
98
- errorTemplate: { code: id, severity: 'error', messageTemplate: '{{message}}' },
99
- fixExample: null,
100
- })],
116
+ rules: [
117
+ ValidationRule.create({
118
+ ruleName: `${id}-rule`,
119
+ errorTemplate: { code: id, severity: "error", messageTemplate: "{{message}}" },
120
+ fixExample: null,
121
+ }),
122
+ ],
101
123
  enabledCondition,
102
124
  externalPolicyRef,
103
125
  });
104
126
 
105
127
  const definitions = [
106
- createDef('L2-001', 'L2', 'always', 'PhaseGatePolicyPort'),
107
- createDef('L2-002', 'L2', 'always', 'MetadataPolicyPort'),
108
- createDef('L2-003', 'L2', 'always'),
109
- createDef('L2-013', 'L2', 'always', 'CliE2eTestExistenceService'),
110
- createDef('L2-014', 'L2', 'always', 'WorkItemStatusPolicyPort'),
111
- createDef('L2-015', 'L2', 'always', 'ContractTraceabilityPolicyPort'),
112
- createDef('L3-001', 'L3', 'always'),
113
- createDef('L3-002', 'L3', 'strictOnly'),
114
- createDef('L3-003', 'L3', 'always'),
115
- createDef('L3-004', 'L3', 'always', 'AcCoveragePolicyPort'),
128
+ createDef("L2-001", "L2", "always", "PhaseGatePolicyPort"),
129
+ createDef("L2-002", "L2", "always", "MetadataPolicyPort"),
130
+ createDef("L2-003", "L2", "always"),
131
+ createDef("L2-013", "L2", "always", "CliE2eTestExistenceService"),
132
+ createDef("L2-014", "L2", "always", "WorkItemStatusPolicyPort"),
133
+ createDef("L2-015", "L2", "always", "ContractTraceabilityPolicyPort"),
134
+ // WI-258 / ADR-030 §Decision.3.②: L2-016 (coverage-attestation-gating, fail-closed, default-ON)
135
+ createDef("L2-016", "L2", "always", "CoverageAttestationGatingPolicyPort"),
136
+ createDef("L3-001", "L3", "always"),
137
+ createDef("L3-002", "L3", "strictOnly"),
138
+ createDef("L3-003", "L3", "always"),
139
+ createDef("L3-004", "L3", "always", "AcCoveragePolicyPort"),
116
140
  // WI-227 / H16-03: L3-005 (ac-bound-coverage) は registry には登録するが
117
141
  // default-OFF(DEFAULT_CONFIG.layers.L3.validators に含めない)。fail-closed / opt-in。
118
- createDef('L3-005', 'L3', 'always', 'AcBoundCoveragePolicyPort'),
119
- createDef('L4-001', 'L4', 'always'),
120
- createDef('L4-002', 'L4', 'always'),
121
- createDef('L4-003', 'L4', 'strictOnly'),
122
- createDef('L4-004', 'L4', 'always'),
123
- createDef('L4-005', 'L4', 'always'),
124
- createDef('L4-006', 'L4', 'always', 'SkillCatalogDriftPort'),
142
+ createDef("L3-005", "L3", "always", "AcBoundCoveragePolicyPort"),
143
+ // WI-259 / ADR-030 §Decision.3.④: L3-006 (injection-scan) は advisory (warning-only, default-ON)
144
+ createDef("L3-006", "L3", "always", "InjectionScanPolicyPort"),
145
+ createDef("L4-001", "L4", "always"),
146
+ createDef("L4-002", "L4", "always"),
147
+ createDef("L4-003", "L4", "strictOnly"),
148
+ createDef("L4-004", "L4", "always"),
149
+ createDef("L4-005", "L4", "always"),
150
+ createDef("L4-006", "L4", "always", "SkillCatalogDriftPort"),
125
151
  // WI-222 / HF2-05: L4-007 (ac-level-traceability) は registry には登録するが
126
152
  // default-OFF(DEFAULT_CONFIG.layers.L4.validators に含めない)。advisory-only。
127
- createDef('L4-007', 'L4', 'always', 'AcLevelTraceabilityPort'),
153
+ createDef("L4-007", "L4", "always", "AcLevelTraceabilityPort"),
128
154
  ];
129
155
 
130
156
  return new ValidatorRegistry(definitions);
@@ -162,26 +188,40 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
162
188
  const acBoundCoveragePolicyPort = new NyquistAcBoundCoveragePolicyAdapter();
163
189
  // L3-003: テストカバレッジレポート(vitest --coverage の json-summary 出力)を読み取る。
164
190
  // 未配線だと L3-003 は装飾的な pass になり 90% 閾値が形骸化するため必ず配線する。
165
- const coverageReportPort = new JsonCoverageReportAdapter(
166
- join(process.cwd(), 'coverage', 'coverage-summary.json'),
167
- );
191
+ const coverageReportPort = new JsonCoverageReportAdapter(join(process.cwd(), "coverage", "coverage-summary.json"));
168
192
  const testQualityAnalyzerPort = new BiomeAstTestQualityAnalyzerAdapter();
169
193
  const securityScannerPort = new FileSystemSecurityPatternScannerAdapter();
170
194
  const performanceScannerPort = new AstPerformanceScannerAdapter();
171
195
  const workItemStatusPolicyPort = new TraceabilityWorkItemStatusPolicyAdapter(process.cwd());
172
196
  const contractTraceabilityPolicyPort = new FileSystemContractTraceabilityPolicyAdapter();
197
+ // WI-258 / ADR-030 §Decision.3.②: L2-016 (coverage-attestation-gating) 用アダプタ。
198
+ // docs/product/construction/*​/coverage_report.md を cwd 起点で走査する(targetPaths 非依存)。
199
+ const coverageAttestationGatingPolicyPort = new FileSystemCoverageAttestationGatingAdapter(process.cwd());
200
+ // WI-259 / ADR-030 §Decision.3.④: L3-006 (injection-scan, advisory) 用アダプタ。
201
+ // 指示搭載ファイル群(skills/**​/SKILL.md / CLAUDE.md / AGENTS.md / agent-context / .claude/settings.json)を
202
+ // cwd 起点で走査する(targetPaths 非依存)。
203
+ const injectionScanPolicyPort = new FileSystemInjectionScanAdapter(process.cwd());
173
204
 
174
205
  const cwd = process.cwd();
175
- const designDocsRoot = configData.paths?.designDocs ?? 'docs/product/construction';
176
- const inceptionDocsRoot = configData.paths?.inceptionDocs ?? 'docs/inception';
206
+ const designDocsRoot = configData.paths?.designDocs ?? "docs/product/construction";
207
+ const inceptionDocsRoot = configData.paths?.inceptionDocs ?? "docs/inception";
177
208
  const docsRoot = join(cwd, designDocsRoot);
178
- const e2eTestFileRegistryPort = new E2eTestFileRegistryAdapter({ e2eTestRoot: join(cwd, 'scripts/harness/__tests__/e2e') });
209
+ const e2eTestFileRegistryPort = new E2eTestFileRegistryAdapter({
210
+ e2eTestRoot: join(cwd, "scripts/harness/__tests__/e2e"),
211
+ });
179
212
  const cliCommandRegistryPort = new CliCommandRegistryAdapter({
180
213
  commands: [
181
- 'validate', 'lint', 'ci-check',
182
- 'phasegate:check-ready', 'phasegate:check-phase', 'phasegate:ci-check',
183
- 'phasegate:detect-drift', 'phasegate:lint', 'phasegate:complete-check',
184
- 'phasegate:impact-analysis', 'phasegate:status',
214
+ "validate",
215
+ "lint",
216
+ "ci-check",
217
+ "phasegate:check-ready",
218
+ "phasegate:check-phase",
219
+ "phasegate:ci-check",
220
+ "phasegate:detect-drift",
221
+ "phasegate:lint",
222
+ "phasegate:complete-check",
223
+ "phasegate:impact-analysis",
224
+ "phasegate:status",
185
225
  ],
186
226
  });
187
227
 
@@ -197,6 +237,7 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
197
237
  cliCommandRegistryPort,
198
238
  workItemStatusPolicyPort,
199
239
  contractTraceabilityPolicyPort,
240
+ coverageAttestationGatingPolicyPort,
200
241
  });
201
242
 
202
243
  // WI-227 / H16-03: L3-005 のスコープ対象 story-id を config から取得(既定 [])。
@@ -213,19 +254,20 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
213
254
  coverageReportPort,
214
255
  securityScannerPort,
215
256
  performanceScannerPort,
257
+ injectionScanPolicyPort,
216
258
  acBoundStories,
217
259
  });
218
260
 
219
261
  const markdownDesignDocumentPort = new MarkdownDesignDocumentAdapter(docsRoot);
220
262
  const sourceCodeAnalyzerAdapter = new BiomeAstSourceCodeAnalyzerAdapter();
221
- const adrReferencePort = new AdrFoundationReferenceAdapter();
263
+ const adrReferencePort = new AdrFoundationReferenceAdapter(cwd);
222
264
  const sourceAnalysisPort = new ImportGraphSourceAnalysisAdapter();
223
265
  const architectureSemanticSourcePort = new FileSystemArchitectureSemanticSourceAdapter();
224
266
  const skillCatalogDriftPort = new FileSystemSkillCatalogDriftAdapter(cwd);
225
267
  // WI-222 / HF2-05: L4-007 (advisory) 用の AC 単位トレーサビリティ port。
226
268
  // matrix path は L3-004 と同じ config キーを参照する。
227
269
  const acLevelTraceabilityPort = new NyquistAcLevelTraceabilityAdapter({
228
- matrixFilePath: configData.layers?.L3?.requirementMatrixPath ?? '.harness/requirement-test-matrix.json',
270
+ matrixFilePath: configData.layers?.L3?.requirementMatrixPath ?? ".harness/requirement-test-matrix.json",
229
271
  });
230
272
  const workItemReflectionPort = new FileSystemWorkItemReflectionAdapter(cwd);
231
273
 
@@ -275,11 +317,11 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
275
317
 
276
318
  const aggregateValidationResultsUseCase = new AggregateValidationResultsUseCase();
277
319
  const itTestFileAnalyzerPort = new ItTestFileAnalyzerAdapter({
278
- itTestRoot: join(cwd, 'scripts/harness/__tests__/integration'),
320
+ itTestRoot: join(cwd, "scripts/harness/__tests__/integration"),
279
321
  // アダプター自体のテストファイルは vi.mock() を使用しているため誤検知防止で除外
280
322
  excludePattern: /it-test-file-analyzer-adapter\.test\.ts$/,
281
323
  });
282
- const sourceFileTextScannerPort = new SourceFileTextScannerAdapter({ sourceRoot: join(cwd, 'scripts/harness') });
324
+ const sourceFileTextScannerPort = new SourceFileTextScannerAdapter({ sourceRoot: join(cwd, "scripts/harness") });
283
325
  const runL1ValidatorsUseCase = new RunL1ValidatorsUseCase({
284
326
  itTestFileAnalyzerPort,
285
327
  sourceFileTextScannerPort,
@@ -0,0 +1,14 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-258
4
+
5
+ import type { CoverageReportGatingModel } from "../value-objects/coverage-gating-report.js";
6
+
7
+ /**
8
+ * WI-258 / ADR-030 §Decision.3.② — coverage_report 走査結果の供給ポート。
9
+ * 走査対象(docs/product/construction/*​/coverage_report.md)の解決は infrastructure が担う
10
+ * (cwd 起点・targetPaths 非依存の corpus 走査)。
11
+ */
12
+ export interface CoverageAttestationGatingPolicyPort {
13
+ collect(): Promise<readonly CoverageReportGatingModel[]>;
14
+ }
@@ -0,0 +1,14 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-259
4
+
5
+ import type { InjectionScanTarget } from "../value-objects/injection-scan-report.js";
6
+
7
+ /**
8
+ * WI-259 / ADR-030 §Decision.3.④ — 指示搭載ファイルの供給ポート。
9
+ * 走査対象(skills/**​/SKILL.md / CLAUDE.md / AGENTS.md / docs/templates/agent-context/** /
10
+ * .claude/settings.json)の解決は infrastructure が担う(cwd 起点・targetPaths 非依存の corpus 走査)。
11
+ */
12
+ export interface InjectionScanPolicyPort {
13
+ collect(): Promise<readonly InjectionScanTarget[]>;
14
+ }
@@ -0,0 +1,56 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-258
4
+
5
+ /**
6
+ * WI-258 / ADR-030 §Decision.3.② — coverage-attestation-gating (L2-016) の判定ドメインサービス。
7
+ *
8
+ * INV-A: hasLegacyMarker のファイルは error を生成せず legacyCount に計上し warning を 1 件生成(見える負債)。
9
+ * INV-B: マーカー無しファイルで attestation 参照を持たない ✅ claim は error violation(fail-closed)。
10
+ * INV-C: ✅ を持たないファイルは violation も warning も生成しない(対象外)。
11
+ */
12
+
13
+ import {
14
+ type CoverageGatingFinding,
15
+ CoverageGatingReport,
16
+ type CoverageReportGatingModel,
17
+ } from "../value-objects/coverage-gating-report.js";
18
+
19
+ export class CoverageAttestationGatingService {
20
+ check(models: readonly CoverageReportGatingModel[]): CoverageGatingReport {
21
+ const violations: CoverageGatingFinding[] = [];
22
+ const warnings: CoverageGatingFinding[] = [];
23
+ let legacyCount = 0;
24
+
25
+ for (const model of models) {
26
+ if (model.hasLegacyMarker) {
27
+ // INV-A: 免除だが可視化。claim の有無に関わらず legacy として計上する
28
+ // (マーカーは「このファイルはまだゲートされていない負債」の宣言であるため)。
29
+ legacyCount += 1;
30
+ warnings.push({
31
+ severity: "warning",
32
+ sourcePath: model.path,
33
+ message: `ungated-legacy coverage_report (attestation ゲート未適用の負債): ${model.path}`,
34
+ suggestion:
35
+ "各 ✅ 主張に <!-- @attestation <id> --> を付与し、@coverage-gating: ungated-legacy マーカーを除去して段階返済すること。",
36
+ });
37
+ continue;
38
+ }
39
+
40
+ // INV-B / INV-C: マーカー無しファイルの各 ✅ claim を検査する。
41
+ for (const claim of model.claims) {
42
+ if (!claim.hasAttestationRef) {
43
+ violations.push({
44
+ severity: "error",
45
+ sourcePath: model.path,
46
+ message: `${model.path}:${claim.lineNumber} の ✅ 主張に attestation 参照がありません(bare ✅ は fail-closed)。`,
47
+ suggestion:
48
+ "✅ 主張に <!-- @attestation <id> --> を付与するか、未返済なら <!-- @coverage-gating: ungated-legacy --> マーカーで免除(負債可視化)すること。",
49
+ });
50
+ }
51
+ }
52
+ }
53
+
54
+ return CoverageGatingReport.create(violations, warnings, legacyCount);
55
+ }
56
+ }
@@ -0,0 +1,118 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-259
4
+
5
+ /**
6
+ * WI-259 / ADR-030 §Decision.3.④ — advisory インジェクションスキャナ(L3-006)の判定ドメインサービス。
7
+ *
8
+ * 指示搭載ファイル群に対し既知のインジェクションパターンを行単位で照合する純粋サービス。
9
+ * INV-A: 生成する finding は必ず severity='warning'(error / violation を一切生成しない — §4.(b))。
10
+ * INV-B: HTML コメント内の指示上書きは html-comment-instruction に一本化し instruction-override として二重報告しない。
11
+ * INV-C: どのパターンにも該当しない対象は finding を生成しない(無音 → pass)。
12
+ *
13
+ * パターンは narrow に設計し、自リポジトリの正当な文書(散文)に誤検知しないことを実 corpus で実証する。
14
+ */
15
+
16
+ import {
17
+ type InjectionFinding,
18
+ InjectionScanReport,
19
+ type InjectionScanTarget,
20
+ } from "../value-objects/injection-scan-report.js";
21
+
22
+ /** 指示上書きフレーズ(英/日)。narrow な定型のみ。 */
23
+ const OVERRIDE_PATTERNS: readonly RegExp[] = [
24
+ /ignore\s+(?:all\s+|any\s+)?(?:previous|prior|above)\s+(?:instructions|rules)/i,
25
+ /disregard\s+(?:your|all)\s+(?:instructions|training)/i,
26
+ /これまでの指示を無視/,
27
+ /以前の指示を無視/,
28
+ /上記の指示を無視/,
29
+ /指示を(?:全て|すべて)無視/,
30
+ /システムプロンプトを無視/,
31
+ ];
32
+
33
+ /** HTML コメントを含む行か(`<!--` の存在で判定。行内コメント・複数行コメント開始のいずれも拾う)。 */
34
+ const HTML_COMMENT_LINE = /<!--/;
35
+
36
+ /** 不可視 Unicode: zero-width (U+200B-U+200D, U+FEFF) + bidi 制御 (U+202A-U+202E, U+2066-U+2069)。 */
37
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: bidi/zero-width 制御文字の検出が目的
38
+ const INVISIBLE_UNICODE = /[​-‍‪-‮⁦-⁩]/;
39
+
40
+ /** 連続 200 文字以上の base64 文字列塊。 */
41
+ const BASE64_BLOB = /[A-Za-z0-9+/]{200,}={0,2}/;
42
+
43
+ export class InjectionPatternScanService {
44
+ scan(targets: readonly InjectionScanTarget[]): InjectionScanReport {
45
+ const findings: InjectionFinding[] = [];
46
+
47
+ for (const target of targets) {
48
+ const lines = target.content.split(/\r?\n/);
49
+ for (let i = 0; i < lines.length; i++) {
50
+ const line = lines[i];
51
+ const lineNumber = i + 1;
52
+
53
+ const hasOverride = OVERRIDE_PATTERNS.some((pattern) => pattern.test(line));
54
+ if (hasOverride) {
55
+ // INV-B: HTML コメント内の指示上書きは html-comment-instruction に一本化する。
56
+ if (HTML_COMMENT_LINE.test(line)) {
57
+ findings.push(
58
+ this.finding(
59
+ "html-comment-instruction",
60
+ target.path,
61
+ lineNumber,
62
+ "HTML コメント内にエージェント宛ての指示上書きフレーズが埋め込まれています。",
63
+ "隠蔽された指示の可能性があります。人間レビューで意図を確認してください(advisory)。",
64
+ ),
65
+ );
66
+ } else {
67
+ findings.push(
68
+ this.finding(
69
+ "instruction-override",
70
+ target.path,
71
+ lineNumber,
72
+ "指示上書きフレーズ(例: ignore previous instructions / これまでの指示を無視)を検出しました。",
73
+ "インジェクションの可能性があります。人間レビューで意図を確認してください(advisory)。",
74
+ ),
75
+ );
76
+ }
77
+ }
78
+
79
+ if (INVISIBLE_UNICODE.test(line)) {
80
+ findings.push(
81
+ this.finding(
82
+ "invisible-unicode",
83
+ target.path,
84
+ lineNumber,
85
+ "不可視 Unicode 文字(zero-width / bidi 制御)を検出しました。",
86
+ "見えない文字で指示を隠蔽している可能性があります。人間レビューで確認してください(advisory)。",
87
+ ),
88
+ );
89
+ }
90
+
91
+ if (BASE64_BLOB.test(line)) {
92
+ findings.push(
93
+ this.finding(
94
+ "base64-blob",
95
+ target.path,
96
+ lineNumber,
97
+ "連続 200 文字以上の base64 らしき塊を検出しました。",
98
+ "エンコードされた指示・ペイロードの可能性があります。人間レビューで確認してください(advisory)。",
99
+ ),
100
+ );
101
+ }
102
+ }
103
+ }
104
+
105
+ return InjectionScanReport.create(findings);
106
+ }
107
+
108
+ private finding(
109
+ kind: InjectionFinding["kind"],
110
+ sourcePath: string,
111
+ lineNumber: number,
112
+ message: string,
113
+ suggestion: string,
114
+ ): InjectionFinding {
115
+ // INV-A: severity は必ず 'warning'。
116
+ return { kind, severity: "warning", sourcePath, lineNumber, message, suggestion };
117
+ }
118
+ }
@@ -0,0 +1,67 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-258
4
+
5
+ /**
6
+ * WI-258 / ADR-030 §Decision.3.② — coverage_report の attestation ゲート(L2-016)用ドメインモデル。
7
+ *
8
+ * coverage_report.md の ✅ 主張に attestation 参照(`<!-- @attestation <id> -->`)を要求する
9
+ * anti-laundering の value-object 群。L2 は参照の存在・形状のみを検証し(bare ✅ を fail-closed で遮断)、
10
+ * attestation レコードとの authoritative 突合は L3 が担う(ADR-030)。
11
+ */
12
+
13
+ /** 1 件の ✅ 主張(AC が「達成」と主張する行)。 */
14
+ export interface CoverageClaim {
15
+ /** ✅ を含む行番号(1 起点)。 */
16
+ readonly lineNumber: number;
17
+ /** 同一行 or 直前の連続コメント行に `@attestation` 参照があるか。 */
18
+ readonly hasAttestationRef: boolean;
19
+ }
20
+
21
+ /** 1 coverage_report ファイルの走査結果。 */
22
+ export interface CoverageReportGatingModel {
23
+ readonly path: string;
24
+ /** `<!-- @coverage-gating: ungated-legacy -->` マーカー(ファイル全体免除)の有無。 */
25
+ readonly hasLegacyMarker: boolean;
26
+ readonly claims: readonly CoverageClaim[];
27
+ }
28
+
29
+ /** ゲート判定の 1 finding。 */
30
+ export interface CoverageGatingFinding {
31
+ readonly severity: "error" | "warning";
32
+ readonly sourcePath: string;
33
+ readonly message: string;
34
+ readonly suggestion: string;
35
+ }
36
+
37
+ /**
38
+ * ゲート判定レポート。violations は fail-closed の error、warnings は legacy 可視化。
39
+ */
40
+ export class CoverageGatingReport {
41
+ readonly violations: readonly CoverageGatingFinding[];
42
+ readonly warnings: readonly CoverageGatingFinding[];
43
+ readonly legacyCount: number;
44
+
45
+ private constructor(
46
+ violations: readonly CoverageGatingFinding[],
47
+ warnings: readonly CoverageGatingFinding[],
48
+ legacyCount: number,
49
+ ) {
50
+ this.violations = Object.freeze([...violations]);
51
+ this.warnings = Object.freeze([...warnings]);
52
+ this.legacyCount = legacyCount;
53
+ Object.freeze(this);
54
+ }
55
+
56
+ static create(
57
+ violations: readonly CoverageGatingFinding[],
58
+ warnings: readonly CoverageGatingFinding[],
59
+ legacyCount: number,
60
+ ): CoverageGatingReport {
61
+ return new CoverageGatingReport(violations, warnings, legacyCount);
62
+ }
63
+
64
+ hasViolations(): boolean {
65
+ return this.violations.length > 0;
66
+ }
67
+ }