project-tiny-context-harness 0.8.12 → 0.8.13
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/README.md +43 -19
- package/assets/README.md +81 -40
- package/assets/README.zh-CN.md +44 -22
- package/assets/agents/AGENTS_CORE.md +8 -4
- package/assets/skills/context_development_engineer/SKILL.md +9 -1
- package/assets/skills/design-resource-authoring/SKILL.md +7 -5
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +2 -2
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +22 -2
- package/assets/skills/design-resource-authoring/references/recovery-and-writeback.md +199 -0
- package/assets/skills/design-resource-authoring/references/resource-selection.md +2 -2
- package/assets/skills/long-task-workflow/SKILL.md +6 -6
- package/assets/skills/long-task-workflow/references/contract-authoring.md +27 -22
- package/assets/skills/long-task-workflow/references/evidence-design.md +49 -32
- package/assets/skills/long-task-workflow/references/source-authoring.md +2 -2
- package/dist/commands/design-resource-recovery.d.ts +1 -0
- package/dist/commands/design-resource-recovery.js +152 -0
- package/dist/commands/design-resource.js +20 -1
- package/dist/commands/index.js +1 -1
- package/dist/lib/design-resource-reconciliation-codec.d.ts +2 -0
- package/dist/lib/design-resource-reconciliation-codec.js +174 -0
- package/dist/lib/design-resource-reconciliation-types.d.ts +62 -0
- package/dist/lib/design-resource-reconciliation-types.js +1 -0
- package/dist/lib/design-resource-reconciliation.d.ts +3 -0
- package/dist/lib/design-resource-reconciliation.js +224 -0
- package/dist/lib/design-resource-recovery-authority-policy.d.ts +8 -0
- package/dist/lib/design-resource-recovery-authority-policy.js +123 -0
- package/dist/lib/design-resource-recovery-catalog-resources.d.ts +6 -0
- package/dist/lib/design-resource-recovery-catalog-resources.js +121 -0
- package/dist/lib/design-resource-recovery-catalog-shape.d.ts +3 -0
- package/dist/lib/design-resource-recovery-catalog-shape.js +104 -0
- package/dist/lib/design-resource-recovery-catalog.d.ts +9 -0
- package/dist/lib/design-resource-recovery-catalog.js +103 -0
- package/dist/lib/design-resource-recovery-cleanup.d.ts +2 -0
- package/dist/lib/design-resource-recovery-cleanup.js +11 -0
- package/dist/lib/design-resource-recovery-codec-primitives.d.ts +19 -0
- package/dist/lib/design-resource-recovery-codec-primitives.js +92 -0
- package/dist/lib/design-resource-recovery-codec.d.ts +4 -0
- package/dist/lib/design-resource-recovery-codec.js +93 -0
- package/dist/lib/design-resource-recovery-current.d.ts +9 -0
- package/dist/lib/design-resource-recovery-current.js +41 -0
- package/dist/lib/design-resource-recovery-delta-policy.d.ts +5 -0
- package/dist/lib/design-resource-recovery-delta-policy.js +108 -0
- package/dist/lib/design-resource-recovery-files.d.ts +37 -0
- package/dist/lib/design-resource-recovery-files.js +204 -0
- package/dist/lib/design-resource-recovery-final-disposition-shape.d.ts +2 -0
- package/dist/lib/design-resource-recovery-final-disposition-shape.js +47 -0
- package/dist/lib/design-resource-recovery-patch-types.d.ts +54 -0
- package/dist/lib/design-resource-recovery-patch-types.js +1 -0
- package/dist/lib/design-resource-recovery-replay.d.ts +7 -0
- package/dist/lib/design-resource-recovery-replay.js +112 -0
- package/dist/lib/design-resource-recovery-repository-bindings.d.ts +9 -0
- package/dist/lib/design-resource-recovery-repository-bindings.js +49 -0
- package/dist/lib/design-resource-recovery-schema.d.ts +5 -0
- package/dist/lib/design-resource-recovery-schema.js +5 -0
- package/dist/lib/design-resource-recovery-shape.d.ts +10 -0
- package/dist/lib/design-resource-recovery-shape.js +184 -0
- package/dist/lib/design-resource-recovery-source-authority.d.ts +5 -0
- package/dist/lib/design-resource-recovery-source-authority.js +219 -0
- package/dist/lib/design-resource-recovery-text.d.ts +17 -0
- package/dist/lib/design-resource-recovery-text.js +186 -0
- package/dist/lib/design-resource-recovery-types.d.ts +197 -0
- package/dist/lib/design-resource-recovery-types.js +1 -0
- package/dist/lib/design-resource-recovery-writeback-policy.d.ts +5 -0
- package/dist/lib/design-resource-recovery-writeback-policy.js +326 -0
- package/dist/lib/design-resource-recovery-writeback-shape.d.ts +6 -0
- package/dist/lib/design-resource-recovery-writeback-shape.js +155 -0
- package/dist/lib/design-resource-recovery.d.ts +44 -0
- package/dist/lib/design-resource-recovery.js +216 -0
- package/dist/lib/long-task-acceptance-shape.js +8 -2
- package/dist/lib/long-task-activation-validation.js +13 -3
- package/dist/lib/long-task-admitted-observation-records.d.ts +25 -0
- package/dist/lib/long-task-admitted-observation-records.js +40 -0
- package/dist/lib/long-task-admitted-observation.d.ts +93 -0
- package/dist/lib/long-task-admitted-observation.js +201 -0
- package/dist/lib/long-task-artifacts.d.ts +1 -0
- package/dist/lib/long-task-artifacts.js +1 -0
- package/dist/lib/long-task-authority-material-diff.js +1 -0
- package/dist/lib/long-task-authority-policy.d.ts +2 -0
- package/dist/lib/long-task-authority-policy.js +2 -0
- package/dist/lib/long-task-authority-revision-details.js +3 -1
- package/dist/lib/long-task-authority.js +2 -1
- package/dist/lib/long-task-check-execution-policy.js +5 -0
- package/dist/lib/long-task-check-runner.d.ts +2 -2
- package/dist/lib/long-task-check-runner.js +440 -23
- package/dist/lib/long-task-claims.d.ts +18 -0
- package/dist/lib/long-task-claims.js +35 -0
- package/dist/lib/long-task-compact-structure-targets.js +1 -0
- package/dist/lib/long-task-conformance-policy.js +3 -1
- package/dist/lib/long-task-counterfactual-claim-policy.d.ts +3 -4
- package/dist/lib/long-task-counterfactual-claim-policy.js +11 -3
- package/dist/lib/long-task-counterfactual-sandbox.js +1 -0
- package/dist/lib/long-task-counterfactual-types.d.ts +2 -0
- package/dist/lib/long-task-delivery-compiler.js +2 -0
- package/dist/lib/long-task-evidence-capability-policy.d.ts +3 -2
- package/dist/lib/long-task-evidence-capability-policy.js +114 -8
- package/dist/lib/long-task-evidence-capability-runtime.d.ts +5 -2
- package/dist/lib/long-task-evidence-capability-runtime.js +149 -5
- package/dist/lib/long-task-evidence-sensitivity-policy.d.ts +9 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.js +31 -1
- package/dist/lib/long-task-evidence-v2.d.ts +4 -4
- package/dist/lib/long-task-evidence-v2.js +321 -43
- package/dist/lib/long-task-exact-comparison.d.ts +16 -0
- package/dist/lib/long-task-exact-comparison.js +28 -0
- package/dist/lib/long-task-execution-observation.d.ts +24 -0
- package/dist/lib/long-task-execution-observation.js +332 -0
- package/dist/lib/long-task-explain-acceptance-link.d.ts +4 -0
- package/dist/lib/long-task-explain-acceptance-link.js +4 -0
- package/dist/lib/long-task-explain-claim-links.d.ts +2 -0
- package/dist/lib/long-task-explain-claim-links.js +2 -0
- package/dist/lib/long-task-explain-source-links.d.ts +6 -0
- package/dist/lib/long-task-final-v2.js +7 -4
- package/dist/lib/long-task-json-pointer-observation.d.ts +59 -0
- package/dist/lib/long-task-json-pointer-observation.js +184 -0
- package/dist/lib/long-task-observation-artifact.d.ts +8 -0
- package/dist/lib/long-task-observation-artifact.js +58 -0
- package/dist/lib/long-task-observation-authority.d.ts +17 -0
- package/dist/lib/long-task-observation-authority.js +348 -0
- package/dist/lib/long-task-paths.js +1 -1
- package/dist/lib/long-task-process-observation.d.ts +6 -0
- package/dist/lib/long-task-process-observation.js +117 -0
- package/dist/lib/long-task-process-runtime-closure.d.ts +13 -0
- package/dist/lib/long-task-process-runtime-closure.js +175 -0
- package/dist/lib/long-task-progress.js +2 -0
- package/dist/lib/long-task-protected-files.d.ts +1 -1
- package/dist/lib/long-task-protected-files.js +1 -30
- package/dist/lib/long-task-risk.js +8 -3
- package/dist/lib/long-task-root-shape.js +10 -1
- package/dist/lib/long-task-runner-environment.d.ts +1 -1
- package/dist/lib/long-task-runner-environment.js +4 -4
- package/dist/lib/long-task-runner-freeze.d.ts +4 -2
- package/dist/lib/long-task-runner-freeze.js +128 -28
- package/dist/lib/long-task-runtime-types.d.ts +111 -0
- package/dist/lib/long-task-scoped-binding.d.ts +13 -0
- package/dist/lib/long-task-scoped-binding.js +11 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +1 -0
- package/dist/lib/long-task-semantic-fact-contract-closure.js +3 -3
- package/dist/lib/long-task-semantic-fact-evidence.d.ts +3 -3
- package/dist/lib/long-task-semantic-fact-evidence.js +75 -58
- package/dist/lib/long-task-source-claim-validation.js +4 -1
- package/dist/lib/long-task-source-target-continuity.d.ts +2 -2
- package/dist/lib/long-task-source-target-continuity.js +35 -2
- package/dist/lib/long-task-source-target-index.d.ts +3 -0
- package/dist/lib/long-task-source-target-index.js +19 -0
- package/dist/lib/long-task-stage-policy.js +10 -4
- package/dist/lib/long-task-static-observation-freeze.d.ts +83 -0
- package/dist/lib/long-task-static-observation-freeze.js +428 -0
- package/dist/lib/long-task-status-projection.js +5 -1
- package/dist/lib/long-task-target-policy.d.ts +1 -1
- package/dist/lib/long-task-target-policy.js +3 -0
- package/dist/lib/long-task-verifier-dependency-closure.js +7 -3
- package/dist/lib/long-task-verifier-v2.js +70 -9
- package/dist/lib/long-task-workspace.d.ts +1 -1
- package/dist/lib/long-task-workspace.js +1 -12
- package/dist/lib/repository-path-safety.d.ts +14 -0
- package/dist/lib/repository-path-safety.js +126 -0
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +53 -8
- package/migrations/README.md +77 -0
- package/package.json +1 -1
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { computeRawExecutionIdentity } from "./long-task-check-execution-policy.js";
|
|
4
|
-
import { assertRepositoryPattern, classifyRepositoryPatternOverlap, matchesRepoPattern, normalizeRepositoryFile, } from "./long-task-paths.js";
|
|
4
|
+
import { assertRepositoryPattern, classifyRepositoryPatternOverlap, matchesRepoPattern, normalizeRepositoryFile, proveRepositoryPatternSubset, } from "./long-task-paths.js";
|
|
5
5
|
import { assertProtectedRepositoryFile } from "./long-task-protected-files.js";
|
|
6
6
|
import { nearestRunnerFile, npmCliPath, npxCliPath, } from "./long-task-runner-files.js";
|
|
7
7
|
import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
|
|
8
8
|
import { repoRelative, resolveInsideRepository, } from "./long-task-workspace.js";
|
|
9
9
|
import { evidenceAdapterForRunner } from "./long-task-evidence-adapter-policy.js";
|
|
10
10
|
import { freezeLocalVerifierDependencyClosure, packageScriptVerifierRoots, } from "./long-task-verifier-dependency-closure.js";
|
|
11
|
-
|
|
11
|
+
import { compileObservationAuthorityPlan } from "./long-task-observation-authority.js";
|
|
12
|
+
import { compileProcessRuntimeClosure } from "./long-task-process-runtime-closure.js";
|
|
13
|
+
export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets, designConformanceTargets, semanticFactExpectations, productionBindings, productionOwnerPaths, sourceBackedExecutionTarget, protectedAuthorityPaths = []) {
|
|
12
14
|
const prefix = outcomeKey ? `CHECK.${outcomeKey}` : "CHECK.GLOBAL";
|
|
13
15
|
const expectedOutputs = check.expected_output_paths.map((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.expected_output_paths[${index}]`));
|
|
14
16
|
const protectedAuthorityFiles = protectedAuthorityPaths.map((file, index) => normalizeRepositoryFile(file, `${check.key}.protected_authority_paths[${index}]`));
|
|
@@ -17,27 +19,54 @@ export async function freezeDeliveryCheck(check, outcomeKey, repository, baselin
|
|
|
17
19
|
if (!baseline.files.some((file) => matchesRepoPattern(file.path, normalized)) &&
|
|
18
20
|
!protectedAuthorityFiles.some((file) => matchesRepoPattern(file, normalized)) &&
|
|
19
21
|
!expectedOutputs.some((output) => classifyRepositoryPatternOverlap(output, normalized).status ===
|
|
20
|
-
"proven_overlap")
|
|
22
|
+
"proven_overlap") &&
|
|
23
|
+
!plannedBindingMayProvideInput(productionBindings, normalized))
|
|
21
24
|
throw new Error(`input_path_not_found:${check.key}:${pattern}`);
|
|
22
25
|
}
|
|
23
26
|
check.artifact_globs.forEach((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.artifact_globs[${index}]`));
|
|
24
27
|
const cwd = resolveInsideRepository(repository, check.runner.cwd, `${check.key}.cwd`);
|
|
25
28
|
if (!(await stat(cwd).catch(() => null))?.isDirectory())
|
|
26
29
|
throw new Error(`runner_cwd_not_found:${check.key}:${check.runner.cwd}`);
|
|
27
|
-
const target = await resolvedRunnerTarget(check, repository, cwd);
|
|
28
|
-
const verificationInputHashes = await freezeVerificationInputs(check, repository, baseline, cwd, target);
|
|
30
|
+
const target = await resolvedRunnerTarget(check, repository, cwd, executionTarget, productionBindings, sourceBackedExecutionTarget);
|
|
31
|
+
const verificationInputHashes = await freezeVerificationInputs(check, repository, baseline, cwd, target, executionTarget);
|
|
29
32
|
validateSemanticFactOracleInputs(check.key, semanticFactExpectations, verificationInputHashes);
|
|
33
|
+
const runner = await freezeRunner(check, repository, cwd, target, verificationInputHashes);
|
|
34
|
+
const observationAuthorities = compileObservationAuthorityPlan({
|
|
35
|
+
check,
|
|
36
|
+
outcome_key: outcomeKey,
|
|
37
|
+
runner,
|
|
38
|
+
execution_target: executionTarget,
|
|
39
|
+
design_targets: designConformanceTargets,
|
|
40
|
+
semantic_fact_expectations: semanticFactExpectations,
|
|
41
|
+
production_bindings: productionBindings,
|
|
42
|
+
production_owner_paths: productionOwnerPaths,
|
|
43
|
+
source_backed_execution_target: sourceBackedExecutionTarget,
|
|
44
|
+
workspace_manifest: baseline,
|
|
45
|
+
protected_authority_paths: protectedAuthorityPaths,
|
|
46
|
+
});
|
|
47
|
+
const processRuntimeClosure = compileProcessRuntimeClosure({
|
|
48
|
+
check,
|
|
49
|
+
runner,
|
|
50
|
+
execution_target: executionTarget,
|
|
51
|
+
observation_authorities: observationAuthorities,
|
|
52
|
+
production_bindings: productionBindings,
|
|
53
|
+
production_owner_paths: productionOwnerPaths,
|
|
54
|
+
source_backed_execution_target: sourceBackedExecutionTarget,
|
|
55
|
+
protected_authority_paths: protectedAuthorityPaths,
|
|
56
|
+
});
|
|
30
57
|
const compiled = {
|
|
31
58
|
...check,
|
|
32
59
|
internal_id: `${prefix}.${check.key}`,
|
|
33
60
|
outcome_key: outcomeKey,
|
|
34
61
|
evidence_adapter: evidenceAdapterForRunner(check.runner.type),
|
|
35
|
-
runner
|
|
62
|
+
runner,
|
|
36
63
|
verification_input_hashes: verificationInputHashes,
|
|
37
64
|
execution_target_definition: executionTarget,
|
|
38
65
|
known_execution_targets: knownExecutionTargets,
|
|
39
66
|
design_conformance_targets: designConformanceTargets,
|
|
40
67
|
semantic_fact_expectations: semanticFactExpectations,
|
|
68
|
+
observation_authorities: observationAuthorities,
|
|
69
|
+
process_runtime_closure: processRuntimeClosure,
|
|
41
70
|
};
|
|
42
71
|
return {
|
|
43
72
|
...compiled,
|
|
@@ -56,7 +85,7 @@ function validateSemanticFactOracleInputs(checkKey, expectations, verificationIn
|
|
|
56
85
|
throw new Error(`semantic_fact_oracle_verification_input_mismatch:${checkKey}:${oracle.key}:${oracle.identity}`);
|
|
57
86
|
}
|
|
58
87
|
}
|
|
59
|
-
async function resolvedRunnerTarget(check, repository, cwd) {
|
|
88
|
+
async function resolvedRunnerTarget(check, repository, cwd, executionTarget, productionBindings, sourceBackedExecutionTarget) {
|
|
60
89
|
if (check.runner.type === "package_script") {
|
|
61
90
|
const packageFile = await nearestRunnerFile(cwd, repository, "package.json");
|
|
62
91
|
if (!packageFile)
|
|
@@ -64,12 +93,50 @@ async function resolvedRunnerTarget(check, repository, cwd) {
|
|
|
64
93
|
return assertProtectedRepositoryFile(repository, packageFile, `${check.key}.package_json`);
|
|
65
94
|
}
|
|
66
95
|
const target = resolveInsideRepository(cwd, check.runner.target, `${check.key}.target`);
|
|
67
|
-
|
|
96
|
+
const targetInfo = await stat(target).catch(() => null);
|
|
97
|
+
if (!targetInfo?.isFile()) {
|
|
98
|
+
const relativeTarget = repoRelative(repository, target);
|
|
99
|
+
if (!targetInfo &&
|
|
100
|
+
plannedDirectProductRoot({
|
|
101
|
+
check,
|
|
102
|
+
executionTarget,
|
|
103
|
+
productionBindings,
|
|
104
|
+
sourceBackedExecutionTarget,
|
|
105
|
+
relativeTarget,
|
|
106
|
+
}))
|
|
107
|
+
return target;
|
|
68
108
|
throw new Error(`${check.runner.type}_path_not_found:${check.key}:${check.runner.target}`);
|
|
109
|
+
}
|
|
69
110
|
const protectedTarget = await assertProtectedRepositoryFile(repository, target, `${check.key}.runner_target`);
|
|
70
111
|
repoRelative(repository, protectedTarget);
|
|
71
112
|
return protectedTarget;
|
|
72
113
|
}
|
|
114
|
+
function plannedBindingMayProvideInput(bindings, inputPattern) {
|
|
115
|
+
return bindings.some((scoped) => scoped.binding.existence === "planned" &&
|
|
116
|
+
scoped.binding.carrier_paths.some((carrier) => isExactRepositoryFile(carrier, `${scoped.binding_ref}.carrier`) &&
|
|
117
|
+
proveRepositoryPatternSubset(carrier, inputPattern).status ===
|
|
118
|
+
"proven_subset"));
|
|
119
|
+
}
|
|
120
|
+
function plannedDirectProductRoot(input) {
|
|
121
|
+
return (input.check.runner.type === "project_binary" &&
|
|
122
|
+
input.check.execution_target.entrypoint === "root" &&
|
|
123
|
+
input.executionTarget.role === "product" &&
|
|
124
|
+
input.executionTarget.runtime_family === "process" &&
|
|
125
|
+
input.sourceBackedExecutionTarget?.target_ref ===
|
|
126
|
+
input.executionTarget.key &&
|
|
127
|
+
input.relativeTarget === input.executionTarget.root_entrypoint &&
|
|
128
|
+
input.productionBindings.some((scoped) => scoped.binding.existence === "planned" &&
|
|
129
|
+
scoped.binding.carrier_paths.some((carrier) => isExactRepositoryFile(carrier, `${scoped.binding_ref}.carrier`) &&
|
|
130
|
+
carrier === input.relativeTarget)));
|
|
131
|
+
}
|
|
132
|
+
function isExactRepositoryFile(value, label) {
|
|
133
|
+
try {
|
|
134
|
+
return normalizeRepositoryFile(value, label) === value;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
73
140
|
async function freezeRunner(check, repository, cwd, target, verificationInputHashes) {
|
|
74
141
|
const runner = check.runner;
|
|
75
142
|
if (runner.argv.some((value) => value.includes("\0")))
|
|
@@ -137,7 +204,7 @@ async function freezeRunner(check, repository, cwd, target, verificationInputHas
|
|
|
137
204
|
})),
|
|
138
205
|
};
|
|
139
206
|
}
|
|
140
|
-
async function freezeVerificationInputs(check, repository, manifest, cwd, target) {
|
|
207
|
+
async function freezeVerificationInputs(check, repository, manifest, cwd, target, executionTarget) {
|
|
141
208
|
const result = {};
|
|
142
209
|
for (const [index, source] of check.verification_inputs.entries()) {
|
|
143
210
|
const pattern = assertRepositoryPattern(repository, source, `${check.key}.verification_inputs[${index}]`);
|
|
@@ -149,31 +216,42 @@ async function freezeVerificationInputs(check, repository, manifest, cwd, target
|
|
|
149
216
|
result[file.path] = sha256Hex(await readFile(protectedFile));
|
|
150
217
|
}
|
|
151
218
|
}
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
"
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
]) {
|
|
162
|
-
const file = await nearestRunnerFile(cwd, repository, name);
|
|
163
|
-
if (file)
|
|
164
|
-
automatic.add(repoRelative(repository, file));
|
|
165
|
-
}
|
|
166
|
-
if (check.runner.type === "playwright_test")
|
|
219
|
+
const directProductRoot = check.runner.type === "project_binary" &&
|
|
220
|
+
executionTarget.role === "product" &&
|
|
221
|
+
executionTarget.runtime_family === "process" &&
|
|
222
|
+
check.execution_target.entrypoint === "root";
|
|
223
|
+
const automatic = new Set(directProductRoot ? [] : [repoRelative(repository, target)]);
|
|
224
|
+
if (!directProductRoot) {
|
|
225
|
+
const packageFile = await nearestRunnerFile(cwd, repository, "package.json");
|
|
226
|
+
if (packageFile)
|
|
227
|
+
automatic.add(repoRelative(repository, packageFile));
|
|
167
228
|
for (const name of [
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
229
|
+
"package-lock.json",
|
|
230
|
+
"npm-shrinkwrap.json",
|
|
231
|
+
"pnpm-lock.yaml",
|
|
232
|
+
"yarn.lock",
|
|
172
233
|
]) {
|
|
173
234
|
const file = await nearestRunnerFile(cwd, repository, name);
|
|
174
235
|
if (file)
|
|
175
236
|
automatic.add(repoRelative(repository, file));
|
|
176
237
|
}
|
|
238
|
+
}
|
|
239
|
+
if (check.runner.type === "playwright_test")
|
|
240
|
+
if (playwrightConfigArgument(check.runner.argv)) {
|
|
241
|
+
const file = resolveInsideRepository(cwd, playwrightConfigArgument(check.runner.argv), `${check.key}.playwright_config`);
|
|
242
|
+
automatic.add(repoRelative(repository, file));
|
|
243
|
+
}
|
|
244
|
+
else
|
|
245
|
+
for (const name of [
|
|
246
|
+
"playwright.config.ts",
|
|
247
|
+
"playwright.config.js",
|
|
248
|
+
"playwright.config.mjs",
|
|
249
|
+
"playwright.config.cjs",
|
|
250
|
+
]) {
|
|
251
|
+
const file = await nearestRunnerFile(cwd, repository, name);
|
|
252
|
+
if (file)
|
|
253
|
+
automatic.add(repoRelative(repository, file));
|
|
254
|
+
}
|
|
177
255
|
for (const relative of automatic) {
|
|
178
256
|
const file = manifest.files.find((candidate) => candidate.path === relative);
|
|
179
257
|
if (!file)
|
|
@@ -198,6 +276,28 @@ async function freezeVerificationInputs(check, repository, manifest, cwd, target
|
|
|
198
276
|
]));
|
|
199
277
|
return sortRecord(result);
|
|
200
278
|
}
|
|
279
|
+
export function playwrightConfigArgument(argv) {
|
|
280
|
+
const values = [];
|
|
281
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
282
|
+
const value = argv[index];
|
|
283
|
+
if (value === "--config") {
|
|
284
|
+
const next = argv[index + 1];
|
|
285
|
+
if (!next || next.startsWith("-"))
|
|
286
|
+
throw new Error("playwright_config_argument_missing");
|
|
287
|
+
values.push(next);
|
|
288
|
+
index += 1;
|
|
289
|
+
}
|
|
290
|
+
else if (value.startsWith("--config=")) {
|
|
291
|
+
const config = value.slice("--config=".length);
|
|
292
|
+
if (!config)
|
|
293
|
+
throw new Error("playwright_config_argument_missing");
|
|
294
|
+
values.push(config);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (values.length > 1)
|
|
298
|
+
throw new Error("playwright_config_argument_ambiguous");
|
|
299
|
+
return values[0] ?? null;
|
|
300
|
+
}
|
|
201
301
|
function sortRecord(value) {
|
|
202
302
|
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));
|
|
203
303
|
}
|
|
@@ -8,6 +8,7 @@ import type { EffectiveRiskLevel, RiskFactName } from "./long-task-risk-types.js
|
|
|
8
8
|
import type { SemanticFactExpectationV2 } from "./semantic-fact-types.js";
|
|
9
9
|
import type { CompiledSourceItemV2 } from "./long-task-source-authority-types.js";
|
|
10
10
|
import type { WorkspaceManifestV2 } from "./long-task-workspace-runtime-types.js";
|
|
11
|
+
import type { JsonPointerExactObservation } from "./long-task-json-pointer-observation.js";
|
|
11
12
|
export interface FrozenRunnerV2 extends DeliveryRunnerV2 {
|
|
12
13
|
executable: string;
|
|
13
14
|
executable_argv_prefix: string[];
|
|
@@ -18,6 +19,74 @@ export interface FrozenRunnerV2 extends DeliveryRunnerV2 {
|
|
|
18
19
|
package_script: string | null;
|
|
19
20
|
execution_identity: string;
|
|
20
21
|
}
|
|
22
|
+
export type CompiledObservationAuthorityKindV2 = "package_static_json_exact" | "package_process_json_exact" | "external_confirmation";
|
|
23
|
+
export type CompiledObservationActualProjectionV2 = "raw_exact" | "presence_boolean" | "truthy_boolean" | "falsy_boolean";
|
|
24
|
+
export interface CompiledObservationAuthorityV2 {
|
|
25
|
+
obligation_ref: string;
|
|
26
|
+
fact_ref: string | null;
|
|
27
|
+
assertion_ref: string;
|
|
28
|
+
claim_refs: string[];
|
|
29
|
+
target_ref: string;
|
|
30
|
+
proof_surface: ProofSurface;
|
|
31
|
+
method: string;
|
|
32
|
+
evidence_capabilities: EvidenceCapabilityV2[];
|
|
33
|
+
authority: CompiledObservationAuthorityKindV2;
|
|
34
|
+
expected_identity: string;
|
|
35
|
+
expected_value_sha256: string;
|
|
36
|
+
actual_projection: CompiledObservationActualProjectionV2;
|
|
37
|
+
observation_identity: string;
|
|
38
|
+
comparison: {
|
|
39
|
+
comparator: string;
|
|
40
|
+
mode: string;
|
|
41
|
+
parameters_sha256: string | null;
|
|
42
|
+
tolerance_sha256: string | null;
|
|
43
|
+
mask_sha256: string | null;
|
|
44
|
+
};
|
|
45
|
+
locator_policy: {
|
|
46
|
+
kind: "fixed_json_pointer";
|
|
47
|
+
value: string;
|
|
48
|
+
};
|
|
49
|
+
carrier_refs: Array<{
|
|
50
|
+
binding_ref: string;
|
|
51
|
+
carrier_paths: string[];
|
|
52
|
+
}>;
|
|
53
|
+
runtime_requirements: {
|
|
54
|
+
runtime_family: ExecutionTargetV2["runtime_family"];
|
|
55
|
+
target_role: ExecutionTargetV2["role"];
|
|
56
|
+
entrypoint: DeliveryCheckV2["execution_target"]["entrypoint"];
|
|
57
|
+
runner_type: DeliveryRunnerV2["type"];
|
|
58
|
+
resolved_runner_target: string;
|
|
59
|
+
declared_root_entrypoint: string;
|
|
60
|
+
resolved_runner_argv: string[];
|
|
61
|
+
declared_root_argv: string[] | null;
|
|
62
|
+
effect: DeliveryRunnerV2["effect"];
|
|
63
|
+
direct_root_match: boolean;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export interface SourceBackedExecutionTargetV2 {
|
|
67
|
+
target_ref: string;
|
|
68
|
+
canonical_target_ref: string;
|
|
69
|
+
source_claim_key: string;
|
|
70
|
+
source_item_key: string;
|
|
71
|
+
source_path: string;
|
|
72
|
+
source_text_sha256: string;
|
|
73
|
+
target_identity: string;
|
|
74
|
+
}
|
|
75
|
+
export interface CompiledProcessRuntimeClosureV2 {
|
|
76
|
+
target_ref: string;
|
|
77
|
+
source_target: SourceBackedExecutionTargetV2;
|
|
78
|
+
root_target: string;
|
|
79
|
+
root_argv_files: string[];
|
|
80
|
+
production_carrier_files: string[];
|
|
81
|
+
allowed_runtime_files: string[];
|
|
82
|
+
production_binding_refs: string[];
|
|
83
|
+
forbidden_role_matches: Array<{
|
|
84
|
+
path: string;
|
|
85
|
+
role: "expected_authority" | "verification" | "evidence";
|
|
86
|
+
pattern: string;
|
|
87
|
+
}>;
|
|
88
|
+
closure_identity: string;
|
|
89
|
+
}
|
|
21
90
|
export interface CompiledCheckV2 extends Omit<DeliveryCheckV2, "runner"> {
|
|
22
91
|
internal_id: string;
|
|
23
92
|
outcome_key: string | null;
|
|
@@ -29,6 +98,8 @@ export interface CompiledCheckV2 extends Omit<DeliveryCheckV2, "runner"> {
|
|
|
29
98
|
known_execution_targets: ExecutionTargetV2[];
|
|
30
99
|
design_conformance_targets: CompiledDesignTargetV2[];
|
|
31
100
|
semantic_fact_expectations: SemanticFactExpectationV2[];
|
|
101
|
+
observation_authorities: CompiledObservationAuthorityV2[];
|
|
102
|
+
process_runtime_closure: CompiledProcessRuntimeClosureV2 | null;
|
|
32
103
|
}
|
|
33
104
|
export interface ProductClaimV2 {
|
|
34
105
|
id: string;
|
|
@@ -160,6 +231,46 @@ export interface RawCommandExecutionV2 {
|
|
|
160
231
|
attempts: number;
|
|
161
232
|
duration_ms: number;
|
|
162
233
|
error: string | null;
|
|
234
|
+
package_observations?: PackageObservationValueV2[];
|
|
235
|
+
host_execution_attestation?: HostExecutionAttestationV2 | null;
|
|
236
|
+
}
|
|
237
|
+
export interface PackageObservationValueV2 {
|
|
238
|
+
authority: Exclude<CompiledObservationAuthorityKindV2, "external_confirmation">;
|
|
239
|
+
observation_identity: string;
|
|
240
|
+
assertion_ref: string;
|
|
241
|
+
obligation_ref: string;
|
|
242
|
+
method: string;
|
|
243
|
+
raw_value: unknown;
|
|
244
|
+
observation: JsonPointerExactObservation | null;
|
|
245
|
+
reason: string | null;
|
|
246
|
+
}
|
|
247
|
+
export interface PackageProcessObservationV1 {
|
|
248
|
+
schema_version: "ty-context-product-observation-v1";
|
|
249
|
+
artifact_sha256: string;
|
|
250
|
+
observations: Record<string, unknown>;
|
|
251
|
+
value_sha256_by_identity: Record<string, string>;
|
|
252
|
+
package_observations: PackageObservationValueV2[];
|
|
253
|
+
}
|
|
254
|
+
export interface HostExecutionAttestationV2 {
|
|
255
|
+
raw_execution_identity: string;
|
|
256
|
+
executable_path: string;
|
|
257
|
+
declared_root_entrypoint: string;
|
|
258
|
+
actual_argv: string[];
|
|
259
|
+
declared_root_argv: string[];
|
|
260
|
+
direct_root_match: boolean;
|
|
261
|
+
pid: number;
|
|
262
|
+
started_at: string;
|
|
263
|
+
completed_at: string;
|
|
264
|
+
exit_code: number;
|
|
265
|
+
snapshot_sha256: string;
|
|
266
|
+
observation_execution_nonce: string;
|
|
267
|
+
observation_artifact_sha256: string;
|
|
268
|
+
process_runtime_closure_identity: string;
|
|
269
|
+
}
|
|
270
|
+
export interface CheckRunnerExecutionContextV2 {
|
|
271
|
+
snapshot_sha256?: string;
|
|
272
|
+
observation_authorities?: readonly CompiledObservationAuthorityV2[];
|
|
273
|
+
process_runtime_closure_identity?: string;
|
|
163
274
|
}
|
|
164
275
|
export interface CheckExecutionResultV2 {
|
|
165
276
|
internal_id: string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DeliveryBindingV2 } from "./long-task-delivery-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ephemeral compiler identity for one authored Outcome-local Binding.
|
|
4
|
+
* Authored Contracts keep their existing local Binding keys.
|
|
5
|
+
*/
|
|
6
|
+
export interface ScopedDeliveryBindingV2 {
|
|
7
|
+
outcome_key: string;
|
|
8
|
+
local_key: string;
|
|
9
|
+
binding_ref: string;
|
|
10
|
+
binding: DeliveryBindingV2;
|
|
11
|
+
}
|
|
12
|
+
export declare function scopeDeliveryBinding(outcomeKey: string, binding: DeliveryBindingV2): ScopedDeliveryBindingV2;
|
|
13
|
+
export declare function scopeDeliveryBindings(outcomeKey: string, bindings: readonly DeliveryBindingV2[]): ScopedDeliveryBindingV2[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function scopeDeliveryBinding(outcomeKey, binding) {
|
|
2
|
+
return {
|
|
3
|
+
outcome_key: outcomeKey,
|
|
4
|
+
local_key: binding.key,
|
|
5
|
+
binding_ref: `${outcomeKey}.${binding.key}`,
|
|
6
|
+
binding,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function scopeDeliveryBindings(outcomeKey, bindings) {
|
|
10
|
+
return bindings.map((binding) => scopeDeliveryBinding(outcomeKey, binding));
|
|
11
|
+
}
|
|
@@ -22,6 +22,7 @@ export interface ExecutionTargetV2 {
|
|
|
22
22
|
role: "product" | "support" | "observer";
|
|
23
23
|
runtime_family: ExecutionTargetRuntimeFamilyV2;
|
|
24
24
|
root_entrypoint: string;
|
|
25
|
+
root_argv?: string[];
|
|
25
26
|
capabilities: ExecutionTargetCapabilityV2[];
|
|
26
27
|
}
|
|
27
28
|
export interface DeliveryStageV2 {
|
|
@@ -19,9 +19,9 @@ export function validateSemanticFactContractProjection(contract, manifest, index
|
|
|
19
19
|
assertSameSemanticFactClosureSet(bindings.proofs.map((item) => revisionPair(item.proof_ref, item.obligation_revision_digest, `contract_obligation_revision:${outcome.key}`)), proofs.map((item) => revisionPair(item.key, obligationRevisions.get(item.key), `source_obligation_revision:${outcome.key}`)), `contract_obligation_revision_set:${outcome.key}`);
|
|
20
20
|
}
|
|
21
21
|
assertSameSemanticFactClosureSet(bindings.proofs.map((item) => item.proof_ref), proofs.map((item) => item.key), `contract_proof_set:${outcome.key}`);
|
|
22
|
-
uniqueSemanticFactClosureValues(bindings.proofs
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
uniqueSemanticFactClosureValues(bindings.proofs
|
|
23
|
+
.filter((item) => item.authority === "machine")
|
|
24
|
+
.map((item) => `${item.check_ref}\0${item.assertion_ref}`), `contract_proof_target:${outcome.key}`);
|
|
25
25
|
validateSemanticFactOutcomeBindings(outcome, manifest, index, allFactBindings, factRevisions, revisionsRequired);
|
|
26
26
|
validateSemanticFactProofBindings(contract, outcome, manifest, index, targetByRef, expectations, allProofBindings, factRevisions, obligationRevisions, revisionsRequired);
|
|
27
27
|
}
|
|
@@ -3,7 +3,7 @@ type SemanticRecord = Extract<EvidenceCapabilityRecordV2, {
|
|
|
3
3
|
capability: "semantic_fact";
|
|
4
4
|
}>;
|
|
5
5
|
export declare function validateSemanticFactEvidence(check: CompiledCheckV2, record: SemanticRecord, artifactHashes: Record<string, string>): string | null;
|
|
6
|
-
|
|
6
|
+
type SemanticFactExactComparisonMaterial = {
|
|
7
7
|
fact_ref: string;
|
|
8
8
|
proof_ref: string;
|
|
9
9
|
fact_key?: string;
|
|
@@ -18,8 +18,8 @@ export declare function semanticFactComparisonResultIdentity(value: {
|
|
|
18
18
|
parameters_sha256: string;
|
|
19
19
|
tolerance_sha256: string | null;
|
|
20
20
|
mask_sha256: string | null;
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
};
|
|
22
|
+
export declare function semanticFactComparisonResultIdentity(value: SemanticFactExactComparisonMaterial): string;
|
|
23
23
|
export declare function validateDistinctSemanticFactEvidence(records: EvidenceCapabilityRecordV2[]): string | null;
|
|
24
24
|
export declare const typed_semantic_fact_runtime_evidence = "obligation_key+obligation_revision_digest->fact_key+fact_revision_digest+actual+comparison+verdict+oracle+environment";
|
|
25
25
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { evaluateExactDigestComparison, } from "./long-task-exact-comparison.js";
|
|
2
|
+
import { canonicalValueJson } from "./strict-codec.js";
|
|
2
3
|
export function validateSemanticFactEvidence(check, record, artifactHashes) {
|
|
3
4
|
const expectations = check.semantic_fact_expectations.filter((item) => item.assertion_ref === record.assertion_key);
|
|
4
5
|
if (expectations.length !== 1)
|
|
@@ -15,8 +16,6 @@ export function validateSemanticFactEvidence(check, record, artifactHashes) {
|
|
|
15
16
|
const observerError = validateSemanticFactObservers(record, expected, artifactHashes);
|
|
16
17
|
if (observerError)
|
|
17
18
|
return observerError;
|
|
18
|
-
if (record.verdict !== "passed" || record.comparison.passed !== true)
|
|
19
|
-
return "semantic_fact_failed";
|
|
20
19
|
return null;
|
|
21
20
|
}
|
|
22
21
|
function validateSemanticFactEvidenceAuthority(check, record, expected) {
|
|
@@ -34,28 +33,9 @@ function validateSemanticFactEvidenceAuthority(check, record, expected) {
|
|
|
34
33
|
return "semantic_fact_expected_value_mismatch";
|
|
35
34
|
if (!sameSemanticFactComparisonAuthority(record, expected))
|
|
36
35
|
return "semantic_fact_comparison_authority_mismatch";
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
proof_ref: record.proof_ref,
|
|
41
|
-
fact_key: record.fact_key,
|
|
42
|
-
fact_revision_digest: record.fact_revision_digest,
|
|
43
|
-
obligation_key: record.obligation_key,
|
|
44
|
-
obligation_revision_digest: record.obligation_revision_digest,
|
|
45
|
-
target_ref: record.target_ref,
|
|
46
|
-
actual_value_sha256: record.actual_observation.value_sha256,
|
|
47
|
-
expected_value_sha256: expected.expected.sha256,
|
|
48
|
-
comparator: record.comparison.comparator,
|
|
49
|
-
mode: record.comparison.mode,
|
|
50
|
-
parameters_sha256: record.comparison.parameters.sha256,
|
|
51
|
-
tolerance_sha256: record.comparison.tolerance?.sha256 ?? null,
|
|
52
|
-
mask_sha256: record.comparison.mask?.sha256 ?? null,
|
|
53
|
-
passed: record.comparison.passed,
|
|
54
|
-
}))
|
|
55
|
-
return "semantic_fact_comparison_result_identity_mismatch";
|
|
56
|
-
if (record.comparison.comparator === "exact_value" &&
|
|
57
|
-
record.actual_observation.value_sha256 !== expected.expected.sha256)
|
|
58
|
-
return "semantic_fact_exact_value_mismatch";
|
|
36
|
+
const exactError = validateSemanticFactExactComparison(record, expected);
|
|
37
|
+
if (exactError)
|
|
38
|
+
return exactError;
|
|
59
39
|
if (canonicalValueJson(record.oracle) !== canonicalValueJson(expected.oracle) ||
|
|
60
40
|
canonicalValueJson(record.environment) !==
|
|
61
41
|
canonicalValueJson(expected.environment))
|
|
@@ -93,7 +73,11 @@ function validSemanticFactRedaction(sensitivity, redaction) {
|
|
|
93
73
|
(sensitivity === "protected" && redaction !== null));
|
|
94
74
|
}
|
|
95
75
|
function sameSemanticFactComparisonAuthority(record, expected) {
|
|
96
|
-
return (
|
|
76
|
+
return (expected.comparison.comparator === "exact_value" &&
|
|
77
|
+
expected.comparison.mode === "exact" &&
|
|
78
|
+
expected.comparison.tolerance === null &&
|
|
79
|
+
expected.comparison.mask === null &&
|
|
80
|
+
record.comparison.comparator === expected.comparison.comparator &&
|
|
97
81
|
record.comparison.mode === expected.comparison.mode &&
|
|
98
82
|
canonicalValueJson(record.comparison.parameters) ===
|
|
99
83
|
canonicalValueJson(expected.comparison.parameters) &&
|
|
@@ -102,6 +86,17 @@ function sameSemanticFactComparisonAuthority(record, expected) {
|
|
|
102
86
|
canonicalValueJson(record.comparison.mask) ===
|
|
103
87
|
canonicalValueJson(expected.comparison.mask));
|
|
104
88
|
}
|
|
89
|
+
function validateSemanticFactExactComparison(record, expected) {
|
|
90
|
+
const recomputed = evaluateSemanticFactExactComparison(expected, record.target_ref, record.actual_observation.value_sha256);
|
|
91
|
+
if (!recomputed.passed)
|
|
92
|
+
return "semantic_fact_exact_value_mismatch";
|
|
93
|
+
if (record.comparison.passed !== recomputed.passed ||
|
|
94
|
+
record.verdict !== semanticFactVerdict(recomputed.passed))
|
|
95
|
+
return "project_submitted_verdict_disagrees_with_harness";
|
|
96
|
+
return record.comparison.result_sha256 === recomputed.result_sha256
|
|
97
|
+
? null
|
|
98
|
+
: "semantic_fact_comparison_result_identity_mismatch";
|
|
99
|
+
}
|
|
105
100
|
function validateSemanticFactArtifacts(record, expected, artifactHashes) {
|
|
106
101
|
if (artifactHashes[record.actual_observation.artifact_path] !==
|
|
107
102
|
record.actual_observation.artifact_sha256)
|
|
@@ -129,52 +124,74 @@ function validateSemanticFactObservers(record, expected, artifactHashes) {
|
|
|
129
124
|
observerObservations.add(observation);
|
|
130
125
|
if (artifactHashes[observer.artifact_path] !== observer.artifact_sha256)
|
|
131
126
|
return "semantic_fact_observer_artifact_mismatch";
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
observer.value_sha256 !== expected.expected.sha256))
|
|
127
|
+
const recomputed = evaluateSemanticFactExactComparison(expected, observer.target_ref, observer.value_sha256);
|
|
128
|
+
if (!recomputed.passed)
|
|
135
129
|
return "semantic_fact_observer_failed";
|
|
136
|
-
if (observer.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
proof_ref: record.proof_ref,
|
|
140
|
-
fact_key: record.fact_key,
|
|
141
|
-
fact_revision_digest: record.fact_revision_digest,
|
|
142
|
-
obligation_key: record.obligation_key,
|
|
143
|
-
obligation_revision_digest: record.obligation_revision_digest,
|
|
144
|
-
target_ref: observer.target_ref,
|
|
145
|
-
actual_value_sha256: observer.value_sha256,
|
|
146
|
-
expected_value_sha256: expected.expected.sha256,
|
|
147
|
-
comparator: record.comparison.comparator,
|
|
148
|
-
mode: record.comparison.mode,
|
|
149
|
-
parameters_sha256: record.comparison.parameters.sha256,
|
|
150
|
-
tolerance_sha256: record.comparison.tolerance?.sha256 ?? null,
|
|
151
|
-
mask_sha256: record.comparison.mask?.sha256 ?? null,
|
|
152
|
-
passed: observer.passed,
|
|
153
|
-
}))
|
|
130
|
+
if (observer.passed !== recomputed.passed)
|
|
131
|
+
return "project_submitted_verdict_disagrees_with_harness";
|
|
132
|
+
if (observer.comparison_result_sha256 !== recomputed.result_sha256)
|
|
154
133
|
return "semantic_fact_observer_comparison_identity_mismatch";
|
|
155
134
|
}
|
|
156
135
|
return null;
|
|
157
136
|
}
|
|
158
137
|
export function semanticFactComparisonResultIdentity(value) {
|
|
138
|
+
return evaluateSemanticFactExactComparisonMaterial(value).result_sha256;
|
|
139
|
+
}
|
|
140
|
+
function evaluateSemanticFactExactComparison(expected, targetRef, actualValueSha256) {
|
|
141
|
+
return evaluateSemanticFactExactComparisonMaterial({
|
|
142
|
+
fact_ref: expected.fact_ref,
|
|
143
|
+
proof_ref: expected.proof_ref,
|
|
144
|
+
fact_key: expected.fact_key,
|
|
145
|
+
fact_revision_digest: expected.fact_revision_digest,
|
|
146
|
+
obligation_key: expected.obligation_key,
|
|
147
|
+
obligation_revision_digest: expected.obligation_revision_digest,
|
|
148
|
+
target_ref: targetRef,
|
|
149
|
+
actual_value_sha256: actualValueSha256,
|
|
150
|
+
expected_value_sha256: expected.expected.sha256,
|
|
151
|
+
comparator: expected.comparison.comparator,
|
|
152
|
+
mode: expected.comparison.mode,
|
|
153
|
+
parameters_sha256: expected.comparison.parameters.sha256,
|
|
154
|
+
tolerance_sha256: expected.comparison.tolerance?.sha256 ?? null,
|
|
155
|
+
mask_sha256: expected.comparison.mask?.sha256 ?? null,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function evaluateSemanticFactExactComparisonMaterial(value) {
|
|
159
|
+
return evaluateExactDigestComparison({
|
|
160
|
+
identity: semanticFactComparisonIdentity(value),
|
|
161
|
+
actual_value_sha256: value.actual_value_sha256,
|
|
162
|
+
expected_value_sha256: value.expected_value_sha256,
|
|
163
|
+
comparator: value.comparator,
|
|
164
|
+
mode: value.mode,
|
|
165
|
+
parameters_sha256: value.parameters_sha256,
|
|
166
|
+
tolerance_sha256: value.tolerance_sha256,
|
|
167
|
+
mask_sha256: value.mask_sha256,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function semanticFactComparisonIdentity(value) {
|
|
159
171
|
const revisionIdentityPresent = value.fact_key !== undefined ||
|
|
160
172
|
value.fact_revision_digest !== undefined ||
|
|
161
173
|
value.obligation_key !== undefined ||
|
|
162
174
|
value.obligation_revision_digest !== undefined;
|
|
163
|
-
return
|
|
164
|
-
?
|
|
175
|
+
return revisionIdentityPresent
|
|
176
|
+
? {
|
|
177
|
+
kind: "semantic_fact_non_ui",
|
|
178
|
+
fact_ref: value.fact_ref,
|
|
179
|
+
proof_ref: value.proof_ref,
|
|
180
|
+
fact_key: value.fact_key,
|
|
181
|
+
fact_revision_digest: value.fact_revision_digest,
|
|
182
|
+
obligation_key: value.obligation_key,
|
|
183
|
+
obligation_revision_digest: value.obligation_revision_digest,
|
|
184
|
+
target_ref: value.target_ref,
|
|
185
|
+
}
|
|
165
186
|
: {
|
|
187
|
+
kind: "semantic_fact_non_ui",
|
|
166
188
|
fact_ref: value.fact_ref,
|
|
167
189
|
proof_ref: value.proof_ref,
|
|
168
190
|
target_ref: value.target_ref,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
parameters_sha256: value.parameters_sha256,
|
|
174
|
-
tolerance_sha256: value.tolerance_sha256,
|
|
175
|
-
mask_sha256: value.mask_sha256,
|
|
176
|
-
passed: value.passed,
|
|
177
|
-
}));
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function semanticFactVerdict(passed) {
|
|
194
|
+
return passed ? "passed" : "failed";
|
|
178
195
|
}
|
|
179
196
|
export function validateDistinctSemanticFactEvidence(records) {
|
|
180
197
|
const observations = new Set();
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { resolveAcceptanceAssertion } from "./long-task-acceptance-reference.js";
|
|
2
2
|
import { fail } from "./long-task-delivery-shape.js";
|
|
3
|
+
import { executionTargetSourceTargetRef } from "./long-task-source-target-index.js";
|
|
3
4
|
export function validateSourceClaimMappings(contract, compiledClaims, report) {
|
|
4
5
|
validateSourcePresence(contract, report);
|
|
5
6
|
const sources = new Set(contract.task.source_paths);
|
|
6
7
|
const productClaims = new Set(Object.values(compiledClaims.by_outcome)
|
|
7
8
|
.flat()
|
|
8
9
|
.map((claim) => claim.id));
|
|
10
|
+
const executionTargetClaims = new Set(contract.task.execution_targets.map((target) => executionTargetSourceTargetRef(target.key)));
|
|
9
11
|
const globalClaims = new Map(compiledClaims.by_global.map((claim) => [claim.local_key, claim]));
|
|
10
12
|
const coveredGlobalClaims = new Set(Object.entries(compiledClaims.summary.claims_by_global)
|
|
11
13
|
.filter(([, value]) => value.covered)
|
|
@@ -22,7 +24,8 @@ export function validateSourceClaimMappings(contract, compiledClaims, report) {
|
|
|
22
24
|
for (const reference of disposition.refs) {
|
|
23
25
|
if (reference.endsWith(".result"))
|
|
24
26
|
issue(report, "source_claim_result_overcompression", `${claim.key}:${reference}`);
|
|
25
|
-
if (!productClaims.has(reference)
|
|
27
|
+
if (!productClaims.has(reference) &&
|
|
28
|
+
!executionTargetClaims.has(reference))
|
|
26
29
|
issue(report, "source_claim_product_ref_unknown", `${claim.key}:${reference}`);
|
|
27
30
|
}
|
|
28
31
|
if (disposition.type === "acceptance") {
|