project-tiny-context-harness 0.8.1 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +401 -395
  3. package/assets/README.md +628 -549
  4. package/assets/README.zh-CN.md +345 -339
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +70 -70
  7. package/assets/context_templates/architecture.md +28 -28
  8. package/assets/context_templates/area.md +34 -34
  9. package/assets/context_templates/context.toml +30 -30
  10. package/assets/context_templates/deployment.md +35 -35
  11. package/assets/context_templates/global.md +57 -57
  12. package/assets/context_templates/product-surface-contract.md +70 -70
  13. package/assets/context_templates/screen-contract.md +189 -189
  14. package/assets/context_templates/verification.md +32 -32
  15. package/assets/github/.gitkeep +1 -1
  16. package/assets/github/harness.yml +39 -39
  17. package/assets/make/.gitkeep +1 -1
  18. package/assets/make/ty-context.mk +48 -48
  19. package/assets/skills/context_development_engineer/SKILL.md +137 -137
  20. package/assets/skills/context_full_project_export/SKILL.md +28 -28
  21. package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
  22. package/assets/skills/context_product_plan/SKILL.md +88 -88
  23. package/assets/skills/context_surface_contract/SKILL.md +191 -191
  24. package/assets/skills/context_uiux_design/SKILL.md +172 -172
  25. package/assets/skills/design-resource-authoring/SKILL.md +85 -85
  26. package/assets/skills/design-resource-authoring/references/downstream-handoff.md +136 -136
  27. package/assets/skills/design-resource-authoring/references/open-design-provider.md +135 -135
  28. package/assets/skills/design-resource-authoring/references/resource-selection.md +173 -173
  29. package/assets/skills/design-system-authoring/SKILL.md +57 -57
  30. package/assets/skills/design-system-authoring/agents/openai.yaml +6 -6
  31. package/assets/skills/design-system-authoring/references/authority-adoption.md +48 -48
  32. package/assets/skills/design-system-authoring/references/open-design-design-system-provider.md +110 -110
  33. package/assets/skills/long-task-workflow/SKILL.md +100 -100
  34. package/assets/skills/long-task-workflow/references/authority-lifecycle.md +75 -73
  35. package/assets/skills/long-task-workflow/references/contract-authoring.md +119 -115
  36. package/assets/skills/long-task-workflow/references/evidence-design.md +77 -76
  37. package/assets/skills/long-task-workflow/references/source-authoring.md +102 -99
  38. package/assets/skills/source-plan-authoring/SKILL.md +14 -14
  39. package/assets/tools/validate_context.py +442 -442
  40. package/dist/commands/design-resource.js +2 -2
  41. package/dist/commands/index.js +26 -26
  42. package/dist/commands/long-task-authoring.js +83 -9
  43. package/dist/commands/long-task.js +15 -15
  44. package/dist/lib/context-graph-snapshot.js +7 -0
  45. package/dist/lib/design-resource-handoff-shape-evidence.js +3 -0
  46. package/dist/lib/design-resource-handoff-types.d.ts +2 -0
  47. package/dist/lib/design-resource-handoff-validation-coverage.js +1 -0
  48. package/dist/lib/design-resource-handoff-validation-structure.js +2 -0
  49. package/dist/lib/execution-target-capabilities.d.ts +2 -0
  50. package/dist/lib/execution-target-capabilities.js +31 -0
  51. package/dist/lib/long-task-acceptance-shape.js +81 -20
  52. package/dist/lib/long-task-applicability-shape.d.ts +4 -0
  53. package/dist/lib/long-task-applicability-shape.js +54 -0
  54. package/dist/lib/long-task-assertions-v2.js +8 -0
  55. package/dist/lib/long-task-authoring-preflight-diagnostics.js +5 -0
  56. package/dist/lib/long-task-authoring-preflight-repair-order.js +3 -0
  57. package/dist/lib/long-task-authoring-preflight.js +12 -8
  58. package/dist/lib/long-task-authority-materials.js +46 -4
  59. package/dist/lib/long-task-authority-policy.d.ts +54 -0
  60. package/dist/lib/long-task-authority-policy.js +61 -0
  61. package/dist/lib/long-task-authority-types.d.ts +12 -2
  62. package/dist/lib/long-task-authority.js +9 -2
  63. package/dist/lib/long-task-check-shape.js +6 -1
  64. package/dist/lib/long-task-claim-definitions.js +27 -42
  65. package/dist/lib/long-task-claims.js +275 -146
  66. package/dist/lib/long-task-contract-types.d.ts +42 -8
  67. package/dist/lib/long-task-control-fields.d.ts +12 -0
  68. package/dist/lib/long-task-control-fields.js +66 -0
  69. package/dist/lib/long-task-control-types.d.ts +1 -0
  70. package/dist/lib/long-task-control-types.js +1 -0
  71. package/dist/lib/long-task-counterfactual-claim-policy.js +7 -0
  72. package/dist/lib/long-task-counterfactual-types.d.ts +12 -0
  73. package/dist/lib/long-task-delivery-compiler.js +1 -0
  74. package/dist/lib/long-task-delivery-preflight.js +24 -0
  75. package/dist/lib/long-task-delivery-shape.d.ts +1 -0
  76. package/dist/lib/long-task-delivery-shape.js +1 -0
  77. package/dist/lib/long-task-delivery-types.d.ts +1 -0
  78. package/dist/lib/long-task-delivery-types.js +1 -0
  79. package/dist/lib/long-task-delivery-validation.js +46 -0
  80. package/dist/lib/long-task-design-resource-handoff.js +48 -7
  81. package/dist/lib/long-task-evidence-capability-codec.js +37 -0
  82. package/dist/lib/long-task-evidence-capability-policy.js +80 -38
  83. package/dist/lib/long-task-evidence-capability-runtime.js +36 -0
  84. package/dist/lib/long-task-evidence-capability-types.d.ts +13 -1
  85. package/dist/lib/long-task-evidence-findings.js +3 -0
  86. package/dist/lib/long-task-evidence-sensitivity-policy.js +38 -0
  87. package/dist/lib/long-task-evidence-v2.js +7 -1
  88. package/dist/lib/long-task-final-integrity.d.ts +16 -0
  89. package/dist/lib/long-task-final-integrity.js +98 -0
  90. package/dist/lib/long-task-final-v2.js +17 -34
  91. package/dist/lib/long-task-outcome-parser.js +22 -4
  92. package/dist/lib/long-task-playwright-case-evidence.d.ts +2 -0
  93. package/dist/lib/long-task-playwright-case-evidence.js +10 -2
  94. package/dist/lib/long-task-playwright-evidence.d.ts +1 -0
  95. package/dist/lib/long-task-playwright-evidence.js +32 -0
  96. package/dist/lib/long-task-product-shape.d.ts +3 -1
  97. package/dist/lib/long-task-product-shape.js +100 -4
  98. package/dist/lib/long-task-requirement-shape.js +3 -0
  99. package/dist/lib/long-task-root-shape.js +12 -6
  100. package/dist/lib/long-task-runner-freeze.js +16 -0
  101. package/dist/lib/long-task-runtime-types.d.ts +11 -2
  102. package/dist/lib/long-task-semantic-assurance-policy.d.ts +4 -0
  103. package/dist/lib/long-task-semantic-assurance-policy.js +52 -0
  104. package/dist/lib/long-task-semantic-contract-types.d.ts +18 -1
  105. package/dist/lib/long-task-semantic-drift-migration.js +33 -2
  106. package/dist/lib/long-task-semantic-mutation.d.ts +7 -0
  107. package/dist/lib/long-task-semantic-mutation.js +81 -0
  108. package/dist/lib/long-task-shape-primitives.d.ts +1 -1
  109. package/dist/lib/long-task-shape-primitives.js +1 -0
  110. package/dist/lib/long-task-source-authority-types.d.ts +2 -0
  111. package/dist/lib/long-task-source-item-parser.d.ts +1 -1
  112. package/dist/lib/long-task-source-item-parser.js +150 -104
  113. package/dist/lib/long-task-source-markers.d.ts +12 -0
  114. package/dist/lib/long-task-source-markers.js +146 -0
  115. package/dist/lib/long-task-source-target-continuity.d.ts +1 -1
  116. package/dist/lib/long-task-source-target-continuity.js +80 -55
  117. package/dist/lib/long-task-source-target-index.js +7 -29
  118. package/dist/lib/long-task-status-v2.d.ts +1 -0
  119. package/dist/lib/long-task-status-v2.js +2 -2
  120. package/dist/lib/long-task-target-policy.js +20 -0
  121. package/dist/lib/long-task-ui-design-policy.js +27 -1
  122. package/dist/lib/long-task-ui-surface-shape.js +21 -1
  123. package/dist/lib/long-task-ui-surface-types.d.ts +7 -0
  124. package/dist/lib/long-task-verification-preview.d.ts +10 -0
  125. package/dist/lib/long-task-verifier-dependency-closure.d.ts +3 -0
  126. package/dist/lib/long-task-verifier-dependency-closure.js +179 -0
  127. package/dist/lib/long-task-verifier-v2.js +12 -2
  128. package/dist/lib/long-task-workspace.js +5 -1
  129. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +99 -25
  130. package/migrations/README.md +15 -15
  131. package/package.json +84 -84
  132. package/source-mappings.yaml +25 -25
