project-tiny-context-harness 0.7.9 → 0.8.0

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 (150) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +393 -380
  3. package/assets/README.md +567 -557
  4. package/assets/README.zh-CN.md +339 -326
  5. package/assets/agents/.gitkeep +1 -1
  6. package/assets/agents/AGENTS_CORE.md +66 -64
  7. package/assets/context_templates/architecture.md +33 -33
  8. package/assets/context_templates/area.md +39 -39
  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 +52 -51
  12. package/assets/context_templates/product-surface-contract.md +70 -70
  13. package/assets/context_templates/screen-contract.md +186 -177
  14. package/assets/context_templates/verification.md +32 -32
  15. package/assets/github/.gitkeep +1 -1
  16. package/assets/github/harness.yml +41 -41
  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 +135 -131
  20. package/assets/skills/context_full_project_export/SKILL.md +70 -70
  21. package/assets/skills/context_harness_upgrade/SKILL.md +60 -60
  22. package/assets/skills/context_product_plan/SKILL.md +88 -87
  23. package/assets/skills/context_surface_contract/SKILL.md +191 -191
  24. package/assets/skills/context_uiux_design/SKILL.md +158 -154
  25. package/assets/skills/design-resource-authoring/SKILL.md +84 -79
  26. package/assets/skills/design-resource-authoring/references/downstream-handoff.md +136 -108
  27. package/assets/skills/design-resource-authoring/references/open-design-provider.md +133 -127
  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 -47
  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 -92
  34. package/assets/skills/long-task-workflow/agents/openai.yaml +4 -4
  35. package/assets/skills/long-task-workflow/references/authority-lifecycle.md +76 -59
  36. package/assets/skills/long-task-workflow/references/contract-authoring.md +116 -105
  37. package/assets/skills/long-task-workflow/references/evidence-design.md +78 -75
  38. package/assets/skills/long-task-workflow/references/source-authoring.md +101 -98
  39. package/assets/skills/normal-long-task/SKILL.md +12 -12
  40. package/assets/skills/source-plan-authoring/SKILL.md +14 -14
  41. package/assets/tools/validate_context.py +442 -442
  42. package/dist/commands/design-resource.d.ts +1 -0
  43. package/dist/commands/design-resource.js +32 -0
  44. package/dist/commands/index.js +4 -0
  45. package/dist/commands/long-task-command-args.d.ts +1 -0
  46. package/dist/commands/long-task-command-args.js +6 -0
  47. package/dist/commands/long-task-revision.js +16 -4
  48. package/dist/commands/long-task.js +12 -5
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.js +1 -0
  51. package/dist/lib/design-md.js +3 -1
  52. package/dist/lib/design-resource-handoff-file-primitives.d.ts +4 -0
  53. package/dist/lib/design-resource-handoff-file-primitives.js +14 -0
  54. package/dist/lib/design-resource-handoff-file-validation.d.ts +2 -0
  55. package/dist/lib/design-resource-handoff-file-validation.js +142 -0
  56. package/dist/lib/design-resource-handoff-parser.d.ts +3 -0
  57. package/dist/lib/design-resource-handoff-parser.js +29 -0
  58. package/dist/lib/design-resource-handoff-policy.d.ts +3 -0
  59. package/dist/lib/design-resource-handoff-policy.js +36 -0
  60. package/dist/lib/design-resource-handoff-shape-evidence.d.ts +4 -0
  61. package/dist/lib/design-resource-handoff-shape-evidence.js +84 -0
  62. package/dist/lib/design-resource-handoff-shape-primitives.d.ts +9 -0
  63. package/dist/lib/design-resource-handoff-shape-primitives.js +44 -0
  64. package/dist/lib/design-resource-handoff-shape-structure.d.ts +5 -0
  65. package/dist/lib/design-resource-handoff-shape-structure.js +118 -0
  66. package/dist/lib/design-resource-handoff-shape.d.ts +2 -0
  67. package/dist/lib/design-resource-handoff-shape.js +75 -0
  68. package/dist/lib/design-resource-handoff-types.d.ts +139 -0
  69. package/dist/lib/design-resource-handoff-types.js +46 -0
  70. package/dist/lib/design-resource-handoff-validation-coverage.d.ts +4 -0
  71. package/dist/lib/design-resource-handoff-validation-coverage.js +168 -0
  72. package/dist/lib/design-resource-handoff-validation-primitives.d.ts +11 -0
  73. package/dist/lib/design-resource-handoff-validation-primitives.js +26 -0
  74. package/dist/lib/design-resource-handoff-validation-structure.d.ts +6 -0
  75. package/dist/lib/design-resource-handoff-validation-structure.js +93 -0
  76. package/dist/lib/design-resource-handoff-validation.d.ts +3 -0
  77. package/dist/lib/design-resource-handoff-validation.js +78 -0
  78. package/dist/lib/design-resource-handoff-web-dependency-validation.d.ts +3 -0
  79. package/dist/lib/design-resource-handoff-web-dependency-validation.js +70 -0
  80. package/dist/lib/long-task-activation-validation.js +14 -2
  81. package/dist/lib/long-task-authoring-preflight-diagnostics.js +7 -0
  82. package/dist/lib/long-task-authoring-preflight.js +39 -1
  83. package/dist/lib/long-task-authority-material-diff.js +14 -0
  84. package/dist/lib/long-task-authority-materials.js +21 -0
  85. package/dist/lib/long-task-authority-policy.d.ts +33 -0
  86. package/dist/lib/long-task-authority-policy.js +36 -0
  87. package/dist/lib/long-task-authority-revision-analysis.d.ts +1 -0
  88. package/dist/lib/long-task-authority-revision-analysis.js +30 -0
  89. package/dist/lib/long-task-authority-revision-brief.d.ts +3 -0
  90. package/dist/lib/long-task-authority-revision-brief.js +74 -0
  91. package/dist/lib/long-task-authority-revision-details.js +16 -16
  92. package/dist/lib/long-task-authority-revision-diagnosis.d.ts +1 -1
  93. package/dist/lib/long-task-authority-revision-diagnosis.js +8 -0
  94. package/dist/lib/long-task-authority-revision-enforcement.js +7 -3
  95. package/dist/lib/long-task-authority-revision-summary.d.ts +3 -0
  96. package/dist/lib/long-task-authority-revision-summary.js +133 -21
  97. package/dist/lib/long-task-authority-revision-types.d.ts +19 -1
  98. package/dist/lib/long-task-authority-revision.js +5 -0
  99. package/dist/lib/long-task-authority-types.d.ts +2 -0
  100. package/dist/lib/long-task-authority.js +10 -2
  101. package/dist/lib/long-task-check-execution-policy.js +2 -0
  102. package/dist/lib/long-task-claim-definitions.js +1 -5
  103. package/dist/lib/long-task-contract-types.d.ts +2 -0
  104. package/dist/lib/long-task-counterfactual-sandbox.d.ts +7 -0
  105. package/dist/lib/long-task-counterfactual-sandbox.js +27 -1
  106. package/dist/lib/long-task-delivery-compiler.js +26 -8
  107. package/dist/lib/long-task-delivery-types.d.ts +1 -0
  108. package/dist/lib/long-task-delivery-types.js +1 -0
  109. package/dist/lib/long-task-delivery-validation.js +3 -0
  110. package/dist/lib/long-task-design-resource-handoff.d.ts +2 -0
  111. package/dist/lib/long-task-design-resource-handoff.js +177 -0
  112. package/dist/lib/long-task-evidence-capability-codec.js +19 -0
  113. package/dist/lib/long-task-evidence-capability-policy.js +4 -0
  114. package/dist/lib/long-task-evidence-capability-runtime.js +25 -0
  115. package/dist/lib/long-task-evidence-capability-types.d.ts +9 -1
  116. package/dist/lib/long-task-outcome-parser.js +11 -1
  117. package/dist/lib/long-task-paths.d.ts +0 -1
  118. package/dist/lib/long-task-paths.js +0 -4
  119. package/dist/lib/long-task-playwright-case-evidence.d.ts +43 -0
  120. package/dist/lib/long-task-playwright-case-evidence.js +152 -0
  121. package/dist/lib/long-task-playwright-evidence.js +19 -152
  122. package/dist/lib/long-task-runner-freeze.d.ts +2 -2
  123. package/dist/lib/long-task-runner-freeze.js +2 -1
  124. package/dist/lib/long-task-runtime-types.d.ts +2 -0
  125. package/dist/lib/long-task-semantic-contract-types.d.ts +1 -1
  126. package/dist/lib/long-task-semantic-drift-migration.js +6 -1
  127. package/dist/lib/long-task-shape-primitives.d.ts +1 -1
  128. package/dist/lib/long-task-shape-primitives.js +1 -0
  129. package/dist/lib/long-task-status-v2.js +12 -7
  130. package/dist/lib/long-task-ui-design-policy.d.ts +17 -0
  131. package/dist/lib/long-task-ui-design-policy.js +128 -0
  132. package/dist/lib/long-task-ui-surface-policy.d.ts +4 -0
  133. package/dist/lib/long-task-ui-surface-policy.js +109 -0
  134. package/dist/lib/long-task-ui-surface-shape.d.ts +2 -0
  135. package/dist/lib/long-task-ui-surface-shape.js +94 -0
  136. package/dist/lib/long-task-ui-surface-types.d.ts +44 -0
  137. package/dist/lib/long-task-ui-surface-types.js +1 -0
  138. package/dist/lib/long-task-ui-surface-validation.d.ts +11 -0
  139. package/dist/lib/long-task-ui-surface-validation.js +62 -0
  140. package/dist/lib/long-task-verification-preview.d.ts +55 -0
  141. package/dist/lib/long-task-verification-preview.js +120 -0
  142. package/dist/lib/long-task-verifier-v2.js +11 -18
  143. package/dist/lib/long-task-workspace-scope.d.ts +38 -0
  144. package/dist/lib/long-task-workspace-scope.js +121 -0
  145. package/dist/lib/long-task-workspace.d.ts +1 -0
  146. package/dist/lib/long-task-workspace.js +73 -9
  147. package/dist/schemas/long-task-delivery-v2/long-task-delivery-v2.schema.json +84 -2
  148. package/migrations/README.md +7 -7
  149. package/package.json +3 -3
  150. package/source-mappings.yaml +25 -25
