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
@@ -26,7 +26,7 @@ export async function designResource(args) {
26
26
  console.log(`Acceptance blockers: ${result.counts.acceptance_blockers}`);
27
27
  }
28
28
  function help() {
29
- console.log(`ty-context design-resource commands:
30
- preflight <handoff.md> [--json]
29
+ console.log(`ty-context design-resource commands:
30
+ preflight <handoff.md> [--json]
31
31
  Validate one selected implementation handoff`);
32
32
  }
@@ -36,32 +36,32 @@ export const commands = {
36
36
  package: packageSource,
37
37
  };
38
38
  export function help() {
39
- console.log(`ty-context commands:
40
- init [--adopt] [--harness-folder <path>]
41
- Initialize/adopt a project; without --harness-folder, choose target agent first
42
- enable long-task Install Long-Task Skill, Source Plan pointer, Stop Hook and templates
43
- disable long-task Remove only package-owned long-task profile assets
44
- sync Refresh managed assets; does not run migrations
45
- upgrade [--check] [--json]
46
- Run safe migrations, sync managed assets and doctor
47
- doctor Diagnose project configuration and drift
48
- check-modularity --touched|--file <path>|--base <ref> [--limit 300] [--fail-on-warning]
49
- Warn when selected handwritten source files exceed a line-count limit
50
- export-context --full|--code|--all|--source-pack|--code-index|--task-context
51
- Export temporary Context, code snapshot or bounded Source Pack artifacts
52
- validate <gate> Run a Harness validation gate
53
- validate-context Validate Minimal Context fact-source recoverability
54
- validate-code-modularity
55
- Enforce touched handwritten source file modularity
56
- validate-harness Run validate-context and validate-code-modularity
57
- design-resource <subcommand>
58
- Validate a selected design-resource implementation handoff
59
- long-task <subcommand>
60
- Manage one Canonical Delivery Contract in the current workspace
61
- delivery-set <subcommand>
62
- Retired; use one complete Contract with semantic Outcomes
63
- composite-long-task Retired command; use ty-context long-task
64
- composite-campaign Retired command; use ty-context long-task
39
+ console.log(`ty-context commands:
40
+ init [--adopt] [--harness-folder <path>]
41
+ Initialize/adopt a project; without --harness-folder, choose target agent first
42
+ enable long-task Install Long-Task Skill, Source Plan pointer, Stop Hook and templates
43
+ disable long-task Remove only package-owned long-task profile assets
44
+ sync Refresh managed assets; does not run migrations
45
+ upgrade [--check] [--json]
46
+ Run safe migrations, sync managed assets and doctor
47
+ doctor Diagnose project configuration and drift
48
+ check-modularity --touched|--file <path>|--base <ref> [--limit 300] [--fail-on-warning]
49
+ Warn when selected handwritten source files exceed a line-count limit
50
+ export-context --full|--code|--all|--source-pack|--code-index|--task-context
51
+ Export temporary Context, code snapshot or bounded Source Pack artifacts
52
+ validate <gate> Run a Harness validation gate
53
+ validate-context Validate Minimal Context fact-source recoverability
54
+ validate-code-modularity
55
+ Enforce touched handwritten source file modularity
56
+ validate-harness Run validate-context and validate-code-modularity
57
+ design-resource <subcommand>
58
+ Validate a selected design-resource implementation handoff
59
+ long-task <subcommand>
60
+ Manage one Canonical Delivery Contract in the current workspace
61
+ delivery-set <subcommand>
62
+ Retired; use one complete Contract with semantic Outcomes
63
+ composite-long-task Retired command; use ty-context long-task
64
+ composite-campaign Retired command; use ty-context long-task
65
65
  package <subcommand> Maintain package canonical source`);
66
66
  }
67
67
  async function withLongTaskProfile(args, handler) {
@@ -39,8 +39,10 @@ task:
39
39
  role: product
40
40
  runtime_family: process
41
41
  root_entrypoint: tests/replace-oracle.mjs
42
+ capabilities: [process-runtime, cold-start, production-root]
42
43
  source_paths: [plans/replace-me.md]
43
44
  context_refs: [project_context/areas/replace-me.md]
45
+ context_snapshot_mode: full
44
46
  source_claims:
45
47
  - key: replace-requirement
46
48
  source_ref: plans/replace-me.md#replace-requirement
@@ -48,6 +50,12 @@ source_claims:
48
50
  disposition:
49
51
  type: claim
50
52
  refs: [replace-outcome.requirement.replace-requirement]
53
+ - key: replace-architecture
54
+ source_ref: plans/replace-me.md#replace-architecture
55
+ statement: Preserve the declared owner, dependency direction, verifier boundary and architecture conformance.
56
+ disposition:
57
+ type: claim
58
+ refs: [replace-outcome.obligation.architecture]
51
59
  stages:
52
60
  - key: delivery
53
61
  title: Delivery
@@ -55,13 +63,22 @@ stages:
55
63
  gate_outcome: replace-outcome
56
64
  risk:
57
65
  facts: {}
58
- global: {}
66
+ global:
67
+ applicability: []
59
68
  outcomes:
60
69
  - key: replace-outcome
61
70
  title: Replace outcome
62
71
  stage: delivery
72
+ applicability:
73
+ - key: root-success
74
+ target_ref: replace-runtime
75
+ journey_role: success
76
+ dimensions: [{key: delivery-state, value: ready}]
77
+ given_refs: [source-ready]
78
+ when_refs: [inspect-result]
63
79
  product:
64
80
  observable_result: Describe what a user or system can observe.
81
+ result_applicability_refs: [root-success]
65
82
  success_path_required: true
66
83
  degradation_path_required: false
67
84
  owner:
@@ -72,7 +89,17 @@ outcomes:
72
89
  - key: replace-requirement
73
90
  statement: Preserve one atomic source requirement.
74
91
  required_proof_surfaces: [runtime_behavior]
92
+ applicability_refs: [root-success]
93
+ control_relation_closure:
94
+ state: not_applicable
95
+ statement: This Outcome declares no user-visible Controls.
96
+ applicability_refs: [root-success]
75
97
  technical:
98
+ obligations:
99
+ - key: architecture
100
+ statement: Preserve the declared owner, dependency direction, verifier boundary and architecture conformance.
101
+ required_proof_surfaces: [runtime_behavior]
102
+ applicability_refs: [root-success]
76
103
  expected_change_paths: ["src/**"]
77
104
  bindings:
78
105
  - key: replace-carrier
@@ -97,21 +124,68 @@ outcomes:
97
124
  input_paths: [src/replace-me.ts]
98
125
  expected_output_paths: [src/replace-me.ts]
99
126
  positive_assertions:
100
- - key: replace-success
101
- criterion: The declared outcome and requirement are observable.
102
- claims: [result, requirement.replace-requirement]
127
+ - key: replace-result
128
+ criterion: The declared outcome is observable.
129
+ claims: [result]
130
+ applicability_ref: root-success
103
131
  observation: result
104
132
  evidence_capabilities: [state_delta, target_runtime]
105
133
  operator: equals
106
134
  expected: true
135
+ - key: replace-requirement
136
+ criterion: The atomic Source requirement is observable.
137
+ claims: [requirement.replace-requirement]
138
+ applicability_ref: root-success
139
+ observation: requirement_result
140
+ evidence_capabilities: [state_delta, target_runtime]
141
+ operator: equals
142
+ expected: true
143
+ - key: replace-architecture
144
+ criterion: The declared architecture obligation remains conformant.
145
+ claims: [obligation.architecture]
146
+ applicability_ref: root-success
147
+ observation: architecture_result
148
+ evidence_capabilities: [state_delta, target_runtime]
149
+ operator: equals
150
+ expected: true
151
+ - key: replace-liveness
152
+ criterion: The declared target remains live under semantic mutation.
153
+ claims: []
154
+ observation: target_live
155
+ evidence_capabilities: [target_runtime]
156
+ operator: equals
157
+ expected: true
158
+ negative_assertions:
159
+ - key: replace-relations-na
160
+ criterion: Cross-Control relations remain inapplicable when no Controls are declared.
161
+ claims: [control_relation_closure]
162
+ applicability_ref: root-success
163
+ observation: relations_applicable
164
+ evidence_capabilities: [state_delta, target_runtime]
165
+ operator: equals
166
+ expected: false
107
167
  counterfactual_controls:
108
- - key: remove-replace-carrier
168
+ - key: replace-semantic-carrier
169
+ binding_key: replace-carrier
170
+ claims: [result, requirement.replace-requirement, obligation.architecture]
171
+ check_key: replace-check
172
+ mutation:
173
+ type: replace_text
174
+ path: src/replace-me.ts
175
+ match: IMPLEMENTED_STATE
176
+ replacement: SEMANTIC_FAILURE_STATE
177
+ expected_assertion_failures: [replace-result, replace-requirement, replace-architecture]
178
+ preserved_assertions: [replace-liveness]
179
+ - key: replace-relation-applicability
109
180
  binding_key: replace-carrier
110
- claims: [result, requirement.replace-requirement]
181
+ claims: [control_relation_closure]
111
182
  check_key: replace-check
112
183
  mutation:
113
- type: remove_paths
114
- paths: [src/replace-me.ts]
115
- expected_assertion_failures: [replace-success]
184
+ type: replace_text
185
+ path: src/replace-me.ts
186
+ match: NO_CROSS_CONTROL_RELATIONS
187
+ replacement: CROSS_CONTROL_RELATIONS_APPLY
188
+ expected_assertion_failures: [replace-relations-na]
189
+ preserved_assertions: [replace-liveness]
116
190
  `;
117
191
  }
@@ -124,20 +124,20 @@ async function finalGate(workdir, args) {
124
124
  process.exitCode = 1;
125
125
  }
126
126
  function help() {
127
- console.log(`ty-context long-task commands:
128
- init <workdir>
129
- preflight <workdir>
130
- compile <workdir>
131
- compile <workdir> --revise
132
- diagnose-revision <workdir> [--outcome <key>] [--check <key>]
133
- approve-authority-revision <workdir> --revision <sha>
134
- explain <workdir>
135
- verify <workdir> [--outcome <key>] [--check <key>] [--explain]
136
- status <workdir>
137
- resume <workdir>
138
- doctor <workdir>
139
- final-gate <workdir>
140
- stop-check <workdir> [--message <text>]
141
- close <workdir>
127
+ console.log(`ty-context long-task commands:
128
+ init <workdir>
129
+ preflight <workdir>
130
+ compile <workdir>
131
+ compile <workdir> --revise
132
+ diagnose-revision <workdir> [--outcome <key>] [--check <key>]
133
+ approve-authority-revision <workdir> --revision <sha>
134
+ explain <workdir>
135
+ verify <workdir> [--outcome <key>] [--check <key>] [--explain]
136
+ status <workdir>
137
+ resume <workdir>
138
+ doctor <workdir>
139
+ final-gate <workdir>
140
+ stop-check <workdir> [--message <text>]
141
+ close <workdir>
142
142
  abandon <workdir> [--force-corrupt-state]`);
143
143
  }
@@ -15,6 +15,13 @@ export async function captureContextGraphSnapshot(repositoryRoot, contextRefs, m
15
15
  const explicitlySelected = new Set();
16
16
  if (mode === "full") {
17
17
  allFiles.forEach((file) => selected.add(file));
18
+ for (const contextRef of contextRefs) {
19
+ const normalized = normalizeRepoPath(contextRef);
20
+ if (!available.has(normalized)) {
21
+ throw new Error(`context_ref_invalid:${contextRef}`);
22
+ }
23
+ explicitlySelected.add(normalized);
24
+ }
18
25
  }
19
26
  else {
20
27
  for (const required of [
@@ -1,6 +1,7 @@
1
1
  import { DESIGN_RESOURCE_DIMENSIONS, DESIGN_RESOURCE_EVIDENCE_KINDS, DESIGN_RESOURCE_LOCATOR_KINDS, } from "./design-resource-handoff-types.js";
2
2
  import { contractKey, contractKeys, sourceItemKeys, stableKey, stableKeys, verificationMethods, } from "./design-resource-handoff-shape-primitives.js";
3
3
  import { array, literal, object, string, } from "./long-task-shape-primitives.js";
4
+ import { EXECUTION_TARGET_CAPABILITIES } from "./execution-target-capabilities.js";
4
5
  export function parseDesignResourceHandoffEvidence(value) {
5
6
  return array(value, "design_resource_handoff.evidence").map((item, index) => {
6
7
  const label = `design_resource_handoff.evidence[${index}]`;
@@ -69,6 +70,7 @@ export function parseDesignResourceHandoffBlockers(value) {
69
70
  "dimensions",
70
71
  "source_item_refs",
71
72
  "verification_methods",
73
+ "required_capabilities",
72
74
  "description",
73
75
  ]);
74
76
  return {
@@ -78,6 +80,7 @@ export function parseDesignResourceHandoffBlockers(value) {
78
80
  dimensions: array(row.dimensions, `${label}.dimensions`).map((dimension, itemIndex) => literal(dimension, DESIGN_RESOURCE_DIMENSIONS, `${label}.dimensions[${itemIndex}]`)),
79
81
  source_item_refs: sourceItemKeys(row.source_item_refs, `${label}.source_item_refs`),
80
82
  verification_methods: verificationMethods(row.verification_methods, `${label}.verification_methods`),
83
+ required_capabilities: array(row.required_capabilities, `${label}.required_capabilities`).map((capability, capabilityIndex) => literal(capability, EXECUTION_TARGET_CAPABILITIES, `${label}.required_capabilities[${capabilityIndex}]`)),
81
84
  description: string(row.description, `${label}.description`),
82
85
  };
83
86
  });
@@ -1,3 +1,4 @@
1
+ import type { ExecutionTargetCapabilityV2 } from "./execution-target-capabilities.js";
1
2
  export declare const DESIGN_RESOURCE_DIMENSIONS: readonly ["surface_flow", "visual_content", "component_control", "state_interaction", "motion", "adaptation_input", "accessibility", "assets"];
2
3
  export type DesignResourceDimension = (typeof DESIGN_RESOURCE_DIMENSIONS)[number];
3
4
  export declare const DESIGN_RESOURCE_EVIDENCE_KINDS: readonly ["frame", "component_variant", "prototype_state", "prototype_transition", "motion_spec", "motion_capture", "responsive_spec", "input_spec", "accessibility_spec", "semantic_tree", "token_spec", "asset", "annotation"];
@@ -115,6 +116,7 @@ export interface DesignResourceHandoffBlockerV1 {
115
116
  dimensions: DesignResourceDimension[];
116
117
  source_item_refs: string[];
117
118
  verification_methods: DesignResourceVerificationMethod[];
119
+ required_capabilities: ExecutionTargetCapabilityV2[];
118
120
  description: string;
119
121
  }
120
122
  export interface ParsedDesignResourceHandoffV1 {
@@ -80,6 +80,7 @@ export function validateDesignResourceBlockers(handoff, subjects, targets, sourc
80
80
  ["dimensions", blocker.dimensions],
81
81
  ["source_item_refs", blocker.source_item_refs],
82
82
  ["verification_methods", blocker.verification_methods],
83
+ ["required_capabilities", blocker.required_capabilities],
83
84
  ]) {
84
85
  requireNonemptyDesignResourceValues(values, `acceptance_blocker_${name}_required:${blocker.key}`);
85
86
  requireUniqueDesignResourceValues(values, `acceptance_blocker_${name}_duplicate:${blocker.key}`);
@@ -17,6 +17,8 @@ export function validateDesignResourceConditions(handoff) {
17
17
  ]) {
18
18
  requireNonemptyDesignResourceValues(values, `condition_${name}_required:${condition.key}`);
19
19
  requireUniqueDesignResourceValues(values, `condition_${name}_duplicate:${condition.key}`);
20
+ if (values.length !== 1)
21
+ invalidDesignResourceHandoff(`condition_${name}_must_be_atomic`, condition.key);
20
22
  }
21
23
  }
22
24
  }
@@ -0,0 +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"];
2
+ export type ExecutionTargetCapabilityV2 = (typeof EXECUTION_TARGET_CAPABILITIES)[number];
@@ -0,0 +1,31 @@
1
+ export const EXECUTION_TARGET_CAPABILITIES = [
2
+ "browser-runtime",
3
+ "native-runtime",
4
+ "desktop-runtime",
5
+ "service-runtime",
6
+ "process-runtime",
7
+ "external-runtime",
8
+ "cold-start",
9
+ "production-root",
10
+ "pointer-input",
11
+ "keyboard-input",
12
+ "touch-input",
13
+ "viewport-control",
14
+ "pixel-density-observation",
15
+ "safe-area-observation",
16
+ "motion-observation",
17
+ "reduced-motion",
18
+ "color-scheme-control",
19
+ "text-scale-control",
20
+ "assistive-technology",
21
+ "screen-reader",
22
+ "physical-device",
23
+ "device-orientation",
24
+ "sensor-input",
25
+ "camera-input",
26
+ "haptic-output",
27
+ "thermal-observation",
28
+ "power-mode-control",
29
+ "persistent-storage",
30
+ "network-boundary",
31
+ ];
@@ -10,25 +10,32 @@ export function parseCounterfactuals(value, label) {
10
10
  "check_key",
11
11
  "mutation",
12
12
  "expected_assertion_failures",
13
+ ], ["preserved_assertions"]);
14
+ const mutation = object(row.mutation, `${itemLabel}.mutation`, ["type"], [
15
+ "paths",
16
+ "path",
17
+ "fixture_path",
18
+ "pointer",
19
+ "value",
20
+ "match",
21
+ "replacement",
13
22
  ]);
14
- const mutation = object(row.mutation, `${itemLabel}.mutation`, ["type"], ["paths", "path", "fixture_path"]);
15
- const type = literal(mutation.type, ["remove_paths", "replace_file"], `${itemLabel}.mutation.type`);
23
+ const type = literal(mutation.type, [
24
+ "remove_paths",
25
+ "replace_file",
26
+ "replace_json_value",
27
+ "replace_text",
28
+ ], `${itemLabel}.mutation.type`);
16
29
  return {
17
30
  key: key(row.key, `${itemLabel}.key`),
18
31
  binding_key: key(row.binding_key, `${itemLabel}.binding_key`),
19
32
  claims: strings(row.claims, `${itemLabel}.claims`),
20
33
  check_key: key(row.check_key, `${itemLabel}.check_key`),
21
- mutation: type === "remove_paths"
22
- ? {
23
- type,
24
- paths: repositoryFiles(mutation.paths, `${itemLabel}.mutation.paths`),
25
- }
26
- : {
27
- type,
28
- path: repositoryFile(mutation.path, `${itemLabel}.mutation.path`),
29
- fixture_path: repositoryFile(mutation.fixture_path, `${itemLabel}.mutation.fixture_path`),
30
- },
34
+ mutation: parseCounterfactualMutation(row.mutation, `${itemLabel}.mutation`),
31
35
  expected_assertion_failures: strings(row.expected_assertion_failures, `${itemLabel}.expected_assertion_failures`).map((item, assertionIndex) => key(item, `${itemLabel}.expected_assertion_failures[${assertionIndex}]`)),
36
+ preserved_assertions: Object.hasOwn(row, "preserved_assertions")
37
+ ? strings(row.preserved_assertions, `${itemLabel}.preserved_assertions`).map((item, assertionIndex) => key(item, `${itemLabel}.preserved_assertions[${assertionIndex}]`))
38
+ : [],
32
39
  };
33
40
  });
34
41
  }
