phasegate 0.229.0 → 0.264.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 (154) hide show
  1. package/CHANGELOG.md +73 -1
  2. package/README.ja.md +31 -1
  3. package/README.md +30 -0
  4. package/docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md +155 -0
  5. package/docs/ADR/032-world-node-identity.md +198 -0
  6. package/docs/ADR/033-world-snapshot-canonicalization.md +246 -0
  7. package/docs/ADR/034-world-constraint-semantics.md +218 -0
  8. package/docs/ADR/035-world-adoption-baseline-and-waiver.md +341 -0
  9. package/docs/ADR/036-world-model-and-doc-freshness.md +169 -0
  10. package/docs/ADR/037-world-cli-and-output-contract.md +398 -0
  11. package/docs/contracts/attestation-v2.schema.json +110 -0
  12. package/docs/contracts/requirement-test-matrix.schema.json +15 -0
  13. package/docs/contracts/world-baseline.schema.json +35 -0
  14. package/docs/contracts/world-constraints.schema.json +56 -0
  15. package/docs/contracts/world-debts.schema.json +32 -0
  16. package/docs/contracts/world-obligation-report.schema.json +259 -0
  17. package/docs/contracts/world-waivers.schema.json +32 -0
  18. package/docs/guide/cli-reference.md +45 -0
  19. package/docs/guide/configuration.md +56 -0
  20. package/docs/templates/ci/aidlc-gate.yml +42 -2
  21. package/package.json +1 -1
  22. package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
  23. package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
  24. package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
  25. package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
  26. package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
  27. package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
  28. package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
  29. package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
  30. package/scripts/harness/attestation/application/ports/sha256-capability.ts +25 -0
  31. package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
  32. package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
  33. package/scripts/harness/attestation/composition-root.ts +19 -4
  34. package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
  35. package/scripts/harness/attestation/index.ts +13 -2
  36. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts +6 -6
  37. package/scripts/harness/attestation/infrastructure/adapters/node-crypto-sha256-capability.ts +19 -0
  38. package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
  39. package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
  40. package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
  41. package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
  42. package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
  43. package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
  44. package/scripts/harness/config-foundation/index.ts +14 -15
  45. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
  46. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
  47. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
  48. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
  49. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
  50. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
  51. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +4 -1
  52. package/scripts/harness/integrations/pre-commit.ts +169 -27
  53. package/scripts/harness/main.ts +276 -126
  54. package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +11 -0
  55. package/scripts/harness/nyquist-validation/application/usecases/check-ac-coverage-gate-usecase.ts +6 -0
  56. package/scripts/harness/nyquist-validation/application/usecases/generate-requirement-test-matrix-usecase.ts +8 -4
  57. package/scripts/harness/nyquist-validation/domain/entities/story-mapping.ts +29 -2
  58. package/scripts/harness/nyquist-validation/domain/services/ac-coverage-gate-policy.ts +28 -0
  59. package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +71 -4
  60. package/scripts/harness/nyquist-validation/infrastructure/schema/matrix-schema-loader.ts +4 -0
  61. package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
  62. package/scripts/harness/traceability-model/application/dto/traceability-world-read-dto.ts +67 -0
  63. package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
  64. package/scripts/harness/traceability-model/application/facades/traceability-world-read-facade.ts +372 -0
  65. package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
  66. package/scripts/harness/traceability-model/application/ports/traceability-world-read-source-port.ts +61 -0
  67. package/scripts/harness/traceability-model/composition-root.ts +26 -5
  68. package/scripts/harness/traceability-model/index.ts +26 -6
  69. package/scripts/harness/traceability-model/infrastructure/adapters/file-system-traceability-world-read-adapter.ts +223 -0
  70. package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
  71. package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +86 -8
  72. package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
  73. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
  74. package/scripts/harness/validator-system/composition-root.ts +21 -6
  75. package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
  76. package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
  77. package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
  78. package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
  79. package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
  80. package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
  81. package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
  82. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
  83. package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
  84. package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
  85. package/scripts/harness/world-model/application/dto/world-inspection-dto.ts +43 -0
  86. package/scripts/harness/world-model/application/dto/world-obligation-report-dto.ts +54 -0
  87. package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +127 -0
  88. package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
  89. package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
  90. package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
  91. package/scripts/harness/world-model/application/ports/obligation-report-writer-port.ts +7 -0
  92. package/scripts/harness/world-model/application/ports/world-control-declaration-repository-port.ts +57 -0
  93. package/scripts/harness/world-model/application/ports/world-fact-source-port.ts +17 -0
  94. package/scripts/harness/world-model/application/usecases/build-snapshot-use-case.ts +111 -0
  95. package/scripts/harness/world-model/application/usecases/derive-obligations-use-case.ts +155 -0
  96. package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +146 -0
  97. package/scripts/harness/world-model/application/usecases/inspect-world-use-case.ts +74 -0
  98. package/scripts/harness/world-model/application/usecases/pin-constraint-endpoint-use-case.ts +139 -0
  99. package/scripts/harness/world-model/composition-root.ts +247 -0
  100. package/scripts/harness/world-model/domain/entities/constraint-record.ts +148 -0
  101. package/scripts/harness/world-model/domain/entities/control-declarations.ts +274 -0
  102. package/scripts/harness/world-model/domain/entities/edge.ts +41 -0
  103. package/scripts/harness/world-model/domain/entities/extraction-diagnostic.ts +60 -0
  104. package/scripts/harness/world-model/domain/entities/snapshot.ts +75 -0
  105. package/scripts/harness/world-model/domain/entities/world-node.ts +210 -0
  106. package/scripts/harness/world-model/domain/ports/world-hashing-port.ts +8 -0
  107. package/scripts/harness/world-model/domain/services/canonical-json-serializer.ts +113 -0
  108. package/scripts/harness/world-model/domain/services/constraint-evaluator.ts +486 -0
  109. package/scripts/harness/world-model/domain/services/obligation-derivation-service.ts +199 -0
  110. package/scripts/harness/world-model/domain/services/policy-inputs-digest-deriver.ts +66 -0
  111. package/scripts/harness/world-model/domain/services/snapshot-root-deriver.ts +218 -0
  112. package/scripts/harness/world-model/domain/services/text-content-normalizer.ts +30 -0
  113. package/scripts/harness/world-model/domain/services/violation-fingerprint-deriver.ts +183 -0
  114. package/scripts/harness/world-model/domain/value-objects/artifact-kind.ts +58 -0
  115. package/scripts/harness/world-model/domain/value-objects/change-provenance.ts +137 -0
  116. package/scripts/harness/world-model/domain/value-objects/corpus-role.ts +57 -0
  117. package/scripts/harness/world-model/domain/value-objects/declared-key.ts +35 -0
  118. package/scripts/harness/world-model/domain/value-objects/evaluation-id.ts +41 -0
  119. package/scripts/harness/world-model/domain/value-objects/explicit-constraint-relation.ts +53 -0
  120. package/scripts/harness/world-model/domain/value-objects/explicit-node-alias.ts +30 -0
  121. package/scripts/harness/world-model/domain/value-objects/node-pin.ts +34 -0
  122. package/scripts/harness/world-model/domain/value-objects/path-key.ts +103 -0
  123. package/scripts/harness/world-model/domain/value-objects/sha256-digest.ts +39 -0
  124. package/scripts/harness/world-model/domain/value-objects/violation-fingerprint.ts +36 -0
  125. package/scripts/harness/world-model/domain/value-objects/wcr-rule-id.ts +59 -0
  126. package/scripts/harness/world-model/domain/value-objects/world-node-id.ts +222 -0
  127. package/scripts/harness/world-model/index.ts +33 -0
  128. package/scripts/harness/world-model/infrastructure/adapters/adr-fact-extractor.ts +27 -0
  129. package/scripts/harness/world-model/infrastructure/adapters/assembled-world-fact-source.ts +17 -0
  130. package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +323 -0
  131. package/scripts/harness/world-model/infrastructure/adapters/attestation-sha256-world-hashing-adapter.ts +15 -0
  132. package/scripts/harness/world-model/infrastructure/adapters/composite-design-fact-source.ts +23 -0
  133. package/scripts/harness/world-model/infrastructure/adapters/design-corpus-fact-extractor.ts +285 -0
  134. package/scripts/harness/world-model/infrastructure/adapters/design-fact-extraction.ts +63 -0
  135. package/scripts/harness/world-model/infrastructure/adapters/file-system-obligation-report-writer-adapter.ts +37 -0
  136. package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +332 -0
  137. package/scripts/harness/world-model/infrastructure/adapters/integrity-manifest-fact-extractor.ts +101 -0
  138. package/scripts/harness/world-model/infrastructure/adapters/json-fact-extractor-support.ts +151 -0
  139. package/scripts/harness/world-model/infrastructure/adapters/markdown-design-fact-extractor.ts +493 -0
  140. package/scripts/harness/world-model/infrastructure/adapters/matrix-fact-extractor.ts +283 -0
  141. package/scripts/harness/world-model/infrastructure/adapters/product-fact-extractor.ts +29 -0
  142. package/scripts/harness/world-model/infrastructure/adapters/proposal-fact-extractor.ts +29 -0
  143. package/scripts/harness/world-model/infrastructure/adapters/runtime-fact-extraction.ts +19 -0
  144. package/scripts/harness/world-model/infrastructure/adapters/source-metadata-fact-extractor.ts +22 -0
  145. package/scripts/harness/world-model/infrastructure/adapters/test-reference-source-fact-extractor.ts +22 -0
  146. package/scripts/harness/world-model/infrastructure/adapters/traceability-design-fact-adapter.ts +112 -0
  147. package/scripts/harness/world-model/infrastructure/adapters/traceability-world-read-facade-merger.ts +38 -0
  148. package/scripts/harness/world-model/infrastructure/adapters/type-script-source-fact-extractor.ts +236 -0
  149. package/scripts/harness/world-model/infrastructure/adapters/unit-fact-extractor.ts +71 -0
  150. package/scripts/harness/world-model/infrastructure/adapters/world-control-declaration-mapper.ts +383 -0
  151. package/scripts/harness/world-model/presentation/cli/world-command-support.ts +60 -0
  152. package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +109 -0
  153. package/scripts/harness/world-model/presentation/cli/world-inspect-command-handler.ts +194 -0
  154. package/scripts/harness/world-model/presentation/cli/world-pin-command-handler.ts +100 -0
@@ -5,6 +5,9 @@
5
5
  * DI 組み立て — validator-system の全依存関係を構築する
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
+ * @work-item-id WI-301
9
+ * @work-item-id WI-302
10
+ * @work-item-id WI-305
8
11
  */
9
12
 
10
13
  import { join } from "node:path";
@@ -17,6 +20,7 @@ import { RunL2ValidatorsUseCase } from "./application/use-cases/run-l2-validator
17
20
  import { RunL3ValidatorsUseCase } from "./application/use-cases/run-l3-validators-usecase.js";
18
21
  import { RunL4ValidatorsUseCase } from "./application/use-cases/run-l4-validators-usecase.js";
19
22
  import { RunQuickModeUseCase } from "./application/use-cases/run-quick-mode-usecase.js";
23
+ import { DesignChangeDeclarationPolicy } from "./domain/services/design-change-declaration-policy.js";
20
24
  import {
21
25
  ArchitectureSemanticAnalysisService,
22
26
  type ArchitectureSemanticPolicy,
@@ -55,6 +59,8 @@ import { PhaseDependencyPhaseGatePolicyAdapter } from "./infrastructure/adapters
55
59
  import { SourceFileTextScannerAdapter } from "./infrastructure/adapters/source-file-text-scanner-adapter.js";
56
60
  import { TraceabilityMetadataPolicyAdapter } from "./infrastructure/adapters/traceability-metadata-policy-adapter.js";
57
61
  import { TraceabilityWorkItemStatusPolicyAdapter } from "./infrastructure/adapters/traceability-work-item-status-policy-adapter.js";
62
+ import { WorldModelConstraintAdmissionAdapter } from "./infrastructure/adapters/world-model-constraint-admission-adapter.js";
63
+ import { WorldModelConstraintRederivationAdapter } from "./infrastructure/adapters/world-model-constraint-rederivation-adapter.js";
58
64
  import { ReportValidationResultsHandler } from "./presentation/handlers/report-validation-results-handler.js";
59
65
  import { RunQuickModeHandler } from "./presentation/handlers/run-quick-mode-handler.js";
60
66
  import { RunValidatorsHandler } from "./presentation/handlers/run-validators-handler.js";
@@ -99,12 +105,6 @@ const DEFAULT_CONFIG = {
99
105
 
100
106
  /** バリデータ定義カタログ */
101
107
  export function buildDefaultRegistry(): ValidatorRegistry {
102
- const defaultRule = ValidationRule.create({
103
- ruleName: "default-rule",
104
- errorTemplate: { code: "L2-001", severity: "error", messageTemplate: "{{message}}" },
105
- fixExample: null,
106
- });
107
-
108
108
  const createDef = (
109
109
  id: string,
110
110
  layer: "L2" | "L3" | "L4",
@@ -134,6 +134,7 @@ export function buildDefaultRegistry(): ValidatorRegistry {
134
134
  createDef("L2-015", "L2", "always", "ContractTraceabilityPolicyPort"),
135
135
  // WI-258 / ADR-030 §Decision.3.②: L2-016 (coverage-attestation-gating, fail-closed, default-ON)。
136
136
  createDef("L2-016", "L2", "always", "CoverageAttestationGatingPolicyPort"),
137
+ createDef("L2-017", "L2", "always", "WorldConstraintAdmissionPolicyPort"),
137
138
  createDef("L3-001", "L3", "always"),
138
139
  createDef("L3-002", "L3", "strictOnly"),
139
140
  createDef("L3-003", "L3", "always"),
@@ -146,6 +147,7 @@ export function buildDefaultRegistry(): ValidatorRegistry {
146
147
  // WI-268 / ADR-030 §Decision.1・§Decision.3.② 第2段: L3-007 (coverage-attestation-verification)
147
148
  // は fail-closed / default-ON。L2-016 の authoritative 相棒。
148
149
  createDef("L3-007", "L3", "always", "CoverageAttestationVerificationPolicyPort"),
150
+ createDef("L3-008", "L3", "always", "WorldConstraintRederivationPolicyPort"),
149
151
  createDef("L4-001", "L4", "always"),
150
152
  createDef("L4-002", "L4", "always"),
151
153
  createDef("L4-003", "L4", "strictOnly"),
@@ -170,6 +172,7 @@ export interface ValidatorSystemModule {
170
172
  aggregateValidationResultsUseCase: AggregateValidationResultsUseCase;
171
173
  runFullValidationUseCase: RunFullValidationUseCase;
172
174
  driftDetectionService: DriftDetectionService;
175
+ designChangeDeclarationPolicy: DesignChangeDeclarationPolicy;
173
176
  handlers: {
174
177
  runValidators: RunValidatorsHandler;
175
178
  runQuickMode: RunQuickModeHandler;
@@ -184,6 +187,7 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
184
187
  const defaultFailOnWarning = configData.validate?.failOnWarning ?? false;
185
188
  const registry = buildDefaultRegistry();
186
189
  const executionService = new ValidatorExecutionService({ configPort });
190
+ const designChangeDeclarationPolicy = new DesignChangeDeclarationPolicy();
187
191
  const contractMapper = new ValidationResultContractMapper();
188
192
  const phaseGatePolicyPort = new PhaseDependencyPhaseGatePolicyAdapter();
189
193
  const metadataPolicyPort = new TraceabilityMetadataPolicyAdapter();
@@ -201,6 +205,14 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
201
205
  // WI-258 / ADR-030 §Decision.3.②: L2-016 (coverage-attestation-gating) 用アダプタ。
202
206
  // docs/product/construction/*​/coverage_report.md を cwd 起点で走査する(targetPaths 非依存)。
203
207
  const coverageAttestationGatingPolicyPort = new FileSystemCoverageAttestationGatingAdapter(process.cwd());
208
+ const worldConstraintAdmissionPolicyPort = new WorldModelConstraintAdmissionAdapter({
209
+ rootDir: process.cwd(),
210
+ resolvedConfig: (configData as { world?: import("../world-model/index.js").WorldResolvedConfigInput }).world,
211
+ });
212
+ const worldConstraintRederivationPolicyPort = new WorldModelConstraintRederivationAdapter({
213
+ rootDir: process.cwd(),
214
+ resolvedConfig: (configData as { world?: import("../world-model/index.js").WorldResolvedConfigInput }).world,
215
+ });
204
216
  // WI-259 / ADR-030 §Decision.3.④: L3-006 (injection-scan, advisory) 用アダプタ。
205
217
  // 指示搭載ファイル群(skills/**​/SKILL.md / CLAUDE.md / AGENTS.md / agent-context / .claude/settings.json)を
206
218
  // cwd 起点で走査する(targetPaths 非依存)。
@@ -249,6 +261,7 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
249
261
  workItemStatusPolicyPort,
250
262
  contractTraceabilityPolicyPort,
251
263
  coverageAttestationGatingPolicyPort,
264
+ worldConstraintAdmissionPolicyPort,
252
265
  });
253
266
 
254
267
  // WI-227 / H16-03: L3-005 のスコープ対象 story-id を config から取得(既定 [])。
@@ -267,6 +280,7 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
267
280
  performanceScannerPort,
268
281
  injectionScanPolicyPort,
269
282
  coverageAttestationVerificationPolicyPort,
283
+ worldConstraintRederivationPolicyPort,
270
284
  acBoundStories,
271
285
  });
272
286
 
@@ -367,6 +381,7 @@ export function createValidatorSystemModule(config?: object): ValidatorSystemMod
367
381
  aggregateValidationResultsUseCase,
368
382
  runFullValidationUseCase,
369
383
  driftDetectionService,
384
+ designChangeDeclarationPolicy,
370
385
  handlers,
371
386
  };
372
387
  }
@@ -0,0 +1,28 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-301
4
+
5
+ export type WorldAdmissionClassification = "adopted-legacy" | "new-structural" | "invalid-declaration" | "waived";
6
+
7
+ export interface WorldConstraintAdmissionObligation {
8
+ readonly ruleId: string;
9
+ readonly violationFingerprint: string;
10
+ readonly constraintId: string | null;
11
+ readonly classification: WorldAdmissionClassification;
12
+ }
13
+
14
+ export interface WorldConstraintAdmissionDiagnostic {
15
+ readonly code: string;
16
+ readonly path: string;
17
+ readonly message: string;
18
+ readonly scope: "constraint" | "other";
19
+ }
20
+
21
+ export interface WorldConstraintAdmissionObservation {
22
+ readonly obligations: readonly WorldConstraintAdmissionObligation[];
23
+ readonly diagnostics: readonly WorldConstraintAdmissionDiagnostic[];
24
+ }
25
+
26
+ export interface WorldConstraintAdmissionPolicyPort {
27
+ collect(): Promise<WorldConstraintAdmissionObservation>;
28
+ }
@@ -0,0 +1,11 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-302
4
+
5
+ import type { WorldConstraintAdmissionObservation } from "./world-constraint-admission-policy-port.js";
6
+
7
+ export type WorldConstraintRederivationObservation = WorldConstraintAdmissionObservation;
8
+
9
+ export interface WorldConstraintRederivationPolicyPort {
10
+ collect(): Promise<WorldConstraintRederivationObservation>;
11
+ }
@@ -0,0 +1,75 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-305
4
+
5
+ export interface DesignChangedFragmentInput {
6
+ readonly corpusRole: "product" | "inception";
7
+ readonly declaredKey: string;
8
+ readonly path: string;
9
+ readonly workItemIds: readonly string[];
10
+ }
11
+
12
+ export interface DesignPinnedEndpointInput {
13
+ readonly constraintId: string;
14
+ readonly endpoint: "claimant" | "premise";
15
+ readonly corpusRole: "product" | "inception";
16
+ readonly declaredKey: string;
17
+ }
18
+
19
+ export interface DesignChangeDeclarationFinding {
20
+ readonly code: "design-change-declaration-missing";
21
+ readonly corpusRole: "product" | "inception";
22
+ readonly declaredKey: string;
23
+ readonly path: string;
24
+ readonly expectedWorkItemIds: readonly string[];
25
+ readonly constraintIds: readonly string[];
26
+ }
27
+
28
+ export interface DesignChangeDeclarationEvaluation {
29
+ readonly checkedFragmentCount: number;
30
+ readonly findings: readonly DesignChangeDeclarationFinding[];
31
+ }
32
+
33
+ export interface DesignChangeDeclarationInput {
34
+ readonly changedFragments: readonly DesignChangedFragmentInput[];
35
+ readonly pinnedEndpoints: readonly DesignPinnedEndpointInput[];
36
+ readonly trailerWorkItemIds: readonly string[];
37
+ }
38
+
39
+ const compare = (left: string, right: string): number => (left < right ? -1 : left > right ? 1 : 0);
40
+ const keyOf = (value: { readonly corpusRole: string; readonly declaredKey: string }): string =>
41
+ `${value.corpusRole}\u0000${value.declaredKey}`;
42
+ const uniqueSorted = (values: readonly string[]): readonly string[] =>
43
+ Object.freeze([...new Set(values)].sort(compare));
44
+
45
+ export class DesignChangeDeclarationPolicy {
46
+ evaluate(input: DesignChangeDeclarationInput): DesignChangeDeclarationEvaluation {
47
+ const endpointsByFragment = new Map<string, DesignPinnedEndpointInput[]>();
48
+ for (const endpoint of input.pinnedEndpoints) {
49
+ const key = keyOf(endpoint);
50
+ const current = endpointsByFragment.get(key) ?? [];
51
+ current.push(endpoint);
52
+ endpointsByFragment.set(key, current);
53
+ }
54
+ const trailerIds = new Set(input.trailerWorkItemIds);
55
+ const pinnedChanges = input.changedFragments
56
+ .filter((fragment) => endpointsByFragment.has(keyOf(fragment)))
57
+ .sort((left, right) => compare(keyOf(left), keyOf(right)) || compare(left.path, right.path));
58
+ const findings = pinnedChanges.flatMap((fragment): readonly DesignChangeDeclarationFinding[] => {
59
+ if (fragment.workItemIds.some((workItemId) => trailerIds.has(workItemId))) return [];
60
+ return [
61
+ Object.freeze({
62
+ code: "design-change-declaration-missing" as const,
63
+ corpusRole: fragment.corpusRole,
64
+ declaredKey: fragment.declaredKey,
65
+ path: fragment.path,
66
+ expectedWorkItemIds: uniqueSorted(fragment.workItemIds),
67
+ constraintIds: uniqueSorted(
68
+ (endpointsByFragment.get(keyOf(fragment)) ?? []).map((endpoint) => endpoint.constraintId),
69
+ ),
70
+ }),
71
+ ];
72
+ });
73
+ return Object.freeze({ checkedFragmentCount: pinnedChanges.length, findings: Object.freeze(findings) });
74
+ }
75
+ }
@@ -0,0 +1,78 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-301
4
+
5
+ import type {
6
+ WorldAdmissionClassification,
7
+ WorldConstraintAdmissionObservation,
8
+ } from "../ports/world-constraint-admission-policy-port.js";
9
+
10
+ export interface WorldConstraintAdmissionFinding {
11
+ readonly severity: "error" | "warning";
12
+ readonly ruleId: string | null;
13
+ readonly violationFingerprint: string | null;
14
+ readonly constraintId: string | null;
15
+ readonly classification: WorldAdmissionClassification | "constraint-input-invalid" | "local-evaluation-incomplete";
16
+ readonly message: string;
17
+ readonly suggestion: string;
18
+ readonly sourcePath: string | null;
19
+ }
20
+
21
+ const LOCAL_TRUST_NOTICE = "Local L2 evidence can be forged; authoritative L3 re-derivation is required.";
22
+ const AUTHORITATIVE_SUGGESTION =
23
+ "Repair the declaration or structural finding, then rely on authoritative L3 clean-corpus re-derivation.";
24
+
25
+ const compareNullable = (left: string | null, right: string | null): number =>
26
+ (left ?? "") < (right ?? "") ? -1 : (left ?? "") > (right ?? "") ? 1 : 0;
27
+
28
+ export class WorldConstraintAdmissionService {
29
+ evaluate(observation: WorldConstraintAdmissionObservation): readonly WorldConstraintAdmissionFinding[] {
30
+ const obligationFindings = observation.obligations.map((obligation): WorldConstraintAdmissionFinding => {
31
+ const blocking =
32
+ obligation.classification === "new-structural" || obligation.classification === "invalid-declaration";
33
+ const label =
34
+ obligation.classification === "invalid-declaration"
35
+ ? "non-adoptable invalid World constraint declaration"
36
+ : obligation.classification === "new-structural"
37
+ ? "new World structural violation"
38
+ : obligation.classification === "adopted-legacy"
39
+ ? "adopted legacy World violation"
40
+ : "actively waived World violation";
41
+ return Object.freeze({
42
+ severity: blocking ? "error" : "warning",
43
+ ruleId: obligation.ruleId,
44
+ violationFingerprint: obligation.violationFingerprint,
45
+ constraintId: obligation.constraintId,
46
+ classification: obligation.classification,
47
+ message: `L2 local fast-path reports ${label}: ${obligation.ruleId} ${obligation.violationFingerprint}. ${LOCAL_TRUST_NOTICE}`,
48
+ suggestion: AUTHORITATIVE_SUGGESTION,
49
+ sourcePath: null,
50
+ });
51
+ });
52
+ const diagnosticFindings = observation.diagnostics.map((item): WorldConstraintAdmissionFinding => {
53
+ const constraintInput = item.scope === "constraint";
54
+ return Object.freeze({
55
+ severity: constraintInput ? "error" : "warning",
56
+ ruleId: constraintInput ? "WCR-001" : null,
57
+ violationFingerprint: null,
58
+ constraintId: null,
59
+ classification: constraintInput ? "constraint-input-invalid" : "local-evaluation-incomplete",
60
+ message: constraintInput
61
+ ? `L2 local fast-path cannot admit constraint declaration input (${item.code}): ${item.message}. ${LOCAL_TRUST_NOTICE}`
62
+ : `L2 local fast-path could not complete non-constraint policy observation (${item.code}): ${item.message}. ${LOCAL_TRUST_NOTICE}`,
63
+ suggestion: AUTHORITATIVE_SUGGESTION,
64
+ sourcePath: item.path,
65
+ });
66
+ });
67
+
68
+ return Object.freeze(
69
+ [...obligationFindings, ...diagnosticFindings].sort(
70
+ (left, right) =>
71
+ compareNullable(left.ruleId, right.ruleId) ||
72
+ compareNullable(left.violationFingerprint, right.violationFingerprint) ||
73
+ compareNullable(left.sourcePath, right.sourcePath) ||
74
+ left.classification.localeCompare(right.classification),
75
+ ),
76
+ );
77
+ }
78
+ }
@@ -0,0 +1,76 @@
1
+ // @unit validator-system
2
+ // @layer domain
3
+ // @work-item-id WI-302
4
+
5
+ import type { WorldAdmissionClassification } from "../ports/world-constraint-admission-policy-port.js";
6
+ import type { WorldConstraintRederivationObservation } from "../ports/world-constraint-rederivation-policy-port.js";
7
+
8
+ export interface WorldConstraintRederivationFinding {
9
+ readonly severity: "error" | "warning";
10
+ readonly ruleId: string | null;
11
+ readonly violationFingerprint: string | null;
12
+ readonly constraintId: string | null;
13
+ readonly classification:
14
+ | WorldAdmissionClassification
15
+ | "constraint-input-invalid"
16
+ | "authoritative-evaluation-failed";
17
+ readonly message: string;
18
+ readonly suggestion: string;
19
+ readonly sourcePath: string | null;
20
+ }
21
+
22
+ const REPAIR_SUGGESTION =
23
+ "Repair the versioned declaration or current corpus finding, then rerun authoritative L3 clean-corpus re-derivation.";
24
+
25
+ const compareNullable = (left: string | null, right: string | null): number =>
26
+ (left ?? "") < (right ?? "") ? -1 : (left ?? "") > (right ?? "") ? 1 : 0;
27
+
28
+ export class WorldConstraintRederivationService {
29
+ evaluate(observation: WorldConstraintRederivationObservation): readonly WorldConstraintRederivationFinding[] {
30
+ const obligationFindings = observation.obligations.map((obligation): WorldConstraintRederivationFinding => {
31
+ const blocking =
32
+ obligation.classification === "new-structural" || obligation.classification === "invalid-declaration";
33
+ const label =
34
+ obligation.classification === "invalid-declaration"
35
+ ? "non-adoptable invalid World constraint declaration"
36
+ : obligation.classification === "new-structural"
37
+ ? "new World structural violation"
38
+ : obligation.classification === "adopted-legacy"
39
+ ? "adopted legacy World violation"
40
+ : "actively waived World violation";
41
+ return Object.freeze({
42
+ severity: blocking ? "error" : "warning",
43
+ ruleId: obligation.ruleId,
44
+ violationFingerprint: obligation.violationFingerprint,
45
+ constraintId: obligation.constraintId,
46
+ classification: obligation.classification,
47
+ message: `L3 authoritative clean-corpus re-derivation reports ${label}: ${obligation.ruleId} ${obligation.violationFingerprint}.`,
48
+ suggestion: REPAIR_SUGGESTION,
49
+ sourcePath: null,
50
+ });
51
+ });
52
+ const diagnosticFindings = observation.diagnostics.map((item): WorldConstraintRederivationFinding => {
53
+ const constraintInput = item.scope === "constraint";
54
+ return Object.freeze({
55
+ severity: "error",
56
+ ruleId: constraintInput ? "WCR-001" : null,
57
+ violationFingerprint: null,
58
+ constraintId: null,
59
+ classification: constraintInput ? "constraint-input-invalid" : "authoritative-evaluation-failed",
60
+ message: `L3 authoritative clean-corpus re-derivation cannot produce a trustworthy result (${item.code}): ${item.message}.`,
61
+ suggestion: REPAIR_SUGGESTION,
62
+ sourcePath: item.path,
63
+ });
64
+ });
65
+
66
+ return Object.freeze(
67
+ [...obligationFindings, ...diagnosticFindings].sort(
68
+ (left, right) =>
69
+ compareNullable(left.ruleId, right.ruleId) ||
70
+ compareNullable(left.violationFingerprint, right.violationFingerprint) ||
71
+ compareNullable(left.sourcePath, right.sourcePath) ||
72
+ left.classification.localeCompare(right.classification),
73
+ ),
74
+ );
75
+ }
76
+ }
@@ -14,6 +14,8 @@
14
14
  * WI-258 (ADR-030 §Decision.3.②) で L2-016(coverage-attestation-gating, fail-closed)を追加
15
15
  * WI-259 (ADR-030 §Decision.3.④) で L3-006(injection-scan, advisory warning-only)を追加
16
16
  * WI-268 (ADR-030 §Decision.1・§Decision.3.② 第2段) で L3-007(coverage-attestation-verification, fail-closed)を追加
17
+ * WI-301 で L2-017(world-constraint-admission, local fast-path)を追加
18
+ * WI-302 で L3-008(world-constraint-rederivation, authoritative)を追加
17
19
  */
18
20
 
19
21
  export class InvalidValidatorIdError extends Error {
@@ -38,6 +40,7 @@ const VALIDATOR_NAME_MAP: Record<string, string> = {
38
40
  "L2-014": "work-item-status-staleness",
39
41
  "L2-015": "contract-traceability-coverage",
40
42
  "L2-016": "coverage-attestation-gating",
43
+ "L2-017": "world-constraint-admission",
41
44
  "L3-001": "security",
42
45
  "L3-002": "performance",
43
46
  "L3-003": "coverage",
@@ -45,6 +48,7 @@ const VALIDATOR_NAME_MAP: Record<string, string> = {
45
48
  "L3-005": "ac-bound-coverage",
46
49
  "L3-006": "injection-scan",
47
50
  "L3-007": "coverage-attestation-verification",
51
+ "L3-008": "world-constraint-rederivation",
48
52
  "L4-001": "drift-detect",
49
53
  "L4-002": "consistency-check",
50
54
  "L4-003": "dead-code",
@@ -3,28 +3,39 @@
3
3
  * @unit validator-system
4
4
  * @work-item-id WI-156
5
5
  * @work-item-id WI-212
6
+ * @work-item-id WI-301
7
+ * @work-item-id WI-302
6
8
  *
7
9
  * HarnessConfigValidatorConfigAdapter — ValidatorConfigPort実装
8
10
  * HarnessConfigV2からLayerConfig VOを構築する
9
11
  */
10
- import { LayerConfig } from '../../domain/value-objects/layer-config.js';
11
- import { ValidatorId } from '../../domain/value-objects/validator-id.js';
12
- import type { ValidatorConfigPort } from '../../domain/ports/validator-config-port.js';
12
+
13
+ import type { ValidatorConfigPort } from "../../domain/ports/validator-config-port.js";
14
+ import { LayerConfig } from "../../domain/value-objects/layer-config.js";
15
+ import { ValidatorId } from "../../domain/value-objects/validator-id.js";
13
16
 
14
17
  export interface HarnessConfigLayers {
15
18
  L2?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string };
16
- L3?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string; coverageThreshold?: number; bundleSizeLimit?: number };
19
+ L3?: {
20
+ enabled?: boolean;
21
+ validators?: string[];
22
+ strictOnly?: boolean;
23
+ preset?: string;
24
+ coverageThreshold?: number;
25
+ bundleSizeLimit?: number;
26
+ };
17
27
  L4?: { enabled?: boolean; validators?: string[]; strictOnly?: boolean; preset?: string; deadCodeGC?: boolean };
18
28
  }
19
29
 
20
30
  export interface HarnessConfigV2Like {
21
- preset?: 'minimal' | 'standard' | 'strict';
22
- project?: { preset?: 'minimal' | 'standard' | 'strict'; languages?: readonly string[] };
31
+ preset?: "minimal" | "standard" | "strict";
32
+ project?: { preset?: "minimal" | "standard" | "strict"; languages?: readonly string[] };
23
33
  layers?: HarnessConfigLayers;
24
34
  harnesses?: {
25
35
  bundleSizeLimit?: number;
26
36
  deadCodeGC?: boolean;
27
37
  };
38
+ world?: { enabled?: boolean };
28
39
  }
29
40
 
30
41
  export class HarnessConfigValidatorConfigAdapter implements ValidatorConfigPort {
@@ -34,20 +45,23 @@ export class HarnessConfigValidatorConfigAdapter implements ValidatorConfigPort
34
45
  this.config = config;
35
46
  }
36
47
 
37
- async getLayerConfig(layer: 'L2' | 'L3' | 'L4'): Promise<LayerConfig> {
38
- const preset = (this.config.project?.preset ?? this.config.preset ?? 'standard') as 'minimal' | 'standard' | 'strict';
39
- const strictOnly = preset === 'strict';
48
+ async getLayerConfig(layer: "L2" | "L3" | "L4"): Promise<LayerConfig> {
49
+ const preset = (this.config.project?.preset ?? this.config.preset ?? "standard") as
50
+ | "minimal"
51
+ | "standard"
52
+ | "strict";
53
+ const strictOnly = preset === "strict";
40
54
  const layerData = this.config.layers?.[layer] ?? {};
41
55
 
42
56
  const defaultValidators: Record<string, string[]> = {
43
- L2: ['L2-001', 'L2-002', 'L2-003', 'L2-013', 'L2-014', 'L2-015'],
44
- L3: ['L3-001', 'L3-002', 'L3-003', 'L3-004'],
45
- L4: ['L4-001', 'L4-002', 'L4-003', 'L4-004', 'L4-005', 'L4-006'],
57
+ L2: ["L2-001", "L2-002", "L2-003", "L2-013", "L2-014", "L2-015"],
58
+ L3: ["L3-001", "L3-002", "L3-003", "L3-004"],
59
+ L4: ["L4-001", "L4-002", "L4-003", "L4-004", "L4-005", "L4-006"],
46
60
  };
47
61
 
48
62
  const thresholds: Record<string, number> = {};
49
63
 
50
- if (layer === 'L3') {
64
+ if (layer === "L3") {
51
65
  const l3 = this.config.layers?.L3;
52
66
  if (l3?.coverageThreshold !== undefined) thresholds.coverageThreshold = l3.coverageThreshold;
53
67
  if (l3?.bundleSizeLimit !== undefined) thresholds.bundleSizeLimit = l3.bundleSizeLimit;
@@ -56,16 +70,24 @@ export class HarnessConfigValidatorConfigAdapter implements ValidatorConfigPort
56
70
  }
57
71
  }
58
72
 
59
- if (layer === 'L4') {
73
+ if (layer === "L4") {
60
74
  if (this.config.harnesses?.deadCodeGC !== undefined) {
61
75
  thresholds.deadCodeGC = this.config.harnesses.deadCodeGC ? 1 : 0;
62
76
  }
63
77
  }
64
78
 
79
+ const configuredValidatorIds = layerData.validators ?? defaultValidators[layer];
80
+ const automaticWorldValidatorId = layer === "L2" ? "L2-017" : layer === "L3" ? "L3-008" : null;
81
+ const selectedValidatorIds =
82
+ automaticWorldValidatorId === null
83
+ ? configuredValidatorIds
84
+ : this.config.world?.enabled === true
85
+ ? [...configuredValidatorIds, automaticWorldValidatorId]
86
+ : configuredValidatorIds.filter((validatorId) => validatorId !== automaticWorldValidatorId);
65
87
  return LayerConfig.create({
66
88
  layer,
67
89
  enabled: layerData.enabled !== false,
68
- validatorIds: (layerData.validators ?? defaultValidators[layer]).map((idOrName) => this.normalizeValidatorId(idOrName)),
90
+ validatorIds: [...new Set(selectedValidatorIds.map((idOrName) => this.normalizeValidatorId(idOrName)))],
69
91
  thresholds,
70
92
  strictOnly: layerData.strictOnly ?? strictOnly,
71
93
  preset,
@@ -74,7 +96,7 @@ export class HarnessConfigValidatorConfigAdapter implements ValidatorConfigPort
74
96
 
75
97
  async getProjectLanguages(): Promise<readonly string[]> {
76
98
  const languages = this.config.project?.languages;
77
- return languages && languages.length > 0 ? [...languages] : ['typescript'];
99
+ return languages && languages.length > 0 ? [...languages] : ["typescript"];
78
100
  }
79
101
 
80
102
  private normalizeValidatorId(idOrName: string): string {
@@ -0,0 +1,56 @@
1
+ // @unit validator-system
2
+ // @layer infrastructure
3
+ // @work-item-id WI-301
4
+
5
+ import { createWorldModelModule, type WorldResolvedConfigInput } from "../../../world-model/index.js";
6
+ import type {
7
+ WorldConstraintAdmissionObservation,
8
+ WorldConstraintAdmissionPolicyPort,
9
+ } from "../../domain/ports/world-constraint-admission-policy-port.js";
10
+
11
+ interface Options {
12
+ readonly rootDir: string;
13
+ readonly resolvedConfig?: WorldResolvedConfigInput;
14
+ }
15
+
16
+ export class WorldModelConstraintAdmissionAdapter implements WorldConstraintAdmissionPolicyPort {
17
+ constructor(private readonly options: Options) {}
18
+
19
+ async collect(): Promise<WorldConstraintAdmissionObservation> {
20
+ const module = createWorldModelModule({
21
+ rootDir: this.options.rootDir,
22
+ resolvedConfig: this.options.resolvedConfig,
23
+ });
24
+ const actual = await module.deriveWorldObligationsUseCase.execute({ writeReport: false });
25
+ const constraintsPath =
26
+ this.options.resolvedConfig?.declarations?.constraintsPath ?? "phasegate.world-constraints.json";
27
+ if (actual.status === "execution-failure") {
28
+ return Object.freeze({
29
+ obligations: Object.freeze([]),
30
+ diagnostics: Object.freeze(
31
+ actual.diagnostics.map((item) =>
32
+ Object.freeze({
33
+ code: item.code,
34
+ path: item.path,
35
+ message: item.message,
36
+ scope: item.path === constraintsPath ? ("constraint" as const) : ("other" as const),
37
+ }),
38
+ ),
39
+ ),
40
+ });
41
+ }
42
+ return Object.freeze({
43
+ obligations: Object.freeze(
44
+ actual.result.report.structuralObligations.map((item) =>
45
+ Object.freeze({
46
+ ruleId: item.ruleId,
47
+ violationFingerprint: item.violationFingerprint,
48
+ constraintId: item.constraintId,
49
+ classification: item.classification,
50
+ }),
51
+ ),
52
+ ),
53
+ diagnostics: Object.freeze([]),
54
+ });
55
+ }
56
+ }
@@ -0,0 +1,56 @@
1
+ // @unit validator-system
2
+ // @layer infrastructure
3
+ // @work-item-id WI-302
4
+
5
+ import { createWorldModelModule, type WorldResolvedConfigInput } from "../../../world-model/index.js";
6
+ import type {
7
+ WorldConstraintRederivationObservation,
8
+ WorldConstraintRederivationPolicyPort,
9
+ } from "../../domain/ports/world-constraint-rederivation-policy-port.js";
10
+
11
+ interface Options {
12
+ readonly rootDir: string;
13
+ readonly resolvedConfig?: WorldResolvedConfigInput;
14
+ }
15
+
16
+ export class WorldModelConstraintRederivationAdapter implements WorldConstraintRederivationPolicyPort {
17
+ constructor(private readonly options: Options) {}
18
+
19
+ async collect(): Promise<WorldConstraintRederivationObservation> {
20
+ const module = createWorldModelModule({
21
+ rootDir: this.options.rootDir,
22
+ resolvedConfig: this.options.resolvedConfig,
23
+ });
24
+ const actual = await module.deriveWorldObligationsUseCase.execute({ writeReport: false });
25
+ const constraintsPath =
26
+ this.options.resolvedConfig?.declarations?.constraintsPath ?? "phasegate.world-constraints.json";
27
+ if (actual.status === "execution-failure") {
28
+ return Object.freeze({
29
+ obligations: Object.freeze([]),
30
+ diagnostics: Object.freeze(
31
+ actual.diagnostics.map((item) =>
32
+ Object.freeze({
33
+ code: item.code,
34
+ path: item.path,
35
+ message: item.message,
36
+ scope: item.path === constraintsPath ? ("constraint" as const) : ("other" as const),
37
+ }),
38
+ ),
39
+ ),
40
+ });
41
+ }
42
+ return Object.freeze({
43
+ obligations: Object.freeze(
44
+ actual.result.report.structuralObligations.map((item) =>
45
+ Object.freeze({
46
+ ruleId: item.ruleId,
47
+ violationFingerprint: item.violationFingerprint,
48
+ constraintId: item.constraintId,
49
+ classification: item.classification,
50
+ }),
51
+ ),
52
+ ),
53
+ diagnostics: Object.freeze([]),
54
+ });
55
+ }
56
+ }
@@ -0,0 +1,19 @@
1
+ // @unit world-model
2
+ // @layer application
3
+ // @work-item-id WI-305
4
+
5
+ export interface PinnedDesignEndpointDto {
6
+ readonly constraintId: string;
7
+ readonly endpoint: "claimant" | "premise";
8
+ readonly nodeId: string;
9
+ readonly corpusRole: "product" | "inception";
10
+ readonly declaredKey: string;
11
+ }
12
+
13
+ export type PinnedDesignEndpointReadResultDto =
14
+ | {
15
+ readonly state: "available";
16
+ readonly endpoints: readonly PinnedDesignEndpointDto[];
17
+ readonly diagnosticCodes: readonly string[];
18
+ }
19
+ | { readonly state: "unavailable"; readonly diagnosticCodes: readonly string[] };