@@ -1,3 +1,4 @@
1
+ import { collectCases, declaredCaseIds, duplicateCaseInstance, record, same, } from "./long-task-playwright-case-evidence.js";
1
2
  export function extractPlaywrightEvidence(check, report, exitCode) {
2
3
  const stats = record(report.stats);
3
4
  if (!stats)
@@ -61,6 +62,10 @@ export function extractPlaywrightEvidence(check, report, exitCode) {
61
62
  }
62
63
  }
63
64
  observations["playwright.case_ids"] = cases.map((item) => item.id).sort();
65
+ const evidenceRecords = evidenceRecordsForCases(check, cases);
66
+ return { observations, evidence_records: evidenceRecords, error: null };
67
+ }
68
+ function evidenceRecordsForCases(check, cases) {
64
69
  const evidenceRecords = [];
65
70
  for (const item of cases) {
66
71
  const assertion = [
@@ -86,127 +91,22 @@ export function extractPlaywrightEvidence(check, report, exitCode) {
86
91
  session_id: `playwright:${item.id}:${item.project_ids.join(",")}`,
87
92
  cold_start: check.execution_target.entrypoint === "root",
88
93
  });
89
- }
90
- return { observations, evidence_records: evidenceRecords, error: null };
91
- }
92
- function collectCases(report, declaredIds) {
93
- const cases = [];
94
- const collection = { unbound_unexpected_instances: 0 };
95
- const error = visitSuites(report.suites, cases, declaredIds, collection);
96
- return { cases, error, ...collection };
97
- }
98
- function visitSuites(value, cases, declaredIds, collection) {
99
- if (!Array.isArray(value))
100
- return null;
101
- for (const suiteValue of value) {
102
- const suite = record(suiteValue);
103
- if (!suite)
104
- continue;
105
- const nestedError = visitSuites(suite.suites, cases, declaredIds, collection);
106
- if (nestedError)
107
- return nestedError;
108
- if (!Array.isArray(suite.specs))
109
- continue;
110
- for (const specValue of suite.specs) {
111
- const spec = record(specValue);
112
- if (!spec || !Array.isArray(spec.tests))
113
- continue;
114
- for (const testValue of spec.tests) {
115
- const test = record(testValue);
116
- if (!test)
117
- continue;
118
- const title = [spec.title, test.title]
119
- .filter((item) => typeof item === "string")
120
- .join(" ");
121
- const ids = declaredIdsInTitle(title, declaredIds);
122
- if (ids.length > 1)
123
- return `playwright_test_multiple_ac_ids:${ids.join(",")}`;
124
- const instance = playwrightCase(ids[0] ?? "unbound", test);
125
- if (ids.length === 1)
126
- cases.push(instance);
127
- else if (instance.unexpected)
128
- collection.unbound_unexpected_instances += 1;
129
- }
94
+ if (assertion?.evidence_capabilities.includes("design_conformance") &&
95
+ item.executed) {
96
+ for (const target of (check.design_conformance_targets ?? []).filter((candidate) => candidate.conformance_assertion_ref === assertion.key ||
97
+ candidate.verification_method_bindings.some((binding) => binding.assertion_ref === assertion.key)))
98
+ evidenceRecords.push({
99
+ assertion_key: assertion.key,
100
+ capability: "design_conformance",
101
+ design_target_ref: target.key,
102
+ target_ref: target.target_ref,
103
+ condition_keys: target.condition_keys,
104
+ actual_artifact_path: target.actual_artifact_path,
105
+ comparison_artifact_path: target.comparison_artifact_path,
106
+ });
130
107
  }
131
108
  }
132
- return null;
133
- }
134
- function declaredIdsInTitle(title, declared) {
135
- const explicit = [...title.matchAll(/\[ac:([a-z0-9][a-z0-9-]*)\]/gu)].map((match) => match[1]);
136
- const legacy = [...title.matchAll(/\[([a-z0-9][a-z0-9-]*)\]/gu)].map((match) => match[1]);
137
- return [
138
- ...new Set([...explicit, ...legacy].filter((id) => declared.has(id))),
139
- ].sort();
140
- }
141
- function playwrightCase(id, test) {
142
- const status = typeof test.status === "string" ? test.status : "invalid";
143
- const projectId = typeof test.projectId === "string"
144
- ? test.projectId
145
- : typeof test.projectName === "string"
146
- ? test.projectName
147
- : "default";
148
- const results = Array.isArray(test.results)
149
- ? test.results.map(record).filter(Boolean)
150
- : [];
151
- const resultStatuses = results
152
- .map((result) => result.status)
153
- .filter((value) => typeof value === "string");
154
- const skipped = status === "skipped" ||
155
- (resultStatuses.length > 0 &&
156
- resultStatuses.every((value) => value === "skipped"));
157
- const executed = !skipped && resultStatuses.length > 0;
158
- const flaky = status === "flaky";
159
- const unexpected = status === "unexpected";
160
- const timedOut = resultStatuses.includes("timedOut");
161
- const interrupted = resultStatuses.includes("interrupted");
162
- const passed = executed &&
163
- !flaky &&
164
- !unexpected &&
165
- status === "expected" &&
166
- resultStatuses.length > 0 &&
167
- resultStatuses.at(-1) === "passed";
168
- const traces = results.map((result) => scenarioTrace(result));
169
- const givenKeys = traces[0]?.given_keys ?? [];
170
- const actionKeys = traces[0]?.action_keys ?? [];
171
- const traceConsistent = traces.every((trace) => same(trace.given_keys, givenKeys) && same(trace.action_keys, actionKeys));
172
- return {
173
- id,
174
- project_id: projectId,
175
- executed,
176
- passed,
177
- skipped,
178
- flaky,
179
- unexpected,
180
- timed_out: timedOut,
181
- interrupted,
182
- status,
183
- given_keys: traceConsistent ? givenKeys : [],
184
- action_keys: traceConsistent ? actionKeys : [],
185
- };
186
- }
187
- function declaredCaseIds(check) {
188
- const result = new Set();
189
- for (const assertion of [
190
- ...check.positive_assertions,
191
- ...check.negative_assertions,
192
- ]) {
193
- if (!assertion.claims.length)
194
- continue;
195
- const match = /^playwright\.case\.([a-z0-9][a-z0-9-]*)\.passed$/u.exec(assertion.observation);
196
- if (match)
197
- result.add(assertion.key);
198
- }
199
- return result;
200
- }
201
- function duplicateCaseInstance(values) {
202
- const seen = new Set();
203
- for (const value of values) {
204
- const identity = `${value.id}\0${value.project_id}`;
205
- if (seen.has(identity))
206
- return value;
207
- seen.add(identity);
208
- }
209
- return null;
109
+ return evidenceRecords;
210
110
  }
211
111
  function aggregateCases(instances) {
212
112
  const grouped = new Map();
@@ -271,42 +171,9 @@ function aggregateCases(instances) {
271
171
  })
272
172
  .sort((left, right) => left.id.localeCompare(right.id));
273
173
  }