@@ -42,7 +49,7 @@ export function parseGlobalCounterfactuals(value, label) {
42
49
  "check_key",
43
50
  "mutation",
44
51
  "expected_assertion_failures",
45
- ]);
52
+ ], ["preserved_assertions"]);
46
53
  const bindingRef = string(row.binding_ref, `${itemLabel}.binding_ref`);
47
54
  if (!/^[a-z0-9][a-z0-9-]*\.[a-z0-9][a-z0-9-]*$/u.test(bindingRef))
48
55
  fail(`${itemLabel}.binding_ref`, "must be <outcome-key>.<binding-key>");
@@ -59,39 +66,93 @@ export function parseGlobalCounterfactuals(value, label) {
59
66
  check_key: key(row.check_key, `${itemLabel}.check_key`),
60
67
  mutation: parseCounterfactualMutation(row.mutation, `${itemLabel}.mutation`),
61
68
  expected_assertion_failures: failures,
69
+ preserved_assertions: Object.hasOwn(row, "preserved_assertions")
70
+ ? strings(row.preserved_assertions, `${itemLabel}.preserved_assertions`).map((entry, assertionIndex) => key(entry, `${itemLabel}.preserved_assertions[${assertionIndex}]`))
71
+ : [],
62
72
  };
63
73
  });