@@ -1,161 +1,29 @@
1
1
  import { assertAllClaimsCovered, assertAllGlobalClaimsCovered, generateClaims, generateGlobalClaims, validateGlobalProofPolarity, validateProofSurface, } from "./long-task-claim-definitions.js";
2
2
  import { fail } from "./long-task-delivery-shape.js";
3
3
  import { validateClaimAssertionOperator, validateGlobalAssertionOperator, } from "./long-task-claim-proof-policy.js";
4
+ import { matchesRepoPattern } from "./long-task-paths.js";
4
5
  export function compileProductClaimCoverage(contract, options = {}) {
5
6
  const byGlobal = generateGlobalClaims(contract.global);
6
7
  const byOutcome = Object.fromEntries(contract.outcomes.map((outcome) => [outcome.key, generateClaims(outcome)]));
7
8
  for (const [outcomeKey, claims] of Object.entries(byOutcome))
8
9
  if (!claims.some((claim) => claim.kind !== "result"))
9
10
  fail("outcome_atomic_claim_required", outcomeKey);
10
- const globalClaimMap = new Map(byGlobal.map((claim) => [claim.local_key, claim]));
11
- const outcomeClaimIds = new Set(Object.values(byOutcome)
12
- .flat()
13
- .map((claim) => claim.id));
14
- const globalProofs = new Map();
15
- const addGlobalProof = (claimKey, proof) => {
16
- const claim = globalClaimMap.get(claimKey);
17
- if (!claim) {
18
- if (outcomeClaimIds.has(claimKey))
19
- fail("global_assertion_claim_cross_scope", claimKey);
20
- fail("global_assertion_claim_unknown", claimKey);
21
- }
22
- validateGlobalProofPolarity(claim, proof);
23
- const rows = globalProofs.get(claimKey) ?? [];
24
- rows.push(proof);
25
- globalProofs.set(claimKey, rows);
26
- };
27
- for (const check of contract.global.acceptance.checks) {
28
- const assertionKeys = new Set();
29
- for (const [polarity, assertions] of [
30
- ["positive", check.positive_assertions],
31
- ["negative", check.negative_assertions],
32
- ])
33
- for (const assertion of assertions) {
34
- if (assertionKeys.has(assertion.key))
35
- fail("assertion_key_duplicate", `GLOBAL:${check.key}:${assertion.key}`);
36
- assertionKeys.add(assertion.key);
37
- validateGlobalAssertionOperator(assertion, check.key);
38
- for (const claimKey of assertion.claims)
39
- addGlobalProof(claimKey, {
40
- check_key: check.key,
41
- assertion_key: assertion.key,
42
- polarity,
43
- proof_surface: check.proof_surface,
44
- });
45
- }
46
- }
47
- const globalRows = {};
48
- const uncoveredGlobal = [];
49
- for (const claim of byGlobal) {
50
- const proofs = globalProofs.get(claim.local_key) ?? [];
51
- const covered = proofs.length > 0;
52
- globalRows[claim.local_key] = { covered, proofs };
53
- if (!covered)
54
- uncoveredGlobal.push(claim.id);
55
- }
11
+ const globalProfileMap = validateProfiles("GLOBAL", contract.global.applicability, contract.global.acceptance.checks, contract.task.execution_targets.map((target) => target.key));
12
+ const globalRows = compileGlobalScope(contract, byGlobal, globalProfileMap);
56
13
  const outcomeKeys = new Set(contract.outcomes.map((outcome) => outcome.key));
57
14
  const globalLocalKeys = new Set(byGlobal.map((claim) => claim.local_key));
58
- const summaryRows = {};
59
- const uncoveredOutcome = [];
15
+ const outcomeRows = {};
60
16
  for (const outcome of contract.outcomes) {
61
- const claims = byOutcome[outcome.key];
62
- const claimMap = new Map(claims.map((claim) => [claim.local_key, claim]));
63
- const proofs = new Map();
64
- const addProof = (claimKey, proof, observation, assertion) => {
65
- const claim = claimMap.get(claimKey);
66
- if (!claim) {
67
- if (globalLocalKeys.has(claimKey))
68
- fail("assertion_claim_cross_scope", `${outcome.key}:${claimKey}`);
69
- const first = claimKey.split(".")[0];
70
- if (outcomeKeys.has(first) && first !== outcome.key)
71
- fail("assertion_claim_cross_outcome", `${outcome.key}:${claimKey}`);
72
- fail("assertion_claim_unknown", `${outcome.key}:${claimKey}`);
73
- }
74
- if (observation === "playwright.passed" &&
75
- (claim.kind === "requirement" || claim.kind === "control"))
76
- fail("fine_grained_claim_requires_ac_observation", `${outcome.key}:${claim.local_key}`);
77
- validateProofSurface(claim, proof, outcome.key);
78
- if (assertion)
79
- validateClaimAssertionOperator(claim, assertion, proof.proof_surface, outcome.key, proof.check_key);
80
- const rows = proofs.get(claimKey) ?? [];
81
- rows.push(proof);
82
- proofs.set(claimKey, rows);
83
- };
84
- for (const check of outcome.acceptance.checks) {
85
- const assertionKeys = new Set();
86
- for (const [polarity, assertions] of [
87
- ["positive", check.positive_assertions],
88
- ["negative", check.negative_assertions],
89
- ]) {
90
- for (const assertion of assertions) {
91
- if (assertionKeys.has(assertion.key))
92
- fail("assertion_key_duplicate", `${outcome.key}:${check.key}:${assertion.key}`);
93
- assertionKeys.add(assertion.key);
94
- for (const claimKey of assertion.claims)
95
- addProof(claimKey, {
96
- check_key: check.key,
97
- assertion_key: assertion.key,
98
- polarity,
99
- proof_surface: check.proof_surface,
100
- }, assertion.observation, assertion);
101
- }
102
- }
103
- }
104
- if (outcome.acceptance.population) {
105
- const population = outcome.acceptance.population;
106
- const check = outcome.acceptance.checks.find((candidate) => candidate.key === population.check_key);
107
- if (!check)
108
- fail("outcome_check_reference_unknown", `${outcome.key}:${population.check_key}`);
109
- for (const claimKey of population.claims)
110
- addProof(claimKey, {
111
- check_key: check.key,
112
- assertion_key: null,
113
- polarity: "population",
114
- proof_surface: check.proof_surface,
115
- });
116
- }
117
- for (const counterfactual of outcome.acceptance.counterfactual_controls) {
118
- const check = outcome.acceptance.checks.find((candidate) => candidate.key === counterfactual.check_key);
119
- if (!check)
120
- fail("outcome_check_reference_unknown", `${outcome.key}:${counterfactual.check_key}`);
121
- const assertionKeys = new Set([...check.positive_assertions, ...check.negative_assertions].map((assertion) => assertion.key));
122
- if (!counterfactual.expected_assertion_failures.length)
123
- fail("counterfactual_expected_assertion_required", `${outcome.key}:${counterfactual.key}`);
124
- for (const assertionKey of counterfactual.expected_assertion_failures)
125
- if (!assertionKeys.has(assertionKey))
126
- fail("counterfactual_assertion_unknown", `${outcome.key}:${counterfactual.key}:${assertionKey}`);
127
- for (const claimKey of counterfactual.claims)
128
- addProof(claimKey, {
129
- check_key: check.key,
130
- assertion_key: counterfactual.expected_assertion_failures.join(","),
131
- polarity: "counterfactual",
132
- proof_surface: check.proof_surface,
133
- });
134
- }
135
- const rows = {};
136
- for (const claim of claims) {
137
- const claimProofs = proofs.get(claim.local_key) ?? [];
138
- const requiredSurfaces = [...claim.required_proof_surfaces].sort();
139
- const coveredSurfaces = [
140
- ...new Set(claimProofs.map((proof) => proof.proof_surface)),
141
- ].sort();
142
- const missingSurfaces = requiredSurfaces.filter((surface) => !coveredSurfaces.includes(surface));
143
- const covered = claimProofs.length > 0 &&
144
- (requiredSurfaces.length === 0 || missingSurfaces.length === 0);
145
- rows[claim.local_key] = {
146
- required_surfaces: requiredSurfaces,
147
- covered_surfaces: coveredSurfaces,
148
- missing_surfaces: missingSurfaces,
149
- covered,
150
- proofs: claimProofs,
151
- };
152
- if (claimProofs.length && missingSurfaces.length)
153
- fail("product_claim_required_surfaces_missing", `${outcome.key}:${claim.local_key}:${missingSurfaces.join(",")}`);
154
- if (!covered)
155
- uncoveredOutcome.push(claim.id);
156
- }
157
- summaryRows[outcome.key] = rows;
17
+ const profiles = validateProfiles(outcome.key, outcome.applicability, outcome.acceptance.checks, contract.task.execution_targets.map((target) => target.key));
18
+ outcomeRows[outcome.key] = compileOutcomeScope(contract, outcome.key, byOutcome[outcome.key], profiles, outcomeKeys, globalLocalKeys);
158
19
  }
20
+ const uncoveredGlobal = byGlobal
21
+ .filter((claim) => !globalRows[claim.local_key]?.covered)
22
+ .map((claim) => claim.id);
23
+ const uncoveredOutcome = Object.values(byOutcome)
24
+ .flat()
25
+ .filter((claim) => !outcomeRows[claim.outcome_key]?.[claim.local_key]?.covered)
26
+ .map((claim) => claim.id);
159
27
  const uncovered = [...uncoveredGlobal, ...uncoveredOutcome].sort();
160
28
  const total = byGlobal.length +
161
29
  Object.values(byOutcome).reduce((sum, claims) => sum + claims.length, 0);
@@ -167,14 +35,264 @@ export function compileProductClaimCoverage(contract, options = {}) {
167
35
  claims_covered: total - uncovered.length,
168
36
  uncovered_claims: uncovered,
169
37
  claims_by_global: globalRows,
170
- claims_by_outcome: summaryRows,
38
+ claims_by_outcome: outcomeRows,
171
39
  },
172
40
  };