274
- function record(value) {
275
- return value && typeof value === "object" && !Array.isArray(value)
276
- ? value
277
- : null;
278
- }
279
174
  function integer(value) {
280
175
  return Number.isInteger(value) && Number(value) >= 0 ? Number(value) : null;
281
176
  }
282
- function scenarioTrace(result) {
283
- const givenKeys = [];
284
- const actionKeys = [];
285
- const visit = (value) => {
286
- if (!Array.isArray(value))
287
- return;
288
- for (const item of value) {
289
- const step = record(item);
290
- if (!step)
291
- continue;
292
- if (typeof step.title === "string") {
293
- const given = /^\[given:([a-z0-9][a-z0-9-]*)\]$/u.exec(step.title);
294
- const action = /^\[action:([a-z0-9][a-z0-9-]*)\]$/u.exec(step.title);
295
- if (given)
296
- givenKeys.push(given[1]);
297
- if (action)
298
- actionKeys.push(action[1]);
299
- }
300
- visit(step.steps);
301
- }
302
- };
303
- visit(result.steps);
304
- return { given_keys: givenKeys, action_keys: actionKeys };
305
- }
306
- function same(left, right) {
307
- return (left.length === right.length &&
308
- left.every((value, index) => value === right[index]));
309
- }
310
177
  function invalid(error) {
311
178
  return { observations: {}, evidence_records: [], error };
312
179
  }
