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.
- package/LICENSE +21 -21
- package/README.md +401 -395
- package/assets/README.md +628 -549
- package/assets/README.zh-CN.md +345 -339
- package/assets/agents/.gitkeep +1 -1
- package/assets/agents/AGENTS_CORE.md +70 -70
- package/assets/context_templates/architecture.md +28 -28
- package/assets/context_templates/area.md +34 -34
- package/assets/context_templates/context.toml +30 -30
- package/assets/context_templates/deployment.md +35 -35
- package/assets/context_templates/global.md +57 -57
- package/assets/context_templates/product-surface-contract.md +70 -70
- package/assets/context_templates/screen-contract.md +189 -189
- package/assets/context_templates/verification.md +32 -32
- package/assets/github/.gitkeep +1 -1
- package/assets/github/harness.yml +39 -39
- package/assets/make/.gitkeep +1 -1
- package/assets/make/ty-context.mk +48 -48
- package/assets/skills/context_development_engineer/SKILL.md +137 -137
- 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 +88 -88
- package/assets/skills/context_surface_contract/SKILL.md +191 -191
- package/assets/skills/context_uiux_design/SKILL.md +172 -172
- package/assets/skills/design-resource-authoring/SKILL.md +85 -85
- package/assets/skills/design-resource-authoring/references/downstream-handoff.md +136 -136
- package/assets/skills/design-resource-authoring/references/open-design-provider.md +135 -135
- package/assets/skills/design-resource-authoring/references/resource-selection.md +173 -173
- 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 +100 -100
- package/assets/skills/long-task-workflow/references/authority-lifecycle.md +75 -73
- package/assets/skills/long-task-workflow/references/contract-authoring.md +119 -115
- package/assets/skills/long-task-workflow/references/evidence-design.md +77 -76
- package/assets/skills/long-task-workflow/references/source-authoring.md +102 -99
- package/assets/skills/source-plan-authoring/SKILL.md +14 -14
- package/assets/tools/validate_context.py +442 -442
- package/dist/commands/design-resource.js +2 -2
- package/dist/commands/index.js +26 -26
- package/dist/commands/long-task-authoring.js +83 -9
- package/dist/commands/long-task.js +15 -15
- package/dist/lib/context-graph-snapshot.js +7 -0
- package/dist/lib/design-resource-handoff-shape-evidence.js +3 -0
- package/dist/lib/design-resource-handoff-types.d.ts +2 -0
- package/dist/lib/design-resource-handoff-validation-coverage.js +1 -0
- package/dist/lib/design-resource-handoff-validation-structure.js +2 -0
- package/dist/lib/execution-target-capabilities.d.ts +2 -0
- package/dist/lib/execution-target-capabilities.js +31 -0
- package/dist/lib/long-task-acceptance-shape.js +81 -20
- package/dist/lib/long-task-applicability-shape.d.ts +4 -0
- package/dist/lib/long-task-applicability-shape.js +54 -0
- package/dist/lib/long-task-assertions-v2.js +8 -0
- package/dist/lib/long-task-authoring-preflight-diagnostics.js +5 -0
- package/dist/lib/long-task-authoring-preflight-repair-order.js +3 -0
- package/dist/lib/long-task-authoring-preflight.js +12 -8
- package/dist/lib/long-task-authority-materials.js +46 -4
- package/dist/lib/long-task-authority-policy.d.ts +54 -0
- package/dist/lib/long-task-authority-policy.js +61 -0
- package/dist/lib/long-task-authority-types.d.ts +12 -2
- package/dist/lib/long-task-authority.js +9 -2
- package/dist/lib/long-task-check-shape.js +6 -1
- package/dist/lib/long-task-claim-definitions.js +27 -42
- package/dist/lib/long-task-claims.js +275 -146
- package/dist/lib/long-task-contract-types.d.ts +42 -8
- package/dist/lib/long-task-control-fields.d.ts +12 -0
- package/dist/lib/long-task-control-fields.js +66 -0
- package/dist/lib/long-task-control-types.d.ts +1 -0
- package/dist/lib/long-task-control-types.js +1 -0
- package/dist/lib/long-task-counterfactual-claim-policy.js +7 -0
- package/dist/lib/long-task-counterfactual-types.d.ts +12 -0
- package/dist/lib/long-task-delivery-compiler.js +1 -0
- package/dist/lib/long-task-delivery-preflight.js +24 -0
- package/dist/lib/long-task-delivery-shape.d.ts +1 -0
- package/dist/lib/long-task-delivery-shape.js +1 -0
- 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 +46 -0
- package/dist/lib/long-task-design-resource-handoff.js +48 -7
- package/dist/lib/long-task-evidence-capability-codec.js +37 -0
- package/dist/lib/long-task-evidence-capability-policy.js +80 -38
- package/dist/lib/long-task-evidence-capability-runtime.js +36 -0
- package/dist/lib/long-task-evidence-capability-types.d.ts +13 -1
- package/dist/lib/long-task-evidence-findings.js +3 -0
- package/dist/lib/long-task-evidence-sensitivity-policy.js +38 -0
- package/dist/lib/long-task-evidence-v2.js +7 -1
- package/dist/lib/long-task-final-integrity.d.ts +16 -0
- package/dist/lib/long-task-final-integrity.js +98 -0
- package/dist/lib/long-task-final-v2.js +17 -34
- package/dist/lib/long-task-outcome-parser.js +22 -4
- package/dist/lib/long-task-playwright-case-evidence.d.ts +2 -0
- package/dist/lib/long-task-playwright-case-evidence.js +10 -2
- package/dist/lib/long-task-playwright-evidence.d.ts +1 -0
- package/dist/lib/long-task-playwright-evidence.js +32 -0
- package/dist/lib/long-task-product-shape.d.ts +3 -1
- package/dist/lib/long-task-product-shape.js +100 -4
- package/dist/lib/long-task-requirement-shape.js +3 -0
- package/dist/lib/long-task-root-shape.js +12 -6
- package/dist/lib/long-task-runner-freeze.js +16 -0
- package/dist/lib/long-task-runtime-types.d.ts +11 -2
- package/dist/lib/long-task-semantic-assurance-policy.d.ts +4 -0
- package/dist/lib/long-task-semantic-assurance-policy.js +52 -0
- package/dist/lib/long-task-semantic-contract-types.d.ts +18 -1
- package/dist/lib/long-task-semantic-drift-migration.js +33 -2
- package/dist/lib/long-task-semantic-mutation.d.ts +7 -0
- package/dist/lib/long-task-semantic-mutation.js +81 -0
- package/dist/lib/long-task-shape-primitives.d.ts +1 -1
- package/dist/lib/long-task-shape-primitives.js +1 -0
- package/dist/lib/long-task-source-authority-types.d.ts +2 -0
- package/dist/lib/long-task-source-item-parser.d.ts +1 -1
- package/dist/lib/long-task-source-item-parser.js +150 -104
- package/dist/lib/long-task-source-markers.d.ts +12 -0
- package/dist/lib/long-task-source-markers.js +146 -0
- package/dist/lib/long-task-source-target-continuity.d.ts +1 -1
- package/dist/lib/long-task-source-target-continuity.js +80 -55
- package/dist/lib/long-task-source-target-index.js +7 -29
- package/dist/lib/long-task-status-v2.d.ts +1 -0
- package/dist/lib/long-task-status-v2.js +2 -2
- package/dist/lib/long-task-target-policy.js +20 -0
- package/dist/lib/long-task-ui-design-policy.js +27 -1
- package/dist/lib/long-task-ui-surface-shape.js +21 -1
- package/dist/lib/long-task-ui-surface-types.d.ts +7 -0
- package/dist/lib/long-task-verification-preview.d.ts +10 -0
- package/dist/lib/long-task-verifier-dependency-closure.d.ts +3 -0
- package/dist/lib/long-task-verifier-dependency-closure.js +179 -0
- package/dist/lib/long-task-verifier-v2.js +12 -2
- package/dist/lib/long-task-workspace.js +5 -1
- package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +99 -25
- package/migrations/README.md +15 -15
- package/package.json +84 -84
- 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
|
}
|
package/dist/commands/index.js
CHANGED
|
@@ -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-
|
|
101
|
-
criterion: The declared outcome
|
|
102
|
-
claims: [result
|
|
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:
|
|
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: [
|
|
181
|
+
claims: [control_relation_closure]
|
|
111
182
|
check_key: replace-check
|
|
112
183
|
mutation:
|
|
113
|
-
type:
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
15
|
-
|
|
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:
|
|
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"], [
|
|
67
|
-
|
|
68
|
-
|
|
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:
|
|
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:
|