project-tiny-context-harness 0.8.4 → 0.8.5
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/LICENSE +21 -21
- package/README.md +393 -371
- package/assets/README.md +573 -526
- package/assets/README.zh-CN.md +333 -311
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +44 -25
- package/assets/context_templates/architecture.md +28 -28
- package/assets/context_templates/area.md +34 -34
- package/assets/context_templates/context.toml +30 -30
- package/assets/context_templates/deployment.md +35 -35
- package/assets/context_templates/global.md +57 -57
- package/assets/context_templates/product-surface-contract.md +70 -70
- package/assets/context_templates/screen-contract.md +189 -189
- package/assets/context_templates/verification.md +32 -32
- package/assets/github/.gitkeep +1 -1
- package/assets/github/harness.yml +39 -39
- package/assets/make/.gitkeep +1 -1
- package/assets/make/ty-context.mk +48 -48
- package/assets/skills/context_development_engineer/SKILL.md +148 -125
- package/assets/skills/context_full_project_export/SKILL.md +28 -28
- package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
- package/assets/skills/context_product_plan/SKILL.md +99 -79
- package/assets/skills/context_surface_contract/SKILL.md +191 -191
- package/assets/skills/context_uiux_design/SKILL.md +171 -171
- package/assets/skills/design-resource-authoring/SKILL.md +86 -84
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +138 -123
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +132 -127
- package/assets/skills/design-resource-authoring/references/resource-selection.md +181 -154
- package/assets/skills/design-system-authoring/SKILL.md +57 -57
- package/assets/skills/design-system-authoring/agents/openai.yaml +6 -6
- package/assets/skills/design-system-authoring/references/authority-adoption.md +48 -48
- package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
- package/assets/skills/long-task-workflow/SKILL.md +98 -92
- package/assets/skills/long-task-workflow/agents/openai.yaml +3 -1
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +72 -72
- package/assets/skills/long-task-workflow/references/contract-authoring.md +122 -101
- package/assets/skills/long-task-workflow/references/evidence-design.md +82 -61
- package/assets/skills/long-task-workflow/references/source-authoring.md +109 -90
- package/assets/skills/source-plan-authoring/SKILL.md +14 -14
- package/assets/tools/validate_context.py +442 -442
- package/dist/commands/long-task-authoring.js +27 -2
- package/dist/lib/context-templates.js +1 -1
- package/dist/lib/design-resource-fact-enums.d.ts +20 -0
- package/dist/lib/design-resource-fact-enums.js +170 -0
- package/dist/lib/design-resource-fact-locator-extractors.d.ts +8 -0
- package/dist/lib/design-resource-fact-locator-extractors.js +108 -0
- package/dist/lib/design-resource-fact-locator-resolver.d.ts +3 -0
- package/dist/lib/design-resource-fact-locator-resolver.js +112 -0
- package/dist/lib/design-resource-fact-locator-validation.d.ts +5 -0
- package/dist/lib/design-resource-fact-locator-validation.js +16 -0
- package/dist/lib/design-resource-fact-manifest-catalog.d.ts +4 -0
- package/dist/lib/design-resource-fact-manifest-catalog.js +249 -0
- package/dist/lib/design-resource-fact-manifest-model.d.ts +91 -0
- package/dist/lib/design-resource-fact-manifest-model.js +21 -0
- package/dist/lib/design-resource-fact-manifest-shape-axes.d.ts +6 -0
- package/dist/lib/design-resource-fact-manifest-shape-axes.js +159 -0
- package/dist/lib/design-resource-fact-manifest-shape-evidence.d.ts +4 -0
- package/dist/lib/design-resource-fact-manifest-shape-evidence.js +59 -0
- package/dist/lib/design-resource-fact-manifest-shape-facts.d.ts +4 -0
- package/dist/lib/design-resource-fact-manifest-shape-facts.js +109 -0
- package/dist/lib/design-resource-fact-manifest-shape-inspector.d.ts +5 -0
- package/dist/lib/design-resource-fact-manifest-shape-inspector.js +144 -0
- package/dist/lib/design-resource-fact-manifest-shape.d.ts +7 -0
- package/dist/lib/design-resource-fact-manifest-shape.js +75 -0
- package/dist/lib/design-resource-fact-manifest-types.d.ts +3 -0
- package/dist/lib/design-resource-fact-manifest-types.js +3 -0
- package/dist/lib/design-resource-fact-manifest-universe.d.ts +5 -0
- package/dist/lib/design-resource-fact-manifest-universe.js +50 -0
- package/dist/lib/design-resource-fact-manifest-validation.d.ts +3 -0
- package/dist/lib/design-resource-fact-manifest-validation.js +106 -0
- package/dist/lib/design-resource-fact-policy.d.ts +18 -0
- package/dist/lib/design-resource-fact-policy.js +72 -1
- package/dist/lib/design-resource-fact-property-methods.d.ts +3 -0
- package/dist/lib/design-resource-fact-property-methods.js +158 -0
- package/dist/lib/design-resource-fact-shape-primitives.d.ts +3 -0
- package/dist/lib/design-resource-fact-shape-primitives.js +18 -0
- package/dist/lib/design-resource-fact-types.d.ts +164 -0
- package/dist/lib/design-resource-fact-types.js +1 -0
- package/dist/lib/design-resource-fact-universe-assets.d.ts +4 -0
- package/dist/lib/design-resource-fact-universe-assets.js +71 -0
- package/dist/lib/design-resource-fact-universe-catalog.d.ts +4 -0
- package/dist/lib/design-resource-fact-universe-catalog.js +151 -0
- package/dist/lib/design-resource-fact-universe-conditions.d.ts +2 -0
- package/dist/lib/design-resource-fact-universe-conditions.js +92 -0
- package/dist/lib/design-resource-fact-universe-facts.d.ts +4 -0
- package/dist/lib/design-resource-fact-universe-facts.js +108 -0
- package/dist/lib/design-resource-fact-universe-helpers.d.ts +30 -0
- package/dist/lib/design-resource-fact-universe-helpers.js +167 -0
- package/dist/lib/design-resource-fact-universe-inspector.d.ts +7 -0
- package/dist/lib/design-resource-fact-universe-inspector.js +119 -0
- package/dist/lib/design-resource-fact-universe-proof.d.ts +4 -0
- package/dist/lib/design-resource-fact-universe-proof.js +113 -0
- package/dist/lib/design-resource-fact-universe-subjects.d.ts +5 -0
- package/dist/lib/design-resource-fact-universe-subjects.js +97 -0
- package/dist/lib/design-resource-fact-universe-variations.d.ts +2 -0
- package/dist/lib/design-resource-fact-universe-variations.js +75 -0
- package/dist/lib/design-resource-fact-value-validation.d.ts +2 -0
- package/dist/lib/design-resource-fact-value-validation.js +80 -0
- package/dist/lib/design-resource-handoff-file-primitives.js +2 -0
- package/dist/lib/design-resource-handoff-file-validation.js +13 -100
- package/dist/lib/design-resource-handoff-policy.d.ts +1 -0
- package/dist/lib/design-resource-handoff-policy.js +118 -11
- package/dist/lib/design-resource-handoff-shape-evidence.js +46 -3
- package/dist/lib/design-resource-handoff-shape-primitives.d.ts +5 -0
- package/dist/lib/design-resource-handoff-shape-primitives.js +28 -0
- package/dist/lib/design-resource-handoff-shape-structure.js +143 -22
- package/dist/lib/design-resource-handoff-shape.js +25 -0
- package/dist/lib/design-resource-handoff-types.d.ts +97 -21
- package/dist/lib/design-resource-handoff-types.js +22 -0
- package/dist/lib/design-resource-handoff-validation-coverage.d.ts +1 -1
- package/dist/lib/design-resource-handoff-validation-coverage.js +145 -118
- package/dist/lib/design-resource-handoff-validation-fact-cells.d.ts +2 -0
- package/dist/lib/design-resource-handoff-validation-fact-cells.js +60 -0
- package/dist/lib/design-resource-handoff-validation-fact-records.d.ts +2 -0
- package/dist/lib/design-resource-handoff-validation-fact-records.js +90 -0
- package/dist/lib/design-resource-handoff-validation-facts.js +10 -94
- package/dist/lib/design-resource-handoff-validation-proofs.d.ts +2 -0
- package/dist/lib/design-resource-handoff-validation-proofs.js +67 -0
- package/dist/lib/design-resource-handoff-validation-resource-closure.d.ts +3 -0
- package/dist/lib/design-resource-handoff-validation-resource-closure.js +88 -0
- package/dist/lib/design-resource-handoff-validation-structure.js +43 -14
- package/dist/lib/design-resource-handoff-validation.js +32 -0
- package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +2 -1
- package/dist/lib/design-resource-handoff-web-dependency-validation.js +67 -7
- package/dist/lib/execution-target-capabilities.d.ts +1 -1
- package/dist/lib/execution-target-capabilities.js +14 -0
- package/dist/lib/long-task-activation-validation.js +6 -2
- package/dist/lib/long-task-applicability-shape.js +3 -3
- package/dist/lib/long-task-authoring-authority-preview.js +1 -0
- package/dist/lib/long-task-authority-policy.d.ts +1 -0
- package/dist/lib/long-task-authority-policy.js +1 -0
- package/dist/lib/long-task-authority.js +13 -0
- package/dist/lib/long-task-claim-definitions.js +13 -1
- package/dist/lib/long-task-claims.js +23 -1
- package/dist/lib/long-task-contract-types.d.ts +3 -0
- package/dist/lib/long-task-delivery-compiler.js +1 -0
- package/dist/lib/long-task-delivery-parser.js +11 -1
- package/dist/lib/long-task-delivery-types.d.ts +1 -0
- package/dist/lib/long-task-delivery-types.js +1 -0
- package/dist/lib/long-task-delivery-validation.js +17 -0
- package/dist/lib/long-task-design-resource-handoff.js +62 -38
- package/dist/lib/long-task-design-target-capabilities.d.ts +14 -0
- package/dist/lib/long-task-design-target-capabilities.js +126 -0
- package/dist/lib/long-task-evidence-capability-codec.d.ts +94 -0
- package/dist/lib/long-task-evidence-capability-codec.js +395 -22
- package/dist/lib/long-task-evidence-capability-policy.js +18 -0
- package/dist/lib/long-task-evidence-capability-runtime.js +78 -0
- package/dist/lib/long-task-evidence-capability-types.d.ts +114 -1
- package/dist/lib/long-task-outcome-parser.js +4 -0
- package/dist/lib/long-task-playwright-capability-records.d.ts +5 -0
- package/dist/lib/long-task-playwright-capability-records.js +146 -0
- package/dist/lib/long-task-playwright-case-evidence.d.ts +3 -2
- package/dist/lib/long-task-playwright-case-evidence.js +10 -79
- package/dist/lib/long-task-playwright-case-primitives.d.ts +28 -0
- package/dist/lib/long-task-playwright-case-primitives.js +143 -0
- package/dist/lib/long-task-playwright-evidence.d.ts +1 -1
- package/dist/lib/long-task-playwright-evidence.js +10 -75
- package/dist/lib/long-task-runner-freeze.d.ts +2 -2
- package/dist/lib/long-task-runner-freeze.js +15 -1
- package/dist/lib/long-task-runtime-types.d.ts +4 -1
- package/dist/lib/long-task-semantic-contract-types.d.ts +1 -1
- package/dist/lib/long-task-semantic-drift-migration.js +2 -2
- package/dist/lib/long-task-semantic-fact-binding-types.d.ts +57 -0
- package/dist/lib/long-task-semantic-fact-binding-types.js +1 -0
- package/dist/lib/long-task-semantic-fact-closure-primitives.d.ts +5 -0
- package/dist/lib/long-task-semantic-fact-closure-primitives.js +43 -0
- package/dist/lib/long-task-semantic-fact-closure.d.ts +13 -0
- package/dist/lib/long-task-semantic-fact-closure.js +48 -0
- package/dist/lib/long-task-semantic-fact-contract-closure.d.ts +4 -0
- package/dist/lib/long-task-semantic-fact-contract-closure.js +24 -0
- package/dist/lib/long-task-semantic-fact-contract-facts.d.ts +4 -0
- package/dist/lib/long-task-semantic-fact-contract-facts.js +30 -0
- package/dist/lib/long-task-semantic-fact-contract-proofs.d.ts +4 -0
- package/dist/lib/long-task-semantic-fact-contract-proofs.js +97 -0
- package/dist/lib/long-task-semantic-fact-evidence.d.ts +21 -0
- package/dist/lib/long-task-semantic-fact-evidence.js +165 -0
- package/dist/lib/long-task-semantic-fact-input-closure.d.ts +4 -0
- package/dist/lib/long-task-semantic-fact-input-closure.js +101 -0
- package/dist/lib/long-task-semantic-fact-provenance-closure.d.ts +4 -0
- package/dist/lib/long-task-semantic-fact-provenance-closure.js +140 -0
- package/dist/lib/long-task-semantic-fact-shape.d.ts +3 -0
- package/dist/lib/long-task-semantic-fact-shape.js +89 -0
- package/dist/lib/long-task-semantic-fact-value-closure.d.ts +3 -0
- package/dist/lib/long-task-semantic-fact-value-closure.js +110 -0
- package/dist/lib/long-task-shape-primitives.d.ts +2 -1
- package/dist/lib/long-task-shape-primitives.js +7 -0
- package/dist/lib/long-task-source-item-parser.js +25 -6
- package/dist/lib/long-task-source-target-continuity.js +4 -1
- package/dist/lib/long-task-source-target-index.d.ts +1 -1
- package/dist/lib/long-task-source-target-index.js +5 -1
- package/dist/lib/long-task-ui-design-policy.js +8 -4
- package/dist/lib/long-task-ui-surface-shape.js +83 -1
- package/dist/lib/long-task-ui-surface-types.d.ts +29 -0
- package/dist/lib/modularity.js +7 -1
- package/dist/lib/semantic-fact-base-types.d.ts +14 -0
- package/dist/lib/semantic-fact-base-types.js +1 -0
- package/dist/lib/semantic-fact-catalog.d.ts +8 -0
- package/dist/lib/semantic-fact-catalog.js +191 -0
- package/dist/lib/semantic-fact-condition-shape.d.ts +48 -0
- package/dist/lib/semantic-fact-condition-shape.js +111 -0
- package/dist/lib/semantic-fact-input-shape.d.ts +34 -0
- package/dist/lib/semantic-fact-input-shape.js +111 -0
- package/dist/lib/semantic-fact-inventory-types.d.ts +147 -0
- package/dist/lib/semantic-fact-inventory-types.js +1 -0
- package/dist/lib/semantic-fact-manifest-shape.d.ts +4 -0
- package/dist/lib/semantic-fact-manifest-shape.js +135 -0
- package/dist/lib/semantic-fact-manifest-types.d.ts +58 -0
- package/dist/lib/semantic-fact-manifest-types.js +19 -0
- package/dist/lib/semantic-fact-policy-authority.d.ts +8 -0
- package/dist/lib/semantic-fact-policy-authority.js +79 -0
- package/dist/lib/semantic-fact-policy-census.d.ts +2 -0
- package/dist/lib/semantic-fact-policy-census.js +80 -0
- package/dist/lib/semantic-fact-policy-condition-references.d.ts +7 -0
- package/dist/lib/semantic-fact-policy-condition-references.js +19 -0
- package/dist/lib/semantic-fact-policy-conditions.d.ts +2 -0
- package/dist/lib/semantic-fact-policy-conditions.js +105 -0
- package/dist/lib/semantic-fact-policy-facts.d.ts +3 -0
- package/dist/lib/semantic-fact-policy-facts.js +73 -0
- package/dist/lib/semantic-fact-policy-primitives.d.ts +26 -0
- package/dist/lib/semantic-fact-policy-primitives.js +169 -0
- package/dist/lib/semantic-fact-policy-proofs.d.ts +2 -0
- package/dist/lib/semantic-fact-policy-proofs.js +75 -0
- package/dist/lib/semantic-fact-policy-properties.d.ts +3 -0
- package/dist/lib/semantic-fact-policy-properties.js +84 -0
- package/dist/lib/semantic-fact-policy-units.d.ts +4 -0
- package/dist/lib/semantic-fact-policy-units.js +103 -0
- package/dist/lib/semantic-fact-policy.d.ts +17 -0
- package/dist/lib/semantic-fact-policy.js +41 -0
- package/dist/lib/semantic-fact-proof-shape.d.ts +51 -0
- package/dist/lib/semantic-fact-proof-shape.js +121 -0
- package/dist/lib/semantic-fact-proof-types.d.ts +74 -0
- package/dist/lib/semantic-fact-proof-types.js +1 -0
- package/dist/lib/semantic-fact-property-shape.d.ts +29 -0
- package/dist/lib/semantic-fact-property-shape.js +77 -0
- package/dist/lib/semantic-fact-shape-constants.d.ts +3 -0
- package/dist/lib/semantic-fact-shape-constants.js +38 -0
- package/dist/lib/semantic-fact-shape-primitives.d.ts +15 -0
- package/dist/lib/semantic-fact-shape-primitives.js +68 -0
- package/dist/lib/semantic-fact-source-parser.d.ts +9 -0
- package/dist/lib/semantic-fact-source-parser.js +46 -0
- package/dist/lib/semantic-fact-support-shape.d.ts +21 -0
- package/dist/lib/semantic-fact-support-shape.js +59 -0
- package/dist/lib/semantic-fact-types.d.ts +5 -0
- package/dist/lib/semantic-fact-types.js +5 -0
- package/dist/lib/semantic-fact-unit-shape.d.ts +34 -0
- package/dist/lib/semantic-fact-unit-shape.js +89 -0
- package/dist/lib/semantic-fact-value-shape.d.ts +12 -0
- package/dist/lib/semantic-fact-value-shape.js +39 -0
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +1339 -131
- package/migrations/README.md +15 -15
- package/package.json +84 -84
- package/source-mappings.yaml +25 -25
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { DESIGN_RESOURCE_VERIFICATION_METHODS } from "./design-resource-handoff-types.js";
|
|
2
|
+
import { DESIGN_RESOURCE_COMPARATORS } from "./design-resource-fact-manifest-types.js";
|
|
3
|
+
import { DESIGN_RESOURCE_LOCATOR_KINDS } from "./design-resource-handoff-types.js";
|
|
2
4
|
export function decodeEvidenceCapabilityRecords(value) {
|
|
3
5
|
if (!Array.isArray(value))
|
|
4
6
|
throw invalidRecord("must_be_array");
|
|
@@ -203,42 +205,398 @@ function decodeRecord(value, index) {
|
|
|
203
205
|
"artifact_path",
|
|
204
206
|
"observation_artifact_path",
|
|
205
207
|
"fact_refs",
|
|
208
|
+
"fact_results",
|
|
206
209
|
]);
|
|
207
210
|
return {
|
|
208
211
|
condition_key: key(cell.condition_key, `${cellLabel}.condition_key`),
|
|
209
212
|
artifact_path: nonEmpty(cell.artifact_path, `${cellLabel}.artifact_path`),
|
|
210
213
|
observation_artifact_path: nonEmpty(cell.observation_artifact_path, `${cellLabel}.observation_artifact_path`),
|
|
211
214
|
fact_refs: designFactRefs(cell.fact_refs, `${cellLabel}.fact_refs`),
|
|
215
|
+
fact_results: array(cell.fact_results, `${cellLabel}.fact_results`).map((result, resultIndex) => decodeDesignFactResult(result, `${cellLabel}.fact_results[${resultIndex}]`)),
|
|
212
216
|
};
|
|
213
217
|
}),
|
|
214
218
|
};
|
|
219
|
+
case "semantic_fact":
|
|
220
|
+
return decodeSemanticFactEvidence(row, label, base);
|
|
215
221
|
case "input_variation":
|
|
216
|
-
|
|
217
|
-
"assertion_key",
|
|
218
|
-
"capability",
|
|
219
|
-
"cases",
|
|
220
|
-
"failure_case_observed",
|
|
221
|
-
]);
|
|
222
|
-
if (typeof row.failure_case_observed !== "boolean")
|
|
223
|
-
throw invalidRecord(`${label}.failure_case_observed`);
|
|
224
|
-
return {
|
|
225
|
-
...base,
|
|
226
|
-
capability,
|
|
227
|
-
cases: array(row.cases, `${label}.cases`).map((item, caseIndex) => {
|
|
228
|
-
const caseLabel = `${label}.cases[${caseIndex}]`;
|
|
229
|
-
const entry = record(item, caseLabel);
|
|
230
|
-
exact(entry, caseLabel, ["input_sha256", "output_sha256"]);
|
|
231
|
-
return {
|
|
232
|
-
input_sha256: sha(entry.input_sha256, `${caseLabel}.input_sha256`),
|
|
233
|
-
output_sha256: sha(entry.output_sha256, `${caseLabel}.output_sha256`),
|
|
234
|
-
};
|
|
235
|
-
}),
|
|
236
|
-
failure_case_observed: row.failure_case_observed,
|
|
237
|
-
};
|
|
222
|
+
return decodeInputVariationEvidence(row, label, base);
|
|
238
223
|
default:
|
|
239
224
|
throw invalidRecord(`${label}.capability_unsupported:${capability}`);
|
|
240
225
|
}
|
|
241
226
|
}
|
|
227
|
+
function decodeInputVariationEvidence(row, label, base) {
|
|
228
|
+
exact(row, label, [
|
|
229
|
+
"assertion_key",
|
|
230
|
+
"capability",
|
|
231
|
+
"cases",
|
|
232
|
+
"failure_case_observed",
|
|
233
|
+
]);
|
|
234
|
+
if (typeof row.failure_case_observed !== "boolean")
|
|
235
|
+
throw invalidRecord(`${label}.failure_case_observed`);
|
|
236
|
+
return {
|
|
237
|
+
...base,
|
|
238
|
+
capability: "input_variation",
|
|
239
|
+
cases: array(row.cases, `${label}.cases`).map((item, caseIndex) => {
|
|
240
|
+
const caseLabel = `${label}.cases[${caseIndex}]`;
|
|
241
|
+
const entry = record(item, caseLabel);
|
|
242
|
+
exact(entry, caseLabel, ["input_sha256", "output_sha256"]);
|
|
243
|
+
return {
|
|
244
|
+
input_sha256: sha(entry.input_sha256, `${caseLabel}.input_sha256`),
|
|
245
|
+
output_sha256: sha(entry.output_sha256, `${caseLabel}.output_sha256`),
|
|
246
|
+
};
|
|
247
|
+
}),
|
|
248
|
+
failure_case_observed: row.failure_case_observed,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function decodeSemanticFactEvidence(row, label, base) {
|
|
252
|
+
exact(row, label, [
|
|
253
|
+
"assertion_key",
|
|
254
|
+
"capability",
|
|
255
|
+
"manifest_ref",
|
|
256
|
+
"manifest_sha256",
|
|
257
|
+
"outcome_ref",
|
|
258
|
+
"target_ref",
|
|
259
|
+
"fact_ref",
|
|
260
|
+
"proof_ref",
|
|
261
|
+
"method",
|
|
262
|
+
"subject_ref",
|
|
263
|
+
"condition_ref",
|
|
264
|
+
"property_ref",
|
|
265
|
+
"actual_observation",
|
|
266
|
+
"actual_environment",
|
|
267
|
+
"expected",
|
|
268
|
+
"comparison",
|
|
269
|
+
"verdict",
|
|
270
|
+
"oracle",
|
|
271
|
+
"environment",
|
|
272
|
+
"observer_results",
|
|
273
|
+
]);
|
|
274
|
+
const actual = record(row.actual_observation, `${label}.actual_observation`);
|
|
275
|
+
exact(actual, `${label}.actual_observation`, [
|
|
276
|
+
"artifact_path",
|
|
277
|
+
"artifact_sha256",
|
|
278
|
+
"locator",
|
|
279
|
+
"value_sha256",
|
|
280
|
+
"sensitivity",
|
|
281
|
+
"redaction",
|
|
282
|
+
]);
|
|
283
|
+
const actualEnvironment = record(row.actual_environment, `${label}.actual_environment`);
|
|
284
|
+
exact(actualEnvironment, `${label}.actual_environment`, [
|
|
285
|
+
"artifact_path",
|
|
286
|
+
"artifact_sha256",
|
|
287
|
+
"locator",
|
|
288
|
+
"value_sha256",
|
|
289
|
+
]);
|
|
290
|
+
const comparison = record(row.comparison, `${label}.comparison`);
|
|
291
|
+
exact(comparison, `${label}.comparison`, [
|
|
292
|
+
"artifact_path",
|
|
293
|
+
"artifact_sha256",
|
|
294
|
+
"locator",
|
|
295
|
+
"result_sha256",
|
|
296
|
+
"comparator",
|
|
297
|
+
"mode",
|
|
298
|
+
"parameters",
|
|
299
|
+
"tolerance",
|
|
300
|
+
"mask",
|
|
301
|
+
"passed",
|
|
302
|
+
]);
|
|
303
|
+
if (typeof comparison.passed !== "boolean")
|
|
304
|
+
throw invalidRecord(`${label}.comparison.passed`);
|
|
305
|
+
const oracle = record(row.oracle, `${label}.oracle`);
|
|
306
|
+
exact(oracle, `${label}.oracle`, [
|
|
307
|
+
"key",
|
|
308
|
+
"trust",
|
|
309
|
+
"identity",
|
|
310
|
+
"version",
|
|
311
|
+
"sha256",
|
|
312
|
+
"capabilities",
|
|
313
|
+
]);
|
|
314
|
+
const environment = record(row.environment, `${label}.environment`);
|
|
315
|
+
exact(environment, `${label}.environment`, ["key", "identity", "definition"]);
|
|
316
|
+
return {
|
|
317
|
+
...base,
|
|
318
|
+
capability: "semantic_fact",
|
|
319
|
+
manifest_ref: semanticFactRef(row.manifest_ref, `${label}.manifest_ref`),
|
|
320
|
+
manifest_sha256: sha(row.manifest_sha256, `${label}.manifest_sha256`),
|
|
321
|
+
outcome_ref: semanticFactRef(row.outcome_ref, `${label}.outcome_ref`),
|
|
322
|
+
target_ref: key(row.target_ref, `${label}.target_ref`),
|
|
323
|
+
fact_ref: semanticFactRef(row.fact_ref, `${label}.fact_ref`),
|
|
324
|
+
proof_ref: semanticFactRef(row.proof_ref, `${label}.proof_ref`),
|
|
325
|
+
method: semanticFactRef(row.method, `${label}.method`),
|
|
326
|
+
subject_ref: semanticFactRef(row.subject_ref, `${label}.subject_ref`),
|
|
327
|
+
condition_ref: semanticFactRef(row.condition_ref, `${label}.condition_ref`),
|
|
328
|
+
property_ref: semanticFactRef(row.property_ref, `${label}.property_ref`),
|
|
329
|
+
actual_observation: {
|
|
330
|
+
artifact_path: nonEmpty(actual.artifact_path, `${label}.actual_observation.artifact_path`),
|
|
331
|
+
artifact_sha256: sha(actual.artifact_sha256, `${label}.actual_observation.artifact_sha256`),
|
|
332
|
+
locator: decodeEvidenceLocator(actual.locator, `${label}.actual_observation.locator`),
|
|
333
|
+
value_sha256: sha(actual.value_sha256, `${label}.actual_observation.value_sha256`),
|
|
334
|
+
sensitivity: literal(actual.sensitivity, ["plain", "protected"], `${label}.actual_observation.sensitivity`),
|
|
335
|
+
redaction: nullable(actual.redaction, (value) => {
|
|
336
|
+
const entry = record(value, `${label}.actual_observation.redaction`);
|
|
337
|
+
exact(entry, `${label}.actual_observation.redaction`, [
|
|
338
|
+
"policy_ref",
|
|
339
|
+
"representation",
|
|
340
|
+
"raw_persisted",
|
|
341
|
+
]);
|
|
342
|
+
if (entry.raw_persisted !== false)
|
|
343
|
+
throw invalidRecord(`${label}.actual_observation.redaction.raw_persisted`);
|
|
344
|
+
return {
|
|
345
|
+
policy_ref: semanticFactRef(entry.policy_ref, `${label}.actual_observation.redaction.policy_ref`),
|
|
346
|
+
representation: literal(entry.representation, ["digest_only", "redacted_structured"], `${label}.actual_observation.redaction.representation`),
|
|
347
|
+
raw_persisted: false,
|
|
348
|
+
};
|
|
349
|
+
}),
|
|
350
|
+
},
|
|
351
|
+
actual_environment: {
|
|
352
|
+
artifact_path: nonEmpty(actualEnvironment.artifact_path, `${label}.actual_environment.artifact_path`),
|
|
353
|
+
artifact_sha256: sha(actualEnvironment.artifact_sha256, `${label}.actual_environment.artifact_sha256`),
|
|
354
|
+
locator: decodeEvidenceLocator(actualEnvironment.locator, `${label}.actual_environment.locator`),
|
|
355
|
+
value_sha256: sha(actualEnvironment.value_sha256, `${label}.actual_environment.value_sha256`),
|
|
356
|
+
},
|
|
357
|
+
expected: decodeSemanticLocatedValue(row.expected, `${label}.expected`),
|
|
358
|
+
comparison: {
|
|
359
|
+
artifact_path: nonEmpty(comparison.artifact_path, `${label}.comparison.artifact_path`),
|
|
360
|
+
artifact_sha256: sha(comparison.artifact_sha256, `${label}.comparison.artifact_sha256`),
|
|
361
|
+
locator: decodeEvidenceLocator(comparison.locator, `${label}.comparison.locator`),
|
|
362
|
+
result_sha256: sha(comparison.result_sha256, `${label}.comparison.result_sha256`),
|
|
363
|
+
comparator: semanticFactRef(comparison.comparator, `${label}.comparison.comparator`),
|
|
364
|
+
mode: literal(comparison.mode, ["exact", "tolerance"], `${label}.comparison.mode`),
|
|
365
|
+
parameters: decodeSemanticLocatedValue(comparison.parameters, `${label}.comparison.parameters`),
|
|
366
|
+
tolerance: nullable(comparison.tolerance, (value) => decodeSemanticLocatedValue(value, `${label}.comparison.tolerance`)),
|
|
367
|
+
mask: nullable(comparison.mask, (value) => decodeSemanticLocatedValue(value, `${label}.comparison.mask`)),
|
|
368
|
+
passed: comparison.passed,
|
|
369
|
+
},
|
|
370
|
+
verdict: literal(row.verdict, ["passed", "failed"], `${label}.verdict`),
|
|
371
|
+
oracle: {
|
|
372
|
+
key: semanticFactRef(oracle.key, `${label}.oracle.key`),
|
|
373
|
+
trust: literal(oracle.trust, ["frozen_executable", "named_external_tcb"], `${label}.oracle.trust`),
|
|
374
|
+
identity: nonEmpty(oracle.identity, `${label}.oracle.identity`),
|
|
375
|
+
version: nonEmpty(oracle.version, `${label}.oracle.version`),
|
|
376
|
+
sha256: nullableSha(oracle.sha256, `${label}.oracle.sha256`),
|
|
377
|
+
capabilities: semanticFactRefs(oracle.capabilities, `${label}.oracle.capabilities`),
|
|
378
|
+
},
|
|
379
|
+
environment: {
|
|
380
|
+
key: semanticFactRef(environment.key, `${label}.environment.key`),
|
|
381
|
+
identity: nonEmpty(environment.identity, `${label}.environment.identity`),
|
|
382
|
+
definition: decodeSemanticLocatedValue(environment.definition, `${label}.environment.definition`),
|
|
383
|
+
},
|
|
384
|
+
observer_results: array(row.observer_results, `${label}.observer_results`).map((item, index) => {
|
|
385
|
+
const itemLabel = `${label}.observer_results[${index}]`;
|
|
386
|
+
const entry = record(item, itemLabel);
|
|
387
|
+
exact(entry, itemLabel, [
|
|
388
|
+
"target_ref",
|
|
389
|
+
"artifact_path",
|
|
390
|
+
"artifact_sha256",
|
|
391
|
+
"locator",
|
|
392
|
+
"value_sha256",
|
|
393
|
+
"comparison_result_sha256",
|
|
394
|
+
"passed",
|
|
395
|
+
]);
|
|
396
|
+
if (typeof entry.passed !== "boolean")
|
|
397
|
+
throw invalidRecord(`${itemLabel}.passed`);
|
|
398
|
+
return {
|
|
399
|
+
target_ref: key(entry.target_ref, `${itemLabel}.target_ref`),
|
|
400
|
+
artifact_path: nonEmpty(entry.artifact_path, `${itemLabel}.artifact_path`),
|
|
401
|
+
artifact_sha256: sha(entry.artifact_sha256, `${itemLabel}.artifact_sha256`),
|
|
402
|
+
locator: decodeEvidenceLocator(entry.locator, `${itemLabel}.locator`),
|
|
403
|
+
value_sha256: sha(entry.value_sha256, `${itemLabel}.value_sha256`),
|
|
404
|
+
comparison_result_sha256: sha(entry.comparison_result_sha256, `${itemLabel}.comparison_result_sha256`),
|
|
405
|
+
passed: entry.passed,
|
|
406
|
+
};
|
|
407
|
+
}),
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function decodeSemanticLocatedValue(value, label) {
|
|
411
|
+
const row = record(value, label);
|
|
412
|
+
const representation = literal(row.representation, ["inline", "located", "digest_only"], `${label}.representation`);
|
|
413
|
+
exact(row, label, representation === "inline"
|
|
414
|
+
? ["representation", "locator", "sha256", "value"]
|
|
415
|
+
: ["representation", "locator", "sha256"]);
|
|
416
|
+
const locator = record(row.locator, `${label}.locator`);
|
|
417
|
+
exact(locator, `${label}.locator`, ["material_ref", "kind", "value"]);
|
|
418
|
+
return {
|
|
419
|
+
representation,
|
|
420
|
+
locator: {
|
|
421
|
+
material_ref: semanticFactRef(locator.material_ref, `${label}.locator.material_ref`),
|
|
422
|
+
kind: literal(locator.kind, [
|
|
423
|
+
"source_item",
|
|
424
|
+
"manifest_pointer",
|
|
425
|
+
"json_pointer",
|
|
426
|
+
"yaml_pointer",
|
|
427
|
+
"whole_resource",
|
|
428
|
+
"schema_pointer",
|
|
429
|
+
"api_operation",
|
|
430
|
+
"code_symbol",
|
|
431
|
+
"custom",
|
|
432
|
+
], `${label}.locator.kind`),
|
|
433
|
+
value: nonEmpty(locator.value, `${label}.locator.value`),
|
|
434
|
+
},
|
|
435
|
+
sha256: sha(row.sha256, `${label}.sha256`),
|
|
436
|
+
...(representation === "inline" ? { value: row.value } : {}),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function decodeDesignFactResult(value, label) {
|
|
440
|
+
const row = record(value, label);
|
|
441
|
+
exact(row, label, [
|
|
442
|
+
"fact_ref",
|
|
443
|
+
"subject_ref",
|
|
444
|
+
"variation_ref",
|
|
445
|
+
"property_ref",
|
|
446
|
+
"actual_observation",
|
|
447
|
+
"actual_environment",
|
|
448
|
+
"expected",
|
|
449
|
+
"comparison",
|
|
450
|
+
"verdict",
|
|
451
|
+
"oracle",
|
|
452
|
+
"environment",
|
|
453
|
+
]);
|
|
454
|
+
const actual = record(row.actual_observation, `${label}.actual_observation`);
|
|
455
|
+
exact(actual, `${label}.actual_observation`, [
|
|
456
|
+
"artifact_path",
|
|
457
|
+
"artifact_sha256",
|
|
458
|
+
"locator",
|
|
459
|
+
"value_sha256",
|
|
460
|
+
"sensitivity",
|
|
461
|
+
"redaction",
|
|
462
|
+
]);
|
|
463
|
+
const expected = decodeLocatedDigest(row.expected, `${label}.expected`);
|
|
464
|
+
const actualEnvironment = record(row.actual_environment, `${label}.actual_environment`);
|
|
465
|
+
exact(actualEnvironment, `${label}.actual_environment`, [
|
|
466
|
+
"artifact_path",
|
|
467
|
+
"artifact_sha256",
|
|
468
|
+
"locator",
|
|
469
|
+
"value_sha256",
|
|
470
|
+
]);
|
|
471
|
+
const comparison = record(row.comparison, `${label}.comparison`);
|
|
472
|
+
exact(comparison, `${label}.comparison`, [
|
|
473
|
+
"artifact_path",
|
|
474
|
+
"artifact_sha256",
|
|
475
|
+
"locator",
|
|
476
|
+
"result_sha256",
|
|
477
|
+
"comparator",
|
|
478
|
+
"mode",
|
|
479
|
+
"parameters",
|
|
480
|
+
"tolerance",
|
|
481
|
+
"mask",
|
|
482
|
+
"passed",
|
|
483
|
+
]);
|
|
484
|
+
const comparator = nonEmpty(comparison.comparator, `${label}.comparison.comparator`);
|
|
485
|
+
if (!DESIGN_RESOURCE_COMPARATORS.includes(comparator) &&
|
|
486
|
+
!/^custom\.[a-z0-9][a-z0-9._-]*$/u.test(comparator))
|
|
487
|
+
throw invalidRecord(`${label}.comparison.comparator`);
|
|
488
|
+
if (typeof comparison.passed !== "boolean")
|
|
489
|
+
throw invalidRecord(`${label}.comparison.passed`);
|
|
490
|
+
const oracle = record(row.oracle, `${label}.oracle`);
|
|
491
|
+
exact(oracle, `${label}.oracle`, [
|
|
492
|
+
"key",
|
|
493
|
+
"trust",
|
|
494
|
+
"identity",
|
|
495
|
+
"version",
|
|
496
|
+
"sha256",
|
|
497
|
+
]);
|
|
498
|
+
const environment = record(row.environment, `${label}.environment`);
|
|
499
|
+
exact(environment, `${label}.environment`, ["key", "identity", "definition"]);
|
|
500
|
+
return {
|
|
501
|
+
fact_ref: designFactRef(row.fact_ref, `${label}.fact_ref`),
|
|
502
|
+
subject_ref: designFactRef(row.subject_ref, `${label}.subject_ref`),
|
|
503
|
+
variation_ref: designFactRef(row.variation_ref, `${label}.variation_ref`),
|
|
504
|
+
property_ref: designFactRef(row.property_ref, `${label}.property_ref`),
|
|
505
|
+
actual_observation: {
|
|
506
|
+
artifact_path: nonEmpty(actual.artifact_path, `${label}.actual_observation.artifact_path`),
|
|
507
|
+
artifact_sha256: sha(actual.artifact_sha256, `${label}.actual_observation.artifact_sha256`),
|
|
508
|
+
locator: decodeEvidenceLocator(actual.locator, `${label}.actual_observation.locator`),
|
|
509
|
+
value_sha256: sha(actual.value_sha256, `${label}.actual_observation.value_sha256`),
|
|
510
|
+
sensitivity: literal(actual.sensitivity, ["plain", "protected"], `${label}.actual_observation.sensitivity`),
|
|
511
|
+
redaction: nullable(actual.redaction, (value) => {
|
|
512
|
+
const redaction = record(value, `${label}.actual_observation.redaction`);
|
|
513
|
+
exact(redaction, `${label}.actual_observation.redaction`, [
|
|
514
|
+
"policy_ref",
|
|
515
|
+
"representation",
|
|
516
|
+
"raw_persisted",
|
|
517
|
+
]);
|
|
518
|
+
if (redaction.raw_persisted !== false)
|
|
519
|
+
throw invalidRecord(`${label}.actual_observation.redaction.raw_persisted`);
|
|
520
|
+
return {
|
|
521
|
+
policy_ref: designFactRef(redaction.policy_ref, `${label}.actual_observation.redaction.policy_ref`),
|
|
522
|
+
representation: literal(redaction.representation, ["digest_only", "redacted_structured"], `${label}.actual_observation.redaction.representation`),
|
|
523
|
+
raw_persisted: false,
|
|
524
|
+
};
|
|
525
|
+
}),
|
|
526
|
+
},
|
|
527
|
+
actual_environment: {
|
|
528
|
+
artifact_path: nonEmpty(actualEnvironment.artifact_path, `${label}.actual_environment.artifact_path`),
|
|
529
|
+
artifact_sha256: sha(actualEnvironment.artifact_sha256, `${label}.actual_environment.artifact_sha256`),
|
|
530
|
+
locator: decodeEvidenceLocator(actualEnvironment.locator, `${label}.actual_environment.locator`),
|
|
531
|
+
value_sha256: sha(actualEnvironment.value_sha256, `${label}.actual_environment.value_sha256`),
|
|
532
|
+
},
|
|
533
|
+
expected,
|
|
534
|
+
comparison: {
|
|
535
|
+
artifact_path: nonEmpty(comparison.artifact_path, `${label}.comparison.artifact_path`),
|
|
536
|
+
artifact_sha256: sha(comparison.artifact_sha256, `${label}.comparison.artifact_sha256`),
|
|
537
|
+
locator: decodeEvidenceLocator(comparison.locator, `${label}.comparison.locator`),
|
|
538
|
+
result_sha256: sha(comparison.result_sha256, `${label}.comparison.result_sha256`),
|
|
539
|
+
comparator,
|
|
540
|
+
mode: literal(comparison.mode, ["exact", "tolerance"], `${label}.comparison.mode`),
|
|
541
|
+
parameters: decodeLocatedDigest(comparison.parameters, `${label}.comparison.parameters`),
|
|
542
|
+
tolerance: nullable(comparison.tolerance, (value) => decodeLocatedDigest(value, `${label}.comparison.tolerance`)),
|
|
543
|
+
mask: nullable(comparison.mask, (value) => decodeLocatedDigest(value, `${label}.comparison.mask`)),
|
|
544
|
+
passed: comparison.passed,
|
|
545
|
+
},
|
|
546
|
+
verdict: literal(row.verdict, ["passed", "failed"], `${label}.verdict`),
|
|
547
|
+
oracle: {
|
|
548
|
+
key: designFactRef(oracle.key, `${label}.oracle.key`),
|
|
549
|
+
trust: literal(oracle.trust, ["frozen_executable", "named_external_tcb"], `${label}.oracle.trust`),
|
|
550
|
+
identity: nonEmpty(oracle.identity, `${label}.oracle.identity`),
|
|
551
|
+
version: nonEmpty(oracle.version, `${label}.oracle.version`),
|
|
552
|
+
sha256: nullableSha(oracle.sha256, `${label}.oracle.sha256`),
|
|
553
|
+
},
|
|
554
|
+
environment: {
|
|
555
|
+
key: designFactRef(environment.key, `${label}.environment.key`),
|
|
556
|
+
identity: nonEmpty(environment.identity, `${label}.environment.identity`),
|
|
557
|
+
definition: decodeLocatedDigest(environment.definition, `${label}.environment.definition`),
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
export function decodeDesignFactResults(value, label) {
|
|
562
|
+
return array(value, label).map((item, index) => decodeDesignFactResult(item, `${label}[${index}]`));
|
|
563
|
+
}
|
|
564
|
+
function decodeLocatedDigest(value, label) {
|
|
565
|
+
const row = record(value, label);
|
|
566
|
+
exact(row, label, ["locator", "sha256"]);
|
|
567
|
+
const locator = record(row.locator, `${label}.locator`);
|
|
568
|
+
exact(locator, `${label}.locator`, ["resource_ref", "kind", "value"]);
|
|
569
|
+
return {
|
|
570
|
+
locator: {
|
|
571
|
+
resource_ref: designFactRef(locator.resource_ref, `${label}.locator.resource_ref`),
|
|
572
|
+
kind: literal(locator.kind, DESIGN_RESOURCE_LOCATOR_KINDS, `${label}.locator.kind`),
|
|
573
|
+
value: nonEmpty(locator.value, `${label}.locator.value`),
|
|
574
|
+
},
|
|
575
|
+
sha256: sha(row.sha256, `${label}.sha256`),
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function decodeEvidenceLocator(value, label) {
|
|
579
|
+
const row = record(value, label);
|
|
580
|
+
exact(row, label, ["kind", "value"]);
|
|
581
|
+
return {
|
|
582
|
+
kind: literal(row.kind, [
|
|
583
|
+
"json_pointer",
|
|
584
|
+
"image_region",
|
|
585
|
+
"semantic_node",
|
|
586
|
+
"trace_event",
|
|
587
|
+
"timeline_sample",
|
|
588
|
+
"asset_ref",
|
|
589
|
+
"custom",
|
|
590
|
+
], `${label}.kind`),
|
|
591
|
+
value: nonEmpty(row.value, `${label}.value`),
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function nullableSha(value, label) {
|
|
595
|
+
return value === null ? null : sha(value, label);
|
|
596
|
+
}
|
|
597
|
+
function nullable(value, decode) {
|
|
598
|
+
return value === null ? null : decode(value);
|
|
599
|
+
}
|
|
242
600
|
function invalidRecord(detail) {
|
|
243
601
|
return new Error(`check_evidence_records_invalid:${detail}`);
|
|
244
602
|
}
|
|
@@ -283,6 +641,21 @@ function designFactRefs(value, label) {
|
|
|
283
641
|
return result;
|
|
284
642
|
});
|
|
285
643
|
}
|
|
644
|
+
function designFactRef(value, label) {
|
|
645
|
+
const result = nonEmpty(value, label);
|
|
646
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/u.test(result))
|
|
647
|
+
throw invalidRecord(label);
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
650
|
+
function semanticFactRefs(value, label) {
|
|
651
|
+
return array(value, label).map((item, index) => semanticFactRef(item, `${label}[${index}]`));
|
|
652
|
+
}
|
|
653
|
+
function semanticFactRef(value, label) {
|
|
654
|
+
const result = nonEmpty(value, label);
|
|
655
|
+
if (!/^[a-z0-9][a-z0-9._:-]*$/u.test(result))
|
|
656
|
+
throw invalidRecord(label);
|
|
657
|
+
return result;
|
|
658
|
+
}
|
|
286
659
|
function sha(value, label) {
|
|
287
660
|
const result = nonEmpty(value, label);
|
|
288
661
|
if (!/^[a-f0-9]{64}$/u.test(result))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateRuntimeEvidenceRecord } from "./long-task-evidence-capability-runtime.js";
|
|
2
|
+
import { validateDistinctSemanticFactEvidence } from "./long-task-semantic-fact-evidence.js";
|
|
2
3
|
import { checkFinding } from "./long-task-evidence-findings.js";
|
|
3
4
|
export { decodeEvidenceCapabilityRecords } from "./long-task-evidence-capability-codec.js";
|
|
4
5
|
export function validateEvidenceCapabilityDeclarations(contract, report) {
|
|
@@ -31,6 +32,10 @@ function validateAssertionEvidenceCapabilityDeclarations(assertion, check, targe
|
|
|
31
32
|
if (assertion.operator === "exists" &&
|
|
32
33
|
!assertion.evidence_capabilities.includes("presence"))
|
|
33
34
|
issue(report, "exists_requires_presence_capability", label);
|
|
35
|
+
validateArtifactCapabilityDeclarations(assertion, check, label, report);
|
|
36
|
+
validateRunnerCapabilityDeclarations(assertion, check, targets, label, report);
|
|
37
|
+
}
|
|
38
|
+
function validateArtifactCapabilityDeclarations(assertion, check, label, report) {
|
|
34
39
|
if (assertion.evidence_capabilities.includes("visual_render") &&
|
|
35
40
|
!check.artifact_globs.length)
|
|
36
41
|
issue(report, "visual_render_artifact_required", label);
|
|
@@ -40,6 +45,11 @@ function validateAssertionEvidenceCapabilityDeclarations(assertion, check, targe
|
|
|
40
45
|
if (assertion.evidence_capabilities.includes("design_method") &&
|
|
41
46
|
!check.artifact_globs.length)
|
|
42
47
|
issue(report, "design_method_artifact_required", label);
|
|
48
|
+
if (assertion.evidence_capabilities.includes("semantic_fact") &&
|
|
49
|
+
!check.artifact_globs.length)
|
|
50
|
+
issue(report, "semantic_fact_artifact_required", label);
|
|
51
|
+
}
|
|
52
|
+
function validateRunnerCapabilityDeclarations(assertion, check, targets, label, report) {
|
|
43
53
|
if (assertion.evidence_capabilities.includes("interaction_trace") &&
|
|
44
54
|
!check.scenario.when.length)
|
|
45
55
|
issue(report, "interaction_trace_actions_required", label);
|
|
@@ -48,6 +58,7 @@ function validateAssertionEvidenceCapabilityDeclarations(assertion, check, targe
|
|
|
48
58
|
capability !== "interaction_trace" &&
|
|
49
59
|
capability !== "design_conformance" &&
|
|
50
60
|
capability !== "design_method" &&
|
|
61
|
+
capability !== "semantic_fact" &&
|
|
51
62
|
capability !== "target_runtime"))
|
|
52
63
|
issue(report, "playwright_evidence_capability_unsupported", label);
|
|
53
64
|
if (["boundary_invocation", "external_side_effect"].some((capability) => assertion.evidence_capabilities.includes(capability)) &&
|
|
@@ -137,6 +148,13 @@ export function evaluateEvidenceCapabilities(check, records, artifactHashes) {
|
|
|
137
148
|
complete[assertion.key] = assertionComplete;
|
|
138
149
|
}
|
|
139
150
|
validateDistinctDesignMethodArtifacts(check, runtimeRecords, artifactHashes, findings);
|
|
151
|
+
const semanticDistinctness = validateDistinctSemanticFactEvidence(runtimeRecords);
|
|
152
|
+
if (semanticDistinctness)
|
|
153
|
+
findings.push({
|
|
154
|
+
...checkFinding(check, "semantic_fact_evidence_reused", `Semantic Fact evidence is not independently attributable: ${semanticDistinctness}.`, "Emit exactly one independently located current observation and comparison result for every Fact-by-method obligation."),
|
|
155
|
+
expected: "unique_fact_proof_and_artifact_locator_identity",
|
|
156
|
+
actual: semanticDistinctness,
|
|
157
|
+
});
|
|
140
158
|
return { complete, findings };
|
|
141
159
|
}
|
|
142
160
|
function validateDistinctDesignMethodArtifacts(check, records, artifactHashes, findings) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateSemanticFactEvidence } from "./long-task-semantic-fact-evidence.js";
|
|
1
2
|
export function validateRuntimeEvidenceRecord(check, record, artifactHashes) {
|
|
2
3
|
switch (record.capability) {
|
|
3
4
|
case "interaction_trace":
|
|
@@ -29,6 +30,8 @@ export function validateRuntimeEvidenceRecord(check, record, artifactHashes) {
|
|
|
29
30
|
return validateDesignConformance(check, record, artifactHashes);
|
|
30
31
|
case "design_method":
|
|
31
32
|
return validateDesignMethod(check, record, artifactHashes);
|
|
33
|
+
case "semantic_fact":
|
|
34
|
+
return validateSemanticFactEvidence(check, record, artifactHashes);
|
|
32
35
|
case "target_runtime":
|
|
33
36
|
return validateTargetRuntime(check, record);
|
|
34
37
|
case "input_variation":
|
|
@@ -54,6 +57,7 @@ function validateDesignMethod(check, record, artifactHashes) {
|
|
|
54
57
|
artifact_path: item.path,
|
|
55
58
|
observation_artifact_path: item.observation_path,
|
|
56
59
|
fact_refs: item.fact_refs,
|
|
60
|
+
fact_expectations: item.fact_expectations,
|
|
57
61
|
},
|
|
58
62
|
]));
|
|
59
63
|
if (record.cells.length !== expected.size)
|
|
@@ -65,13 +69,87 @@ function validateDesignMethod(check, record, artifactHashes) {
|
|
|
65
69
|
return "design_method_artifact_path_mismatch";
|
|
66
70
|
if (!same([...cell.fact_refs].sort(), [...(expectedCell?.fact_refs ?? [])].sort()))
|
|
67
71
|
return "design_method_fact_refs_mismatch";
|
|
72
|
+
if (!same([...cell.fact_results.map((item) => item.fact_ref)].sort(), [...(expectedCell?.fact_refs ?? [])].sort()))
|
|
73
|
+
return "design_method_fact_results_mismatch";
|
|
68
74
|
if (!artifactHashes[cell.artifact_path])
|
|
69
75
|
return "design_method_artifact_missing";
|
|
70
76
|
if (!artifactHashes[cell.observation_artifact_path])
|
|
71
77
|
return "design_method_observation_artifact_missing";
|
|
78
|
+
const expectations = new Map((expectedCell?.fact_expectations ?? []).map((item) => [
|
|
79
|
+
item.fact_ref,
|
|
80
|
+
item,
|
|
81
|
+
]));
|
|
82
|
+
const actualIdentities = new Set();
|
|
83
|
+
const comparisonIdentities = new Set();
|
|
84
|
+
for (const result of cell.fact_results) {
|
|
85
|
+
const expectation = expectations.get(result.fact_ref);
|
|
86
|
+
if (!expectation)
|
|
87
|
+
return "design_method_fact_expectation_missing";
|
|
88
|
+
if (result.subject_ref !== expectation.subject_ref ||
|
|
89
|
+
result.variation_ref !== expectation.variation_ref ||
|
|
90
|
+
result.property_ref !== expectation.property_ref ||
|
|
91
|
+
result.actual_observation.sensitivity !==
|
|
92
|
+
expectation.observation_sensitivity)
|
|
93
|
+
return "design_method_fact_identity_mismatch";
|
|
94
|
+
if ((result.actual_observation.sensitivity === "plain" &&
|
|
95
|
+
result.actual_observation.redaction !== null) ||
|
|
96
|
+
(result.actual_observation.sensitivity === "protected" &&
|
|
97
|
+
result.actual_observation.redaction === null))
|
|
98
|
+
return "design_method_observation_protection_mismatch";
|
|
99
|
+
if (canonicalJson(result.expected) !== canonicalJson(expectation.expected))
|
|
100
|
+
return "design_method_expected_value_mismatch";
|
|
101
|
+
if (result.comparison.comparator !== expectation.comparison.comparator ||
|
|
102
|
+
result.comparison.mode !== expectation.comparison.mode ||
|
|
103
|
+
canonicalJson(result.comparison.parameters) !==
|
|
104
|
+
canonicalJson(expectation.comparison.parameters) ||
|
|
105
|
+
canonicalJson(result.comparison.tolerance) !==
|
|
106
|
+
canonicalJson(expectation.comparison.tolerance) ||
|
|
107
|
+
canonicalJson(result.comparison.mask) !==
|
|
108
|
+
canonicalJson(expectation.comparison.mask))
|
|
109
|
+
return "design_method_comparison_authority_mismatch";
|
|
110
|
+
if (canonicalJson(result.oracle) !== canonicalJson(expectation.oracle) ||
|
|
111
|
+
canonicalJson(result.environment) !==
|
|
112
|
+
canonicalJson(expectation.environment))
|
|
113
|
+
return "design_method_oracle_environment_mismatch";
|
|
114
|
+
if (result.actual_observation.artifact_path !==
|
|
115
|
+
cell.observation_artifact_path ||
|
|
116
|
+
result.actual_observation.artifact_sha256 !==
|
|
117
|
+
artifactHashes[cell.observation_artifact_path])
|
|
118
|
+
return "design_method_actual_observation_mismatch";
|
|
119
|
+
if (result.actual_environment.artifact_path !==
|
|
120
|
+
cell.observation_artifact_path ||
|
|
121
|
+
result.actual_environment.artifact_sha256 !==
|
|
122
|
+
artifactHashes[cell.observation_artifact_path] ||
|
|
123
|
+
result.actual_environment.value_sha256 !==
|
|
124
|
+
expectation.environment.definition.sha256)
|
|
125
|
+
return "design_method_actual_environment_mismatch";
|
|
126
|
+
if (result.comparison.artifact_path !== cell.artifact_path ||
|
|
127
|
+
result.comparison.artifact_sha256 !== artifactHashes[cell.artifact_path])
|
|
128
|
+
return "design_method_comparison_artifact_mismatch";
|
|
129
|
+
const actualIdentity = `${result.actual_observation.artifact_path}\0${canonicalJson(result.actual_observation.locator)}`;
|
|
130
|
+
if (actualIdentities.has(actualIdentity))
|
|
131
|
+
return "design_method_actual_observation_reused";
|
|
132
|
+
actualIdentities.add(actualIdentity);
|
|
133
|
+
const comparisonIdentity = `${result.comparison.artifact_path}\0${canonicalJson(result.comparison.locator)}`;
|
|
134
|
+
if (comparisonIdentities.has(comparisonIdentity))
|
|
135
|
+
return "design_method_comparison_result_reused";
|
|
136
|
+
comparisonIdentities.add(comparisonIdentity);
|
|
137
|
+
if (result.verdict !== "passed" || result.comparison.passed !== true)
|
|
138
|
+
return "design_method_fact_failed";
|
|
139
|
+
}
|
|
72
140
|
}
|
|
73
141
|
return null;
|
|
74
142
|
}
|
|
143
|
+
function canonicalJson(value) {
|
|
144
|
+
if (Array.isArray(value))
|
|
145
|
+
return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
|
|
146
|
+
if (value && typeof value === "object")
|
|
147
|
+
return `{${Object.entries(value)
|
|
148
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
149
|
+
.map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`)
|
|
150
|
+
.join(",")}}`;
|
|
151
|
+
return JSON.stringify(value);
|
|
152
|
+
}
|
|
75
153
|
function validateDesignConformance(check, record, artifactHashes) {
|
|
76
154
|
const target = (check.design_conformance_targets ?? []).find((item) => item.key === record.design_target_ref &&
|
|
77
155
|
designTargetUsesAssertion(item, record.assertion_key));
|