@@ -1,2 +1,2 @@
1
- import type { CompiledCheckV2, DeliveryCheckV2, ExecutionTargetV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
2
- export declare function freezeDeliveryCheck(check: DeliveryCheckV2, outcomeKey: string | null, repository: string, baseline: WorkspaceManifestV2, executionTarget: ExecutionTargetV2, knownExecutionTargets: ExecutionTargetV2[]): Promise<CompiledCheckV2>;
1
+ import type { CompiledCheckV2, CompiledDesignTargetV2, DeliveryCheckV2, ExecutionTargetV2, WorkspaceManifestV2 } from "./long-task-delivery-types.js";
2
+ export declare function freezeDeliveryCheck(check: DeliveryCheckV2, outcomeKey: string | null, repository: string, baseline: WorkspaceManifestV2, executionTarget: ExecutionTargetV2, knownExecutionTargets: ExecutionTargetV2[], designConformanceTargets: CompiledDesignTargetV2[]): Promise<CompiledCheckV2>;
@@ -7,7 +7,7 @@ import { nearestRunnerFile, npmCliPath, npxCliPath, } from "./long-task-runner-f
7
7
  import { canonicalValueJson, sha256Hex } from "./strict-codec.js";
8
8
  import { repoRelative, resolveInsideRepository, } from "./long-task-workspace.js";
9
9
  import { evidenceAdapterForRunner } from "./long-task-evidence-adapter-policy.js";
10
- export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets) {
10
+ export async function freezeDeliveryCheck(check, outcomeKey, repository, baseline, executionTarget, knownExecutionTargets, designConformanceTargets) {
11
11
  const prefix = outcomeKey ? `CHECK.${outcomeKey}` : "CHECK.GLOBAL";
12
12
  const expectedOutputs = check.expected_output_paths.map((pattern, index) => assertRepositoryPattern(repository, pattern, `${check.key}.expected_output_paths[${index}]`));
13
13
  for (const [index, pattern] of check.input_paths.entries()) {
@@ -32,6 +32,7 @@ export async function freezeDeliveryCheck(check, outcomeKey, repository, baselin
32
32
  verification_input_hashes: verificationInputHashes,
33
33
  execution_target_definition: executionTarget,
34
34
  known_execution_targets: knownExecutionTargets,
35
+ design_conformance_targets: designConformanceTargets,
35
36
  };
36
37
  return {
37
38
  ...compiled,
@@ -1,5 +1,6 @@
1
1
  import type { DeliveryCheckV2, DeliveryContractV2, DeliveryOutcomeV2, DeliveryRunnerV2, ProofSurface } from "./long-task-contract-types.js";
2
2
  import type { EvidenceCapabilityV2, ExecutionTargetV2 } from "./long-task-semantic-contract-types.js";
3
+ import type { CompiledDesignTargetV2 } from "./long-task-ui-surface-types.js";
3
4
  import type { AuthorityHashesV2, ContextAuthoritySnapshotV2, InitialTaskBaseV2, NextAuthorityMaterialsV2, VerifierIdentityV2 } from "./long-task-authority-types.js";
4
5
  import type { EvidenceAdapter } from "./long-task-evidence-adapter-types.js";
5
6
  import type { EvidenceCapabilityRecordV2 } from "./long-task-evidence-capability-types.js";
@@ -25,6 +26,7 @@ export interface CompiledCheckV2 extends Omit<DeliveryCheckV2, "runner"> {
25
26
  raw_execution_identity: string;
26
27
  execution_target_definition: ExecutionTargetV2;
27
28
  known_execution_targets: ExecutionTargetV2[];
29
+ design_conformance_targets: CompiledDesignTargetV2[];
28
30
  }
29
31
  export interface ProductClaimV2 {
30
32
  id: string;
@@ -25,7 +25,7 @@ export interface DeliveryStageV2 {
25
25
  gate_outcome: string;
26
26
  }
27
27
  export type DeliveryJourneyRoleV2 = "success" | "degradation" | "recovery" | "stage_gate" | "conformance";
28
- export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "target_runtime" | "input_variation";
28
+ export type EvidenceCapabilityV2 = "presence" | "interaction_trace" | "state_delta" | "cross_surface_consistency" | "durable_readback" | "boundary_invocation" | "external_side_effect" | "failure_injection" | "visual_render" | "design_conformance" | "target_runtime" | "input_variation";
29
29
  export interface CheckExecutionTargetV2 {
30
30
  target_ref: string;
31
31
  entrypoint: "root" | "internal";
@@ -37,8 +37,13 @@ export function assertNoSemanticDriftMigration(fields) {
37
37
  function collectOutcome(outcome, label, missing) {
38
38
  required(outcome, label, ["stage"], missing);
39
39
  const product = row(outcome.product);
40
- if (product)
40
+ if (product) {
41
41
  required(product, `${label}.product`, ["success_path_required", "degradation_path_required"], missing);
42
+ if (Array.isArray(product.controls) &&
43
+ product.controls.length > 0 &&
44
+ !Object.hasOwn(product, "surface_bindings"))
45
+ missing.push(`${label}.product.surface_bindings`);
46
+ }
42
47
  const acceptance = row(outcome.acceptance);
43
48
  collectChecks(acceptance?.checks, `${label}.acceptance.checks`, missing);
44
49
  }
@@ -16,5 +16,5 @@ export declare function key(value: unknown, label: string): string;
16
16
  export declare function nullable<T>(value: unknown, parser: (value: unknown) => T): T | null;
17
17
  export declare const PROOF_SURFACES: readonly ["ui_browser", "runtime_behavior", "api_contract", "data_state", "security_boundary", "population_coverage", "implementation_structure"];
18
18
  export declare const JOURNEY_ROLES: readonly ["success", "degradation", "recovery", "stage_gate", "conformance"];
19
- export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "target_runtime", "input_variation"];
19
+ export declare const EVIDENCE_CAPABILITIES: readonly ["presence", "interaction_trace", "state_delta", "cross_surface_consistency", "durable_readback", "boundary_invocation", "external_side_effect", "failure_injection", "visual_render", "design_conformance", "target_runtime", "input_variation"];
20
20
  export declare function fail(label: string, message: string): never;
@@ -98,6 +98,7 @@ export const EVIDENCE_CAPABILITIES = [
98
98
  "external_side_effect",
99
99
  "failure_injection",
100
100
  "visual_render",
101
+ "design_conformance",
101
102
  "target_runtime",
102
103
  "input_variation",
103
104
  ];
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { compileDeliveryContract } from "./long-task-delivery-compiler.js";
3
+ import { authorityRevisionDecisionNextAction } from "./long-task-authority-revision-brief.js";
3
4
  import { projectAuthorityRevisionDecision } from "./long-task-authority-revision-summary.js";
4
5
  import { runDeliveryFinalGate } from "./long-task-final-v2.js";
5
6
  import { deliveryCompileFreshness } from "./long-task-freshness.js";
@@ -83,10 +84,10 @@ export async function resumeDeliveryTask(workdir) {
83
84
  if (active.workdir !== path.resolve(workdir))
84
85
  throw new Error("active_task_workdir_mismatch");
85
86
  const compiled = active.authority_snapshot;
86
- const [status, git] = await Promise.all([
87
- readDeliveryStatusForAuthority(active),
88
- currentGitState(compiled.repository_root),
89
- ]);
87
+ // Status capture runs git write-tree; finish it before git status can refresh
88
+ // the same repository index inside currentGitState.
89
+ const status = await readDeliveryStatusForAuthority(active);
90
+ const git = await currentGitState(compiled.repository_root);
90
91
  return {
91
92
  schema_version: "long-task-resume-v2",
92
93
  task: {
@@ -312,11 +313,15 @@ function acceptedScopeMessage(workflowStatus, confirmations, targetProfile) {
312
313
  }
313
314
  function nextAction(status) {
314
315
  if (status.pending_authority_revision)
315
- return `Ask the user to approve or reject Authority Revision ${status.pending_authority_revision.revision_identity}; keep the previous Authority active until then.`;
316
+ return authorityRevisionDecisionNextAction(status.pending_authority_revision);
316
317
  if (status.findings.length)
317
318
  return status.findings.at(-1).next_action;
318
- if (status.ready_outcomes.length)
319
- return `Implement and verify ready Outcome: ${status.ready_outcomes[0]}.`;
319
+ if (status.ready_outcomes.length) {
320
+ const outcome = status.ready_outcomes[0];
321
+ if (status.outcomes[outcome] === "progress_stale")
322
+ return `Targeted evidence for ready Outcome ${outcome} is stale. This is a freshness fact, not an immediate per-edit rerun instruction: coalesce relevant changes, use the cheapest reliable project-owned feedback, and refresh the declared Check before relying on this Outcome or entering Final Gate.`;
323
+ return `Implement and verify ready Outcome: ${outcome}.`;
324
+ }
320
325
  return "Create a clean candidate commit; Stop will run the authoritative Live Final Gate.";
321
326
  }
322
327
  function message(error) {
@@ -0,0 +1,17 @@
1
+ import type { CompiledClaimsV2 } from "./long-task-claims.js";
2
+ import type { DeliveryCheckV2, DeliveryContractV2, DeliveryOutcomeV2, ProductClaimV2 } from "./long-task-delivery-types.js";
3
+ import { type Reporter } from "./long-task-ui-surface-validation.js";
4
+ interface UiDesignBindingContext {
5
+ outcome: DeliveryOutcomeV2;
6
+ binding: DeliveryOutcomeV2["product"]["surface_bindings"][number];
7
+ outcomeClaims: Map<string, ProductClaimV2>;
8
+ claims: CompiledClaimsV2;
9
+ checks: Map<string, DeliveryCheckV2>;
10
+ confirmations: Map<string, DeliveryContractV2["global"]["acceptance"]["external_confirmations"][number]>;
11
+ carriers: string[];
12
+ designTargetKeys: Set<string>;
13
+ designAssertionRefs: Set<string>;
14
+ report?: Reporter;
15
+ }
16
+ export declare function validateUiDesignBinding(context: UiDesignBindingContext): void;
17
+ export {};
@@ -0,0 +1,128 @@
1
+ import { matchesRepoPattern } from "./long-task-paths.js";
2
+ import { issue, unique, validateCarrierInputs, validateRootJourney, validateTargetLocalClaimProof, } from "./long-task-ui-surface-validation.js";
3
+ export function validateUiDesignBinding(context) {
4
+ validateDesignTargets(context);
5
+ validateBlockers(context);
6
+ }
7
+ function validateDesignTargets({ outcome, binding, outcomeClaims, checks, carriers, designTargetKeys, designAssertionRefs, report, }) {
8
+ for (const target of binding.design_targets) {
9
+ const label = `${outcome.key}:${binding.key}:${target.key}`;
10
+ if (designTargetKeys.has(target.key))
11
+ issue(report, "ui_design_target_key_duplicate", label);
12
+ designTargetKeys.add(target.key);
13
+ const assertionIdentity = `${target.conformance_check_ref}\0${target.conformance_assertion_ref}`;
14
+ if (designAssertionRefs.has(assertionIdentity))
15
+ issue(report, "ui_design_target_assertion_duplicate", label);
16
+ designAssertionRefs.add(assertionIdentity);
17
+ unique(target.verification_method_bindings.map((item) => item.method), "ui_design_target_verification_method_duplicate", label, report);
18
+ unique(target.verification_method_bindings.map((item) => item.assertion_ref), "ui_design_target_verification_assertion_duplicate", label, report);
19
+ if (!target.verification_method_bindings.length)
20
+ issue(report, "ui_design_target_verification_methods_required", label);
21
+ for (const [name, values] of [
22
+ ["source_paths", target.source_paths],
23
+ ["condition_keys", target.condition_keys],
24
+ ["claim_refs", target.claim_refs],
25
+ ]) {
26
+ unique(values, `ui_design_target_${name}_duplicate`, label, report);
27
+ if (!values.length)
28
+ issue(report, `ui_design_target_${name}_required`, label);
29
+ }
30
+ for (const claimRef of target.claim_refs) {
31
+ const claim = outcomeClaims.get(claimRef);
32
+ if (!claim ||
33
+ claim.kind !== "control" ||
34
+ !binding.control_refs.some((control) => claimRef.startsWith(`control.${control}.`)))
35
+ issue(report, "ui_design_target_control_claim_required", `${label}:${claimRef}`);
36
+ }
37
+ const check = checks.get(target.conformance_check_ref);
38
+ if (!check) {
39
+ issue(report, "ui_design_target_conformance_check_unknown", `${label}:${target.conformance_check_ref}`);
40
+ continue;
41
+ }
42
+ validateRootJourney(binding, check, label, report);
43
+ validateCarrierInputs(check, carriers, label, report);
44
+ validateDesignAssertion(target, check, label, report);
45
+ for (const methodBinding of target.verification_method_bindings) {
46
+ const identity = `${target.conformance_check_ref}\0${methodBinding.assertion_ref}`;
47
+ if (methodBinding.assertion_ref !== target.conformance_assertion_ref &&
48
+ designAssertionRefs.has(identity))
49
+ issue(report, "ui_design_target_assertion_duplicate", `${label}:${methodBinding.assertion_ref}`);
50
+ if (methodBinding.assertion_ref !== target.conformance_assertion_ref)
51
+ designAssertionRefs.add(identity);
52
+ if (!check.positive_assertions.some((item) => item.key === methodBinding.assertion_ref))
53
+ issue(report, "ui_design_target_verification_assertion_unknown", `${label}:${methodBinding.method}:${methodBinding.assertion_ref}`);
54
+ }
55
+ validateDesignFiles(target, check, label, report);
56
+ }
57
+ }
58
+ function validateDesignAssertion(target, check, label, report) {
59
+ const assertion = check.positive_assertions.find((item) => item.key === target.conformance_assertion_ref);
60
+ if (!assertion) {
61
+ issue(report, "ui_design_target_conformance_assertion_unknown", `${label}:${target.conformance_assertion_ref}`);
62
+ return;
63
+ }
64
+ for (const claimRef of target.claim_refs)
65
+ if (!assertion.claims.includes(claimRef))
66
+ issue(report, "ui_design_target_claim_not_asserted", `${label}:${claimRef}`);
67
+ for (const capability of [
68
+ "design_conformance",
69
+ "interaction_trace",
70
+ "target_runtime",
71
+ ])
72
+ if (!assertion.evidence_capabilities.includes(capability))
73
+ issue(report, "ui_design_target_capability_required", `${label}:${capability}`);
74
+ }
75
+ function validateDesignFiles(target, check, label, report) {
76
+ for (const source of target.source_paths)
77
+ if (!check.verification_inputs.some((pattern) => matchesRepoPattern(source, pattern)))
78
+ issue(report, "ui_design_target_verification_input_missing", `${label}:${source}`);
79
+ if (target.actual_artifact_path === target.comparison_artifact_path)
80
+ issue(report, "ui_design_target_artifacts_must_differ", label);
81
+ for (const artifact of [
82
+ target.actual_artifact_path,
83
+ target.comparison_artifact_path,
84
+ ])
85
+ if (!check.artifact_globs.some((pattern) => matchesRepoPattern(artifact, pattern)))
86
+ issue(report, "ui_design_target_artifact_glob_missing", `${label}:${artifact}`);
87
+ }
88
+ function validateBlockers(context) {
89
+ const { outcome, binding, outcomeClaims, claims, checks, confirmations, report, } = context;
90
+ const label = `${outcome.key}:${binding.key}`;
91
+ unique(binding.acceptance_blockers.map((item) => item.key), "ui_design_blocker_key_duplicate", label, report);
92
+ for (const blocker of binding.acceptance_blockers) {
93
+ const blockerLabel = `${label}:${blocker.key}`;
94
+ unique(blocker.refs, "ui_design_blocker_ref_duplicate", blockerLabel, report);
95
+ if (!blocker.refs.length)
96
+ issue(report, "ui_design_blocker_ref_required", blockerLabel);
97
+ unique(blocker.source_item_refs, "ui_design_blocker_source_item_duplicate", blockerLabel, report);
98
+ unique(blocker.verification_methods, "ui_design_blocker_verification_method_duplicate", blockerLabel, report);
99
+ if (!blocker.source_item_refs.length)
100
+ issue(report, "ui_design_blocker_source_item_required", blockerLabel);
101
+ if (!blocker.verification_methods.length)
102
+ issue(report, "ui_design_blocker_verification_method_required", blockerLabel);
103
+ if (blocker.status === "machine_claim")
104
+ validateMachineBlocker(context, blocker.refs, blockerLabel);
105
+ if (blocker.status === "external_confirmation")
106
+ validateExternalBlocker(outcome, confirmations, blocker.refs, blockerLabel, report);
107
+ }
108
+ }
109
+ function validateMachineBlocker({ outcome, binding, outcomeClaims, claims, checks, report, }, claimRefs, label) {
110
+ for (const claimRef of claimRefs) {
111
+ const claim = outcomeClaims.get(claimRef);
112
+ if (!claim)
113
+ issue(report, "ui_design_blocker_machine_claim_unknown", `${label}:${claimRef}`);
114
+ else
115
+ validateTargetLocalClaimProof(outcome, claim, binding.target_ref, null, claims, checks, label, report);
116
+ }
117
+ }
118
+ function validateExternalBlocker(outcome, confirmations, confirmationRefs, label, report) {
119
+ for (const confirmationRef of confirmationRefs) {
120
+ const confirmation = confirmations.get(confirmationRef);
121
+ if (!confirmation)
122
+ issue(report, "ui_design_blocker_confirmation_unknown", `${label}:${confirmationRef}`);
123
+ else if (!confirmation.blocks_target)
124
+ issue(report, "ui_design_blocker_confirmation_must_block_target", `${label}:${confirmationRef}`);
125
+ else if (!confirmation.impact_claims.some((claim) => claim.startsWith(`${outcome.key}.`)))
126
+ issue(report, "ui_design_blocker_confirmation_impact_mismatch", `${label}:${confirmationRef}`);
127
+ }
128
+ }
@@ -0,0 +1,4 @@
1
+ import type { CompiledClaimsV2 } from "./long-task-claims.js";
2
+ import type { DeliveryContractV2 } from "./long-task-delivery-types.js";
3
+ import { type Reporter } from "./long-task-ui-surface-validation.js";
4
+ export declare function validateUiSurfaceBindings(contract: DeliveryContractV2, claims: CompiledClaimsV2, report?: Reporter): void;
@@ -0,0 +1,109 @@
1
+ import { validateUiDesignBinding } from "./long-task-ui-design-policy.js";
2
+ import { bindingCarriers, controlClaims, expectedControlProofSurface, issue, unique, validateCarrierInputs, validateRootJourney, validateTargetLocalClaimProof, } from "./long-task-ui-surface-validation.js";
3
+ export function validateUiSurfaceBindings(contract, claims, report) {
4
+ const targets = new Map(contract.task.execution_targets.map((target) => [target.key, target]));
5
+ const requiredTargets = new Set(contract.task.target_profile.required_target_refs);
6
+ const confirmations = new Map(contract.global.acceptance.external_confirmations.map((item) => [
7
+ item.key,
8
+ item,
9
+ ]));
10
+ for (const outcome of contract.outcomes)
11
+ validateOutcomeBindings(outcome, claims, targets, requiredTargets, confirmations, report);
12
+ }
13
+ function validateOutcomeBindings(outcome, claims, targets, requiredTargets, confirmations, report) {
14
+ const surfaceBindings = outcome.product.surface_bindings ?? [];
15
+ if (outcome.product.controls.length && !surfaceBindings.length)
16
+ issue(report, "ui_surface_binding_required", outcome.key);
17
+ if (!outcome.product.controls.length && surfaceBindings.length)
18
+ issue(report, "ui_surface_binding_without_controls", outcome.key);
19
+ unique(surfaceBindings.map((item) => item.key), "ui_surface_binding_key_duplicate", outcome.key, report);
20
+ const controls = new Map(outcome.product.controls.map((control) => [control.key, control]));
21
+ const ownerSurfaces = new Set(outcome.product.owner_surfaces);
22
+ const technicalBindings = new Map(outcome.technical.bindings.map((binding) => [binding.key, binding]));
23
+ const checks = new Map(outcome.acceptance.checks.map((check) => [check.key, check]));
24
+ const outcomeClaims = new Map((claims.by_outcome[outcome.key] ?? []).map((claim) => [
25
+ claim.local_key,
26
+ claim,
27
+ ]));
28
+ const boundControls = new Set();
29
+ const boundControlTargets = new Set();
30
+ const designTargetKeys = new Set();
31
+ const designAssertionRefs = new Set();
32
+ for (const binding of surfaceBindings) {
33
+ const label = `${outcome.key}:${binding.key}`;
34
+ if (!ownerSurfaces.has(binding.surface_ref))
35
+ issue(report, "ui_surface_binding_owner_surface_unknown", `${label}:${binding.surface_ref}`);
36
+ const target = targets.get(binding.target_ref);
37
+ if (!target || target.role !== "product")
38
+ issue(report, "ui_surface_binding_product_target_required", `${label}:${binding.target_ref}`);
39
+ if (!requiredTargets.has(binding.target_ref))
40
+ issue(report, "ui_surface_binding_required_target_required", `${label}:${binding.target_ref}`);
41
+ validateBoundControls(binding, controls, boundControls, boundControlTargets, label, report);
42
+ const carriers = bindingCarriers(binding.route_binding_ref, binding.component_binding_refs, technicalBindings, label, report);
43
+ const rootCheck = checks.get(binding.root_journey_check_ref);
44
+ if (!rootCheck)
45
+ issue(report, "ui_surface_binding_root_check_unknown", `${label}:${binding.root_journey_check_ref}`);
46
+ else {
47
+ validateRootJourney(binding, rootCheck, label, report);
48
+ validateCarrierInputs(rootCheck, carriers, label, report);
49
+ validateRootBoundControlAssertions(binding, rootCheck, controls, label, report);
50
+ }
51
+ for (const controlRef of binding.control_refs)
52
+ for (const claim of controlClaims(outcomeClaims, controlRef))
53
+ validateTargetLocalClaimProof(outcome, claim, binding.target_ref, expectedControlProofSurface(target?.runtime_family), claims, checks, label, report);
54
+ validateUiDesignBinding({
55
+ outcome,
56
+ binding,
57
+ outcomeClaims,
58
+ claims,
59
+ checks,
60
+ confirmations,
61
+ carriers,
62
+ designTargetKeys,
63
+ designAssertionRefs,
64
+ report,
65
+ });
66
+ }
67
+ for (const control of outcome.product.controls)
68
+ if (!boundControls.has(control.key))
69
+ issue(report, "ui_surface_binding_control_unbound", `${outcome.key}:${control.key}`);
70
+ }
71
+ function validateBoundControls(binding, controls, boundControls, boundControlTargets, label, report) {
72
+ unique(binding.control_refs, "ui_surface_binding_control_ref_duplicate", label, report);
73
+ if (!binding.control_refs.length)
74
+ issue(report, "ui_surface_binding_control_ref_required", label);
75
+ for (const controlRef of binding.control_refs) {
76
+ const control = controls.get(controlRef);
77
+ if (!control)
78
+ issue(report, "ui_surface_binding_control_unknown", `${label}:${controlRef}`);
79
+ else if (control.surface.trim() && control.surface !== binding.surface_ref)
80
+ issue(report, "ui_surface_binding_control_surface_mismatch", `${label}:${controlRef}:${control.surface}`);
81
+ const identity = `${controlRef}\0${binding.target_ref}`;
82
+ if (boundControlTargets.has(identity))
83
+ issue(report, "ui_surface_binding_control_target_duplicate", `${label}:${controlRef}:${binding.target_ref}`);
84
+ boundControlTargets.add(identity);
85
+ boundControls.add(controlRef);
86
+ }
87
+ }
88
+ function validateRootBoundControlAssertions(binding, check, controls, label, report) {
89
+ for (const controlRef of binding.control_refs) {
90
+ const control = controls.get(controlRef);
91
+ if (!control)
92
+ continue;
93
+ const claimRef = rootJourneyClaimRef(control);
94
+ if (!check.positive_assertions.some((assertion) => assertion.claims.includes(claimRef) &&
95
+ assertion.evidence_capabilities.includes("interaction_trace") &&
96
+ assertion.evidence_capabilities.includes("target_runtime")))
97
+ issue(report, "ui_surface_binding_root_control_proof_missing", `${label}:${controlRef}:${claimRef}`);
98
+ }
99
+ }
100
+ function rootJourneyClaimRef(control) {
101
+ const field = control.navigation_result?.trim()
102
+ ? "navigation_result"
103
+ : control.interaction?.trim()
104
+ ? "interaction"
105
+ : control.trigger?.trim()
106
+ ? "trigger"
107
+ : "location";
108
+ return `control.${control.key}.${field}`;
109
+ }
@@ -0,0 +1,2 @@
1
+ import type { DeliverySurfaceBindingV2 } from "./long-task-ui-surface-types.js";
2
+ export declare function parseSurfaceBindings(value: unknown, label: string): DeliverySurfaceBindingV2[];