64
74
  }
65
75
  function parseCounterfactualMutation(value, label) {
66
- const mutation = object(value, label, ["type"], ["paths", "path", "fixture_path"]);
67
- const type = literal(mutation.type, ["remove_paths", "replace_file"], `${label}.type`);
68
- return type === "remove_paths"
69
- ? {
76
+ const mutation = object(value, label, ["type"], [
77
+ "paths",
78
+ "path",
79
+ "fixture_path",
80
+ "pointer",
81
+ "value",
82
+ "match",
83
+ "replacement",
84
+ ]);
85
+ const type = literal(mutation.type, [
86
+ "remove_paths",
87
+ "replace_file",
88
+ "replace_json_value",
89
+ "replace_text",
90
+ ], `${label}.type`);
91
+ if (type === "remove_paths")
92
+ return {
70
93
  type,
71
94
  paths: repositoryFiles(mutation.paths, `${label}.paths`),
72
- }
73
- : {
95
+ };
96
+ const target = repositoryFile(mutation.path, `${label}.path`);
97
+ if (type === "replace_file")
98
+ return {
74
99
  type,
75
- path: repositoryFile(mutation.path, `${label}.path`),
100
+ path: target,
76
101
  fixture_path: repositoryFile(mutation.fixture_path, `${label}.fixture_path`),
77
102
  };
103
+ if (type === "replace_json_value") {
104
+ const pointer = string(mutation.pointer, `${label}.pointer`);
105
+ if (!/^\/(?:[^~/]|~[01])+(?:\/(?:[^~/]|~[01])+)*$/u.test(pointer))
106
+ fail(`${label}.pointer`, "must be a non-root RFC 6901 JSON pointer");
107
+ if (!Object.hasOwn(mutation, "value"))
108
+ fail(`${label}.value`, "must be present");
109
+ assertJsonValue(mutation.value, `${label}.value`);
110
+ return { type, path: target, pointer, value: mutation.value };
111
+ }
112
+ const match = string(mutation.match, `${label}.match`);
113
+ const replacement = typeof mutation.replacement === "string"
114
+ ? mutation.replacement
115
+ : fail(`${label}.replacement`, "must be a string");
116
+ if (match === replacement)
117
+ fail(`${label}.replacement`, "must differ from match");
118
+ return { type, path: target, match, replacement };
119
+ }
120
+ function assertJsonValue(value, label) {
121
+ if (value === undefined ||
122
+ typeof value === "function" ||
123
+ typeof value === "symbol" ||
124
+ typeof value === "bigint")
125
+ fail(label, "must be JSON-compatible");
126
+ try {
127
+ const encoded = JSON.stringify(value);
128
+ if (encoded === undefined)
129
+ fail(label, "must be JSON-compatible");
130
+ JSON.parse(encoded);
131
+ }
132
+ catch {
133
+ fail(label, "must be JSON-compatible");
134
+ }
78
135
  }
79
136
  export function parsePopulation(value, label) {
80
137
  const row = object(value, label, [
81
138
  "check_key",
139
+ "universe_binding_key",
82
140
  "claims",
83
141
  "observations",
84
142
  "exclusion_rules",
85
143
  ]);
86
144
  const observations = object(row.observations, `${label}.observations`, [
145
+ "universe_ids",
87
146
  "eligible_ids",
88
147
  "observed_ids",
89
148
  "excluded_items",
90
149
  ]);
91
150
  return {
92
151
  check_key: key(row.check_key, `${label}.check_key`),
152
+ universe_binding_key: key(row.universe_binding_key, `${label}.universe_binding_key`),
93
153
  claims: strings(row.claims, `${label}.claims`),
94
154
  observations: {
155
+ universe_ids: string(observations.universe_ids, `${label}.observations.universe_ids`),
95
156
  eligible_ids: string(observations.eligible_ids, `${label}.observations.eligible_ids`),
96
157
  observed_ids: string(observations.observed_ids, `${label}.observations.observed_ids`),
97
158
  excluded_items: string(observations.excluded_items, `${label}.observations.excluded_items`),
@@ -0,0 +1,4 @@
1
+ import type { ApplicableKeyedStatementV2, ClaimApplicabilityV2 } from "./long-task-semantic-contract-types.js";
2
+ export declare function parseClaimApplicability(value: unknown, label: string): ClaimApplicabilityV2[];
3
+ export declare function parseApplicableKeyedStatements(value: unknown, label: string): ApplicableKeyedStatementV2[];
4
+ export declare function parseKeyRefs(value: unknown, label: string): string[];
@@ -0,0 +1,54 @@
1
+ import { array, key, literal, object, string, strings, } from "./long-task-shape-primitives.js";
2
+ const JOURNEY_ROLES = [
3
+ "success",
4
+ "degradation",
5
+ "recovery",
6
+ "stage_gate",
7
+ "conformance",
8
+ ];
9
+ export function parseClaimApplicability(value, label) {
10
+ return array(value, label).map((item, index) => {
11
+ const itemLabel = `${label}[${index}]`;
12
+ const row = object(item, itemLabel, [
13
+ "key",
14
+ "target_ref",
15
+ "journey_role",
16
+ "dimensions",
17
+ "given_refs",
18
+ "when_refs",
19
+ ]);
20
+ return {
21
+ key: key(row.key, `${itemLabel}.key`),
22
+ target_ref: key(row.target_ref, `${itemLabel}.target_ref`),
23
+ journey_role: literal(row.journey_role, JOURNEY_ROLES, `${itemLabel}.journey_role`),
24
+ dimensions: array(row.dimensions, `${itemLabel}.dimensions`).map((dimension, dimensionIndex) => {
25
+ const dimensionLabel = `${itemLabel}.dimensions[${dimensionIndex}]`;
26
+ const entry = object(dimension, dimensionLabel, ["key", "value"]);
27
+ return {
28
+ key: key(entry.key, `${dimensionLabel}.key`),
29
+ value: key(entry.value, `${dimensionLabel}.value`),
30
+ };
31
+ }),
32
+ given_refs: parseKeyRefs(row.given_refs, `${itemLabel}.given_refs`),
33
+ when_refs: parseKeyRefs(row.when_refs, `${itemLabel}.when_refs`),
34
+ };
35
+ });
36
+ }
37
+ export function parseApplicableKeyedStatements(value, label) {
38
+ return array(value, label).map((item, index) => {
39
+ const itemLabel = `${label}[${index}]`;
40
+ const row = object(item, itemLabel, [
41
+ "key",
42
+ "statement",
43
+ "applicability_refs",
44
+ ]);
45
+ return {
46
+ key: key(row.key, `${itemLabel}.key`),
47
+ statement: string(row.statement, `${itemLabel}.statement`),
48
+ applicability_refs: parseKeyRefs(row.applicability_refs, `${itemLabel}.applicability_refs`),
49
+ };
50
+ });
51
+ }
52
+ export function parseKeyRefs(value, label) {
53
+ return strings(value, label).map((item, index) => key(item, `${label}[${index}]`));
54
+ }
@@ -77,14 +77,18 @@ export function evaluateDeliveryAssertionDetailed(assertion, observations) {
77
77
  return result(comparison.passed, expected, value);
78
78
  }
79
79
  export function evaluatePopulation(requirement, observations) {
80
+ const universe = observationValue(observations, requirement.observations.universe_ids).value;
80
81
  const eligible = observationValue(observations, requirement.observations.eligible_ids).value;
81
82
  const observed = observationValue(observations, requirement.observations.observed_ids).value;
82
83
  const excluded = observationValue(observations, requirement.observations.excluded_items).value;
83
84
  const actual = {
85
+ universe_ids: universe,
84
86
  eligible_ids: eligible,
85
87
  observed_ids: observed,
86
88
  excluded_items: excluded,
87
89
  };
90
+ if (!validIds(universe))
91
+ return failure(actual, "universe_ids_invalid");
88
92
  if (!validIds(eligible))
89
93
  return failure(actual, "eligible_ids_invalid");
90
94
  if (!validIds(observed))
@@ -92,6 +96,10 @@ export function evaluatePopulation(requirement, observations) {
92
96
  if (!Array.isArray(excluded))
93
97
  return failure(actual, "excluded_items_invalid");
94
98
  const eligibleSet = new Set(eligible);
99
+ const universeSet = new Set(universe);
100
+ if (universeSet.size !== eligibleSet.size ||
101
+ [...universeSet].some((id) => !eligibleSet.has(id)))
102
+ return failure(actual, "eligible_universe_mismatch");
95
103
  const observedSet = new Set(observed);
96
104
  const excludedIds = [];
97
105
  const rules = new Set(requirement.exclusion_rules.map((item) => item.key));
@@ -147,6 +147,10 @@ function diagnosticRefs(code, message) {
147
147
  case "global_claim_uncovered":
148
148
  case "source_claim_decision_required":
149
149
  return payload.flatMap((value) => value.split(",")).filter(Boolean);
150
+ case "product_claim_required_surfaces_missing":
151
+ return payload.length >= 2
152
+ ? [`${payload[0]}.${payload[1]}`, ...payload.slice(2)]
153
+ : payload;
150
154
  case "assertion_criterion_required":
151
155
  return payload.length ? [payload.join(":")] : [];
152
156
  default:
@@ -166,6 +170,7 @@ function diagnosticRepairHint(code) {
166
170
  case "forbidden_shortcut_key_duplicate":
167
171
  return "Remove an accidental duplicate or assign distinct stable keys while preserving each distinct semantic item.";
168
172
  case "product_claim_uncovered":
173
+ case "product_claim_required_surfaces_missing":
169
174
  case "global_claim_uncovered":
170
175
  return "Add claim-bearing Assertion coverage for every required proof surface or correct the Claim mapping; do not weaken or delete the uncovered Claim.";
171
176
  case "assertion_criterion_required":
@@ -7,6 +7,7 @@ const STRUCTURAL_BLOCKERS = new Set([
7
7
  ]);
8
8
  const COVERAGE_FOLLOW_UPS = new Set([
9
9
  "product_claim_uncovered",
10
+ "product_claim_required_surfaces_missing",
10
11
  "global_claim_uncovered",
11
12
  ]);
12
13
  /**
@@ -83,6 +84,8 @@ function repairEntity(diagnostic) {
83
84
  return scopedClaim(refs, "forbidden_shortcut");
84
85
  case "product_claim_uncovered":
85
86
  return refs.length === 1 ? refs[0] : null;
87
+ case "product_claim_required_surfaces_missing":
88
+ return (refs.find((ref) => /^[a-z0-9][a-z0-9-]*\.(?:result|requirement\.|control\.|control_relation\.|non_completing\.|obligation\.|forbidden_shortcut\.)/u.test(ref)) ?? null);
86
89
  case "global_claim_uncovered":
87
90
  return refs.length === 1 ? refs[0] : null;
88
91
  default: