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.
- package/CHANGELOG.md +73 -1
- package/README.ja.md +31 -1
- package/README.md +30 -0
- package/docs/ADR/031-world-model-ownership-and-corpus-lifecycle.md +155 -0
- package/docs/ADR/032-world-node-identity.md +198 -0
- package/docs/ADR/033-world-snapshot-canonicalization.md +246 -0
- package/docs/ADR/034-world-constraint-semantics.md +218 -0
- package/docs/ADR/035-world-adoption-baseline-and-waiver.md +341 -0
- package/docs/ADR/036-world-model-and-doc-freshness.md +169 -0
- package/docs/ADR/037-world-cli-and-output-contract.md +398 -0
- package/docs/contracts/attestation-v2.schema.json +110 -0
- package/docs/contracts/requirement-test-matrix.schema.json +15 -0
- package/docs/contracts/world-baseline.schema.json +35 -0
- package/docs/contracts/world-constraints.schema.json +56 -0
- package/docs/contracts/world-debts.schema.json +32 -0
- package/docs/contracts/world-obligation-report.schema.json +259 -0
- package/docs/contracts/world-waivers.schema.json +32 -0
- package/docs/guide/cli-reference.md +45 -0
- package/docs/guide/configuration.md +56 -0
- package/docs/templates/ci/aidlc-gate.yml +42 -2
- package/package.json +1 -1
- package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
- package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
- package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
- package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
- package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
- package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
- package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
- package/scripts/harness/attestation/application/ports/sha256-capability.ts +25 -0
- package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
- package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
- package/scripts/harness/attestation/composition-root.ts +19 -4
- package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
- package/scripts/harness/attestation/index.ts +13 -2
- package/scripts/harness/attestation/infrastructure/adapters/node-crypto-content-hasher-adapter.ts +6 -6
- package/scripts/harness/attestation/infrastructure/adapters/node-crypto-sha256-capability.ts +19 -0
- package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
- package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
- package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
- package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
- package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
- package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
- package/scripts/harness/config-foundation/index.ts +14 -15
- package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
- package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
- package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +4 -1
- package/scripts/harness/integrations/pre-commit.ts +169 -27
- package/scripts/harness/main.ts +276 -126
- package/scripts/harness/nyquist-validation/application/dto/generate-matrix-output.ts +11 -0
- package/scripts/harness/nyquist-validation/application/usecases/check-ac-coverage-gate-usecase.ts +6 -0
- package/scripts/harness/nyquist-validation/application/usecases/generate-requirement-test-matrix-usecase.ts +8 -4
- package/scripts/harness/nyquist-validation/domain/entities/story-mapping.ts +29 -2
- package/scripts/harness/nyquist-validation/domain/services/ac-coverage-gate-policy.ts +28 -0
- package/scripts/harness/nyquist-validation/infrastructure/adapters/markdown-requirement-source-adapter.ts +71 -4
- package/scripts/harness/nyquist-validation/infrastructure/schema/matrix-schema-loader.ts +4 -0
- package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
- package/scripts/harness/traceability-model/application/dto/traceability-world-read-dto.ts +67 -0
- package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
- package/scripts/harness/traceability-model/application/facades/traceability-world-read-facade.ts +372 -0
- package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
- package/scripts/harness/traceability-model/application/ports/traceability-world-read-source-port.ts +61 -0
- package/scripts/harness/traceability-model/composition-root.ts +26 -5
- package/scripts/harness/traceability-model/index.ts +26 -6
- package/scripts/harness/traceability-model/infrastructure/adapters/file-system-traceability-world-read-adapter.ts +223 -0
- package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
- package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +86 -8
- package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
- package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
- package/scripts/harness/validator-system/composition-root.ts +21 -6
- package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
- package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
- package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
- package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
- package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
- package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
- package/scripts/harness/world-model/application/dto/world-inspection-dto.ts +43 -0
- package/scripts/harness/world-model/application/dto/world-obligation-report-dto.ts +54 -0
- package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +127 -0
- package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
- package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
- package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
- package/scripts/harness/world-model/application/ports/obligation-report-writer-port.ts +7 -0
- package/scripts/harness/world-model/application/ports/world-control-declaration-repository-port.ts +57 -0
- package/scripts/harness/world-model/application/ports/world-fact-source-port.ts +17 -0
- package/scripts/harness/world-model/application/usecases/build-snapshot-use-case.ts +111 -0
- package/scripts/harness/world-model/application/usecases/derive-obligations-use-case.ts +155 -0
- package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +146 -0
- package/scripts/harness/world-model/application/usecases/inspect-world-use-case.ts +74 -0
- package/scripts/harness/world-model/application/usecases/pin-constraint-endpoint-use-case.ts +139 -0
- package/scripts/harness/world-model/composition-root.ts +247 -0
- package/scripts/harness/world-model/domain/entities/constraint-record.ts +148 -0
- package/scripts/harness/world-model/domain/entities/control-declarations.ts +274 -0
- package/scripts/harness/world-model/domain/entities/edge.ts +41 -0
- package/scripts/harness/world-model/domain/entities/extraction-diagnostic.ts +60 -0
- package/scripts/harness/world-model/domain/entities/snapshot.ts +75 -0
- package/scripts/harness/world-model/domain/entities/world-node.ts +210 -0
- package/scripts/harness/world-model/domain/ports/world-hashing-port.ts +8 -0
- package/scripts/harness/world-model/domain/services/canonical-json-serializer.ts +113 -0
- package/scripts/harness/world-model/domain/services/constraint-evaluator.ts +486 -0
- package/scripts/harness/world-model/domain/services/obligation-derivation-service.ts +199 -0
- package/scripts/harness/world-model/domain/services/policy-inputs-digest-deriver.ts +66 -0
- package/scripts/harness/world-model/domain/services/snapshot-root-deriver.ts +218 -0
- package/scripts/harness/world-model/domain/services/text-content-normalizer.ts +30 -0
- package/scripts/harness/world-model/domain/services/violation-fingerprint-deriver.ts +183 -0
- package/scripts/harness/world-model/domain/value-objects/artifact-kind.ts +58 -0
- package/scripts/harness/world-model/domain/value-objects/change-provenance.ts +137 -0
- package/scripts/harness/world-model/domain/value-objects/corpus-role.ts +57 -0
- package/scripts/harness/world-model/domain/value-objects/declared-key.ts +35 -0
- package/scripts/harness/world-model/domain/value-objects/evaluation-id.ts +41 -0
- package/scripts/harness/world-model/domain/value-objects/explicit-constraint-relation.ts +53 -0
- package/scripts/harness/world-model/domain/value-objects/explicit-node-alias.ts +30 -0
- package/scripts/harness/world-model/domain/value-objects/node-pin.ts +34 -0
- package/scripts/harness/world-model/domain/value-objects/path-key.ts +103 -0
- package/scripts/harness/world-model/domain/value-objects/sha256-digest.ts +39 -0
- package/scripts/harness/world-model/domain/value-objects/violation-fingerprint.ts +36 -0
- package/scripts/harness/world-model/domain/value-objects/wcr-rule-id.ts +59 -0
- package/scripts/harness/world-model/domain/value-objects/world-node-id.ts +222 -0
- package/scripts/harness/world-model/index.ts +33 -0
- package/scripts/harness/world-model/infrastructure/adapters/adr-fact-extractor.ts +27 -0
- package/scripts/harness/world-model/infrastructure/adapters/assembled-world-fact-source.ts +17 -0
- package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +323 -0
- package/scripts/harness/world-model/infrastructure/adapters/attestation-sha256-world-hashing-adapter.ts +15 -0
- package/scripts/harness/world-model/infrastructure/adapters/composite-design-fact-source.ts +23 -0
- package/scripts/harness/world-model/infrastructure/adapters/design-corpus-fact-extractor.ts +285 -0
- package/scripts/harness/world-model/infrastructure/adapters/design-fact-extraction.ts +63 -0
- package/scripts/harness/world-model/infrastructure/adapters/file-system-obligation-report-writer-adapter.ts +37 -0
- package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +332 -0
- package/scripts/harness/world-model/infrastructure/adapters/integrity-manifest-fact-extractor.ts +101 -0
- package/scripts/harness/world-model/infrastructure/adapters/json-fact-extractor-support.ts +151 -0
- package/scripts/harness/world-model/infrastructure/adapters/markdown-design-fact-extractor.ts +493 -0
- package/scripts/harness/world-model/infrastructure/adapters/matrix-fact-extractor.ts +283 -0
- package/scripts/harness/world-model/infrastructure/adapters/product-fact-extractor.ts +29 -0
- package/scripts/harness/world-model/infrastructure/adapters/proposal-fact-extractor.ts +29 -0
- package/scripts/harness/world-model/infrastructure/adapters/runtime-fact-extraction.ts +19 -0
- package/scripts/harness/world-model/infrastructure/adapters/source-metadata-fact-extractor.ts +22 -0
- package/scripts/harness/world-model/infrastructure/adapters/test-reference-source-fact-extractor.ts +22 -0
- package/scripts/harness/world-model/infrastructure/adapters/traceability-design-fact-adapter.ts +112 -0
- package/scripts/harness/world-model/infrastructure/adapters/traceability-world-read-facade-merger.ts +38 -0
- package/scripts/harness/world-model/infrastructure/adapters/type-script-source-fact-extractor.ts +236 -0
- package/scripts/harness/world-model/infrastructure/adapters/unit-fact-extractor.ts +71 -0
- package/scripts/harness/world-model/infrastructure/adapters/world-control-declaration-mapper.ts +383 -0
- package/scripts/harness/world-model/presentation/cli/world-command-support.ts +60 -0
- package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +109 -0
- package/scripts/harness/world-model/presentation/cli/world-inspect-command-handler.ts +194 -0
- package/scripts/harness/world-model/presentation/cli/world-pin-command-handler.ts +100 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// @unit world-model
|
|
2
|
+
// @layer application
|
|
3
|
+
// @work-item-id WI-296, WI-297
|
|
4
|
+
// @work-item-id WI-300
|
|
5
|
+
|
|
6
|
+
import { ExtractionDiagnostic } from "../../domain/entities/extraction-diagnostic.js";
|
|
7
|
+
import type { Snapshot } from "../../domain/entities/snapshot.js";
|
|
8
|
+
import { ConstraintEvaluator, type ConstraintFindingDto } from "../../domain/services/constraint-evaluator.js";
|
|
9
|
+
import type { SnapshotRootDeriver } from "../../domain/services/snapshot-root-deriver.js";
|
|
10
|
+
import { ChangeProvenance } from "../../domain/value-objects/change-provenance.js";
|
|
11
|
+
import { PathKey } from "../../domain/value-objects/path-key.js";
|
|
12
|
+
import type { Sha256Digest } from "../../domain/value-objects/sha256-digest.js";
|
|
13
|
+
import type {
|
|
14
|
+
ConstraintDeclarationRepositoryPort,
|
|
15
|
+
WorldControlDiagnosticDto,
|
|
16
|
+
} from "../ports/world-control-declaration-repository-port.js";
|
|
17
|
+
import type { BuildSnapshotContract } from "./build-snapshot-use-case.js";
|
|
18
|
+
import type { DeriveObligationsResult, DeriveObligationsUseCase } from "./derive-obligations-use-case.js";
|
|
19
|
+
|
|
20
|
+
export interface PolicyDatePort {
|
|
21
|
+
currentUtcDate(): string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DeriveWorldObligationsResult =
|
|
25
|
+
| { readonly status: "derived"; readonly result: Extract<DeriveObligationsResult, { status: "derived" }> }
|
|
26
|
+
| { readonly status: "execution-failure"; readonly diagnostics: readonly WorldControlDiagnosticDto[] };
|
|
27
|
+
|
|
28
|
+
export interface DeriveWorldObligationsInput {
|
|
29
|
+
readonly writeReport: boolean;
|
|
30
|
+
readonly reportPath?: string;
|
|
31
|
+
readonly baselineSnapshot?: Snapshot;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Dependencies {
|
|
35
|
+
readonly buildSnapshot: BuildSnapshotContract;
|
|
36
|
+
readonly constraintRepository: ConstraintDeclarationRepositoryPort;
|
|
37
|
+
readonly rootDeriver: SnapshotRootDeriver;
|
|
38
|
+
readonly deriveObligations: DeriveObligationsUseCase;
|
|
39
|
+
readonly policyDate: PolicyDatePort;
|
|
40
|
+
readonly constraintConfigDigest: Sha256Digest;
|
|
41
|
+
readonly evaluationConfigDigest: Sha256Digest;
|
|
42
|
+
readonly constraintPath?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const RULESET_VERSION = "phasegate-world-wcr/v1";
|
|
46
|
+
|
|
47
|
+
export class DeriveWorldObligationsUseCase {
|
|
48
|
+
constructor(private readonly dependencies: Dependencies) {}
|
|
49
|
+
|
|
50
|
+
async execute(input: DeriveWorldObligationsInput): Promise<DeriveWorldObligationsResult> {
|
|
51
|
+
const [snapshot, constraints] = await Promise.all([
|
|
52
|
+
this.dependencies.buildSnapshot.execute(),
|
|
53
|
+
this.dependencies.constraintRepository.load(),
|
|
54
|
+
]);
|
|
55
|
+
if (constraints.state === "invalid") {
|
|
56
|
+
return { status: "execution-failure", diagnostics: constraints.diagnostics };
|
|
57
|
+
}
|
|
58
|
+
const declarationDiagnostics = [
|
|
59
|
+
...constraints.value.diagnostics.map((item) =>
|
|
60
|
+
ExtractionDiagnostic.create({
|
|
61
|
+
code: item.code,
|
|
62
|
+
path: PathKey.create(item.path),
|
|
63
|
+
payload: { locator: item.locator, message: item.message },
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
...constraints.value.malformedDeclarations.map((declaration) =>
|
|
67
|
+
ExtractionDiagnostic.create({
|
|
68
|
+
code: "malformed-constraint-declaration",
|
|
69
|
+
path: PathKey.create(this.dependencies.constraintPath ?? "phasegate.world-constraints.json"),
|
|
70
|
+
payload: declaration.toCanonicalValue(),
|
|
71
|
+
}),
|
|
72
|
+
),
|
|
73
|
+
];
|
|
74
|
+
const constraintRoot = this.dependencies.rootDeriver.deriveConstraintRoot({
|
|
75
|
+
schemaVersion: constraints.value.schemaVersion,
|
|
76
|
+
rulesetVersion: RULESET_VERSION,
|
|
77
|
+
constraintConfigDigest: this.dependencies.constraintConfigDigest,
|
|
78
|
+
constraints: constraints.value.records.map((record) => ({
|
|
79
|
+
id: record.constraintId,
|
|
80
|
+
value: record.toCanonicalValue(),
|
|
81
|
+
})),
|
|
82
|
+
explicitClaims: [],
|
|
83
|
+
aliases: constraints.value.aliases.map((alias) => ({
|
|
84
|
+
id: alias.from,
|
|
85
|
+
value: alias.toCanonicalValue(),
|
|
86
|
+
})),
|
|
87
|
+
declarationDiagnostics,
|
|
88
|
+
}).root;
|
|
89
|
+
const evaluation = new ConstraintEvaluator().evaluateFull({
|
|
90
|
+
currentSnapshot: snapshot,
|
|
91
|
+
baselineSnapshot: input.baselineSnapshot,
|
|
92
|
+
records: constraints.value.records,
|
|
93
|
+
malformedDeclarations: constraints.value.malformedDeclarations,
|
|
94
|
+
aliases: constraints.value.aliases,
|
|
95
|
+
relations: constraints.value.relations,
|
|
96
|
+
changeProvenance: ChangeProvenance.between(input.baselineSnapshot ?? null, snapshot),
|
|
97
|
+
});
|
|
98
|
+
const implicitFindings = snapshot.extractionDiagnostics.flatMap((diagnostic): readonly ConstraintFindingDto[] => {
|
|
99
|
+
if (diagnostic.code !== "duplicate-node-id" || diagnostic.nodeId === undefined) return [];
|
|
100
|
+
const facts = Array.isArray(diagnostic.payload.candidateFacts) ? diagnostic.payload.candidateFacts : [];
|
|
101
|
+
const digests = facts
|
|
102
|
+
.flatMap((fact) => {
|
|
103
|
+
if (typeof fact !== "string") return [];
|
|
104
|
+
try {
|
|
105
|
+
const parsed = JSON.parse(fact) as { contentDigest?: unknown };
|
|
106
|
+
return typeof parsed.contentDigest === "string" ? [parsed.contentDigest] : [];
|
|
107
|
+
} catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
.sort();
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
ruleId: "WCR-005",
|
|
115
|
+
constraintId: null,
|
|
116
|
+
factType: null,
|
|
117
|
+
endpoint: null,
|
|
118
|
+
claimant: null,
|
|
119
|
+
premise: null,
|
|
120
|
+
declarationArtifactId: "",
|
|
121
|
+
declarationLocator: "",
|
|
122
|
+
evidence: {
|
|
123
|
+
nodeId: diagnostic.nodeId.toString(),
|
|
124
|
+
candidateCount:
|
|
125
|
+
typeof diagnostic.payload.candidates === "number" ? diagnostic.payload.candidates : digests.length,
|
|
126
|
+
candidateContentDigests: digests,
|
|
127
|
+
resolution: "global-node-id",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
});
|
|
132
|
+
const result = await this.dependencies.deriveObligations.execute({
|
|
133
|
+
rulesetVersion: RULESET_VERSION,
|
|
134
|
+
findings: [...evaluation.findings, ...implicitFindings],
|
|
135
|
+
corpusRoot: snapshot.corpusRoot,
|
|
136
|
+
constraintRoot,
|
|
137
|
+
evaluationConfigDigest: this.dependencies.evaluationConfigDigest,
|
|
138
|
+
policyAsOfDate: this.dependencies.policyDate.currentUtcDate(),
|
|
139
|
+
writeReport: input.writeReport,
|
|
140
|
+
reportPath: input.reportPath,
|
|
141
|
+
});
|
|
142
|
+
return result.status === "derived"
|
|
143
|
+
? { status: "derived", result }
|
|
144
|
+
: { status: "execution-failure", diagnostics: result.diagnostics };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// @unit world-model
|
|
2
|
+
// @layer application
|
|
3
|
+
// @work-item-id WI-291
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
WorldExtractionDiagnosticDto,
|
|
7
|
+
WorldInspectionDto,
|
|
8
|
+
WorldInventoryCountDto,
|
|
9
|
+
WorldJsonObject,
|
|
10
|
+
} from "../dto/world-inspection-dto.js";
|
|
11
|
+
import type { BuildSnapshotContract } from "./build-snapshot-use-case.js";
|
|
12
|
+
|
|
13
|
+
export interface InspectWorldContract {
|
|
14
|
+
execute(): Promise<WorldInspectionDto>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface InspectWorldUseCaseDeps {
|
|
18
|
+
readonly buildSnapshot: BuildSnapshotContract;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const compareStrings = (left: string, right: string): number => (left < right ? -1 : left > right ? 1 : 0);
|
|
22
|
+
|
|
23
|
+
const countValues = (values: readonly string[]): readonly WorldInventoryCountDto[] => {
|
|
24
|
+
const counts = new Map<string, number>();
|
|
25
|
+
for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
26
|
+
return [...counts.entries()]
|
|
27
|
+
.sort(([left], [right]) => compareStrings(left, right))
|
|
28
|
+
.map(([value, count]) => ({ value, count }));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export class InspectWorldUseCase implements InspectWorldContract {
|
|
32
|
+
constructor(private readonly deps: InspectWorldUseCaseDeps) {}
|
|
33
|
+
|
|
34
|
+
async execute(): Promise<WorldInspectionDto> {
|
|
35
|
+
const snapshot = await this.deps.buildSnapshot.execute();
|
|
36
|
+
const nodes = snapshot.nodes
|
|
37
|
+
.map((node) => node.toCanonicalValue() as WorldJsonObject)
|
|
38
|
+
.sort((left, right) => compareStrings(String(left.id), String(right.id)));
|
|
39
|
+
const edges = snapshot.edges
|
|
40
|
+
.map((edge) => edge.toCanonicalValue() as WorldJsonObject)
|
|
41
|
+
.sort((left, right) => compareStrings(JSON.stringify(left), JSON.stringify(right)));
|
|
42
|
+
const diagnostics = snapshot.extractionDiagnostics
|
|
43
|
+
.map((diagnostic) => diagnostic.toCanonicalValue() as WorldExtractionDiagnosticDto)
|
|
44
|
+
.sort((left, right) => compareStrings(JSON.stringify(left), JSON.stringify(right)));
|
|
45
|
+
const artifactNodes = snapshot.nodes.filter((node) => node.projection.type === "artifact");
|
|
46
|
+
const hardDiagnosticCount = snapshot.extractionDiagnostics.filter(
|
|
47
|
+
(diagnostic) => diagnostic.code !== "not-present",
|
|
48
|
+
).length;
|
|
49
|
+
return {
|
|
50
|
+
snapshotId: snapshot.id.toString(),
|
|
51
|
+
schemaVersion: snapshot.schemaVersion,
|
|
52
|
+
extractorVersion: snapshot.extractorVersion,
|
|
53
|
+
corpusRoot: snapshot.corpusRoot.toString(),
|
|
54
|
+
summary: {
|
|
55
|
+
nodeCount: nodes.length,
|
|
56
|
+
edgeCount: edges.length,
|
|
57
|
+
diagnosticCount: diagnostics.length,
|
|
58
|
+
hardDiagnosticCount,
|
|
59
|
+
},
|
|
60
|
+
inventory: {
|
|
61
|
+
nodeTypes: countValues(snapshot.nodes.map((node) => node.id.nodeType)),
|
|
62
|
+
corpusRoles: countValues(
|
|
63
|
+
artifactNodes.map((node) => (node.projection.type === "artifact" ? node.projection.corpusRole : "")),
|
|
64
|
+
),
|
|
65
|
+
artifactKinds: countValues(
|
|
66
|
+
artifactNodes.map((node) => (node.projection.type === "artifact" ? node.projection.artifactKind : "")),
|
|
67
|
+
),
|
|
68
|
+
},
|
|
69
|
+
nodes,
|
|
70
|
+
edges,
|
|
71
|
+
diagnostics,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// @unit world-model
|
|
2
|
+
// @layer application
|
|
3
|
+
// @work-item-id WI-296
|
|
4
|
+
|
|
5
|
+
import { ConstraintRecord } from "../../domain/entities/constraint-record.js";
|
|
6
|
+
import type { Snapshot } from "../../domain/entities/snapshot.js";
|
|
7
|
+
import { NodePin } from "../../domain/value-objects/node-pin.js";
|
|
8
|
+
import { WorldNodeId } from "../../domain/value-objects/world-node-id.js";
|
|
9
|
+
import type {
|
|
10
|
+
ConstraintDeclarationRepositoryPort,
|
|
11
|
+
ConstraintDeclarationSet,
|
|
12
|
+
WorldControlDiagnosticDto,
|
|
13
|
+
} from "../ports/world-control-declaration-repository-port.js";
|
|
14
|
+
import type { BuildSnapshotContract } from "./build-snapshot-use-case.js";
|
|
15
|
+
|
|
16
|
+
export type PinEndpointRole = "claimant" | "premise";
|
|
17
|
+
|
|
18
|
+
export interface PinConstraintEndpointInput {
|
|
19
|
+
readonly constraintId: string;
|
|
20
|
+
readonly endpoint: PinEndpointRole;
|
|
21
|
+
readonly apply: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type PinConstraintEndpointResult =
|
|
25
|
+
| { readonly status: "preview" | "applied" | "unchanged"; readonly candidate: PinCandidateDto }
|
|
26
|
+
| { readonly status: "domain-failure"; readonly code: string; readonly message: string }
|
|
27
|
+
| { readonly status: "execution-failure"; readonly diagnostics: readonly WorldControlDiagnosticDto[] };
|
|
28
|
+
|
|
29
|
+
export interface PinCandidateDto {
|
|
30
|
+
readonly constraintId: string;
|
|
31
|
+
readonly endpoint: PinEndpointRole;
|
|
32
|
+
readonly nodeId: string;
|
|
33
|
+
readonly beforeDigest: string;
|
|
34
|
+
readonly afterDigest: string;
|
|
35
|
+
readonly changed: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const compareStrings = (left: string, right: string): number => (left < right ? -1 : left > right ? 1 : 0);
|
|
39
|
+
|
|
40
|
+
const serialize = (set: ConstraintDeclarationSet, replacement: ConstraintRecord): unknown => ({
|
|
41
|
+
schemaVersion: set.schemaVersion,
|
|
42
|
+
constraints: set.records
|
|
43
|
+
.map((record) => (record.constraintId.equals(replacement.constraintId) ? replacement : record))
|
|
44
|
+
.sort((left, right) => compareStrings(left.constraintId.toString(), right.constraintId.toString()))
|
|
45
|
+
.map((record) => ({
|
|
46
|
+
constraintId: record.constraintId.toString(),
|
|
47
|
+
factType: record.factType,
|
|
48
|
+
claimant: record.claimant.toCanonicalValue(),
|
|
49
|
+
premise: record.premise.toCanonicalValue(),
|
|
50
|
+
applicableRuleIds: record.applicableRuleIds.map((ruleId) => ruleId.toString()),
|
|
51
|
+
})),
|
|
52
|
+
aliases: set.aliases
|
|
53
|
+
.map((alias) => ({ from: alias.from.toString(), to: alias.to.toString() }))
|
|
54
|
+
.sort((left, right) => compareStrings(left.from, right.from)),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const resolveNode = (snapshot: Snapshot, set: ConstraintDeclarationSet, nodeId: WorldNodeId) => {
|
|
58
|
+
const duplicate = snapshot.extractionDiagnostics.some(
|
|
59
|
+
(diagnostic) => diagnostic.code === "duplicate-node-id" && diagnostic.nodeId?.equals(nodeId),
|
|
60
|
+
);
|
|
61
|
+
if (duplicate) return { ok: false as const, code: "duplicate-endpoint", message: `duplicate endpoint: ${nodeId}` };
|
|
62
|
+
const exact = snapshot.nodes.filter((node) => node.id.equals(nodeId));
|
|
63
|
+
if (exact.length === 1) return { ok: true as const, node: exact[0] };
|
|
64
|
+
const aliases = set.aliases.filter((alias) => alias.from.equals(nodeId));
|
|
65
|
+
if (aliases.length !== 1 || set.aliases.some((alias) => alias.from.equals(aliases[0]?.to))) {
|
|
66
|
+
return {
|
|
67
|
+
ok: false as const,
|
|
68
|
+
code: aliases.length === 0 ? "missing-endpoint" : "ambiguous-endpoint-alias",
|
|
69
|
+
message: `endpoint cannot be resolved uniquely: ${nodeId}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const targets = snapshot.nodes.filter((node) => node.id.equals(aliases[0].to));
|
|
73
|
+
return targets.length === 1
|
|
74
|
+
? { ok: true as const, node: targets[0] }
|
|
75
|
+
: {
|
|
76
|
+
ok: false as const,
|
|
77
|
+
code: targets.length === 0 ? "missing-endpoint" : "duplicate-endpoint",
|
|
78
|
+
message: `alias target cannot be resolved uniquely: ${aliases[0].to}`,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export class PinConstraintEndpointUseCase {
|
|
83
|
+
constructor(
|
|
84
|
+
private readonly buildSnapshot: BuildSnapshotContract,
|
|
85
|
+
private readonly repository: ConstraintDeclarationRepositoryPort,
|
|
86
|
+
) {}
|
|
87
|
+
|
|
88
|
+
async execute(input: PinConstraintEndpointInput): Promise<PinConstraintEndpointResult> {
|
|
89
|
+
let constraintId: WorldNodeId;
|
|
90
|
+
try {
|
|
91
|
+
constraintId = WorldNodeId.parse(input.constraintId);
|
|
92
|
+
if (constraintId.nodeType !== "constraint") throw new Error("not constraint ID");
|
|
93
|
+
} catch {
|
|
94
|
+
return { status: "domain-failure", code: "invalid-constraint-id", message: input.constraintId };
|
|
95
|
+
}
|
|
96
|
+
const [snapshot, loaded] = await Promise.all([this.buildSnapshot.execute(), this.repository.load()]);
|
|
97
|
+
if (loaded.state === "invalid") return { status: "execution-failure", diagnostics: loaded.diagnostics };
|
|
98
|
+
if (loaded.value.malformedDeclarations.length > 0 || loaded.value.diagnostics.length > 0) {
|
|
99
|
+
return {
|
|
100
|
+
status: "domain-failure",
|
|
101
|
+
code: "malformed-constraint-declaration",
|
|
102
|
+
message: "constraint declarations contain malformed or ambiguous candidates",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const records = loaded.value.records.filter((record) => record.constraintId.equals(constraintId));
|
|
106
|
+
if (records.length !== 1) {
|
|
107
|
+
return { status: "domain-failure", code: "constraint-not-found", message: input.constraintId };
|
|
108
|
+
}
|
|
109
|
+
const record = records[0];
|
|
110
|
+
const before = input.endpoint === "claimant" ? record.claimant : record.premise;
|
|
111
|
+
const resolved = resolveNode(snapshot, loaded.value, before.nodeId);
|
|
112
|
+
if (!resolved.ok) return { status: "domain-failure", code: resolved.code, message: resolved.message };
|
|
113
|
+
const after = NodePin.create({ nodeId: before.nodeId, contentDigest: resolved.node.contentDigest });
|
|
114
|
+
const replacement = ConstraintRecord.create({
|
|
115
|
+
constraintId: record.constraintId,
|
|
116
|
+
schemaVersion: record.schemaVersion,
|
|
117
|
+
factType: record.factType,
|
|
118
|
+
claimant: input.endpoint === "claimant" ? after : record.claimant,
|
|
119
|
+
premise: input.endpoint === "premise" ? after : record.premise,
|
|
120
|
+
applicableRuleIds: record.applicableRuleIds,
|
|
121
|
+
declarationArtifactId: record.declarationArtifactId,
|
|
122
|
+
declarationLocator: record.declarationLocator,
|
|
123
|
+
});
|
|
124
|
+
const candidate = Object.freeze({
|
|
125
|
+
constraintId: input.constraintId,
|
|
126
|
+
endpoint: input.endpoint,
|
|
127
|
+
nodeId: before.nodeId.toString(),
|
|
128
|
+
beforeDigest: before.contentDigest.toString(),
|
|
129
|
+
afterDigest: after.contentDigest.toString(),
|
|
130
|
+
changed: !before.contentDigest.equals(after.contentDigest),
|
|
131
|
+
});
|
|
132
|
+
if (!input.apply) return { status: "preview", candidate };
|
|
133
|
+
if (!candidate.changed) return { status: "unchanged", candidate };
|
|
134
|
+
const written = await this.repository.replaceAtomically(serialize(loaded.value, replacement));
|
|
135
|
+
return written.state === "written"
|
|
136
|
+
? { status: "applied", candidate }
|
|
137
|
+
: { status: "execution-failure", diagnostics: written.diagnostics };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// @unit world-model
|
|
2
|
+
// @layer composition
|
|
3
|
+
// @work-item-id WI-291
|
|
4
|
+
// @work-item-id WI-292
|
|
5
|
+
// @work-item-id WI-295
|
|
6
|
+
// @work-item-id WI-296, WI-297
|
|
7
|
+
// @work-item-id WI-300
|
|
8
|
+
// @work-item-id WI-305
|
|
9
|
+
// @work-item-id WI-306
|
|
10
|
+
|
|
11
|
+
import { createAttestationModule, createSha256Capability } from "../attestation/index.js";
|
|
12
|
+
import { createTraceabilityModelModule } from "../traceability-model/index.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveWorldCorpusConfig,
|
|
15
|
+
type WorldResolvedConfigInput,
|
|
16
|
+
} from "./application/dto/world-resolved-config-input.js";
|
|
17
|
+
import { PinnedDesignEndpointFacade } from "./application/facades/pinned-design-endpoint-facade.js";
|
|
18
|
+
import { WorldSnapshotRootFacade } from "./application/facades/world-snapshot-root-facade.js";
|
|
19
|
+
import { BuildSnapshotUseCase } from "./application/usecases/build-snapshot-use-case.js";
|
|
20
|
+
import { DeriveObligationsUseCase } from "./application/usecases/derive-obligations-use-case.js";
|
|
21
|
+
import {
|
|
22
|
+
DeriveWorldObligationsUseCase,
|
|
23
|
+
type PolicyDatePort,
|
|
24
|
+
} from "./application/usecases/derive-world-obligations-use-case.js";
|
|
25
|
+
import { InspectWorldUseCase } from "./application/usecases/inspect-world-use-case.js";
|
|
26
|
+
import { PinConstraintEndpointUseCase } from "./application/usecases/pin-constraint-endpoint-use-case.js";
|
|
27
|
+
import { CanonicalJsonSerializer } from "./domain/services/canonical-json-serializer.js";
|
|
28
|
+
import { ObligationDerivationService } from "./domain/services/obligation-derivation-service.js";
|
|
29
|
+
import { PolicyInputsDigestDeriver } from "./domain/services/policy-inputs-digest-deriver.js";
|
|
30
|
+
import { SnapshotRootDeriver } from "./domain/services/snapshot-root-deriver.js";
|
|
31
|
+
import { ViolationFingerprintDeriver } from "./domain/services/violation-fingerprint-deriver.js";
|
|
32
|
+
import { AdrFactExtractor } from "./infrastructure/adapters/adr-fact-extractor.js";
|
|
33
|
+
import { AssembledWorldFactSource } from "./infrastructure/adapters/assembled-world-fact-source.js";
|
|
34
|
+
import {
|
|
35
|
+
AttestationFactExtractor,
|
|
36
|
+
AttestationVerificationHandlerAdapter,
|
|
37
|
+
} from "./infrastructure/adapters/attestation-fact-extractor.js";
|
|
38
|
+
import { AttestationSha256WorldHashingAdapter } from "./infrastructure/adapters/attestation-sha256-world-hashing-adapter.js";
|
|
39
|
+
import { CompositeDesignFactSource } from "./infrastructure/adapters/composite-design-fact-source.js";
|
|
40
|
+
import { DesignCorpusFactExtractor } from "./infrastructure/adapters/design-corpus-fact-extractor.js";
|
|
41
|
+
import { FileSystemObligationReportWriterAdapter } from "./infrastructure/adapters/file-system-obligation-report-writer-adapter.js";
|
|
42
|
+
import {
|
|
43
|
+
FileSystemAdoptionBaselineRepositoryAdapter,
|
|
44
|
+
FileSystemConstraintDeclarationRepositoryAdapter,
|
|
45
|
+
FileSystemSemanticDebtRepositoryAdapter,
|
|
46
|
+
FileSystemWaiverDeclarationRepositoryAdapter,
|
|
47
|
+
} from "./infrastructure/adapters/file-system-world-control-repository-adapters.js";
|
|
48
|
+
import { IntegrityManifestFactExtractor } from "./infrastructure/adapters/integrity-manifest-fact-extractor.js";
|
|
49
|
+
import { MarkdownDesignFactExtractor } from "./infrastructure/adapters/markdown-design-fact-extractor.js";
|
|
50
|
+
import { MatrixFactExtractor } from "./infrastructure/adapters/matrix-fact-extractor.js";
|
|
51
|
+
import { ProductFactExtractor } from "./infrastructure/adapters/product-fact-extractor.js";
|
|
52
|
+
import { ProposalFactExtractor } from "./infrastructure/adapters/proposal-fact-extractor.js";
|
|
53
|
+
import { SourceMetadataFactExtractor } from "./infrastructure/adapters/source-metadata-fact-extractor.js";
|
|
54
|
+
import { TestReferenceSourceFactExtractor } from "./infrastructure/adapters/test-reference-source-fact-extractor.js";
|
|
55
|
+
import { TraceabilityDesignFactAdapter } from "./infrastructure/adapters/traceability-design-fact-adapter.js";
|
|
56
|
+
import { TraceabilityWorldReadFacadeMerger } from "./infrastructure/adapters/traceability-world-read-facade-merger.js";
|
|
57
|
+
import { UnitFactExtractor } from "./infrastructure/adapters/unit-fact-extractor.js";
|
|
58
|
+
import { WorldDeriveCommandHandler } from "./presentation/cli/world-derive-command-handler.js";
|
|
59
|
+
import { WorldInspectCommandHandler } from "./presentation/cli/world-inspect-command-handler.js";
|
|
60
|
+
import { WorldPinCommandHandler } from "./presentation/cli/world-pin-command-handler.js";
|
|
61
|
+
|
|
62
|
+
const WORLD_SNAPSHOT_SCHEMA_VERSION = "phasegate-world-snapshot/v1";
|
|
63
|
+
const WORLD_EXTRACTOR_VERSION = "phasegate-world-extractor/v2";
|
|
64
|
+
|
|
65
|
+
export interface WorldModelModuleOptions {
|
|
66
|
+
readonly rootDir: string;
|
|
67
|
+
readonly resolvedConfig?: WorldResolvedConfigInput;
|
|
68
|
+
readonly policyDate?: PolicyDatePort;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createWorldModelModule(options: WorldModelModuleOptions) {
|
|
72
|
+
const config = resolveWorldCorpusConfig(options.resolvedConfig);
|
|
73
|
+
const hashingPort = new AttestationSha256WorldHashingAdapter(createSha256Capability());
|
|
74
|
+
const serializer = new CanonicalJsonSerializer();
|
|
75
|
+
const markdownExtractor = new MarkdownDesignFactExtractor({ hashingPort });
|
|
76
|
+
const traceabilityFacades = config.productScopes.flatMap((scope) =>
|
|
77
|
+
config.inceptionRoots.map(
|
|
78
|
+
(inceptionRoot) =>
|
|
79
|
+
createTraceabilityModelModule(options.rootDir, {
|
|
80
|
+
pathRoots: {
|
|
81
|
+
designDocsRoot: scope.designDocsRoot,
|
|
82
|
+
inceptionRoot,
|
|
83
|
+
testRoots: config.sourceRoots.map((sourceRoot) => `${sourceRoot}/__tests__`),
|
|
84
|
+
},
|
|
85
|
+
}).worldReadFacade,
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
const designCorpus = new DesignCorpusFactExtractor({
|
|
89
|
+
traceabilityAdapter: new TraceabilityDesignFactAdapter({
|
|
90
|
+
facade: new TraceabilityWorldReadFacadeMerger(traceabilityFacades),
|
|
91
|
+
hashingPort,
|
|
92
|
+
serializer,
|
|
93
|
+
}),
|
|
94
|
+
productExtractor: new CompositeDesignFactSource(
|
|
95
|
+
config.productScopes.map(
|
|
96
|
+
(scope) =>
|
|
97
|
+
new ProductFactExtractor({
|
|
98
|
+
rootDir: options.rootDir,
|
|
99
|
+
markdownExtractor,
|
|
100
|
+
productRoot: scope.productRoot,
|
|
101
|
+
}),
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
proposalExtractor: new CompositeDesignFactSource(
|
|
105
|
+
config.inceptionRoots.map(
|
|
106
|
+
(inceptionRoot) => new ProposalFactExtractor({ rootDir: options.rootDir, markdownExtractor, inceptionRoot }),
|
|
107
|
+
),
|
|
108
|
+
),
|
|
109
|
+
adrExtractor: new CompositeDesignFactSource(
|
|
110
|
+
config.adrRoots.map((adrRoot) => new AdrFactExtractor({ rootDir: options.rootDir, markdownExtractor, adrRoot })),
|
|
111
|
+
),
|
|
112
|
+
unitExtractor: new CompositeDesignFactSource(
|
|
113
|
+
config.productScopes.map(
|
|
114
|
+
(scope) =>
|
|
115
|
+
new UnitFactExtractor({
|
|
116
|
+
rootDir: options.rootDir,
|
|
117
|
+
markdownExtractor,
|
|
118
|
+
unitRoot: scope.unitRoot,
|
|
119
|
+
}),
|
|
120
|
+
),
|
|
121
|
+
),
|
|
122
|
+
});
|
|
123
|
+
const attestationModule = createAttestationModule(options.rootDir);
|
|
124
|
+
const factSource = new AssembledWorldFactSource([
|
|
125
|
+
designCorpus,
|
|
126
|
+
...config.sourceRoots.flatMap((sourceRoot) => [
|
|
127
|
+
new SourceMetadataFactExtractor({ rootDir: options.rootDir, hashingPort, sourceRoot }),
|
|
128
|
+
new TestReferenceSourceFactExtractor({ rootDir: options.rootDir, hashingPort, sourceRoot }),
|
|
129
|
+
]),
|
|
130
|
+
new MatrixFactExtractor({
|
|
131
|
+
rootDir: options.rootDir,
|
|
132
|
+
hashingPort,
|
|
133
|
+
matrixPath: config.matrixPath,
|
|
134
|
+
serializer,
|
|
135
|
+
}),
|
|
136
|
+
new AttestationFactExtractor({
|
|
137
|
+
rootDir: options.rootDir,
|
|
138
|
+
hashingPort,
|
|
139
|
+
attestationPath: config.attestationPath,
|
|
140
|
+
verificationFacade: new AttestationVerificationHandlerAdapter(attestationModule.verifyAttestationHandler),
|
|
141
|
+
serializer,
|
|
142
|
+
}),
|
|
143
|
+
new IntegrityManifestFactExtractor({
|
|
144
|
+
rootDir: options.rootDir,
|
|
145
|
+
hashingPort,
|
|
146
|
+
manifestPath: config.integrityManifestPath,
|
|
147
|
+
serializer,
|
|
148
|
+
}),
|
|
149
|
+
]);
|
|
150
|
+
const corpusConfigDigest = hashingPort.sha256(
|
|
151
|
+
serializer.serialize({
|
|
152
|
+
schemaVersion: "phasegate-world-corpus-config/v1",
|
|
153
|
+
productScopes: config.productScopes,
|
|
154
|
+
inceptionRoots: config.inceptionRoots,
|
|
155
|
+
adrRoots: config.adrRoots,
|
|
156
|
+
sourceRoots: config.sourceRoots,
|
|
157
|
+
include: config.include,
|
|
158
|
+
exclude: config.exclude,
|
|
159
|
+
inputs: {
|
|
160
|
+
matrixPath: config.matrixPath,
|
|
161
|
+
attestationPath: config.attestationPath,
|
|
162
|
+
integrityManifestPath: config.integrityManifestPath,
|
|
163
|
+
},
|
|
164
|
+
}),
|
|
165
|
+
);
|
|
166
|
+
const buildSnapshotUseCase = new BuildSnapshotUseCase({
|
|
167
|
+
factSource,
|
|
168
|
+
rootDeriver: new SnapshotRootDeriver(serializer, hashingPort),
|
|
169
|
+
serializer,
|
|
170
|
+
schemaVersion: WORLD_SNAPSHOT_SCHEMA_VERSION,
|
|
171
|
+
extractorVersion: WORLD_EXTRACTOR_VERSION,
|
|
172
|
+
corpusConfigDigest,
|
|
173
|
+
});
|
|
174
|
+
const inspectWorldUseCase = new InspectWorldUseCase({ buildSnapshot: buildSnapshotUseCase });
|
|
175
|
+
const worldSnapshotRootFacade = new WorldSnapshotRootFacade(buildSnapshotUseCase);
|
|
176
|
+
const fingerprintDeriver = new ViolationFingerprintDeriver(serializer, hashingPort);
|
|
177
|
+
const constraintRepository = new FileSystemConstraintDeclarationRepositoryAdapter({
|
|
178
|
+
rootDir: options.rootDir,
|
|
179
|
+
fileName: config.constraintsPath,
|
|
180
|
+
});
|
|
181
|
+
const rootDeriver = new SnapshotRootDeriver(serializer, hashingPort);
|
|
182
|
+
const deriveObligationsUseCase = new DeriveObligationsUseCase({
|
|
183
|
+
baselineRepository: new FileSystemAdoptionBaselineRepositoryAdapter({
|
|
184
|
+
rootDir: options.rootDir,
|
|
185
|
+
fileName: config.baselinePath,
|
|
186
|
+
}),
|
|
187
|
+
waiverRepository: new FileSystemWaiverDeclarationRepositoryAdapter({
|
|
188
|
+
rootDir: options.rootDir,
|
|
189
|
+
fileName: config.waiversPath,
|
|
190
|
+
}),
|
|
191
|
+
semanticDebtRepository: new FileSystemSemanticDebtRepositoryAdapter({
|
|
192
|
+
rootDir: options.rootDir,
|
|
193
|
+
fileName: config.debtsPath,
|
|
194
|
+
}),
|
|
195
|
+
policyInputsDigestDeriver: new PolicyInputsDigestDeriver(serializer, hashingPort),
|
|
196
|
+
evaluationIdDeriver: new SnapshotRootDeriver(serializer, hashingPort),
|
|
197
|
+
obligationDerivationService: new ObligationDerivationService(fingerprintDeriver),
|
|
198
|
+
serializer,
|
|
199
|
+
writer: new FileSystemObligationReportWriterAdapter({
|
|
200
|
+
rootDir: options.rootDir,
|
|
201
|
+
reportPath: config.obligationReportPath,
|
|
202
|
+
}),
|
|
203
|
+
});
|
|
204
|
+
const deriveWorldObligationsUseCase = new DeriveWorldObligationsUseCase({
|
|
205
|
+
buildSnapshot: buildSnapshotUseCase,
|
|
206
|
+
constraintRepository,
|
|
207
|
+
rootDeriver,
|
|
208
|
+
deriveObligations: deriveObligationsUseCase,
|
|
209
|
+
policyDate: options.policyDate ?? {
|
|
210
|
+
currentUtcDate: () => new Date().toISOString().slice(0, 10),
|
|
211
|
+
},
|
|
212
|
+
constraintConfigDigest: hashingPort.sha256(
|
|
213
|
+
serializer.serialize({
|
|
214
|
+
schemaVersion: "phasegate-world-constraint-config/v1",
|
|
215
|
+
constraintsPath: config.constraintsPath,
|
|
216
|
+
}),
|
|
217
|
+
),
|
|
218
|
+
evaluationConfigDigest: hashingPort.sha256(
|
|
219
|
+
serializer.serialize({
|
|
220
|
+
schemaVersion: "phasegate-world-evaluation-config/v1",
|
|
221
|
+
rulesetVersion: "phasegate-world-wcr/v1",
|
|
222
|
+
}),
|
|
223
|
+
),
|
|
224
|
+
constraintPath: config.constraintsPath,
|
|
225
|
+
});
|
|
226
|
+
const pinConstraintEndpointUseCase = new PinConstraintEndpointUseCase(buildSnapshotUseCase, constraintRepository);
|
|
227
|
+
const pinnedDesignEndpointFacade = new PinnedDesignEndpointFacade(constraintRepository);
|
|
228
|
+
const worldInspectCommandHandler = new WorldInspectCommandHandler({ inspectWorld: inspectWorldUseCase });
|
|
229
|
+
const worldPinCommandHandler = new WorldPinCommandHandler(pinConstraintEndpointUseCase);
|
|
230
|
+
const worldDeriveCommandHandler = new WorldDeriveCommandHandler(
|
|
231
|
+
deriveWorldObligationsUseCase,
|
|
232
|
+
config.obligationReportPath,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
buildSnapshotUseCase,
|
|
237
|
+
deriveObligationsUseCase,
|
|
238
|
+
deriveWorldObligationsUseCase,
|
|
239
|
+
inspectWorldUseCase,
|
|
240
|
+
pinConstraintEndpointUseCase,
|
|
241
|
+
pinnedDesignEndpointFacade,
|
|
242
|
+
worldDeriveCommandHandler,
|
|
243
|
+
worldInspectCommandHandler,
|
|
244
|
+
worldSnapshotRootFacade,
|
|
245
|
+
worldPinCommandHandler,
|
|
246
|
+
} as const;
|
|
247
|
+
}
|