173
41
  if (!options.allow_uncovered)
174
42
  assertCompiledClaimsCovered(compiled);
175
43
  return compiled;
176
44
  }
45
+ function compileGlobalScope(contract, claims, profiles) {
46
+ const claimMap = new Map(claims.map((claim) => [claim.local_key, claim]));
47
+ const outcomeClaimIds = new Set(contract.outcomes.flatMap((outcome) => generateClaims(outcome).map((claim) => claim.id)));
48
+ const proofs = new Map();
49
+ for (const proof of scopeAssertions(contract.global.acceptance.checks)) {
50
+ validateAssertionArity(proof.assertion, "GLOBAL", proof.check.key);
51
+ if (!proof.assertion.claims.length)
52
+ continue;
53
+ const claimKey = proof.assertion.claims[0];
54
+ const claim = claimMap.get(claimKey);
55
+ if (!claim) {
56
+ if (outcomeClaimIds.has(claimKey))
57
+ fail("global_assertion_claim_cross_scope", claimKey);
58
+ fail("global_assertion_claim_unknown", claimKey);
59
+ }
60
+ const applicabilityRef = validateAssertionApplicability(claim.applicability_refs, proof, profiles, "GLOBAL");
61
+ const claimProof = {
62
+ check_key: proof.check.key,
63
+ assertion_key: proof.assertion.key,
64
+ polarity: proof.polarity,
65
+ proof_surface: proof.check.proof_surface,
66
+ applicability_ref: applicabilityRef,
67
+ };
68
+ validateGlobalProofPolarity(claim, claimProof);
69
+ validateGlobalAssertionOperator(proof.assertion, proof.check.key);
70
+ addProof(proofs, claimKey, claimProof);
71
+ }
72
+ validateProfileUse("GLOBAL", profiles, claims);
73
+ return Object.fromEntries(claims.map((claim) => {
74
+ const claimProofs = proofs.get(claim.local_key) ?? [];
75
+ const coverage = applicabilityCoverage(claim.applicability_refs, claimProofs, [], claim.required_polarity);
76
+ return [
77
+ claim.local_key,
78
+ {
79
+ covered: coverage.uncovered.length === 0,
80
+ applicability_refs: [...claim.applicability_refs].sort(),
81
+ uncovered_applicability_refs: coverage.uncovered,
82
+ proofs: claimProofs,
83
+ },
84
+ ];
85
+ }));
86
+ }
87
+ function compileOutcomeScope(contract, outcomeKey, claims, profiles, outcomeKeys, globalLocalKeys) {
88
+ const outcome = contract.outcomes.find((candidate) => candidate.key === outcomeKey);
89
+ const claimMap = new Map(claims.map((claim) => [claim.local_key, claim]));
90
+ const proofs = new Map();
91
+ for (const proof of scopeAssertions(outcome.acceptance.checks)) {
92
+ validateAssertionArity(proof.assertion, outcomeKey, proof.check.key);
93
+ if (!proof.assertion.claims.length)
94
+ continue;
95
+ const claimKey = proof.assertion.claims[0];
96
+ const claim = claimMap.get(claimKey);
97
+ if (!claim) {
98
+ if (globalLocalKeys.has(claimKey))
99
+ fail("assertion_claim_cross_scope", `${outcomeKey}:${claimKey}`);
100
+ const first = claimKey.split(".")[0];
101
+ if (outcomeKeys.has(first) && first !== outcomeKey)
102
+ fail("assertion_claim_cross_outcome", `${outcomeKey}:${claimKey}`);
103
+ fail("assertion_claim_unknown", `${outcomeKey}:${claimKey}`);
104
+ }
105
+ if (proof.assertion.observation === "playwright.passed" &&
106
+ (claim.kind === "requirement" ||
107
+ claim.kind === "control" ||
108
+ claim.kind === "control_relation"))
109
+ fail("fine_grained_claim_requires_ac_observation", `${outcomeKey}:${claim.local_key}`);
110
+ const applicabilityRef = validateAssertionApplicability(claim.applicability_refs, proof, profiles, outcomeKey);
111
+ const claimProof = {
112
+ check_key: proof.check.key,
113
+ assertion_key: proof.assertion.key,
114
+ polarity: proof.polarity,
115
+ proof_surface: proof.check.proof_surface,
116
+ applicability_ref: applicabilityRef,
117
+ };
118
+ validateProofSurface(claim, claimProof, outcomeKey);
119
+ validateClaimAssertionOperator(claim, proof.assertion, proof.check.proof_surface, outcomeKey, proof.check.key);
120
+ addProof(proofs, claimKey, claimProof);
121
+ }
122
+ validatePopulationReferences(outcome, claimMap);
123
+ validateCounterfactualReferences(outcome, claimMap);
124
+ validateProfileUse(outcomeKey, profiles, claims);
125
+ return Object.fromEntries(claims.map((claim) => {
126
+ const claimProofs = proofs.get(claim.local_key) ?? [];
127
+ const requiredSurfaces = [...claim.required_proof_surfaces].sort();
128
+ const coveredSurfaces = [
129
+ ...new Set(claimProofs.map((proof) => proof.proof_surface)),
130
+ ].sort();
131
+ const missingSurfaces = requiredSurfaces.filter((surface) => !coveredSurfaces.includes(surface));
132
+ const coverage = applicabilityCoverage(claim.applicability_refs, claimProofs, requiredSurfaces, claim.required_polarity);
133
+ return [
134
+ claim.local_key,
135
+ {
136
+ required_surfaces: requiredSurfaces,
137
+ covered_surfaces: coveredSurfaces,
138
+ missing_surfaces: missingSurfaces,
139
+ covered: coverage.uncovered.length === 0,
140
+ applicability_refs: [...claim.applicability_refs].sort(),
141
+ uncovered_applicability_refs: coverage.uncovered,
142
+ proofs: claimProofs,
143
+ },
144
+ ];
145
+ }));
146
+ }
147
+ function validateProfiles(scope, profiles, checks, targetRefs) {
148
+ const result = new Map();
149
+ const targets = new Set(targetRefs);
150
+ for (const profile of profiles) {
151
+ if (result.has(profile.key))
152
+ fail("claim_applicability_key_duplicate", `${scope}:${profile.key}`);
153
+ if (!targets.has(profile.target_ref))
154
+ fail("claim_applicability_target_unknown", `${scope}:${profile.key}:${profile.target_ref}`);
155
+ validateUniqueNonemptyRefs(profile.given_refs, "claim_applicability_given_refs", `${scope}:${profile.key}`);
156
+ validateUniqueNonemptyRefs(profile.when_refs, "claim_applicability_when_refs", `${scope}:${profile.key}`);
157
+ result.set(profile.key, profile);
158
+ }
159
+ validateScenarioStepSemantics(scope, checks);
160
+ return result;
161
+ }
162
+ function validateScenarioStepSemantics(scope, checks) {
163
+ for (const phase of ["given", "when"]) {
164
+ const semantics = new Map();
165
+ for (const check of checks) {
166
+ const seen = new Set();
167
+ for (const step of check.scenario[phase]) {
168
+ if (seen.has(step.key))
169
+ fail("check_scenario_step_duplicate", `${scope}:${check.key}:${phase}:${step.key}`);
170
+ seen.add(step.key);
171
+ const previous = semantics.get(step.key);
172
+ if (previous !== undefined && previous !== step.statement)
173
+ fail("check_scenario_step_semantics_conflict", `${scope}:${phase}:${step.key}`);
174
+ semantics.set(step.key, step.statement);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ function validateAssertionArity(assertion, scope, checkKey) {
180
+ if (assertion.claims.length > 1)
181
+ fail("assertion_single_claim_required", `${scope}:${checkKey}:${assertion.key}`);
182
+ if (assertion.claims.length === 1 && !assertion.applicability_ref)
183
+ fail("assertion_applicability_ref_required", `${scope}:${checkKey}:${assertion.key}`);
184
+ if (!assertion.claims.length && assertion.applicability_ref)
185
+ fail("claimless_assertion_applicability_ref_forbidden", `${scope}:${checkKey}:${assertion.key}`);
186
+ }
187
+ function validateAssertionApplicability(claimRefs, proof, profiles, scope) {
188
+ validateUniqueNonemptyRefs(claimRefs, "claim_applicability_refs", `${scope}:${proof.assertion.claims[0]}`);
189
+ const reference = proof.assertion.applicability_ref;
190
+ if (!claimRefs.includes(reference))
191
+ fail("claim_assertion_applicability_not_declared", `${scope}:${proof.assertion.claims[0]}:${reference}`);
192
+ const profile = profiles.get(reference);
193
+ if (!profile)
194
+ fail("claim_applicability_ref_unknown", `${scope}:${proof.assertion.claims[0]}:${reference}`);
195
+ const label = `${scope}:${proof.check.key}:${proof.assertion.key}:${reference}`;
196
+ if (proof.check.execution_target.target_ref !== profile.target_ref)
197
+ fail("claim_applicability_target_mismatch", label);
198
+ if (!proof.check.journey_roles.includes(profile.journey_role))
199
+ fail("claim_applicability_journey_mismatch", label);
200
+ if (!sameSet(proof.check.scenario.given.map((step) => step.key), profile.given_refs))
201
+ fail("claim_applicability_given_mismatch", label);
202
+ if (proof.check.scenario.when.map((step) => step.key).join("\0") !==
203
+ profile.when_refs.join("\0"))
204
+ fail("claim_applicability_when_mismatch", label);
205
+ return reference;
206
+ }
207
+ function validatePopulationReferences(outcome, claims) {
208
+ const population = outcome.acceptance.population;
209
+ if (!population)
210
+ return;
211
+ const check = outcome.acceptance.checks.find((candidate) => candidate.key === population.check_key);
212
+ if (!check)
213
+ fail("outcome_check_reference_unknown", `${outcome.key}:${population.check_key}`);
214
+ const universeBinding = outcome.technical.bindings.find((binding) => binding.key === population.universe_binding_key);
215
+ if (!universeBinding)
216
+ fail("population_universe_binding_unknown", `${outcome.key}:${population.universe_binding_key}`);
217
+ const missingUniverseInputs = universeBinding.carrier_paths.filter((carrier) => !check.input_paths.some((pattern) => matchesRepoPattern(carrier, pattern)));
218
+ if (missingUniverseInputs.length)
219
+ fail("population_universe_carrier_input_missing", `${outcome.key}:${population.check_key}:${missingUniverseInputs.join(",")}`);
220
+ for (const claim of population.claims)
221
+ if (!claims.has(claim))
222
+ fail("assertion_claim_unknown", `${outcome.key}:${claim}`);
223
+ }
224
+ function validateCounterfactualReferences(outcome, claims) {
225
+ for (const control of outcome.acceptance.counterfactual_controls) {
226
+ const check = outcome.acceptance.checks.find((candidate) => candidate.key === control.check_key);
227
+ if (!check)
228
+ fail("outcome_check_reference_unknown", `${outcome.key}:${control.check_key}`);
229
+ const assertions = new Set([...check.positive_assertions, ...check.negative_assertions].map((assertion) => assertion.key));
230
+ if (!control.expected_assertion_failures.length)
231
+ fail("counterfactual_expected_assertion_required", `${outcome.key}:${control.key}`);
232
+ for (const assertion of [
233
+ ...control.expected_assertion_failures,
234
+ ...control.preserved_assertions,
235
+ ])
236
+ if (!assertions.has(assertion))
237
+ fail("counterfactual_assertion_unknown", `${outcome.key}:${control.key}:${assertion}`);
238
+ for (const claim of control.claims)
239
+ if (!claims.has(claim))
240
+ fail("assertion_claim_unknown", `${outcome.key}:${claim}`);
241
+ }
242
+ }
243
+ function scopeAssertions(checks) {
244
+ return checks.flatMap((check) => [
245
+ ...check.positive_assertions.map((assertion) => ({
246
+ check,
247
+ assertion,
248
+ polarity: "positive",
249
+ })),
250
+ ...check.negative_assertions.map((assertion) => ({
251
+ check,
252
+ assertion,
253
+ polarity: "negative",
254
+ })),
255
+ ]);
256
+ }
257
+ function applicabilityCoverage(refs, proofs, requiredSurfaces, requiredPolarity) {
258
+ const uncovered = refs.filter((reference) => {
259
+ const matching = proofs.filter((proof) => proof.applicability_ref === reference &&
260
+ proof.polarity === requiredPolarity);
261
+ if (!matching.length)
262
+ return true;
263
+ return requiredSurfaces.some((surface) => !matching.some((proof) => proof.proof_surface === surface));
264
+ });
265
+ return { uncovered: [...uncovered].sort() };
266
+ }
267
+ function validateProfileUse(scope, profiles, claims) {
268
+ const used = new Set(claims.flatMap((claim) => claim.applicability_refs));
269
+ for (const reference of used)
270
+ if (!profiles.has(reference))
271
+ fail("claim_applicability_ref_unknown", `${scope}:${reference}`);
272
+ for (const reference of profiles.keys())
273
+ if (!used.has(reference))
274
+ fail("claim_applicability_profile_unused", `${scope}:${reference}`);
275
+ }
276
+ function validateUniqueNonemptyRefs(refs, code, detail) {
277
+ if (!refs.length)
278
+ fail(`${code}_required`, detail);
279
+ if (new Set(refs).size !== refs.length)
280
+ fail(`${code}_duplicate`, detail);
281
+ }
282
+ function addProof(proofs, claim, proof) {
283
+ const rows = proofs.get(claim) ?? [];
284
+ rows.push(proof);
285
+ proofs.set(claim, rows);
286
+ }
287
+ function sameSet(left, right) {
288
+ return (left.length === right.length &&
289
+ new Set(left).size === left.length &&
290
+ left.every((item) => right.includes(item)));
291
+ }
177
292
  export function assertCompiledClaimsCovered(compiled) {
293
+ for (const [outcomeKey, claims] of Object.entries(compiled.by_outcome))
294
+ for (const claim of claims)
295
+ assertRequiredSurfacesForEveryApplicability(outcomeKey, claim, compiled.summary.claims_by_outcome[outcomeKey]?.[claim.local_key]);
178
296
  const uncoveredGlobal = compiled.by_global
179
297
  .filter((claim) => !compiled.summary.claims_by_global[claim.local_key]?.covered)
180
298
  .map((claim) => claim.id);
@@ -185,3 +303,14 @@ export function assertCompiledClaimsCovered(compiled) {
185
303
  assertAllGlobalClaimsCovered(uncoveredGlobal);
186
304
  assertAllClaimsCovered(uncoveredOutcome);
187
305
  }
306
+ function assertRequiredSurfacesForEveryApplicability(scope, claim, summary) {
307
+ if (!summary || !claim.required_proof_surfaces.length)
308
+ return;
309
+ for (const applicabilityRef of claim.applicability_refs) {
310
+ const proofs = summary.proofs.filter((proof) => proof.applicability_ref === applicabilityRef &&
311
+ proof.polarity === claim.required_polarity);
312
+ const missing = claim.required_proof_surfaces.filter((surface) => !proofs.some((proof) => proof.proof_surface === surface));
313
+ if (missing.length)
314
+ fail("product_claim_required_surfaces_missing", `${scope}:${claim.local_key}:${applicabilityRef}:${missing.sort().join(",")}`);
315
+ }
316
+ }
@@ -1,6 +1,7 @@
1
1
  import type { LongTaskRiskFacts, RequestedRiskLevel } from "./long-task-risk-types.js";
2
2
  import type { CounterfactualControlV2, GlobalCounterfactualControlV2 } from "./long-task-counterfactual-types.js";
3
- import type { CheckExecutionTargetV2, DeliveryJourneyRoleV2, DeliveryScenarioV2, DeliveryStageV2, EvidenceCapabilityV2, ExecutionTargetV2, ExternalConfirmationKindV2, KeyedStatementV2, TargetProfileV2 } from "./long-task-semantic-contract-types.js";
3
+ import type { DeliveryControlFieldNameV2 } from "./long-task-control-types.js";
4
+ import type { ApplicableKeyedStatementV2, CheckExecutionTargetV2, ClaimApplicabilityV2, DeliveryJourneyRoleV2, DeliveryScenarioV2, DeliveryStageV2, EvidenceCapabilityV2, ExecutionTargetV2, ExternalConfirmationKindV2, KeyedStatementV2, TargetProfileV2 } from "./long-task-semantic-contract-types.js";
4
5
  import type { DeliverySurfaceBindingV2 } from "./long-task-ui-surface-types.js";
5
6
  export type SourceClaimDispositionV2 = {
6
7
  type: "claim";
@@ -51,6 +52,7 @@ interface DeliveryAssertionBaseV2 {
51
52
  key: string;
52
53
  criterion?: string;
53
54
  claims: string[];
55
+ applicability_ref?: string;
54
56
  observation: string;
55
57
  evidence_capabilities: EvidenceCapabilityV2[];
56
58
  }
@@ -125,8 +127,33 @@ export interface DeliveryControlV2 {
125
127
  permission: string;
126
128
  feedback: string;
127
129
  accessibility: string;
130
+ field_coverage: DeliveryControlFieldCoverageV2[];
128
131
  }
129
- interface DeliveryRequirementV2 extends KeyedStatementV2 {
132
+ export type DeliveryControlFieldCoverageV2 = {
133
+ fields: DeliveryControlFieldNameV2[];
134
+ state: "specified";
135
+ applicability_refs: string[];
136
+ } | {
137
+ fields: DeliveryControlFieldNameV2[];
138
+ state: "not_applicable";
139
+ statement: string;
140
+ applicability_refs: string[];
141
+ } | {
142
+ fields: DeliveryControlFieldNameV2[];
143
+ state: "unresolved";
144
+ statement: string;
145
+ applicability_refs: string[];
146
+ };
147
+ export interface DeliveryControlRelationV2 extends ApplicableKeyedStatementV2 {
148
+ control_refs: string[];
149
+ required_proof_surfaces: ProofSurface[];
150
+ }
151
+ export interface DeliveryControlRelationClosureV2 {
152
+ state: "specified" | "not_applicable" | "unresolved";
153
+ statement: string;
154
+ applicability_refs: string[];
155
+ }
156
+ interface DeliveryRequirementV2 extends ApplicableKeyedStatementV2 {
130
157
  required_proof_surfaces: ProofSurface[];
131
158
  }
132
159
  export interface DeliveryOwnerV2 {
@@ -134,7 +161,7 @@ export interface DeliveryOwnerV2 {
134
161
  context_refs: string[];
135
162
  path_globs: string[];
136
163
  }
137
- export interface DeliveryObligationV2 extends KeyedStatementV2 {
164
+ export interface DeliveryObligationV2 extends ApplicableKeyedStatementV2 {
138
165
  required_proof_surfaces: ProofSurface[];
139
166
  }
140
167
  export interface DeliveryBindingV2 {
@@ -152,8 +179,10 @@ export interface RollbackRecoveryV2 {
152
179
  }
153
180
  export interface PopulationRequirementV2 {
154
181
  check_key: string;
182
+ universe_binding_key: string;
155
183
  claims: string[];
156
184
  observations: {
185
+ universe_ids: string;
157
186
  eligible_ids: string;
158
187
  observed_ids: string;
159
188
  excluded_items: string;
@@ -165,16 +194,20 @@ export interface DeliveryOutcomeV2 {
165
194
  title: string;
166
195
  stage: string;
167
196
  depends_on: string[];
197
+ applicability: ClaimApplicabilityV2[];
168
198
  product: {
169
199
  observable_result: string;
200
+ result_applicability_refs: string[];
170
201
  success_path_required: boolean;
171
202
  degradation_path_required: boolean;
172
203
  owner: DeliveryOwnerV2;
173
204
  requirements: DeliveryRequirementV2[];
174
205
  owner_surfaces: string[];
175
206
  controls: DeliveryControlV2[];
207
+ control_relation_closure: DeliveryControlRelationClosureV2;
208
+ control_relations: DeliveryControlRelationV2[];
176
209
  surface_bindings: DeliverySurfaceBindingV2[];
177
- non_completing_outcomes: KeyedStatementV2[];
210
+ non_completing_outcomes: ApplicableKeyedStatementV2[];
178
211
  };
179
212
  technical: {
180
213
  obligations: DeliveryObligationV2[];
@@ -182,7 +215,7 @@ export interface DeliveryOutcomeV2 {
182
215
  allowed_support_paths: string[];
183
216
  forbidden_paths: string[];
184
217
  bindings: DeliveryBindingV2[];
185
- forbidden_shortcuts: KeyedStatementV2[];
218
+ forbidden_shortcuts: ApplicableKeyedStatementV2[];
186
219
  rollback_and_recovery: RollbackRecoveryV2 | null;
187
220
  };
188
221
  acceptance: {
@@ -210,13 +243,14 @@ export interface DeliveryContractV2 {
210
243
  facts: LongTaskRiskFacts;
211
244
  };
212
245
  global: {
246
+ applicability: ClaimApplicabilityV2[];
213
247
  product: {
214
- non_goals: KeyedStatementV2[];
248
+ non_goals: ApplicableKeyedStatementV2[];
215
249
  };
216
250
  technical: {
217
- constraints: KeyedStatementV2[];
251
+ constraints: ApplicableKeyedStatementV2[];
218
252
  forbidden_paths: KeyedPathV2[];
219
- forbidden_shortcuts: KeyedStatementV2[];
253
+ forbidden_shortcuts: ApplicableKeyedStatementV2[];
220
254
  };
221
255
  acceptance: {
222
256
  checks: DeliveryCheckV2[];
@@ -0,0 +1,12 @@
1
+ import type { DeliveryControlV2 } from "./long-task-contract-types.js";
2
+ import type { DeliveryControlFieldNameV2 } from "./long-task-control-types.js";
3
+ export declare const CONTROL_FIELD_NAMES: readonly ["surface", "region", "location", "control_type", "label_content", "user_task", "visibility", "availability", "trigger", "input", "validation", "default_value", "interaction", "navigation_result", "loading_state", "empty_state", "success_state", "failure_state", "recovery", "permission", "feedback", "accessibility"];
4
+ export interface ControlFieldFactV2 {
5
+ contract_field: DeliveryControlFieldNameV2;
6
+ claim_field: string;
7
+ statement: string;
8
+ state: "specified" | "not_applicable" | "unresolved";
9
+ applicability_refs: string[];
10
+ }
11
+ export declare function controlFieldFacts(control: DeliveryControlV2): ControlFieldFactV2[];
12
+ export declare function controlFieldState(control: DeliveryControlV2, field: DeliveryControlFieldNameV2): ControlFieldFactV2["state"];
@@ -0,0 +1,66 @@
1
+ export const CONTROL_FIELD_NAMES = [
2
+ "surface",
3
+ "region",
4
+ "location",
5
+ "control_type",
6
+ "label_content",
7
+ "user_task",
8
+ "visibility",
9
+ "availability",
10
+ "trigger",
11
+ "input",
12
+ "validation",
13
+ "default_value",
14
+ "interaction",
15
+ "navigation_result",
16
+ "loading_state",
17
+ "empty_state",
18
+ "success_state",
19
+ "failure_state",
20
+ "recovery",
21
+ "permission",
22
+ "feedback",
23
+ "accessibility",
24
+ ];
25
+ const CLAIM_FIELD_BY_CONTRACT_FIELD = {
26
+ surface: "surface",
27
+ region: "region",
28
+ location: "location",
29
+ control_type: "control_type",
30
+ label_content: "label_content",
31
+ user_task: "user_task",
32
+ visibility: "visibility",
33
+ availability: "availability",
34
+ trigger: "trigger",
35
+ input: "input",
36
+ validation: "validation",
37
+ default_value: "default_value",
38
+ interaction: "interaction",
39
+ navigation_result: "navigation_result",
40
+ loading_state: "loading",
41
+ empty_state: "empty",
42
+ success_state: "success",
43
+ failure_state: "failure",
44
+ recovery: "recovery",
45
+ permission: "permission",
46
+ feedback: "feedback",
47
+ accessibility: "accessibility",
48
+ };
49
+ export function controlFieldFacts(control) {
50
+ const coverage = new Map(control.field_coverage.flatMap((entry) => entry.fields.map((field) => [field, entry])));
51
+ return CONTROL_FIELD_NAMES.map((field) => {
52
+ const entry = coverage.get(field);
53
+ if (!entry)
54
+ throw new Error(`control_field_coverage_missing:${control.key}:${field}`);
55
+ return {
56
+ contract_field: field,
57
+ claim_field: CLAIM_FIELD_BY_CONTRACT_FIELD[field],
58
+ statement: entry.state === "specified" ? control[field] : entry.statement,
59
+ state: entry.state,
60
+ applicability_refs: [...entry.applicability_refs],
61
+ };
62
+ });
63
+ }
64
+ export function controlFieldState(control, field) {
65
+ return controlFieldFacts(control).find((candidate) => candidate.contract_field === field).state;
66
+ }
@@ -0,0 +1 @@
1
+ export type DeliveryControlFieldNameV2 = "surface" | "region" | "location" | "control_type" | "label_content" | "user_task" | "visibility" | "availability" | "trigger" | "input" | "validation" | "default_value" | "interaction" | "navigation_result" | "loading_state" | "empty_state" | "success_state" | "failure_state" | "recovery" | "permission" | "feedback" | "accessibility";
@@ -0,0 +1 @@
1
+ export {};
@@ -54,4 +54,11 @@ function validateExpectedAssertions(control, check, unknownPrefix) {
54
54
  for (const key of control.expected_assertion_failures)
55
55
  if (!assertions.has(key))
56
56
  throw new Error(`${unknownPrefix}:${key}`);
57
+ const failures = new Set(control.expected_assertion_failures);
58
+ for (const key of control.preserved_assertions) {
59
+ if (!assertions.has(key))
60
+ throw new Error(`${unknownPrefix}:${key}`);
61
+ if (failures.has(key))
62
+ throw new Error(`counterfactual_preserved_assertion_conflict:${unknownPrefix}:${key}`);
63
+ }
57
64
  }