project-tiny-context-harness 0.8.4 → 0.8.6
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 +394 -363
- package/assets/README.md +570 -514
- package/assets/README.zh-CN.md +331 -300
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +45 -25
- package/assets/context_templates/architecture.md +26 -25
- package/assets/context_templates/area.md +32 -31
- package/assets/context_templates/context.toml +30 -24
- 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 +31 -30
- 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 +155 -122
- 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-default-footprint.js +2 -0
- package/dist/lib/context-manifest.js +6 -0
- 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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { designFactComparatorSupportsMethod, designFactEvidenceSupportsMethod, designFactMethodIsCompatible, designFactOracleSupportsMethod, } from "./design-resource-fact-policy.js";
|
|
2
|
+
import { invalidDesignResourceHandoff, requireKnownDesignResourceRef, requireUniqueDesignResourceValues, } from "./design-resource-handoff-validation-primitives.js";
|
|
3
|
+
export function validateDesignResourceProofObligations(handoff, resources, targets, evidence) {
|
|
4
|
+
const facts = new Map(handoff.facts.map((item) => [item.key, item]));
|
|
5
|
+
const oracles = new Map(handoff.oracles.map((item) => [item.key, item]));
|
|
6
|
+
const environments = new Map(handoff.environments.map((item) => [item.key, item]));
|
|
7
|
+
const proofByFact = new Map();
|
|
8
|
+
const factMethodPairs = [];
|
|
9
|
+
for (const proof of handoff.proof_obligations) {
|
|
10
|
+
validateProofReferences(proof, facts, oracles, environments);
|
|
11
|
+
validateProofMethod(proof, facts.get(proof.fact_ref), oracles.get(proof.oracle_ref), evidence);
|
|
12
|
+
validateProofResources(proof, facts.get(proof.fact_ref), environments, resources, targets);
|
|
13
|
+
validateProofComparison(proof);
|
|
14
|
+
proofByFact.set(proof.fact_ref, (proofByFact.get(proof.fact_ref) ?? 0) + 1);
|
|
15
|
+
factMethodPairs.push(`${proof.fact_ref}\0${proof.method}`);
|
|
16
|
+
}
|
|
17
|
+
requireUniqueDesignResourceValues(factMethodPairs, "fact_verification_method_obligation_duplicate");
|
|
18
|
+
for (const fact of handoff.facts)
|
|
19
|
+
if (!proofByFact.has(fact.key))
|
|
20
|
+
invalidDesignResourceHandoff("fact_verification_method_required", fact.key);
|
|
21
|
+
for (const environment of handoff.environments)
|
|
22
|
+
requireKnownDesignResourceRef(resources, environment.definition.locator.resource_ref, "environment_resource");
|
|
23
|
+
}
|
|
24
|
+
function validateProofReferences(proof, facts, oracles, environments) {
|
|
25
|
+
requireKnownDesignResourceRef(facts, proof.fact_ref, "proof_fact");
|
|
26
|
+
requireKnownDesignResourceRef(oracles, proof.oracle_ref, "proof_oracle");
|
|
27
|
+
requireKnownDesignResourceRef(environments, proof.environment_ref, "proof_environment");
|
|
28
|
+
}
|
|
29
|
+
function validateProofMethod(proof, fact, oracle, evidence) {
|
|
30
|
+
if (!designFactMethodIsCompatible(fact.dimension, proof.method))
|
|
31
|
+
invalidDesignResourceHandoff("proof_verification_method_incompatible", `${proof.key}:${fact.dimension}:${proof.method}`);
|
|
32
|
+
if (!fact.evidence_refs.some((ref) => designFactEvidenceSupportsMethod(proof.method, evidence.get(ref).kind)))
|
|
33
|
+
invalidDesignResourceHandoff("proof_method_evidence_missing", `${proof.key}:${proof.fact_ref}:${proof.method}`);
|
|
34
|
+
if (!designFactComparatorSupportsMethod(proof.method, proof.comparison.comparator))
|
|
35
|
+
invalidDesignResourceHandoff("proof_comparator_method_incompatible", `${proof.key}:${proof.method}:${proof.comparison.comparator}`);
|
|
36
|
+
if (!designFactOracleSupportsMethod(proof.method, oracle.capability_refs))
|
|
37
|
+
invalidDesignResourceHandoff("proof_oracle_capability_missing", `${proof.key}:${proof.oracle_ref}:${proof.method}`);
|
|
38
|
+
}
|
|
39
|
+
function validateProofResources(proof, fact, environments, resources, targets) {
|
|
40
|
+
const target = targets.get(fact.target_ref);
|
|
41
|
+
const environmentResourceRef = environments.get(proof.environment_ref)
|
|
42
|
+
.definition.locator.resource_ref;
|
|
43
|
+
if (!target.resource_refs.includes(environmentResourceRef))
|
|
44
|
+
invalidDesignResourceHandoff("proof_environment_outside_target", `${proof.key}:${proof.environment_ref}:${environmentResourceRef}`);
|
|
45
|
+
for (const located of [
|
|
46
|
+
proof.comparison.parameters,
|
|
47
|
+
proof.comparison.tolerance,
|
|
48
|
+
proof.comparison.mask,
|
|
49
|
+
])
|
|
50
|
+
if (located) {
|
|
51
|
+
requireKnownDesignResourceRef(resources, located.locator.resource_ref, "proof_resource");
|
|
52
|
+
if (!target.resource_refs.includes(located.locator.resource_ref))
|
|
53
|
+
invalidDesignResourceHandoff("proof_resource_outside_target", `${proof.key}:${located.locator.resource_ref}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function validateProofComparison(proof) {
|
|
57
|
+
if (proof.comparison.mode === "exact" &&
|
|
58
|
+
(proof.comparison.tolerance !== null || proof.comparison.mask !== null))
|
|
59
|
+
invalidDesignResourceHandoff("proof_exact_tolerance_forbidden", proof.key);
|
|
60
|
+
if (proof.comparison.mode === "tolerance" &&
|
|
61
|
+
proof.comparison.tolerance === null)
|
|
62
|
+
invalidDesignResourceHandoff("proof_tolerance_required", proof.key);
|
|
63
|
+
if (proof.comparison.mask !== null &&
|
|
64
|
+
proof.comparison.comparator !== "pixel_diff" &&
|
|
65
|
+
!proof.comparison.comparator.startsWith("custom."))
|
|
66
|
+
invalidDesignResourceHandoff("proof_mask_comparator_incompatible", `${proof.key}:${proof.comparison.comparator}`);
|
|
67
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DesignResourceHandoffV1 } from "./design-resource-handoff-types.js";
|
|
2
|
+
export declare function validateDesignResourceExactTargetFacts(handoff: DesignResourceHandoffV1): void;
|
|
3
|
+
export declare function validateDesignResourceResourceFactClosure(handoff: DesignResourceHandoffV1, resources: Map<string, DesignResourceHandoffV1["resources"][number]>, evidence: Map<string, DesignResourceHandoffV1["evidence"][number]>): void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EXACT_TARGET_FULL_TARGET_METHODS } from "./design-resource-fact-policy.js";
|
|
2
|
+
import { invalidDesignResourceHandoff, requireKnownDesignResourceRef, requireUniqueDesignResourceValues, } from "./design-resource-handoff-validation-primitives.js";
|
|
3
|
+
export function validateDesignResourceExactTargetFacts(handoff) {
|
|
4
|
+
const proofsByFact = new Map();
|
|
5
|
+
for (const proof of handoff.proof_obligations) {
|
|
6
|
+
const methods = proofsByFact.get(proof.fact_ref) ?? [];
|
|
7
|
+
methods.push(proof.method);
|
|
8
|
+
proofsByFact.set(proof.fact_ref, methods);
|
|
9
|
+
}
|
|
10
|
+
for (const target of handoff.targets) {
|
|
11
|
+
if (target.interpretation !== "exact_target")
|
|
12
|
+
continue;
|
|
13
|
+
for (const conditionRef of target.condition_refs)
|
|
14
|
+
for (const method of EXACT_TARGET_FULL_TARGET_METHODS)
|
|
15
|
+
if (!hasExactTargetFact(handoff, target.key, conditionRef, method, proofsByFact))
|
|
16
|
+
invalidDesignResourceHandoff("exact_target_full_target_fact_missing", `${target.key}:${conditionRef}:${method}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function hasExactTargetFact(handoff, targetRef, conditionRef, method, proofsByFact) {
|
|
20
|
+
return handoff.facts.some((fact) => fact.target_ref === targetRef &&
|
|
21
|
+
fact.condition_ref === conditionRef &&
|
|
22
|
+
fact.observation_scope === "full_target" &&
|
|
23
|
+
(proofsByFact.get(fact.key) ?? []).includes(method));
|
|
24
|
+
}
|
|
25
|
+
export function validateDesignResourceResourceFactClosure(handoff, resources, evidence) {
|
|
26
|
+
const lineageNodes = new Map(handoff.lineage_nodes.map((item) => [item.key, item]));
|
|
27
|
+
const proofsByFact = new Map(handoff.facts.map((fact) => [
|
|
28
|
+
fact.key,
|
|
29
|
+
handoff.proof_obligations.filter((proof) => proof.fact_ref === fact.key),
|
|
30
|
+
]));
|
|
31
|
+
const environments = new Map(handoff.environments.map((environment) => [environment.key, environment]));
|
|
32
|
+
const closuresByResource = new Map();
|
|
33
|
+
for (const closure of handoff.resource_fact_closure) {
|
|
34
|
+
validateResourceClosure(closure, handoff, resources, evidence, lineageNodes, proofsByFact, environments);
|
|
35
|
+
if (closuresByResource.has(closure.resource_ref))
|
|
36
|
+
invalidDesignResourceHandoff("resource_fact_closure_duplicate", closure.resource_ref);
|
|
37
|
+
closuresByResource.set(closure.resource_ref, closure.key);
|
|
38
|
+
}
|
|
39
|
+
for (const resource of handoff.resources)
|
|
40
|
+
if (!closuresByResource.has(resource.key))
|
|
41
|
+
invalidDesignResourceHandoff("resource_fact_closure_missing", resource.key);
|
|
42
|
+
}
|
|
43
|
+
function validateResourceClosure(closure, handoff, resources, evidence, lineageNodes, proofsByFact, environments) {
|
|
44
|
+
requireKnownDesignResourceRef(resources, closure.resource_ref, "resource_fact_closure_resource");
|
|
45
|
+
requireUniqueDesignResourceValues(closure.fact_refs, `resource_fact_closure_fact_ref_duplicate:${closure.key}`);
|
|
46
|
+
const expected = handoff.facts
|
|
47
|
+
.filter((fact) => factUsesResource(fact, closure.resource_ref, proofsByFact.get(fact.key) ?? [], environments, lineageNodes, evidence))
|
|
48
|
+
.map((fact) => fact.key);
|
|
49
|
+
for (const factRef of closure.fact_refs)
|
|
50
|
+
if (!handoff.facts.some((fact) => fact.key === factRef))
|
|
51
|
+
invalidDesignResourceHandoff("resource_fact_closure_fact_unknown", `${closure.key}:${factRef}`);
|
|
52
|
+
assertSameSet(closure.fact_refs, expected, "resource_fact_closure_mismatch", closure.resource_ref);
|
|
53
|
+
validateClosureDisposition(closure, resources.get(closure.resource_ref));
|
|
54
|
+
}
|
|
55
|
+
function factUsesResource(fact, resourceRef, proofs, environments, lineageNodes, evidence) {
|
|
56
|
+
const proofResources = proofs.flatMap((proof) => [
|
|
57
|
+
proof.comparison.parameters.locator.resource_ref,
|
|
58
|
+
proof.comparison.tolerance?.locator.resource_ref,
|
|
59
|
+
proof.comparison.mask?.locator.resource_ref,
|
|
60
|
+
environments.get(proof.environment_ref)?.definition.locator.resource_ref,
|
|
61
|
+
]);
|
|
62
|
+
const lineageResources = [
|
|
63
|
+
...fact.lineage.token_chain_refs,
|
|
64
|
+
...fact.lineage.override_chain_refs,
|
|
65
|
+
].map((ref) => lineageNodes.get(ref)?.value.locator.resource_ref);
|
|
66
|
+
return (fact.value.locator.resource_ref === resourceRef ||
|
|
67
|
+
fact.lineage.resolved_value.locator.resource_ref === resourceRef ||
|
|
68
|
+
lineageResources.includes(resourceRef) ||
|
|
69
|
+
proofResources.includes(resourceRef) ||
|
|
70
|
+
fact.evidence_refs.some((evidenceRef) => evidence.get(evidenceRef)?.resource_ref === resourceRef));
|
|
71
|
+
}
|
|
72
|
+
function validateClosureDisposition(closure, resource) {
|
|
73
|
+
if (closure.disposition === "material_with_facts" &&
|
|
74
|
+
closure.fact_refs.length === 0)
|
|
75
|
+
invalidDesignResourceHandoff("resource_fact_closure_facts_required", closure.key);
|
|
76
|
+
if (closure.disposition === "supporting_only" && closure.fact_refs.length > 0)
|
|
77
|
+
invalidDesignResourceHandoff("supporting_only_resource_fact_forbidden", closure.key);
|
|
78
|
+
if (resource.role !== "supporting" &&
|
|
79
|
+
closure.disposition !== "material_with_facts")
|
|
80
|
+
invalidDesignResourceHandoff("target_resource_fact_closure_required", `${closure.key}:${resource.role}`);
|
|
81
|
+
}
|
|
82
|
+
function assertSameSet(actual, expected, code, detail) {
|
|
83
|
+
const left = [...new Set(actual)].sort();
|
|
84
|
+
const right = [...new Set(expected)].sort();
|
|
85
|
+
if (left.length !== right.length ||
|
|
86
|
+
left.some((item, index) => item !== right[index]))
|
|
87
|
+
invalidDesignResourceHandoff(code, `${detail}:${left.join(",")}:${right.join(",")}`);
|
|
88
|
+
}
|
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import { invalidDesignResourceHandoff, requireKnownDesignResourceRef, requireNonemptyDesignResourceValues, requireUniqueDesignResourceValues, } from "./design-resource-handoff-validation-primitives.js";
|
|
2
2
|
export function validateDesignResourceScope(handoff) {
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const scopedSurfaceKeys = new Set(handoff.scope.surface_keys);
|
|
4
|
+
const surfaceSubjects = handoff.subjects.filter((subject) => subject.kind === "surface");
|
|
5
|
+
const surfaceStableKeys = new Set(surfaceSubjects.flatMap((subject) => subject.stable_keys));
|
|
6
6
|
for (const surfaceKey of handoff.scope.surface_keys)
|
|
7
7
|
if (!surfaceStableKeys.has(surfaceKey))
|
|
8
8
|
invalidDesignResourceHandoff("scope_surface_subject_missing", surfaceKey);
|
|
9
|
+
for (const subject of surfaceSubjects)
|
|
10
|
+
if (!subject.stable_keys.some((key) => scopedSurfaceKeys.has(key)))
|
|
11
|
+
invalidDesignResourceHandoff("scope_surface_subject_outside_scope", subject.key);
|
|
9
12
|
}
|
|
10
13
|
export function validateDesignResourceConditions(handoff) {
|
|
14
|
+
const viewportProfiles = new Map();
|
|
15
|
+
const densityProfiles = new Map();
|
|
16
|
+
const safeAreaProfiles = new Map();
|
|
17
|
+
const textScaleProfiles = new Map();
|
|
11
18
|
for (const condition of handoff.conditions) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
requireNonemptyDesignResourceValues(values, `condition_${name}_required:${condition.key}`);
|
|
19
|
-
requireUniqueDesignResourceValues(values, `condition_${name}_duplicate:${condition.key}`);
|
|
20
|
-
if (values.length !== 1)
|
|
21
|
-
invalidDesignResourceHandoff(`condition_${name}_must_be_atomic`, condition.key);
|
|
22
|
-
}
|
|
19
|
+
requireConsistentConditionProfile(viewportProfiles, condition.viewport.key, `${condition.viewport.width}\0${condition.viewport.height}\0${condition.viewport.unit}`, "viewport", condition.key);
|
|
20
|
+
requireConsistentConditionProfile(densityProfiles, condition.density.key, String(condition.density.pixel_ratio), "density", condition.key);
|
|
21
|
+
requireConsistentConditionProfile(safeAreaProfiles, condition.safe_area.key, `${condition.safe_area.top}\0${condition.safe_area.right}\0${condition.safe_area.bottom}\0${condition.safe_area.left}\0${condition.safe_area.unit}`, "safe_area", condition.key);
|
|
22
|
+
requireConsistentConditionProfile(textScaleProfiles, condition.text_scale.key, String(condition.text_scale.multiplier), "text_scale", condition.key);
|
|
23
|
+
requireUniqueDesignResourceValues(condition.custom_axes.map((item) => item.axis_ref), `condition_custom_axis_duplicate:${condition.key}`);
|
|
24
|
+
requireUniqueDesignResourceValues(condition.custom_axes.map((item) => `${item.axis_ref}\0${item.value_ref}`), `condition_custom_axis_value_duplicate:${condition.key}`);
|
|
23
25
|
}
|
|
24
26
|
}
|
|
27
|
+
function requireConsistentConditionProfile(profiles, key, definition, profileKind, conditionKey) {
|
|
28
|
+
const existing = profiles.get(key);
|
|
29
|
+
if (existing !== undefined && existing !== definition)
|
|
30
|
+
invalidDesignResourceHandoff(`condition_${profileKind}_profile_conflict`, `${key}:${conditionKey}`);
|
|
31
|
+
profiles.set(key, definition);
|
|
32
|
+
}
|
|
25
33
|
export function validateDesignResourceSubjects(handoff, targets) {
|
|
26
34
|
const stableKeys = new Set();
|
|
35
|
+
const subjects = new Map(handoff.subjects.map((subject) => [subject.key, subject]));
|
|
27
36
|
for (const subject of handoff.subjects) {
|
|
28
37
|
requireNonemptyDesignResourceValues(subject.stable_keys, `subject_stable_keys_required:${subject.key}`);
|
|
29
38
|
requireUniqueDesignResourceValues(subject.stable_keys, `subject_stable_key_duplicate:${subject.key}`);
|
|
@@ -36,6 +45,23 @@ export function validateDesignResourceSubjects(handoff, targets) {
|
|
|
36
45
|
invalidDesignResourceHandoff("subject_stable_key_ambiguous", stableKey);
|
|
37
46
|
stableKeys.add(stableKey);
|
|
38
47
|
}
|
|
48
|
+
for (const ref of [
|
|
49
|
+
subject.parent_ref,
|
|
50
|
+
subject.instance_of_ref,
|
|
51
|
+
subject.override_of_ref,
|
|
52
|
+
subject.family_ref,
|
|
53
|
+
subject.portal_host_ref,
|
|
54
|
+
])
|
|
55
|
+
if (ref !== null && !subjects.has(ref))
|
|
56
|
+
invalidDesignResourceHandoff("subject_hierarchy_ref_unknown", `${subject.key}:${ref}`);
|
|
57
|
+
requireUniqueDesignResourceValues(subject.census_refs, `subject_census_ref_duplicate:${subject.key}`);
|
|
58
|
+
requireUniqueDesignResourceValues(subject.relation_endpoints.map((item) => item.role), `subject_relation_endpoint_role_duplicate:${subject.key}`);
|
|
59
|
+
if (subject.presence === "always" && subject.presence_rule_ref !== null)
|
|
60
|
+
invalidDesignResourceHandoff("subject_always_presence_rule_forbidden", subject.key);
|
|
61
|
+
if (subject.presence !== "always" && subject.presence_rule_ref === null)
|
|
62
|
+
invalidDesignResourceHandoff("subject_dynamic_presence_rule_required", subject.key);
|
|
63
|
+
if (subject.presence === "virtualized" && subject.population_ref === null)
|
|
64
|
+
invalidDesignResourceHandoff("subject_virtualized_population_required", subject.key);
|
|
39
65
|
}
|
|
40
66
|
}
|
|
41
67
|
export function validateDesignResourceTargets(handoff, resources, conditions) {
|
|
@@ -60,6 +86,9 @@ function validateTargetSourceProfile(target, resources) {
|
|
|
60
86
|
requireUniqueDesignResourceValues(profile.dependency_resource_refs, `source_profile_dependency_resource_ref_duplicate:${target.key}`);
|
|
61
87
|
for (const ref of profile.dependency_resource_refs)
|
|
62
88
|
requireKnownDesignResourceRef(resources, ref, "source_profile_dependency_resource");
|
|
89
|
+
requireKnownDesignResourceRef(resources, profile.fact_manifest_resource_ref, "source_profile_fact_manifest_resource");
|
|
90
|
+
if (!profile.dependency_resource_refs.includes(profile.fact_manifest_resource_ref))
|
|
91
|
+
invalidDesignResourceHandoff("source_profile_fact_manifest_dependency_missing", target.key);
|
|
63
92
|
if (profile.dependency_resource_refs.includes(profile.entry_resource_ref))
|
|
64
93
|
invalidDesignResourceHandoff("source_profile_entry_repeated_as_dependency", target.key);
|
|
65
94
|
const declared = [
|
|
@@ -2,6 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parseDesignResourceHandoffMarkdown } from "./design-resource-handoff-parser.js";
|
|
4
4
|
import { validateDesignResourceFiles } from "./design-resource-handoff-file-validation.js";
|
|
5
|
+
import { loadAndValidateDesignResourceFactManifests } from "./design-resource-fact-manifest-validation.js";
|
|
5
6
|
import { validateDesignResourceFacts } from "./design-resource-handoff-validation-facts.js";
|
|
6
7
|
import { validateDesignResourceBlockers, validateDesignResourceCoverage, validateDesignResourceReachability, } from "./design-resource-handoff-validation-coverage.js";
|
|
7
8
|
import { indexDesignResourceItems, invalidDesignResourceHandoff, requireNonemptyDesignResourceValues, requireUniqueDesignResourceObjects, requireUniqueDesignResourceValues, } from "./design-resource-handoff-validation-primitives.js";
|
|
@@ -14,6 +15,7 @@ export async function preflightDesignResourceHandoff(repository, handoffPath) {
|
|
|
14
15
|
validateDesignResourceHandoffSemantics(parsed);
|
|
15
16
|
const resourceHashes = await validateResourceIntegrity(repository, parsed);
|
|
16
17
|
await validateDesignResourceFiles(repository, parsed);
|
|
18
|
+
const manifests = await loadAndValidateDesignResourceFactManifests(repository, parsed);
|
|
17
19
|
const handoff = parsed.handoff;
|
|
18
20
|
return {
|
|
19
21
|
schema_version: "design-resource-handoff-preflight-v1",
|
|
@@ -22,11 +24,21 @@ export async function preflightDesignResourceHandoff(repository, handoffPath) {
|
|
|
22
24
|
resource_hashes: resourceHashes,
|
|
23
25
|
counts: {
|
|
24
26
|
resources: handoff.resources.length,
|
|
27
|
+
manifests: manifests.size,
|
|
28
|
+
axis_dispositions: handoff.axis_dispositions.length,
|
|
25
29
|
conditions: handoff.conditions.length,
|
|
26
30
|
subjects: handoff.subjects.length,
|
|
31
|
+
variations: handoff.variations.length,
|
|
32
|
+
properties: handoff.properties.length,
|
|
33
|
+
lineage_nodes: handoff.lineage_nodes.length,
|
|
27
34
|
targets: handoff.targets.length,
|
|
28
35
|
evidence: handoff.evidence.length,
|
|
36
|
+
fact_cells: handoff.fact_cells.length,
|
|
29
37
|
facts: handoff.facts.length,
|
|
38
|
+
proof_obligations: handoff.proof_obligations.length,
|
|
39
|
+
oracles: handoff.oracles.length,
|
|
40
|
+
environments: handoff.environments.length,
|
|
41
|
+
asset_bindings: handoff.asset_bindings.length,
|
|
30
42
|
resource_fact_closure: handoff.resource_fact_closure.length,
|
|
31
43
|
coverage: handoff.coverage.length,
|
|
32
44
|
acceptance_blockers: handoff.acceptance_blockers.length,
|
|
@@ -37,21 +49,41 @@ export function validateDesignResourceHandoffSemantics(parsed) {
|
|
|
37
49
|
const { handoff } = parsed;
|
|
38
50
|
requireNonemptyDesignResourceValues(handoff.scope.surface_keys, "scope_surface_keys_required");
|
|
39
51
|
requireNonemptyDesignResourceValues(handoff.resources, "resources_required");
|
|
52
|
+
requireNonemptyDesignResourceValues(handoff.axis_dispositions, "axis_dispositions_required");
|
|
40
53
|
requireNonemptyDesignResourceValues(handoff.conditions, "conditions_required");
|
|
41
54
|
requireNonemptyDesignResourceValues(handoff.subjects, "subjects_required");
|
|
55
|
+
requireNonemptyDesignResourceValues(handoff.variation_axis_dispositions, "variation_axis_dispositions_required");
|
|
56
|
+
requireNonemptyDesignResourceValues(handoff.variations, "variations_required");
|
|
57
|
+
requireNonemptyDesignResourceValues(handoff.properties, "properties_required");
|
|
42
58
|
requireNonemptyDesignResourceValues(handoff.targets, "targets_required");
|
|
43
59
|
requireNonemptyDesignResourceValues(handoff.evidence, "evidence_required");
|
|
60
|
+
requireNonemptyDesignResourceValues(handoff.fact_cells, "fact_cells_required");
|
|
44
61
|
requireNonemptyDesignResourceValues(handoff.facts, "facts_required");
|
|
62
|
+
requireNonemptyDesignResourceValues(handoff.proof_obligations, "proof_obligations_required");
|
|
63
|
+
requireNonemptyDesignResourceValues(handoff.oracles, "oracles_required");
|
|
64
|
+
requireNonemptyDesignResourceValues(handoff.environments, "environments_required");
|
|
45
65
|
requireNonemptyDesignResourceValues(handoff.resource_fact_closure, "resource_fact_closure_required");
|
|
46
66
|
requireNonemptyDesignResourceValues(handoff.coverage, "coverage_required");
|
|
47
67
|
requireUniqueDesignResourceValues(handoff.scope.surface_keys, "scope_surface_key_duplicate");
|
|
48
68
|
requireUniqueDesignResourceObjects(handoff.resources, "resource_key_duplicate");
|
|
49
69
|
requireUniqueDesignResourceValues(handoff.resources.map((item) => item.path), "resource_path_duplicate");
|
|
70
|
+
requireUniqueDesignResourceObjects(handoff.axis_dispositions, "axis_disposition_key_duplicate");
|
|
71
|
+
requireUniqueDesignResourceObjects(handoff.condition_exclusions, "condition_exclusion_key_duplicate");
|
|
50
72
|
requireUniqueDesignResourceObjects(handoff.conditions, "condition_key_duplicate");
|
|
51
73
|
requireUniqueDesignResourceObjects(handoff.subjects, "subject_key_duplicate");
|
|
74
|
+
requireUniqueDesignResourceObjects(handoff.variation_axis_dispositions, "variation_axis_disposition_key_duplicate");
|
|
75
|
+
requireUniqueDesignResourceObjects(handoff.variation_exclusions, "variation_exclusion_key_duplicate");
|
|
76
|
+
requireUniqueDesignResourceObjects(handoff.variations, "variation_key_duplicate");
|
|
77
|
+
requireUniqueDesignResourceObjects(handoff.properties, "property_key_duplicate");
|
|
78
|
+
requireUniqueDesignResourceObjects(handoff.lineage_nodes, "lineage_node_key_duplicate");
|
|
52
79
|
requireUniqueDesignResourceObjects(handoff.targets, "target_key_duplicate");
|
|
53
80
|
requireUniqueDesignResourceObjects(handoff.evidence, "evidence_key_duplicate");
|
|
54
81
|
requireUniqueDesignResourceObjects(handoff.facts, "fact_key_duplicate");
|
|
82
|
+
requireUniqueDesignResourceObjects(handoff.fact_cells, "fact_cell_key_duplicate");
|
|
83
|
+
requireUniqueDesignResourceObjects(handoff.proof_obligations, "proof_obligation_key_duplicate");
|
|
84
|
+
requireUniqueDesignResourceObjects(handoff.oracles, "oracle_key_duplicate");
|
|
85
|
+
requireUniqueDesignResourceObjects(handoff.environments, "environment_key_duplicate");
|
|
86
|
+
requireUniqueDesignResourceObjects(handoff.asset_bindings, "asset_binding_key_duplicate");
|
|
55
87
|
requireUniqueDesignResourceObjects(handoff.resource_fact_closure, "resource_fact_closure_key_duplicate");
|
|
56
88
|
requireUniqueDesignResourceObjects(handoff.coverage, "coverage_key_duplicate");
|
|
57
89
|
requireUniqueDesignResourceObjects(handoff.acceptance_blockers, "acceptance_blocker_key_duplicate");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ParsedDesignResourceHandoffV1 } from "./design-resource-handoff-types.js";
|
|
2
2
|
import { type DesignResource } from "./design-resource-handoff-file-primitives.js";
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function validateDesignResourceImplementationDependencyClosure(target: ParsedDesignResourceHandoffV1["handoff"]["targets"][number], resources: Map<string, DesignResource>, contents: Map<string, Buffer>): void;
|
|
4
|
+
export declare const validateDesignResourceWebDependencyClosure: typeof validateDesignResourceImplementationDependencyClosure;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { htmlAttributes, isTextResource, } from "./design-resource-handoff-file-primitives.js";
|
|
3
3
|
import { invalidDesignResourceHandoff } from "./design-resource-handoff-validation-primitives.js";
|
|
4
|
-
export function
|
|
4
|
+
export function validateDesignResourceImplementationDependencyClosure(target, resources, contents) {
|
|
5
5
|
const declaredPaths = new Set(target.resource_refs.map((ref) => resources.get(ref).path));
|
|
6
6
|
for (const resourceRef of target.resource_refs) {
|
|
7
7
|
const resource = resources.get(resourceRef);
|
|
@@ -10,17 +10,23 @@ export function validateDesignResourceWebDependencyClosure(target, resources, co
|
|
|
10
10
|
const content = contents.get(resourceRef).toString("utf8");
|
|
11
11
|
for (const reference of localDependencyReferences(content, resource.media_type)) {
|
|
12
12
|
const resolved = resolveResourceReference(resource.path, reference);
|
|
13
|
-
|
|
13
|
+
const declared = resolveDeclaredPath(declaredPaths, resolved);
|
|
14
|
+
if (declared === null)
|
|
14
15
|
invalidDesignResourceHandoff("implementation_dependency_undeclared", `${target.key}:${resource.path}:${reference}:${resolved}`);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
function localDependencyReferences(content, mediaType) {
|
|
19
20
|
const values = new Set();
|
|
20
|
-
|
|
21
|
+
const markupMediaTypes = [
|
|
22
|
+
"text/html",
|
|
23
|
+
"application/xhtml+xml",
|
|
24
|
+
"image/svg+xml",
|
|
25
|
+
];
|
|
26
|
+
if (markupMediaTypes.includes(mediaType)) {
|
|
21
27
|
for (const tag of content.matchAll(/<(script|img|source|video|audio|track|iframe|embed|input|link|object|use|image)\b([^<>]*)>/giu)) {
|
|
22
28
|
const attributes = htmlAttributes(tag[2]);
|
|
23
|
-
for (const name of ["src", "href", "poster"])
|
|
29
|
+
for (const name of ["src", "href", "xlink:href", "poster"])
|
|
24
30
|
addLocalReference(values, attributes.get(name));
|
|
25
31
|
if (tag[1].toLowerCase() === "object")
|
|
26
32
|
addLocalReference(values, attributes.get("data"));
|
|
@@ -28,8 +34,7 @@ function localDependencyReferences(content, mediaType) {
|
|
|
28
34
|
addLocalReference(values, candidate.trim().split(/\s+/u)[0]);
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
|
-
if (mediaType === "text/css" ||
|
|
32
|
-
["text/html", "application/xhtml+xml"].includes(mediaType))
|
|
37
|
+
if (mediaType === "text/css" || markupMediaTypes.includes(mediaType))
|
|
33
38
|
for (const match of content.matchAll(/(?:url\(\s*["']?([^"')\s]+)|@import\s+(?:url\(\s*)?["']([^"']+))/giu))
|
|
34
39
|
addLocalReference(values, match[1] ?? match[2]);
|
|
35
40
|
if ([
|
|
@@ -40,14 +45,24 @@ function localDependencyReferences(content, mediaType) {
|
|
|
40
45
|
"text/ecmascript",
|
|
41
46
|
"application/ecmascript",
|
|
42
47
|
"text/html",
|
|
48
|
+
"application/xhtml+xml",
|
|
49
|
+
"image/svg+xml",
|
|
43
50
|
].includes(mediaType)) {
|
|
44
51
|
for (const match of content.matchAll(/(?:\b(?:from|import)\s*|\bimport\s*\(|\brequire\s*\()\s*["']([^"']+)["']/gu))
|
|
45
|
-
|
|
52
|
+
addModuleReference(values, match[1]);
|
|
46
53
|
for (const match of content.matchAll(/(?:\bfetch\s*\(|\bnew\s+(?:Shared)?Worker\s*\(|\bnew\s+URL\s*\()\s*["']([^"']+)["']/gu))
|
|
47
54
|
addLocalReference(values, match[1]);
|
|
48
55
|
}
|
|
49
56
|
return values;
|
|
50
57
|
}
|
|
58
|
+
function addModuleReference(values, raw) {
|
|
59
|
+
if (!raw)
|
|
60
|
+
return;
|
|
61
|
+
const value = raw.trim();
|
|
62
|
+
if (!value.startsWith(".") && !value.startsWith("/"))
|
|
63
|
+
return;
|
|
64
|
+
addLocalReference(values, value);
|
|
65
|
+
}
|
|
51
66
|
function addLocalReference(values, raw) {
|
|
52
67
|
if (!raw)
|
|
53
68
|
return;
|
|
@@ -68,3 +83,48 @@ function resolveResourceReference(from, reference) {
|
|
|
68
83
|
invalidDesignResourceHandoff("implementation_dependency_path_unsafe", `${from}:${reference}`);
|
|
69
84
|
return resolved;
|
|
70
85
|
}
|
|
86
|
+
function resolveDeclaredPath(declaredPaths, resolved) {
|
|
87
|
+
if (declaredPaths.has(resolved))
|
|
88
|
+
return resolved;
|
|
89
|
+
const candidates = [
|
|
90
|
+
...[
|
|
91
|
+
".js",
|
|
92
|
+
".jsx",
|
|
93
|
+
".mjs",
|
|
94
|
+
".cjs",
|
|
95
|
+
".ts",
|
|
96
|
+
".tsx",
|
|
97
|
+
".json",
|
|
98
|
+
".css",
|
|
99
|
+
".svg",
|
|
100
|
+
".png",
|
|
101
|
+
".jpg",
|
|
102
|
+
".jpeg",
|
|
103
|
+
".webp",
|
|
104
|
+
".avif",
|
|
105
|
+
".gif",
|
|
106
|
+
".ico",
|
|
107
|
+
".woff",
|
|
108
|
+
".woff2",
|
|
109
|
+
".ttf",
|
|
110
|
+
".otf",
|
|
111
|
+
".mp4",
|
|
112
|
+
".webm",
|
|
113
|
+
".mp3",
|
|
114
|
+
".wav",
|
|
115
|
+
".lottie",
|
|
116
|
+
].map((extension) => `${resolved}${extension}`),
|
|
117
|
+
...[
|
|
118
|
+
"index.js",
|
|
119
|
+
"index.jsx",
|
|
120
|
+
"index.mjs",
|
|
121
|
+
"index.ts",
|
|
122
|
+
"index.tsx",
|
|
123
|
+
"index.json",
|
|
124
|
+
].map((name) => `${resolved}/${name}`),
|
|
125
|
+
].filter((candidate) => declaredPaths.has(candidate));
|
|
126
|
+
if (candidates.length > 1)
|
|
127
|
+
invalidDesignResourceHandoff("implementation_dependency_resolution_ambiguous", `${resolved}:${candidates.join(",")}`);
|
|
128
|
+
return candidates[0] ?? null;
|
|
129
|
+
}
|
|
130
|
+
export const validateDesignResourceWebDependencyClosure = validateDesignResourceImplementationDependencyClosure;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const EXECUTION_TARGET_CAPABILITIES: readonly ["browser-runtime", "native-runtime", "desktop-runtime", "service-runtime", "process-runtime", "external-runtime", "cold-start", "production-root", "pointer-input", "keyboard-input", "touch-input", "viewport-control", "pixel-density-observation", "safe-area-observation", "motion-observation", "reduced-motion", "color-scheme-control", "text-scale-control", "assistive-technology", "screen-reader", "physical-device", "device-orientation", "sensor-input", "camera-input", "haptic-output", "thermal-observation", "power-mode-control", "persistent-storage", "network-boundary"];
|
|
1
|
+
export declare const EXECUTION_TARGET_CAPABILITIES: readonly ["browser-runtime", "native-runtime", "desktop-runtime", "service-runtime", "process-runtime", "external-runtime", "cold-start", "production-root", "pointer-input", "keyboard-input", "touch-input", "viewport-control", "pixel-density-observation", "safe-area-observation", "motion-observation", "reduced-motion", "color-scheme-control", "text-scale-control", "localization-control", "rtl-control", "assistive-technology", "screen-reader", "physical-device", "device-orientation", "sensor-input", "camera-input", "haptic-output", "audio-output", "reduced-transparency", "increased-contrast", "bold-text-control", "button-shapes-control", "system-ui-observation", "ime-control", "permission-control", "network-state-control", "lifecycle-control", "window-state-control", "fold-state-control", "thermal-observation", "power-mode-control", "persistent-storage", "network-boundary"];
|
|
2
2
|
export type ExecutionTargetCapabilityV2 = (typeof EXECUTION_TARGET_CAPABILITIES)[number];
|
|
@@ -17,6 +17,8 @@ export const EXECUTION_TARGET_CAPABILITIES = [
|
|
|
17
17
|
"reduced-motion",
|
|
18
18
|
"color-scheme-control",
|
|
19
19
|
"text-scale-control",
|
|
20
|
+
"localization-control",
|
|
21
|
+
"rtl-control",
|
|
20
22
|
"assistive-technology",
|
|
21
23
|
"screen-reader",
|
|
22
24
|
"physical-device",
|
|
@@ -24,6 +26,18 @@ export const EXECUTION_TARGET_CAPABILITIES = [
|
|
|
24
26
|
"sensor-input",
|
|
25
27
|
"camera-input",
|
|
26
28
|
"haptic-output",
|
|
29
|
+
"audio-output",
|
|
30
|
+
"reduced-transparency",
|
|
31
|
+
"increased-contrast",
|
|
32
|
+
"bold-text-control",
|
|
33
|
+
"button-shapes-control",
|
|
34
|
+
"system-ui-observation",
|
|
35
|
+
"ime-control",
|
|
36
|
+
"permission-control",
|
|
37
|
+
"network-state-control",
|
|
38
|
+
"lifecycle-control",
|
|
39
|
+
"window-state-control",
|
|
40
|
+
"fold-state-control",
|
|
27
41
|
"thermal-observation",
|
|
28
42
|
"power-mode-control",
|
|
29
43
|
"persistent-storage",
|
|
@@ -7,6 +7,7 @@ import { validateSemanticConformance } from "./long-task-conformance-policy.js";
|
|
|
7
7
|
import { deliveryContractStructureDiagnostics, validateDeliveryContractStructure, } from "./long-task-delivery-validation.js";
|
|
8
8
|
import { validateRawExecutionObservationOwnership } from "./long-task-observation-ownership.js";
|
|
9
9
|
import { validateLongTaskDesignResourceHandoffs } from "./long-task-design-resource-handoff.js";
|
|
10
|
+
import { validateLongTaskSemanticFactClosure } from "./long-task-semantic-fact-closure.js";
|
|
10
11
|
import { freezeDeliveryCheck } from "./long-task-runner-freeze.js";
|
|
11
12
|
import { classifyLongTaskRisk, validateRiskProof, } from "./long-task-risk.js";
|
|
12
13
|
import { validateSourceContinuity } from "./long-task-source-continuity.js";
|
|
@@ -49,6 +50,9 @@ export async function validateContractForActivation(options) {
|
|
|
49
50
|
return decision;
|
|
50
51
|
});
|
|
51
52
|
const context = await attempt(mode, diagnostics, () => captureContextGraphSnapshot(repository, contract.task.context_refs, contract.task.context_snapshot_mode));
|
|
53
|
+
const semanticFactClosure = sourceItems && context
|
|
54
|
+
? await attempt(mode, diagnostics, () => validateLongTaskSemanticFactClosure(contract, repository, sourceItems, context.files))
|
|
55
|
+
: null;
|
|
52
56
|
const workdirRelative = repoRelative(repository, workdir);
|
|
53
57
|
const workspace = await attempt(mode, diagnostics, async () => {
|
|
54
58
|
const manifest = await captureWorkspaceManifest(repository, workdir);
|
|
@@ -62,7 +66,7 @@ export async function validateContractForActivation(options) {
|
|
|
62
66
|
const executionTarget = contract.task.execution_targets.find((target) => target.key === check.execution_target.target_ref);
|
|
63
67
|
if (!executionTarget)
|
|
64
68
|
continue;
|
|
65
|
-
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, null, repository, workspace, executionTarget, contract.task.execution_targets, []), null, check.key);
|
|
69
|
+
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, null, repository, workspace, executionTarget, contract.task.execution_targets, [], []), null, check.key);
|
|
66
70
|
if (frozen)
|
|
67
71
|
globalChecks.push(frozen);
|
|
68
72
|
}
|
|
@@ -73,7 +77,7 @@ export async function validateContractForActivation(options) {
|
|
|
73
77
|
const executionTarget = contract.task.execution_targets.find((target) => target.key === check.execution_target.target_ref);
|
|
74
78
|
if (!executionTarget)
|
|
75
79
|
continue;
|
|
76
|
-
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, outcome.key, repository, workspace, executionTarget, contract.task.execution_targets, designTargetsForCheck(outcome, check.key)), outcome.key, check.key);
|
|
80
|
+
const frozen = await attempt(mode, diagnostics, () => freezeDeliveryCheck(check, outcome.key, repository, workspace, executionTarget, contract.task.execution_targets, designTargetsForCheck(outcome, check.key), semanticFactClosure?.expectations_by_check.get(check.key) ?? []), outcome.key, check.key);
|
|
77
81
|
if (frozen)
|
|
78
82
|
checks.push(frozen);
|
|
79
83
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { array, key, literal, object, string, strings, } from "./long-task-shape-primitives.js";
|
|
1
|
+
import { array, key, literal, object, semanticRef, string, strings, } from "./long-task-shape-primitives.js";
|
|
2
2
|
const JOURNEY_ROLES = [
|
|
3
3
|
"success",
|
|
4
4
|
"degradation",
|
|
@@ -25,8 +25,8 @@ export function parseClaimApplicability(value, label) {
|
|
|
25
25
|
const dimensionLabel = `${itemLabel}.dimensions[${dimensionIndex}]`;
|
|
26
26
|
const entry = object(dimension, dimensionLabel, ["key", "value"]);
|
|
27
27
|
return {
|
|
28
|
-
key:
|
|
29
|
-
value:
|
|
28
|
+
key: semanticRef(entry.key, `${dimensionLabel}.key`),
|
|
29
|
+
value: semanticRef(entry.value, `${dimensionLabel}.value`),
|
|
30
30
|
};
|
|
31
31
|
}),
|
|
32
32
|
given_refs: parseKeyRefs(row.given_refs, `${itemLabel}.given_refs`),
|
|
@@ -31,6 +31,7 @@ export function authoringRevisionPreview(contract, sourceHashes, sourceItems, co
|
|
|
31
31
|
const hashes = computeAuthorityHashes(contract);
|
|
32
32
|
const previousDeclaredHashes = computeAuthorityHashes({
|
|
33
33
|
schema_version: "long-task-delivery-v2",
|
|
34
|
+
semantic_fact_manifest: active.authority_snapshot.semantic_fact_manifest,
|
|
34
35
|
task: active.authority_snapshot.task,
|
|
35
36
|
source_claims: active.authority_snapshot.source_claims,
|
|
36
37
|
stages: active.authority_snapshot.stages,
|
|
@@ -60,6 +60,7 @@ export declare const AUTHORITY_FIELD_POLICY_REGISTRIES: {
|
|
|
60
60
|
stage: "semantic_user_review";
|
|
61
61
|
depends_on: "readiness_only";
|
|
62
62
|
applicability: "semantic_user_review";
|
|
63
|
+
semantic_fact_bindings: "semantic_user_review";
|
|
63
64
|
product: "semantic_user_review";
|
|
64
65
|
technical: "semantic_user_review";
|
|
65
66
|
acceptance: "proof_additive";
|
|
@@ -43,6 +43,7 @@ const OUTCOME_AUTHORITY_POLICY = {
|
|
|
43
43
|
stage: "semantic_user_review",
|
|
44
44
|
depends_on: "readiness_only",
|
|
45
45
|
applicability: "semantic_user_review",
|
|
46
|
+
semantic_fact_bindings: "semantic_user_review",
|
|
46
47
|
product: "semantic_user_review",
|
|
47
48
|
technical: "semantic_user_review",
|
|
48
49
|
acceptance: "proof_additive",
|
|
@@ -17,6 +17,7 @@ export function computeAuthorityHashes(contract) {
|
|
|
17
17
|
source_authority_hash: hash({
|
|
18
18
|
source_paths: contract.task.source_paths,
|
|
19
19
|
source_claims: contract.source_claims,
|
|
20
|
+
semantic_fact_manifest: contract.semantic_fact_manifest,
|
|
20
21
|
}),
|
|
21
22
|
product_authority_hash: hash({
|
|
22
23
|
goal: contract.task.goal,
|
|
@@ -31,6 +32,14 @@ export function computeAuthorityHashes(contract) {
|
|
|
31
32
|
key: outcome.key,
|
|
32
33
|
stage: outcome.stage,
|
|
33
34
|
applicability: outcome.applicability,
|
|
35
|
+
...(outcome.semantic_fact_bindings
|
|
36
|
+
? {
|
|
37
|
+
semantic_fact_bindings: {
|
|
38
|
+
manifest_ref: outcome.semantic_fact_bindings.manifest_ref,
|
|
39
|
+
facts: outcome.semantic_fact_bindings.facts,
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
: {}),
|
|
34
43
|
product: outcome.product,
|
|
35
44
|
})),
|
|
36
45
|
}),
|
|
@@ -40,6 +49,9 @@ export function computeAuthorityHashes(contract) {
|
|
|
40
49
|
global_counterfactual_controls: contract.global.acceptance.counterfactual_controls,
|
|
41
50
|
outcomes: contract.outcomes.map((outcome) => ({
|
|
42
51
|
key: outcome.key,
|
|
52
|
+
...(outcome.semantic_fact_bindings
|
|
53
|
+
? { semantic_fact_proofs: outcome.semantic_fact_bindings.proofs }
|
|
54
|
+
: {}),
|
|
43
55
|
checks: outcome.acceptance.checks.map(acceptanceCheck),
|
|
44
56
|
population: outcome.acceptance.population,
|
|
45
57
|
counterfactual_controls: outcome.acceptance.counterfactual_controls,
|
|
@@ -61,6 +73,7 @@ export function outcomeAuthorityHash(outcome) {
|
|
|
61
73
|
return hash({
|
|
62
74
|
stage: outcome.stage,
|
|
63
75
|
applicability: outcome.applicability,
|
|
76
|
+
semantic_fact_bindings: outcome.semantic_fact_bindings,
|
|
64
77
|
product: outcome.product,
|
|
65
78
|
acceptance: {
|
|
66
79
|
checks: outcome.acceptance.checks.map(acceptanceCheck),
|